From f275db6974edefeb6e856505aeee5eec88f310be Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Jul 2026 16:32:52 -0400 Subject: [PATCH] refactor: remove dead split facades (#114726) * refactor: remove dead split facades * fix: update facade ownership references --- .../.generated/plugin-sdk-api-baseline.sha256 | 4 +- scripts/tool-display.ts | 2 +- .../agent-command.compaction-rotation.test.ts | 2 +- .../agent-command.live-model-switch.test.ts | 2 +- .../agent-tool-definition-adapter.test.ts | 2 +- ...ash-tools.exec-foreground-failures.test.ts | 2 +- ...sh-tools.exec-gateway-approval.e2e.test.ts | 2 +- src/agents/bash-tools.exec-run.ts | 3 ++ .../bash-tools.exec-task-wiring.test.ts | 2 +- .../bash-tools.exec.approval-id.test.ts | 2 +- .../bash-tools.exec.background-abort.test.ts | 4 +- src/agents/bash-tools.exec.path.test.ts | 4 +- .../bash-tools.exec.resolve-env-hook.test.ts | 4 +- .../bash-tools.exec.script-preflight.test.ts | 2 +- .../bash-tools.exec.security-floor.test.ts | 2 +- src/agents/bash-tools.exec.ts | 13 ----- src/agents/bash-tools.ts | 6 +-- .../compact.abort-signal.test.ts | 10 +++- src/agents/embedded-agent-runner/compact.ts | 8 ++- .../result-fallback-classifier.ts | 2 +- .../embedded-agent-runner/run-entry.test.ts | 2 +- src/agents/embedded-agent-runner/run-entry.ts | 3 +- src/agents/model-auth.ts | 46 ++--------------- src/agents/model-fallback.probe.test.ts | 4 +- .../model-fallback.run-embedded.e2e.test.ts | 4 +- src/agents/model-fallback.test-support.ts | 49 +----------------- src/agents/model-fallback.test.ts | 10 ++-- src/agents/model-fallback.ts | 21 -------- .../outcome-fallback-runtime-contract.test.ts | 2 +- src/agents/tools/image-tool.ts | 2 +- src/agents/tools/tool-runtime.helpers.ts | 2 +- .../reply/agent-runner-error-handler.ts | 2 +- .../agent-runner-execution.test-support.ts | 5 +- .../reply/agent-runner-failure-reply.ts | 2 +- .../reply/agent-runner.media-paths.test.ts | 5 +- .../agent-runner.misc.runreplyagent.test.ts | 5 +- .../agent-runner.runreplyagent.e2e.test.ts | 9 ++-- src/auto-reply/reply/model-selection.test.ts | 2 +- src/auto-reply/reply/reply-operation-abort.ts | 2 +- src/cli/capability-cli/image.ts | 2 +- .../cron-cli/cron-pagination.gateway.test.ts | 2 +- src/commands/doctor/cron/index.ts | 4 +- src/cron/active-jobs-manual-run.test.ts | 2 +- .../isolated-agent/run-execution.runtime.ts | 2 +- .../isolated-agent/run-fallback-policy.ts | 2 +- .../service.list-page-sort-guards.test.ts | 2 +- src/cron/service.removal-postcommit.test.ts | 3 +- .../service.startup-overflow-clobber.test.ts | 3 +- src/cron/service.ts | 51 ++++++++++--------- src/cron/service/ops.pacing.test.ts | 2 +- src/cron/service/ops.regression.test.ts | 4 +- .../service/ops.run-admission-cleanup.test.ts | 3 +- src/cron/service/ops.run-admission.test.ts | 5 +- src/cron/service/ops.test.ts | 5 +- src/cron/service/ops.ts | 22 -------- .../ops.update.disable-and-list.test.ts | 3 +- src/cron/service/timer.regression.test.ts | 3 +- .../trigger-handling-test-harness.ts | 2 +- test/scripts/audit-seams.test.ts | 6 ++- ui/src/pages/chat/chat-pane-board.test.ts | 2 +- ui/src/pages/chat/chat-pane-deps.ts | 14 ++--- ui/src/pages/chat/chat-pane-history.test.ts | 2 +- ui/src/pages/chat/chat-pane-identity.test.ts | 2 +- ui/src/pages/chat/chat-pane-lifecycle.test.ts | 2 +- .../pages/chat/chat-pane.message-cut.test.ts | 2 +- ui/src/pages/chat/chat-pane.test-support.ts | 2 +- ui/src/pages/chat/chat-pane.test.ts | 2 +- ui/src/pages/chat/chat-send.test.ts | 11 ++-- ui/src/pages/chat/chat-state.test.ts | 12 ++--- ui/src/pages/chat/chat-state.ts | 8 --- 70 files changed, 165 insertions(+), 277 deletions(-) delete mode 100644 src/agents/bash-tools.exec.ts delete mode 100644 src/agents/model-fallback.ts delete mode 100644 src/cron/service/ops.ts delete mode 100644 ui/src/pages/chat/chat-state.ts diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index 7acc5e103662..1ca8dcfda483 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -4,9 +4,9 @@ cbf4e2c3088f8886a7c9ea91325a66e0f0846cea21f0b2891f36399b4811306c module/account 8e985f345f21a1c9a2b0e94304aaaad6a326bec1c1ce3b26027d2862804a366e module/account-resolution e5e67ddf3cab38fcbf9220bc3160715897e2709d9a9ff6ff36f1ecc9453c2367 module/agent-config-primitives 74daa746deb548379d3f0d6eac3c4d082df1034c4360cc03bf51fee0f10a2e4d module/agent-harness -d3e25a2954f140ec892394123e9543878c00bd0fc99d09865d7bad2b264b289b module/agent-harness-runtime +060517a859a6354894bad581ca4a3e138b9a69c8cf8bae4656e0893c549df77b module/agent-harness-runtime 5168648cd946abad8a92822889f13ceacc87ed502314a66190d0b1eb8ebe76ea module/agent-media-payload -8b406b7a50b0b4f088be869ea6a899c0d33229a5c73d3f82bda76ce0be0941b0 module/agent-runtime +2dcb4d62d90e5d71594f6b843c97534509a154784e378fb1c75bd86b5122b710 module/agent-runtime 56b6d5fb6af3d95af1200065aca2e7d4f59e5fa59740505fe6ff433077ef6646 module/allow-from 55cea5390d68839ca7768b4a0cc570b17b65fa0fa3bc4d76130ef0f16cb79ede module/allowlist-config-edit 7ddd81bd5f55de9adf64bf4d92d012f24b37b6da0a72805a3a220d8feff24ca3 module/approval-auth-runtime diff --git a/scripts/tool-display.ts b/scripts/tool-display.ts index c95f24617c6f..09093c1f4ce5 100644 --- a/scripts/tool-display.ts +++ b/scripts/tool-display.ts @@ -14,7 +14,7 @@ const outputPath = path.join( ); const toolSources = [ path.join(repoRoot, "src/agents/apply-patch.ts"), - path.join(repoRoot, "src/agents/bash-tools.exec.ts"), + path.join(repoRoot, "src/agents/bash-tools.exec-run.ts"), path.join(repoRoot, "src/agents/bash-tools.process.ts"), path.join(repoRoot, "src/auto-reply/reply/acp-projector.ts"), ]; diff --git a/src/agents/agent-command.compaction-rotation.test.ts b/src/agents/agent-command.compaction-rotation.test.ts index 88c2559a0f83..a46941e9ae8a 100644 --- a/src/agents/agent-command.compaction-rotation.test.ts +++ b/src/agents/agent-command.compaction-rotation.test.ts @@ -142,7 +142,7 @@ vi.mock("./exec-defaults.js", () => ({ resolveNodeExecEligibility: () => ({ canExec: false }), })); -vi.mock("./model-fallback.js", () => ({ +vi.mock("./model-fallback-runner.js", () => ({ runWithModelFallback: async (params: { provider: string; model: string; diff --git a/src/agents/agent-command.live-model-switch.test.ts b/src/agents/agent-command.live-model-switch.test.ts index 6bf30767e935..5ce6a15032db 100644 --- a/src/agents/agent-command.live-model-switch.test.ts +++ b/src/agents/agent-command.live-model-switch.test.ts @@ -110,7 +110,7 @@ const state = vi.hoisted(() => ({ trajectoryRecorderParamsMock: vi.fn(), })); -vi.mock("./model-fallback.js", () => ({ +vi.mock("./model-fallback-runner.js", () => ({ runWithModelFallback: (params: unknown) => state.runWithModelFallbackMock(params), })); diff --git a/src/agents/agent-tool-definition-adapter.test.ts b/src/agents/agent-tool-definition-adapter.test.ts index 6a2ffe1b89c5..9a0279c95152 100644 --- a/src/agents/agent-tool-definition-adapter.test.ts +++ b/src/agents/agent-tool-definition-adapter.test.ts @@ -17,7 +17,7 @@ import { toToolDefinitions, } from "./agent-tool-definition-adapter.js"; import { wrapToolWithBeforeToolCallHook } from "./agent-tools.before-tool-call.js"; -import { createExecTool } from "./bash-tools.exec.js"; +import { createExecTool } from "./bash-tools.exec-run.js"; import type { ClientToolDefinition } from "./embedded-agent-runner/run/params.js"; type ToolExecute = ReturnType[number]["execute"]; diff --git a/src/agents/bash-tools.exec-foreground-failures.test.ts b/src/agents/bash-tools.exec-foreground-failures.test.ts index a09c0ab28a65..7e58f5fea868 100644 --- a/src/agents/bash-tools.exec-foreground-failures.test.ts +++ b/src/agents/bash-tools.exec-foreground-failures.test.ts @@ -12,7 +12,7 @@ import type { ProcessSupervisor } from "../process/supervisor/index.js"; import type { SpawnInput } from "../process/supervisor/types.js"; import { captureEnv } from "../test-utils/env.js"; import { resetProcessRegistryForTests } from "./bash-process-registry.test-support.js"; -import { createExecTool } from "./bash-tools.exec.js"; +import { createExecTool } from "./bash-tools.exec-run.js"; import type { BashSandboxConfig } from "./bash-tools.shared.js"; import { getBashShellConfig } from "./shell-utils.js"; diff --git a/src/agents/bash-tools.exec-gateway-approval.e2e.test.ts b/src/agents/bash-tools.exec-gateway-approval.e2e.test.ts index aa3da8c24fb9..860af9ed2ad5 100644 --- a/src/agents/bash-tools.exec-gateway-approval.e2e.test.ts +++ b/src/agents/bash-tools.exec-gateway-approval.e2e.test.ts @@ -19,8 +19,8 @@ import { import { captureEnv, setTestEnvValue } from "../test-utils/env.js"; import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js"; import { withTimeout } from "../utils/with-timeout.js"; +import { createExecTool } from "./bash-tools.exec-run.js"; import type { ExecApprovalFollowupOutcome } from "./bash-tools.exec-types.js"; -import { createExecTool } from "./bash-tools.exec.js"; const TEST_ENV_KEYS = [ "HOME", diff --git a/src/agents/bash-tools.exec-run.ts b/src/agents/bash-tools.exec-run.ts index ecadf582adf8..c60f3af06d03 100644 --- a/src/agents/bash-tools.exec-run.ts +++ b/src/agents/bash-tools.exec-run.ts @@ -668,3 +668,6 @@ export function createExecTool( }, }; } + +/** Default exec tool instance used by agent tool registries. */ +export const execTool = createExecTool(); diff --git a/src/agents/bash-tools.exec-task-wiring.test.ts b/src/agents/bash-tools.exec-task-wiring.test.ts index 4d684d627038..531e397692be 100644 --- a/src/agents/bash-tools.exec-task-wiring.test.ts +++ b/src/agents/bash-tools.exec-task-wiring.test.ts @@ -7,7 +7,7 @@ const taskTracking = vi.hoisted(() => ({ vi.mock("./bash-tools.exec-task-tracking.js", () => taskTracking); -import { createExecTool } from "./bash-tools.exec.js"; +import { createExecTool } from "./bash-tools.exec-run.js"; describe("exec background task wiring", () => { beforeEach(() => { diff --git a/src/agents/bash-tools.exec.approval-id.test.ts b/src/agents/bash-tools.exec.approval-id.test.ts index 7bb849425e46..b2cbadb61600 100644 --- a/src/agents/bash-tools.exec.approval-id.test.ts +++ b/src/agents/bash-tools.exec.approval-id.test.ts @@ -17,7 +17,7 @@ import { sendMessage } from "../infra/outbound/message.js"; import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js"; import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js"; import { buildSystemRunPreparePayload } from "../test-utils/system-run-prepare-payload.js"; -import { createExecTool as createExecToolImpl } from "./bash-tools.exec.js"; +import { createExecTool as createExecToolImpl } from "./bash-tools.exec-run.js"; import { callGatewayTool } from "./tools/gateway.js"; const createExecTool = ( diff --git a/src/agents/bash-tools.exec.background-abort.test.ts b/src/agents/bash-tools.exec.background-abort.test.ts index d31a50169ade..78317dd5d63b 100644 --- a/src/agents/bash-tools.exec.background-abort.test.ts +++ b/src/agents/bash-tools.exec.background-abort.test.ts @@ -96,7 +96,7 @@ const TEST_EXEC_DEFAULTS = { ask: "off" as const, }; -let createExecTool: typeof import("./bash-tools.exec.js").createExecTool; +let createExecTool: typeof import("./bash-tools.exec-run.js").createExecTool; let getFinishedSession: typeof import("./bash-process-registry.js").getFinishedSession; let getSession: typeof import("./bash-process-registry.js").getSession; let resetProcessRegistryForTests: typeof import("./bash-process-registry.test-support.js").resetProcessRegistryForTests; @@ -107,7 +107,7 @@ const createTestExecTool = ( ): ReturnType => createExecTool({ ...TEST_EXEC_DEFAULTS, ...defaults }); beforeAll(async () => { - ({ createExecTool } = await import("./bash-tools.exec.js")); + ({ createExecTool } = await import("./bash-tools.exec-run.js")); ({ getFinishedSession, getSession } = await import("./bash-process-registry.js")); ({ resetProcessRegistryForTests } = await import("./bash-process-registry.test-support.js")); }); diff --git a/src/agents/bash-tools.exec.path.test.ts b/src/agents/bash-tools.exec.path.test.ts index 6b1b188db9f0..e2d06958851a 100644 --- a/src/agents/bash-tools.exec.path.test.ts +++ b/src/agents/bash-tools.exec.path.test.ts @@ -115,7 +115,7 @@ vi.mock("../process/supervisor/index.js", () => ({ }), })); -let createExecTool: typeof import("./bash-tools.exec.js").createExecTool; +let createExecTool: typeof import("./bash-tools.exec-run.js").createExecTool; function createExecApprovals(): ExecApprovalsResolved { return { @@ -175,7 +175,7 @@ describe("exec PATH login shell merge", () => { let envSnapshot: ReturnType; beforeAll(async () => { - ({ createExecTool } = await import("./bash-tools.exec.js")); + ({ createExecTool } = await import("./bash-tools.exec-run.js")); }); afterAll(() => { diff --git a/src/agents/bash-tools.exec.resolve-env-hook.test.ts b/src/agents/bash-tools.exec.resolve-env-hook.test.ts index 26fb6de30eaf..0898d8351c2c 100644 --- a/src/agents/bash-tools.exec.resolve-env-hook.test.ts +++ b/src/agents/bash-tools.exec.resolve-env-hook.test.ts @@ -115,7 +115,7 @@ vi.mock("../process/supervisor/index.js", () => ({ }), })); -let createExecTool: typeof import("./bash-tools.exec.js").createExecTool; +let createExecTool: typeof import("./bash-tools.exec-run.js").createExecTool; let toToolDefinitions: typeof import("./agent-tool-definition-adapter.js").toToolDefinitions; let createOpenClawCodingTools: typeof import("./agent-tools.js").createOpenClawCodingTools; const testExtensionContext = {} as ExtensionContext; @@ -129,7 +129,7 @@ function installResolveExecEnvHook(result: Record) { describe("exec resolve_exec_env hook wiring", () => { beforeAll(async () => { - ({ createExecTool } = await import("./bash-tools.exec.js")); + ({ createExecTool } = await import("./bash-tools.exec-run.js")); ({ toToolDefinitions } = await import("./agent-tool-definition-adapter.js")); ({ createOpenClawCodingTools } = await import("./agent-tools.js")); }); diff --git a/src/agents/bash-tools.exec.script-preflight.test.ts b/src/agents/bash-tools.exec.script-preflight.test.ts index 6f250543f4e7..0ec56ad9c72c 100644 --- a/src/agents/bash-tools.exec.script-preflight.test.ts +++ b/src/agents/bash-tools.exec.script-preflight.test.ts @@ -10,7 +10,7 @@ import { __setFsSafeTestHooksForTest } from "@openclaw/fs-safe/test-hooks"; import { afterEach, describe, expect, it, vi } from "vitest"; import { detectUnsafeExecControlShellCommand } from "../infra/exec-control-command-guard.js"; import { withTempDir } from "../test-utils/temp-dir.js"; -import { createExecTool } from "./bash-tools.exec.js"; +import { createExecTool } from "./bash-tools.exec-run.js"; vi.mock("./bash-tools.exec-host-gateway.js", () => ({ processGatewayAllowlist: async () => ({ allowWithoutEnforcedCommand: true }), diff --git a/src/agents/bash-tools.exec.security-floor.test.ts b/src/agents/bash-tools.exec.security-floor.test.ts index 959ad278e413..1d5590ac80bc 100644 --- a/src/agents/bash-tools.exec.security-floor.test.ts +++ b/src/agents/bash-tools.exec.security-floor.test.ts @@ -12,7 +12,7 @@ import type { ExecAutoReviewer } from "../infra/exec-auto-review.js"; import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js"; import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js"; import { resetProcessRegistryForTests } from "./bash-process-registry.test-support.js"; -import { createExecTool as createExecToolImpl } from "./bash-tools.exec.js"; +import { createExecTool as createExecToolImpl } from "./bash-tools.exec-run.js"; import { callGatewayTool } from "./tools/gateway.js"; const createExecTool = ( diff --git a/src/agents/bash-tools.exec.ts b/src/agents/bash-tools.exec.ts deleted file mode 100644 index 62e68e77caaa..000000000000 --- a/src/agents/bash-tools.exec.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** Public facade for the exec tool factory and default instance. */ -import { createExecTool } from "./bash-tools.exec-run.js"; - -export type { BashSandboxConfig } from "./bash-tools.shared.js"; -export type { - ExecElevatedDefaults, - ExecToolDefaults, - ExecToolDetails, -} from "./bash-tools.exec-types.js"; -export { createExecTool }; - -/** Default exec tool instance used by agent tool registries. */ -export const execTool = createExecTool(); diff --git a/src/agents/bash-tools.ts b/src/agents/bash-tools.ts index fce10cc04683..f7f923a58760 100644 --- a/src/agents/bash-tools.ts +++ b/src/agents/bash-tools.ts @@ -4,12 +4,12 @@ * modules to keep host policy seams local. */ export type { - BashSandboxConfig, ExecElevatedDefaults, ExecToolDefaults, ExecToolDetails, -} from "./bash-tools.exec.js"; +} from "./bash-tools.exec-types.js"; +export type { BashSandboxConfig } from "./bash-tools.shared.js"; export { describeExecTool, describeProcessTool } from "./bash-tools.descriptions.js"; -export { createExecTool, execTool } from "./bash-tools.exec.js"; +export { createExecTool, execTool } from "./bash-tools.exec-run.js"; export type { ProcessToolDefaults } from "./bash-tools.process.js"; export { createProcessTool, processTool } from "./bash-tools.process.js"; diff --git a/src/agents/embedded-agent-runner/compact.abort-signal.test.ts b/src/agents/embedded-agent-runner/compact.abort-signal.test.ts index 63d65d9858e1..91e8b1831a48 100644 --- a/src/agents/embedded-agent-runner/compact.abort-signal.test.ts +++ b/src/agents/embedded-agent-runner/compact.abort-signal.test.ts @@ -1,16 +1,22 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; -vi.mock("../model-fallback.js", () => ({ +vi.mock("../model-fallback-candidates.js", () => ({ resolveModelCandidateChain: (params: { provider: string; model: string }) => [ { provider: params.provider, model: params.model }, ], +})); + +vi.mock("../model-fallback-runner.js", () => ({ runWithModelFallback: vi.fn(async (params: Record) => ({ result: { ok: true, compacted: false, reason: "no-op" }, provider: params.provider, model: params.model, attempts: [], })), +})); + +vi.mock("../model-fallback-attempt.js", () => ({ isFallbackSummaryError: () => false, })); @@ -36,7 +42,7 @@ vi.mock("../prepared-model-runtime.js", () => ({ ), })); -import { runWithModelFallback } from "../model-fallback.js"; +import { runWithModelFallback } from "../model-fallback-runner.js"; import { compactEmbeddedAgentSessionDirect } from "./compact.js"; const runMock = vi.mocked(runWithModelFallback); diff --git a/src/agents/embedded-agent-runner/compact.ts b/src/agents/embedded-agent-runner/compact.ts index 4c438f0c4f26..733457c93650 100644 --- a/src/agents/embedded-agent-runner/compact.ts +++ b/src/agents/embedded-agent-runner/compact.ts @@ -16,11 +16,9 @@ import { hasMeaningfulConversationContent } from "../compaction-real-conversatio import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../defaults.js"; import { coerceToFailoverError } from "../failover-error.js"; import { ensureSelectedAgentHarnessPlugin } from "../harness/runtime-plugin.js"; -import { - isFallbackSummaryError, - resolveModelCandidateChain, - runWithModelFallback, -} from "../model-fallback.js"; +import { isFallbackSummaryError } from "../model-fallback-attempt.js"; +import { resolveModelCandidateChain } from "../model-fallback-candidates.js"; +import { runWithModelFallback } from "../model-fallback-runner.js"; import { acquireAgentRunPreparedModelRuntime } from "../prepared-model-runtime.js"; import { applyAgentRunSessionTargetIdentity, diff --git a/src/agents/embedded-agent-runner/result-fallback-classifier.ts b/src/agents/embedded-agent-runner/result-fallback-classifier.ts index 3bc2c30aed2d..34b009ebaf24 100644 --- a/src/agents/embedded-agent-runner/result-fallback-classifier.ts +++ b/src/agents/embedded-agent-runner/result-fallback-classifier.ts @@ -6,7 +6,7 @@ import { isSilentReplyPayloadText } from "../../auto-reply/tokens.js"; import { classifyFailoverReason } from "../embedded-agent-helpers/errors.js"; import type { FailoverReason } from "../embedded-agent-helpers/types.js"; import { isGpt5ModelId } from "../gpt5-prompt-overlay.js"; -import type { ModelFallbackResultClassification } from "../model-fallback.js"; +import type { ModelFallbackResultClassification } from "../model-fallback-attempt.js"; import { hasCommittedOutboundDeliveryEvidence, hasVisibleAgentPayload, diff --git a/src/agents/embedded-agent-runner/run-entry.test.ts b/src/agents/embedded-agent-runner/run-entry.test.ts index 8451e8df86c1..2a55c7c8f88b 100644 --- a/src/agents/embedded-agent-runner/run-entry.test.ts +++ b/src/agents/embedded-agent-runner/run-entry.test.ts @@ -38,7 +38,7 @@ const state = vi.hoisted(() => ({ ensureSelectedAgentHarnessPlugin: vi.fn(async (_params: unknown) => undefined), })); -vi.mock("../model-fallback.js", () => ({ +vi.mock("../model-fallback-runner.js", () => ({ runWithModelFallback: (params: FallbackRunnerParams) => state.runWithModelFallback(params), })); diff --git a/src/agents/embedded-agent-runner/run-entry.ts b/src/agents/embedded-agent-runner/run-entry.ts index 6db11d6c6851..864cf354eb7c 100644 --- a/src/agents/embedded-agent-runner/run-entry.ts +++ b/src/agents/embedded-agent-runner/run-entry.ts @@ -1,8 +1,9 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { buildAgentRunTerminalOutcome } from "../agent-run-terminal-outcome.js"; import { ensureSelectedAgentHarnessPlugin } from "../harness/runtime-plugin.js"; +import type { ModelFallbackResultClassification } from "../model-fallback-attempt.js"; import type { ModelFallbackStepFields } from "../model-fallback-observation.js"; -import { runWithModelFallback, type ModelFallbackResultClassification } from "../model-fallback.js"; +import { runWithModelFallback } from "../model-fallback-runner.js"; import type { FallbackAttempt, ModelFallbackRouteResolution } from "../model-fallback.types.js"; import type { ModelManifestNormalizationContext } from "../model-ref-shared.js"; import { resolveAgentRunAbortLifecycleFields } from "../run-termination.js"; diff --git a/src/agents/model-auth.ts b/src/agents/model-auth.ts index 34f64adb7822..eda5d0c96a67 100644 --- a/src/agents/model-auth.ts +++ b/src/agents/model-auth.ts @@ -1,17 +1,4 @@ -/** - * Shared model-auth facade. Implementation lives in responsibility-focused modules. - */ -import type { OpenClawConfig } from "../config/types.openclaw.js"; -import type { AuthProfileStore } from "./auth-profiles.js"; -import { - resolveModelAuthMode as resolveModelAuthModeImpl, - type ModelAuthMode, -} from "./model-auth-model.js"; -import { - resolveApiKeyForProvider as resolveApiKeyForProviderImpl, - type ProviderCredentialPrecedence, -} from "./model-auth-provider.js"; -import type { ResolvedProviderAuth } from "./model-auth-runtime-shared.js"; +/** Shared model-auth facade for runtime, Plugin SDK, and test import boundaries. */ export { ensureAuthProfileStore, @@ -27,6 +14,7 @@ export { applySecretRefHeaderSentinels, getApiKeyForModel, hasAvailableAuthForProvider, + resolveModelAuthMode, } from "./model-auth-model.js"; export type { ModelAuthMode } from "./model-auth-model.js"; export { @@ -39,6 +27,7 @@ export { shouldPreferExplicitConfigApiKeyAuth, } from "./model-auth-provider-config.js"; export type { ProviderEntryApiKeyBindingResolution } from "./model-auth-provider-config.js"; +export { resolveApiKeyForProvider } from "./model-auth-provider.js"; export type { ProviderCredentialPrecedence } from "./model-auth-provider.js"; export { createRuntimeProviderAuthLookup, @@ -56,32 +45,3 @@ export { resolveAwsSdkEnvVarName, } from "./model-auth-runtime-shared.js"; export type { ResolvedProviderAuth } from "./model-auth-runtime-shared.js"; - -export async function resolveApiKeyForProvider(params: { - provider: string; - cfg?: OpenClawConfig; - profileId?: string; - preferredProfile?: string; - store?: AuthProfileStore; - agentDir?: string; - workspaceDir?: string; - lockedProfile?: boolean; - forceRefresh?: boolean; - credentialPrecedence?: ProviderCredentialPrecedence; - allowAuthProfileFallback?: boolean; - skipSetupProviderFallback?: boolean; - modelId?: string; - modelApi?: string; - secretSentinels?: boolean; -}): Promise { - return resolveApiKeyForProviderImpl(params); -} - -export function resolveModelAuthMode( - provider?: string, - cfg?: OpenClawConfig, - store?: AuthProfileStore, - options?: { workspaceDir?: string }, -): ModelAuthMode | undefined { - return resolveModelAuthModeImpl(provider, cfg, store, options); -} diff --git a/src/agents/model-fallback.probe.test.ts b/src/agents/model-fallback.probe.test.ts index b13d9335e71d..9e58b06223fb 100644 --- a/src/agents/model-fallback.probe.test.ts +++ b/src/agents/model-fallback.probe.test.ts @@ -111,7 +111,7 @@ type AuthProfilesSourceCheckModule = typeof import("./auth-profiles/source-check type AuthProfilesUsageModule = typeof import("./auth-profiles/usage.js"); type AuthProfilesOrderModule = typeof import("./auth-profiles/order.js"); type ModelFallbackCooldownModule = typeof import("./model-fallback-cooldown.js"); -type ModelFallbackModule = typeof import("./model-fallback.js"); +type ModelFallbackModule = typeof import("./model-fallback-runner.js"); type LoggerModule = typeof import("../logging/logger.js"); let mockedEnsureAuthProfileStore: ReturnType< @@ -149,7 +149,7 @@ async function loadModelFallbackProbeModules() { const authProfilesOrderModule = await import("./auth-profiles/order.js"); const loggerModule = await import("../logging/logger.js"); const modelFallbackCooldownModule = await import("./model-fallback-cooldown.js"); - const modelFallbackModule = await import("./model-fallback.js"); + const modelFallbackModule = await import("./model-fallback-runner.js"); const modelFallbackTestSupport = await import("./model-fallback.test-support.js"); mockedEnsureAuthProfileStore = vi.mocked(authProfilesStoreModule.ensureAuthProfileStore); mockedHasAnyAuthProfileStoreSource = vi.mocked( diff --git a/src/agents/model-fallback.run-embedded.e2e.test.ts b/src/agents/model-fallback.run-embedded.e2e.test.ts index c896281458aa..0061678fbc6c 100644 --- a/src/agents/model-fallback.run-embedded.e2e.test.ts +++ b/src/agents/model-fallback.run-embedded.e2e.test.ts @@ -63,13 +63,13 @@ const installRunEmbeddedMocks = () => { }; let runEmbeddedAgent: typeof import("./embedded-agent-runner/run.js").runEmbeddedAgent; -let runWithModelFallback: typeof import("./model-fallback.js").runWithModelFallback; +let runWithModelFallback: typeof import("./model-fallback-runner.js").runWithModelFallback; beforeAll(async () => { vi.resetModules(); installRunEmbeddedMocks(); ({ runEmbeddedAgent } = await import("./embedded-agent-runner/run.js")); - ({ runWithModelFallback } = await import("./model-fallback.js")); + ({ runWithModelFallback } = await import("./model-fallback-runner.js")); }); beforeEach(() => { diff --git a/src/agents/model-fallback.test-support.ts b/src/agents/model-fallback.test-support.ts index cccf33f59fef..b081ce3c07d6 100644 --- a/src/agents/model-fallback.test-support.ts +++ b/src/agents/model-fallback.test-support.ts @@ -1,47 +1,2 @@ -import type { AuthProfileStore } from "./auth-profiles/types.js"; -import type { FailoverReason } from "./embedded-agent-helpers/types.js"; -import type { ModelCandidate } from "./model-fallback.types.js"; -import "./model-fallback.js"; - -type CooldownDecision = - | { type: "skip"; reason: FailoverReason; error: string } - | { type: "attempt"; reason: FailoverReason; markProbe: boolean } - | { type: "suspend_lanes"; reason: FailoverReason; leaderCandidate?: ModelCandidate }; - -type ModelFallbackTestApi = { - resolveCooldownDecision(params: { - candidate: ModelCandidate; - isPrimary: boolean; - requestedModel: boolean; - hasFallbackCandidates: boolean; - now: number; - probeThrottleKey: string; - authRuntime: typeof import("./auth-profiles.runtime.js"); - authStore: AuthProfileStore; - profileIds: string[]; - }): CooldownDecision; - shouldDiscardDeferredSessionSuspension(params: { - error: unknown; - abortSignal?: AbortSignal; - }): boolean; -}; - -function getTestApi(): ModelFallbackTestApi { - const api = (globalThis as Record)[ - Symbol.for("openclaw.modelFallbackTestApi") - ]; - if (!api) { - throw new Error("model fallback test API is unavailable"); - } - return api as ModelFallbackTestApi; -} - -export const resolveCooldownDecision: ModelFallbackTestApi["resolveCooldownDecision"] = (params) => - getTestApi().resolveCooldownDecision(params); - -export function shouldDiscardDeferredSessionSuspension(params: { - error: unknown; - abortSignal?: AbortSignal; -}): boolean { - return getTestApi().shouldDiscardDeferredSessionSuspension(params); -} +export { shouldDiscardDeferredSessionSuspension } from "./model-fallback-attempt.js"; +export { resolveCooldownDecision } from "./model-fallback-cooldown.js"; diff --git a/src/agents/model-fallback.test.ts b/src/agents/model-fallback.test.ts index 16fbeac9fa7f..7e894dac11ae 100644 --- a/src/agents/model-fallback.test.ts +++ b/src/agents/model-fallback.test.ts @@ -33,12 +33,10 @@ import { import { clearAgentHarnesses, registerAgentHarness } from "./harness/registry.js"; import type { AgentHarness } from "./harness/types.js"; import { LiveSessionModelSwitchError } from "./live-model-switch-error.js"; -import { - isFallbackSummaryError, - resolveModelCandidateChain, - runWithImageModelFallback, - runWithModelFallback as runWithModelFallbackBase, -} from "./model-fallback.js"; +import { isFallbackSummaryError } from "./model-fallback-attempt.js"; +import { resolveModelCandidateChain } from "./model-fallback-candidates.js"; +import { runWithImageModelFallback } from "./model-fallback-image.js"; +import { runWithModelFallback as runWithModelFallbackBase } from "./model-fallback-runner.js"; import { shouldDiscardDeferredSessionSuspension } from "./model-fallback.test-support.js"; import { createAgentRunDirectAbortError, diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts deleted file mode 100644 index 945927910e1c..000000000000 --- a/src/agents/model-fallback.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { shouldDiscardDeferredSessionSuspension } from "./model-fallback-attempt.js"; -import { resolveCooldownDecision } from "./model-fallback-cooldown.js"; - -export { - resolveImageFallbackCandidates, - resolveImageFallbackDefaultProvider, - resolveModelCandidateChain, -} from "./model-fallback-candidates.js"; -export { - isFallbackSummaryError, - type ModelFallbackResultClassification, -} from "./model-fallback-attempt.js"; -export { runWithModelFallback } from "./model-fallback-runner.js"; -export { runWithImageModelFallback } from "./model-fallback-image.js"; - -if (process.env.VITEST || process.env.NODE_ENV === "test") { - (globalThis as Record)[Symbol.for("openclaw.modelFallbackTestApi")] = { - resolveCooldownDecision, - shouldDiscardDeferredSessionSuspension, - }; -} diff --git a/src/agents/outcome-fallback-runtime-contract.test.ts b/src/agents/outcome-fallback-runtime-contract.test.ts index c9939420daa2..401a4a171629 100644 --- a/src/agents/outcome-fallback-runtime-contract.test.ts +++ b/src/agents/outcome-fallback-runtime-contract.test.ts @@ -10,7 +10,7 @@ import { classifyEmbeddedAgentRunResultForModelFallback, mergeEmbeddedAgentRunResultForModelFallbackExhaustion, } from "./embedded-agent-runner/result-fallback-classifier.js"; -import { runWithModelFallback } from "./model-fallback.js"; +import { runWithModelFallback } from "./model-fallback-runner.js"; vi.mock("./auth-profiles/source-check.js", () => ({ hasAnyAuthProfileStoreSource: () => false, diff --git a/src/agents/tools/image-tool.ts b/src/agents/tools/image-tool.ts index fcee75ef2d12..d389ab39a366 100644 --- a/src/agents/tools/image-tool.ts +++ b/src/agents/tools/image-tool.ts @@ -45,7 +45,7 @@ import { isMinimaxVlmProvider } from "../minimax-vlm.js"; import { resolveImageFallbackCandidates, resolveImageFallbackDefaultProvider, -} from "../model-fallback.js"; +} from "../model-fallback-candidates.js"; import type { PreparedModelRuntimeSnapshot } from "../prepared-model-runtime.js"; import { optionalFiniteNumberSchema, optionalPositiveIntegerSchema } from "../schema/typebox.js"; import { readFiniteNumberParam, readPositiveIntegerParam } from "./common.js"; diff --git a/src/agents/tools/tool-runtime.helpers.ts b/src/agents/tools/tool-runtime.helpers.ts index af349cf42866..3ceb12a3e080 100644 --- a/src/agents/tools/tool-runtime.helpers.ts +++ b/src/agents/tools/tool-runtime.helpers.ts @@ -5,7 +5,7 @@ * sandbox media paths, or workspace helpers without depending on broad agent barrels. */ export { getApiKeyForModel, requireApiKey } from "../model-auth.js"; -export { runWithImageModelFallback } from "../model-fallback.js"; +export { runWithImageModelFallback } from "../model-fallback-image.js"; export { createSandboxBridgeReadFile, resolveSandboxedBridgeMediaPath, diff --git a/src/auto-reply/reply/agent-runner-error-handler.ts b/src/auto-reply/reply/agent-runner-error-handler.ts index d09f19dc9937..da125ae0c25c 100644 --- a/src/auto-reply/reply/agent-runner-error-handler.ts +++ b/src/auto-reply/reply/agent-runner-error-handler.ts @@ -15,7 +15,7 @@ import { import { sanitizeUserFacingText } from "../../agents/embedded-agent-helpers/sanitize-user-facing-text.js"; import { isFailoverError } from "../../agents/failover-error.js"; import { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js"; -import { isFallbackSummaryError } from "../../agents/model-fallback.js"; +import { isFallbackSummaryError } from "../../agents/model-fallback-attempt.js"; import { AGENT_RUN_RESTART_ABORT_STOP_REASON, resolveAgentRunErrorLifecycleFields, diff --git a/src/auto-reply/reply/agent-runner-execution.test-support.ts b/src/auto-reply/reply/agent-runner-execution.test-support.ts index 83792e7996df..3b46a18200f7 100644 --- a/src/auto-reply/reply/agent-runner-execution.test-support.ts +++ b/src/auto-reply/reply/agent-runner-execution.test-support.ts @@ -81,8 +81,11 @@ vi.mock("../../agents/cli-runner.js", () => ({ runCliAgent: (params: unknown) => state.runCliAgentMock(params), })); -vi.mock("../../agents/model-fallback.js", () => ({ +vi.mock("../../agents/model-fallback-runner.js", () => ({ runWithModelFallback: (params: unknown) => state.runWithModelFallbackMock(params), +})); + +vi.mock("../../agents/model-fallback-attempt.js", () => ({ isFallbackSummaryError: (err: unknown) => err instanceof Error && err.name === "FallbackSummaryError" && diff --git a/src/auto-reply/reply/agent-runner-failure-reply.ts b/src/auto-reply/reply/agent-runner-failure-reply.ts index 56c8726702ca..9815cac68277 100644 --- a/src/auto-reply/reply/agent-runner-failure-reply.ts +++ b/src/auto-reply/reply/agent-runner-failure-reply.ts @@ -24,7 +24,7 @@ import { isFailoverError, } from "../../agents/failover-error.js"; import { isMissingProviderAuthError } from "../../agents/model-auth.js"; -import { isFallbackSummaryError } from "../../agents/model-fallback.js"; +import { isFallbackSummaryError } from "../../agents/model-fallback-attempt.js"; import { resolveSilentReplyPolicy } from "../../config/silent-reply.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { formatErrorMessage } from "../../infra/errors.js"; diff --git a/src/auto-reply/reply/agent-runner.media-paths.test.ts b/src/auto-reply/reply/agent-runner.media-paths.test.ts index cf5562328d0c..cfa933842775 100644 --- a/src/auto-reply/reply/agent-runner.media-paths.test.ts +++ b/src/auto-reply/reply/agent-runner.media-paths.test.ts @@ -40,12 +40,15 @@ const resolveCommandSecretRefsViaGatewayMock = vi.fn(); const resolveOutboundAttachmentFromUrlMock = vi.fn(); const createReplyMediaContextRuntimeMock = vi.fn(); -vi.mock("../../agents/model-fallback.js", () => ({ +vi.mock("../../agents/model-fallback-runner.js", () => ({ runWithModelFallback: (params: { provider: string; model: string; run: (provider: string, model: string) => Promise; }) => runWithModelFallbackMock(params), +})); + +vi.mock("../../agents/model-fallback-attempt.js", () => ({ isFallbackSummaryError: (err: unknown) => err instanceof Error && err.name === "FallbackSummaryError" && diff --git a/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts b/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts index 080d90a5d238..f10bf55baca1 100644 --- a/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts +++ b/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts @@ -87,12 +87,15 @@ const compactState = vi.hoisted(() => ({ compactEmbeddedAgentSessionMock: vi.fn(), })); -vi.mock("../../agents/model-fallback.js", () => ({ +vi.mock("../../agents/model-fallback-runner.js", () => ({ runWithModelFallback: (params: { provider: string; model: string; run: (provider: string, model: string) => Promise; }) => runWithModelFallbackMock(params), +})); + +vi.mock("../../agents/model-fallback-attempt.js", () => ({ isFallbackSummaryError: (err: unknown) => err instanceof Error && err.name === "FallbackSummaryError" && diff --git a/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts b/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts index a412f97095cb..d46db6cd32f3 100644 --- a/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts +++ b/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts @@ -125,7 +125,7 @@ async function readStoredMainSession(storePath: string): Promise { return requireStoredSessionEntry(storePath); } -let modelFallbackModule: typeof import("../../agents/model-fallback.js"); +let modelFallbackModule: typeof import("../../agents/model-fallback-runner.js"); let onAgentEvent: typeof import("../../infra/agent-events.js").onAgentEvent; let runReplyAgentPromise: @@ -139,7 +139,7 @@ async function getRunReplyAgent() { return await runReplyAgentPromise; } -vi.mock("../../agents/model-fallback.js", () => ({ +vi.mock("../../agents/model-fallback-runner.js", () => ({ runWithModelFallback: async ({ provider, model, @@ -155,6 +155,9 @@ vi.mock("../../agents/model-fallback.js", () => ({ model, attempts: [], }), +})); + +vi.mock("../../agents/model-fallback-attempt.js", () => ({ isFallbackSummaryError: (err: unknown) => err instanceof Error && err.name === "FallbackSummaryError" && @@ -221,7 +224,7 @@ vi.mock("./queue.js", async (importOriginal) => ({ beforeAll(async () => { // Avoid attributing the initial agent-runner import cost to the first test case. - modelFallbackModule = await import("../../agents/model-fallback.js"); + modelFallbackModule = await import("../../agents/model-fallback-runner.js"); ({ onAgentEvent } = await import("../../infra/agent-events.js")); await getRunReplyAgent(); }); diff --git a/src/auto-reply/reply/model-selection.test.ts b/src/auto-reply/reply/model-selection.test.ts index 07978e656509..acf6c32e4494 100644 --- a/src/auto-reply/reply/model-selection.test.ts +++ b/src/auto-reply/reply/model-selection.test.ts @@ -12,7 +12,7 @@ import { loadManifestModelCatalog, loadPreparedModelCatalog as loadModelCatalogLocal, } from "../../agents/model-catalog.runtime.js"; -import { resolveModelCandidateChain } from "../../agents/model-fallback.js"; +import { resolveModelCandidateChain } from "../../agents/model-fallback-candidates.js"; import type { OpenClawConfig } from "../../config/config.js"; import type { SessionEntry } from "../../config/sessions.js"; import { loadSessionEntry, replaceSessionEntry } from "../../config/sessions/session-accessor.js"; diff --git a/src/auto-reply/reply/reply-operation-abort.ts b/src/auto-reply/reply/reply-operation-abort.ts index 73719c3954a4..724a424388e4 100644 --- a/src/auto-reply/reply/reply-operation-abort.ts +++ b/src/auto-reply/reply/reply-operation-abort.ts @@ -1,4 +1,4 @@ -import { isFallbackSummaryError } from "../../agents/model-fallback.js"; +import { isFallbackSummaryError } from "../../agents/model-fallback-attempt.js"; import { isAgentRunRestartAbortReason } from "../../agents/run-termination.js"; import { CommandLaneClearedError, GatewayDrainingError } from "../../process/command-queue.js"; import type { ReplyOperation } from "./reply-run-registry.js"; diff --git a/src/cli/capability-cli/image.ts b/src/cli/capability-cli/image.ts index 6cfc2cde81ab..683574be7808 100644 --- a/src/cli/capability-cli/image.ts +++ b/src/cli/capability-cli/image.ts @@ -6,7 +6,7 @@ import { } from "@openclaw/normalization-core/string-coerce"; import type { Command } from "commander"; import { resolveAgentDir, resolveDefaultAgentId } from "../../agents/agent-scope.js"; -import { runWithImageModelFallback } from "../../agents/model-fallback.js"; +import { runWithImageModelFallback } from "../../agents/model-fallback-image.js"; import { getRuntimeConfig } from "../../config/config.js"; import { resolveAgentModelPrimaryValue } from "../../config/model-input.js"; import { diff --git a/src/cli/cron-cli/cron-pagination.gateway.test.ts b/src/cli/cron-cli/cron-pagination.gateway.test.ts index d58835274aa7..cbfdb4ef0913 100644 --- a/src/cli/cron-cli/cron-pagination.gateway.test.ts +++ b/src/cli/cron-cli/cron-pagination.gateway.test.ts @@ -3,7 +3,7 @@ import { expectDefined } from "@openclaw/normalization-core"; import { Command } from "commander"; import { afterEach, describe, expect, it, vi } from "vitest"; import { createMockCronStateForJobs } from "../../cron/service.test-harness.js"; -import { listPage } from "../../cron/service/ops.js"; +import { listPage } from "../../cron/service/ops-read.js"; import type { CronJob } from "../../cron/types.js"; import { cronHandlers } from "../../gateway/server-methods/cron.js"; diff --git a/src/commands/doctor/cron/index.ts b/src/commands/doctor/cron/index.ts index 549bd8b92df0..41afc2fd1062 100644 --- a/src/commands/doctor/cron/index.ts +++ b/src/commands/doctor/cron/index.ts @@ -41,7 +41,7 @@ function readLegacyCronStorePath(cfg: OpenClawConfig): string | undefined { // The scheduler sets this while a run is active and clears it on completion, so a // leftover marker (gateway killed mid-run) makes `cron list` show the job as // `running` while nothing executes it. Startup marks exactly these runs interrupted -// (`src/cron/service/ops.ts` `start`), so doctor only reports the count here. +// (`src/cron/service/ops-lifecycle.ts` `start`), so doctor only reports the count here. function countInFlightCronJobs(jobs: Array>): number { return jobs.filter((job) => { const state = job.state; @@ -60,7 +60,7 @@ const CHRONIC_FAILURE_MIN_CONSECUTIVE_ERRORS = 3; // Count enabled jobs stuck in repeated run failures. `state.consecutiveErrors` // resets to 0 on the next successful run and also increments for runs interrupted -// by a gateway restart (startup marks in-flight runs failed, `src/cron/service/ops.ts`), +// by a gateway restart (startup marks in-flight runs failed, `src/cron/service/ops-lifecycle.ts`), // so a streak can mean task failures, interrupted runs, or a mix — the note says so. // Failure alerts are opt-in, so by default nothing else surfaces the streak. // Disabled jobs no longer re-fire (e.g. the scheduler disables exhausted diff --git a/src/cron/active-jobs-manual-run.test.ts b/src/cron/active-jobs-manual-run.test.ts index 45394e767b88..73b64a51957a 100644 --- a/src/cron/active-jobs-manual-run.test.ts +++ b/src/cron/active-jobs-manual-run.test.ts @@ -1,7 +1,7 @@ // Regression: upstream commit 7d1575b5df (#60310, 2026-04-04) introduced // activeJobIds + markCronJobActive/clearCronJobActive but only wired the pair // into the scheduled due-job path. The manual-run path (cron.run() → -// prepareManualRun + finishPreparedManualRun in src/cron/service/ops.ts) was +// prepareManualRun + finishPreparedManualRun in src/cron/service/ops-run.ts) was // left without the mark/clear pair, so task-registry.maintenance.ts // hasBackingSession (cron branch under isRuntimeAuthoritative()=true) // returns false during manual-run executions and reconciles them as `lost` diff --git a/src/cron/isolated-agent/run-execution.runtime.ts b/src/cron/isolated-agent/run-execution.runtime.ts index d7a969c41b2e..6197b679a1de 100644 --- a/src/cron/isolated-agent/run-execution.runtime.ts +++ b/src/cron/isolated-agent/run-execution.runtime.ts @@ -7,7 +7,7 @@ export { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-bu export { resolveCronAgentLane } from "../../agents/lanes.js"; export { ensureSelectedAgentHarnessPlugin } from "../../agents/harness/runtime-plugin.js"; export { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js"; -export { runWithModelFallback } from "../../agents/model-fallback.js"; +export { runWithModelFallback } from "../../agents/model-fallback-runner.js"; export { resolveCandidateThinkingLevel } from "../../agents/thinking-runtime.js"; export { classifyEmbeddedAgentRunResultForModelFallback, diff --git a/src/cron/isolated-agent/run-fallback-policy.ts b/src/cron/isolated-agent/run-fallback-policy.ts index eb7323e6dc57..0fd5aeb76759 100644 --- a/src/cron/isolated-agent/run-fallback-policy.ts +++ b/src/cron/isolated-agent/run-fallback-policy.ts @@ -1,5 +1,5 @@ /** Resolves model fallback chains for isolated cron runs and preflight. */ -import { resolveModelCandidateChain } from "../../agents/model-fallback.js"; +import { resolveModelCandidateChain } from "../../agents/model-fallback-candidates.js"; import type { ModelCandidate } from "../../agents/model-fallback.types.js"; import { resolveAgentModelFallbackValues } from "../../config/model-input.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; diff --git a/src/cron/service.list-page-sort-guards.test.ts b/src/cron/service.list-page-sort-guards.test.ts index f7164e640810..60fa7fc20880 100644 --- a/src/cron/service.list-page-sort-guards.test.ts +++ b/src/cron/service.list-page-sort-guards.test.ts @@ -4,7 +4,7 @@ import os from "node:os"; import path from "node:path"; import { describe, expect, it } from "vitest"; import { createMockCronStateForJobs } from "./service.test-harness.js"; -import { listPage } from "./service/ops.js"; +import { listPage } from "./service/ops-read.js"; import type { CronJob } from "./types.js"; function createBaseJob(overrides?: Partial): CronJob { diff --git a/src/cron/service.removal-postcommit.test.ts b/src/cron/service.removal-postcommit.test.ts index d28f34955723..38ce567fb0fb 100644 --- a/src/cron/service.removal-postcommit.test.ts +++ b/src/cron/service.removal-postcommit.test.ts @@ -1,7 +1,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { resetGatewayWorkAdmission } from "../process/gateway-work-admission.js"; import { setupCronServiceSuite } from "./service.test-harness.js"; -import { list, run } from "./service/ops.js"; +import { list } from "./service/ops-read.js"; +import { run } from "./service/ops-run.js"; import { createCronServiceState, type CronEvent, type CronServiceState } from "./service/state.js"; import { ensureLoaded } from "./service/store.js"; import { runMissedJobs } from "./service/timer.js"; diff --git a/src/cron/service.startup-overflow-clobber.test.ts b/src/cron/service.startup-overflow-clobber.test.ts index 24ed594e931e..0ba797c53ed3 100644 --- a/src/cron/service.startup-overflow-clobber.test.ts +++ b/src/cron/service.startup-overflow-clobber.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it, vi } from "vitest"; import { setupCronServiceSuite } from "./service.test-harness.js"; -import { start, status } from "./service/ops.js"; +import { start } from "./service/ops-lifecycle.js"; +import { status } from "./service/ops-read.js"; import { createCronServiceState } from "./service/state.js"; import { onTimer } from "./service/timer.test-support.js"; import { saveCronStore } from "./store.js"; diff --git a/src/cron/service.ts b/src/cron/service.ts index e7c8675e1a7b..2268616d1309 100644 --- a/src/cron/service.ts +++ b/src/cron/service.ts @@ -5,7 +5,10 @@ import type { CronServiceRunResult, } from "./service-contract.js"; import type { CronListPageOptions } from "./service/list-page-types.js"; -import * as ops from "./service/ops.js"; +import * as lifecycleOps from "./service/ops-lifecycle.js"; +import * as mutationOps from "./service/ops-mutations.js"; +import * as readOps from "./service/ops-read.js"; +import * as runOps from "./service/ops-run.js"; import { type CronAddOptions, type CronServiceDeps, @@ -62,9 +65,9 @@ export class CronService implements CronServiceContract { this.startInProgress += 1; this.state.schedulerStarted = false; try { - await ops.start(this.state); + await lifecycleOps.start(this.state); if (generation !== this.lifecycleGeneration) { - ops.stop(this.state); + lifecycleOps.stop(this.state); return; } this.state.schedulerStarted = !this.state.stopped; @@ -75,15 +78,15 @@ export class CronService implements CronServiceContract { stop() { this.lifecycleGeneration += 1; - ops.stop(this.state); + lifecycleOps.stop(this.state); } pauseScheduling() { - ops.pauseScheduling(this.state); + lifecycleOps.pauseScheduling(this.state); } resumeScheduling() { - ops.resumeScheduling(this.state); + lifecycleOps.resumeScheduling(this.state); } getSuspensionBlockerCount() { @@ -91,23 +94,23 @@ export class CronService implements CronServiceContract { } async status() { - return await ops.status(this.state); + return await readOps.status(this.state); } async list(opts?: { includeDisabled?: boolean }) { - return await ops.list(this.state, opts); + return await readOps.list(this.state, opts); } async listPage(opts?: CronListPageOptions) { - return await ops.listPage(this.state, opts); + return await readOps.listPage(this.state, opts); } async add(input: CronJobCreate, opts?: CronAddOptions) { - return await ops.add(this.state, input, opts); + return await mutationOps.add(this.state, input, opts); } async update(id: string, patch: CronJobPatch, opts?: CronUpdateOptions) { - return await ops.update(this.state, id, patch, opts); + return await mutationOps.update(this.state, id, patch, opts); } async updateWithPrecondition( @@ -116,15 +119,15 @@ export class CronService implements CronServiceContract { precondition: CronUpdatePrecondition, opts?: CronUpdateOptions, ) { - return await ops.updateWithPrecondition(this.state, id, patch, precondition, opts); + return await mutationOps.updateWithPrecondition(this.state, id, patch, precondition, opts); } async remove(id: string, opts?: { systemOwned?: boolean }) { - return await ops.remove(this.state, id, opts); + return await mutationOps.remove(this.state, id, opts); } async removeAgentJobsTransactional(agentId: string, commit: () => Promise): Promise { - return await ops.removeAgentJobsTransactional(this.state, agentId, commit); + return await mutationOps.removeAgentJobsTransactional(this.state, agentId, commit); } async run( @@ -132,11 +135,11 @@ export class CronService implements CronServiceContract { mode?: "due" | "force", opts?: CronServiceRunOptions, ): Promise { - return await ops.run(this.state, id, mode, opts); + return await runOps.run(this.state, id, mode, opts); } async enqueueRun(id: string, mode?: "due" | "force"): Promise { - const result = await ops.enqueueRun(this.state, id, mode); + const result = await runOps.enqueueRun(this.state, id, mode); if (result.ok && "runnable" in result) { // ops.enqueueRun resolves runnable dispositions before crossing the // public facade; leaking one would expose an internal scheduler detail. @@ -155,18 +158,18 @@ export class CronService implements CronServiceContract { } async readJob(id: string): Promise { - return await ops.readJob(this.state, id); + return await readOps.readJob(this.state, id); } async readScratch(id: string) { - return await ops.readScratch(this.state, id); + return await readOps.readScratch(this.state, id); } async writeScratch( id: string, params: { content: string | null; expectedRevision?: number; sourceSha256?: string }, ) { - return await ops.writeScratch(this.state, id, params); + return await readOps.writeScratch(this.state, id, params); } async recordExternalFailure( @@ -175,7 +178,7 @@ export class CronService implements CronServiceContract { statePatch: Partial, source?: { scheduleKey: string; identity: string }, ): Promise { - await ops.recordExternalFailure(this.state, id, error, statePatch, source); + await readOps.recordExternalFailure(this.state, id, error, statePatch, source); } async updateExternalState( @@ -184,7 +187,7 @@ export class CronService implements CronServiceContract { streamSourceIdentity: string, statePatch: Partial, ): Promise { - return await ops.updateExternalState( + return await readOps.updateExternalState( this.state, id, streamScheduleKey, @@ -198,7 +201,7 @@ export class CronService implements CronServiceContract { streamScheduleKey: string, streamSourceIdentity: string, ): Promise { - return await ops.retireExternalStreamSource( + return await readOps.retireExternalStreamSource( this.state, id, streamScheduleKey, @@ -210,7 +213,7 @@ export class CronService implements CronServiceContract { id: string, counters: Pick, ): Promise { - await ops.updateExternalCounters(this.state, id, counters); + await readOps.updateExternalCounters(this.state, id, counters); } getDefaultAgentId(): string | undefined { @@ -218,6 +221,6 @@ export class CronService implements CronServiceContract { } wake(opts: { mode: CronWakeMode; text: string; sessionKey?: string; agentId?: string }) { - return ops.wakeNow(this.state, opts); + return runOps.wakeNow(this.state, opts); } } diff --git a/src/cron/service/ops.pacing.test.ts b/src/cron/service/ops.pacing.test.ts index 59fb8918b4c9..c96ffb70fca4 100644 --- a/src/cron/service/ops.pacing.test.ts +++ b/src/cron/service/ops.pacing.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it, vi } from "vitest"; import { withEnvAsync } from "../../test-utils/env.js"; import { setupCronServiceSuite } from "../service.test-harness.js"; import type { CronJobCreate, CronJobPatch, CronPacing } from "../types.js"; -import { add, update } from "./ops.js"; +import { add, update } from "./ops-mutations.js"; import { createCronServiceState } from "./state.js"; const { logger, makeStorePath } = setupCronServiceSuite({ prefix: "cron-pacing-ops" }); diff --git a/src/cron/service/ops.regression.test.ts b/src/cron/service/ops.regression.test.ts index b13586addfa6..fd6b58384755 100644 --- a/src/cron/service/ops.regression.test.ts +++ b/src/cron/service/ops.regression.test.ts @@ -25,7 +25,9 @@ import { import { CommandLane } from "../../process/lanes.js"; import { isCronJobActive } from "../active-jobs.js"; import { loadCronStore, saveCronStore } from "../store.js"; -import { enqueueRun, remove, run, start, update } from "./ops.js"; +import { start } from "./ops-lifecycle.js"; +import { remove, update } from "./ops-mutations.js"; +import { enqueueRun, run } from "./ops-run.js"; import type { CronEvent } from "./state.js"; import { createCronServiceState } from "./state.js"; import { ensureLoaded } from "./store.js"; diff --git a/src/cron/service/ops.run-admission-cleanup.test.ts b/src/cron/service/ops.run-admission-cleanup.test.ts index e80f7695079a..685ae49e3a8a 100644 --- a/src/cron/service/ops.run-admission-cleanup.test.ts +++ b/src/cron/service/ops.run-admission-cleanup.test.ts @@ -7,7 +7,8 @@ import { } from "../../../test/helpers/cron/service-regression-fixtures.js"; import * as cronStoreModule from "../store.js"; import { loadCronStore, saveCronStore } from "../store.js"; -import { run, stop } from "./ops.js"; +import { stop } from "./ops-lifecycle.js"; +import { run } from "./ops-run.js"; import { createCronServiceState } from "./state.js"; import { runMissedJobs } from "./timer.js"; import { onTimer } from "./timer.test-support.js"; diff --git a/src/cron/service/ops.run-admission.test.ts b/src/cron/service/ops.run-admission.test.ts index 310c4d8781d4..74c47460ef1c 100644 --- a/src/cron/service/ops.run-admission.test.ts +++ b/src/cron/service/ops.run-admission.test.ts @@ -18,7 +18,10 @@ import * as cronStoreModule from "../store.js"; import { loadCronStore, saveCronStore } from "../store.js"; import { cronStreamScheduleKey } from "../stream-schedule.js"; import { recomputeNextRunsForMaintenance } from "./jobs.js"; -import { enqueueRun, list, run, stop, update } from "./ops.js"; +import { stop } from "./ops-lifecycle.js"; +import { update } from "./ops-mutations.js"; +import { list } from "./ops-read.js"; +import { enqueueRun, run } from "./ops-run.js"; import { createCronServiceState } from "./state.js"; import { onTimer } from "./timer.test-support.js"; diff --git a/src/cron/service/ops.test.ts b/src/cron/service/ops.test.ts index f58adef9902f..fa918e84e9dd 100644 --- a/src/cron/service/ops.test.ts +++ b/src/cron/service/ops.test.ts @@ -13,7 +13,10 @@ import { setupCronServiceSuite, writeCronStoreSnapshot } from "../service.test-h import * as cronStoreModule from "../store.js"; import { loadCronJobsStoreWithConfigJobs, loadCronStore } from "../store.js"; import type { CronJob } from "../types.js"; -import { add, list, remove, run, start, stop, update } from "./ops.js"; +import { start, stop } from "./ops-lifecycle.js"; +import { add, remove, update } from "./ops-mutations.js"; +import { list } from "./ops-read.js"; +import { run } from "./ops-run.js"; import { createCronServiceState, type CronEvent } from "./state.js"; import { tryCreateCronTaskRun, tryFinishCronTaskRun } from "./task-runs.js"; import { runMissedJobs } from "./timer.js"; diff --git a/src/cron/service/ops.ts b/src/cron/service/ops.ts deleted file mode 100644 index 99bd48310c2e..000000000000 --- a/src/cron/service/ops.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** Stable public facade for cron service operations. */ -export { pauseScheduling, resumeScheduling, start, stop } from "./ops-lifecycle.js"; -export { - list, - listPage, - readJob, - readScratch, - recordExternalFailure, - retireExternalStreamSource, - status, - updateExternalCounters, - updateExternalState, - writeScratch, -} from "./ops-read.js"; -export { - add, - remove, - removeAgentJobsTransactional, - update, - updateWithPrecondition, -} from "./ops-mutations.js"; -export { enqueueRun, run, wakeNow } from "./ops-run.js"; diff --git a/src/cron/service/ops.update.disable-and-list.test.ts b/src/cron/service/ops.update.disable-and-list.test.ts index b491171c19f5..8a9c7aab68d0 100644 --- a/src/cron/service/ops.update.disable-and-list.test.ts +++ b/src/cron/service/ops.update.disable-and-list.test.ts @@ -3,7 +3,8 @@ import { noopLogger, setupCronRegressionFixtures, } from "../../../test/helpers/cron/service-regression-fixtures.js"; -import { add, list, update } from "./ops.js"; +import { add, update } from "./ops-mutations.js"; +import { list } from "./ops-read.js"; import { createCronServiceState } from "./state.js"; const fixtures = setupCronRegressionFixtures({ prefix: "cron-disable-list-" }); diff --git a/src/cron/service/timer.regression.test.ts b/src/cron/service/timer.regression.test.ts index 93546ed9fd08..806b9ac011e0 100644 --- a/src/cron/service/timer.regression.test.ts +++ b/src/cron/service/timer.regression.test.ts @@ -38,7 +38,8 @@ import type { import { cancelActiveCronTaskRun } from "./active-run-cancellation.js"; import { resetActiveCronTaskRunsForTests } from "./active-run-cancellation.test-support.js"; import { computeJobNextRunAtMs, recomputeNextRunsForMaintenance } from "./jobs.js"; -import { run as runManualCronJob, stop } from "./ops.js"; +import { stop } from "./ops-lifecycle.js"; +import { run as runManualCronJob } from "./ops-run.js"; import { createCronServiceState as createBaseCronServiceState, type CronEvent } from "./state.js"; import { applyJobResult, executeJobCoreWithTimeout, runMissedJobs } from "./timer.js"; import { executeJobCore, onTimer } from "./timer.test-support.js"; diff --git a/test/helpers/auto-reply/trigger-handling-test-harness.ts b/test/helpers/auto-reply/trigger-handling-test-harness.ts index 8544592027a1..2518eb3f2f16 100644 --- a/test/helpers/auto-reply/trigger-handling-test-harness.ts +++ b/test/helpers/auto-reply/trigger-handling-test-harness.ts @@ -173,7 +173,7 @@ const modelFallbackMocks = getSharedMocks("openclaw.trigger-handling.model-fallb })); const installModelFallbackMock = () => - vi.doMock("../../../src/agents/model-fallback.js", () => modelFallbackMocks); + vi.doMock("../../../src/agents/model-fallback-runner.js", () => modelFallbackMocks); installModelFallbackMock(); diff --git a/test/scripts/audit-seams.test.ts b/test/scripts/audit-seams.test.ts index 2fb3e4a992a2..34e1c67d9fbd 100644 --- a/test/scripts/audit-seams.test.ts +++ b/test/scripts/audit-seams.test.ts @@ -10,7 +10,7 @@ describe("audit-seams cron seam classification", () => { it("detects cron agent handoff and outbound delivery boundaries", () => { const source = ` import { runCliAgent } from "../../agents/cli-runner.js"; - import { runWithModelFallback } from "../../agents/model-fallback.js"; + import { runWithModelFallback } from "../../agents/model-fallback-runner.js"; import { registerAgentRunContext } from "../../infra/agent-events.js"; import { deliverOutboundPayloads } from "../../infra/outbound/deliver.js"; import { buildOutboundSessionContext } from "../../infra/outbound/session-context.js"; @@ -45,7 +45,9 @@ describe("audit-seams cron seam classification", () => { } `; - expect(describeSeamKinds("src/cron/service/ops.ts", source)).toContain("cron-scheduler-state"); + expect(describeSeamKinds("src/cron/service/ops-lifecycle.ts", source)).toContain( + "cron-scheduler-state", + ); }); }); diff --git a/ui/src/pages/chat/chat-pane-board.test.ts b/ui/src/pages/chat/chat-pane-board.test.ts index c2be5ad2f889..5c23501159c0 100644 --- a/ui/src/pages/chat/chat-pane-board.test.ts +++ b/ui/src/pages/chat/chat-pane-board.test.ts @@ -15,7 +15,7 @@ import { createStorageMock } from "../../test-helpers/storage.ts"; import type { SessionObserverDigest } from "./chat-pane-deps.ts"; import "./chat-pane.ts"; import type { ResolvedBoardView } from "./chat-pane-shared.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; import { detachPanelToColumn, mergePanelIntoColumn, diff --git a/ui/src/pages/chat/chat-pane-deps.ts b/ui/src/pages/chat/chat-pane-deps.ts index 74508e71944f..ea81e09c9c83 100644 --- a/ui/src/pages/chat/chat-pane-deps.ts +++ b/ui/src/pages/chat/chat-pane-deps.ts @@ -194,15 +194,18 @@ export { switchChatModel, switchChatThinkingLevel, } from "./chat-session.ts"; +export { ChatStateController } from "./chat-state-controller.ts"; +export { handlePageGatewayEvent } from "./chat-state-events.ts"; +export type { ChatPageHost } from "./chat-state-host.ts"; +export { createPageState } from "./chat-state-page.ts"; export { - canCreateChatSession, - ChatStateController, - createPageState, - handlePageGatewayEvent, refreshChatCommands, refreshChatMetadata, refreshChatModelAuthStatus, refreshPageChat, +} from "./chat-state-refresh.ts"; +export { + canCreateChatSession, refreshRouteSessionOptions, resetChatStateForRouteSession, retryChatComposerMemoryFallback, @@ -210,8 +213,7 @@ export { resolveChatAvatarUrl, selectedChatSessionRow, saveRouteSessionSettings, - type ChatPageHost, -} from "./chat-state.ts"; +} from "./chat-state-route.ts"; export { resetChatViewState } from "./chat-view-state.ts"; export { renderChat, type ChatProps } from "./chat-view.ts"; export { diff --git a/ui/src/pages/chat/chat-pane-history.test.ts b/ui/src/pages/chat/chat-pane-history.test.ts index e6e0ec83c806..3216eed2ae80 100644 --- a/ui/src/pages/chat/chat-pane-history.test.ts +++ b/ui/src/pages/chat/chat-pane-history.test.ts @@ -7,7 +7,7 @@ import type { ApplicationContext } from "../../app/context.ts"; import type { SessionCapability } from "../../lib/sessions/index.ts"; import "./chat-pane.ts"; import { loadChatHistory } from "./chat-history.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; type TestChatPane = HTMLElement & { catalogMessages: unknown[]; diff --git a/ui/src/pages/chat/chat-pane-identity.test.ts b/ui/src/pages/chat/chat-pane-identity.test.ts index 19a9191c06cc..1588af3983c3 100644 --- a/ui/src/pages/chat/chat-pane-identity.test.ts +++ b/ui/src/pages/chat/chat-pane-identity.test.ts @@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest"; import type { GatewayBrowserClient } from "../../api/gateway.ts"; import type { SessionCapability } from "../../lib/sessions/index.ts"; import { createTestChatPane } from "./chat-pane.test-support.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; describe("chat pane assistant identity snapshots", () => { it("keeps a session-specific assistant identity across ordinary gateway snapshots", () => { diff --git a/ui/src/pages/chat/chat-pane-lifecycle.test.ts b/ui/src/pages/chat/chat-pane-lifecycle.test.ts index 2a4e0da40a9e..134dd95f6815 100644 --- a/ui/src/pages/chat/chat-pane-lifecycle.test.ts +++ b/ui/src/pages/chat/chat-pane-lifecycle.test.ts @@ -14,7 +14,7 @@ import type { ApplicationContext } from "../../app/context.ts"; import { createInitialUserMessageHandoff } from "../../app/initial-user-message-handoff.ts"; import type { SessionCapability } from "../../lib/sessions/index.ts"; import { createTestChatPane, type TestChatPane } from "./chat-pane.test-support.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; import { dismissConfirmedActionPopovers, openChatRewindConfirmation, diff --git a/ui/src/pages/chat/chat-pane.message-cut.test.ts b/ui/src/pages/chat/chat-pane.message-cut.test.ts index 970323eb4930..acbd19e6b0fb 100644 --- a/ui/src/pages/chat/chat-pane.message-cut.test.ts +++ b/ui/src/pages/chat/chat-pane.message-cut.test.ts @@ -3,7 +3,7 @@ import type { GatewayBrowserClient } from "../../api/gateway.ts"; import type { ApplicationContext } from "../../app/context.ts"; import type { SessionCapability } from "../../lib/sessions/index.ts"; import "./chat-pane.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; type TestChatPane = HTMLElement & { connectedClient: GatewayBrowserClient | null; diff --git a/ui/src/pages/chat/chat-pane.test-support.ts b/ui/src/pages/chat/chat-pane.test-support.ts index 708148b0dac0..89372d4fc071 100644 --- a/ui/src/pages/chat/chat-pane.test-support.ts +++ b/ui/src/pages/chat/chat-pane.test-support.ts @@ -17,7 +17,7 @@ import { createInitialUserMessageHandoff } from "../../app/initial-user-message- import type { CatalogSessionKey } from "../../lib/sessions/catalog-key.ts"; import type { SessionCapability } from "../../lib/sessions/index.ts"; import "./chat-pane.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; import { createBackgroundTasksProps } from "./components/chat-background-tasks.ts"; import { createSessionWorkspaceProps } from "./components/chat-session-workspace.ts"; import type { ChatMessageCache } from "./session-message-cache.ts"; diff --git a/ui/src/pages/chat/chat-pane.test.ts b/ui/src/pages/chat/chat-pane.test.ts index fb581fc1fa71..14a8df04db56 100644 --- a/ui/src/pages/chat/chat-pane.test.ts +++ b/ui/src/pages/chat/chat-pane.test.ts @@ -22,7 +22,7 @@ import { createTestChatPane, type TestChatPane, } from "./chat-pane.test-support.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; import { createBackgroundTasksProps } from "./components/chat-background-tasks.ts"; import { createSessionWorkspaceProps } from "./components/chat-session-workspace.ts"; import type { SidebarContent } from "./components/chat-sidebar.ts"; diff --git a/ui/src/pages/chat/chat-send.test.ts b/ui/src/pages/chat/chat-send.test.ts index 0fe49ea84a50..ea3e612619f1 100644 --- a/ui/src/pages/chat/chat-send.test.ts +++ b/ui/src/pages/chat/chat-send.test.ts @@ -24,7 +24,7 @@ import { switchChatThinkingLevel, } from "./chat-session.ts"; import { patchChatSessionSettings } from "./chat-settings-patches.ts"; -import type { ChatPageHost } from "./chat-state.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; import { admitStoredChatComposerQueueItem, listStoredChatOutboxes, @@ -158,7 +158,7 @@ let handleSendChat: typeof import("./chat-send-submit.ts").handleSendChat; let steerQueuedChatMessage: typeof import("./chat-send-actions.ts").steerQueuedChatMessage; let handleAbortChat: typeof import("./run-lifecycle.ts").handleAbortChat; let hasAbortableSessionRun: typeof import("./run-lifecycle.ts").hasAbortableSessionRun; -let handlePageGatewayEvent: typeof import("./chat-state.ts").handlePageGatewayEvent; +let handlePageGatewayEvent: typeof import("./chat-state-events.ts").handlePageGatewayEvent; let loadChatBranches: typeof import("./chat-history.ts").loadChatBranches; let loadChatHistory: typeof import("./chat-history.ts").loadChatHistory; let clearPendingQueueItemsForRun: typeof import("./chat-queue.ts").clearPendingQueueItemsForRun; @@ -173,7 +173,7 @@ let flushChatQueueForEvent: typeof import("./chat-send-actions.ts").flushChatQue let retryReconnectableQueuedChatSends: typeof import("./chat-send-actions.ts").retryReconnectableQueuedChatSends; let retryQueuedChatMessage: typeof import("./chat-send-actions.ts").retryQueuedChatMessage; let recordChatSendServerTiming: typeof import("./chat-send-timing.ts").recordChatSendServerTiming; -let refreshPageChat: typeof import("./chat-state.ts").refreshPageChat; +let refreshPageChat: typeof import("./chat-state-refresh.ts").refreshPageChat; async function loadChatHelpers(): Promise { ({ @@ -184,9 +184,8 @@ async function loadChatHelpers(): Promise { } = await import("./chat-send-actions.ts")); ({ handleSendChat } = await import("./chat-send-submit.ts")); ({ recordChatSendServerTiming } = await import("./chat-send-timing.ts")); - const chatState = await import("./chat-state.ts"); - handlePageGatewayEvent = chatState.handlePageGatewayEvent; - refreshPageChat = chatState.refreshPageChat; + ({ handlePageGatewayEvent } = await import("./chat-state-events.ts")); + ({ refreshPageChat } = await import("./chat-state-refresh.ts")); ({ loadChatBranches, loadChatHistory } = await import("./chat-history.ts")); ({ handleAbortChat, hasAbortableSessionRun } = await import("./run-lifecycle.ts")); ({ diff --git a/ui/src/pages/chat/chat-state.test.ts b/ui/src/pages/chat/chat-state.test.ts index 0804a30c9deb..37ee68b583bf 100644 --- a/ui/src/pages/chat/chat-state.test.ts +++ b/ui/src/pages/chat/chat-state.test.ts @@ -17,17 +17,17 @@ import { subscribeChatOutboxProjection, updateQueuedMessageForSession, } from "./chat-queue.ts"; +import { ChatStateController } from "./chat-state-controller.ts"; +import { handlePageGatewayEvent } from "./chat-state-events.ts"; +import type { ChatPageHost } from "./chat-state-host.ts"; +import { createPageState } from "./chat-state-page.ts"; +import { refreshChatMetadata } from "./chat-state-refresh.ts"; import { - ChatStateController, - createPageState, - handlePageGatewayEvent, - refreshChatMetadata, resetChatStateForRouteSession, retryChatComposerMemoryFallback, resolveChatAvatarUrl, selectedChatSessionRow, - type ChatPageHost, -} from "./chat-state.ts"; +} from "./chat-state-route.ts"; import { admitStoredChatComposerQueueItem, ChatComposerPersistence, diff --git a/ui/src/pages/chat/chat-state.ts b/ui/src/pages/chat/chat-state.ts deleted file mode 100644 index a89499554564..000000000000 --- a/ui/src/pages/chat/chat-state.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Control UI chat state facade. Keep the public surface stable while ownership -// lives in focused route, refresh, event, page, and lifecycle modules. -export * from "./chat-state-controller.ts"; -export * from "./chat-state-events.ts"; -export type { ChatPageHost } from "./chat-state-host.ts"; -export { createPageState } from "./chat-state-page.ts"; -export * from "./chat-state-refresh.ts"; -export * from "./chat-state-route.ts";