From 15792b153fb382c5839399b36c7409ea1779aa88 Mon Sep 17 00:00:00 2001 From: cpojer Date: Sat, 31 Jan 2026 16:03:28 +0900 Subject: [PATCH] chore: Enable more lint rules, disable some that trigger a lot. Will clean up later. --- .oxlintrc.json | 15 +++++++- src/agents/anthropic-payload-log.ts | 2 +- src/agents/apply-patch-update.ts | 2 +- src/agents/auth-health.ts | 4 +- src/agents/auth-profiles/display.ts | 4 +- src/agents/auth-profiles/oauth.ts | 3 +- src/agents/auth-profiles/order.ts | 6 +-- src/agents/auth-profiles/repair.ts | 7 ++-- src/agents/bash-tools.exec.ts | 26 +++++-------- src/agents/bash-tools.process.ts | 2 +- src/agents/bedrock-discovery.ts | 4 +- src/agents/cache-trace.ts | 8 ++-- src/agents/cli-runner/helpers.ts | 4 +- src/agents/compaction.test.ts | 4 +- src/agents/model-auth.ts | 6 +-- src/agents/model-catalog.ts | 4 +- src/agents/model-compat.ts | 2 +- src/agents/model-fallback.ts | 4 +- src/agents/model-scan.ts | 4 +- src/agents/models-config.ts | 2 +- src/agents/models.profiles.live.test.ts | 2 +- src/agents/pi-embedded-helpers/errors.ts | 2 +- src/agents/pi-embedded-helpers/images.ts | 2 +- src/agents/pi-embedded-helpers/openai.ts | 6 +-- src/agents/pi-embedded-runner/extra-params.ts | 2 +- src/agents/pi-embedded-runner/google.ts | 2 +- src/agents/pi-embedded-runner/model.ts | 2 +- .../run.overflow-compaction.test.ts | 6 +-- src/agents/pi-embedded-runner/run/attempt.ts | 2 +- ...pi-embedded-subscribe.handlers.messages.ts | 2 +- .../compaction-safeguard-runtime.ts | 4 +- .../pi-extensions/compaction-safeguard.ts | 4 +- .../context-pruning/extension.ts | 3 +- .../pi-extensions/context-pruning/runtime.ts | 4 +- src/agents/pi-tool-definition-adapter.ts | 2 +- ...aliases-schemas-without-dropping-b.test.ts | 2 +- src/agents/pi-tools.read.ts | 6 +-- src/agents/pi-tools.ts | 6 +-- src/agents/sandbox/config-hash.ts | 4 +- src/agents/session-transcript-repair.ts | 4 +- ...skills.buildworkspaceskillcommands.test.ts | 2 +- ...skills.buildworkspaceskillsnapshot.test.ts | 2 +- src/agents/skills.ts | 2 +- src/agents/skills/config.ts | 2 +- src/agents/skills/frontmatter.ts | 4 +- src/agents/subagent-announce.ts | 9 +---- src/agents/subagent-registry.ts | 12 +++--- src/agents/system-prompt.ts | 2 +- src/agents/tool-images.ts | 4 +- src/agents/tools/agent-step.ts | 12 +++--- src/agents/tools/agents-list-tool.ts | 4 +- src/agents/tools/browser-tool.ts | 16 ++++---- src/agents/tools/cron-tool.ts | 4 +- src/agents/tools/image-tool.ts | 4 +- src/agents/tools/message-tool.ts | 2 +- src/agents/tools/nodes-tool.ts | 25 +++++++------ src/agents/tools/nodes-utils.ts | 4 +- src/agents/tools/sessions-announce-target.ts | 4 +- src/agents/tools/sessions-helpers.ts | 8 ++-- src/agents/tools/sessions-history-tool.ts | 8 ++-- src/agents/tools/sessions-list-tool.ts | 11 ++---- src/agents/tools/sessions-send-tool.a2a.ts | 4 +- src/agents/tools/sessions-send-tool.ts | 24 ++++++------ src/agents/tools/sessions-spawn-tool.ts | 8 ++-- src/auto-reply/envelope.ts | 2 +- .../reply/commands-context-report.ts | 4 +- src/auto-reply/reply/commands-models.ts | 4 +- src/auto-reply/reply/commands-session.ts | 4 +- src/auto-reply/reply/commands-subagents.ts | 16 ++++---- .../reply/directive-handling.impl.ts | 3 +- .../reply/get-reply-directives-apply.ts | 4 +- src/auto-reply/reply/get-reply-directives.ts | 8 ++-- src/auto-reply/reply/groups.ts | 2 +- src/auto-reply/reply/model-selection.ts | 2 +- src/auto-reply/reply/session-updates.ts | 2 +- src/auto-reply/reply/session.ts | 7 ++-- src/auto-reply/reply/subagents-utils.ts | 2 +- src/browser/cdp.ts | 2 +- src/browser/extension-relay.ts | 2 +- src/browser/profiles.test.ts | 8 ++-- src/browser/profiles.ts | 2 +- src/browser/pw-role-snapshot.test.ts | 2 +- ...ls-core.last-file-chooser-arm-wins.test.ts | 4 +- src/browser/pw-tools-core.responses.ts | 2 +- src/browser/pw-tools-core.snapshot.ts | 2 +- src/browser/pw-tools-core.state.ts | 3 +- src/browser/routes/agent.act.ts | 2 +- src/browser/routes/agent.storage.ts | 4 +- src/browser/screenshot.ts | 2 +- ...-contract-form-layout-act-commands.test.ts | 37 +++++++++---------- ....agent-contract-snapshot-endpoints.test.ts | 28 +++++++------- .../discord/handle-action.guild-admin.ts | 2 +- src/channels/plugins/catalog.ts | 2 +- src/channels/plugins/config-helpers.ts | 2 +- src/channels/plugins/directory-config.test.ts | 8 ++-- src/channels/plugins/index.ts | 2 +- .../plugins/onboarding/channel-access.ts | 4 +- src/channels/plugins/onboarding/helpers.ts | 4 +- src/channels/plugins/onboarding/whatsapp.ts | 8 ++-- src/channels/plugins/whatsapp-heartbeat.ts | 2 +- src/channels/registry.ts | 6 +-- src/cli/cli-utils.ts | 2 +- src/cli/config-cli.ts | 2 +- src/cli/devices-cli.ts | 2 +- src/cli/exec-approvals-cli.ts | 2 +- src/cli/gateway-cli/register.ts | 2 +- src/cli/models-cli.test.ts | 5 +-- src/cli/nodes-cli/format.ts | 2 +- src/cli/nodes-cli/register.camera.ts | 8 ++-- src/cli/nodes-cli/register.canvas.ts | 2 +- src/cli/nodes-cli/register.invoke.ts | 4 +- src/cli/nodes-cli/register.location.ts | 2 +- src/cli/nodes-cli/register.pairing.ts | 2 +- src/cli/nodes-cli/register.screen.ts | 2 +- src/cli/nodes-cli/register.status.ts | 16 ++++---- src/cli/nodes-cli/rpc.ts | 4 +- src/cli/pairing-cli.ts | 4 +- src/cli/ports.ts | 4 +- src/cli/program.nodes-media.test.ts | 2 +- src/cli/security-cli.ts | 2 +- src/cli/update-cli.ts | 4 +- src/commands/agent.test.ts | 2 +- src/commands/agents.commands.list.ts | 2 +- src/commands/auth-choice-prompt.ts | 4 +- src/commands/channels/add.ts | 2 +- src/commands/channels/remove.ts | 8 ++-- src/commands/channels/status.ts | 4 +- src/commands/configure.channels.ts | 2 +- src/commands/configure.daemon.ts | 2 +- src/commands/configure.gateway.ts | 4 +- src/commands/configure.wizard.ts | 2 +- src/commands/doctor-config-flow.ts | 4 +- src/commands/doctor-prompter.ts | 28 ++++++-------- src/commands/doctor-state-integrity.ts | 2 +- src/commands/health.ts | 2 +- src/commands/message-format.ts | 2 +- src/commands/model-picker.ts | 6 +-- src/commands/models/list.list-command.ts | 2 +- src/commands/models/list.probe.ts | 2 +- src/commands/models/list.registry.ts | 4 +- src/commands/models/list.status-command.ts | 6 +-- src/commands/models/scan.ts | 8 ++-- src/commands/onboard-channels.ts | 14 +++---- src/commands/onboard-helpers.ts | 2 +- .../onboard-non-interactive.gateway.test.ts | 2 +- src/commands/onboard-remote.ts | 4 +- src/commands/onboard-skills.ts | 2 +- src/commands/onboarding/registry.ts | 4 +- src/commands/sessions.ts | 2 +- src/commands/status-all.ts | 16 ++++---- src/commands/status-all/channels.ts | 4 +- src/commands/status.command.ts | 4 +- src/commands/status.link-channel.ts | 2 +- src/commands/status.summary.ts | 2 +- src/config/io.ts | 2 +- src/config/sessions.cache.test.ts | 2 +- src/config/sessions/group.ts | 2 +- src/config/sessions/store.ts | 4 +- src/cron/normalize.ts | 4 +- src/cron/run-log.ts | 2 +- src/cron/service/jobs.ts | 2 +- src/cron/service/ops.ts | 4 +- src/cron/store.ts | 2 +- src/discord/accounts.ts | 2 +- src/discord/audit.ts | 2 +- src/discord/monitor.slash.test.ts | 4 +- src/discord/monitor/allow-list.ts | 2 +- src/discord/resolve-channels.ts | 12 +----- src/discord/send.permissions.ts | 4 +- src/gateway/client.ts | 2 +- .../gateway-models.profiles.live.test.ts | 2 +- src/gateway/hooks-mapping.ts | 2 +- src/gateway/server-maintenance.ts | 2 +- src/gateway/server-methods/agent-job.ts | 19 ++++------ src/gateway/server-methods/agent.ts | 6 +-- src/gateway/server-methods/cron.ts | 2 +- src/gateway/server-methods/logs.ts | 2 +- src/gateway/server-methods/nodes.helpers.ts | 2 +- src/gateway/server-methods/send.ts | 12 +++--- src/gateway/server-methods/sessions.ts | 14 +++---- src/gateway/server-methods/skills.ts | 4 +- src/gateway/server-methods/system.ts | 6 +-- src/gateway/server-methods/wizard.ts | 8 ++-- src/gateway/server-node-subscriptions.test.ts | 2 +- ...ver.chat.gateway-server-chat-b.e2e.test.ts | 7 ++-- src/gateway/server.config-patch.e2e.test.ts | 2 +- src/gateway/server.reload.e2e.test.ts | 4 +- .../server/ws-connection/message-handler.ts | 12 +++--- src/gateway/session-utils.fs.ts | 2 +- src/gateway/session-utils.ts | 2 +- src/gateway/test-helpers.mocks.ts | 2 +- src/gateway/tools-invoke-http.ts | 5 +-- .../bundled/session-memory/handler.test.ts | 12 +++--- src/hooks/bundled/session-memory/handler.ts | 4 +- src/hooks/bundled/soul-evil/handler.ts | 2 +- src/hooks/config.ts | 2 +- src/hooks/frontmatter.test.ts | 4 +- src/hooks/frontmatter.ts | 4 +- src/hooks/gmail-setup-utils.ts | 2 +- src/hooks/workspace.ts | 2 +- src/imessage/accounts.ts | 2 +- src/imessage/send.ts | 2 +- src/infra/backoff.ts | 2 +- src/infra/channel-summary.ts | 2 +- src/infra/dedupe.ts | 2 +- src/infra/device-auth-store.ts | 2 +- src/infra/device-pairing.ts | 8 ++-- src/infra/fs-safe.ts | 2 +- src/infra/net/ssrf.pinning.test.ts | 4 +- src/infra/node-pairing.ts | 4 +- src/infra/outbound/channel-selection.ts | 2 +- src/infra/outbound/message-action-runner.ts | 2 +- src/infra/outbound/message.ts | 6 +-- src/infra/outbound/targets.ts | 4 +- src/infra/provider-usage.fetch.minimax.ts | 2 +- src/infra/session-cost-usage.ts | 2 +- src/infra/ssh-tunnel.ts | 2 +- src/infra/state-migrations.ts | 5 ++- src/infra/system-presence.ts | 4 +- src/infra/tailscale.ts | 2 +- src/line/auto-reply-delivery.ts | 4 +- src/line/bot-message-context.ts | 8 ++-- src/line/flex-templates.ts | 2 +- src/line/reply-chunks.ts | 10 ++--- src/logging/config.ts | 2 +- src/logging/subsystem.ts | 4 +- src/macos/gateway-daemon.ts | 4 +- src/markdown/frontmatter.test.ts | 4 +- src/markdown/ir.ts | 2 +- src/markdown/render.ts | 4 +- src/media-understanding/attachments.ts | 2 +- src/media-understanding/providers/image.ts | 4 +- src/media/image-ops.ts | 2 +- src/media/store.redirect.test.ts | 6 +-- src/memory/embeddings.ts | 14 ++++--- src/memory/hybrid.ts | 2 +- src/memory/manager-cache-key.ts | 4 +- src/memory/manager-search.ts | 2 +- src/memory/manager.ts | 4 +- src/memory/status-format.ts | 4 +- src/node-host/runner.ts | 11 +++--- src/pairing/pairing-store.ts | 4 +- src/plugins/cli.ts | 4 +- src/plugins/hooks.ts | 8 ++-- src/plugins/loader.ts | 2 +- src/plugins/runtime.ts | 2 +- src/plugins/schema-validator.ts | 2 +- src/plugins/services.ts | 2 +- src/plugins/slots.ts | 4 +- src/routing/bindings.ts | 2 +- src/security/audit-extra.ts | 2 +- src/security/audit.ts | 4 +- src/security/fix.test.ts | 2 +- src/security/fix.ts | 2 +- src/signal/accounts.ts | 2 +- src/signal/format.ts | 6 +-- src/signal/probe.ts | 2 +- src/slack/accounts.ts | 2 +- src/slack/monitor/events/reactions.ts | 2 +- src/slack/monitor/provider.ts | 5 +-- src/slack/monitor/slash.ts | 2 +- src/slack/monitor/thread-resolution.ts | 2 +- src/slack/resolve-users.ts | 4 +- src/slack/scopes.ts | 2 +- src/telegram/accounts.ts | 2 +- src/telegram/audit.ts | 8 ++-- src/telegram/bot.ts | 2 +- src/telegram/bot/helpers.ts | 2 +- src/telegram/monitor.ts | 3 +- src/telegram/sticker-cache.ts | 4 +- src/telegram/webhook.ts | 4 +- src/terminal/table.ts | 4 +- src/test-utils/ports.ts | 2 +- src/tts/tts.ts | 2 +- src/tui/components/custom-editor.ts | 3 -- src/tui/components/searchable-select-list.ts | 2 +- src/types/pi-coding-agent.d.ts | 2 - src/web/accounts.ts | 2 +- src/web/auto-reply/monitor/echo.ts | 2 +- .../auto-reply/monitor/group-activation.ts | 2 +- src/web/inbound/extract.ts | 8 ++-- src/web/inbound/media.ts | 8 ++-- src/web/login.ts | 4 +- src/web/media.ts | 2 +- src/web/qr-image.ts | 4 +- src/web/session.ts | 4 +- src/wizard/clack-prompter.ts | 2 +- src/wizard/onboarding.finalize.ts | 16 ++++---- src/wizard/onboarding.gateway-config.ts | 19 ++++------ src/wizard/onboarding.ts | 8 ++-- test/gateway.multi.e2e.test.ts | 1 + test/helpers/envelope-timestamp.ts | 2 +- 292 files changed, 643 insertions(+), 699 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index 4d85dff765..2f063ecd93 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -7,13 +7,24 @@ ], "categories": { "correctness": "error", - "perf": "error" + "perf": "error", + "suspicious": "error", }, "rules": { "eslint-plugin-unicorn/prefer-array-find": "off", "eslint/no-await-in-loop": "off", "oxc/no-accumulating-spread": "off", - "oxc/no-map-spread": "off" + "oxc/no-map-spread": "off", + "typescript/no-unsafe-type-assertion": "off", + "typescript/no-unnecessary-template-expression": "off", + "unicorn/consistent-function-scoping": "off", + "typescript/no-extraneous-class": "off", + "oxc/no-async-endpoint-handlers": "off", + "eslint/no-useless-concat": "off", + "eslint/no-unused-vars": "off", + "eslint/no-new": "off", + "eslint/preserve-caught-error": "off", + "unicorn/require-post-message-target-origin": "off", }, "ignorePatterns": ["src/canvas-host/a2ui/a2ui.bundle.js"] } diff --git a/src/agents/anthropic-payload-log.ts b/src/agents/anthropic-payload-log.ts index c823b03ff3..cba6ddf28a 100644 --- a/src/agents/anthropic-payload-log.ts +++ b/src/agents/anthropic-payload-log.ts @@ -161,7 +161,7 @@ export function createAnthropicPayloadLogger(params: { const wrapStreamFn: AnthropicPayloadLogger["wrapStreamFn"] = (streamFn) => { const wrapped: StreamFn = (model, context, options) => { - if (!isAnthropicModel(model as Model)) { + if (!isAnthropicModel(model)) { return streamFn(model, context, options); } const nextOnPayload = (payload: unknown) => { diff --git a/src/agents/apply-patch-update.ts b/src/agents/apply-patch-update.ts index 597d14b935..e5d5367015 100644 --- a/src/agents/apply-patch-update.ts +++ b/src/agents/apply-patch-update.ts @@ -85,7 +85,7 @@ function applyReplacements( replacements: Array<[number, number, string[]]>, ): string[] { const result = [...lines]; - for (const [startIndex, oldLen, newLines] of [...replacements].reverse()) { + for (const [startIndex, oldLen, newLines] of [...replacements].toReversed()) { for (let i = 0; i < oldLen; i += 1) { if (startIndex < result.length) { result.splice(startIndex, 1); diff --git a/src/agents/auth-health.ts b/src/agents/auth-health.ts index 4301c8a718..4f0db300d9 100644 --- a/src/agents/auth-health.ts +++ b/src/agents/auth-health.ts @@ -169,7 +169,7 @@ export function buildAuthHealthSummary(params: { warnAfterMs, }), ) - .sort((a, b) => { + .toSorted((a, b) => { if (a.provider !== b.provider) { return a.provider.localeCompare(b.provider); } @@ -236,7 +236,7 @@ export function buildAuthHealthSummary(params: { } } - const providers = Array.from(providersMap.values()).sort((a, b) => + const providers = Array.from(providersMap.values()).toSorted((a, b) => a.provider.localeCompare(b.provider), ); diff --git a/src/agents/auth-profiles/display.ts b/src/agents/auth-profiles/display.ts index d746f99ad4..538f560ade 100644 --- a/src/agents/auth-profiles/display.ts +++ b/src/agents/auth-profiles/display.ts @@ -9,9 +9,7 @@ export function resolveAuthProfileDisplayLabel(params: { const { cfg, store, profileId } = params; const profile = store.profiles[profileId]; const configEmail = cfg?.auth?.profiles?.[profileId]?.email?.trim(); - const email = - configEmail || - (profile && "email" in profile ? (profile.email as string | undefined)?.trim() : undefined); + const email = configEmail || (profile && "email" in profile ? profile.email?.trim() : undefined); if (email) return `${profileId} (${email})`; return profileId; } diff --git a/src/agents/auth-profiles/oauth.ts b/src/agents/auth-profiles/oauth.ts index 59e8a77e8b..0e66dea3de 100644 --- a/src/agents/auth-profiles/oauth.ts +++ b/src/agents/auth-profiles/oauth.ts @@ -62,7 +62,7 @@ async function refreshOAuthTokenWithLock(params: { const newCredentials = await refreshQwenPortalCredentials(cred); return { apiKey: newCredentials.access, newCredentials }; })() - : await getOAuthApiKey(cred.provider as OAuthProvider, oauthCreds); + : await getOAuthApiKey(cred.provider, oauthCreds); if (!result) return null; store.profiles[params.profileId] = { ...cred, @@ -233,6 +233,7 @@ export async function resolveApiKeyForProfile(params: { `OAuth token refresh failed for ${cred.provider}: ${message}. ` + "Please try again or re-authenticate." + (hint ? `\n\n${hint}` : ""), + { cause: error }, ); } } diff --git a/src/agents/auth-profiles/order.ts b/src/agents/auth-profiles/order.ts index 68bfba68e4..6e2b5baaf3 100644 --- a/src/agents/auth-profiles/order.ts +++ b/src/agents/auth-profiles/order.ts @@ -112,7 +112,7 @@ export function resolveAuthProfileOrder(params: { } const cooldownSorted = inCooldown - .sort((a, b) => a.cooldownUntil - b.cooldownUntil) + .toSorted((a, b) => a.cooldownUntil - b.cooldownUntil) .map((entry) => entry.profileId); const ordered = [...available, ...cooldownSorted]; @@ -163,7 +163,7 @@ function orderProfilesByMode(order: string[], store: AuthProfileStore): string[] // Primary sort: type preference (oauth > token > api_key). // Secondary sort: lastUsed (oldest first for round-robin within type). const sorted = scored - .sort((a, b) => { + .toSorted((a, b) => { // First by type (oauth > token > api_key) if (a.typeScore !== b.typeScore) return a.typeScore - b.typeScore; // Then by lastUsed (oldest first) @@ -177,7 +177,7 @@ function orderProfilesByMode(order: string[], store: AuthProfileStore): string[] profileId, cooldownUntil: resolveProfileUnusableUntil(store.usageStats?.[profileId] ?? {}) ?? now, })) - .sort((a, b) => a.cooldownUntil - b.cooldownUntil) + .toSorted((a, b) => a.cooldownUntil - b.cooldownUntil) .map((entry) => entry.profileId); return [...sorted, ...cooldownSorted]; diff --git a/src/agents/auth-profiles/repair.ts b/src/agents/auth-profiles/repair.ts index a1028b4f4c..a4575dea94 100644 --- a/src/agents/auth-profiles/repair.ts +++ b/src/agents/auth-profiles/repair.ts @@ -45,7 +45,7 @@ export function suggestOAuthProfileIdForLegacyDefault(params: { const byEmail = oauthProfiles.find((id) => { const cred = params.store.profiles[id]; if (!cred || cred.type !== "oauth") return false; - const email = (cred.email as string | undefined)?.trim(); + const email = cred.email?.trim(); return email === configuredEmail || id === `${providerKey}:${configuredEmail}`; }); if (byEmail) return byEmail; @@ -93,11 +93,10 @@ export function repairOAuthProfileIdMismatch(params: { } const toCred = params.store.profiles[toProfileId]; - const toEmail = - toCred?.type === "oauth" ? (toCred.email as string | undefined)?.trim() : undefined; + const toEmail = toCred?.type === "oauth" ? toCred.email?.trim() : undefined; const nextProfiles = { - ...(params.cfg.auth?.profiles as Record | undefined), + ...params.cfg.auth?.profiles, } as Record; delete nextProfiles[legacyProfileId]; nextProfiles[toProfileId] = { diff --git a/src/agents/bash-tools.exec.ts b/src/agents/bash-tools.exec.ts index ad77d10e6b..d226ce2adc 100644 --- a/src/agents/bash-tools.exec.ts +++ b/src/agents/bash-tools.exec.ts @@ -912,6 +912,7 @@ export function createExecTool( if (!nodeQuery && String(err).includes("node required")) { throw new Error( "exec host=node requires a node id when multiple nodes are available (set tools.exec.node or exec.node).", + { cause: err }, ); } throw err; @@ -941,11 +942,11 @@ export function createExecTool( let allowlistSatisfied = false; if (hostAsk === "on-miss" && hostSecurity === "allowlist" && analysisOk) { try { - const approvalsSnapshot = (await callGatewayTool( + const approvalsSnapshot = await callGatewayTool( "exec.approvals.node.get", { timeoutMs: 10_000 }, { nodeId }, - )) as { file?: unknown } | null; + ); const approvalsFile = approvalsSnapshot && typeof approvalsSnapshot === "object" ? approvalsSnapshot.file @@ -1016,7 +1017,7 @@ export function createExecTool( void (async () => { let decision: string | null = null; try { - const decisionResult = (await callGatewayTool( + const decisionResult = await callGatewayTool( "exec.approval.request", { timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS }, { @@ -1031,7 +1032,7 @@ export function createExecTool( sessionKey: defaults?.sessionKey, timeoutMs: DEFAULT_APPROVAL_TIMEOUT_MS, }, - )) as { decision?: string } | null; + ); decision = decisionResult && typeof decisionResult === "object" ? (decisionResult.decision ?? null) @@ -1124,20 +1125,11 @@ export function createExecTool( } const startedAt = Date.now(); - const raw = (await callGatewayTool( + const raw = await callGatewayTool( "node.invoke", { timeoutMs: invokeTimeoutMs }, buildInvokeParams(false, null), - )) as { - payload?: { - exitCode?: number; - timedOut?: boolean; - success?: boolean; - stdout?: string; - stderr?: string; - error?: string | null; - }; - }; + ); const payload = raw?.payload ?? {}; return { content: [ @@ -1197,7 +1189,7 @@ export function createExecTool( void (async () => { let decision: string | null = null; try { - const decisionResult = (await callGatewayTool( + const decisionResult = await callGatewayTool( "exec.approval.request", { timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS }, { @@ -1212,7 +1204,7 @@ export function createExecTool( sessionKey: defaults?.sessionKey, timeoutMs: DEFAULT_APPROVAL_TIMEOUT_MS, }, - )) as { decision?: string } | null; + ); decision = decisionResult && typeof decisionResult === "object" ? (decisionResult.decision ?? null) diff --git a/src/agents/bash-tools.process.ts b/src/agents/bash-tools.process.ts index 1463df086c..272c2cb4ac 100644 --- a/src/agents/bash-tools.process.ts +++ b/src/agents/bash-tools.process.ts @@ -116,7 +116,7 @@ export function createProcessTool( exitSignal: s.exitSignal ?? undefined, })); const lines = [...running, ...finished] - .sort((a, b) => b.startedAt - a.startedAt) + .toSorted((a, b) => b.startedAt - a.startedAt) .map((s) => { const label = s.name ? truncateMiddle(s.name, 80) : truncateMiddle(s.command, 120); return `${s.sessionId} ${pad(s.status, 9)} ${formatDuration(s.runtimeMs)} :: ${label}`; diff --git a/src/agents/bedrock-discovery.ts b/src/agents/bedrock-discovery.ts index 3b42d0081f..70e495e5c3 100644 --- a/src/agents/bedrock-discovery.ts +++ b/src/agents/bedrock-discovery.ts @@ -32,7 +32,7 @@ function normalizeProviderFilter(filter?: string[]): string[] { const normalized = new Set( filter.map((entry) => entry.trim().toLowerCase()).filter((entry) => entry.length > 0), ); - return Array.from(normalized).sort(); + return Array.from(normalized).toSorted(); } function buildCacheKey(params: { @@ -168,7 +168,7 @@ export async function discoverBedrockModels(params: { }), ); } - return discovered.sort((a, b) => a.name.localeCompare(b.name)); + return discovered.toSorted((a, b) => a.name.localeCompare(b.name)); })(); if (refreshIntervalSeconds > 0) { diff --git a/src/agents/cache-trace.ts b/src/agents/cache-trace.ts index d4236c1287..0d119b6ba8 100644 --- a/src/agents/cache-trace.ts +++ b/src/agents/cache-trace.ts @@ -147,7 +147,7 @@ function stableStringify(value: unknown): string { return `[${value.map((entry) => stableStringify(entry)).join(",")}]`; } const record = value as Record; - const keys = Object.keys(record).sort(); + const keys = Object.keys(record).toSorted(); const entries = keys.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`); return `{${entries.join(",")}}`; } @@ -249,9 +249,9 @@ export function createCacheTrace(params: CacheTraceInit): CacheTrace | null { const wrapped: StreamFn = (model, context, options) => { recordStage("stream:context", { model: { - id: (model as Model)?.id, - provider: (model as Model)?.provider, - api: (model as Model)?.api, + id: model?.id, + provider: model?.provider, + api: model?.api, }, system: (context as { system?: unknown }).system, messages: (context as { messages?: AgentMessage[] }).messages ?? [], diff --git a/src/agents/cli-runner/helpers.ts b/src/agents/cli-runner/helpers.ts index 67a60956a3..de3268974d 100644 --- a/src/agents/cli-runner/helpers.ts +++ b/src/agents/cli-runner/helpers.ts @@ -159,7 +159,7 @@ function buildModelAliasLines(cfg?: OpenClawConfig) { entries.push({ alias, model }); } return entries - .sort((a, b) => a.alias.localeCompare(b.alias)) + .toSorted((a, b) => a.alias.localeCompare(b.alias)) .map((entry) => `- ${entry.alias}: ${entry.model}`); } @@ -228,7 +228,7 @@ export function normalizeCliModel(modelId: string, backend: CliBackendConfig): s function toUsage(raw: Record): CliUsage | undefined { const pick = (key: string) => - typeof raw[key] === "number" && raw[key] > 0 ? (raw[key] as number) : undefined; + typeof raw[key] === "number" && raw[key] > 0 ? raw[key] : undefined; const input = pick("input_tokens") ?? pick("inputTokens"); const output = pick("output_tokens") ?? pick("outputTokens"); const cacheRead = diff --git a/src/agents/compaction.test.ts b/src/agents/compaction.test.ts index 32511a5866..b2d3dac46d 100644 --- a/src/agents/compaction.test.ts +++ b/src/agents/compaction.test.ts @@ -128,8 +128,8 @@ describe("pruneHistoryForContextShare", () => { const allIds = [ ...pruned.droppedMessagesList.map((m) => m.timestamp), ...pruned.messages.map((m) => m.timestamp), - ].sort((a, b) => a - b); - const originalIds = messages.map((m) => m.timestamp).sort((a, b) => a - b); + ].toSorted((a, b) => a - b); + const originalIds = messages.map((m) => m.timestamp).toSorted((a, b) => a - b); expect(allIds).toEqual(originalIds); }); diff --git a/src/agents/model-auth.ts b/src/agents/model-auth.ts index 763d4938d1..1f88ddc7f4 100644 --- a/src/agents/model-auth.ts +++ b/src/agents/model-auth.ts @@ -34,13 +34,11 @@ function resolveProviderConfig( const matched = Object.entries(providers).find( ([key]) => normalizeProviderId(key) === normalized, ); - return matched?.[1] as ModelProviderConfig | undefined; + return matched?.[1]; } return ( (providers[normalized] as ModelProviderConfig | undefined) ?? - (Object.entries(providers).find(([key]) => normalizeProviderId(key) === normalized)?.[1] as - | ModelProviderConfig - | undefined) + Object.entries(providers).find(([key]) => normalizeProviderId(key) === normalized)?.[1] ); } diff --git a/src/agents/model-catalog.ts b/src/agents/model-catalog.ts index 0e784af838..791980875b 100644 --- a/src/agents/model-catalog.ts +++ b/src/agents/model-catalog.ts @@ -83,9 +83,7 @@ export async function loadModelCatalog(params?: { ? entry.contextWindow : undefined; const reasoning = typeof entry?.reasoning === "boolean" ? entry.reasoning : undefined; - const input = Array.isArray(entry?.input) - ? (entry.input as Array<"text" | "image">) - : undefined; + const input = Array.isArray(entry?.input) ? entry.input : undefined; models.push({ id, name, provider, contextWindow, reasoning, input }); } diff --git a/src/agents/model-compat.ts b/src/agents/model-compat.ts index 741819073a..3874526ecf 100644 --- a/src/agents/model-compat.ts +++ b/src/agents/model-compat.ts @@ -9,7 +9,7 @@ export function normalizeModelCompat(model: Model): Model { const isZai = model.provider === "zai" || baseUrl.includes("api.z.ai"); if (!isZai || !isOpenAiCompletionsModel(model)) return model; - const openaiModel = model as Model<"openai-completions">; + const openaiModel = model; const compat = openaiModel.compat ?? undefined; if (compat?.supportsDeveloperRole === false) return model; diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index b99a104d59..89a35f4dd7 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -224,7 +224,7 @@ export async function runWithModelFallback(params: { let lastError: unknown; for (let i = 0; i < candidates.length; i += 1) { - const candidate = candidates[i] as ModelCandidate; + const candidate = candidates[i]; if (authStore) { const profileIds = resolveAuthProfileOrder({ cfg: params.cfg, @@ -330,7 +330,7 @@ export async function runWithImageModelFallback(params: { let lastError: unknown; for (let i = 0; i < candidates.length; i += 1) { - const candidate = candidates[i] as ModelCandidate; + const candidate = candidates[i]; try { const result = await params.run(candidate.provider, candidate.model); return { diff --git a/src/agents/model-scan.ts b/src/agents/model-scan.ts index ba47753726..47d90f92d7 100644 --- a/src/agents/model-scan.ts +++ b/src/agents/model-scan.ts @@ -325,7 +325,7 @@ async function mapWithConcurrency( opts?: { onProgress?: (completed: number, total: number) => void }, ): Promise { const limit = Math.max(1, Math.floor(concurrency)); - const results = Array.from({ length: items.length }) as R[]; + const results = Array.from({ length: items.length }); let nextIndex = 0; let completed = 0; @@ -334,7 +334,7 @@ async function mapWithConcurrency( const current = nextIndex; nextIndex += 1; if (current >= items.length) return; - results[current] = await fn(items[current] as T, current); + results[current] = await fn(items[current], current); completed += 1; opts?.onProgress?.(completed, items.length); } diff --git a/src/agents/models-config.ts b/src/agents/models-config.ts index 22c21af941..fd5ab37304 100644 --- a/src/agents/models-config.ts +++ b/src/agents/models-config.ts @@ -79,7 +79,7 @@ export async function ensureOpenClawModelsJson( const cfg = config ?? loadConfig(); const agentDir = agentDirOverride?.trim() ? agentDirOverride.trim() : resolveOpenClawAgentDir(); - const explicitProviders = (cfg.models?.providers ?? {}) as Record; + const explicitProviders = cfg.models?.providers ?? {}; const implicitProviders = await resolveImplicitProviders({ agentDir }); const providers: Record = mergeProviders({ implicit: implicitProviders, diff --git a/src/agents/models.profiles.live.test.ts b/src/agents/models.profiles.live.test.ts index e6d89be027..15f2d369ee 100644 --- a/src/agents/models.profiles.live.test.ts +++ b/src/agents/models.profiles.live.test.ts @@ -167,7 +167,7 @@ describeLive("live models (profile keys)", () => { const agentDir = resolveOpenClawAgentDir(); const authStorage = discoverAuthStorage(agentDir); const modelRegistry = discoverModels(authStorage, agentDir); - const models = modelRegistry.getAll() as Array>; + const models = modelRegistry.getAll(); const rawModels = process.env.OPENCLAW_LIVE_MODELS?.trim(); const useModern = rawModels === "modern" || rawModels === "all"; diff --git a/src/agents/pi-embedded-helpers/errors.ts b/src/agents/pi-embedded-helpers/errors.ts index 9bc92f259f..674edb6d15 100644 --- a/src/agents/pi-embedded-helpers/errors.ts +++ b/src/agents/pi-embedded-helpers/errors.ts @@ -160,7 +160,7 @@ function stableStringify(value: unknown): string { return `[${value.map((entry) => stableStringify(entry)).join(",")}]`; } const record = value as Record; - const keys = Object.keys(record).sort(); + const keys = Object.keys(record).toSorted(); const entries = keys.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`); return `{${entries.join(",")}}`; } diff --git a/src/agents/pi-embedded-helpers/images.ts b/src/agents/pi-embedded-helpers/images.ts index 518226ae0b..912500f744 100644 --- a/src/agents/pi-embedded-helpers/images.ts +++ b/src/agents/pi-embedded-helpers/images.ts @@ -60,7 +60,7 @@ export async function sanitizeSessionMessagesImages( const toolMsg = msg as Extract; const content = Array.isArray(toolMsg.content) ? toolMsg.content : []; const nextContent = (await sanitizeContentBlocksImages( - content as ContentBlock[], + content, label, )) as unknown as typeof toolMsg.content; out.push({ ...toolMsg, content: nextContent }); diff --git a/src/agents/pi-embedded-helpers/openai.ts b/src/agents/pi-embedded-helpers/openai.ts index 00a6892b67..f1350c087c 100644 --- a/src/agents/pi-embedded-helpers/openai.ts +++ b/src/agents/pi-embedded-helpers/openai.ts @@ -87,16 +87,16 @@ export function downgradeOpenAIReasoningBlocks(messages: AgentMessage[]): AgentM } const record = block as OpenAIThinkingBlock; if (record.type !== "thinking") { - nextContent.push(block as AssistantContentBlock); + nextContent.push(block); continue; } const signature = parseOpenAIReasoningSignature(record.thinkingSignature); if (!signature) { - nextContent.push(block as AssistantContentBlock); + nextContent.push(block); continue; } if (hasFollowingNonThinkingBlock(assistantMsg.content, i)) { - nextContent.push(block as AssistantContentBlock); + nextContent.push(block); continue; } changed = true; diff --git a/src/agents/pi-embedded-runner/extra-params.ts b/src/agents/pi-embedded-runner/extra-params.ts index 6599b9fd65..745ef23610 100644 --- a/src/agents/pi-embedded-runner/extra-params.ts +++ b/src/agents/pi-embedded-runner/extra-params.ts @@ -65,7 +65,7 @@ function createStreamFnWithExtraParams( const underlying = baseStreamFn ?? streamSimple; const wrappedStreamFn: StreamFn = (model, context, options) => - underlying(model as Model, context, { + underlying(model, context, { ...streamParams, ...options, }); diff --git a/src/agents/pi-embedded-runner/google.ts b/src/agents/pi-embedded-runner/google.ts index 7b26d0d04b..5ea6b84322 100644 --- a/src/agents/pi-embedded-runner/google.ts +++ b/src/agents/pi-embedded-runner/google.ts @@ -60,7 +60,7 @@ function sanitizeAntigravityThinkingBlocks(messages: AgentMessage[]): AgentMessa out.push(msg); continue; } - const assistant = msg as Extract; + const assistant = msg; if (!Array.isArray(assistant.content)) { out.push(msg); continue; diff --git a/src/agents/pi-embedded-runner/model.ts b/src/agents/pi-embedded-runner/model.ts index 9fbfba5b4d..db8b459715 100644 --- a/src/agents/pi-embedded-runner/model.ts +++ b/src/agents/pi-embedded-runner/model.ts @@ -46,7 +46,7 @@ export function buildModelAliasLines(cfg?: OpenClawConfig) { entries.push({ alias, model }); } return entries - .sort((a, b) => a.alias.localeCompare(b.alias)) + .toSorted((a, b) => a.alias.localeCompare(b.alias)) .map((entry) => `- ${entry.alias}: ${entry.model}`); } diff --git a/src/agents/pi-embedded-runner/run.overflow-compaction.test.ts b/src/agents/pi-embedded-runner/run.overflow-compaction.test.ts index 9065773554..13707d22cd 100644 --- a/src/agents/pi-embedded-runner/run.overflow-compaction.test.ts +++ b/src/agents/pi-embedded-runner/run.overflow-compaction.test.ts @@ -82,11 +82,7 @@ vi.mock("../defaults.js", () => ({ })); vi.mock("../failover-error.js", () => ({ - FailoverError: class extends Error { - constructor(msg: string) { - super(msg); - } - }, + FailoverError: class extends Error {}, resolveFailoverStatus: vi.fn(), })); diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index 5d4d4d0218..c4b5eff981 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -854,7 +854,7 @@ export async function runEmbeddedAttempt( const lastAssistant = messagesSnapshot .slice() - .reverse() + .toReversed() .find((m) => (m as AgentMessage)?.role === "assistant") as AssistantMessage | undefined; const toolMetasNormalized = toolMetas diff --git a/src/agents/pi-embedded-subscribe.handlers.messages.ts b/src/agents/pi-embedded-subscribe.handlers.messages.ts index 1f515e1137..568303e34a 100644 --- a/src/agents/pi-embedded-subscribe.handlers.messages.ts +++ b/src/agents/pi-embedded-subscribe.handlers.messages.ts @@ -162,7 +162,7 @@ export function handleMessageEnd( const msg = evt.message; if (msg?.role !== "assistant") return; - const assistantMessage = msg as AssistantMessage; + const assistantMessage = msg; promoteThinkingTagsToBlocks(assistantMessage); const rawText = extractAssistantText(assistantMessage); diff --git a/src/agents/pi-extensions/compaction-safeguard-runtime.ts b/src/agents/pi-extensions/compaction-safeguard-runtime.ts index f42cf7abe5..450ab6f8ff 100644 --- a/src/agents/pi-extensions/compaction-safeguard-runtime.ts +++ b/src/agents/pi-extensions/compaction-safeguard-runtime.ts @@ -14,7 +14,7 @@ export function setCompactionSafeguardRuntime( return; } - const key = sessionManager as object; + const key = sessionManager; if (value === null) { REGISTRY.delete(key); return; @@ -30,5 +30,5 @@ export function getCompactionSafeguardRuntime( return null; } - return REGISTRY.get(sessionManager as object) ?? null; + return REGISTRY.get(sessionManager) ?? null; } diff --git a/src/agents/pi-extensions/compaction-safeguard.ts b/src/agents/pi-extensions/compaction-safeguard.ts index b2fe398849..cf76e402eb 100644 --- a/src/agents/pi-extensions/compaction-safeguard.ts +++ b/src/agents/pi-extensions/compaction-safeguard.ts @@ -117,8 +117,8 @@ function computeFileLists(fileOps: FileOperations): { modifiedFiles: string[]; } { const modified = new Set([...fileOps.edited, ...fileOps.written]); - const readFiles = [...fileOps.read].filter((f) => !modified.has(f)).sort(); - const modifiedFiles = [...modified].sort(); + const readFiles = [...fileOps.read].filter((f) => !modified.has(f)).toSorted(); + const modifiedFiles = [...modified].toSorted(); return { readFiles, modifiedFiles }; } diff --git a/src/agents/pi-extensions/context-pruning/extension.ts b/src/agents/pi-extensions/context-pruning/extension.ts index 411cc9a44c..d544a4811d 100644 --- a/src/agents/pi-extensions/context-pruning/extension.ts +++ b/src/agents/pi-extensions/context-pruning/extension.ts @@ -1,4 +1,3 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; import type { ContextEvent, ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; import { pruneContextMessages } from "./pruner.js"; @@ -21,7 +20,7 @@ export default function contextPruningExtension(api: ExtensionAPI): void { } const next = pruneContextMessages({ - messages: event.messages as AgentMessage[], + messages: event.messages, settings: runtime.settings, ctx, isToolPrunable: runtime.isToolPrunable, diff --git a/src/agents/pi-extensions/context-pruning/runtime.ts b/src/agents/pi-extensions/context-pruning/runtime.ts index fecb4ce3e0..7780464d1d 100644 --- a/src/agents/pi-extensions/context-pruning/runtime.ts +++ b/src/agents/pi-extensions/context-pruning/runtime.ts @@ -20,7 +20,7 @@ export function setContextPruningRuntime( return; } - const key = sessionManager as object; + const key = sessionManager; if (value === null) { REGISTRY.delete(key); return; @@ -36,5 +36,5 @@ export function getContextPruningRuntime( return null; } - return REGISTRY.get(sessionManager as object) ?? null; + return REGISTRY.get(sessionManager) ?? null; } diff --git a/src/agents/pi-tool-definition-adapter.ts b/src/agents/pi-tool-definition-adapter.ts index 9632928224..63c65a077b 100644 --- a/src/agents/pi-tool-definition-adapter.ts +++ b/src/agents/pi-tool-definition-adapter.ts @@ -32,7 +32,7 @@ export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] { label: tool.label ?? name, description: tool.description ?? "", // biome-ignore lint/suspicious/noExplicitAny: TypeBox schema from pi-agent-core uses a different module instance. - parameters: tool.parameters as any, + parameters: tool.parameters, execute: async ( toolCallId, params, diff --git a/src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping-b.test.ts b/src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping-b.test.ts index 1b49931cc8..b5f1d1470d 100644 --- a/src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping-b.test.ts +++ b/src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping-b.test.ts @@ -117,7 +117,7 @@ describe("createOpenClawCodingTools", () => { return { name: tool.name, type: schema?.type, - keys: schema ? Object.keys(schema).sort() : null, + keys: schema ? Object.keys(schema).toSorted() : null, }; }) .filter((entry) => entry.type !== "object"); diff --git a/src/agents/pi-tools.read.ts b/src/agents/pi-tools.read.ts index 6decbb83b4..f48f50a8a9 100644 --- a/src/agents/pi-tools.read.ts +++ b/src/agents/pi-tools.read.ts @@ -272,11 +272,7 @@ export function createOpenClawReadTool(base: AnyAgentTool): AnyAgentTool { normalized ?? (params && typeof params === "object" ? (params as Record) : undefined); assertRequiredParams(record, CLAUDE_PARAM_GROUPS.read, base.name); - const result = (await base.execute( - toolCallId, - normalized ?? params, - signal, - )) as AgentToolResult; + const result = await base.execute(toolCallId, normalized ?? params, signal); const filePath = typeof record?.path === "string" ? String(record.path) : ""; const normalizedResult = await normalizeReadImageResult(result, filePath); return sanitizeToolResultImages(normalizedResult, `read:${filePath}`); diff --git a/src/agents/pi-tools.ts b/src/agents/pi-tools.ts index 802f1aced0..39b9d58186 100644 --- a/src/agents/pi-tools.ts +++ b/src/agents/pi-tools.ts @@ -247,7 +247,7 @@ export function createOpenClawCodingTools(options?: { // Wrap with param normalization for Claude Code compatibility return [wrapToolParamNormalization(createEditTool(workspaceRoot), CLAUDE_PARAM_GROUPS.edit)]; } - return [tool as AnyAgentTool]; + return [tool]; }); const { cleanupMs: cleanupMsOverride, ...execDefaults } = options?.exec ?? {}; const execTool = createExecTool({ @@ -338,13 +338,13 @@ export function createOpenClawCodingTools(options?: { ]; const coreToolNames = new Set( tools - .filter((tool) => !getPluginToolMeta(tool as AnyAgentTool)) + .filter((tool) => !getPluginToolMeta(tool)) .map((tool) => normalizeToolName(tool.name)) .filter(Boolean), ); const pluginGroups = buildPluginToolGroups({ tools, - toolMeta: (tool) => getPluginToolMeta(tool as AnyAgentTool), + toolMeta: (tool) => getPluginToolMeta(tool), }); const resolvePolicy = (policy: typeof profilePolicy, label: string) => { const resolved = stripPluginOnlyAllowlist(policy, pluginGroups, coreToolNames); diff --git a/src/agents/sandbox/config-hash.ts b/src/agents/sandbox/config-hash.ts index 872bac4bc0..6253a9f1f9 100644 --- a/src/agents/sandbox/config-hash.ts +++ b/src/agents/sandbox/config-hash.ts @@ -20,14 +20,14 @@ function normalizeForHash(value: unknown): unknown { .filter((item): item is unknown => item !== undefined); const primitives = normalized.filter(isPrimitive); if (primitives.length === normalized.length) { - return [...primitives].sort((a, b) => + return [...primitives].toSorted((a, b) => primitiveToString(a).localeCompare(primitiveToString(b)), ); } return normalized; } if (value && typeof value === "object") { - const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b)); + const entries = Object.entries(value).toSorted(([a], [b]) => a.localeCompare(b)); const normalized: Record = {}; for (const [key, entryValue] of entries) { const next = normalizeForHash(entryValue); diff --git a/src/agents/session-transcript-repair.ts b/src/agents/session-transcript-repair.ts index 2728bb89cc..68e5a2bf29 100644 --- a/src/agents/session-transcript-repair.ts +++ b/src/agents/session-transcript-repair.ts @@ -95,7 +95,7 @@ export function repairToolUseResultPairing(messages: AgentMessage[]): ToolUseRep }; for (let i = 0; i < messages.length; i += 1) { - const msg = messages[i] as AgentMessage; + const msg = messages[i]; if (!msg || typeof msg !== "object") { out.push(msg); continue; @@ -129,7 +129,7 @@ export function repairToolUseResultPairing(messages: AgentMessage[]): ToolUseRep let j = i + 1; for (; j < messages.length; j += 1) { - const next = messages[j] as AgentMessage; + const next = messages[j]; if (!next || typeof next !== "object") { remainder.push(next); continue; diff --git a/src/agents/skills.buildworkspaceskillcommands.test.ts b/src/agents/skills.buildworkspaceskillcommands.test.ts index c0812551a0..648be6592d 100644 --- a/src/agents/skills.buildworkspaceskillcommands.test.ts +++ b/src/agents/skills.buildworkspaceskillcommands.test.ts @@ -57,7 +57,7 @@ describe("buildWorkspaceSkillCommandSpecs", () => { reservedNames: new Set(["help"]), }); - const names = commands.map((entry) => entry.name).sort(); + const names = commands.map((entry) => entry.name).toSorted(); expect(names).toEqual(["hello_world", "hello_world_2", "help_2"]); expect(commands.find((entry) => entry.skillName === "hidden-skill")).toBeUndefined(); }); diff --git a/src/agents/skills.buildworkspaceskillsnapshot.test.ts b/src/agents/skills.buildworkspaceskillsnapshot.test.ts index d53b8a1232..2832ae5065 100644 --- a/src/agents/skills.buildworkspaceskillsnapshot.test.ts +++ b/src/agents/skills.buildworkspaceskillsnapshot.test.ts @@ -62,7 +62,7 @@ describe("buildWorkspaceSkillSnapshot", () => { expect(snapshot.prompt).toContain("visible-skill"); expect(snapshot.prompt).not.toContain("hidden-skill"); - expect(snapshot.skills.map((skill) => skill.name).sort()).toEqual([ + expect(snapshot.skills.map((skill) => skill.name).toSorted()).toEqual([ "hidden-skill", "visible-skill", ]); diff --git a/src/agents/skills.ts b/src/agents/skills.ts index eaf27ea7ad..11a2caa90f 100644 --- a/src/agents/skills.ts +++ b/src/agents/skills.ts @@ -39,7 +39,7 @@ export function resolveSkillsInstallPreferences(config?: OpenClawConfig) { const manager = managerRaw.toLowerCase(); const nodeManager = manager === "pnpm" || manager === "yarn" || manager === "bun" || manager === "npm" - ? (manager as "npm" | "pnpm" | "yarn" | "bun") + ? manager : "npm"; return { preferBrew, nodeManager }; } diff --git a/src/agents/skills/config.ts b/src/agents/skills/config.ts index c053f2b39c..f0a59869ad 100644 --- a/src/agents/skills/config.ts +++ b/src/agents/skills/config.ts @@ -30,7 +30,7 @@ export function resolveConfigPath(config: OpenClawConfig | undefined, pathStr: s export function isConfigPathTruthy(config: OpenClawConfig | undefined, pathStr: string): boolean { const value = resolveConfigPath(config, pathStr); if (value === undefined && pathStr in DEFAULT_CONFIG_VALUES) { - return DEFAULT_CONFIG_VALUES[pathStr] === true; + return DEFAULT_CONFIG_VALUES[pathStr]; } return isTruthy(value); } diff --git a/src/agents/skills/frontmatter.ts b/src/agents/skills/frontmatter.ts index 2f3ae5b24c..a3c3d13e8d 100644 --- a/src/agents/skills/frontmatter.ts +++ b/src/agents/skills/frontmatter.ts @@ -41,7 +41,7 @@ function parseInstallSpec(input: unknown): SkillInstallSpec | undefined { } const spec: SkillInstallSpec = { - kind: kind as SkillInstallSpec["kind"], + kind: kind, }; if (typeof raw.id === "string") spec.id = raw.id; @@ -78,7 +78,7 @@ export function resolveOpenClawMetadata( const raw = getFrontmatterValue(frontmatter, "metadata"); if (!raw) return undefined; try { - const parsed = JSON5.parse(raw) as Record; + const parsed = JSON5.parse(raw); if (!parsed || typeof parsed !== "object") return undefined; const metadataRawCandidates = [MANIFEST_KEY, ...LEGACY_MANIFEST_KEYS]; let metadataRaw: unknown; diff --git a/src/agents/subagent-announce.ts b/src/agents/subagent-announce.ts index 36dbbcf2b8..f5feda3bcf 100644 --- a/src/agents/subagent-announce.ts +++ b/src/agents/subagent-announce.ts @@ -327,19 +327,14 @@ export async function runSubagentAnnounceFlow(params: { let outcome: SubagentRunOutcome | undefined = params.outcome; if (!reply && params.waitForCompletion !== false) { const waitMs = Math.min(params.timeoutMs, 60_000); - const wait = (await callGateway({ + const wait = await callGateway({ method: "agent.wait", params: { runId: params.childRunId, timeoutMs: waitMs, }, timeoutMs: waitMs + 2000, - })) as { - status?: string; - error?: string; - startedAt?: number; - endedAt?: number; - }; + }); if (wait?.status === "timeout") { outcome = { status: "timeout" }; } else if (wait?.status === "error") { diff --git a/src/agents/subagent-registry.ts b/src/agents/subagent-registry.ts index d325e40e28..930209d52f 100644 --- a/src/agents/subagent-registry.ts +++ b/src/agents/subagent-registry.ts @@ -170,8 +170,7 @@ function ensureListener() { } const phase = evt.data?.phase; if (phase === "start") { - const startedAt = - typeof evt.data?.startedAt === "number" ? (evt.data.startedAt as number) : undefined; + const startedAt = typeof evt.data?.startedAt === "number" ? evt.data.startedAt : undefined; if (startedAt) { entry.startedAt = startedAt; persistSubagentRuns(); @@ -179,11 +178,10 @@ function ensureListener() { return; } if (phase !== "end" && phase !== "error") return; - const endedAt = - typeof evt.data?.endedAt === "number" ? (evt.data.endedAt as number) : Date.now(); + const endedAt = typeof evt.data?.endedAt === "number" ? evt.data.endedAt : Date.now(); entry.endedAt = endedAt; if (phase === "error") { - const error = typeof evt.data?.error === "string" ? (evt.data.error as string) : undefined; + const error = typeof evt.data?.error === "string" ? evt.data.error : undefined; entry.outcome = { status: "error", error }; } else { entry.outcome = { status: "ok" }; @@ -284,14 +282,14 @@ export function registerSubagentRun(params: { async function waitForSubagentCompletion(runId: string, waitTimeoutMs: number) { try { const timeoutMs = Math.max(1, Math.floor(waitTimeoutMs)); - const wait = (await callGateway({ + const wait = await callGateway({ method: "agent.wait", params: { runId, timeoutMs, }, timeoutMs: timeoutMs + 10_000, - })) as { status?: string; startedAt?: number; endedAt?: number; error?: string }; + }); if (wait?.status !== "ok" && wait?.status !== "error") return; const entry = subagentRuns.get(runId); if (!entry) return; diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index 9d914ab13e..6ea8e3ad94 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -264,7 +264,7 @@ export function buildAgentSystemPrompt(params: { const name = resolveToolName(tool); return summary ? `- ${name}: ${summary}` : `- ${name}`; }); - for (const tool of extraTools.sort()) { + for (const tool of extraTools.toSorted()) { const summary = coreToolSummaries[tool] ?? externalToolSummaries.get(tool); const name = resolveToolName(tool); toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`); diff --git a/src/agents/tool-images.ts b/src/agents/tool-images.ts index 9571dbd008..3e169561ef 100644 --- a/src/agents/tool-images.ts +++ b/src/agents/tool-images.ts @@ -91,7 +91,7 @@ async function resizeImageBase64IfNeeded(params: { const sideGrid = [sideStart, 1800, 1600, 1400, 1200, 1000, 800] .map((v) => Math.min(params.maxDimensionPx, v)) .filter((v, i, arr) => v > 0 && arr.indexOf(v) === i) - .sort((a, b) => b - a); + .toSorted((a, b) => b - a); let smallest: { buffer: Buffer; size: number } | null = null; for (const side of sideGrid) { @@ -191,7 +191,7 @@ export async function sanitizeImageBlocks( ): Promise<{ images: ImageContent[]; dropped: number }> { if (images.length === 0) return { images, dropped: 0 }; const sanitized = await sanitizeContentBlocksImages(images as ToolContentBlock[], label, opts); - const next = sanitized.filter(isImageBlock) as ImageContent[]; + const next = sanitized.filter(isImageBlock); return { images: next, dropped: Math.max(0, images.length - next.length) }; } diff --git a/src/agents/tools/agent-step.ts b/src/agents/tools/agent-step.ts index e55c16a781..eb826f3065 100644 --- a/src/agents/tools/agent-step.ts +++ b/src/agents/tools/agent-step.ts @@ -9,10 +9,10 @@ export async function readLatestAssistantReply(params: { sessionKey: string; limit?: number; }): Promise { - const history = (await callGateway({ + const history = await callGateway({ method: "chat.history", params: { sessionKey: params.sessionKey, limit: params.limit ?? 50 }, - })) as { messages?: unknown[] }; + }); const filtered = stripToolMessages(Array.isArray(history?.messages) ? history.messages : []); const last = filtered.length > 0 ? filtered[filtered.length - 1] : undefined; return last ? extractAssistantText(last) : undefined; @@ -27,7 +27,7 @@ export async function runAgentStep(params: { lane?: string; }): Promise { const stepIdem = crypto.randomUUID(); - const response = (await callGateway({ + const response = await callGateway({ method: "agent", params: { message: params.message, @@ -39,19 +39,19 @@ export async function runAgentStep(params: { extraSystemPrompt: params.extraSystemPrompt, }, timeoutMs: 10_000, - })) as { runId?: string; acceptedAt?: number }; + }); const stepRunId = typeof response?.runId === "string" && response.runId ? response.runId : ""; const resolvedRunId = stepRunId || stepIdem; const stepWaitMs = Math.min(params.timeoutMs, 60_000); - const wait = (await callGateway({ + const wait = await callGateway({ method: "agent.wait", params: { runId: resolvedRunId, timeoutMs: stepWaitMs, }, timeoutMs: stepWaitMs + 2000, - })) as { status?: string }; + }); if (wait?.status !== "ok") return undefined; return await readLatestAssistantReply({ sessionKey: params.sessionKey }); } diff --git a/src/agents/tools/agents-list-tool.ts b/src/agents/tools/agents-list-tool.ts index 28f1368446..fb8d6ff624 100644 --- a/src/agents/tools/agents-list-tool.ts +++ b/src/agents/tools/agents-list-tool.ts @@ -72,7 +72,9 @@ export function createAgentsListTool(opts?: { } const all = Array.from(allowed); - const rest = all.filter((id) => id !== requesterAgentId).sort((a, b) => a.localeCompare(b)); + const rest = all + .filter((id) => id !== requesterAgentId) + .toSorted((a, b) => a.localeCompare(b)); const ordered = [requesterAgentId, ...rest]; const agents: AgentListEntry[] = ordered.map((id) => ({ id, diff --git a/src/agents/tools/browser-tool.ts b/src/agents/tools/browser-tool.ts index ccdfd7c0fb..77a233166d 100644 --- a/src/agents/tools/browser-tool.ts +++ b/src/agents/tools/browser-tool.ts @@ -93,7 +93,7 @@ async function resolveBrowserNodeTarget(params: { if (params.target === "node") { if (browserNodes.length === 1) { - const node = browserNodes[0]!; + const node = browserNodes[0]; return { nodeId: node.nodeId, label: node.displayName ?? node.remoteIp ?? node.nodeId }; } throw new Error( @@ -104,7 +104,7 @@ async function resolveBrowserNodeTarget(params: { if (mode === "manual") return null; if (browserNodes.length === 1) { - const node = browserNodes[0]!; + const node = browserNodes[0]; return { nodeId: node.nodeId, label: node.displayName ?? node.remoteIp ?? node.nodeId }; } return null; @@ -123,7 +123,7 @@ async function callBrowserProxy(params: { typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs) ? Math.max(1, Math.floor(params.timeoutMs)) : DEFAULT_BROWSER_PROXY_TIMEOUT_MS; - const payload = (await callGatewayTool( + const payload = await callGatewayTool( "node.invoke", { timeoutMs: gatewayTimeoutMs }, { @@ -139,11 +139,7 @@ async function callBrowserProxy(params: { }, idempotencyKey: crypto.randomUUID(), }, - )) as { - ok?: boolean; - payload?: BrowserProxyResult; - payloadJSON?: string | null; - }; + ); const parsed = payload?.payload ?? (typeof payload?.payloadJSON === "string" && payload.payloadJSON @@ -414,7 +410,7 @@ export function createBrowserTool(opts?: { const snapshotDefaults = loadConfig().browser?.snapshotDefaults; const format = params.snapshotFormat === "ai" || params.snapshotFormat === "aria" - ? (params.snapshotFormat as "ai" | "aria") + ? params.snapshotFormat : "ai"; const mode = params.mode === "efficient" @@ -697,10 +693,12 @@ export function createBrowserTool(opts?: { if (!tabs.length) { throw new Error( "No Chrome tabs are attached via the OpenClaw Browser Relay extension. Click the toolbar icon on the tab you want to control (badge ON), then retry.", + { cause: err }, ); } throw new Error( `Chrome tab not found (stale targetId?). Run action=tabs profile="chrome" and use one of the returned targetIds.`, + { cause: err }, ); } throw err; diff --git a/src/agents/tools/cron-tool.ts b/src/agents/tools/cron-tool.ts index 739b3ada37..ca3e69a5fc 100644 --- a/src/agents/tools/cron-tool.ts +++ b/src/agents/tools/cron-tool.ts @@ -103,10 +103,10 @@ async function buildReminderContextLines(params: { const { mainKey, alias } = resolveMainSessionAlias(cfg); const resolvedKey = resolveInternalSessionKey({ key: sessionKey, alias, mainKey }); try { - const res = (await callGatewayTool("chat.history", params.gatewayOpts, { + const res = await callGatewayTool("chat.history", params.gatewayOpts, { sessionKey: resolvedKey, limit: maxMessages, - })) as { messages?: unknown[] }; + }); const messages = Array.isArray(res?.messages) ? res.messages : []; const parsed = messages .map((msg) => extractMessageText(msg as ChatMessage)) diff --git a/src/agents/tools/image-tool.ts b/src/agents/tools/image-tool.ts index faa40fd744..29cd240a52 100644 --- a/src/agents/tools/image-tool.ts +++ b/src/agents/tools/image-tool.ts @@ -267,10 +267,10 @@ async function runImagePrompt(params: { } const context = buildImageContext(params.prompt, params.base64, params.mimeType); - const message = (await complete(model, context, { + const message = await complete(model, context, { apiKey, maxTokens: 512, - })) as AssistantMessage; + }); const text = coerceImageAssistantText({ message, provider: model.provider, diff --git a/src/agents/tools/message-tool.ts b/src/agents/tools/message-tool.ts index d7050e4e60..93e7420cf2 100644 --- a/src/agents/tools/message-tool.ts +++ b/src/agents/tools/message-tool.ts @@ -307,7 +307,7 @@ function buildMessageToolDescription(options?: { if (channelActions.length > 0) { // Always include "send" as a base action const allActions = new Set(["send", ...channelActions]); - const actionList = Array.from(allActions).sort().join(", "); + const actionList = Array.from(allActions).toSorted().join(", "); return `${baseDescription} Current channel (${options.currentChannel}) supports: ${actionList}.`; } } diff --git a/src/agents/tools/nodes-tool.ts b/src/agents/tools/nodes-tool.ts index 77b7378764..d3379c2f59 100644 --- a/src/agents/tools/nodes-tool.ts +++ b/src/agents/tools/nodes-tool.ts @@ -199,7 +199,7 @@ export function createNodesTool(options?: { const details: Array> = []; for (const facing of facings) { - const raw = (await callGatewayTool("node.invoke", gatewayOpts, { + const raw = await callGatewayTool("node.invoke", gatewayOpts, { nodeId, command: "camera.snap", params: { @@ -211,7 +211,7 @@ export function createNodesTool(options?: { deviceId, }, idempotencyKey: crypto.randomUUID(), - })) as { payload?: unknown }; + }); const payload = parseCameraSnapPayload(raw?.payload); const normalizedFormat = payload.format.toLowerCase(); if ( @@ -250,12 +250,12 @@ export function createNodesTool(options?: { case "camera_list": { const node = readStringParam(params, "node", { required: true }); const nodeId = await resolveNodeId(gatewayOpts, node); - const raw = (await callGatewayTool("node.invoke", gatewayOpts, { + const raw = await callGatewayTool("node.invoke", gatewayOpts, { nodeId, command: "camera.list", params: {}, idempotencyKey: crypto.randomUUID(), - })) as { payload?: unknown }; + }); const payload = raw && typeof raw.payload === "object" && raw.payload !== null ? raw.payload : {}; return jsonResult(payload); @@ -280,7 +280,7 @@ export function createNodesTool(options?: { typeof params.deviceId === "string" && params.deviceId.trim() ? params.deviceId.trim() : undefined; - const raw = (await callGatewayTool("node.invoke", gatewayOpts, { + const raw = await callGatewayTool("node.invoke", gatewayOpts, { nodeId, command: "camera.clip", params: { @@ -291,7 +291,7 @@ export function createNodesTool(options?: { deviceId, }, idempotencyKey: crypto.randomUUID(), - })) as { payload?: unknown }; + }); const payload = parseCameraClipPayload(raw?.payload); const filePath = cameraTempPath({ kind: "clip", @@ -326,7 +326,7 @@ export function createNodesTool(options?: { : 0; const includeAudio = typeof params.includeAudio === "boolean" ? params.includeAudio : true; - const raw = (await callGatewayTool("node.invoke", gatewayOpts, { + const raw = await callGatewayTool("node.invoke", gatewayOpts, { nodeId, command: "screen.record", params: { @@ -337,7 +337,7 @@ export function createNodesTool(options?: { includeAudio, }, idempotencyKey: crypto.randomUUID(), - })) as { payload?: unknown }; + }); const payload = parseScreenRecordPayload(raw?.payload); const filePath = typeof params.outPath === "string" && params.outPath.trim() @@ -373,7 +373,7 @@ export function createNodesTool(options?: { Number.isFinite(params.locationTimeoutMs) ? params.locationTimeoutMs : undefined; - const raw = (await callGatewayTool("node.invoke", gatewayOpts, { + const raw = await callGatewayTool("node.invoke", gatewayOpts, { nodeId, command: "location.get", params: { @@ -382,7 +382,7 @@ export function createNodesTool(options?: { timeoutMs: locationTimeoutMs, }, idempotencyKey: crypto.randomUUID(), - })) as { payload?: unknown }; + }); return jsonResult(raw?.payload ?? {}); } case "run": { @@ -423,7 +423,7 @@ export function createNodesTool(options?: { typeof params.needsScreenRecording === "boolean" ? params.needsScreenRecording : undefined; - const raw = (await callGatewayTool("node.invoke", gatewayOpts, { + const raw = await callGatewayTool("node.invoke", gatewayOpts, { nodeId, command: "system.run", params: { @@ -437,7 +437,7 @@ export function createNodesTool(options?: { }, timeoutMs: invokeTimeoutMs, idempotencyKey: crypto.randomUUID(), - })) as { payload?: unknown }; + }); return jsonResult(raw?.payload ?? {}); } default: @@ -454,6 +454,7 @@ export function createNodesTool(options?: { const message = err instanceof Error ? err.message : String(err); throw new Error( `agent=${agentLabel} node=${nodeLabel} gateway=${gatewayLabel} action=${action}: ${message}`, + { cause: err }, ); } }, diff --git a/src/agents/tools/nodes-utils.ts b/src/agents/tools/nodes-utils.ts index 04cda45c4e..0d7b8fb5e4 100644 --- a/src/agents/tools/nodes-utils.ts +++ b/src/agents/tools/nodes-utils.ts @@ -71,10 +71,10 @@ function normalizeNodeKey(value: string) { async function loadNodes(opts: GatewayCallOptions): Promise { try { - const res = (await callGatewayTool("node.list", opts, {})) as unknown; + const res = await callGatewayTool("node.list", opts, {}); return parseNodeList(res); } catch { - const res = (await callGatewayTool("node.pair.list", opts, {})) as unknown; + const res = await callGatewayTool("node.pair.list", opts, {}); const { paired } = parsePairingList(res); return paired.map((n) => ({ nodeId: n.nodeId, diff --git a/src/agents/tools/sessions-announce-target.ts b/src/agents/tools/sessions-announce-target.ts index ed993788f9..7b9fd1daf3 100644 --- a/src/agents/tools/sessions-announce-target.ts +++ b/src/agents/tools/sessions-announce-target.ts @@ -20,14 +20,14 @@ export async function resolveAnnounceTarget(params: { } try { - const list = (await callGateway({ + const list = await callGateway({ method: "sessions.list", params: { includeGlobal: true, includeUnknown: true, limit: 200, }, - })) as { sessions?: Array> }; + }); const sessions = Array.isArray(list?.sessions) ? list.sessions : []; const match = sessions.find((entry) => entry?.key === params.sessionKey) ?? diff --git a/src/agents/tools/sessions-helpers.ts b/src/agents/tools/sessions-helpers.ts index 3ce2bc0cba..c8d3459c79 100644 --- a/src/agents/tools/sessions-helpers.ts +++ b/src/agents/tools/sessions-helpers.ts @@ -135,7 +135,7 @@ async function resolveSessionKeyFromSessionId(params: { }): Promise { try { // Resolve via gateway so we respect store routing and visibility rules. - const result = (await callGateway({ + const result = await callGateway({ method: "sessions.resolve", params: { sessionId: params.sessionId, @@ -143,7 +143,7 @@ async function resolveSessionKeyFromSessionId(params: { includeGlobal: !params.restrictToSpawned, includeUnknown: !params.restrictToSpawned, }, - })) as { key?: unknown }; + }); const key = typeof result?.key === "string" ? result.key.trim() : ""; if (!key) { throw new Error( @@ -188,13 +188,13 @@ async function resolveSessionKeyFromKey(params: { }): Promise { try { // Try key-based resolution first so non-standard keys keep working. - const result = (await callGateway({ + const result = await callGateway({ method: "sessions.resolve", params: { key: params.key, spawnedBy: params.restrictToSpawned ? params.requesterInternalKey : undefined, }, - })) as { key?: unknown }; + }); const key = typeof result?.key === "string" ? result.key.trim() : ""; if (!key) return null; return { diff --git a/src/agents/tools/sessions-history-tool.ts b/src/agents/tools/sessions-history-tool.ts index 5351b70c51..d6c8968205 100644 --- a/src/agents/tools/sessions-history-tool.ts +++ b/src/agents/tools/sessions-history-tool.ts @@ -28,7 +28,7 @@ async function isSpawnedSessionAllowed(params: { targetSessionKey: string; }): Promise { try { - const list = (await callGateway({ + const list = await callGateway({ method: "sessions.list", params: { includeGlobal: false, @@ -36,7 +36,7 @@ async function isSpawnedSessionAllowed(params: { limit: 500, spawnedBy: params.requesterSessionKey, }, - })) as { sessions?: Array> }; + }); const sessions = Array.isArray(list?.sessions) ? list.sessions : []; return sessions.some((entry) => entry?.key === params.targetSessionKey); } catch { @@ -126,10 +126,10 @@ export function createSessionsHistoryTool(opts?: { ? Math.max(1, Math.floor(params.limit)) : undefined; const includeTools = Boolean(params.includeTools); - const result = (await callGateway({ + const result = await callGateway({ method: "chat.history", params: { sessionKey: resolvedKey, limit }, - })) as { messages?: unknown[] }; + }); const rawMessages = Array.isArray(result?.messages) ? result.messages : []; const messages = includeTools ? rawMessages : stripToolMessages(rawMessages); return jsonResult({ diff --git a/src/agents/tools/sessions-list-tool.ts b/src/agents/tools/sessions-list-tool.ts index 148a33d306..035be9abc6 100644 --- a/src/agents/tools/sessions-list-tool.ts +++ b/src/agents/tools/sessions-list-tool.ts @@ -79,7 +79,7 @@ export function createSessionsListTool(opts?: { : 0; const messageLimit = Math.min(messageLimitRaw, 20); - const list = (await callGateway({ + const list = await callGateway({ method: "sessions.list", params: { limit, @@ -88,10 +88,7 @@ export function createSessionsListTool(opts?: { includeUnknown: !restrictToSpawned, spawnedBy: restrictToSpawned ? requesterInternalKey : undefined, }, - })) as { - path?: string; - sessions?: Array>; - }; + }); const sessions = Array.isArray(list?.sessions) ? list.sessions : []; const storePath = typeof list?.path === "string" ? list.path : undefined; @@ -187,10 +184,10 @@ export function createSessionsListTool(opts?: { alias, mainKey, }); - const history = (await callGateway({ + const history = await callGateway({ method: "chat.history", params: { sessionKey: resolvedKey, limit: messageLimit }, - })) as { messages?: unknown[] }; + }); const rawMessages = Array.isArray(history?.messages) ? history.messages : []; const filtered = stripToolMessages(rawMessages); row.messages = filtered.length > messageLimit ? filtered.slice(-messageLimit) : filtered; diff --git a/src/agents/tools/sessions-send-tool.a2a.ts b/src/agents/tools/sessions-send-tool.a2a.ts index a98c34a236..6a0de3094a 100644 --- a/src/agents/tools/sessions-send-tool.a2a.ts +++ b/src/agents/tools/sessions-send-tool.a2a.ts @@ -33,14 +33,14 @@ export async function runSessionsSendA2AFlow(params: { let latestReply = params.roundOneReply; if (!primaryReply && params.waitRunId) { const waitMs = Math.min(params.announceTimeoutMs, 60_000); - const wait = (await callGateway({ + const wait = await callGateway({ method: "agent.wait", params: { runId: params.waitRunId, timeoutMs: waitMs, }, timeoutMs: waitMs + 2000, - })) as { status?: string }; + }); if (wait?.status === "ok") { primaryReply = await readLatestAssistantReply({ sessionKey: params.targetSessionKey, diff --git a/src/agents/tools/sessions-send-tool.ts b/src/agents/tools/sessions-send-tool.ts index 28344b83b8..bc5d295efa 100644 --- a/src/agents/tools/sessions-send-tool.ts +++ b/src/agents/tools/sessions-send-tool.ts @@ -81,11 +81,11 @@ export function createSessionsSendTool(opts?: { } const listSessions = async (listParams: Record) => { - const result = (await callGateway({ + const result = await callGateway({ method: "sessions.list", params: listParams, timeoutMs: 10_000, - })) as { sessions?: Array> }; + }); return Array.isArray(result?.sessions) ? result.sessions : []; }; @@ -136,11 +136,11 @@ export function createSessionsSendTool(opts?: { }; let resolvedKey = ""; try { - const resolved = (await callGateway({ + const resolved = await callGateway({ method: "sessions.resolve", params: resolveParams, timeoutMs: 10_000, - })) as { key?: unknown }; + }); resolvedKey = typeof resolved?.key === "string" ? resolved.key.trim() : ""; } catch (err) { const msg = err instanceof Error ? err.message : String(err); @@ -283,11 +283,11 @@ export function createSessionsSendTool(opts?: { if (timeoutSeconds === 0) { try { - const response = (await callGateway({ + const response = await callGateway({ method: "agent", params: sendParams, timeoutMs: 10_000, - })) as { runId?: string; acceptedAt?: number }; + }); if (typeof response?.runId === "string" && response.runId) { runId = response.runId; } @@ -311,11 +311,11 @@ export function createSessionsSendTool(opts?: { } try { - const response = (await callGateway({ + const response = await callGateway({ method: "agent", params: sendParams, timeoutMs: 10_000, - })) as { runId?: string; acceptedAt?: number }; + }); if (typeof response?.runId === "string" && response.runId) { runId = response.runId; } @@ -333,14 +333,14 @@ export function createSessionsSendTool(opts?: { let waitStatus: string | undefined; let waitError: string | undefined; try { - const wait = (await callGateway({ + const wait = await callGateway({ method: "agent.wait", params: { runId, timeoutMs, }, timeoutMs: timeoutMs + 2000, - })) as { status?: string; error?: string }; + }); waitStatus = typeof wait?.status === "string" ? wait.status : undefined; waitError = typeof wait?.error === "string" ? wait.error : undefined; } catch (err) { @@ -371,10 +371,10 @@ export function createSessionsSendTool(opts?: { }); } - const history = (await callGateway({ + const history = await callGateway({ method: "chat.history", params: { sessionKey: resolvedKey, limit: 50 }, - })) as { messages?: unknown[] }; + }); const filtered = stripToolMessages(Array.isArray(history?.messages) ? history.messages : []); const last = filtered.length > 0 ? filtered[filtered.length - 1] : undefined; const reply = last ? extractAssistantText(last) : undefined; diff --git a/src/agents/tools/sessions-spawn-tool.ts b/src/agents/tools/sessions-spawn-tool.ts index e5e1391d10..e00730f2a2 100644 --- a/src/agents/tools/sessions-spawn-tool.ts +++ b/src/agents/tools/sessions-spawn-tool.ts @@ -84,9 +84,7 @@ export function createSessionsSpawnTool(opts?: { const modelOverride = readStringParam(params, "model"); const thinkingOverrideRaw = readStringParam(params, "thinking"); const cleanup = - params.cleanup === "keep" || params.cleanup === "delete" - ? (params.cleanup as "keep" | "delete") - : "keep"; + params.cleanup === "keep" || params.cleanup === "delete" ? params.cleanup : "keep"; const requesterOrigin = normalizeDeliveryContext({ channel: opts?.agentChannel, accountId: opts?.agentAccountId, @@ -211,7 +209,7 @@ export function createSessionsSpawnTool(opts?: { const childIdem = crypto.randomUUID(); let childRunId: string = childIdem; try { - const response = (await callGateway({ + const response = await callGateway({ method: "agent", params: { message: task, @@ -230,7 +228,7 @@ export function createSessionsSpawnTool(opts?: { groupSpace: opts?.agentGroupSpace ?? undefined, }, timeoutMs: 10_000, - })) as { runId?: string }; + }); if (typeof response?.runId === "string" && response.runId) { childRunId = response.runId; } diff --git a/src/auto-reply/envelope.ts b/src/auto-reply/envelope.ts index a50235f269..1d3f73fcf0 100644 --- a/src/auto-reply/envelope.ts +++ b/src/auto-reply/envelope.ts @@ -115,7 +115,7 @@ function formatZonedTimestamp(date: Date, timeZone?: string): string | undefined const hh = pick("hour"); const min = pick("minute"); const tz = [...parts] - .reverse() + .toReversed() .find((part) => part.type === "timeZoneName") ?.value?.trim(); if (!yyyy || !mm || !dd || !hh || !min) return undefined; diff --git a/src/auto-reply/reply/commands-context-report.ts b/src/auto-reply/reply/commands-context-report.ts index 9e54576547..5319ec3ea5 100644 --- a/src/auto-reply/reply/commands-context-report.ts +++ b/src/auto-reply/reply/commands-context-report.ts @@ -38,7 +38,7 @@ function formatListTop( entries: Array<{ name: string; value: number }>, cap: number, ): { lines: string[]; omitted: number } { - const sorted = [...entries].sort((a, b) => b.value - a.value); + const sorted = [...entries].toSorted((a, b) => b.value - a.value); const top = sorted.slice(0, cap); const omitted = Math.max(0, sorted.length - top.length); const lines = top.map((e) => `- ${e.name}: ${formatCharsAndTokens(e.value)}`); @@ -263,7 +263,7 @@ export async function buildContextReply(params: HandleCommandsParams): Promise t.propertiesCount != null) - .sort((a, b) => (b.propertiesCount ?? 0) - (a.propertiesCount ?? 0)) + .toSorted((a, b) => (b.propertiesCount ?? 0) - (a.propertiesCount ?? 0)) .slice(0, 30) .map((t) => `- ${t.name}: ${t.propertiesCount} params`); diff --git a/src/auto-reply/reply/commands-models.ts b/src/auto-reply/reply/commands-models.ts index 73616c628c..87d0bfd68f 100644 --- a/src/auto-reply/reply/commands-models.ts +++ b/src/auto-reply/reply/commands-models.ts @@ -154,7 +154,7 @@ export async function resolveModelsCommandReply(params: { add(resolvedDefault.provider, resolvedDefault.model); addModelConfigEntries(); - const providers = [...byProvider.keys()].sort(); + const providers = [...byProvider.keys()].toSorted(); if (!provider) { const lines: string[] = [ @@ -181,7 +181,7 @@ export async function resolveModelsCommandReply(params: { return { text: lines.join("\n") }; } - const models = [...(byProvider.get(provider) ?? new Set())].sort(); + const models = [...(byProvider.get(provider) ?? new Set())].toSorted(); const total = models.length; if (total === 0) { diff --git a/src/auto-reply/reply/commands-session.ts b/src/auto-reply/reply/commands-session.ts index b63bddb210..15d762f4f8 100644 --- a/src/auto-reply/reply/commands-session.ts +++ b/src/auto-reply/reply/commands-session.ts @@ -289,7 +289,7 @@ export const handleStopCommand: CommandHandler = async (params, allowTextCommand params.sessionStore[abortTarget.key] = abortTarget.entry; if (params.storePath) { await updateSessionStore(params.storePath, (store) => { - store[abortTarget.key] = abortTarget.entry as SessionEntry; + store[abortTarget.key] = abortTarget.entry; }); } } else if (params.command.abortKey) { @@ -336,7 +336,7 @@ export const handleAbortTrigger: CommandHandler = async (params, allowTextComman params.sessionStore[abortTarget.key] = abortTarget.entry; if (params.storePath) { await updateSessionStore(params.storePath, (store) => { - store[abortTarget.key] = abortTarget.entry as SessionEntry; + store[abortTarget.key] = abortTarget.entry; }); } } else if (params.command.abortKey) { diff --git a/src/auto-reply/reply/commands-subagents.ts b/src/auto-reply/reply/commands-subagents.ts index 5009a30fad..e4ff7c27dc 100644 --- a/src/auto-reply/reply/commands-subagents.ts +++ b/src/auto-reply/reply/commands-subagents.ts @@ -316,10 +316,10 @@ export const handleSubagentsCommand: CommandHandler = async (params, allowTextCo reply: { text: `⚠️ ${resolved.error ?? "Unknown subagent."}` }, }; } - const history = (await callGateway({ + const history = await callGateway({ method: "chat.history", params: { sessionKey: resolved.entry.childSessionKey, limit }, - })) as { messages?: unknown[] }; + }); const rawMessages = Array.isArray(history?.messages) ? history.messages : []; const filtered = includeTools ? rawMessages : stripToolMessages(rawMessages); const lines = formatLogLines(filtered as ChatMessage[]); @@ -349,7 +349,7 @@ export const handleSubagentsCommand: CommandHandler = async (params, allowTextCo const idempotencyKey = crypto.randomUUID(); let runId: string = idempotencyKey; try { - const response = (await callGateway({ + const response = await callGateway({ method: "agent", params: { message, @@ -360,7 +360,7 @@ export const handleSubagentsCommand: CommandHandler = async (params, allowTextCo lane: AGENT_LANE_SUBAGENT, }, timeoutMs: 10_000, - })) as { runId?: string }; + }); if (response?.runId) runId = response.runId; } catch (err) { const messageText = @@ -369,11 +369,11 @@ export const handleSubagentsCommand: CommandHandler = async (params, allowTextCo } const waitMs = 30_000; - const wait = (await callGateway({ + const wait = await callGateway({ method: "agent.wait", params: { runId, timeoutMs: waitMs }, timeoutMs: waitMs + 2000, - })) as { status?: string; error?: string }; + }); if (wait?.status === "timeout") { return { shouldContinue: false, @@ -389,10 +389,10 @@ export const handleSubagentsCommand: CommandHandler = async (params, allowTextCo }; } - const history = (await callGateway({ + const history = await callGateway({ method: "chat.history", params: { sessionKey: resolved.entry.childSessionKey, limit: 50 }, - })) as { messages?: unknown[] }; + }); const filtered = stripToolMessages(Array.isArray(history?.messages) ? history.messages : []); const last = filtered.length > 0 ? filtered[filtered.length - 1] : undefined; const replyText = last ? extractAssistantText(last) : undefined; diff --git a/src/auto-reply/reply/directive-handling.impl.ts b/src/auto-reply/reply/directive-handling.impl.ts index 0a7c563aa8..f95fd333e8 100644 --- a/src/auto-reply/reply/directive-handling.impl.ts +++ b/src/auto-reply/reply/directive-handling.impl.ts @@ -54,8 +54,7 @@ function resolveExecDefaults(params: { (agentExec?.ask as ExecAsk | undefined) ?? (globalExec?.ask as ExecAsk | undefined) ?? "on-miss", - node: - (params.sessionEntry?.execNode as string | undefined) ?? agentExec?.node ?? globalExec?.node, + node: params.sessionEntry?.execNode ?? agentExec?.node ?? globalExec?.node, }; } diff --git a/src/auto-reply/reply/get-reply-directives-apply.ts b/src/auto-reply/reply/get-reply-directives-apply.ts index c55e90539c..153dba1e12 100644 --- a/src/auto-reply/reply/get-reply-directives-apply.ts +++ b/src/auto-reply/reply/get-reply-directives-apply.ts @@ -196,8 +196,8 @@ export async function applyInlineDirectiveOverrides(params: { model, contextTokens, resolvedThinkLevel: resolvedDefaultThinkLevel, - resolvedVerboseLevel: (currentVerboseLevel ?? "off") as VerboseLevel, - resolvedReasoningLevel: (currentReasoningLevel ?? "off") as ReasoningLevel, + resolvedVerboseLevel: currentVerboseLevel ?? "off", + resolvedReasoningLevel: currentReasoningLevel ?? "off", resolvedElevatedLevel, resolveDefaultThinkingLevel: async () => resolvedDefaultThinkLevel, isGroup, diff --git a/src/auto-reply/reply/get-reply-directives.ts b/src/auto-reply/reply/get-reply-directives.ts index dfc5866401..8444ddb131 100644 --- a/src/auto-reply/reply/get-reply-directives.ts +++ b/src/auto-reply/reply/get-reply-directives.ts @@ -339,20 +339,20 @@ export async function resolveReplyDirectives(params: { }); const defaultActivation = defaultGroupActivation(requireMention); const resolvedThinkLevel = - (directives.thinkLevel as ThinkLevel | undefined) ?? + directives.thinkLevel ?? (sessionEntry?.thinkingLevel as ThinkLevel | undefined) ?? (agentCfg?.thinkingDefault as ThinkLevel | undefined); const resolvedVerboseLevel = - (directives.verboseLevel as VerboseLevel | undefined) ?? + directives.verboseLevel ?? (sessionEntry?.verboseLevel as VerboseLevel | undefined) ?? (agentCfg?.verboseDefault as VerboseLevel | undefined); const resolvedReasoningLevel: ReasoningLevel = - (directives.reasoningLevel as ReasoningLevel | undefined) ?? + directives.reasoningLevel ?? (sessionEntry?.reasoningLevel as ReasoningLevel | undefined) ?? "off"; const resolvedElevatedLevel = elevatedAllowed - ? ((directives.elevatedLevel as ElevatedLevel | undefined) ?? + ? (directives.elevatedLevel ?? (sessionEntry?.elevatedLevel as ElevatedLevel | undefined) ?? (agentCfg?.elevatedDefault as ElevatedLevel | undefined) ?? "on") diff --git a/src/auto-reply/reply/groups.ts b/src/auto-reply/reply/groups.ts index 5264151dbc..67b506e33d 100644 --- a/src/auto-reply/reply/groups.ts +++ b/src/auto-reply/reply/groups.ts @@ -50,7 +50,7 @@ export function resolveGroupRequireMention(params: { } export function defaultGroupActivation(requireMention: boolean): "always" | "mention" { - return requireMention === false ? "always" : "mention"; + return !requireMention ? "always" : "mention"; } export function buildGroupIntro(params: { diff --git a/src/auto-reply/reply/model-selection.ts b/src/auto-reply/reply/model-selection.ts index e970592e0c..c106356d66 100644 --- a/src/auto-reply/reply/model-selection.ts +++ b/src/auto-reply/reply/model-selection.ts @@ -436,7 +436,7 @@ export function resolveModelDirectiveSelection(params: { }); return Object.assign({ candidate }, details); }) - .sort((a, b) => { + .toSorted((a, b) => { if (b.score !== a.score) return b.score - a.score; if (a.isDefault !== b.isDefault) return a.isDefault ? -1 : 1; if (a.variantMatchCount !== b.variantMatchCount) diff --git a/src/auto-reply/reply/session-updates.ts b/src/auto-reply/reply/session-updates.ts index 939e8f0890..2eebf4b20c 100644 --- a/src/auto-reply/reply/session-updates.ts +++ b/src/auto-reply/reply/session-updates.ts @@ -87,7 +87,7 @@ export async function prependSystemEvents(params: { const min = pick("minute"); const sec = pick("second"); const tz = [...parts] - .reverse() + .toReversed() .find((part) => part.type === "timeZoneName") ?.value?.trim(); if (!yyyy || !mm || !dd || !hh || !min || !sec) return undefined; diff --git a/src/auto-reply/reply/session.ts b/src/auto-reply/reply/session.ts index d7f9305a7e..cbf7e2cf2f 100644 --- a/src/auto-reply/reply/session.ts +++ b/src/auto-reply/reply/session.ts @@ -235,10 +235,9 @@ export async function initSessionState(params: { const baseEntry = !isNewSession && freshEntry ? entry : undefined; // Track the originating channel/to for announce routing (subagent announce-back). const lastChannelRaw = (ctx.OriginatingChannel as string | undefined) || baseEntry?.lastChannel; - const lastToRaw = (ctx.OriginatingTo as string | undefined) || ctx.To || baseEntry?.lastTo; - const lastAccountIdRaw = (ctx.AccountId as string | undefined) || baseEntry?.lastAccountId; - const lastThreadIdRaw = - (ctx.MessageThreadId as string | number | undefined) || baseEntry?.lastThreadId; + const lastToRaw = ctx.OriginatingTo || ctx.To || baseEntry?.lastTo; + const lastAccountIdRaw = ctx.AccountId || baseEntry?.lastAccountId; + const lastThreadIdRaw = ctx.MessageThreadId || baseEntry?.lastThreadId; const deliveryFields = normalizeSessionDeliveryFields({ deliveryContext: { channel: lastChannelRaw, diff --git a/src/auto-reply/reply/subagents-utils.ts b/src/auto-reply/reply/subagents-utils.ts index 9afbff9e01..c6d8a4250c 100644 --- a/src/auto-reply/reply/subagents-utils.ts +++ b/src/auto-reply/reply/subagents-utils.ts @@ -42,7 +42,7 @@ export function formatRunStatus(entry: SubagentRunRecord) { } export function sortSubagentRuns(runs: SubagentRunRecord[]) { - return [...runs].sort((a, b) => { + return [...runs].toSorted((a, b) => { const aTime = a.startedAt ?? a.createdAt ?? 0; const bTime = b.startedAt ?? b.createdAt ?? 0; return bTime - aTime; diff --git a/src/browser/cdp.ts b/src/browser/cdp.ts index 2962853846..9e33855940 100644 --- a/src/browser/cdp.ts +++ b/src/browser/cdp.ts @@ -296,7 +296,7 @@ export async function snapshotDom(opts: { awaitPromise: true, returnByValue: true, }); - const value = evaluated.result?.value as unknown; + const value = evaluated.result?.value; if (!value || typeof value !== "object") return { nodes: [] }; const nodes = (value as { nodes?: unknown }).nodes; return { nodes: Array.isArray(nodes) ? (nodes as DomSnapshotNode[]) : [] }; diff --git a/src/browser/extension-relay.ts b/src/browser/extension-relay.ts index 08589eb4d6..ea3d10d2ae 100644 --- a/src/browser/extension-relay.ts +++ b/src/browser/extension-relay.ts @@ -458,7 +458,7 @@ export async function ensureChromeExtensionRelayServer(opts: { if ("error" in parsed && typeof parsed.error === "string" && parsed.error.trim()) { pending.reject(new Error(parsed.error)); } else { - pending.resolve((parsed as ExtensionResponseMessage).result); + pending.resolve(parsed.result); } return; } diff --git a/src/browser/profiles.test.ts b/src/browser/profiles.test.ts index 22850dd501..6f5d3ca8d8 100644 --- a/src/browser/profiles.test.ts +++ b/src/browser/profiles.test.ts @@ -183,18 +183,18 @@ describe("color allocation", () => { it("allocates next unused color from palette", () => { // biome-ignore lint/style/noNonNullAssertion: Test file with known array - const usedColors = new Set([PROFILE_COLORS[0]!.toUpperCase()]); + const usedColors = new Set([PROFILE_COLORS[0].toUpperCase()]); expect(allocateColor(usedColors)).toBe(PROFILE_COLORS[1]); }); it("skips multiple used colors", () => { const usedColors = new Set([ // biome-ignore lint/style/noNonNullAssertion: Test file with known array - PROFILE_COLORS[0]!.toUpperCase(), + PROFILE_COLORS[0].toUpperCase(), // biome-ignore lint/style/noNonNullAssertion: Test file with known array - PROFILE_COLORS[1]!.toUpperCase(), + PROFILE_COLORS[1].toUpperCase(), // biome-ignore lint/style/noNonNullAssertion: Test file with known array - PROFILE_COLORS[2]!.toUpperCase(), + PROFILE_COLORS[2].toUpperCase(), ]); expect(allocateColor(usedColors)).toBe(PROFILE_COLORS[3]); }); diff --git a/src/browser/profiles.ts b/src/browser/profiles.ts index 41c7fe9db2..b45f5dfd8f 100644 --- a/src/browser/profiles.ts +++ b/src/browser/profiles.ts @@ -91,7 +91,7 @@ export function allocateColor(usedColors: Set): string { // All colors used, cycle based on count const index = usedColors.size % PROFILE_COLORS.length; // biome-ignore lint/style/noNonNullAssertion: Array is non-empty constant - return PROFILE_COLORS[index] ?? PROFILE_COLORS[0]!; + return PROFILE_COLORS[index] ?? PROFILE_COLORS[0]; } export function getUsedColors( diff --git a/src/browser/pw-role-snapshot.test.ts b/src/browser/pw-role-snapshot.test.ts index 41cba2dc68..28af3c7ac2 100644 --- a/src/browser/pw-role-snapshot.test.ts +++ b/src/browser/pw-role-snapshot.test.ts @@ -84,7 +84,7 @@ describe("pw-role-snapshot", () => { expect(res.snapshot).toContain('- button "Save"'); expect(res.snapshot).not.toContain("navigation"); expect(res.snapshot).not.toContain("heading"); - expect(Object.keys(res.refs).sort()).toEqual(["e5", "e7"]); + expect(Object.keys(res.refs).toSorted()).toEqual(["e5", "e7"]); expect(res.refs.e5).toMatchObject({ role: "link", name: "Home" }); expect(res.refs.e7).toMatchObject({ role: "button", name: "Save" }); }); diff --git a/src/browser/pw-tools-core.last-file-chooser-arm-wins.test.ts b/src/browser/pw-tools-core.last-file-chooser-arm-wins.test.ts index ffc371b62a..c1cd47650b 100644 --- a/src/browser/pw-tools-core.last-file-chooser-arm-wins.test.ts +++ b/src/browser/pw-tools-core.last-file-chooser-arm-wins.test.ts @@ -55,13 +55,13 @@ describe("pw-tools-core", () => { () => new Promise((r) => { resolve1 = r; - }) as Promise, + }), ) .mockImplementationOnce( () => new Promise((r) => { resolve2 = r; - }) as Promise, + }), ); currentPage = { diff --git a/src/browser/pw-tools-core.responses.ts b/src/browser/pw-tools-core.responses.ts index 4fa7883bd5..6af5623647 100644 --- a/src/browser/pw-tools-core.responses.ts +++ b/src/browser/pw-tools-core.responses.ts @@ -93,7 +93,7 @@ export async function responseBodyViaPlaywright(opts: { bodyText = new TextDecoder("utf-8").decode(buf); } } catch (err) { - throw new Error(`Failed to read response body for "${url}": ${String(err)}`); + throw new Error(`Failed to read response body for "${url}": ${String(err)}`, { cause: err }); } const trimmed = bodyText.length > maxChars ? bodyText.slice(0, maxChars) : bodyText; diff --git a/src/browser/pw-tools-core.snapshot.ts b/src/browser/pw-tools-core.snapshot.ts index 402513c694..f446eaa748 100644 --- a/src/browser/pw-tools-core.snapshot.ts +++ b/src/browser/pw-tools-core.snapshot.ts @@ -200,6 +200,6 @@ export async function pdfViaPlaywright(opts: { }): Promise<{ buffer: Buffer }> { const page = await getPageForTargetId(opts); ensurePageState(page); - const buffer = await (page as Page).pdf({ printBackground: true }); + const buffer = await page.pdf({ printBackground: true }); return { buffer }; } diff --git a/src/browser/pw-tools-core.state.ts b/src/browser/pw-tools-core.state.ts index 1781df0f6b..6841e5f86e 100644 --- a/src/browser/pw-tools-core.state.ts +++ b/src/browser/pw-tools-core.state.ts @@ -136,7 +136,8 @@ export async function setTimezoneViaPlaywright(opts: { } catch (err) { const msg = String(err); if (msg.includes("Timezone override is already in effect")) return; - if (msg.includes("Invalid timezone")) throw new Error(`Invalid timezone ID: ${timezoneId}`); + if (msg.includes("Invalid timezone")) + throw new Error(`Invalid timezone ID: ${timezoneId}`, { cause: err }); throw err; } }); diff --git a/src/browser/routes/agent.act.ts b/src/browser/routes/agent.act.ts index 3eeb29de23..97e9ec3dd6 100644 --- a/src/browser/routes/agent.act.ts +++ b/src/browser/routes/agent.act.ts @@ -207,7 +207,7 @@ export function registerBrowserAgentActRoutes( loadStateRaw === "load" || loadStateRaw === "domcontentloaded" || loadStateRaw === "networkidle" - ? (loadStateRaw as "load" | "domcontentloaded" | "networkidle") + ? loadStateRaw : undefined; const fn = toStringOrEmpty(body.fn) || undefined; const timeoutMs = toNumber(body.timeoutMs) ?? undefined; diff --git a/src/browser/routes/agent.storage.ts b/src/browser/routes/agent.storage.ts index 2f1905c221..384741375e 100644 --- a/src/browser/routes/agent.storage.ts +++ b/src/browser/routes/agent.storage.ts @@ -53,7 +53,7 @@ export function registerBrowserAgentStorageRoutes( secure: toBoolean(cookie.secure) ?? undefined, sameSite: cookie.sameSite === "Lax" || cookie.sameSite === "None" || cookie.sameSite === "Strict" - ? (cookie.sameSite as "Lax" | "None" | "Strict") + ? cookie.sameSite : undefined, }, }); @@ -270,7 +270,7 @@ export function registerBrowserAgentStorageRoutes( const schemeRaw = toStringOrEmpty(body.colorScheme); const colorScheme = schemeRaw === "dark" || schemeRaw === "light" || schemeRaw === "no-preference" - ? (schemeRaw as "dark" | "light" | "no-preference") + ? schemeRaw : schemeRaw === "none" ? null : undefined; diff --git a/src/browser/screenshot.ts b/src/browser/screenshot.ts index 6e6466d2f1..303e6ba14c 100644 --- a/src/browser/screenshot.ts +++ b/src/browser/screenshot.ts @@ -27,7 +27,7 @@ export async function normalizeBrowserScreenshot( const sideGrid = [sideStart, 1800, 1600, 1400, 1200, 1000, 800] .map((v) => Math.min(maxSide, v)) .filter((v, i, arr) => v > 0 && arr.indexOf(v) === i) - .sort((a, b) => b - a); + .toSorted((a, b) => b - a); let smallest: { buffer: Buffer; size: number } | null = null; diff --git a/src/browser/server.agent-contract-form-layout-act-commands.test.ts b/src/browser/server.agent-contract-form-layout-act-commands.test.ts index 273fae5e20..45952a163c 100644 --- a/src/browser/server.agent-contract-form-layout-act-commands.test.ts +++ b/src/browser/server.agent-contract-form-layout-act-commands.test.ts @@ -286,11 +286,11 @@ describe("browser control server", () => { async () => { const base = await startServerAndBase(); - const select = (await postJson(`${base}/act`, { + const select = await postJson(`${base}/act`, { kind: "select", ref: "5", values: ["a", "b"], - })) as { ok: boolean }; + }); expect(select.ok).toBe(true); expect(pwMocks.selectOptionViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, @@ -299,10 +299,10 @@ describe("browser control server", () => { values: ["a", "b"], }); - const fill = (await postJson(`${base}/act`, { + const fill = await postJson(`${base}/act`, { kind: "fill", fields: [{ ref: "6", type: "textbox", value: "hello" }], - })) as { ok: boolean }; + }); expect(fill.ok).toBe(true); expect(pwMocks.fillFormViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, @@ -310,11 +310,11 @@ describe("browser control server", () => { fields: [{ ref: "6", type: "textbox", value: "hello" }], }); - const resize = (await postJson(`${base}/act`, { + const resize = await postJson(`${base}/act`, { kind: "resize", width: 800, height: 600, - })) as { ok: boolean }; + }); expect(resize.ok).toBe(true); expect(pwMocks.resizeViewportViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, @@ -323,10 +323,10 @@ describe("browser control server", () => { height: 600, }); - const wait = (await postJson(`${base}/act`, { + const wait = await postJson(`${base}/act`, { kind: "wait", timeMs: 5, - })) as { ok: boolean }; + }); expect(wait.ok).toBe(true); expect(pwMocks.waitForViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, @@ -336,10 +336,10 @@ describe("browser control server", () => { textGone: undefined, }); - const evalRes = (await postJson(`${base}/act`, { + const evalRes = await postJson(`${base}/act`, { kind: "evaluate", fn: "() => 1", - })) as { ok: boolean; result?: unknown }; + }); expect(evalRes.ok).toBe(true); expect(evalRes.result).toBe("ok"); expect(pwMocks.evaluateViaPlaywright).toHaveBeenCalledWith({ @@ -358,17 +358,17 @@ describe("browser control server", () => { cfgEvaluateEnabled = false; const base = await startServerAndBase(); - const waitRes = (await postJson(`${base}/act`, { + const waitRes = await postJson(`${base}/act`, { kind: "wait", fn: "() => window.ready === true", - })) as { error?: string }; + }); expect(waitRes.error).toContain("browser.evaluateEnabled=false"); expect(pwMocks.waitForViaPlaywright).not.toHaveBeenCalled(); - const res = (await postJson(`${base}/act`, { + const res = await postJson(`${base}/act`, { kind: "evaluate", fn: "() => 1", - })) as { error?: string }; + }); expect(res.error).toContain("browser.evaluateEnabled=false"); expect(pwMocks.evaluateViaPlaywright).not.toHaveBeenCalled(); @@ -441,17 +441,14 @@ describe("browser control server", () => { expect(consoleRes.ok).toBe(true); expect(Array.isArray(consoleRes.messages)).toBe(true); - const pdf = (await postJson(`${base}/pdf`, {})) as { - ok: boolean; - path?: string; - }; + const pdf = await postJson(`${base}/pdf`, {}); expect(pdf.ok).toBe(true); expect(typeof pdf.path).toBe("string"); - const shot = (await postJson(`${base}/screenshot`, { + const shot = await postJson(`${base}/screenshot`, { element: "body", type: "jpeg", - })) as { ok: boolean; path?: string }; + }); expect(shot.ok).toBe(true); expect(typeof shot.path).toBe("string"); }); diff --git a/src/browser/server.agent-contract-snapshot-endpoints.test.ts b/src/browser/server.agent-contract-snapshot-endpoints.test.ts index 06110ea283..51c2b837ab 100644 --- a/src/browser/server.agent-contract-snapshot-endpoints.test.ts +++ b/src/browser/server.agent-contract-snapshot-endpoints.test.ts @@ -306,9 +306,9 @@ describe("browser control server", () => { it("agent contract: navigation + common act commands", async () => { const base = await startServerAndBase(); - const nav = (await postJson(`${base}/navigate`, { + const nav = await postJson(`${base}/navigate`, { url: "https://example.com", - })) as { ok: boolean; targetId?: string }; + }); expect(nav.ok).toBe(true); expect(typeof nav.targetId).toBe("string"); expect(pwMocks.navigateViaPlaywright).toHaveBeenCalledWith({ @@ -317,12 +317,12 @@ describe("browser control server", () => { url: "https://example.com", }); - const click = (await postJson(`${base}/act`, { + const click = await postJson(`${base}/act`, { kind: "click", ref: "1", button: "left", modifiers: ["Shift"], - })) as { ok: boolean }; + }); expect(click.ok).toBe(true); expect(pwMocks.clickViaPlaywright).toHaveBeenNthCalledWith(1, { cdpUrl: cdpBaseUrl, @@ -343,11 +343,11 @@ describe("browser control server", () => { /'selector' is not supported/i, ); - const type = (await postJson(`${base}/act`, { + const type = await postJson(`${base}/act`, { kind: "type", ref: "1", text: "", - })) as { ok: boolean }; + }); expect(type.ok).toBe(true); expect(pwMocks.typeViaPlaywright).toHaveBeenNthCalledWith(1, { cdpUrl: cdpBaseUrl, @@ -358,10 +358,10 @@ describe("browser control server", () => { slowly: false, }); - const press = (await postJson(`${base}/act`, { + const press = await postJson(`${base}/act`, { kind: "press", key: "Enter", - })) as { ok: boolean }; + }); expect(press.ok).toBe(true); expect(pwMocks.pressKeyViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, @@ -369,10 +369,10 @@ describe("browser control server", () => { key: "Enter", }); - const hover = (await postJson(`${base}/act`, { + const hover = await postJson(`${base}/act`, { kind: "hover", ref: "2", - })) as { ok: boolean }; + }); expect(hover.ok).toBe(true); expect(pwMocks.hoverViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, @@ -380,10 +380,10 @@ describe("browser control server", () => { ref: "2", }); - const scroll = (await postJson(`${base}/act`, { + const scroll = await postJson(`${base}/act`, { kind: "scrollIntoView", ref: "2", - })) as { ok: boolean }; + }); expect(scroll.ok).toBe(true); expect(pwMocks.scrollIntoViewViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, @@ -391,11 +391,11 @@ describe("browser control server", () => { ref: "2", }); - const drag = (await postJson(`${base}/act`, { + const drag = await postJson(`${base}/act`, { kind: "drag", startRef: "3", endRef: "4", - })) as { ok: boolean }; + }); expect(drag.ok).toBe(true); expect(pwMocks.dragViaPlaywright).toHaveBeenCalledWith({ cdpUrl: cdpBaseUrl, diff --git a/src/channels/plugins/actions/discord/handle-action.guild-admin.ts b/src/channels/plugins/actions/discord/handle-action.guild-admin.ts index 5a3b13f618..1be557648c 100644 --- a/src/channels/plugins/actions/discord/handle-action.guild-admin.ts +++ b/src/channels/plugins/actions/discord/handle-action.guild-admin.ts @@ -347,7 +347,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: { const deleteMessageDays = readNumberParam(actionParams, "deleteDays", { integer: true, }); - const discordAction = action as "timeout" | "kick" | "ban"; + const discordAction = action; return await handleDiscordAction( { action: discordAction, diff --git a/src/channels/plugins/catalog.ts b/src/channels/plugins/catalog.ts index 57a673e1bf..acef58e359 100644 --- a/src/channels/plugins/catalog.ts +++ b/src/channels/plugins/catalog.ts @@ -268,7 +268,7 @@ export function listChannelPluginCatalogEntries( return Array.from(resolved.values()) .map(({ entry }) => entry) - .sort((a, b) => { + .toSorted((a, b) => { const orderA = a.meta.order ?? 999; const orderB = b.meta.order ?? 999; if (orderA !== orderB) return orderA - orderB; diff --git a/src/channels/plugins/config-helpers.ts b/src/channels/plugins/config-helpers.ts index 8868fd7a6e..80b8ec2542 100644 --- a/src/channels/plugins/config-helpers.ts +++ b/src/channels/plugins/config-helpers.ts @@ -30,7 +30,7 @@ export function setAccountEnabledInConfigSection(params: { } as OpenClawConfig; } - const baseAccounts = (base?.accounts ?? {}) as Record>; + const baseAccounts = base?.accounts ?? {}; const existing = baseAccounts[accountKey] ?? {}; return { ...params.cfg, diff --git a/src/channels/plugins/directory-config.test.ts b/src/channels/plugins/directory-config.test.ts index 8e96e8f989..17b4bca3f6 100644 --- a/src/channels/plugins/directory-config.test.ts +++ b/src/channels/plugins/directory-config.test.ts @@ -30,7 +30,7 @@ describe("directory (config-backed)", () => { query: null, limit: null, }); - expect(peers?.map((e) => e.id).sort()).toEqual([ + expect(peers?.map((e) => e.id).toSorted()).toEqual([ "user:u123", "user:u234", "user:u777", @@ -73,7 +73,7 @@ describe("directory (config-backed)", () => { query: null, limit: null, }); - expect(peers?.map((e) => e.id).sort()).toEqual(["user:111", "user:12345", "user:222"]); + expect(peers?.map((e) => e.id).toSorted()).toEqual(["user:111", "user:12345", "user:222"]); const groups = await listDiscordDirectoryGroupsFromConfig({ cfg, @@ -81,7 +81,7 @@ describe("directory (config-backed)", () => { query: null, limit: null, }); - expect(groups?.map((e) => e.id).sort()).toEqual(["channel:555", "channel:666"]); + expect(groups?.map((e) => e.id).toSorted()).toEqual(["channel:555", "channel:666"]); }); it("lists Telegram peers/groups from config", async () => { @@ -102,7 +102,7 @@ describe("directory (config-backed)", () => { query: null, limit: null, }); - expect(peers?.map((e) => e.id).sort()).toEqual(["123", "456", "@alice", "@bob"]); + expect(peers?.map((e) => e.id).toSorted()).toEqual(["123", "456", "@alice", "@bob"]); const groups = await listTelegramDirectoryGroupsFromConfig({ cfg, diff --git a/src/channels/plugins/index.ts b/src/channels/plugins/index.ts index 6d448df73f..206a7a40f1 100644 --- a/src/channels/plugins/index.ts +++ b/src/channels/plugins/index.ts @@ -28,7 +28,7 @@ function dedupeChannels(channels: ChannelPlugin[]): ChannelPlugin[] { export function listChannelPlugins(): ChannelPlugin[] { const combined = dedupeChannels(listPluginChannels()); - return combined.sort((a, b) => { + return combined.toSorted((a, b) => { const indexA = CHAT_CHANNEL_ORDER.indexOf(a.id as ChatChannelId); const indexB = CHAT_CHANNEL_ORDER.indexOf(b.id as ChatChannelId); const orderA = a.meta.order ?? (indexA === -1 ? 999 : indexA); diff --git a/src/channels/plugins/onboarding/channel-access.ts b/src/channels/plugins/onboarding/channel-access.ts index e22536479a..b01fe0afae 100644 --- a/src/channels/plugins/onboarding/channel-access.ts +++ b/src/channels/plugins/onboarding/channel-access.ts @@ -33,11 +33,11 @@ export async function promptChannelAccessPolicy(params: { options.push({ value: "disabled", label: "Disabled (block all channels)" }); } const initialValue = params.currentPolicy ?? "allowlist"; - return (await params.prompter.select({ + return await params.prompter.select({ message: `${params.label} access`, options, initialValue, - })) as ChannelAccessPolicy; + }); } export async function promptChannelAllowlist(params: { diff --git a/src/channels/plugins/onboarding/helpers.ts b/src/channels/plugins/onboarding/helpers.ts index 8a25d8a616..ea09495024 100644 --- a/src/channels/plugins/onboarding/helpers.ts +++ b/src/channels/plugins/onboarding/helpers.ts @@ -4,7 +4,7 @@ import type { PromptAccountId, PromptAccountIdParams } from "../onboarding-types export const promptAccountId: PromptAccountId = async (params: PromptAccountIdParams) => { const existingIds = params.listAccountIds(params.cfg); const initial = params.currentId?.trim() || params.defaultAccountId || DEFAULT_ACCOUNT_ID; - const choice = (await params.prompter.select({ + const choice = await params.prompter.select({ message: `${params.label} account`, options: [ ...existingIds.map((id) => ({ @@ -14,7 +14,7 @@ export const promptAccountId: PromptAccountId = async (params: PromptAccountIdPa { value: "__new__", label: "Add a new account" }, ], initialValue: initial, - })) as string; + }); if (choice !== "__new__") return normalizeAccountId(choice); diff --git a/src/channels/plugins/onboarding/whatsapp.ts b/src/channels/plugins/onboarding/whatsapp.ts index eb7b788e28..263fdeafaa 100644 --- a/src/channels/plugins/onboarding/whatsapp.ts +++ b/src/channels/plugins/onboarding/whatsapp.ts @@ -107,13 +107,13 @@ async function promptWhatsAppAllowFrom( "WhatsApp DM access", ); - const phoneMode = (await prompter.select({ + const phoneMode = await prompter.select({ message: "WhatsApp phone setup", options: [ { value: "personal", label: "This is my personal phone number" }, { value: "separate", label: "Separate phone just for OpenClaw" }, ], - })) as "personal" | "separate"; + }); if (phoneMode === "personal") { await prompter.note( @@ -187,13 +187,13 @@ async function promptWhatsAppAllowFrom( { value: "list", label: "Set allowFrom to specific numbers" }, ] as const); - const mode = (await prompter.select({ + const mode = await prompter.select({ message: "WhatsApp allowFrom (optional pre-allowlist)", options: allowOptions.map((opt) => ({ value: opt.value, label: opt.label, })), - })) as (typeof allowOptions)[number]["value"]; + }); if (mode === "keep") { // Keep allowFrom as-is. diff --git a/src/channels/plugins/whatsapp-heartbeat.ts b/src/channels/plugins/whatsapp-heartbeat.ts index 9cb7cae5e3..ae1d7b5d49 100644 --- a/src/channels/plugins/whatsapp-heartbeat.ts +++ b/src/channels/plugins/whatsapp-heartbeat.ts @@ -27,7 +27,7 @@ function getSessionRecipients(cfg: OpenClawConfig) { updatedAt: entry?.updatedAt ?? 0, })) .filter(({ to }) => to.length > 1) - .sort((a, b) => b.updatedAt - a.updatedAt); + .toSorted((a, b) => b.updatedAt - a.updatedAt); // Dedupe while preserving recency ordering. const seen = new Set(); diff --git a/src/channels/registry.ts b/src/channels/registry.ts index 5ec118aba5..e36c935904 100644 --- a/src/channels/registry.ts +++ b/src/channels/registry.ts @@ -127,9 +127,7 @@ export function normalizeChatChannelId(raw?: string | null): ChatChannelId | nul const normalized = normalizeChannelKey(raw); if (!normalized) return null; const resolved = CHAT_CHANNEL_ALIASES[normalized] ?? normalized; - return CHAT_CHANNEL_ORDER.includes(resolved as ChatChannelId) - ? (resolved as ChatChannelId) - : null; + return CHAT_CHANNEL_ORDER.includes(resolved) ? resolved : null; } // Channel docking: prefer this helper in shared code. Importing from @@ -154,7 +152,7 @@ export function normalizeAnyChannelId(raw?: string | null): ChannelId | null { if (id && id === key) return true; return (entry.plugin.meta.aliases ?? []).some((alias) => alias.trim().toLowerCase() === key); }); - return (hit?.plugin.id as ChannelId | undefined) ?? null; + return hit?.plugin.id ?? null; } export function formatChannelPrimerLine(meta: ChatChannelMeta): string { diff --git a/src/cli/cli-utils.ts b/src/cli/cli-utils.ts index fe67d22196..545cb42237 100644 --- a/src/cli/cli-utils.ts +++ b/src/cli/cli-utils.ts @@ -55,7 +55,7 @@ export function resolveOptionFromCommand( ): T | undefined { let current: Command | null | undefined = command; while (current) { - const opts = (current.opts?.() ?? {}) as Record; + const opts = current.opts?.() ?? {}; if (opts[key] !== undefined) return opts[key]; current = current.parent ?? undefined; } diff --git a/src/cli/config-cli.ts b/src/cli/config-cli.ts index 6fa4951a8a..c613bcd6f3 100644 --- a/src/cli/config-cli.ts +++ b/src/cli/config-cli.ts @@ -59,7 +59,7 @@ function parseValue(raw: string, opts: { json?: boolean }): unknown { try { return JSON5.parse(trimmed); } catch (err) { - throw new Error(`Failed to parse JSON5 value: ${String(err)}`); + throw new Error(`Failed to parse JSON5 value: ${String(err)}`, { cause: err }); } } diff --git a/src/cli/devices-cli.ts b/src/cli/devices-cli.ts index 900f7a8860..97ce97695a 100644 --- a/src/cli/devices-cli.ts +++ b/src/cli/devices-cli.ts @@ -101,7 +101,7 @@ function formatTokenSummary(tokens: DeviceTokenSummary[] | undefined) { if (!tokens || tokens.length === 0) return "none"; const parts = tokens .map((t) => `${t.role}${t.revokedAtMs ? " (revoked)" : ""}`) - .sort((a, b) => a.localeCompare(b)); + .toSorted((a, b) => a.localeCompare(b)); return parts.join(", "); } diff --git a/src/cli/exec-approvals-cli.ts b/src/cli/exec-approvals-cli.ts index 13cc615b67..c27f9b2c3e 100644 --- a/src/cli/exec-approvals-cli.ts +++ b/src/cli/exec-approvals-cli.ts @@ -295,7 +295,7 @@ export function registerExecApprovalsCli(program: Command) { const raw = opts.stdin ? await readStdin() : await fs.readFile(String(opts.file), "utf8"); let file: ExecApprovalsFile; try { - file = JSON5.parse(raw) as ExecApprovalsFile; + file = JSON5.parse(raw); } catch (err) { defaultRuntime.error(`Failed to parse approvals JSON: ${String(err)}`); defaultRuntime.exit(1); diff --git a/src/cli/gateway-cli/register.ts b/src/cli/gateway-cli/register.ts index 0e60189348..f6f08d9128 100644 --- a/src/cli/gateway-cli/register.ts +++ b/src/cli/gateway-cli/register.ts @@ -288,7 +288,7 @@ export function registerGatewayCli(program: Command) { async () => await discoverGatewayBeacons({ timeoutMs, wideAreaDomain }), ); - const deduped = dedupeBeacons(beacons).sort((a, b) => + const deduped = dedupeBeacons(beacons).toSorted((a, b) => String(a.displayName || a.instanceName).localeCompare( String(b.displayName || b.instanceName), ), diff --git a/src/cli/models-cli.test.ts b/src/cli/models-cli.test.ts index 2a1759b3fb..ddc6db0e21 100644 --- a/src/cli/models-cli.test.ts +++ b/src/cli/models-cli.test.ts @@ -4,9 +4,8 @@ const githubCopilotLoginCommand = vi.fn(); const modelsStatusCommand = vi.fn().mockResolvedValue(undefined); vi.mock("../commands/models.js", async () => { - const actual = (await vi.importActual( - "../commands/models.js", - )) as typeof import("../commands/models.js"); + const actual = + await vi.importActual("../commands/models.js"); return { ...actual, diff --git a/src/cli/nodes-cli/format.ts b/src/cli/nodes-cli/format.ts index 5817db2f96..236a78c2c9 100644 --- a/src/cli/nodes-cli/format.ts +++ b/src/cli/nodes-cli/format.ts @@ -28,7 +28,7 @@ export function formatPermissions(raw: unknown) { const entries = Object.entries(raw as Record) .map(([key, value]) => [String(key).trim(), value === true] as const) .filter(([key]) => key.length > 0) - .sort((a, b) => a[0].localeCompare(b[0])); + .toSorted((a, b) => a[0].localeCompare(b[0])); if (entries.length === 0) return null; const parts = entries.map(([key, granted]) => `${key}=${granted ? "yes" : "no"}`); return `[${parts.join(", ")}]`; diff --git a/src/cli/nodes-cli/register.camera.ts b/src/cli/nodes-cli/register.camera.ts index 4d9e56cf0b..b5fb1b8104 100644 --- a/src/cli/nodes-cli/register.camera.ts +++ b/src/cli/nodes-cli/register.camera.ts @@ -34,12 +34,12 @@ export function registerNodesCameraCommands(nodes: Command) { .action(async (opts: NodesRpcOpts) => { await runNodesCommand("camera list", async () => { const nodeId = await resolveNodeId(opts, String(opts.node ?? "")); - const raw = (await callGatewayCli("node.invoke", opts, { + const raw = await callGatewayCli("node.invoke", opts, { nodeId, command: "camera.list", params: {}, idempotencyKey: randomIdempotencyKey(), - })) as unknown; + }); const res = typeof raw === "object" && raw !== null ? (raw as { payload?: unknown }) : {}; const payload = @@ -144,7 +144,7 @@ export function registerNodesCameraCommands(nodes: Command) { invokeParams.timeoutMs = timeoutMs; } - const raw = (await callGatewayCli("node.invoke", opts, invokeParams)) as unknown; + const raw = await callGatewayCli("node.invoke", opts, invokeParams); const res = typeof raw === "object" && raw !== null ? (raw as { payload?: unknown }) : {}; const payload = parseCameraSnapPayload(res.payload); @@ -213,7 +213,7 @@ export function registerNodesCameraCommands(nodes: Command) { invokeParams.timeoutMs = timeoutMs; } - const raw = (await callGatewayCli("node.invoke", opts, invokeParams)) as unknown; + const raw = await callGatewayCli("node.invoke", opts, invokeParams); const res = typeof raw === "object" && raw !== null ? (raw as { payload?: unknown }) : {}; const payload = parseCameraClipPayload(res.payload); const filePath = cameraTempPath({ diff --git a/src/cli/nodes-cli/register.canvas.ts b/src/cli/nodes-cli/register.canvas.ts index 13d4a873d8..eb6ec2a126 100644 --- a/src/cli/nodes-cli/register.canvas.ts +++ b/src/cli/nodes-cli/register.canvas.ts @@ -72,7 +72,7 @@ export function registerNodesCanvasCommands(nodes: Command) { invokeParams.timeoutMs = timeoutMs; } - const raw = (await callGatewayCli("node.invoke", opts, invokeParams)) as unknown; + const raw = await callGatewayCli("node.invoke", opts, invokeParams); const res = typeof raw === "object" && raw !== null ? (raw as { payload?: unknown }) : {}; const payload = parseCanvasSnapshotPayload(res.payload); const filePath = canvasSnapshotTempPath({ diff --git a/src/cli/nodes-cli/register.invoke.ts b/src/cli/nodes-cli/register.invoke.ts index a5dc01df09..013610d6c8 100644 --- a/src/cli/nodes-cli/register.invoke.ts +++ b/src/cli/nodes-cli/register.invoke.ts @@ -112,7 +112,7 @@ function resolveExecDefaults( async function resolveNodePlatform(opts: NodesRpcOpts, nodeId: string): Promise { try { - const res = (await callGatewayCli("node.list", opts, {})) as unknown; + const res = await callGatewayCli("node.list", opts, {}); const nodes = parseNodeList(res); const match = nodes.find((node) => node.nodeId === nodeId); return typeof match?.platform === "string" ? match.platform : null; @@ -324,7 +324,7 @@ export function registerNodesInvokeCommands(nodes: Command) { invokeParams.timeoutMs = invokeTimeout; } - const result = (await callGatewayCli("node.invoke", opts, invokeParams)) as unknown; + const result = await callGatewayCli("node.invoke", opts, invokeParams); if (opts.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/nodes-cli/register.location.ts b/src/cli/nodes-cli/register.location.ts index f7cdafd5be..c4dd02356e 100644 --- a/src/cli/nodes-cli/register.location.ts +++ b/src/cli/nodes-cli/register.location.ts @@ -53,7 +53,7 @@ export function registerNodesLocationCommands(nodes: Command) { invokeParams.timeoutMs = invokeTimeoutMs; } - const raw = (await callGatewayCli("node.invoke", opts, invokeParams)) as unknown; + const raw = await callGatewayCli("node.invoke", opts, invokeParams); const res = typeof raw === "object" && raw !== null ? (raw as { payload?: unknown }) : {}; const payload = res.payload && typeof res.payload === "object" diff --git a/src/cli/nodes-cli/register.pairing.ts b/src/cli/nodes-cli/register.pairing.ts index 11b4f68f57..1746ef944d 100644 --- a/src/cli/nodes-cli/register.pairing.ts +++ b/src/cli/nodes-cli/register.pairing.ts @@ -13,7 +13,7 @@ export function registerNodesPairingCommands(nodes: Command) { .description("List pending pairing requests") .action(async (opts: NodesRpcOpts) => { await runNodesCommand("pending", async () => { - const result = (await callGatewayCli("node.pair.list", opts, {})) as unknown; + const result = await callGatewayCli("node.pair.list", opts, {}); const { pending } = parsePairingList(result); if (opts.json) { defaultRuntime.log(JSON.stringify(pending, null, 2)); diff --git a/src/cli/nodes-cli/register.screen.ts b/src/cli/nodes-cli/register.screen.ts index 501e00faec..7dca7dd1c6 100644 --- a/src/cli/nodes-cli/register.screen.ts +++ b/src/cli/nodes-cli/register.screen.ts @@ -54,7 +54,7 @@ export function registerNodesScreenCommands(nodes: Command) { invokeParams.timeoutMs = timeoutMs; } - const raw = (await callGatewayCli("node.invoke", opts, invokeParams)) as unknown; + const raw = await callGatewayCli("node.invoke", opts, invokeParams); const res = typeof raw === "object" && raw !== null ? (raw as { payload?: unknown }) : {}; const parsed = parseScreenRecordPayload(res.payload); const filePath = opts.out ?? screenRecordTempPath({ ext: parsed.format || "mp4" }); diff --git a/src/cli/nodes-cli/register.status.ts b/src/cli/nodes-cli/register.status.ts index 6f916f23b7..9c6a6dab99 100644 --- a/src/cli/nodes-cli/register.status.ts +++ b/src/cli/nodes-cli/register.status.ts @@ -86,7 +86,7 @@ export function registerNodesStatusCommands(nodes: Command) { await runNodesCommand("status", async () => { const connectedOnly = Boolean(opts.connected); const sinceMs = parseSinceMs(opts.lastConnected, "Invalid --last-connected"); - const result = (await callGatewayCli("node.list", opts, {})) as unknown; + const result = await callGatewayCli("node.list", opts, {}); const obj = typeof result === "object" && result !== null ? (result as Record) @@ -146,7 +146,7 @@ export function registerNodesStatusCommands(nodes: Command) { pathEnv ? `path: ${pathEnv}` : null, ].filter(Boolean) as string[]; const caps = Array.isArray(n.caps) - ? n.caps.map(String).filter(Boolean).sort().join(", ") + ? n.caps.map(String).filter(Boolean).toSorted().join(", ") : "?"; const paired = n.paired ? ok("paired") : warn("unpaired"); const connected = n.connected ? ok("connected") : muted("disconnected"); @@ -191,9 +191,9 @@ export function registerNodesStatusCommands(nodes: Command) { .action(async (opts: NodesRpcOpts) => { await runNodesCommand("describe", async () => { const nodeId = await resolveNodeId(opts, String(opts.node ?? "")); - const result = (await callGatewayCli("node.describe", opts, { + const result = await callGatewayCli("node.describe", opts, { nodeId, - })) as unknown; + }); if (opts.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -206,9 +206,11 @@ export function registerNodesStatusCommands(nodes: Command) { const displayName = typeof obj.displayName === "string" ? obj.displayName : nodeId; const connected = Boolean(obj.connected); const paired = Boolean(obj.paired); - const caps = Array.isArray(obj.caps) ? obj.caps.map(String).filter(Boolean).sort() : null; + const caps = Array.isArray(obj.caps) + ? obj.caps.map(String).filter(Boolean).toSorted() + : null; const commands = Array.isArray(obj.commands) - ? obj.commands.map(String).filter(Boolean).sort() + ? obj.commands.map(String).filter(Boolean).toSorted() : []; const perms = formatPermissions(obj.permissions); const family = typeof obj.deviceFamily === "string" ? obj.deviceFamily : null; @@ -274,7 +276,7 @@ export function registerNodesStatusCommands(nodes: Command) { await runNodesCommand("list", async () => { const connectedOnly = Boolean(opts.connected); const sinceMs = parseSinceMs(opts.lastConnected, "Invalid --last-connected"); - const result = (await callGatewayCli("node.pair.list", opts, {})) as unknown; + const result = await callGatewayCli("node.pair.list", opts, {}); const { pending, paired } = parsePairingList(result); const { heading, muted, warn } = getNodesTheme(); const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1); diff --git a/src/cli/nodes-cli/rpc.ts b/src/cli/nodes-cli/rpc.ts index d6b1d30db9..d2807bc482 100644 --- a/src/cli/nodes-cli/rpc.ts +++ b/src/cli/nodes-cli/rpc.ts @@ -61,10 +61,10 @@ export async function resolveNodeId(opts: NodesRpcOpts, query: string) { let nodes: NodeListNode[] = []; try { - const res = (await callGatewayCli("node.list", opts, {})) as unknown; + const res = await callGatewayCli("node.list", opts, {}); nodes = parseNodeList(res); } catch { - const res = (await callGatewayCli("node.pair.list", opts, {})) as unknown; + const res = await callGatewayCli("node.pair.list", opts, {}); const { paired } = parsePairingList(res); nodes = paired.map((n) => ({ nodeId: n.nodeId, diff --git a/src/cli/pairing-cli.ts b/src/cli/pairing-cli.ts index 176dd936b3..72cec23078 100644 --- a/src/cli/pairing-cli.ts +++ b/src/cli/pairing-cli.ts @@ -29,10 +29,10 @@ function parseChannel(raw: unknown, channels: PairingChannel[]): PairingChannel const normalized = normalizeChannelId(value); if (normalized) { - if (!channels.includes(normalized as PairingChannel)) { + if (!channels.includes(normalized)) { throw new Error(`Channel ${normalized} does not support pairing`); } - return normalized as PairingChannel; + return normalized; } // Allow extension channels: validate format but don't require registry diff --git a/src/cli/ports.ts b/src/cli/ports.ts index 5384c056b0..19b5689ae3 100644 --- a/src/cli/ports.ts +++ b/src/cli/ports.ts @@ -40,7 +40,7 @@ export function listPortListeners(port: number): PortProcess[] { const status = (err as { status?: number }).status; const code = (err as { code?: string }).code; if (code === "ENOENT") { - throw new Error("lsof not found; required for --force"); + throw new Error("lsof not found; required for --force", { cause: err }); } if (status === 1) return []; // no listeners throw err instanceof Error ? err : new Error(String(err)); @@ -55,6 +55,7 @@ export function forceFreePort(port: number): PortProcess[] { } catch (err) { throw new Error( `failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`, + { cause: err }, ); } } @@ -68,6 +69,7 @@ function killPids(listeners: PortProcess[], signal: NodeJS.Signals) { } catch (err) { throw new Error( `failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`, + { cause: err }, ); } } diff --git a/src/cli/program.nodes-media.test.ts b/src/cli/program.nodes-media.test.ts index 703f1c9471..adaee5442c 100644 --- a/src/cli/program.nodes-media.test.ts +++ b/src/cli/program.nodes-media.test.ts @@ -96,7 +96,7 @@ describe("cli program (nodes media)", () => { const facings = invokeCalls .map((call) => (call.params?.params as { facing?: string } | undefined)?.facing) .filter(Boolean) - .sort((a, b) => a.localeCompare(b)); + .toSorted((a, b) => a.localeCompare(b)); expect(facings).toEqual(["back", "front"]); const out = String(runtime.log.mock.calls[0]?.[0] ?? ""); diff --git a/src/cli/security-cli.ts b/src/cli/security-cli.ts index dc502b9318..6096892a55 100644 --- a/src/cli/security-cli.ts +++ b/src/cli/security-cli.ts @@ -77,7 +77,7 @@ export function registerSecurityCli(program: Command) { } else if ( fixResult.errors.length === 0 && fixResult.changes.length === 0 && - fixResult.actions.every((a) => a.ok === false) + fixResult.actions.every((a) => !a.ok) ) { lines.push(muted("Fixes: no changes applied")); } else { diff --git a/src/cli/update-cli.ts b/src/cli/update-cli.ts index 320bde3829..3fcba914df 100644 --- a/src/cli/update-cli.ts +++ b/src/cli/update-cli.ts @@ -657,7 +657,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise { message: stylePromptMessage(message), initialValue: false, }); - if (isCancel(ok) || ok === false) { + if (isCancel(ok) || !ok) { if (!opts.json) { defaultRuntime.log(theme.muted("Update cancelled.")); } @@ -1082,7 +1082,7 @@ export async function updateWizardCommand(opts: UpdateWizardOptions = {}): Promi ), initialValue: true, }); - if (isCancel(ok) || ok === false) { + if (isCancel(ok) || !ok) { defaultRuntime.log(theme.muted("Update cancelled.")); defaultRuntime.exit(0); return; diff --git a/src/commands/agent.test.ts b/src/commands/agent.test.ts index d7ace16648..31e68d686a 100644 --- a/src/commands/agent.test.ts +++ b/src/commands/agent.test.ts @@ -150,7 +150,7 @@ describe("agentCommand", () => { if (evt.stream !== "assistant") return; assistantEvents.push({ runId: evt.runId, - text: typeof evt.data?.text === "string" ? (evt.data.text as string) : undefined, + text: typeof evt.data?.text === "string" ? evt.data.text : undefined, }); }); diff --git a/src/commands/agents.commands.list.ts b/src/commands/agents.commands.list.ts index adb40fe4e3..084e5cb516 100644 --- a/src/commands/agents.commands.list.ts +++ b/src/commands/agents.commands.list.ts @@ -77,7 +77,7 @@ export async function agentsListCommand( for (const binding of cfg.bindings ?? []) { const agentId = normalizeAgentId(binding.agentId); const list = bindingMap.get(agentId) ?? []; - list.push(binding as AgentBinding); + list.push(binding); bindingMap.set(agentId, list); } diff --git a/src/commands/auth-choice-prompt.ts b/src/commands/auth-choice-prompt.ts index 275fa72c9f..fcb5554cac 100644 --- a/src/commands/auth-choice-prompt.ts +++ b/src/commands/auth-choice-prompt.ts @@ -42,10 +42,10 @@ export async function promptAuthChoiceGrouped(params: { continue; } - const methodSelection = (await params.prompter.select({ + const methodSelection = await params.prompter.select({ message: `${group.label} auth method`, options: [...group.options, { value: BACK_VALUE, label: "Back" }], - })) as string; + }); if (methodSelection === BACK_VALUE) { continue; diff --git a/src/commands/channels/add.ts b/src/commands/channels/add.ts index 274df1775d..39c0842318 100644 --- a/src/commands/channels/add.ts +++ b/src/commands/channels/add.ts @@ -108,7 +108,7 @@ export async function channelsAddCommand( if (wantsNames) { for (const channel of selection) { const accountId = accountIds[channel] ?? DEFAULT_ACCOUNT_ID; - const plugin = getChannelPlugin(channel as ChannelId); + const plugin = getChannelPlugin(channel); const account = plugin?.config.resolveAccount(nextConfig, accountId) as | { name?: string } | undefined; diff --git a/src/commands/channels/remove.ts b/src/commands/channels/remove.ts index 2999415034..e0f61c699d 100644 --- a/src/commands/channels/remove.ts +++ b/src/commands/channels/remove.ts @@ -38,25 +38,25 @@ export async function channelsRemoveCommand( if (useWizard && prompter) { await prompter.intro("Remove channel account"); - const selectedChannel = (await prompter.select({ + const selectedChannel = await prompter.select({ message: "Channel", options: listChannelPlugins().map((plugin) => ({ value: plugin.id, label: plugin.meta.label, })), - })) as ChatChannel; + }); channel = selectedChannel; accountId = await (async () => { const ids = listAccountIds(cfg, selectedChannel); - const choice = (await prompter.select({ + const choice = await prompter.select({ message: "Account", options: ids.map((id) => ({ value: id, label: id === DEFAULT_ACCOUNT_ID ? "default (primary)" : id, })), initialValue: ids[0] ?? DEFAULT_ACCOUNT_ID, - })) as string; + }); return normalizeAccountId(choice); })(); diff --git a/src/commands/channels/status.ts b/src/commands/channels/status.ts index dd89c34c03..95e9ef134b 100644 --- a/src/commands/channels/status.ts +++ b/src/commands/channels/status.ts @@ -130,7 +130,7 @@ export function formatGatewayChannelsStatusLines(payload: Record 0) { - lines.push(...accountLines(plugin.id as ChatChannel, accounts)); + lines.push(...accountLines(plugin.id, accounts)); } } @@ -217,7 +217,7 @@ async function formatConfigChannelsStatusLines( snapshots.push(snapshot); } if (snapshots.length > 0) { - lines.push(...accountLines(plugin.id as ChatChannel, snapshots)); + lines.push(...accountLines(plugin.id, snapshots)); } } diff --git a/src/commands/configure.channels.ts b/src/commands/configure.channels.ts index 559dd0faf9..5a7ffb01a2 100644 --- a/src/commands/configure.channels.ts +++ b/src/commands/configure.channels.ts @@ -45,7 +45,7 @@ export async function removeChannelConfigWizard( ], }), runtime, - ) as string; + ); if (channel === "done") return next; diff --git a/src/commands/configure.daemon.ts b/src/commands/configure.daemon.ts index c0431c9f10..1f47c6149f 100644 --- a/src/commands/configure.daemon.ts +++ b/src/commands/configure.daemon.ts @@ -123,7 +123,7 @@ export async function maybeInstallDaemon(params: { await ensureSystemdUserLingerInteractive({ runtime: params.runtime, prompter: { - confirm: async (p) => guardCancel(await confirm(p), params.runtime) === true, + confirm: async (p) => guardCancel(await confirm(p), params.runtime), note, }, reason: diff --git a/src/commands/configure.gateway.ts b/src/commands/configure.gateway.ts index 2a1e728574..a0fc2f4c81 100644 --- a/src/commands/configure.gateway.ts +++ b/src/commands/configure.gateway.ts @@ -59,7 +59,7 @@ export async function promptGatewayConfig( ], }), runtime, - ) as "auto" | "lan" | "loopback" | "custom" | "tailnet"; + ); let customBindHost: string | undefined; if (bind === "custom") { @@ -117,7 +117,7 @@ export async function promptGatewayConfig( ], }), runtime, - ) as "off" | "serve" | "funnel"; + ); // Detect Tailscale binary before proceeding with serve/funnel setup. if (tailscaleMode !== "off") { diff --git a/src/commands/configure.wizard.ts b/src/commands/configure.wizard.ts index 505fb77606..2788bc034f 100644 --- a/src/commands/configure.wizard.ts +++ b/src/commands/configure.wizard.ts @@ -240,7 +240,7 @@ export async function runConfigureWizard( ], }), runtime, - ) as "local" | "remote"; + ); if (mode === "remote") { let remoteConfig = await promptRemoteGatewayConfig(baseConfig, prompter); diff --git a/src/commands/doctor-config-flow.ts b/src/commands/doctor-config-flow.ts index 6944752677..d453f1a2bd 100644 --- a/src/commands/doctor-config-flow.ts +++ b/src/commands/doctor-config-flow.ts @@ -74,7 +74,7 @@ function stripUnknownConfigKeys(config: OpenClawConfig): { return { config, removed: [] }; } - const next = structuredClone(config) as OpenClawConfig; + const next = structuredClone(config); const removed: string[] = []; for (const issue of parsed.error.issues) { if (!isUnrecognizedKeysIssue(issue)) continue; @@ -186,7 +186,7 @@ export async function loadAndMaybeMigrateDoctorConfig(params: { let snapshot = await readConfigFileSnapshot(); const baseCfg = snapshot.config ?? {}; let cfg: OpenClawConfig = baseCfg; - let candidate = structuredClone(baseCfg) as OpenClawConfig; + let candidate = structuredClone(baseCfg); let pendingChanges = false; let shouldWriteConfig = false; const fixHints: string[] = []; diff --git a/src/commands/doctor-prompter.ts b/src/commands/doctor-prompter.ts index fb4b877c02..b0f037edf1 100644 --- a/src/commands/doctor-prompter.ts +++ b/src/commands/doctor-prompter.ts @@ -40,14 +40,12 @@ export function createDoctorPrompter(params: { if (nonInteractive) return false; if (shouldRepair) return true; if (!canPrompt) return Boolean(p.initialValue ?? false); - return ( - guardCancel( - await confirm({ - ...p, - message: stylePromptMessage(p.message), - }), - params.runtime, - ) === true + return guardCancel( + await confirm({ + ...p, + message: stylePromptMessage(p.message), + }), + params.runtime, ); }; @@ -62,14 +60,12 @@ export function createDoctorPrompter(params: { if (shouldRepair && shouldForce) return true; if (shouldRepair && !shouldForce) return false; if (!canPrompt) return Boolean(p.initialValue ?? false); - return ( - guardCancel( - await confirm({ - ...p, - message: stylePromptMessage(p.message), - }), - params.runtime, - ) === true + return guardCancel( + await confirm({ + ...p, + message: stylePromptMessage(p.message), + }), + params.runtime, ); }, confirmSkipInNonInteractive: async (p) => { diff --git a/src/commands/doctor-state-integrity.ts b/src/commands/doctor-state-integrity.ts index fa43a14f87..4fad602b70 100644 --- a/src/commands/doctor-state-integrity.ts +++ b/src/commands/doctor-state-integrity.ts @@ -302,7 +302,7 @@ export async function noteStateIntegrity( if (entries.length > 0) { const recent = entries .slice() - .sort((a, b) => { + .toSorted((a, b) => { const aUpdated = typeof a[1].updatedAt === "number" ? a[1].updatedAt : 0; const bUpdated = typeof b[1].updatedAt === "number" ? b[1].updatedAt : 0; return bUpdated - aUpdated; diff --git a/src/commands/health.ts b/src/commands/health.ts index ca78182088..d34637482e 100644 --- a/src/commands/health.ts +++ b/src/commands/health.ts @@ -135,7 +135,7 @@ const buildSessionSummary = (storePath: string) => { const sessions = Object.entries(store) .filter(([key]) => key !== "global" && key !== "unknown") .map(([key, entry]) => ({ key, updatedAt: entry?.updatedAt ?? 0 })) - .sort((a, b) => b.updatedAt - a.updatedAt); + .toSorted((a, b) => b.updatedAt - a.updatedAt); const recent = sessions.slice(0, 5).map((s) => ({ key: s.key, updatedAt: s.updatedAt || null, diff --git a/src/commands/message-format.ts b/src/commands/message-format.ts index e22baa85ff..ba9af32bc2 100644 --- a/src/commands/message-format.ts +++ b/src/commands/message-format.ts @@ -185,7 +185,7 @@ function renderReactions(payload: unknown, opts: FormatOpts): string[] | null { const emoji = (typeof emojiObj?.raw === "string" && emojiObj.raw) || (typeof entry.name === "string" && entry.name) || - (typeof entry.emoji === "string" && (entry.emoji as string)) || + (typeof entry.emoji === "string" && entry.emoji) || ""; const count = typeof entry.count === "number" ? String(entry.count) : ""; const userList = Array.isArray(entry.users) diff --git a/src/commands/model-picker.ts b/src/commands/model-picker.ts index 35ea8f73aa..b3b620bec4 100644 --- a/src/commands/model-picker.ts +++ b/src/commands/model-picker.ts @@ -140,7 +140,7 @@ export async function promptDefaultModel( }); } - const providers = Array.from(new Set(models.map((entry) => entry.provider))).sort((a, b) => + const providers = Array.from(new Set(models.map((entry) => entry.provider))).toSorted((a, b) => a.localeCompare(b), ); @@ -183,7 +183,7 @@ export async function promptDefaultModel( return value; }; - const options: WizardSelectOption[] = []; + const options: WizardSelectOption[] = []; if (allowKeep) { options.push({ value: KEEP_VALUE, @@ -325,7 +325,7 @@ export async function promptModelAllowlist(params: { return value; }; - const options: WizardSelectOption[] = []; + const options: WizardSelectOption[] = []; const seen = new Set(); const addModelOption = (entry: { provider: string; diff --git a/src/commands/models/list.list-command.ts b/src/commands/models/list.list-command.ts index f65968c409..04bb1f9c85 100644 --- a/src/commands/models/list.list-command.ts +++ b/src/commands/models/list.list-command.ts @@ -64,7 +64,7 @@ export async function modelsListCommand( }; if (opts.all) { - const sorted = [...models].sort((a, b) => { + const sorted = [...models].toSorted((a, b) => { const p = a.provider.localeCompare(b.provider); if (p !== 0) return p; return a.id.localeCompare(b.id); diff --git a/src/commands/models/list.probe.ts b/src/commands/models/list.probe.ts index db2d79bcf1..1dce145345 100644 --- a/src/commands/models/list.probe.ts +++ b/src/commands/models/list.probe.ts @@ -445,7 +445,7 @@ export function groupProbeResults(results: AuthProbeResult[]): Map { + return results.slice().toSorted((a, b) => { const provider = a.provider.localeCompare(b.provider); if (provider !== 0) return provider; const aLabel = a.label || a.profileId || ""; diff --git a/src/commands/models/list.registry.ts b/src/commands/models/list.registry.ts index 904f4f9749..841202aee1 100644 --- a/src/commands/models/list.registry.ts +++ b/src/commands/models/list.registry.ts @@ -43,8 +43,8 @@ export async function loadModelRegistry(cfg: OpenClawConfig) { const agentDir = resolveOpenClawAgentDir(); const authStorage = discoverAuthStorage(agentDir); const registry = discoverModels(authStorage, agentDir); - const models = registry.getAll() as Model[]; - const availableModels = registry.getAvailable() as Model[]; + const models = registry.getAll(); + const availableModels = registry.getAvailable(); const availableKeys = new Set(availableModels.map((model) => modelKey(model.provider, model.id))); return { registry, models, availableKeys }; } diff --git a/src/commands/models/list.status-command.ts b/src/commands/models/list.status-command.ts index 879d37f424..c389f6ebf5 100644 --- a/src/commands/models/list.status-command.ts +++ b/src/commands/models/list.status-command.ts @@ -170,7 +170,7 @@ export async function modelsStatusCommand( ) .map((p) => p.trim()) .filter(Boolean) - .sort((a, b) => a.localeCompare(b)); + .toSorted((a, b) => a.localeCompare(b)); const applied = getShellEnvAppliedKeys(); const shellFallbackEnabled = @@ -185,7 +185,7 @@ export async function modelsStatusCommand( const providerAuthMap = new Map(providerAuth.map((entry) => [entry.provider, entry])); const missingProvidersInUse = Array.from(providersInUse) .filter((provider) => !providerAuthMap.has(provider)) - .sort((a, b) => a.localeCompare(b)); + .toSorted((a, b) => a.localeCompare(b)); const probeProfileIds = (() => { if (!opts.probeProfile) return []; @@ -298,7 +298,7 @@ export async function modelsStatusCommand( remainingMs: unusableUntil - now, }); } - return out.sort((a, b) => a.remainingMs - b.remainingMs); + return out.toSorted((a, b) => a.remainingMs - b.remainingMs); })(); const checkStatus = (() => { diff --git a/src/commands/models/scan.ts b/src/commands/models/scan.ts index abde4877c5..9831b04d9d 100644 --- a/src/commands/models/scan.ts +++ b/src/commands/models/scan.ts @@ -33,7 +33,7 @@ const truncate = (value: string, max: number) => { }; function sortScanResults(results: ModelScanResult[]): ModelScanResult[] { - return results.slice().sort((a, b) => { + return results.slice().toSorted((a, b) => { const aImage = a.image.ok ? 1 : 0; const bImage = b.image.ok ? 1 : 0; if (aImage !== bImage) return bImage - aImage; @@ -55,7 +55,7 @@ function sortScanResults(results: ModelScanResult[]): ModelScanResult[] { } function sortImageResults(results: ModelScanResult[]): ModelScanResult[] { - return results.slice().sort((a, b) => { + return results.slice().toSorted((a, b) => { const aLatency = a.image.latencyMs ?? Number.POSITIVE_INFINITY; const bLatency = b.image.latencyMs ?? Number.POSITIVE_INFINITY; if (aLatency !== bLatency) return aLatency - bLatency; @@ -255,7 +255,7 @@ export async function modelsScanCommand( runtime.exit(0); } - selected = selection as string[]; + selected = selection; if (imageSorted.length > 0) { const imageSelection = await multiselect({ message: "Select image fallback models (ordered)", @@ -272,7 +272,7 @@ export async function modelsScanCommand( runtime.exit(0); } - selectedImages = imageSelection as string[]; + selectedImages = imageSelection; } } else if (!process.stdin.isTTY && !opts.yes && !noInput && !opts.json) { throw new Error("Non-interactive scan: pass --yes to apply defaults."); diff --git a/src/commands/onboard-channels.ts b/src/commands/onboard-channels.ts index 6f8c075848..ffc63b814b 100644 --- a/src/commands/onboard-channels.ts +++ b/src/commands/onboard-channels.ts @@ -74,11 +74,11 @@ async function promptConfiguredAction(params: { ...(supportsDelete ? [deleteOption] : []), skipOption, ]; - return (await prompter.select({ + return await prompter.select({ message: `${label} already configured. What do you want to do?`, options, initialValue: "update", - })) as ConfiguredChannelAction; + }); } async function promptRemovalAccountId(params: { @@ -93,14 +93,14 @@ async function promptRemovalAccountId(params: { const accountIds = plugin.config.listAccountIds(cfg).filter(Boolean); const defaultAccountId = resolveChannelDefaultAccountId({ plugin, cfg, accountIds }); if (accountIds.length <= 1) return defaultAccountId; - const selected = (await prompter.select({ + const selected = await prompter.select({ message: `${label} account`, options: accountIds.map((accountId) => ({ value: accountId, label: formatAccountLabel(accountId), })), initialValue: defaultAccountId, - })) as string; + }); return normalizeAccountId(selected) ?? defaultAccountId; } @@ -304,7 +304,7 @@ export async function setupChannels( if (!shouldConfigure) return cfg; const corePrimer = listChatChannels().map((meta) => ({ - id: meta.id as ChannelChoice, + id: meta.id, label: meta.label, blurb: meta.blurb, })); @@ -312,9 +312,9 @@ export async function setupChannels( const primerChannels = [ ...corePrimer, ...installedPlugins - .filter((plugin) => !coreIds.has(plugin.id as ChannelChoice)) + .filter((plugin) => !coreIds.has(plugin.id)) .map((plugin) => ({ - id: plugin.id as ChannelChoice, + id: plugin.id, label: plugin.meta.label, blurb: plugin.meta.blurb, })), diff --git a/src/commands/onboard-helpers.ts b/src/commands/onboard-helpers.ts index 3c5ca6e390..8703d0259d 100644 --- a/src/commands/onboard-helpers.ts +++ b/src/commands/onboard-helpers.ts @@ -33,7 +33,7 @@ export function guardCancel(value: T | symbol, runtime: RuntimeEnv): T { cancel(stylePromptTitle("Setup cancelled.") ?? "Setup cancelled."); runtime.exit(0); } - return value as T; + return value; } export function summarizeExistingConfig(config: OpenClawConfig): string { diff --git a/src/commands/onboard-non-interactive.gateway.test.ts b/src/commands/onboard-non-interactive.gateway.test.ts index e41eea16ac..27170a1771 100644 --- a/src/commands/onboard-non-interactive.gateway.test.ts +++ b/src/commands/onboard-non-interactive.gateway.test.ts @@ -227,7 +227,7 @@ describe("onboard (non-interactive): gateway and remote auth", () => { // otherwise sees a mocked writeConfigFile and the config never lands on disk). vi.resetModules(); vi.doMock("../config/config.js", async () => { - return (await vi.importActual("../config/config.js")) as typeof import("../config/config.js"); + return await vi.importActual("../config/config.js"); }); const { runNonInteractiveOnboarding } = await import("./onboard-non-interactive.js"); diff --git a/src/commands/onboard-remote.ts b/src/commands/onboard-remote.ts index 628e33fbc7..d471f6d825 100644 --- a/src/commands/onboard-remote.ts +++ b/src/commands/onboard-remote.ts @@ -118,13 +118,13 @@ export async function promptRemoteGatewayConfig( }); const url = ensureWsUrl(String(urlInput)); - const authChoice = (await prompter.select({ + const authChoice = await prompter.select({ message: "Gateway auth", options: [ { value: "token", label: "Token (recommended)" }, { value: "off", label: "No auth" }, ], - })) as "token" | "off"; + }); let token = cfg.gateway?.remote?.token ?? ""; if (authChoice === "token") { diff --git a/src/commands/onboard-skills.ts b/src/commands/onboard-skills.ts index 942aac2546..82a13b36bb 100644 --- a/src/commands/onboard-skills.ts +++ b/src/commands/onboard-skills.ts @@ -132,7 +132,7 @@ export async function setupSkills( ], }); - const selected = (toInstall as string[]).filter((name) => name !== "__skip__"); + const selected = toInstall.filter((name) => name !== "__skip__"); for (const name of selected) { const target = installable.find((s) => s.name === name); if (!target || target.install.length === 0) continue; diff --git a/src/commands/onboarding/registry.ts b/src/commands/onboarding/registry.ts index 00c5270c56..d3fdbef2ce 100644 --- a/src/commands/onboarding/registry.ts +++ b/src/commands/onboarding/registry.ts @@ -5,9 +5,7 @@ import type { ChannelOnboardingAdapter } from "./types.js"; const CHANNEL_ONBOARDING_ADAPTERS = () => new Map( listChannelPlugins() - .map((plugin) => - plugin.onboarding ? ([plugin.id as ChannelChoice, plugin.onboarding] as const) : null, - ) + .map((plugin) => (plugin.onboarding ? ([plugin.id, plugin.onboarding] as const) : null)) .filter((entry): entry is readonly [ChannelChoice, ChannelOnboardingAdapter] => Boolean(entry), ), diff --git a/src/commands/sessions.ts b/src/commands/sessions.ts index 1f1d5497fe..bd7232811f 100644 --- a/src/commands/sessions.ts +++ b/src/commands/sessions.ts @@ -144,7 +144,7 @@ function toRows(store: Record): SessionRow[] { contextTokens: entry?.contextTokens, } satisfies SessionRow; }) - .sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0)); + .toSorted((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0)); } export async function sessionsCommand( diff --git a/src/commands/status-all.ts b/src/commands/status-all.ts index d2afebe585..6c52b00278 100644 --- a/src/commands/status-all.ts +++ b/src/commands/status-all.ts @@ -220,7 +220,7 @@ export async function statusAllCommand( progress.setLabel("Querying gateway…"); const health = gatewayReachable - ? await callGateway({ + ? await callGateway({ method: "health", timeoutMs: Math.min(8000, opts?.timeoutMs ?? 10_000), ...callOverrides, @@ -379,19 +379,17 @@ export async function statusAllCommand( daemon ? { Item: "Gateway service", - Value: - daemon.installed === false - ? `${daemon.label} not installed` - : `${daemon.label} ${daemon.installed ? "installed · " : ""}${daemon.loadedText}${daemon.runtime?.status ? ` · ${daemon.runtime.status}` : ""}${daemon.runtime?.pid ? ` (pid ${daemon.runtime.pid})` : ""}`, + Value: !daemon.installed + ? `${daemon.label} not installed` + : `${daemon.label} ${daemon.installed ? "installed · " : ""}${daemon.loadedText}${daemon.runtime?.status ? ` · ${daemon.runtime.status}` : ""}${daemon.runtime?.pid ? ` (pid ${daemon.runtime.pid})` : ""}`, } : { Item: "Gateway service", Value: "unknown" }, nodeService ? { Item: "Node service", - Value: - nodeService.installed === false - ? `${nodeService.label} not installed` - : `${nodeService.label} ${nodeService.installed ? "installed · " : ""}${nodeService.loadedText}${nodeService.runtime?.status ? ` · ${nodeService.runtime.status}` : ""}${nodeService.runtime?.pid ? ` (pid ${nodeService.runtime.pid})` : ""}`, + Value: !nodeService.installed + ? `${nodeService.label} not installed` + : `${nodeService.label} ${nodeService.installed ? "installed · " : ""}${nodeService.loadedText}${nodeService.runtime?.status ? ` · ${nodeService.runtime.status}` : ""}${nodeService.runtime?.pid ? ` (pid ${nodeService.runtime.pid})` : ""}`, } : { Item: "Node service", Value: "unknown" }, { diff --git a/src/commands/status-all/channels.ts b/src/commands/status-all/channels.ts index 1b32f3e38d..7229e1aa36 100644 --- a/src/commands/status-all/channels.ts +++ b/src/commands/status-all/channels.ts @@ -39,7 +39,7 @@ function summarizeSources(sources: Array): { counts.set(key, (counts.get(key) ?? 0) + 1); } const parts = [...counts.entries()] - .sort((a, b) => b[1] - a[1]) + .toSorted((a, b) => b[1] - a[1]) .map(([key, n]) => `${key}${n > 1 ? `×${n}` : ""}`); const label = parts.length > 0 ? parts.join("+") : "unknown"; return { label, parts }; @@ -430,7 +430,7 @@ export async function buildChannelsTable( accountId: entry.accountId, name: entry.snapshot.name, }), - Status: entry.enabled !== false ? "OK" : "WARN", + Status: entry.enabled ? "OK" : "WARN", Notes: notes.join(" · "), }; }), diff --git a/src/commands/status.command.ts b/src/commands/status.command.ts index e87fb09aeb..d016e154d9 100644 --- a/src/commands/status.command.ts +++ b/src/commands/status.command.ts @@ -401,7 +401,9 @@ export async function statusCommand( }; const sevRank = (sev: "critical" | "warn" | "info") => sev === "critical" ? 0 : sev === "warn" ? 1 : 2; - const sorted = [...importantFindings].sort((a, b) => sevRank(a.severity) - sevRank(b.severity)); + const sorted = [...importantFindings].toSorted( + (a, b) => sevRank(a.severity) - sevRank(b.severity), + ); const shown = sorted.slice(0, 6); for (const f of shown) { runtime.log(` ${severityLabel(f.severity)} ${f.title}`); diff --git a/src/commands/status.link-channel.ts b/src/commands/status.link-channel.ts index 5763858ed4..dcbcc227c7 100644 --- a/src/commands/status.link-channel.ts +++ b/src/commands/status.link-channel.ts @@ -41,7 +41,7 @@ export async function resolveLinkChannelContext( snapshot, }) : undefined; - const summaryRecord = summary as Record | undefined; + const summaryRecord = summary; const linked = summaryRecord && typeof summaryRecord.linked === "boolean" ? summaryRecord.linked : null; if (linked === null) continue; diff --git a/src/commands/status.summary.ts b/src/commands/status.summary.ts index 1845e29ead..96b12df7f4 100644 --- a/src/commands/status.summary.ts +++ b/src/commands/status.summary.ts @@ -150,7 +150,7 @@ export async function getStatusSummary(): Promise { const allSessions = Array.from(paths) .flatMap((storePath) => buildSessionRows(loadStore(storePath))) - .sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0)); + .toSorted((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0)); const recent = allSessions.slice(0, 10); const totalSessions = allSessions.length; diff --git a/src/config/io.ts b/src/config/io.ts index ac32bed5b8..372dc066d2 100644 --- a/src/config/io.ts +++ b/src/config/io.ts @@ -178,7 +178,7 @@ export function parseConfigJson5( json5: { parse: (value: string) => unknown } = JSON5, ): ParseConfigJson5Result { try { - return { ok: true, parsed: json5.parse(raw) as unknown }; + return { ok: true, parsed: json5.parse(raw) }; } catch (err) { return { ok: false, error: String(err) }; } diff --git a/src/config/sessions.cache.test.ts b/src/config/sessions.cache.test.ts index 44d6648089..92922576bb 100644 --- a/src/config/sessions.cache.test.ts +++ b/src/config/sessions.cache.test.ts @@ -94,7 +94,7 @@ describe("Session Store Cache", () => { const loaded1 = loadSessionStore(storePath); loaded1["session:1"].cliSessionIds = { openai: "mutated" }; if (loaded1["session:1"].skillsSnapshot?.skills?.length) { - loaded1["session:1"].skillsSnapshot!.skills[0].name = "mutated"; + loaded1["session:1"].skillsSnapshot.skills[0].name = "mutated"; } const loaded2 = loadSessionStore(storePath); diff --git a/src/config/sessions/group.ts b/src/config/sessions/group.ts index 880c1e3897..fb0e341041 100644 --- a/src/config/sessions/group.ts +++ b/src/config/sessions/group.ts @@ -79,7 +79,7 @@ export function resolveGroupSessionKey(ctx: MsgContext): GroupKeyResolution | nu const second = parts[1]?.trim().toLowerCase(); const secondIsKind = second === "group" || second === "channel"; const kind = secondIsKind - ? (second as "group" | "channel") + ? second : from.includes(":channel:") || normalizedChatType === "channel" ? "channel" : "group"; diff --git a/src/config/sessions/store.ts b/src/config/sessions/store.ts index da581fff01..cd438bc053 100644 --- a/src/config/sessions/store.ts +++ b/src/config/sessions/store.ts @@ -127,7 +127,7 @@ export function loadSessionStore( const raw = fs.readFileSync(storePath, "utf-8"); const parsed = JSON5.parse(raw); if (isSessionStoreRecord(parsed)) { - store = parsed as Record; + store = parsed; } mtimeMs = getFileMtimeMs(storePath) ?? mtimeMs; } catch { @@ -317,7 +317,7 @@ async function withSessionStoreLock( const now = Date.now(); if (now - startedAt > timeoutMs) { - throw new Error(`timeout acquiring session store lock: ${lockPath}`); + throw new Error(`timeout acquiring session store lock: ${lockPath}`, { cause: err }); } // Best-effort stale lock eviction (e.g. crashed process). diff --git a/src/cron/normalize.ts b/src/cron/normalize.ts index 55e21684fb..91de138112 100644 --- a/src/cron/normalize.ts +++ b/src/cron/normalize.ts @@ -71,7 +71,7 @@ export function normalizeCronJobInput( const next: UnknownRecord = { ...base }; if ("agentId" in base) { - const agentId = (base as UnknownRecord).agentId; + const agentId = base.agentId; if (agentId === null) { next.agentId = null; } else if (typeof agentId === "string") { @@ -82,7 +82,7 @@ export function normalizeCronJobInput( } if ("enabled" in base) { - const enabled = (base as UnknownRecord).enabled; + const enabled = base.enabled; if (typeof enabled === "boolean") { next.enabled = enabled; } else if (typeof enabled === "string") { diff --git a/src/cron/run-log.ts b/src/cron/run-log.ts index fcb5296917..6949ba941a 100644 --- a/src/cron/run-log.ts +++ b/src/cron/run-log.ts @@ -82,5 +82,5 @@ export async function readCronRunLogEntries( // ignore invalid lines } } - return parsed.reverse(); + return parsed.toReversed(); } diff --git a/src/cron/service/jobs.ts b/src/cron/service/jobs.ts index 132156a0c7..eb3fe34694 100644 --- a/src/cron/service/jobs.ts +++ b/src/cron/service/jobs.ts @@ -83,7 +83,7 @@ export function createJob(state: CronServiceState, input: CronJobCreate): CronJo agentId: normalizeOptionalAgentId(input.agentId), name: normalizeRequiredName(input.name), description: normalizeOptionalText(input.description), - enabled: input.enabled !== false, + enabled: input.enabled, deleteAfterRun: input.deleteAfterRun, createdAtMs: now, updatedAtMs: now, diff --git a/src/cron/service/ops.ts b/src/cron/service/ops.ts index 184d096fbc..a084c2ba44 100644 --- a/src/cron/service/ops.ts +++ b/src/cron/service/ops.ts @@ -45,7 +45,7 @@ export async function status(state: CronServiceState) { enabled: state.deps.cronEnabled, storePath: state.deps.storePath, jobs: state.store?.jobs.length ?? 0, - nextWakeAtMs: state.deps.cronEnabled === true ? (nextWakeAtMs(state) ?? null) : null, + nextWakeAtMs: state.deps.cronEnabled ? (nextWakeAtMs(state) ?? null) : null, }; }); } @@ -55,7 +55,7 @@ export async function list(state: CronServiceState, opts?: { includeDisabled?: b await ensureLoaded(state); const includeDisabled = opts?.includeDisabled === true; const jobs = (state.store?.jobs ?? []).filter((j) => includeDisabled || j.enabled); - return jobs.sort((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0)); + return jobs.toSorted((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0)); }); } diff --git a/src/cron/store.ts b/src/cron/store.ts index e2ecf9cb95..e50d020e4a 100644 --- a/src/cron/store.ts +++ b/src/cron/store.ts @@ -21,7 +21,7 @@ export function resolveCronStorePath(storePath?: string) { export async function loadCronStore(storePath: string): Promise { try { const raw = await fs.promises.readFile(storePath, "utf-8"); - const parsed = JSON5.parse(raw) as Partial | null; + const parsed = JSON5.parse(raw); const jobs = Array.isArray(parsed?.jobs) ? (parsed?.jobs as never[]) : []; return { version: 1, diff --git a/src/discord/accounts.ts b/src/discord/accounts.ts index e4bf6ad318..a041a649a9 100644 --- a/src/discord/accounts.ts +++ b/src/discord/accounts.ts @@ -21,7 +21,7 @@ function listConfiguredAccountIds(cfg: OpenClawConfig): string[] { export function listDiscordAccountIds(cfg: OpenClawConfig): string[] { const ids = listConfiguredAccountIds(cfg); if (ids.length === 0) return [DEFAULT_ACCOUNT_ID]; - return ids.sort((a, b) => a.localeCompare(b)); + return ids.toSorted((a, b) => a.localeCompare(b)); } export function resolveDefaultDiscordAccountId(cfg: OpenClawConfig): string { diff --git a/src/discord/audit.ts b/src/discord/audit.ts index 366e8653ca..056ad43f32 100644 --- a/src/discord/audit.ts +++ b/src/discord/audit.ts @@ -49,7 +49,7 @@ function listConfiguredGuildChannelKeys( ids.add(channelId); } } - return [...ids].sort((a, b) => a.localeCompare(b)); + return [...ids].toSorted((a, b) => a.localeCompare(b)); } export function collectDiscordAuditChannelIds(params: { diff --git a/src/discord/monitor.slash.test.ts b/src/discord/monitor.slash.test.ts index c12bbe4d62..e4415d570a 100644 --- a/src/discord/monitor.slash.test.ts +++ b/src/discord/monitor.slash.test.ts @@ -17,9 +17,7 @@ vi.mock("@buape/carbon", () => ({ MessageReactionAddListener: class {}, MessageReactionRemoveListener: class {}, PresenceUpdateListener: class {}, - Row: class { - constructor(_components: unknown[]) {} - }, + Row: class {}, })); vi.mock("../auto-reply/dispatch.js", async (importOriginal) => { diff --git a/src/discord/monitor/allow-list.ts b/src/discord/monitor/allow-list.ts index b3836fe96d..a0954ec2f5 100644 --- a/src/discord/monitor/allow-list.ts +++ b/src/discord/monitor/allow-list.ts @@ -154,7 +154,7 @@ export function resolveDiscordCommandAuthorized(params: { } export function resolveDiscordGuildEntry(params: { - guild?: Guild | Guild | null; + guild?: Guild | Guild | null; guildEntries?: Record; }): DiscordGuildEntryResolved | null { const guild = params.guild; diff --git a/src/discord/resolve-channels.ts b/src/discord/resolve-channels.ts index cbc1d7dd17..2fc01fa2c6 100644 --- a/src/discord/resolve-channels.ts +++ b/src/discord/resolve-channels.ts @@ -77,11 +77,7 @@ async function listGuildChannels( fetcher: typeof fetch, guildId: string, ): Promise { - const raw = (await fetchDiscord( - `/guilds/${guildId}/channels`, - token, - fetcher, - )) as RESTGetAPIGuildChannelsResult; + const raw = await fetchDiscord(`/guilds/${guildId}/channels`, token, fetcher); return raw .filter((channel) => Boolean(channel.id) && "name" in channel) .map((channel) => { @@ -105,11 +101,7 @@ async function fetchChannel( fetcher: typeof fetch, channelId: string, ): Promise { - const raw = (await fetchDiscord( - `/channels/${channelId}`, - token, - fetcher, - )) as RESTGetAPIChannelResult; + const raw = await fetchDiscord(`/channels/${channelId}`, token, fetcher); if (!raw || !("guild_id" in raw)) return null; return { id: raw.id, diff --git a/src/discord/send.permissions.ts b/src/discord/send.permissions.ts index 8cbd9245e1..2f67b2e84e 100644 --- a/src/discord/send.permissions.ts +++ b/src/discord/send.permissions.ts @@ -10,7 +10,7 @@ import { normalizeDiscordToken } from "./token.js"; const PERMISSION_ENTRIES = Object.entries(PermissionFlagsBits).filter( ([, value]) => typeof value === "bigint", -) as Array<[string, bigint]>; +); type DiscordClientOpts = { token?: string; @@ -60,7 +60,7 @@ function removePermissionBits(base: bigint, deny?: string) { function bitfieldToPermissions(bitfield: bigint) { return PERMISSION_ENTRIES.filter(([, value]) => (bitfield & value) === value) .map(([name]) => name) - .sort(); + .toSorted(); } export function isThreadChannelType(channelType?: number) { diff --git a/src/gateway/client.ts b/src/gateway/client.ts index 23929f9a49..f296d9524f 100644 --- a/src/gateway/client.ts +++ b/src/gateway/client.ts @@ -279,7 +279,7 @@ export class GatewayClient { try { const parsed = JSON.parse(raw); if (validateEventFrame(parsed)) { - const evt = parsed as EventFrame; + const evt = parsed; if (evt.event === "connect.challenge") { const payload = evt.payload as { nonce?: unknown } | undefined; const nonce = payload && typeof payload.nonce === "string" ? payload.nonce : null; diff --git a/src/gateway/gateway-models.profiles.live.test.ts b/src/gateway/gateway-models.profiles.live.test.ts index 78628d3560..90d1ecefcc 100644 --- a/src/gateway/gateway-models.profiles.live.test.ts +++ b/src/gateway/gateway-models.profiles.live.test.ts @@ -965,7 +965,7 @@ describeLive("gateway live (dev agent, profile keys)", () => { }); const authStorage = discoverAuthStorage(agentDir); const modelRegistry = discoverModels(authStorage, agentDir); - const all = modelRegistry.getAll() as Array>; + const all = modelRegistry.getAll(); const rawModels = process.env.OPENCLAW_LIVE_GATEWAY_MODELS?.trim(); const useModern = !rawModels || rawModels === "modern" || rawModels === "all"; diff --git a/src/gateway/hooks-mapping.ts b/src/gateway/hooks-mapping.ts index 2ebf9b136e..e6972134f7 100644 --- a/src/gateway/hooks-mapping.ts +++ b/src/gateway/hooks-mapping.ts @@ -249,7 +249,7 @@ function mergeAction( if (!override) { return validateAction(base); } - const kind = (override.kind ?? base.kind ?? defaultAction) as "wake" | "agent"; + const kind = override.kind ?? base.kind ?? defaultAction; if (kind === "wake") { const baseWake = base.kind === "wake" ? base : undefined; const text = typeof override.text === "string" ? override.text : (baseWake?.text ?? ""); diff --git a/src/gateway/server-maintenance.ts b/src/gateway/server-maintenance.ts index 499521b843..027103950e 100644 --- a/src/gateway/server-maintenance.ts +++ b/src/gateway/server-maintenance.ts @@ -78,7 +78,7 @@ export function startGatewayMaintenanceTimers(params: { if (now - v.ts > DEDUPE_TTL_MS) params.dedupe.delete(k); } if (params.dedupe.size > DEDUPE_MAX) { - const entries = [...params.dedupe.entries()].sort((a, b) => a[1].ts - b[1].ts); + const entries = [...params.dedupe.entries()].toSorted((a, b) => a[1].ts - b[1].ts); for (let i = 0; i < params.dedupe.size - DEDUPE_MAX; i++) { params.dedupe.delete(entries[i][0]); } diff --git a/src/gateway/server-methods/agent-job.ts b/src/gateway/server-methods/agent-job.ts index 2d819c9444..6469b14d18 100644 --- a/src/gateway/server-methods/agent-job.ts +++ b/src/gateway/server-methods/agent-job.ts @@ -35,19 +35,15 @@ function ensureAgentRunListener() { if (evt.stream !== "lifecycle") return; const phase = evt.data?.phase; if (phase === "start") { - const startedAt = - typeof evt.data?.startedAt === "number" ? (evt.data.startedAt as number) : undefined; + const startedAt = typeof evt.data?.startedAt === "number" ? evt.data.startedAt : undefined; agentRunStarts.set(evt.runId, startedAt ?? Date.now()); return; } if (phase !== "end" && phase !== "error") return; const startedAt = - typeof evt.data?.startedAt === "number" - ? (evt.data.startedAt as number) - : agentRunStarts.get(evt.runId); - const endedAt = - typeof evt.data?.endedAt === "number" ? (evt.data.endedAt as number) : undefined; - const error = typeof evt.data?.error === "string" ? (evt.data.error as string) : undefined; + typeof evt.data?.startedAt === "number" ? evt.data.startedAt : agentRunStarts.get(evt.runId); + const endedAt = typeof evt.data?.endedAt === "number" ? evt.data.endedAt : undefined; + const error = typeof evt.data?.error === "string" ? evt.data.error : undefined; agentRunStarts.delete(evt.runId); recordAgentRunSnapshot({ runId: evt.runId, @@ -96,11 +92,10 @@ export async function waitForAgentJob(params: { } const startedAt = typeof evt.data?.startedAt === "number" - ? (evt.data.startedAt as number) + ? evt.data.startedAt : agentRunStarts.get(evt.runId); - const endedAt = - typeof evt.data?.endedAt === "number" ? (evt.data.endedAt as number) : undefined; - const error = typeof evt.data?.error === "string" ? (evt.data.error as string) : undefined; + const endedAt = typeof evt.data?.endedAt === "number" ? evt.data.endedAt : undefined; + const error = typeof evt.data?.error === "string" ? evt.data.error : undefined; const snapshot: AgentRunSnapshot = { runId: evt.runId, status: phase === "error" ? "error" : "ok", diff --git a/src/gateway/server-methods/agent.ts b/src/gateway/server-methods/agent.ts index d159d1f78e..0747ce216e 100644 --- a/src/gateway/server-methods/agent.ts +++ b/src/gateway/server-methods/agent.ts @@ -44,7 +44,7 @@ import type { GatewayRequestHandlers } from "./types.js"; export const agentHandlers: GatewayRequestHandlers = { agent: async ({ params, respond, context }) => { - const p = params as Record; + const p = params; if (!validateAgentParams(p)) { respond( false, @@ -430,7 +430,7 @@ export const agentHandlers: GatewayRequestHandlers = { ); return; } - const p = params as AgentIdentityParams; + const p = params; const agentIdRaw = typeof p.agentId === "string" ? p.agentId.trim() : ""; const sessionKeyRaw = typeof p.sessionKey === "string" ? p.sessionKey.trim() : ""; let agentId = agentIdRaw ? normalizeAgentId(agentIdRaw) : undefined; @@ -471,7 +471,7 @@ export const agentHandlers: GatewayRequestHandlers = { ); return; } - const p = params as AgentWaitParams; + const p = params; const runId = p.runId.trim(); const timeoutMs = typeof p.timeoutMs === "number" && Number.isFinite(p.timeoutMs) diff --git a/src/gateway/server-methods/cron.ts b/src/gateway/server-methods/cron.ts index 4420358b8e..68bbd228c2 100644 --- a/src/gateway/server-methods/cron.ts +++ b/src/gateway/server-methods/cron.ts @@ -89,7 +89,7 @@ export const cronHandlers: GatewayRequestHandlers = { const normalizedPatch = normalizeCronJobPatch((params as { patch?: unknown } | null)?.patch); const candidate = normalizedPatch && typeof params === "object" && params !== null - ? { ...(params as Record), patch: normalizedPatch } + ? { ...params, patch: normalizedPatch } : params; if (!validateCronUpdateParams(candidate)) { respond( diff --git a/src/gateway/server-methods/logs.ts b/src/gateway/server-methods/logs.ts index ea4d27cb25..1f8c07c88b 100644 --- a/src/gateway/server-methods/logs.ts +++ b/src/gateway/server-methods/logs.ts @@ -43,7 +43,7 @@ async function resolveLogFile(file: string): Promise { ); const sorted = candidates .filter((entry): entry is NonNullable => Boolean(entry)) - .sort((a, b) => b.mtimeMs - a.mtimeMs); + .toSorted((a, b) => b.mtimeMs - a.mtimeMs); return sorted[0]?.path ?? file; } diff --git a/src/gateway/server-methods/nodes.helpers.ts b/src/gateway/server-methods/nodes.helpers.ts index fc7964e303..a4c66b0293 100644 --- a/src/gateway/server-methods/nodes.helpers.ts +++ b/src/gateway/server-methods/nodes.helpers.ts @@ -34,7 +34,7 @@ export function uniqueSortedStrings(values: unknown[]) { return [...new Set(values.filter((v) => typeof v === "string"))] .map((v) => v.trim()) .filter(Boolean) - .sort(); + .toSorted(); } export function safeParseJson(value: string | null | undefined): unknown { diff --git a/src/gateway/server-methods/send.ts b/src/gateway/server-methods/send.ts index 1d3adbb6f9..fb81848330 100644 --- a/src/gateway/server-methods/send.ts +++ b/src/gateway/server-methods/send.ts @@ -46,7 +46,7 @@ const getInflightMap = (context: GatewayRequestContext) => { export const sendHandlers: GatewayRequestHandlers = { send: async ({ params, respond, context }) => { - const p = params as Record; + const p = params; if (!validateSendParams(p)) { respond( false, @@ -104,8 +104,8 @@ export const sendHandlers: GatewayRequestHandlers = { typeof request.accountId === "string" && request.accountId.trim().length ? request.accountId.trim() : undefined; - const outboundChannel = channel as Exclude; - const plugin = getChannelPlugin(channel as ChannelId); + const outboundChannel = channel; + const plugin = getChannelPlugin(channel); if (!plugin) { respond( false, @@ -237,7 +237,7 @@ export const sendHandlers: GatewayRequestHandlers = { } }, poll: async ({ params, respond, context }) => { - const p = params as Record; + const p = params; if (!validatePollParams(p)) { respond( false, @@ -290,7 +290,7 @@ export const sendHandlers: GatewayRequestHandlers = { ? request.accountId.trim() : undefined; try { - const plugin = getChannelPlugin(channel as ChannelId); + const plugin = getChannelPlugin(channel); const outbound = plugin?.outbound; if (!outbound?.sendPoll) { respond( @@ -302,7 +302,7 @@ export const sendHandlers: GatewayRequestHandlers = { } const cfg = loadConfig(); const resolved = resolveOutboundTarget({ - channel: channel as Exclude, + channel: channel, to, cfg, accountId, diff --git a/src/gateway/server-methods/sessions.ts b/src/gateway/server-methods/sessions.ts index df59a3f317..f50e1ef492 100644 --- a/src/gateway/server-methods/sessions.ts +++ b/src/gateway/server-methods/sessions.ts @@ -53,7 +53,7 @@ export const sessionsHandlers: GatewayRequestHandlers = { ); return; } - const p = params as import("../protocol/index.js").SessionsListParams; + const p = params; const cfg = loadConfig(); const { storePath, store } = loadCombinedSessionStoreForGateway(cfg); const result = listSessionsFromStore({ @@ -78,7 +78,7 @@ export const sessionsHandlers: GatewayRequestHandlers = { ); return; } - const p = params as import("../protocol/index.js").SessionsPreviewParams; + const p = params; const keysRaw = Array.isArray(p.keys) ? p.keys : []; const keys = keysRaw .map((key) => String(key ?? "").trim()) @@ -144,7 +144,7 @@ export const sessionsHandlers: GatewayRequestHandlers = { ); return; } - const p = params as import("../protocol/index.js").SessionsResolveParams; + const p = params; const cfg = loadConfig(); const resolved = resolveSessionKeyFromResolveParams({ cfg, p }); @@ -166,7 +166,7 @@ export const sessionsHandlers: GatewayRequestHandlers = { ); return; } - const p = params as import("../protocol/index.js").SessionsPatchParams; + const p = params; const key = String(p.key ?? "").trim(); if (!key) { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "key required")); @@ -215,7 +215,7 @@ export const sessionsHandlers: GatewayRequestHandlers = { ); return; } - const p = params as import("../protocol/index.js").SessionsResetParams; + const p = params; const key = String(p.key ?? "").trim(); if (!key) { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "key required")); @@ -273,7 +273,7 @@ export const sessionsHandlers: GatewayRequestHandlers = { ); return; } - const p = params as import("../protocol/index.js").SessionsDeleteParams; + const p = params; const key = String(p.key ?? "").trim(); if (!key) { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "key required")); @@ -359,7 +359,7 @@ export const sessionsHandlers: GatewayRequestHandlers = { ); return; } - const p = params as import("../protocol/index.js").SessionsCompactParams; + const p = params; const key = String(p.key ?? "").trim(); if (!key) { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "key required")); diff --git a/src/gateway/server-methods/skills.ts b/src/gateway/server-methods/skills.ts index 829df66c72..d5e872fdbf 100644 --- a/src/gateway/server-methods/skills.ts +++ b/src/gateway/server-methods/skills.ts @@ -52,7 +52,7 @@ function collectSkillBins(entries: SkillEntry[]): string[] { } } } - return [...bins].sort(); + return [...bins].toSorted(); } export const skillsHandlers: GatewayRequestHandlers = { @@ -95,7 +95,7 @@ export const skillsHandlers: GatewayRequestHandlers = { const entries = loadWorkspaceSkillEntries(workspaceDir, { config: cfg }); for (const bin of collectSkillBins(entries)) bins.add(bin); } - respond(true, { bins: [...bins].sort() }, undefined); + respond(true, { bins: [...bins].toSorted() }, undefined); }, "skills.install": async ({ params, respond }) => { if (!validateSkillsInstallParams(params)) { diff --git a/src/gateway/server-methods/system.ts b/src/gateway/server-methods/system.ts index 66d6eb3de6..b9c5e64ca0 100644 --- a/src/gateway/server-methods/system.ts +++ b/src/gateway/server-methods/system.ts @@ -54,15 +54,15 @@ export const systemHandlers: GatewayRequestHandlers = { const reason = typeof params.reason === "string" ? params.reason : undefined; const roles = Array.isArray(params.roles) && params.roles.every((t) => typeof t === "string") - ? (params.roles as string[]) + ? params.roles : undefined; const scopes = Array.isArray(params.scopes) && params.scopes.every((t) => typeof t === "string") - ? (params.scopes as string[]) + ? params.scopes : undefined; const tags = Array.isArray(params.tags) && params.tags.every((t) => typeof t === "string") - ? (params.tags as string[]) + ? params.tags : undefined; const presenceUpdate = updateSystemPresence({ text, diff --git a/src/gateway/server-methods/wizard.ts b/src/gateway/server-methods/wizard.ts index 7a1e423249..e3a3fca26e 100644 --- a/src/gateway/server-methods/wizard.ts +++ b/src/gateway/server-methods/wizard.ts @@ -33,7 +33,7 @@ export const wizardHandlers: GatewayRequestHandlers = { } const sessionId = randomUUID(); const opts = { - mode: params.mode as "local" | "remote" | undefined, + mode: params.mode, workspace: typeof params.workspace === "string" ? params.workspace : undefined, }; const session = new WizardSession((prompter) => @@ -58,7 +58,7 @@ export const wizardHandlers: GatewayRequestHandlers = { ); return; } - const sessionId = params.sessionId as string; + const sessionId = params.sessionId; const session = context.wizardSessions.get(sessionId); if (!session) { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "wizard not found")); @@ -95,7 +95,7 @@ export const wizardHandlers: GatewayRequestHandlers = { ); return; } - const sessionId = params.sessionId as string; + const sessionId = params.sessionId; const session = context.wizardSessions.get(sessionId); if (!session) { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "wizard not found")); @@ -121,7 +121,7 @@ export const wizardHandlers: GatewayRequestHandlers = { ); return; } - const sessionId = params.sessionId as string; + const sessionId = params.sessionId; const session = context.wizardSessions.get(sessionId); if (!session) { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "wizard not found")); diff --git a/src/gateway/server-node-subscriptions.test.ts b/src/gateway/server-node-subscriptions.test.ts index 9af7a96302..776e5a048f 100644 --- a/src/gateway/server-node-subscriptions.test.ts +++ b/src/gateway/server-node-subscriptions.test.ts @@ -17,7 +17,7 @@ describe("node subscription manager", () => { manager.sendToSession("main", "chat", { ok: true }, sendEvent); expect(sent).toHaveLength(2); - expect(sent.map((s) => s.nodeId).sort()).toEqual(["node-a", "node-b"]); + expect(sent.map((s) => s.nodeId).toSorted()).toEqual(["node-a", "node-b"]); expect(sent[0].event).toBe("chat"); }); diff --git a/src/gateway/server.chat.gateway-server-chat-b.e2e.test.ts b/src/gateway/server.chat.gateway-server-chat-b.e2e.test.ts index 88099ead96..d6d1089380 100644 --- a/src/gateway/server.chat.gateway-server-chat-b.e2e.test.ts +++ b/src/gateway/server.chat.gateway-server-chat-b.e2e.test.ts @@ -111,9 +111,10 @@ describe("gateway server chat", () => { idempotencyKey: "idem-route", }); expect(routeRes.ok).toBe(true); - const stored = JSON.parse( - await fs.readFile(testState.sessionStorePath as string, "utf-8"), - ) as Record; + const stored = JSON.parse(await fs.readFile(testState.sessionStorePath, "utf-8")) as Record< + string, + { lastChannel?: string; lastTo?: string } | undefined + >; expect(stored["agent:main:main"]?.lastChannel).toBe("whatsapp"); expect(stored["agent:main:main"]?.lastTo).toBe("+1555"); diff --git a/src/gateway/server.config-patch.e2e.test.ts b/src/gateway/server.config-patch.e2e.test.ts index 65a5401a1a..982a28f29f 100644 --- a/src/gateway/server.config-patch.e2e.test.ts +++ b/src/gateway/server.config-patch.e2e.test.ts @@ -332,7 +332,7 @@ describe("gateway server sessions", () => { agentId: "home", }); expect(homeSessions.ok).toBe(true); - expect(homeSessions.payload?.sessions.map((s) => s.key).sort()).toEqual([ + expect(homeSessions.payload?.sessions.map((s) => s.key).toSorted()).toEqual([ "agent:home:discord:group:dev", "agent:home:main", ]); diff --git a/src/gateway/server.reload.e2e.test.ts b/src/gateway/server.reload.e2e.test.ts index f629f0fcf6..f991d07c93 100644 --- a/src/gateway/server.reload.e2e.test.ts +++ b/src/gateway/server.reload.e2e.test.ts @@ -115,8 +115,8 @@ const hoisted = vi.hoisted(() => { const startGatewayConfigReloader = vi.fn( (opts: { onHotReload: typeof onHotReload; onRestart: typeof onRestart }) => { - onHotReload = opts.onHotReload as typeof onHotReload; - onRestart = opts.onRestart as typeof onRestart; + onHotReload = opts.onHotReload; + onRestart = opts.onRestart; return { stop: reloaderStop }; }, ); diff --git a/src/gateway/server/ws-connection/message-handler.ts b/src/gateway/server/ws-connection/message-handler.ts index 948d6cefbd..658b93d10d 100644 --- a/src/gateway/server/ws-connection/message-handler.ts +++ b/src/gateway/server/ws-connection/message-handler.ts @@ -263,11 +263,11 @@ export function attachGatewayWsMessageHandler(params: { const isRequestFrame = validateRequestFrame(parsed); if ( !isRequestFrame || - (parsed as RequestFrame).method !== "connect" || - !validateConnectParams((parsed as RequestFrame).params) + parsed.method !== "connect" || + !validateConnectParams(parsed.params) ) { const handshakeError = isRequestFrame - ? (parsed as RequestFrame).method === "connect" + ? parsed.method === "connect" ? `invalid connect params: ${formatValidationErrors(validateConnectParams.errors)}` : "invalid handshake: first request must be connect" : "invalid request frame"; @@ -279,7 +279,7 @@ export function attachGatewayWsMessageHandler(params: { handshakeError, }); if (isRequestFrame) { - const req = parsed as RequestFrame; + const req = parsed; send({ type: "res", id: req.id, @@ -300,7 +300,7 @@ export function attachGatewayWsMessageHandler(params: { return; } - const frame = parsed as RequestFrame; + const frame = parsed; const connectParams = frame.params as ConnectParams; const clientLabel = connectParams.client.displayName ?? connectParams.client.id; @@ -897,7 +897,7 @@ export function attachGatewayWsMessageHandler(params: { }); return; } - const req = parsed as RequestFrame; + const req = parsed; logWs("in", "req", { connId, id: req.id, method: req.method }); const respond = ( ok: boolean, diff --git a/src/gateway/session-utils.fs.ts b/src/gateway/session-utils.fs.ts index 8ab79ce48d..213583ad74 100644 --- a/src/gateway/session-utils.fs.ts +++ b/src/gateway/session-utils.fs.ts @@ -359,7 +359,7 @@ function readRecentMessagesFromTranscript( // skip malformed lines } } - return collected.reverse(); + return collected.toReversed(); } catch { return []; } finally { diff --git a/src/gateway/session-utils.ts b/src/gateway/session-utils.ts index 0cff924c7a..a5d406b3e7 100644 --- a/src/gateway/session-utils.ts +++ b/src/gateway/session-utils.ts @@ -590,7 +590,7 @@ export function listSessionsFromStore(params: { lastAccountId: deliveryFields.lastAccountId ?? entry?.lastAccountId, }; }) - .sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0)); + .toSorted((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0)); if (search) { sessions = sessions.filter((s) => { diff --git a/src/gateway/test-helpers.mocks.ts b/src/gateway/test-helpers.mocks.ts index fa55603a50..d945d4dfc6 100644 --- a/src/gateway/test-helpers.mocks.ts +++ b/src/gateway/test-helpers.mocks.ts @@ -414,7 +414,7 @@ vi.mock("../config/config.js", async () => { : {}; const overrideChannels = testState.channelsConfig && typeof testState.channelsConfig === "object" - ? { ...(testState.channelsConfig as Record) } + ? { ...testState.channelsConfig } : {}; const mergedChannels = { ...fileChannels, ...overrideChannels }; if (testState.allowFrom !== undefined) { diff --git a/src/gateway/tools-invoke-http.ts b/src/gateway/tools-invoke-http.ts index 6637ffd12b..d7c8462ebb 100644 --- a/src/gateway/tools-invoke-http.ts +++ b/src/gateway/tools-invoke-http.ts @@ -145,11 +145,10 @@ export async function handleToolsInvokeHttpRequest( const action = typeof body.action === "string" ? body.action.trim() : undefined; const argsRaw = body.args; - const args = ( + const args = argsRaw && typeof argsRaw === "object" && !Array.isArray(argsRaw) ? (argsRaw as Record) - : {} - ) as Record; + : {}; const rawSessionKey = resolveSessionKeyFromBody(body); const sessionKey = diff --git a/src/hooks/bundled/session-memory/handler.test.ts b/src/hooks/bundled/session-memory/handler.test.ts index c6bf1ae719..9c558789ed 100644 --- a/src/hooks/bundled/session-memory/handler.test.ts +++ b/src/hooks/bundled/session-memory/handler.test.ts @@ -98,7 +98,7 @@ describe("session-memory hook", () => { expect(files.length).toBe(1); // Read the memory file and verify content - const memoryContent = await fs.readFile(path.join(memoryDir, files[0]!), "utf-8"); + const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8"); expect(memoryContent).toContain("user: Hello there"); expect(memoryContent).toContain("assistant: Hi! How can I help?"); expect(memoryContent).toContain("user: What is 2+2?"); @@ -140,7 +140,7 @@ describe("session-memory hook", () => { const memoryDir = path.join(tempDir, "memory"); const files = await fs.readdir(memoryDir); - const memoryContent = await fs.readFile(path.join(memoryDir, files[0]!), "utf-8"); + const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8"); // Only user/assistant messages should be present expect(memoryContent).toContain("user: Hello"); @@ -185,7 +185,7 @@ describe("session-memory hook", () => { const memoryDir = path.join(tempDir, "memory"); const files = await fs.readdir(memoryDir); - const memoryContent = await fs.readFile(path.join(memoryDir, files[0]!), "utf-8"); + const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8"); // Command messages should be filtered out expect(memoryContent).not.toContain("/help"); @@ -236,7 +236,7 @@ describe("session-memory hook", () => { const memoryDir = path.join(tempDir, "memory"); const files = await fs.readdir(memoryDir); - const memoryContent = await fs.readFile(path.join(memoryDir, files[0]!), "utf-8"); + const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8"); // Only last 3 messages should be present expect(memoryContent).not.toContain("user: Message 1\n"); @@ -297,7 +297,7 @@ describe("session-memory hook", () => { const memoryDir = path.join(tempDir, "memory"); const files = await fs.readdir(memoryDir); - const memoryContent = await fs.readFile(path.join(memoryDir, files[0]!), "utf-8"); + const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8"); // Should have exactly 3 user/assistant messages (the last 3) expect(memoryContent).not.toContain("First message"); @@ -370,7 +370,7 @@ describe("session-memory hook", () => { const memoryDir = path.join(tempDir, "memory"); const files = await fs.readdir(memoryDir); - const memoryContent = await fs.readFile(path.join(memoryDir, files[0]!), "utf-8"); + const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8"); // Both messages should be included expect(memoryContent).toContain("user: Only message 1"); diff --git a/src/hooks/bundled/session-memory/handler.ts b/src/hooks/bundled/session-memory/handler.ts index af3b82c771..28082c1d7e 100644 --- a/src/hooks/bundled/session-memory/handler.ts +++ b/src/hooks/bundled/session-memory/handler.ts @@ -129,7 +129,7 @@ const saveSessionToMemory: HookHandler = async (event) => { // If no slug, use timestamp if (!slug) { - const timeSlug = now.toISOString().split("T")[1]!.split(".")[0]!.replace(/:/g, ""); + const timeSlug = now.toISOString().split("T")[1].split(".")[0].replace(/:/g, ""); slug = timeSlug.slice(0, 4); // HHMM console.log("[session-memory] Using fallback timestamp slug:", slug); } @@ -141,7 +141,7 @@ const saveSessionToMemory: HookHandler = async (event) => { console.log("[session-memory] Full path:", memoryFilePath); // Format time as HH:MM:SS UTC - const timeStr = now.toISOString().split("T")[1]!.split(".")[0]; + const timeStr = now.toISOString().split("T")[1].split(".")[0]; // Extract context details const sessionId = (sessionEntry.sessionId as string) || "unknown"; diff --git a/src/hooks/bundled/soul-evil/handler.ts b/src/hooks/bundled/soul-evil/handler.ts index 6b39518b1c..dc11927085 100644 --- a/src/hooks/bundled/soul-evil/handler.ts +++ b/src/hooks/bundled/soul-evil/handler.ts @@ -11,7 +11,7 @@ const soulEvilHook: HookHandler = async (event) => { const context = event.context; if (context.sessionKey && isSubagentSessionKey(context.sessionKey)) return; - const cfg = context.cfg as OpenClawConfig | undefined; + const cfg = context.cfg; const hookConfig = resolveHookConfig(cfg, HOOK_KEY); if (!hookConfig || hookConfig.enabled === false) return; diff --git a/src/hooks/config.ts b/src/hooks/config.ts index 8a1da761d4..b15d3e1843 100644 --- a/src/hooks/config.ts +++ b/src/hooks/config.ts @@ -31,7 +31,7 @@ export function resolveConfigPath(config: OpenClawConfig | undefined, pathStr: s export function isConfigPathTruthy(config: OpenClawConfig | undefined, pathStr: string): boolean { const value = resolveConfigPath(config, pathStr); if (value === undefined && pathStr in DEFAULT_CONFIG_VALUES) { - return DEFAULT_CONFIG_VALUES[pathStr] === true; + return DEFAULT_CONFIG_VALUES[pathStr]; } return isTruthy(value); } diff --git a/src/hooks/frontmatter.test.ts b/src/hooks/frontmatter.test.ts index d7660f0190..a20036f591 100644 --- a/src/hooks/frontmatter.test.ts +++ b/src/hooks/frontmatter.test.ts @@ -57,7 +57,7 @@ metadata: expect(typeof result.metadata).toBe("string"); // Verify the metadata is valid JSON - const parsed = JSON.parse(result.metadata as string); + const parsed = JSON.parse(result.metadata); expect(parsed.openclaw.emoji).toBe("💾"); expect(parsed.openclaw.events).toEqual(["command:new"]); }); @@ -82,7 +82,7 @@ metadata: expect(result.name).toBe("command-logger"); expect(result.metadata).toBeDefined(); - const parsed = JSON.parse(result.metadata as string); + const parsed = JSON.parse(result.metadata); expect(parsed.openclaw.emoji).toBe("📝"); expect(parsed.openclaw.events).toEqual(["command"]); expect(parsed.openclaw.requires.config).toEqual(["workspace.dir"]); diff --git a/src/hooks/frontmatter.ts b/src/hooks/frontmatter.ts index 9bad12508c..33a3445f6b 100644 --- a/src/hooks/frontmatter.ts +++ b/src/hooks/frontmatter.ts @@ -40,7 +40,7 @@ function parseInstallSpec(input: unknown): HookInstallSpec | undefined { } const spec: HookInstallSpec = { - kind: kind as HookInstallSpec["kind"], + kind: kind, }; if (typeof raw.id === "string") spec.id = raw.id; @@ -69,7 +69,7 @@ export function resolveOpenClawMetadata( const raw = getFrontmatterValue(frontmatter, "metadata"); if (!raw) return undefined; try { - const parsed = JSON5.parse(raw) as Record; + const parsed = JSON5.parse(raw); if (!parsed || typeof parsed !== "object") return undefined; const metadataRawCandidates = [MANIFEST_KEY, ...LEGACY_MANIFEST_KEYS]; let metadataRaw: unknown; diff --git a/src/hooks/gmail-setup-utils.ts b/src/hooks/gmail-setup-utils.ts index fe3663e3ef..179097ac57 100644 --- a/src/hooks/gmail-setup-utils.ts +++ b/src/hooks/gmail-setup-utils.ts @@ -249,7 +249,7 @@ export async function ensureTailscaleEndpoint(params: { try { parsed = JSON.parse(status.stdout) as { Self?: { DNSName?: string } }; } catch (err) { - throw new Error(formatJsonParseFailure(statusCommand, status, err)); + throw new Error(formatJsonParseFailure(statusCommand, status, err), { cause: err }); } const dnsName = parsed.Self?.DNSName?.replace(/\.$/, ""); if (!dnsName) { diff --git a/src/hooks/workspace.ts b/src/hooks/workspace.ts index 23caf53b38..84641abe13 100644 --- a/src/hooks/workspace.ts +++ b/src/hooks/workspace.ts @@ -83,7 +83,7 @@ function loadHookFromDir(params: { return { name, description, - source: params.source as Hook["source"], + source: params.source, pluginId: params.pluginId, filePath: hookMdPath, baseDir: params.hookDir, diff --git a/src/imessage/accounts.ts b/src/imessage/accounts.ts index 61feb9d3eb..07a06d7b9c 100644 --- a/src/imessage/accounts.ts +++ b/src/imessage/accounts.ts @@ -19,7 +19,7 @@ function listConfiguredAccountIds(cfg: OpenClawConfig): string[] { export function listIMessageAccountIds(cfg: OpenClawConfig): string[] { const ids = listConfiguredAccountIds(cfg); if (ids.length === 0) return [DEFAULT_ACCOUNT_ID]; - return ids.sort((a, b) => a.localeCompare(b)); + return ids.toSorted((a, b) => a.localeCompare(b)); } export function resolveDefaultIMessageAccountId(cfg: OpenClawConfig): string { diff --git a/src/imessage/send.ts b/src/imessage/send.ts index 30972ef093..a579385f6f 100644 --- a/src/imessage/send.ts +++ b/src/imessage/send.ts @@ -101,7 +101,7 @@ export async function sendMessageIMessage( const params: Record = { text: message, - service: (service || "auto") as IMessageService, + service: service || "auto", region, }; if (filePath) params.file = filePath; diff --git a/src/infra/backoff.ts b/src/infra/backoff.ts index f1d07b5799..215b66cb96 100644 --- a/src/infra/backoff.ts +++ b/src/infra/backoff.ts @@ -19,7 +19,7 @@ export async function sleepWithAbort(ms: number, abortSignal?: AbortSignal) { await delay(ms, undefined, { signal: abortSignal }); } catch (err) { if (abortSignal?.aborted) { - throw new Error("aborted"); + throw new Error("aborted", { cause: err }); } throw err; } diff --git a/src/infra/channel-summary.ts b/src/infra/channel-summary.ts index 4e416b1962..1d099868b5 100644 --- a/src/infra/channel-summary.ts +++ b/src/infra/channel-summary.ts @@ -174,7 +174,7 @@ export async function buildChannelSummary( }) : undefined; - const summaryRecord = summary as Record | undefined; + const summaryRecord = summary; const linked = summaryRecord && typeof summaryRecord.linked === "boolean" ? summaryRecord.linked : null; const configured = diff --git a/src/infra/dedupe.ts b/src/infra/dedupe.ts index ad49d65bd9..dc5a61d427 100644 --- a/src/infra/dedupe.ts +++ b/src/infra/dedupe.ts @@ -33,7 +33,7 @@ export function createDedupeCache(options: DedupeCacheOptions): DedupeCache { return; } while (cache.size > maxSize) { - const oldestKey = cache.keys().next().value as string | undefined; + const oldestKey = cache.keys().next().value; if (!oldestKey) break; cache.delete(oldestKey); } diff --git a/src/infra/device-auth-store.ts b/src/infra/device-auth-store.ts index 0f3515c030..a98c04fdfc 100644 --- a/src/infra/device-auth-store.ts +++ b/src/infra/device-auth-store.ts @@ -33,7 +33,7 @@ function normalizeScopes(scopes: string[] | undefined): string[] { const trimmed = scope.trim(); if (trimmed) out.add(trimmed); } - return [...out].sort(); + return [...out].toSorted(); } function readStore(filePath: string): DeviceAuthStore | null { diff --git a/src/infra/device-pairing.ts b/src/infra/device-pairing.ts index b190199eb1..e98cb7e70d 100644 --- a/src/infra/device-pairing.ts +++ b/src/infra/device-pairing.ts @@ -199,7 +199,7 @@ function normalizeScopes(scopes: string[] | undefined): string[] { const trimmed = scope.trim(); if (trimmed) out.add(trimmed); } - return [...out].sort(); + return [...out].toSorted(); } function scopesAllow(requested: string[], allowed: string[]): boolean { @@ -215,8 +215,8 @@ function newToken() { export async function listDevicePairing(baseDir?: string): Promise { const state = await loadState(baseDir); - const pending = Object.values(state.pendingById).sort((a, b) => b.ts - a.ts); - const paired = Object.values(state.pairedByDeviceId).sort( + const pending = Object.values(state.pendingById).toSorted((a, b) => b.ts - a.ts); + const paired = Object.values(state.pairedByDeviceId).toSorted( (a, b) => b.approvedAtMs - a.approvedAtMs, ); return { pending, paired }; @@ -373,7 +373,7 @@ export function summarizeDeviceTokens( revokedAtMs: token.revokedAtMs, lastUsedAtMs: token.lastUsedAtMs, })) - .sort((a, b) => a.role.localeCompare(b.role)); + .toSorted((a, b) => a.role.localeCompare(b.role)); return summaries.length > 0 ? summaries : undefined; } diff --git a/src/infra/fs-safe.ts b/src/infra/fs-safe.ts index 52a94b46f7..8e4f221980 100644 --- a/src/infra/fs-safe.ts +++ b/src/infra/fs-safe.ts @@ -55,7 +55,7 @@ export async function openFileWithinRoot(params: { } const supportsNoFollow = process.platform !== "win32" && "O_NOFOLLOW" in fsConstants; - const flags = fsConstants.O_RDONLY | (supportsNoFollow ? (fsConstants.O_NOFOLLOW as number) : 0); + const flags = fsConstants.O_RDONLY | (supportsNoFollow ? fsConstants.O_NOFOLLOW : 0); let handle: FileHandle; try { diff --git a/src/infra/net/ssrf.pinning.test.ts b/src/infra/net/ssrf.pinning.test.ts index 42bc54b661..2705fa1c96 100644 --- a/src/infra/net/ssrf.pinning.test.ts +++ b/src/infra/net/ssrf.pinning.test.ts @@ -16,7 +16,7 @@ describe("ssrf pinning", () => { const first = await new Promise<{ address: string; family?: number }>((resolve, reject) => { pinned.lookup("example.com", (err, address, family) => { if (err) reject(err); - else resolve({ address: address as string, family }); + else resolve({ address: address, family }); }); }); expect(first.address).toBe("93.184.216.34"); @@ -53,7 +53,7 @@ describe("ssrf pinning", () => { const result = await new Promise<{ address: string }>((resolve, reject) => { lookup("other.test", (err, address) => { if (err) reject(err); - else resolve({ address: address as string }); + else resolve({ address: address }); }); }); diff --git a/src/infra/node-pairing.ts b/src/infra/node-pairing.ts index f852ff4207..f6c86a492d 100644 --- a/src/infra/node-pairing.ts +++ b/src/infra/node-pairing.ts @@ -149,8 +149,8 @@ function newToken() { export async function listNodePairing(baseDir?: string): Promise { const state = await loadState(baseDir); - const pending = Object.values(state.pendingById).sort((a, b) => b.ts - a.ts); - const paired = Object.values(state.pairedByNodeId).sort( + const pending = Object.values(state.pendingById).toSorted((a, b) => b.ts - a.ts); + const paired = Object.values(state.pairedByNodeId).toSorted( (a, b) => b.approvedAtMs - a.approvedAtMs, ); return { pending, paired }; diff --git a/src/infra/outbound/channel-selection.ts b/src/infra/outbound/channel-selection.ts index 86f6439c60..da740491ed 100644 --- a/src/infra/outbound/channel-selection.ts +++ b/src/infra/outbound/channel-selection.ts @@ -46,7 +46,7 @@ export async function listConfiguredMessageChannels( for (const plugin of listChannelPlugins()) { if (!isKnownChannel(plugin.id)) continue; if (await isPluginConfigured(plugin, cfg)) { - channels.push(plugin.id as MessageChannelId); + channels.push(plugin.id); } } return channels; diff --git a/src/infra/outbound/message-action-runner.ts b/src/infra/outbound/message-action-runner.ts index 98beaa828e..51b08bcd23 100644 --- a/src/infra/outbound/message-action-runner.ts +++ b/src/infra/outbound/message-action-runner.ts @@ -591,7 +591,7 @@ async function handleBroadcastAction( } return { kind: "broadcast", - channel: (targetChannels[0] ?? "discord") as ChannelId, + channel: targetChannels[0] ?? "discord", action: "broadcast", handledBy: input.dryRun ? "dry-run" : "core", payload: { results }, diff --git a/src/infra/outbound/message.ts b/src/infra/outbound/message.ts index 12bf16a359..b71e5c7663 100644 --- a/src/infra/outbound/message.ts +++ b/src/infra/outbound/message.ts @@ -116,7 +116,7 @@ export async function sendMessage(params: MessageSendParams): Promise; + const outboundChannel = channel; const resolvedTarget = resolveOutboundTarget({ channel: outboundChannel, to: params.to, @@ -235,7 +235,7 @@ export async function sendPoll(params: MessagePollParams): Promise Object.assign({ date }, bucket)) - .sort((a, b) => a.date.localeCompare(b.date)); + .toSorted((a, b) => a.date.localeCompare(b.date)); return { updatedAt: Date.now(), diff --git a/src/infra/ssh-tunnel.ts b/src/infra/ssh-tunnel.ts index 399dc22e3f..35068d3dfd 100644 --- a/src/infra/ssh-tunnel.ts +++ b/src/infra/ssh-tunnel.ts @@ -184,7 +184,7 @@ export async function startSshPortForward(opts: { } catch (err) { await stop(); const suffix = stderr.length > 0 ? `\n${stderr.join("\n")}` : ""; - throw new Error(`${err instanceof Error ? err.message : String(err)}${suffix}`); + throw new Error(`${err instanceof Error ? err.message : String(err)}${suffix}`, { cause: err }); } return { diff --git a/src/infra/state-migrations.ts b/src/infra/state-migrations.ts index a53b18fce6..59f18971c6 100644 --- a/src/infra/state-migrations.ts +++ b/src/infra/state-migrations.ts @@ -411,7 +411,7 @@ export async function autoMigrateLegacyStateDir(params: { } catch (err) { try { if (process.platform === "win32") { - if (!legacyDir) throw new Error("Legacy state dir not found"); + if (!legacyDir) throw new Error("Legacy state dir not found", { cause: err }); fs.symlinkSync(targetDir, legacyDir, "junction"); changes.push(formatStateDirMigration(legacyDir, targetDir)); } else { @@ -419,7 +419,8 @@ export async function autoMigrateLegacyStateDir(params: { } } catch (fallbackErr) { try { - if (!legacyDir) throw new Error("Legacy state dir not found"); + if (!legacyDir) + throw new Error("Legacy state dir not found", { cause: err }, { cause: fallbackErr }); fs.renameSync(targetDir, legacyDir); warnings.push( `State dir migration rolled back (failed to link legacy path): ${String(fallbackErr)}`, diff --git a/src/infra/system-presence.ts b/src/infra/system-presence.ts index 0c9cb74cfb..1c84ec0e62 100644 --- a/src/infra/system-presence.ts +++ b/src/infra/system-presence.ts @@ -270,12 +270,12 @@ export function listSystemPresence(): SystemPresence[] { } // enforce max size (LRU by ts) if (entries.size > MAX_ENTRIES) { - const sorted = [...entries.entries()].sort((a, b) => a[1].ts - b[1].ts); + const sorted = [...entries.entries()].toSorted((a, b) => a[1].ts - b[1].ts); const toDrop = entries.size - MAX_ENTRIES; for (let i = 0; i < toDrop; i++) { entries.delete(sorted[i][0]); } } touchSelfPresence(); - return [...entries.values()].sort((a, b) => b.ts - a.ts); + return [...entries.values()].toSorted((a, b) => b.ts - a.ts); } diff --git a/src/infra/tailscale.ts b/src/infra/tailscale.ts index abbb561faf..203773352d 100644 --- a/src/infra/tailscale.ts +++ b/src/infra/tailscale.ts @@ -120,7 +120,7 @@ export async function getTailnetHostname(exec: typeof runExec = runExec, detecte typeof parsed.Self === "object" && parsed.Self !== null ? (parsed.Self as Record) : undefined; - const dns = typeof self?.DNSName === "string" ? (self.DNSName as string) : undefined; + const dns = typeof self?.DNSName === "string" ? self.DNSName : undefined; const ips = Array.isArray(self?.TailscaleIPs) ? ((parsed.Self as { TailscaleIPs?: string[] }).TailscaleIPs ?? []) : []; diff --git a/src/line/auto-reply-delivery.ts b/src/line/auto-reply-delivery.ts index ad4573ca1c..96b1efad7f 100644 --- a/src/line/auto-reply-delivery.ts +++ b/src/line/auto-reply-delivery.ts @@ -121,9 +121,7 @@ export async function deliverLineAutoReply(params: { : { text: "", flexMessages: [] }; for (const flexMsg of processed.flexMessages) { - richMessages.push( - deps.createFlexMessage(flexMsg.altText.slice(0, 400), flexMsg.contents as FlexContainer), - ); + richMessages.push(deps.createFlexMessage(flexMsg.altText.slice(0, 400), flexMsg.contents)); } const chunks = processed.text ? deps.chunkMarkdownText(processed.text, textLimit) : []; diff --git a/src/line/bot-message-context.ts b/src/line/bot-message-context.ts index 8a1c049d29..8e1e691f7f 100644 --- a/src/line/bot-message-context.ts +++ b/src/line/bot-message-context.ts @@ -102,10 +102,10 @@ function describeStickerKeywords(sticker: StickerEventMessage): string { function extractMessageText(message: MessageEvent["message"]): string { if (message.type === "text") { - return (message as TextEventMessage).text; + return message.text; } if (message.type === "location") { - const loc = message as LocationEventMessage; + const loc = message; return ( formatLocationText({ latitude: loc.latitude, @@ -116,7 +116,7 @@ function extractMessageText(message: MessageEvent["message"]): string { ); } if (message.type === "sticker") { - const sticker = message as StickerEventMessage; + const sticker = message; const packageName = STICKER_PACKAGES[sticker.packageId] ?? "sticker"; const keywords = describeStickerKeywords(sticker); @@ -222,7 +222,7 @@ export async function buildLineMessageContext(params: BuildLineMessageContextPar // Build location context if applicable let locationContext: ReturnType | undefined; if (message.type === "location") { - const loc = message as LocationEventMessage; + const loc = message; locationContext = toLocationContext({ latitude: loc.latitude, longitude: loc.longitude, diff --git a/src/line/flex-templates.ts b/src/line/flex-templates.ts index e0fe7e693c..077f835db5 100644 --- a/src/line/flex-templates.ts +++ b/src/line/flex-templates.ts @@ -252,7 +252,7 @@ export function createImageCard( }; if (body && bubble.body) { - (bubble.body as FlexBox).contents.push({ + bubble.body.contents.push({ type: "text", text: body, size: "md", diff --git a/src/line/reply-chunks.ts b/src/line/reply-chunks.ts index e4d5c4b9db..466a1be02d 100644 --- a/src/line/reply-chunks.ts +++ b/src/line/reply-chunks.ts @@ -48,7 +48,7 @@ export async function sendLineReplyChunks( if (hasQuickReplies && remaining.length === 0 && replyMessages.length > 0) { const lastIndex = replyMessages.length - 1; replyMessages[lastIndex] = params.createTextMessageWithQuickReplies( - replyBatch[lastIndex]!, + replyBatch[lastIndex], params.quickReplies!, ); } @@ -63,12 +63,12 @@ export async function sendLineReplyChunks( if (isLastChunk && hasQuickReplies) { await params.pushTextMessageWithQuickReplies( params.to, - remaining[i]!, + remaining[i], params.quickReplies!, { accountId: params.accountId }, ); } else { - await params.pushMessageLine(params.to, remaining[i]!, { + await params.pushMessageLine(params.to, remaining[i], { accountId: params.accountId, }); } @@ -86,12 +86,12 @@ export async function sendLineReplyChunks( if (isLastChunk && hasQuickReplies) { await params.pushTextMessageWithQuickReplies( params.to, - params.chunks[i]!, + params.chunks[i], params.quickReplies!, { accountId: params.accountId }, ); } else { - await params.pushMessageLine(params.to, params.chunks[i]!, { + await params.pushMessageLine(params.to, params.chunks[i], { accountId: params.accountId, }); } diff --git a/src/logging/config.ts b/src/logging/config.ts index b85a8336fb..23060ac68d 100644 --- a/src/logging/config.ts +++ b/src/logging/config.ts @@ -12,7 +12,7 @@ export function readLoggingConfig(): LoggingConfig | undefined { try { if (!fs.existsSync(configPath)) return undefined; const raw = fs.readFileSync(configPath, "utf-8"); - const parsed = json5.parse(raw) as Record; + const parsed = json5.parse(raw); const logging = parsed?.logging; if (!logging || typeof logging !== "object" || Array.isArray(logging)) return undefined; return logging as LoggingConfig; diff --git a/src/logging/subsystem.ts b/src/logging/subsystem.ts index a156fd8f33..5471033a5d 100644 --- a/src/logging/subsystem.ts +++ b/src/logging/subsystem.ts @@ -187,8 +187,8 @@ function logToFile( meta?: Record, ) { if (level === "silent") return; - const safeLevel = level as Exclude; - const method = (fileLogger as unknown as Record)[safeLevel] as unknown as + const safeLevel = level; + const method = (fileLogger as unknown as Record)[safeLevel] as | ((...args: unknown[]) => void) | undefined; if (typeof method !== "function") return; diff --git a/src/macos/gateway-daemon.ts b/src/macos/gateway-daemon.ts index 44bec8d8fe..9f8e3ad95f 100644 --- a/src/macos/gateway-daemon.ts +++ b/src/macos/gateway-daemon.ts @@ -65,9 +65,7 @@ async function main() { setConsoleTimestampPrefix(true); setVerbose(hasFlag(args, "--verbose")); - const wsLogRaw = (hasFlag(args, "--compact") ? "compact" : argValue(args, "--ws-log")) as - | string - | undefined; + const wsLogRaw = hasFlag(args, "--compact") ? "compact" : argValue(args, "--ws-log"); const wsLogStyle: GatewayWsLogStyle = wsLogRaw === "compact" ? "compact" : wsLogRaw === "full" ? "full" : "auto"; setGatewayWsLogStyle(wsLogStyle); diff --git a/src/markdown/frontmatter.test.ts b/src/markdown/frontmatter.test.ts index 462fcb28f5..033c1dded9 100644 --- a/src/markdown/frontmatter.test.ts +++ b/src/markdown/frontmatter.test.ts @@ -33,7 +33,7 @@ metadata: const result = parseFrontmatterBlock(content); expect(result.metadata).toBeDefined(); - const parsed = JSON5.parse(result.metadata ?? "") as { openclaw?: { emoji?: string } }; + const parsed = JSON5.parse(result.metadata ?? ""); expect(parsed.openclaw?.emoji).toBe("disk"); }); @@ -65,7 +65,7 @@ metadata: expect(result.enabled).toBe("true"); expect(result.retries).toBe("3"); expect(JSON.parse(result.tags ?? "[]")).toEqual(["alpha", "beta"]); - const parsed = JSON5.parse(result.metadata ?? "") as { openclaw?: { events?: string[] } }; + const parsed = JSON5.parse(result.metadata ?? ""); expect(parsed.openclaw?.events).toEqual(["command:new"]); }); diff --git a/src/markdown/ir.ts b/src/markdown/ir.ts index 186abeda0c..8a9155bf3d 100644 --- a/src/markdown/ir.ts +++ b/src/markdown/ir.ts @@ -655,7 +655,7 @@ function clampLinkSpans(spans: MarkdownLinkSpan[], maxLength: number): MarkdownL } function mergeStyleSpans(spans: MarkdownStyleSpan[]): MarkdownStyleSpan[] { - const sorted = [...spans].sort((a, b) => { + const sorted = [...spans].toSorted((a, b) => { if (a.start !== b.start) return a.start - b.start; if (a.end !== b.end) return a.end - b.end; return a.style.localeCompare(b.style); diff --git a/src/markdown/render.ts b/src/markdown/render.ts index 9793ab1675..dc53fa695a 100644 --- a/src/markdown/render.ts +++ b/src/markdown/render.ts @@ -34,7 +34,7 @@ const STYLE_RANK = new Map( ); function sortStyleSpans(spans: MarkdownStyleSpan[]): MarkdownStyleSpan[] { - return [...spans].sort((a, b) => { + return [...spans].toSorted((a, b) => { if (a.start !== b.start) return a.start - b.start; if (a.end !== b.end) return b.end - a.end; return (STYLE_RANK.get(a.style) ?? 0) - (STYLE_RANK.get(b.style) ?? 0); @@ -82,7 +82,7 @@ export function renderMarkdownWithMarkers(ir: MarkdownIR, options: RenderOptions } } - const points = [...boundaries].sort((a, b) => a - b); + const points = [...boundaries].toSorted((a, b) => a - b); // Unified stack for both styles and links, tracking close string and end position const stack: { close: string; end: number }[] = []; type OpeningItem = diff --git a/src/media-understanding/attachments.ts b/src/media-understanding/attachments.ts index 96ffef97a0..041190973c 100644 --- a/src/media-understanding/attachments.ts +++ b/src/media-understanding/attachments.ts @@ -145,7 +145,7 @@ function orderAttachments( prefer?: MediaUnderstandingAttachmentsConfig["prefer"], ): MediaAttachment[] { if (!prefer || prefer === "first") return attachments; - if (prefer === "last") return [...attachments].reverse(); + if (prefer === "last") return [...attachments].toReversed(); if (prefer === "path") { const withPath = attachments.filter((item) => item.path); const withoutPath = attachments.filter((item) => !item.path); diff --git a/src/media-understanding/providers/image.ts b/src/media-understanding/providers/image.ts index 031eb6abdd..cf3cc60bf0 100644 --- a/src/media-understanding/providers/image.ts +++ b/src/media-understanding/providers/image.ts @@ -54,10 +54,10 @@ export async function describeImageWithModel( }, ], }; - const message = (await complete(model, context, { + const message = await complete(model, context, { apiKey, maxTokens: params.maxTokens ?? 512, - })) as AssistantMessage; + }); const text = coerceImageAssistantText({ message, provider: model.provider, diff --git a/src/media/image-ops.ts b/src/media/image-ops.ts index 821b3bc7a5..db4f70753f 100644 --- a/src/media/image-ops.ts +++ b/src/media/image-ops.ts @@ -350,7 +350,7 @@ export async function hasAlphaChannel(buffer: Buffer): Promise { // Check if the image has an alpha channel // PNG color types with alpha: 4 (grayscale+alpha), 6 (RGBA) // Sharp reports this via 'channels' (4 = RGBA) or 'hasAlpha' - return meta.hasAlpha === true || meta.channels === 4; + return meta.hasAlpha || meta.channels === 4; } catch { return false; } diff --git a/src/media/store.redirect.test.ts b/src/media/store.redirect.test.ts index 0cab264e56..4a1ff25910 100644 --- a/src/media/store.redirect.test.ts +++ b/src/media/store.redirect.test.ts @@ -58,14 +58,14 @@ describe("media store redirects", () => { res.statusCode = 302; res.headers = { location: "https://example.com/final" }; setImmediate(() => { - cb(res as unknown as Parameters[0]); + cb(res as unknown); res.end(); }); } else { res.statusCode = 200; res.headers = { "content-type": "text/plain" }; setImmediate(() => { - cb(res as unknown as Parameters[0]); + cb(res as unknown); res.write("redirected"); res.end(); }); @@ -98,7 +98,7 @@ describe("media store redirects", () => { res.statusCode = 200; res.headers = {}; setImmediate(() => { - cb(res as unknown as Parameters[0]); + cb(res as unknown); const zip = new JSZip(); zip.file( "[Content_Types].xml", diff --git a/src/memory/embeddings.ts b/src/memory/embeddings.ts index 993fe81241..20f35c6482 100644 --- a/src/memory/embeddings.ts +++ b/src/memory/embeddings.ts @@ -95,14 +95,14 @@ async function createLocalEmbeddingProvider( embedQuery: async (text) => { const ctx = await ensureContext(); const embedding = await ctx.getEmbeddingFor(text); - return Array.from(embedding.vector) as number[]; + return Array.from(embedding.vector); }, embedBatch: async (texts) => { const ctx = await ensureContext(); const embeddings = await Promise.all( texts.map(async (text) => { const embedding = await ctx.getEmbeddingFor(text); - return Array.from(embedding.vector) as number[]; + return Array.from(embedding.vector); }), ); return embeddings; @@ -155,7 +155,7 @@ export async function createEmbeddingProvider( missingKeyErrors.push(message); continue; } - throw new Error(message); + throw new Error(message, { cause: err }); } } @@ -181,10 +181,14 @@ export async function createEmbeddingProvider( fallbackReason: reason, }; } catch (fallbackErr) { - throw new Error(`${reason}\n\nFallback to ${fallback} failed: ${formatError(fallbackErr)}`); + throw new Error( + `${reason}\n\nFallback to ${fallback} failed: ${formatError(fallbackErr)}`, + { cause: primaryErr }, + { cause: fallbackErr }, + ); } } - throw new Error(reason); + throw new Error(reason, { cause: primaryErr }); } } diff --git a/src/memory/hybrid.ts b/src/memory/hybrid.ts index 753748bf91..4837b1c476 100644 --- a/src/memory/hybrid.ts +++ b/src/memory/hybrid.ts @@ -107,5 +107,5 @@ export function mergeHybridResults(params: { }; }); - return merged.sort((a, b) => b.score - a.score); + return merged.toSorted((a, b) => b.score - a.score); } diff --git a/src/memory/manager-cache-key.ts b/src/memory/manager-cache-key.ts index d143a90577..1b03fcd674 100644 --- a/src/memory/manager-cache-key.ts +++ b/src/memory/manager-cache-key.ts @@ -12,8 +12,8 @@ export function computeMemoryManagerCacheKey(params: { const fingerprint = hashText( JSON.stringify({ enabled: settings.enabled, - sources: [...settings.sources].sort((a, b) => a.localeCompare(b)), - extraPaths: [...settings.extraPaths].sort((a, b) => a.localeCompare(b)), + sources: [...settings.sources].toSorted((a, b) => a.localeCompare(b)), + extraPaths: [...settings.extraPaths].toSorted((a, b) => a.localeCompare(b)), provider: settings.provider, model: settings.model, fallback: settings.fallback, diff --git a/src/memory/manager-search.ts b/src/memory/manager-search.ts index f065a96a52..f18be3faa1 100644 --- a/src/memory/manager-search.ts +++ b/src/memory/manager-search.ts @@ -79,7 +79,7 @@ export async function searchVector(params: { })) .filter((entry) => Number.isFinite(entry.score)); return scored - .sort((a, b) => b.score - a.score) + .toSorted((a, b) => b.score - a.score) .slice(0, params.limit) .map((entry) => ({ id: entry.chunk.id, diff --git a/src/memory/manager.ts b/src/memory/manager.ts index 1ad3378a48..c943183639 100644 --- a/src/memory/manager.ts +++ b/src/memory/manager.ts @@ -1730,7 +1730,7 @@ export class MemoryIndexManager { if (this.provider.id === "openai" && this.openAi) { const entries = Object.entries(this.openAi.headers) .filter(([key]) => key.toLowerCase() !== "authorization") - .sort(([a], [b]) => a.localeCompare(b)) + .toSorted(([a], [b]) => a.localeCompare(b)) .map(([key, value]) => [key, value]); return hashText( JSON.stringify({ @@ -1747,7 +1747,7 @@ export class MemoryIndexManager { const lower = key.toLowerCase(); return lower !== "authorization" && lower !== "x-goog-api-key"; }) - .sort(([a], [b]) => a.localeCompare(b)) + .toSorted(([a], [b]) => a.localeCompare(b)) .map(([key, value]) => [key, value]); return hashText( JSON.stringify({ diff --git a/src/memory/status-format.ts b/src/memory/status-format.ts index d0a85ec000..4d080cc958 100644 --- a/src/memory/status-format.ts +++ b/src/memory/status-format.ts @@ -4,7 +4,7 @@ export function resolveMemoryVectorState(vector: { enabled: boolean; available?: tone: Tone; state: "ready" | "unavailable" | "disabled" | "unknown"; } { - if (vector.enabled === false) return { tone: "muted", state: "disabled" }; + if (!vector.enabled) return { tone: "muted", state: "disabled" }; if (vector.available === true) return { tone: "ok", state: "ready" }; if (vector.available === false) return { tone: "warn", state: "unavailable" }; return { tone: "muted", state: "unknown" }; @@ -14,7 +14,7 @@ export function resolveMemoryFtsState(fts: { enabled: boolean; available: boolea tone: Tone; state: "ready" | "unavailable" | "disabled"; } { - if (fts.enabled === false) return { tone: "muted", state: "disabled" }; + if (!fts.enabled) return { tone: "muted", state: "disabled" }; return fts.available ? { tone: "ok", state: "ready" } : { tone: "warn", state: "unavailable" }; } diff --git a/src/node-host/runner.ts b/src/node-host/runner.ts index 51439e38a8..b07c52f7ff 100644 --- a/src/node-host/runner.ts +++ b/src/node-host/runner.ts @@ -569,10 +569,7 @@ export async function runNodeHost(opts: NodeHostRunOptions): Promise { }); const skillBins = new SkillBinsCache(async () => { - const res = (await client.request("skills.bins", {})) as - | { bins?: unknown[] } - | null - | undefined; + const res = await client.request("skills.bins", {}); const bins = Array.isArray(res?.bins) ? res.bins.map((bin) => String(bin)) : []; return bins; }); @@ -735,7 +732,7 @@ async function handleInvoke( : `HTTP ${response.status}`; throw new Error(message); } - const result = response.body as unknown; + const result = response.body; if (allowedProfiles.length > 0 && path === "/profiles") { const obj = typeof result === "object" && result !== null ? (result as Record) : {}; @@ -758,7 +755,9 @@ async function handleInvoke( } return file; } catch (err) { - throw new Error(`browser proxy file read failed for ${p}: ${String(err)}`); + throw new Error(`browser proxy file read failed for ${p}: ${String(err)}`, { + cause: err, + }); } }), ); diff --git a/src/pairing/pairing-store.ts b/src/pairing/pairing-store.ts index 5ae89dbd9e..d71a2be13c 100644 --- a/src/pairing/pairing-store.ts +++ b/src/pairing/pairing-store.ts @@ -166,7 +166,7 @@ function pruneExcessRequests(reqs: PairingRequest[], maxPending: number) { if (maxPending <= 0 || reqs.length <= maxPending) { return { requests: reqs, removed: false }; } - const sorted = reqs.slice().sort((a, b) => resolveLastSeenAt(a) - resolveLastSeenAt(b)); + const sorted = reqs.slice().toSorted((a, b) => resolveLastSeenAt(a) - resolveLastSeenAt(b)); return { requests: sorted.slice(-maxPending), removed: true }; } @@ -314,7 +314,7 @@ export async function listChannelPairingRequests( typeof r.createdAt === "string", ) .slice() - .sort((a, b) => a.createdAt.localeCompare(b.createdAt)); + .toSorted((a, b) => a.createdAt.localeCompare(b.createdAt)); }, ); } diff --git a/src/plugins/cli.ts b/src/plugins/cli.ts index 16a5c8d0da..0d1da1b0c1 100644 --- a/src/plugins/cli.ts +++ b/src/plugins/cli.ts @@ -45,8 +45,8 @@ export function registerPluginCliCommands(program: Command, cfg?: OpenClawConfig workspaceDir, logger, }); - if (result && typeof (result as Promise).then === "function") { - void (result as Promise).catch((err) => { + if (result && typeof result.then === "function") { + void result.catch((err) => { log.warn(`plugin CLI register failed (${entry.pluginId}): ${String(err)}`); }); } diff --git a/src/plugins/hooks.ts b/src/plugins/hooks.ts index 41fd501f7b..a7b5665011 100644 --- a/src/plugins/hooks.ts +++ b/src/plugins/hooks.ts @@ -84,7 +84,7 @@ function getHooksForName( ): PluginHookRegistration[] { return (registry.typedHooks as PluginHookRegistration[]) .filter((h) => h.hookName === hookName) - .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0)); + .toSorted((a, b) => (b.priority ?? 0) - (a.priority ?? 0)); } /** @@ -116,7 +116,7 @@ export function createHookRunner(registry: PluginRegistry, options: HookRunnerOp if (catchErrors) { logger?.error(msg); } else { - throw new Error(msg); + throw new Error(msg, { cause: err }); } } }); @@ -159,7 +159,7 @@ export function createHookRunner(registry: PluginRegistry, options: HookRunnerOp if (catchErrors) { logger?.error(msg); } else { - throw new Error(msg); + throw new Error(msg, { cause: err }); } } } @@ -353,7 +353,7 @@ export function createHookRunner(registry: PluginRegistry, options: HookRunnerOp if (catchErrors) { logger?.error(msg); } else { - throw new Error(msg); + throw new Error(msg, { cause: err }); } } } diff --git a/src/plugins/loader.ts b/src/plugins/loader.ts index 5062082c43..226765e024 100644 --- a/src/plugins/loader.ts +++ b/src/plugins/loader.ts @@ -405,7 +405,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi try { const result = register(api); - if (result && typeof (result as Promise).then === "function") { + if (result && typeof result.then === "function") { registry.diagnostics.push({ level: "warn", pluginId: record.id, diff --git a/src/plugins/runtime.ts b/src/plugins/runtime.ts index 33be2d85c1..cebd88d415 100644 --- a/src/plugins/runtime.ts +++ b/src/plugins/runtime.ts @@ -33,7 +33,7 @@ const state: RegistryState = (() => { key: null, }; } - return globalState[REGISTRY_STATE] as RegistryState; + return globalState[REGISTRY_STATE]; })(); export function setActivePluginRegistry(registry: PluginRegistry, cacheKey?: string) { diff --git a/src/plugins/schema-validator.ts b/src/plugins/schema-validator.ts index 97adb9b3b1..d3ebd6f24b 100644 --- a/src/plugins/schema-validator.ts +++ b/src/plugins/schema-validator.ts @@ -29,7 +29,7 @@ export function validateJsonSchemaValue(params: { }): { ok: true } | { ok: false; errors: string[] } { let cached = schemaCache.get(params.cacheKey); if (!cached || cached.schema !== params.schema) { - const validate = ajv.compile(params.schema) as ValidateFunction; + const validate = ajv.compile(params.schema); cached = { validate, schema: params.schema }; schemaCache.set(params.cacheKey, cached); } diff --git a/src/plugins/services.ts b/src/plugins/services.ts index 201d7ad655..63940f6747 100644 --- a/src/plugins/services.ts +++ b/src/plugins/services.ts @@ -57,7 +57,7 @@ export async function startPluginServices(params: { return { stop: async () => { - for (const entry of running.reverse()) { + for (const entry of running.toReversed()) { if (!entry.stop) continue; try { await entry.stop(); diff --git a/src/plugins/slots.ts b/src/plugins/slots.ts index 785bccbadd..8b13788ed9 100644 --- a/src/plugins/slots.ts +++ b/src/plugins/slots.ts @@ -76,7 +76,9 @@ export function applyExclusiveSlotSelection(params: { } if (disabledIds.length > 0) { - warnings.push(`Disabled other "${slotKey}" slot plugins: ${disabledIds.sort().join(", ")}.`); + warnings.push( + `Disabled other "${slotKey}" slot plugins: ${disabledIds.toSorted().join(", ")}.`, + ); } const changed = prevSlot !== params.selectedId || disabledIds.length > 0; diff --git a/src/routing/bindings.ts b/src/routing/bindings.ts index 873786b1cd..6c204b1d82 100644 --- a/src/routing/bindings.ts +++ b/src/routing/bindings.ts @@ -29,7 +29,7 @@ export function listBoundAccountIds(cfg: OpenClawConfig, channelId: string): str if (!accountId || accountId === "*") continue; ids.add(normalizeAccountId(accountId)); } - return Array.from(ids).sort((a, b) => a.localeCompare(b)); + return Array.from(ids).toSorted((a, b) => a.localeCompare(b)); } export function resolveDefaultAgentBoundAccountId( diff --git a/src/security/audit-extra.ts b/src/security/audit-extra.ts index 05c4ad872e..6be1719d7e 100644 --- a/src/security/audit-extra.ts +++ b/src/security/audit-extra.ts @@ -661,7 +661,7 @@ async function collectIncludePathsRecursive(params: { if (!rawText) continue; const nestedParsed = (() => { try { - return JSON5.parse(rawText) as unknown; + return JSON5.parse(rawText); } catch { return null; } diff --git a/src/security/audit.ts b/src/security/audit.ts index e983301e61..a4a1f76f35 100644 --- a/src/security/audit.ts +++ b/src/security/audit.ts @@ -264,7 +264,7 @@ function collectGatewayConfigFindings( const hasPassword = typeof auth.password === "string" && auth.password.trim().length > 0; const hasSharedSecret = (auth.mode === "token" && hasToken) || (auth.mode === "password" && hasPassword); - const hasTailscaleAuth = auth.allowTailscale === true && tailscaleMode === "serve"; + const hasTailscaleAuth = auth.allowTailscale && tailscaleMode === "serve"; const hasGatewayAuth = hasSharedSecret || hasTailscaleAuth; if (bind !== "loopback" && !hasSharedSecret) { @@ -918,7 +918,7 @@ export async function runSecurityAudit(opts: SecurityAuditOptions): Promise { const parsed = JSON.parse(await fs.readFile(configPath, "utf-8")) as Record; const channels = parsed.channels as Record>; - const whatsapp = channels.whatsapp as Record; + const whatsapp = channels.whatsapp; const accounts = whatsapp.accounts as Record>; expect(accounts.a1.groupPolicy).toBe("allowlist"); diff --git a/src/security/fix.ts b/src/security/fix.ts index 3febd89547..0ae281346e 100644 --- a/src/security/fix.ts +++ b/src/security/fix.ts @@ -330,7 +330,7 @@ async function collectIncludePathsRecursive(params: { if (!rawText) continue; const nestedParsed = (() => { try { - return JSON5.parse(rawText) as unknown; + return JSON5.parse(rawText); } catch { return null; } diff --git a/src/signal/accounts.ts b/src/signal/accounts.ts index 08f6f37476..d8396837c0 100644 --- a/src/signal/accounts.ts +++ b/src/signal/accounts.ts @@ -20,7 +20,7 @@ function listConfiguredAccountIds(cfg: OpenClawConfig): string[] { export function listSignalAccountIds(cfg: OpenClawConfig): string[] { const ids = listConfiguredAccountIds(cfg); if (ids.length === 0) return [DEFAULT_ACCOUNT_ID]; - return ids.sort((a, b) => a.localeCompare(b)); + return ids.toSorted((a, b) => a.localeCompare(b)); } export function resolveDefaultSignalAccountId(cfg: OpenClawConfig): string { diff --git a/src/signal/format.ts b/src/signal/format.ts index 127884e891..c99fa47f68 100644 --- a/src/signal/format.ts +++ b/src/signal/format.ts @@ -53,7 +53,7 @@ function mapStyle(style: MarkdownStyle): SignalTextStyle | null { } function mergeStyles(styles: SignalTextStyleRange[]): SignalTextStyleRange[] { - const sorted = [...styles].sort((a, b) => { + const sorted = [...styles].toSorted((a, b) => { if (a.start !== b.start) return a.start - b.start; if (a.length !== b.length) return a.length - b.length; return a.style.localeCompare(b.style); @@ -90,7 +90,7 @@ function applyInsertionsToStyles( insertions: Insertion[], ): SignalStyleSpan[] { if (insertions.length === 0) return spans; - const sortedInsertions = [...insertions].sort((a, b) => a.pos - b.pos); + const sortedInsertions = [...insertions].toSorted((a, b) => a.pos - b.pos); let updated = spans; for (const insertion of sortedInsertions) { @@ -137,7 +137,7 @@ function renderSignalText(ir: MarkdownIR): SignalFormattedText { const text = ir.text ?? ""; if (!text) return { text: "", styles: [] }; - const sortedLinks = [...ir.links].sort((a, b) => a.start - b.start); + const sortedLinks = [...ir.links].toSorted((a, b) => a.start - b.start); let out = ""; let cursor = 0; const insertions: Insertion[] = []; diff --git a/src/signal/probe.ts b/src/signal/probe.ts index b89f07561e..3892de3344 100644 --- a/src/signal/probe.ts +++ b/src/signal/probe.ts @@ -36,7 +36,7 @@ export async function probeSignal(baseUrl: string, timeoutMs: number): Promise("version", undefined, { + const version = await signalRpcRequest("version", undefined, { baseUrl, timeoutMs, }); diff --git a/src/slack/accounts.ts b/src/slack/accounts.ts index a2696a0641..e6e1e715b1 100644 --- a/src/slack/accounts.ts +++ b/src/slack/accounts.ts @@ -37,7 +37,7 @@ function listConfiguredAccountIds(cfg: OpenClawConfig): string[] { export function listSlackAccountIds(cfg: OpenClawConfig): string[] { const ids = listConfiguredAccountIds(cfg); if (ids.length === 0) return [DEFAULT_ACCOUNT_ID]; - return ids.sort((a, b) => a.localeCompare(b)); + return ids.toSorted((a, b) => a.localeCompare(b)); } export function resolveDefaultSlackAccountId(cfg: OpenClawConfig): string { diff --git a/src/slack/monitor/events/reactions.ts b/src/slack/monitor/events/reactions.ts index ec859051fd..942682040c 100644 --- a/src/slack/monitor/events/reactions.ts +++ b/src/slack/monitor/events/reactions.ts @@ -16,7 +16,7 @@ export function registerSlackReactionEvents(params: { ctx: SlackMonitorContext } if (!item || item.type !== "message") return; const channelInfo = item.channel ? await ctx.resolveChannelName(item.channel) : {}; - const channelType = channelInfo?.type as SlackMessageEvent["channel_type"]; + const channelType = channelInfo?.type; if ( !ctx.isChannelAllowed({ channelId: item.channel, diff --git a/src/slack/monitor/provider.ts b/src/slack/monitor/provider.ts index 366a32a34c..4ee36c83a9 100644 --- a/src/slack/monitor/provider.ts +++ b/src/slack/monitor/provider.ts @@ -7,7 +7,6 @@ import { DEFAULT_GROUP_HISTORY_LIMIT } from "../../auto-reply/reply/history.js"; import { mergeAllowlist, summarizeMapping } from "../../channels/allowlists/resolve-utils.js"; import { loadConfig } from "../../config/config.js"; import type { SessionScope } from "../../config/sessions.js"; -import type { DmPolicy, GroupPolicy } from "../../config/types.js"; import { warn } from "../../globals.js"; import { normalizeMainKey } from "../../routing/session-key.js"; import type { RuntimeEnv } from "../../runtime.js"; @@ -91,13 +90,13 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) { const dmConfig = slackCfg.dm; const dmEnabled = dmConfig?.enabled ?? true; - const dmPolicy = (dmConfig?.policy ?? "pairing") as DmPolicy; + const dmPolicy = dmConfig?.policy ?? "pairing"; let allowFrom = dmConfig?.allowFrom; const groupDmEnabled = dmConfig?.groupEnabled ?? false; const groupDmChannels = dmConfig?.groupChannels; let channelsConfig = slackCfg.channels; const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy; - const groupPolicy = (slackCfg.groupPolicy ?? defaultGroupPolicy ?? "open") as GroupPolicy; + const groupPolicy = slackCfg.groupPolicy ?? defaultGroupPolicy ?? "open"; if ( slackCfg.groupPolicy === undefined && slackCfg.channels === undefined && diff --git a/src/slack/monitor/slash.ts b/src/slack/monitor/slash.ts index 3b2c3680f8..34f8989c36 100644 --- a/src/slack/monitor/slash.ts +++ b/src/slack/monitor/slash.ts @@ -589,7 +589,7 @@ export function registerSlackMonitorSlashCommands(params: { await handleSlashCommand({ command: commandPayload, ack: async () => {}, - respond: respondFn as SlackCommandMiddlewareArgs["respond"], + respond: respondFn, prompt, commandArgs, commandDefinition: commandDefinition ?? undefined, diff --git a/src/slack/monitor/thread-resolution.ts b/src/slack/monitor/thread-resolution.ts index 3a9306144d..79c5ee3e1c 100644 --- a/src/slack/monitor/thread-resolution.ts +++ b/src/slack/monitor/thread-resolution.ts @@ -72,7 +72,7 @@ export function createSlackThreadTsResolver(params: { return; } while (cache.size > maxSize) { - const oldestKey = cache.keys().next().value as string | undefined; + const oldestKey = cache.keys().next().value; if (!oldestKey) break; cache.delete(oldestKey); } diff --git a/src/slack/resolve-users.ts b/src/slack/resolve-users.ts index a87057b5c6..8210445335 100644 --- a/src/slack/resolve-users.ts +++ b/src/slack/resolve-users.ts @@ -127,7 +127,7 @@ export async function resolveSlackUserAllowlist(params: { if (matches.length > 0) { const scored = matches .map((user) => ({ user, score: scoreSlackUser(user, parsed) })) - .sort((a, b) => b.score - a.score); + .toSorted((a, b) => b.score - a.score); const best = scored[0]?.user ?? matches[0]; results.push({ input, @@ -153,7 +153,7 @@ export async function resolveSlackUserAllowlist(params: { if (matches.length > 0) { const scored = matches .map((user) => ({ user, score: scoreSlackUser(user, parsed) })) - .sort((a, b) => b.score - a.score); + .toSorted((a, b) => b.score - a.score); const best = scored[0]?.user ?? matches[0]; results.push({ input, diff --git a/src/slack/scopes.ts b/src/slack/scopes.ts index 911f0f5b94..c5348c8d09 100644 --- a/src/slack/scopes.ts +++ b/src/slack/scopes.ts @@ -41,7 +41,7 @@ function collectScopes(value: unknown, into: string[]) { } function normalizeScopes(scopes: string[]) { - return Array.from(new Set(scopes.map((scope) => scope.trim()).filter(Boolean))).sort(); + return Array.from(new Set(scopes.map((scope) => scope.trim()).filter(Boolean))).toSorted(); } function extractScopes(payload: unknown): string[] { diff --git a/src/telegram/accounts.ts b/src/telegram/accounts.ts index 4c2eb69a6c..af5478584f 100644 --- a/src/telegram/accounts.ts +++ b/src/telegram/accounts.ts @@ -37,7 +37,7 @@ export function listTelegramAccountIds(cfg: OpenClawConfig): string[] { ); debugAccounts("listTelegramAccountIds", ids); if (ids.length === 0) return [DEFAULT_ACCOUNT_ID]; - return ids.sort((a, b) => a.localeCompare(b)); + return ids.toSorted((a, b) => a.localeCompare(b)); } export function resolveDefaultTelegramAccountId(cfg: OpenClawConfig): string { diff --git a/src/telegram/audit.ts b/src/telegram/audit.ts index eb49f2d991..b34901091b 100644 --- a/src/telegram/audit.ts +++ b/src/telegram/audit.ts @@ -59,8 +59,8 @@ export function collectTelegramUnmentionedGroupIds( for (const [key, value] of Object.entries(groups)) { if (key === "*") continue; if (!value || typeof value !== "object") continue; - if ((value as TelegramGroupConfig).enabled === false) continue; - if ((value as TelegramGroupConfig).requireMention !== false) continue; + if (value.enabled === false) continue; + if (value.requireMention !== false) continue; const id = String(key).trim(); if (!id) continue; if (/^-?\d+$/.test(id)) { @@ -102,9 +102,9 @@ export async function auditTelegramGroupMembership(params: { const url = `${base}/getChatMember?chat_id=${encodeURIComponent(chatId)}&user_id=${encodeURIComponent(String(params.botId))}`; const res = await fetchWithTimeout(url, params.timeoutMs, fetcher); const json = (await res.json()) as TelegramApiOk<{ status?: string }> | TelegramApiErr; - if (!res.ok || !isRecord(json) || json.ok !== true) { + if (!res.ok || !isRecord(json) || !json.ok) { const desc = - isRecord(json) && json.ok === false && typeof json.description === "string" + isRecord(json) && !json.ok && typeof json.description === "string" ? json.description : `getChatMember failed (${res.status})`; groups.push({ diff --git a/src/telegram/bot.ts b/src/telegram/bot.ts index fb0940d3bd..2baec9e1c4 100644 --- a/src/telegram/bot.ts +++ b/src/telegram/bot.ts @@ -182,7 +182,7 @@ export function createTelegramBot(opts: TelegramBotOptions) { const MAX_RAW_UPDATE_STRING = 500; const MAX_RAW_UPDATE_ARRAY = 20; const stringifyUpdate = (update: unknown) => { - const seen = new WeakSet(); + const seen = new WeakSet(); return JSON.stringify(update ?? null, (key, value) => { if (typeof value === "string" && value.length > MAX_RAW_UPDATE_STRING) { return `${value.slice(0, MAX_RAW_UPDATE_STRING)}...`; diff --git a/src/telegram/bot/helpers.ts b/src/telegram/bot/helpers.ts index cd57392c0c..c74724e500 100644 --- a/src/telegram/bot/helpers.ts +++ b/src/telegram/bot/helpers.ts @@ -140,7 +140,7 @@ export function expandTextLinks(text: string, entities?: TelegramTextLinkEntity[ (entity): entity is TelegramTextLinkEntity & { url: string } => entity.type === "text_link" && Boolean(entity.url), ) - .sort((a, b) => b.offset - a.offset); + .toSorted((a, b) => b.offset - a.offset); if (textLinks.length === 0) return text; diff --git a/src/telegram/monitor.ts b/src/telegram/monitor.ts index 2709b591b7..fa741e24d2 100644 --- a/src/telegram/monitor.ts +++ b/src/telegram/monitor.ts @@ -105,8 +105,7 @@ export async function monitorTelegramProvider(opts: MonitorTelegramOpts = {}) { } const proxyFetch = - opts.proxyFetch ?? - (account.config.proxy ? makeProxyFetch(account.config.proxy as string) : undefined); + opts.proxyFetch ?? (account.config.proxy ? makeProxyFetch(account.config.proxy) : undefined); let lastUpdateId = await readTelegramUpdateOffset({ accountId: account.accountId, diff --git a/src/telegram/sticker-cache.ts b/src/telegram/sticker-cache.ts index 278b944ae3..e97765f27c 100644 --- a/src/telegram/sticker-cache.ts +++ b/src/telegram/sticker-cache.ts @@ -108,7 +108,7 @@ export function searchStickers(query: string, limit = 10): CachedSticker[] { } return results - .sort((a, b) => b.score - a.score) + .toSorted((a, b) => b.score - a.score) .slice(0, limit) .map((r) => r.sticker); } @@ -130,7 +130,7 @@ export function getCacheStats(): { count: number; oldestAt?: string; newestAt?: if (stickers.length === 0) { return { count: 0 }; } - const sorted = [...stickers].sort( + const sorted = [...stickers].toSorted( (a, b) => new Date(a.cachedAt).getTime() - new Date(b.cachedAt).getTime(), ); return { diff --git a/src/telegram/webhook.ts b/src/telegram/webhook.ts index 1ae534ce21..6ba8d1c057 100644 --- a/src/telegram/webhook.ts +++ b/src/telegram/webhook.ts @@ -68,8 +68,8 @@ export async function startTelegramWebhook(opts: { logWebhookReceived({ channel: "telegram", updateType: "telegram-post" }); } const handled = handler(req, res); - if (handled && typeof (handled as Promise).catch === "function") { - void (handled as Promise) + if (handled && typeof handled.catch === "function") { + void handled .then(() => { if (diagnosticsEnabled) { logWebhookProcessed({ diff --git a/src/terminal/table.ts b/src/terminal/table.ts index 5a735a7490..d4c48351ac 100644 --- a/src/terminal/table.ts +++ b/src/terminal/table.ts @@ -246,13 +246,13 @@ export function renderTable(opts: RenderTableOptions): string { const flexOrder = columns .map((_c, i) => ({ i, w: widths[i] ?? 0 })) .filter(({ i }) => Boolean(columns[i]?.flex)) - .sort((a, b) => b.w - a.w) + .toSorted((a, b) => b.w - a.w) .map((x) => x.i); const nonFlexOrder = columns .map((_c, i) => ({ i, w: widths[i] ?? 0 })) .filter(({ i }) => !columns[i]?.flex) - .sort((a, b) => b.w - a.w) + .toSorted((a, b) => b.w - a.w) .map((x) => x.i); const shrink = (order: number[], minWidths: number[]) => { diff --git a/src/test-utils/ports.ts b/src/test-utils/ports.ts index 428eb3816e..1bd062c035 100644 --- a/src/test-utils/ports.ts +++ b/src/test-utils/ports.ts @@ -23,7 +23,7 @@ async function getOsFreePort(): Promise { reject(new Error("failed to acquire free port")); return; } - const port = (addr as AddressInfo).port; + const port = addr.port; server.close((err) => (err ? reject(err) : resolve(port))); }); }); diff --git a/src/tts/tts.ts b/src/tts/tts.ts index c4c9ce3071..6583c36fa2 100644 --- a/src/tts/tts.ts +++ b/src/tts/tts.ts @@ -904,7 +904,7 @@ async function summarizeText(params: { } catch (err) { const error = err as Error; if (error.name === "AbortError") { - throw new Error("Summarization timed out"); + throw new Error("Summarization timed out", { cause: err }); } throw err; } diff --git a/src/tui/components/custom-editor.ts b/src/tui/components/custom-editor.ts index 0abede6a01..ac87b39c97 100644 --- a/src/tui/components/custom-editor.ts +++ b/src/tui/components/custom-editor.ts @@ -19,9 +19,6 @@ export class CustomEditor extends Editor { onShiftTab?: () => void; onAltEnter?: () => void; - constructor(tui: TUI, theme: EditorTheme, options?: EditorOptions) { - super(tui, theme, options); - } handleInput(data: string): void { if (matchesKey(data, Key.alt("enter")) && this.onAltEnter) { this.onAltEnter(); diff --git a/src/tui/components/searchable-select-list.ts b/src/tui/components/searchable-select-list.ts index 54fc349184..70ba348374 100644 --- a/src/tui/components/searchable-select-list.ts +++ b/src/tui/components/searchable-select-list.ts @@ -136,7 +136,7 @@ export class SearchableSelectList implements Component { .filter((token) => token.length > 0); if (tokens.length === 0) return text; - const uniqueTokens = Array.from(new Set(tokens)).sort((a, b) => b.length - a.length); + const uniqueTokens = Array.from(new Set(tokens)).toSorted((a, b) => b.length - a.length); let result = text; for (const token of uniqueTokens) { const regex = this.getCachedRegex(token); diff --git a/src/types/pi-coding-agent.d.ts b/src/types/pi-coding-agent.d.ts index a96296a39c..b455056e60 100644 --- a/src/types/pi-coding-agent.d.ts +++ b/src/types/pi-coding-agent.d.ts @@ -6,5 +6,3 @@ declare module "@mariozechner/pi-coding-agent" { additionalExtensionPaths?: string[]; } } - -export {}; diff --git a/src/web/accounts.ts b/src/web/accounts.ts index c5010a741e..7179ea8e29 100644 --- a/src/web/accounts.ts +++ b/src/web/accounts.ts @@ -66,7 +66,7 @@ export function hasAnyWhatsAppAuth(cfg: OpenClawConfig): boolean { export function listWhatsAppAccountIds(cfg: OpenClawConfig): string[] { const ids = listConfiguredAccountIds(cfg); if (ids.length === 0) return [DEFAULT_ACCOUNT_ID]; - return ids.sort((a, b) => a.localeCompare(b)); + return ids.toSorted((a, b) => a.localeCompare(b)); } export function resolveDefaultWhatsAppAccountId(cfg: OpenClawConfig): string { diff --git a/src/web/auto-reply/monitor/echo.ts b/src/web/auto-reply/monitor/echo.ts index 1b64b11466..e0e6394ba4 100644 --- a/src/web/auto-reply/monitor/echo.ts +++ b/src/web/auto-reply/monitor/echo.ts @@ -24,7 +24,7 @@ export function createEchoTracker(params: { const trim = () => { while (recentlySent.size > maxItems) { - const firstKey = recentlySent.values().next().value as string | undefined; + const firstKey = recentlySent.values().next().value; if (!firstKey) break; recentlySent.delete(firstKey); } diff --git a/src/web/auto-reply/monitor/group-activation.ts b/src/web/auto-reply/monitor/group-activation.ts index 520671fec6..aeb16428fb 100644 --- a/src/web/auto-reply/monitor/group-activation.ts +++ b/src/web/auto-reply/monitor/group-activation.ts @@ -51,6 +51,6 @@ export function resolveGroupActivationFor(params: { const store = loadSessionStore(storePath); const entry = store[params.sessionKey]; const requireMention = resolveGroupRequireMentionFor(params.cfg, params.conversationId); - const defaultActivation = requireMention === false ? "always" : "mention"; + const defaultActivation = !requireMention ? "always" : "mention"; return normalizeGroupActivation(entry?.groupActivation) ?? defaultActivation; } diff --git a/src/web/inbound/extract.ts b/src/web/inbound/extract.ts index e48ac7be16..d794415f69 100644 --- a/src/web/inbound/extract.ts +++ b/src/web/inbound/extract.ts @@ -10,8 +10,8 @@ import { jidToE164 } from "../../utils.js"; import { parseVcard } from "../vcard.js"; function unwrapMessage(message: proto.IMessage | undefined): proto.IMessage | undefined { - const normalized = normalizeMessageContent(message as proto.IMessage | undefined); - return normalized as proto.IMessage | undefined; + const normalized = normalizeMessageContent(message); + return normalized; } function extractContextInfo(message: proto.IMessage | undefined): proto.IContextInfo | undefined { @@ -244,9 +244,7 @@ export function describeReplyContext(rawMessage: proto.IMessage | undefined): { const message = unwrapMessage(rawMessage); if (!message) return null; const contextInfo = extractContextInfo(message); - const quoted = normalizeMessageContent( - contextInfo?.quotedMessage as proto.IMessage | undefined, - ) as proto.IMessage | undefined; + const quoted = normalizeMessageContent(contextInfo?.quotedMessage as proto.IMessage | undefined); if (!quoted) return null; const location = extractLocationData(quoted); const locationText = location ? formatLocationText(location) : undefined; diff --git a/src/web/inbound/media.ts b/src/web/inbound/media.ts index 9e7d566f4a..952f2755da 100644 --- a/src/web/inbound/media.ts +++ b/src/web/inbound/media.ts @@ -4,8 +4,8 @@ import { logVerbose } from "../../globals.js"; import type { createWaSocket } from "../session.js"; function unwrapMessage(message: proto.IMessage | undefined): proto.IMessage | undefined { - const normalized = normalizeMessageContent(message as proto.IMessage | undefined); - return normalized as proto.IMessage | undefined; + const normalized = normalizeMessageContent(message); + return normalized; } export async function downloadInboundMedia( @@ -31,7 +31,7 @@ export async function downloadInboundMedia( return undefined; } try { - const buffer = (await downloadMediaMessage( + const buffer = await downloadMediaMessage( msg as WAMessage, "buffer", {}, @@ -39,7 +39,7 @@ export async function downloadInboundMedia( reuploadRequest: sock.updateMediaMessage, logger: sock.logger, }, - )) as Buffer; + ); return { buffer, mimetype }; } catch (err) { logVerbose(`downloadMediaMessage failed: ${String(err)}`); diff --git a/src/web/login.ts b/src/web/login.ts index 4b82422546..d4c502ca2c 100644 --- a/src/web/login.ts +++ b/src/web/login.ts @@ -60,11 +60,11 @@ export async function loginWeb( `WhatsApp reported the session is logged out. Cleared cached web session; please rerun ${formatCliCommand("openclaw channels login")} and scan the QR again.`, ), ); - throw new Error("Session logged out; cache cleared. Re-run login."); + throw new Error("Session logged out; cache cleared. Re-run login.", { cause: err }); } const formatted = formatError(err); console.error(danger(`WhatsApp Web connection ended before fully opening. ${formatted}`)); - throw new Error(formatted); + throw new Error(formatted, { cause: err }); } finally { // Let Baileys flush any final events before closing the socket. setTimeout(() => { diff --git a/src/web/media.ts b/src/web/media.ts index 72f6d34de5..a48f0d5d0b 100644 --- a/src/web/media.ts +++ b/src/web/media.ts @@ -250,7 +250,7 @@ export async function optimizeImageToJpeg( try { source = await convertHeicToJpeg(buffer); } catch (err) { - throw new Error(`HEIC image conversion failed: ${String(err)}`); + throw new Error(`HEIC image conversion failed: ${String(err)}`, { cause: err }); } } const sides = [2048, 1536, 1280, 1024, 800]; diff --git a/src/web/qr-image.ts b/src/web/qr-image.ts index 3a495ea369..82f60eac13 100644 --- a/src/web/qr-image.ts +++ b/src/web/qr-image.ts @@ -12,8 +12,8 @@ type QRCodeConstructor = new ( isDark: (row: number, col: number) => boolean; }; -const QRCode = QRCodeModule as unknown as QRCodeConstructor; -const QRErrorCorrectLevel = QRErrorCorrectLevelModule as Record; +const QRCode = QRCodeModule as QRCodeConstructor; +const QRErrorCorrectLevel = QRErrorCorrectLevelModule; function createQrMatrix(input: string) { const qr = new QRCode(-1, QRErrorCorrectLevel.L); diff --git a/src/web/session.ts b/src/web/session.ts index 9e877d8db1..0c8f76b728 100644 --- a/src/web/session.ts +++ b/src/web/session.ts @@ -193,7 +193,7 @@ export function getStatusCode(err: unknown) { function safeStringify(value: unknown, limit = 800): string { try { - const seen = new WeakSet(); + const seen = new WeakSet(); const raw = JSON.stringify( value, (_key, v) => { @@ -236,7 +236,7 @@ function extractBoomDetails(err: unknown): { typeof (output as { statusCode?: unknown }).statusCode === "number" ? ((output as { statusCode?: unknown }).statusCode as number) : typeof payload?.statusCode === "number" - ? (payload.statusCode as number) + ? payload.statusCode : undefined; const error = typeof payload?.error === "string" ? payload.error : undefined; const message = typeof payload?.message === "string" ? payload.message : undefined; diff --git a/src/wizard/clack-prompter.ts b/src/wizard/clack-prompter.ts index 2a66f0b098..469d80311a 100644 --- a/src/wizard/clack-prompter.ts +++ b/src/wizard/clack-prompter.ts @@ -22,7 +22,7 @@ function guardCancel(value: T | symbol): T { cancel(stylePromptTitle("Setup cancelled.") ?? "Setup cancelled."); throw new WizardCancelledError(); } - return value as T; + return value; } export function createClackPrompter(): WizardPrompter { diff --git a/src/wizard/onboarding.finalize.ts b/src/wizard/onboarding.finalize.ts index c5b01d6bf3..37bd01c098 100644 --- a/src/wizard/onboarding.finalize.ts +++ b/src/wizard/onboarding.finalize.ts @@ -111,12 +111,12 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption if (installDaemon) { const daemonRuntime = flow === "quickstart" - ? (DEFAULT_GATEWAY_DAEMON_RUNTIME as GatewayDaemonRuntime) - : ((await prompter.select({ + ? DEFAULT_GATEWAY_DAEMON_RUNTIME + : await prompter.select({ message: "Gateway service runtime", options: GATEWAY_DAEMON_RUNTIME_OPTIONS, initialValue: opts.daemonRuntime ?? DEFAULT_GATEWAY_DAEMON_RUNTIME, - })) as GatewayDaemonRuntime); + }); if (flow === "quickstart") { await prompter.note( "QuickStart uses Node for the Gateway service (stable + supported).", @@ -126,14 +126,14 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption const service = resolveGatewayService(); const loaded = await service.isLoaded({ env: process.env }); if (loaded) { - const action = (await prompter.select({ + const action = await prompter.select({ message: "Gateway service already installed", options: [ { value: "restart", label: "Restart" }, { value: "reinstall", label: "Reinstall" }, { value: "skip", label: "Skip" }, ], - })) as "restart" | "reinstall" | "skip"; + }); if (action === "restart") { await withWizardProgress( "Gateway service", @@ -158,7 +158,7 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption } } - if (!loaded || (loaded && (await service.isLoaded({ env: process.env })) === false)) { + if (!loaded || (loaded && !(await service.isLoaded({ env: process.env })))) { const progress = prompter.progress("Gateway service"); let installError: string | null = null; try { @@ -312,7 +312,7 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption "Token", ); - hatchChoice = (await prompter.select({ + hatchChoice = await prompter.select({ message: "How do you want to hatch your bot?", options: [ { value: "tui", label: "Hatch in TUI (recommended)" }, @@ -320,7 +320,7 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption { value: "later", label: "Do this later" }, ], initialValue: "tui", - })) as "tui" | "web" | "later"; + }); if (hatchChoice === "tui") { await runTui({ diff --git a/src/wizard/onboarding.gateway-config.ts b/src/wizard/onboarding.gateway-config.ts index 5b872b4df7..2870f9e24a 100644 --- a/src/wizard/onboarding.gateway-config.ts +++ b/src/wizard/onboarding.gateway-config.ts @@ -45,10 +45,10 @@ export async function configureGatewayForOnboarding( 10, ); - let bind = ( + let bind = flow === "quickstart" ? quickstartGateway.bind - : ((await prompter.select({ + : await prompter.select({ message: "Gateway bind", options: [ { value: "loopback", label: "Loopback (127.0.0.1)" }, @@ -57,8 +57,7 @@ export async function configureGatewayForOnboarding( { value: "auto", label: "Auto (Loopback → LAN)" }, { value: "custom", label: "Custom IP" }, ], - })) as "loopback" | "lan" | "auto" | "custom" | "tailnet") - ) as "loopback" | "lan" | "auto" | "custom" | "tailnet"; + }); let customBindHost = quickstartGateway.customBindHost; if (bind === "custom") { @@ -87,7 +86,7 @@ export async function configureGatewayForOnboarding( } } - let authMode = ( + let authMode = flow === "quickstart" ? quickstartGateway.authMode : ((await prompter.select({ @@ -101,13 +100,12 @@ export async function configureGatewayForOnboarding( { value: "password", label: "Password" }, ], initialValue: "token", - })) as GatewayAuthChoice) - ) as GatewayAuthChoice; + })) as GatewayAuthChoice); - const tailscaleMode = ( + const tailscaleMode = flow === "quickstart" ? quickstartGateway.tailscaleMode - : ((await prompter.select({ + : await prompter.select({ message: "Tailscale exposure", options: [ { value: "off", label: "Off", hint: "No Tailscale exposure" }, @@ -122,8 +120,7 @@ export async function configureGatewayForOnboarding( hint: "Public HTTPS via Tailscale Funnel (internet)", }, ], - })) as "off" | "serve" | "funnel") - ) as "off" | "serve" | "funnel"; + }); // Detect Tailscale binary before proceeding with serve/funnel setup. if (tailscaleMode !== "off") { diff --git a/src/wizard/onboarding.ts b/src/wizard/onboarding.ts index c2391261ad..5fa0131ae5 100644 --- a/src/wizard/onboarding.ts +++ b/src/wizard/onboarding.ts @@ -135,14 +135,14 @@ export async function runOnboardingWizard( : undefined; let flow: WizardFlow = explicitFlow ?? - ((await prompter.select({ + (await prompter.select({ message: "Onboarding mode", options: [ { value: "quickstart", label: "QuickStart", hint: quickstartHint }, { value: "advanced", label: "Manual", hint: manualHint }, ], initialValue: "quickstart", - })) as "quickstart" | "advanced"); + })); if (opts.mode === "remote" && flow === "quickstart") { await prompter.note( @@ -155,14 +155,14 @@ export async function runOnboardingWizard( if (snapshot.exists) { await prompter.note(summarizeExistingConfig(baseConfig), "Existing config detected"); - const action = (await prompter.select({ + const action = await prompter.select({ message: "Config handling", options: [ { value: "keep", label: "Use existing values" }, { value: "modify", label: "Update values" }, { value: "reset", label: "Reset" }, ], - })) as "keep" | "modify" | "reset"; + }); if (action === "reset") { const workspaceDefault = baseConfig.agents?.defaults?.workspace ?? DEFAULT_WORKSPACE; diff --git a/test/gateway.multi.e2e.test.ts b/test/gateway.multi.e2e.test.ts index 13e600bf12..6be021179e 100644 --- a/test/gateway.multi.e2e.test.ts +++ b/test/gateway.multi.e2e.test.ts @@ -225,6 +225,7 @@ const runCliJson = async (args: string[], env: NodeJS.ProcessEnv): Promise part.type === "timeZoneName") ?.value?.trim();