@cuongtran001/kanna 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/{arc-BLk1CZKB.js → arc-DXtN3EWJ.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-B01ZQYte.js → architectureDiagram-3BPJPVTR-CIGqW1z-.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-diL6a3cq.js → blockDiagram-GPEHLZMM-BafNS_H6.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BY1verL8.js → c4Diagram-AAUBKEIU-YdAgRSis.js} +1 -1
- package/dist/client/assets/channel-BEYTrUAm.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-psdZuajw.js → chunk-2J33WTMH-eiP5y5G-.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-CrwQVBc5.js → chunk-4BX2VUAB-CvLGzPMF.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-9-aj4jKO.js → chunk-55IACEB6-Y-S9Fb8A.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-1FNK9_nB.js → chunk-727SXJPM-6sJH1RI9.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DFhvd_Ek.js → chunk-AQP2D5EJ-hV1r_IXO.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-B7MLrDa7.js → chunk-FMBD7UC4-CC3L28S5.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-D4Df05QE.js → chunk-ND2GUHAM-BZ3czhdH.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-Iq17Dznm.js → chunk-QZHKN3VN-Bjyd6Yr-.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CvnF5Ud6.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CvnF5Ud6.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BmaZhtXy.js → cose-bilkent-S5V4N54A-CfxdDghE.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BCmpfnfP.js → dagre-BM42HDAG-B8CddsbB.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BIEcKowS.js → diagram-2AECGRRQ-F0yS0fVB.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CRBABBfv.js → diagram-5GNKFQAL-cW0i0qlh.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BRxUk16N.js → diagram-KO2AKTUF-BzAKMeJT.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DPBs4xl1.js → diagram-LMA3HP47-qdC4XqIl.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BE9rgVv8.js → diagram-OG6HWLK6-CGcpi6Dh.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-D3vgA1xJ.js → erDiagram-TEJ5UH35-CxNTDicM.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Cgu-8XXC.js → flowDiagram-I6XJVG4X-qkGa5TqY.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CgjXVyTR.js → ganttDiagram-6RSMTGT7-D9mVPoQi.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-zD5D8B-i.js → gitGraphDiagram-PVQCEYII-DA0grAXe.js} +1 -1
- package/dist/client/assets/{index-DBTdhMbJ.js → index-BqUY1Bm4.js} +1 -1
- package/dist/client/assets/index-CLsOWXff.css +32 -0
- package/dist/client/assets/{index-zQLLeAfl.js → index-TU1k6ov6.js} +253 -243
- package/dist/client/assets/{infoDiagram-5YYISTIA-BaFHqT4u.js → infoDiagram-5YYISTIA-CGljtLs3.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-2yAC1br2.js → ishikawaDiagram-YF4QCWOH-CtC0xrmG.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DacQ-ND5.js → journeyDiagram-JHISSGLW-URLnVZeN.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Qlbwm3z4.js → kanban-definition-UN3LZRKU-C2Q6aqQh.js} +1 -1
- package/dist/client/assets/{linear-DeafqpgO.js → linear-ByKHtsIx.js} +1 -1
- package/dist/client/assets/{mermaid.core-KYiCPJDj.js → mermaid.core-Dl_f2KLc.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-B1V-T6d3.js → mindmap-definition-RKZ34NQL-CaJ9IDLI.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DOF9OFRu.js → pieDiagram-4H26LBE5-mmYaf2Oa.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-lH1mB7ko.js → quadrantDiagram-W4KKPZXB-B_PO6OCC.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-BaTsJ_sS.js → requirementDiagram-4Y6WPE33-M4huwJt1.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Pfxib5iI.js → sankeyDiagram-5OEKKPKP-B0hb1sWh.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BQMEKkBC.js → sequenceDiagram-3UESZ5HK-BAqSptnA.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CuldNnzp.js → stateDiagram-AJRCARHV-DTNkvPi5.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-CVN3oGTF.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DP7u0YAg.js → timeline-definition-PNZ67QCA-MgAjHz8Q.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-QlrjpNeQ.js → vennDiagram-CIIHVFJN-DmKoO51W.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BqdJ_sAM.js → wardley-L42UT6IY-CWcyHnYs.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Wi3kaQ5X.js → wardleyDiagram-YWT4CUSO-BGIGmFP9.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-D-KXMyCG.js → xychartDiagram-2RQKCTM6-D20YIvEl.js} +1 -1
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/src/server/agent-coordinator-types.ts +158 -0
- package/src/server/agent-coordinator.ts +919 -0
- package/src/server/agent-deps-builders.ts +425 -0
- package/src/server/agent.oauth-rotation.test.ts +101 -0
- package/src/server/agent.test.ts +24 -8
- package/src/server/agent.ts +35 -4963
- package/src/server/auto-continue/read-model.test.ts +2 -2
- package/src/server/auto-continue/read-model.ts +4 -1
- package/src/server/claude-autocontinue-commands.test.ts +494 -0
- package/src/server/claude-autocontinue-commands.ts +256 -0
- package/src/server/claude-cancel-handler.test.ts +472 -0
- package/src/server/claude-cancel-handler.ts +241 -0
- package/src/server/claude-chat-management.test.ts +395 -0
- package/src/server/claude-chat-management.ts +251 -0
- package/src/server/claude-harness-stream.test.ts +273 -0
- package/src/server/claude-harness-stream.ts +158 -0
- package/src/server/claude-loop-orch-commands.test.ts +579 -0
- package/src/server/claude-loop-orch-commands.ts +466 -0
- package/src/server/claude-message-normalizer.test.ts +213 -0
- package/src/server/claude-message-normalizer.ts +436 -0
- package/src/server/claude-prompt-helpers.test.ts +248 -0
- package/src/server/claude-prompt-helpers.ts +139 -0
- package/src/server/claude-sdk-queue.test.ts +169 -0
- package/src/server/claude-sdk-queue.ts +82 -0
- package/src/server/claude-send-command.test.ts +414 -0
- package/src/server/claude-send-command.ts +420 -0
- package/src/server/claude-session-config-helpers.test.ts +279 -0
- package/src/server/claude-session-config-helpers.ts +151 -0
- package/src/server/claude-session-config.test.ts +250 -0
- package/src/server/claude-session-config.ts +159 -0
- package/src/server/claude-session-error-handler.test.ts +498 -0
- package/src/server/claude-session-error-handler.ts +361 -0
- package/src/server/claude-session-lifecycle.test.ts +669 -0
- package/src/server/claude-session-lifecycle.ts +283 -0
- package/src/server/claude-session-rebuild.test.ts +224 -0
- package/src/server/claude-session-rebuild.ts +101 -0
- package/src/server/claude-session-runner.test.ts +523 -0
- package/src/server/claude-session-runner.ts +521 -0
- package/src/server/claude-session-spawner.test.ts +401 -0
- package/src/server/claude-session-spawner.ts +401 -0
- package/src/server/claude-session-start.test.ts +205 -0
- package/src/server/claude-session-start.ts +277 -0
- package/src/server/claude-session-state-queries.test.ts +344 -0
- package/src/server/claude-session-state-queries.ts +160 -0
- package/src/server/claude-session-state.ts +104 -0
- package/src/server/claude-slash-commands.test.ts +277 -0
- package/src/server/claude-slash-commands.ts +234 -0
- package/src/server/claude-spawn-helpers.test.ts +221 -0
- package/src/server/claude-spawn-helpers.ts +179 -0
- package/src/server/claude-steer-log.test.ts +243 -0
- package/src/server/claude-steer-log.ts +58 -0
- package/src/server/claude-subagent-tool-response.test.ts +213 -0
- package/src/server/claude-subagent-tool-response.ts +165 -0
- package/src/server/claude-subagent-wiring.test.ts +263 -0
- package/src/server/claude-subagent-wiring.ts +324 -0
- package/src/server/claude-tool-respond.test.ts +321 -0
- package/src/server/claude-tool-respond.ts +142 -0
- package/src/server/claude-turn-runner.test.ts +310 -0
- package/src/server/claude-turn-runner.ts +228 -0
- package/src/server/claude-turn-starter.test.ts +266 -0
- package/src/server/claude-turn-starter.ts +566 -0
- package/src/server/claude-usage-math.test.ts +169 -0
- package/src/server/claude-usage-math.ts +132 -0
- package/src/server/diff-store-branch-ops.adapter.test.ts +332 -0
- package/src/server/diff-store-branch-ops.adapter.ts +602 -0
- package/src/server/diff-store-commit-ops.adapter.test.ts +358 -0
- package/src/server/diff-store-commit-ops.adapter.ts +258 -0
- package/src/server/diff-store-errors.ts +85 -0
- package/src/server/diff-store-file-ops.adapter.ts +212 -0
- package/src/server/diff-store-git-branch.adapter.ts +686 -0
- package/src/server/diff-store-io.adapter.ts +27 -0
- package/src/server/diff-store-parse.test.ts +212 -0
- package/src/server/diff-store-parse.ts +122 -0
- package/src/server/diff-store-state.ts +82 -0
- package/src/server/diff-store.ts +76 -1854
- package/src/server/event-store-apply.test.ts +280 -0
- package/src/server/event-store-apply.ts +132 -0
- package/src/server/event-store-chat-lifecycle.test.ts +408 -0
- package/src/server/event-store-chat-lifecycle.ts +441 -0
- package/src/server/event-store-entity-write.ts +356 -0
- package/src/server/event-store-helpers.test.ts +230 -0
- package/src/server/event-store-helpers.ts +235 -0
- package/src/server/event-store-init.ts +276 -0
- package/src/server/event-store-messages.adapter.test.ts +365 -0
- package/src/server/event-store-messages.adapter.ts +213 -0
- package/src/server/event-store-orch-subscription.ts +124 -0
- package/src/server/event-store-orch.test.ts +462 -0
- package/src/server/event-store-orch.ts +312 -0
- package/src/server/event-store-peripheral-events.adapter.test.ts +254 -0
- package/src/server/event-store-peripheral-events.adapter.ts +105 -0
- package/src/server/event-store-snapshot.test.ts +597 -0
- package/src/server/event-store-snapshot.ts +658 -0
- package/src/server/event-store-subagent.test.ts +408 -0
- package/src/server/event-store-subagent.ts +198 -0
- package/src/server/event-store-tool-requests.test.ts +210 -0
- package/src/server/event-store-tool-requests.ts +131 -0
- package/src/server/event-store-transcript-write.adapter.ts +285 -0
- package/src/server/event-store-write-ops.test.ts +554 -0
- package/src/server/event-store-write-ops.ts +529 -0
- package/src/server/event-store.test.ts +35 -0
- package/src/server/event-store.ts +251 -2284
- package/src/server/events.ts +3 -0
- package/src/server/harness-types.ts +15 -1
- package/src/server/oauth-errors.ts +19 -0
- package/src/server/read-models.ts +26 -1
- package/src/server/subagent-orchestrator.ts +3 -0
- package/src/server/ws-router-agent-ctrl.test.ts +187 -0
- package/src/server/ws-router-agent-ctrl.ts +137 -0
- package/src/server/ws-router-broadcast.ts +488 -0
- package/src/server/ws-router-chat.test.ts +461 -0
- package/src/server/ws-router-chat.ts +279 -0
- package/src/server/ws-router-defaults.test.ts +283 -0
- package/src/server/ws-router-defaults.ts +434 -0
- package/src/server/ws-router-diff.test.ts +167 -0
- package/src/server/ws-router-diff.ts +250 -0
- package/src/server/ws-router-envelope.ts +329 -0
- package/src/server/ws-router-misc.test.ts +422 -0
- package/src/server/ws-router-misc.ts +265 -0
- package/src/server/ws-router-orch.test.ts +190 -0
- package/src/server/ws-router-orch.ts +93 -0
- package/src/server/ws-router-project.test.ts +403 -0
- package/src/server/ws-router-project.ts +256 -0
- package/src/server/ws-router-push.test.ts +193 -0
- package/src/server/ws-router-push.ts +120 -0
- package/src/server/ws-router-settings.test.ts +173 -0
- package/src/server/ws-router-settings.ts +416 -0
- package/src/server/ws-router-skills.test.ts +194 -0
- package/src/server/ws-router-skills.ts +204 -0
- package/src/server/ws-router-utils.ts +224 -0
- package/src/server/ws-router.ts +339 -2254
- package/src/shared/app-settings-types.ts +365 -0
- package/src/shared/core-types.ts +27 -0
- package/src/shared/git-diff-types.ts +165 -0
- package/src/shared/loop-progress.test.ts +106 -0
- package/src/shared/loop-progress.ts +88 -0
- package/src/shared/mcp-types.ts +105 -0
- package/src/shared/provider-model-types.ts +437 -0
- package/src/shared/subagent-types.ts +198 -0
- package/src/shared/tool-call-types.ts +314 -0
- package/src/shared/transcript-types.ts +270 -0
- package/src/shared/types.ts +27 -1668
- package/dist/client/assets/channel-BMkhjiLI.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C5Kg1XOD.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C5Kg1XOD.js +0 -1
- package/dist/client/assets/index-H6C-f2Vp.css +0 -32
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Ca2U11af.js +0 -1
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
import { type SetupLoopHandlerResult } from "./kanna-mcp"
|
|
2
|
+
import {
|
|
3
|
+
findLastUserMessageId as findLastUserMessageIdFn,
|
|
4
|
+
recreateActiveTurnFromSession as recreateActiveTurnFromSessionFn,
|
|
5
|
+
type SessionRebuildDeps,
|
|
6
|
+
} from "./claude-session-rebuild"
|
|
7
|
+
import type { LoopSetupInput } from "./loop-template"
|
|
8
|
+
import type {
|
|
9
|
+
AgentProvider,
|
|
10
|
+
ChatAttachment,
|
|
11
|
+
LlmProviderSnapshot,
|
|
12
|
+
McpOAuthState,
|
|
13
|
+
McpServerConfig,
|
|
14
|
+
PendingToolSnapshot,
|
|
15
|
+
QueuedChatMessage,
|
|
16
|
+
SlashCommand,
|
|
17
|
+
Subagent,
|
|
18
|
+
} from "../shared/types"
|
|
19
|
+
import type { ClientCommand } from "../shared/protocol"
|
|
20
|
+
import { EventStore } from "./event-store"
|
|
21
|
+
import type { AnalyticsReporter } from "./analytics"
|
|
22
|
+
import { NoopAnalyticsReporter } from "./analytics"
|
|
23
|
+
import { CodexAppServerManager } from "./codex-app-server"
|
|
24
|
+
import { type GenerateChatTitleResult, generateTitleForChatDetailed } from "./generate-title"
|
|
25
|
+
import type { ClaudeSessionHandle, HarnessTurn } from "./harness-types"
|
|
26
|
+
import { startClaudeSession } from "./claude-session-start"
|
|
27
|
+
import { readLlmProviderSnapshot } from "./llm-provider"
|
|
28
|
+
import { type ClaudeDriverPreference } from "../shared/types"
|
|
29
|
+
import type { AutoContinueEvent } from "./auto-continue/events"
|
|
30
|
+
import { ClaudeLimitDetector, CodexLimitDetector, type LimitDetection, type LimitDetector } from "./auto-continue/limit-detector"
|
|
31
|
+
import { ClaudeAuthErrorDetector, type AuthErrorDetection } from "./auto-continue/auth-error-detector"
|
|
32
|
+
import type { ScheduleManager } from "./auto-continue/schedule-manager"
|
|
33
|
+
import type { LoopState } from "./auto-continue/read-model"
|
|
34
|
+
import type { TunnelGateway } from "./cloudflare-tunnel/gateway"
|
|
35
|
+
import { OAuthTokenPool } from "./oauth-pool/oauth-token-pool"
|
|
36
|
+
import { SubagentOrchestrator, type BackgroundRunOutcome, type ProviderRunStart } from "./subagent-orchestrator"
|
|
37
|
+
import {
|
|
38
|
+
buildSubagentProviderRunForChat as buildSubagentProviderRunForChatFn,
|
|
39
|
+
type SubagentWiringDeps,
|
|
40
|
+
type BuildSubagentProviderRunForChatArgs,
|
|
41
|
+
} from "./claude-subagent-wiring"
|
|
42
|
+
import { OrchestrationQueue, type WorkerResult, type WorkerSpawnArgs } from "./orchestration-queue"
|
|
43
|
+
import { createOrchWorktreeOps } from "./orchestration-worktree.adapter"
|
|
44
|
+
import { runCommandInWorktree } from "./orchestration-exec-io.adapter"
|
|
45
|
+
import type { OrchRunDetail, OrchRunInput } from "../shared/orchestration-types"
|
|
46
|
+
import type { ToolCallbackService } from "./tool-callback"
|
|
47
|
+
import type { ChatPermissionPolicy } from "../shared/permission-policy"
|
|
48
|
+
import { POLICY_DEFAULT } from "../shared/permission-policy"
|
|
49
|
+
import { startClaudeSessionPTY, type StartClaudeSessionPtyArgs } from "./claude-pty/driver"
|
|
50
|
+
import {
|
|
51
|
+
type ClaudeSessionConfigHelpersDeps,
|
|
52
|
+
resolveClaudeDriverPreference as resolveClaudeDriverPreferenceFn,
|
|
53
|
+
getEnabledCustomMcpServers as getEnabledCustomMcpServersFn,
|
|
54
|
+
buildOAuthBearers as buildOAuthBearersFn,
|
|
55
|
+
resolveChatPolicy as resolveChatPolicyFn,
|
|
56
|
+
killPtyInstance as killPtyInstanceFn,
|
|
57
|
+
} from "./claude-session-config-helpers"
|
|
58
|
+
import type { AnyValue } from "../shared/errors"
|
|
59
|
+
import { positiveIntegerFromEnv } from "./claude-prompt-helpers"
|
|
60
|
+
import {
|
|
61
|
+
type SendMessageOptions,
|
|
62
|
+
type SendToStartingProfile,
|
|
63
|
+
} from "./claude-steer-log"
|
|
64
|
+
import type { ActiveTurn, ClaudeSessionState } from "./claude-session-state"
|
|
65
|
+
import { runClaudeSession as runClaudeSessionLoop, type RunClaudeSessionDeps } from "./claude-session-runner"
|
|
66
|
+
import {
|
|
67
|
+
startTurnForChat as startTurnForChatFn,
|
|
68
|
+
type StartTurnDeps,
|
|
69
|
+
} from "./claude-turn-starter"
|
|
70
|
+
import { runTurn as runTurnFn, type RunTurnDeps } from "./claude-turn-runner"
|
|
71
|
+
import { spawnClaudeTurn, type SpawnClaudeTurnArgs, type SpawnClaudeTurnDeps } from "./claude-session-spawner"
|
|
72
|
+
import {
|
|
73
|
+
resolveClaudeIdleMs as resolveClaudeIdleMsFn,
|
|
74
|
+
hasLiveWorkflow as hasLiveWorkflowFn,
|
|
75
|
+
hasPendingBackgroundTask as hasPendingBackgroundTaskFn,
|
|
76
|
+
closeClaudeSession as closeClaudeSessionFn,
|
|
77
|
+
maybeRegisterSdkWorkflowsDir as maybeRegisterSdkWorkflowsDirFn,
|
|
78
|
+
enforceClaudeSessionBudget as enforceClaudeSessionBudgetFn,
|
|
79
|
+
buildPoolUnavailableMessage as buildPoolUnavailableMessageFn,
|
|
80
|
+
type SessionLifecycleDeps,
|
|
81
|
+
} from "./claude-session-lifecycle"
|
|
82
|
+
import {
|
|
83
|
+
handleLimitError as handleLimitErrorFn,
|
|
84
|
+
handleLimitDetection as handleLimitDetectionFn,
|
|
85
|
+
handleAuthFailure as handleAuthFailureFn,
|
|
86
|
+
type SessionErrorHandlerDeps,
|
|
87
|
+
type TokenRotationDedupeEntry,
|
|
88
|
+
} from "./claude-session-error-handler"
|
|
89
|
+
import {
|
|
90
|
+
resolveAutoResumeFor as resolveAutoResumeForFn,
|
|
91
|
+
emitAutoContinueEvent as emitAutoContinueEventFn,
|
|
92
|
+
fireAutoContinue as fireAutoContinueFn,
|
|
93
|
+
acceptAutoContinue as acceptAutoContinueFn,
|
|
94
|
+
rescheduleAutoContinue as rescheduleAutoContinueFn,
|
|
95
|
+
cancelAutoContinue as cancelAutoContinueFn,
|
|
96
|
+
type AutoContinueCommandDeps,
|
|
97
|
+
} from "./claude-autocontinue-commands"
|
|
98
|
+
import {
|
|
99
|
+
buildOrchWorker as buildOrchWorkerFn,
|
|
100
|
+
runOrchestration as runOrchestrationFn,
|
|
101
|
+
cancelOrchRun as cancelOrchRunFn,
|
|
102
|
+
getOrchRunDetail as getOrchRunDetailFn,
|
|
103
|
+
deliverSubagentToMain as deliverSubagentToMainFn,
|
|
104
|
+
setupLoop as setupLoopFn,
|
|
105
|
+
isLoopArmed as isLoopArmedFn,
|
|
106
|
+
stopLoop as stopLoopFn,
|
|
107
|
+
listLiveSchedules as listLiveSchedulesFn,
|
|
108
|
+
type LoopOrchCommandDeps,
|
|
109
|
+
} from "./claude-loop-orch-commands"
|
|
110
|
+
import {
|
|
111
|
+
cancelChat as cancelChatFn,
|
|
112
|
+
type CancelHandlerDeps,
|
|
113
|
+
} from "./claude-cancel-handler"
|
|
114
|
+
import {
|
|
115
|
+
stopDraining as stopDrainingFn,
|
|
116
|
+
closeChat as closeChatFn,
|
|
117
|
+
steer as steerFn,
|
|
118
|
+
dequeue as dequeueFn,
|
|
119
|
+
forkChat as forkChatFn,
|
|
120
|
+
generateTitleInBackground as generateTitleInBackgroundFn,
|
|
121
|
+
type ChatManagementDeps,
|
|
122
|
+
} from "./claude-chat-management"
|
|
123
|
+
import {
|
|
124
|
+
respondTool as respondToolFn,
|
|
125
|
+
type ToolRespondDeps,
|
|
126
|
+
} from "./claude-tool-respond"
|
|
127
|
+
import {
|
|
128
|
+
sendCommand as sendCommandFn,
|
|
129
|
+
enqueueMessage as enqueueMessageFn,
|
|
130
|
+
dequeueAndStartQueuedMessage as dequeueAndStartQueuedMessageFn,
|
|
131
|
+
maybeStartNextQueuedMessage as maybeStartNextQueuedMessageFn,
|
|
132
|
+
type SendCommandDeps,
|
|
133
|
+
} from "./claude-send-command"
|
|
134
|
+
import {
|
|
135
|
+
ensureSlashCommandsLoaded as ensureSlashCommandsLoadedFn,
|
|
136
|
+
mergeLocalCatalog as mergeLocalCatalogFn,
|
|
137
|
+
type SlashCommandsDeps,
|
|
138
|
+
} from "./claude-slash-commands"
|
|
139
|
+
import {
|
|
140
|
+
subagentPendingKey as subagentPendingKeyFn,
|
|
141
|
+
rejectPendingResolversForChat as rejectPendingResolversForChatFn,
|
|
142
|
+
rejectPendingResolversForRun as rejectPendingResolversForRunFn,
|
|
143
|
+
respondSubagentTool as respondSubagentToolFn,
|
|
144
|
+
cancelSubagentRun as cancelSubagentRunFn,
|
|
145
|
+
type SubagentToolResponseDeps,
|
|
146
|
+
} from "./claude-subagent-tool-response"
|
|
147
|
+
import {
|
|
148
|
+
getActiveStatuses as getActiveStatusesFn,
|
|
149
|
+
getWaitStartedAtByChatId as getWaitStartedAtByChatIdFn,
|
|
150
|
+
getPendingTool as getPendingToolFn,
|
|
151
|
+
getDrainingChatIds as getDrainingChatIdsFn,
|
|
152
|
+
getSlashCommandsLoadingChatIds as getSlashCommandsLoadingChatIdsFn,
|
|
153
|
+
getClaudeSessionStates as getClaudeSessionStatesFn,
|
|
154
|
+
sweepIdleClaudeSessions as sweepIdleClaudeSessionsFn,
|
|
155
|
+
type SessionStateQueryDeps,
|
|
156
|
+
} from "./claude-session-state-queries"
|
|
157
|
+
import * as agentDepsBuilders from "./agent-deps-builders"
|
|
158
|
+
import type {
|
|
159
|
+
AgentCoordinatorArgs,
|
|
160
|
+
ClaudeSessionLifecycleOptions,
|
|
161
|
+
} from "./agent-coordinator-types"
|
|
162
|
+
|
|
163
|
+
const DEFAULT_CLAUDE_SESSION_IDLE_MS = 10 * 60 * 1000
|
|
164
|
+
const DEFAULT_CLAUDE_SESSION_MAX_RESIDENT = 4
|
|
165
|
+
const DEFAULT_CLAUDE_SESSION_SWEEP_INTERVAL_MS = 60 * 1000
|
|
166
|
+
// Keep a PTY session warm up to 30 min while a background Bash task is pending —
|
|
167
|
+
// comfortably longer than the 10-min idle window and typical CI durations.
|
|
168
|
+
const DEFAULT_PTY_BACKGROUND_TASK_MAX_MS = 30 * 60 * 1000
|
|
169
|
+
// OpenRouter-only watchdog: a stalled upstream leaves the SDK stream open but
|
|
170
|
+
// silent after the session-token handshake, so the runClaudeSession for-await
|
|
171
|
+
// never ends and the existing fail-close never fires. Abort if no transcript
|
|
172
|
+
// entry arrives within this window. system_init is the SDK init echo (precedes
|
|
173
|
+
// model inference), so 2 min is generous; env-tunable per deployment.
|
|
174
|
+
const DEFAULT_OPENROUTER_FIRST_ENTRY_TIMEOUT_MS = 2 * 60 * 1000
|
|
175
|
+
|
|
176
|
+
// Thrown by Claude spawn paths when the OAuth pool has tokens but every one
|
|
177
|
+
// is currently unusable (rate-limited, errored, disabled, or reserved by
|
|
178
|
+
// another chat). `startTurnForChat` catches this and persists `message` as a
|
|
179
|
+
// `result` transcript entry instead of letting it surface as an ephemeral
|
|
180
|
+
// commandError that gets wiped by the next chat snapshot tick.
|
|
181
|
+
// Moved to oauth-errors.ts to avoid a circular import with claude-turn-starter.ts.
|
|
182
|
+
export class AgentCoordinator {
|
|
183
|
+
// Fields accessed by agent-deps-builders.ts are intentionally non-private
|
|
184
|
+
// (readonly instead of private readonly) to allow the external builder
|
|
185
|
+
// functions to read them without bypassing TypeScript's type system.
|
|
186
|
+
// `onStateChange` and `claudeSessionSweepTimer` are truly internal and stay private.
|
|
187
|
+
readonly store: EventStore
|
|
188
|
+
private readonly onStateChange: (chatId?: string, options?: { immediate?: boolean }) => void
|
|
189
|
+
readonly analytics: AnalyticsReporter
|
|
190
|
+
readonly codexManager: CodexAppServerManager
|
|
191
|
+
readonly generateTitle: (messageContent: string, cwd: string) => Promise<GenerateChatTitleResult>
|
|
192
|
+
readonly startClaudeSessionFn: NonNullable<AgentCoordinatorArgs["startClaudeSession"]>
|
|
193
|
+
readonly startClaudeSessionPTYFn: (args: StartClaudeSessionPtyArgs) => Promise<ClaudeSessionHandle>
|
|
194
|
+
reportBackgroundError: ((message: string) => void) | null = null
|
|
195
|
+
readonly activeTurns = new Map<string, ActiveTurn>()
|
|
196
|
+
readonly drainingStreams = new Map<string, { turn: HarnessTurn }>()
|
|
197
|
+
readonly claudeSessions = new Map<string, ClaudeSessionState>()
|
|
198
|
+
readonly mentionedSubagentIdsByChat = new Map<string, string[]>()
|
|
199
|
+
readonly slashCommandsInFlight = new Set<string>()
|
|
200
|
+
readonly claudeLimitDetector: LimitDetector
|
|
201
|
+
readonly codexLimitDetector: LimitDetector
|
|
202
|
+
readonly claudeAuthErrorDetector: ClaudeAuthErrorDetector
|
|
203
|
+
readonly scheduleManager: ScheduleManager | null
|
|
204
|
+
readonly getAutoResumePreference: () => boolean
|
|
205
|
+
readonly getSubagents: () => Subagent[]
|
|
206
|
+
readonly getAppSettingsSnapshot: NonNullable<AgentCoordinatorArgs["getAppSettingsSnapshot"]>
|
|
207
|
+
private readonly subagentOrchestrator: SubagentOrchestrator
|
|
208
|
+
/** Public accessor for tests + the `delegate_subagent` MCP tool wiring. */
|
|
209
|
+
getSubagentOrchestrator(): SubagentOrchestrator {
|
|
210
|
+
return this.subagentOrchestrator
|
|
211
|
+
}
|
|
212
|
+
private readonly orchestrationQueue: OrchestrationQueue
|
|
213
|
+
/** Public accessor for tests + the `orch_*` MCP tool + ws-router wiring. */
|
|
214
|
+
getOrchestrationQueue(): OrchestrationQueue {
|
|
215
|
+
return this.orchestrationQueue
|
|
216
|
+
}
|
|
217
|
+
readonly throwOnClaudeSessionStart: boolean
|
|
218
|
+
readonly autoResumeByChat = new Map<string, boolean>()
|
|
219
|
+
readonly openrouterFirstEntryTimeoutMs: number
|
|
220
|
+
// Per-tokenId rotation dedupe state. When a shared OAuth token throws
|
|
221
|
+
// limit/auth-error against N chats simultaneously, only the first chat
|
|
222
|
+
// pays the cost of marking the pool + picking a fresh target; subsequent
|
|
223
|
+
// chats within TOKEN_ROTATION_DEDUPE_WINDOW_MS reuse the dedupe slot to
|
|
224
|
+
// stagger their respawns by TOKEN_ROTATION_HERD_STAGGER_MS each.
|
|
225
|
+
readonly tokenRotationDedupe = new Map<string, TokenRotationDedupeEntry>()
|
|
226
|
+
// Per-chat circuit breaker for proactive `/compact` injection lives in the
|
|
227
|
+
// persisted ChatRecord (`compactFailureCount`): increments on every compact
|
|
228
|
+
// attempt that fails (turn errored / cancelled) and resets on success.
|
|
229
|
+
// After MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES, skip further proactive
|
|
230
|
+
// compacts on this chat so doomed sessions don't hammer the API on every
|
|
231
|
+
// turn (mirrors claude-code's autoCompact circuit breaker). Persisting it
|
|
232
|
+
// means a server restart cannot reset a doomed chat's breaker to 0.
|
|
233
|
+
readonly tunnelGateway: TunnelGateway | null
|
|
234
|
+
readonly oauthPool: OAuthTokenPool | null
|
|
235
|
+
readonly toolCallback: ToolCallbackService | null
|
|
236
|
+
readonly chatPolicy: ChatPermissionPolicy
|
|
237
|
+
readonly claudeSessionLifecycle: ClaudeSessionLifecycleOptions
|
|
238
|
+
private readonly claudeSessionSweepTimer: ReturnType<typeof setInterval> | null
|
|
239
|
+
readonly claudePtyRegistry: import("./claude-pty/pid-registry.adapter").ClaudePtyRegistry | null
|
|
240
|
+
readonly ptyInstanceRegistry: import("./claude-pty/pty-instance-registry").PtyInstanceRegistry | null
|
|
241
|
+
readonly workflowRegistry: import("./workflow-registry").WorkflowRegistry | null
|
|
242
|
+
readonly subagentTranscriptRegistry: import("./subagent-transcript-registry").SubagentTranscriptRegistry | null
|
|
243
|
+
readonly localCatalog: import("./local-catalog").LocalCatalogService | null
|
|
244
|
+
readonly readLlmProvider: () => Promise<LlmProviderSnapshot>
|
|
245
|
+
readonly listOpenRouterModelsFn: (() => Promise<import("../shared/types").OpenRouterModel[]>) | null
|
|
246
|
+
readonly persistOAuthStateFn: ((id: string, oauth: McpOAuthState) => void) | null
|
|
247
|
+
readonly subagentPendingResolvers = new Map<
|
|
248
|
+
string,
|
|
249
|
+
{ resolve: (v: AnyValue) => void; reject: (e: Error) => void }
|
|
250
|
+
>()
|
|
251
|
+
|
|
252
|
+
constructor(args: AgentCoordinatorArgs) {
|
|
253
|
+
this.store = args.store
|
|
254
|
+
this.onStateChange = args.onStateChange
|
|
255
|
+
this.analytics = args.analytics ?? NoopAnalyticsReporter
|
|
256
|
+
this.codexManager = args.codexManager ?? new CodexAppServerManager()
|
|
257
|
+
this.generateTitle = args.generateTitle ?? generateTitleForChatDetailed
|
|
258
|
+
this.startClaudeSessionFn = args.startClaudeSession ?? startClaudeSession
|
|
259
|
+
this.startClaudeSessionPTYFn = args.startClaudeSessionPTY ?? startClaudeSessionPTY
|
|
260
|
+
this.claudeLimitDetector = args.claudeLimitDetector ?? new ClaudeLimitDetector()
|
|
261
|
+
this.codexLimitDetector = args.codexLimitDetector ?? new CodexLimitDetector()
|
|
262
|
+
this.claudeAuthErrorDetector = new ClaudeAuthErrorDetector()
|
|
263
|
+
this.scheduleManager = args.scheduleManager ?? null
|
|
264
|
+
this.getAutoResumePreference = args.getAutoResumePreference ?? (() => false)
|
|
265
|
+
this.openrouterFirstEntryTimeoutMs =
|
|
266
|
+
args.openrouterFirstEntryTimeoutMs ?? DEFAULT_OPENROUTER_FIRST_ENTRY_TIMEOUT_MS
|
|
267
|
+
this.getSubagents = args.getSubagents ?? (() => [])
|
|
268
|
+
this.getAppSettingsSnapshot = args.getAppSettingsSnapshot ?? (() => ({}))
|
|
269
|
+
this.readLlmProvider = args.readLlmProvider ?? readLlmProviderSnapshot
|
|
270
|
+
this.listOpenRouterModelsFn = args.listOpenRouterModels ?? null
|
|
271
|
+
this.persistOAuthStateFn = args.persistOAuthState ?? null
|
|
272
|
+
this.subagentOrchestrator = new SubagentOrchestrator({
|
|
273
|
+
store: this.store,
|
|
274
|
+
appSettings: { getSnapshot: () => ({ subagents: this.getSubagents() }) },
|
|
275
|
+
startProviderRun: (a) => this.buildSubagentProviderRunForChat({
|
|
276
|
+
subagent: a.subagent,
|
|
277
|
+
chatId: a.chatId,
|
|
278
|
+
primer: a.primer,
|
|
279
|
+
userInstruction: a.userInstruction,
|
|
280
|
+
runId: a.runId,
|
|
281
|
+
abortSignal: a.abortSignal,
|
|
282
|
+
depth: a.depth,
|
|
283
|
+
ancestorSubagentIds: a.ancestorSubagentIds,
|
|
284
|
+
parentUserMessageId: a.parentUserMessageId,
|
|
285
|
+
}),
|
|
286
|
+
onRunTerminal: (chatId, runId) => {
|
|
287
|
+
this.rejectPendingResolversForRun(chatId, runId)
|
|
288
|
+
// failRun appended the terminal event synchronously before invoking
|
|
289
|
+
// this hook, so the store already has the new state. Emit now so
|
|
290
|
+
// multi-subagent fan-outs do not have to wait for Promise.all.
|
|
291
|
+
this.emitStateChange(chatId)
|
|
292
|
+
},
|
|
293
|
+
onRunProgress: (chatId) => {
|
|
294
|
+
// Run start + every persisted subagent entry. Without this the
|
|
295
|
+
// client only gets a snapshot at terminal, so a delegated run
|
|
296
|
+
// renders blank until it finishes (delegate_subagent blocks the
|
|
297
|
+
// main turn, which itself emits nothing meanwhile). ws-router
|
|
298
|
+
// coalesces (16ms) and signature-dedups, so per-entry fan-out is
|
|
299
|
+
// cheap.
|
|
300
|
+
this.emitStateChange(chatId)
|
|
301
|
+
},
|
|
302
|
+
onBackgroundRunComplete: (chatId, runId, outcome) => {
|
|
303
|
+
void this.deliverSubagentToMain(chatId, runId, outcome)
|
|
304
|
+
},
|
|
305
|
+
maxLive: positiveIntegerFromEnv(process.env.KANNA_SUBAGENT_MAX_LIVE, 0) || undefined,
|
|
306
|
+
liveIdleTimeoutMs: positiveIntegerFromEnv(process.env.KANNA_SUBAGENT_IDLE_TIMEOUT_MS, 0) || undefined,
|
|
307
|
+
// Stall/idle watchdog window. Precedence: app setting > env > orchestrator
|
|
308
|
+
// default. The orchestrator reads this once at construction; a settings
|
|
309
|
+
// change takes effect on next server start (acceptable — restart-scoped).
|
|
310
|
+
runTimeoutMs: (this.getAppSettingsSnapshot().subagentRuntime?.runTimeoutMs
|
|
311
|
+
?? positiveIntegerFromEnv(process.env.KANNA_SUBAGENT_RUN_TIMEOUT_MS, 0))
|
|
312
|
+
|| undefined,
|
|
313
|
+
})
|
|
314
|
+
this.orchestrationQueue = new OrchestrationQueue({
|
|
315
|
+
store: this.store,
|
|
316
|
+
worktrees: createOrchWorktreeOps(),
|
|
317
|
+
startWorker: (a) => this.buildOrchWorker(a),
|
|
318
|
+
runVerify: runCommandInWorktree,
|
|
319
|
+
runInit: runCommandInWorktree,
|
|
320
|
+
})
|
|
321
|
+
this.throwOnClaudeSessionStart = args.throwOnClaudeSessionStart ?? false
|
|
322
|
+
this.tunnelGateway = args.tunnelGateway ?? null
|
|
323
|
+
this.oauthPool = args.oauthPool ?? null
|
|
324
|
+
this.toolCallback = args.toolCallback ?? null
|
|
325
|
+
this.chatPolicy = args.chatPolicy ?? POLICY_DEFAULT
|
|
326
|
+
this.claudeSessionLifecycle = {
|
|
327
|
+
idleMs: args.claudeSessionLifecycle?.idleMs
|
|
328
|
+
?? positiveIntegerFromEnv(process.env.KANNA_CLAUDE_SESSION_IDLE_MS, DEFAULT_CLAUDE_SESSION_IDLE_MS),
|
|
329
|
+
maxResidentSessions: args.claudeSessionLifecycle?.maxResidentSessions
|
|
330
|
+
?? positiveIntegerFromEnv(process.env.KANNA_CLAUDE_SESSION_MAX_RESIDENT, DEFAULT_CLAUDE_SESSION_MAX_RESIDENT),
|
|
331
|
+
sweepIntervalMs: args.claudeSessionLifecycle?.sweepIntervalMs
|
|
332
|
+
?? positiveIntegerFromEnv(process.env.KANNA_CLAUDE_SESSION_SWEEP_INTERVAL_MS, DEFAULT_CLAUDE_SESSION_SWEEP_INTERVAL_MS),
|
|
333
|
+
backgroundTaskMaxMs: args.claudeSessionLifecycle?.backgroundTaskMaxMs
|
|
334
|
+
?? positiveIntegerFromEnv(process.env.KANNA_PTY_BACKGROUND_TASK_MAX_MS, DEFAULT_PTY_BACKGROUND_TASK_MAX_MS),
|
|
335
|
+
}
|
|
336
|
+
this.claudeSessionSweepTimer = this.claudeSessionLifecycle.sweepIntervalMs > 0
|
|
337
|
+
? setInterval(() => { this.sweepIdleClaudeSessions() }, this.claudeSessionLifecycle.sweepIntervalMs)
|
|
338
|
+
: null
|
|
339
|
+
this.claudeSessionSweepTimer?.unref?.()
|
|
340
|
+
this.claudePtyRegistry = args.claudePtyRegistry ?? null
|
|
341
|
+
this.ptyInstanceRegistry = args.ptyInstanceRegistry ?? null
|
|
342
|
+
this.workflowRegistry = args.workflowRegistry ?? null
|
|
343
|
+
this.subagentTranscriptRegistry = args.subagentTranscriptRegistry ?? null
|
|
344
|
+
this.localCatalog = args.localCatalog ?? null
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
setBackgroundErrorReporter(report: ((message: string) => void) | null) {
|
|
348
|
+
this.reportBackgroundError = report
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
dispose() {
|
|
352
|
+
if (this.claudeSessionSweepTimer) clearInterval(this.claudeSessionSweepTimer)
|
|
353
|
+
for (const [chatId, session] of [...this.claudeSessions.entries()]) {
|
|
354
|
+
this.closeClaudeSession(chatId, session)
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
getActiveStatuses() {
|
|
359
|
+
return getActiveStatusesFn(this.buildSessionStateQueryDeps())
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
getWaitStartedAtByChatId(): Map<string, number> {
|
|
363
|
+
return getWaitStartedAtByChatIdFn(this.buildSessionStateQueryDeps())
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
getPendingTool(chatId: string): PendingToolSnapshot | null {
|
|
367
|
+
return getPendingToolFn(this.buildSessionStateQueryDeps(), chatId)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
getDrainingChatIds(): Set<string> {
|
|
371
|
+
return getDrainingChatIdsFn(this.buildSessionStateQueryDeps())
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
getSlashCommandsLoadingChatIds(): Set<string> {
|
|
375
|
+
return getSlashCommandsLoadingChatIdsFn(this.buildSessionStateQueryDeps())
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Snapshot of live claude PTY session states per chat. Used by the
|
|
380
|
+
* sidebar badge selector. Chats not present are implicitly `cold`.
|
|
381
|
+
*/
|
|
382
|
+
getClaudeSessionStates(): Map<string, "warming" | "active" | "idle"> {
|
|
383
|
+
return getClaudeSessionStatesFn(this.buildSessionStateQueryDeps())
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
get toolCallbackService(): ToolCallbackService | null {
|
|
387
|
+
return this.toolCallback
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/** @internal used by agent-deps-builders.ts */
|
|
391
|
+
emitStateChange(chatId?: string, options?: { immediate?: boolean }) {
|
|
392
|
+
this.onStateChange(chatId, options)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ---------------------------------------------------------------------------
|
|
396
|
+
// Session config helpers deps builder
|
|
397
|
+
// ---------------------------------------------------------------------------
|
|
398
|
+
|
|
399
|
+
private buildClaudeSessionConfigHelpersDeps(): ClaudeSessionConfigHelpersDeps {
|
|
400
|
+
return agentDepsBuilders.buildClaudeSessionConfigHelpersDeps(this)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** @internal used by agent-deps-builders.ts */
|
|
404
|
+
resolveClaudeDriverPreference(): ClaudeDriverPreference {
|
|
405
|
+
return resolveClaudeDriverPreferenceFn(this.buildClaudeSessionConfigHelpersDeps())
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** @internal used by agent-deps-builders.ts */
|
|
409
|
+
getEnabledCustomMcpServers(): readonly McpServerConfig[] {
|
|
410
|
+
return getEnabledCustomMcpServersFn(this.buildClaudeSessionConfigHelpersDeps())
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** @internal used by agent-deps-builders.ts */
|
|
414
|
+
async buildOAuthBearers(servers: readonly McpServerConfig[]): Promise<Map<string, string>> {
|
|
415
|
+
return buildOAuthBearersFn(this.buildClaudeSessionConfigHelpersDeps(), servers)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/** @internal used by agent-deps-builders.ts */
|
|
419
|
+
resolveChatPolicy(chatId: string): ChatPermissionPolicy {
|
|
420
|
+
return resolveChatPolicyFn(this.buildClaudeSessionConfigHelpersDeps(), chatId)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// ---------------------------------------------------------------------------
|
|
424
|
+
// Session lifecycle deps builder — wires this.* refs into SessionLifecycleDeps
|
|
425
|
+
// ---------------------------------------------------------------------------
|
|
426
|
+
|
|
427
|
+
private buildSessionLifecycleDeps(): SessionLifecycleDeps {
|
|
428
|
+
return agentDepsBuilders.buildSessionLifecycleDeps(this)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
private buildSessionErrorHandlerDeps(): SessionErrorHandlerDeps {
|
|
432
|
+
return agentDepsBuilders.buildSessionErrorHandlerDeps(this)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ---------------------------------------------------------------------------
|
|
436
|
+
// Auto-continue command deps builder — wires this.* refs into AutoContinueCommandDeps
|
|
437
|
+
// ---------------------------------------------------------------------------
|
|
438
|
+
|
|
439
|
+
private buildAutoContinueCommandDeps(): AutoContinueCommandDeps {
|
|
440
|
+
return agentDepsBuilders.buildAutoContinueCommandDeps(this)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
private buildLoopOrchCommandDeps(): LoopOrchCommandDeps {
|
|
444
|
+
return agentDepsBuilders.buildLoopOrchCommandDeps(this)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ---------------------------------------------------------------------------
|
|
448
|
+
// Cancel handler deps builder — wires this.* refs into CancelHandlerDeps
|
|
449
|
+
// ---------------------------------------------------------------------------
|
|
450
|
+
|
|
451
|
+
private buildCancelHandlerDeps(): CancelHandlerDeps {
|
|
452
|
+
return agentDepsBuilders.buildCancelHandlerDeps(this)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// ---------------------------------------------------------------------------
|
|
456
|
+
// Chat management deps builder — wires this.* refs into ChatManagementDeps
|
|
457
|
+
// ---------------------------------------------------------------------------
|
|
458
|
+
|
|
459
|
+
private buildChatManagementDeps(): ChatManagementDeps {
|
|
460
|
+
return agentDepsBuilders.buildChatManagementDeps(this)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ---------------------------------------------------------------------------
|
|
464
|
+
// Send command deps builder — wires this.* refs into SendCommandDeps
|
|
465
|
+
// ---------------------------------------------------------------------------
|
|
466
|
+
|
|
467
|
+
private buildSendCommandDeps(): SendCommandDeps {
|
|
468
|
+
return agentDepsBuilders.buildSendCommandDeps(this)
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ---------------------------------------------------------------------------
|
|
472
|
+
// Subagent wiring deps builder — wires this.* refs into SubagentWiringDeps
|
|
473
|
+
// ---------------------------------------------------------------------------
|
|
474
|
+
|
|
475
|
+
private buildSubagentWiringDeps(): SubagentWiringDeps {
|
|
476
|
+
return agentDepsBuilders.buildSubagentWiringDeps(this)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
private buildSlashCommandsDeps(): SlashCommandsDeps {
|
|
480
|
+
return agentDepsBuilders.buildSlashCommandsDeps(this)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** @internal used by agent-deps-builders.ts */
|
|
484
|
+
resolveClaudeIdleMs(): number {
|
|
485
|
+
return resolveClaudeIdleMsFn(this.buildSessionLifecycleDeps())
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* True when the chat is hosting an in-flight background Workflow. A live
|
|
490
|
+
* workflow runs inside the warm PTY claude process but registers no
|
|
491
|
+
* activeTurn, pendingPromptSeq, or lastUsedAt bump, so without this signal
|
|
492
|
+
* the idle reaper / budget enforcer would tear the process down mid-run and
|
|
493
|
+
* abort the workflow.
|
|
494
|
+
*
|
|
495
|
+
* Liveness comes from the registry's live-run-dir probe, NOT the terminal
|
|
496
|
+
* `wf_<runId>.json` sidecar: Claude only flushes that sidecar at/near
|
|
497
|
+
* termination, so a sidecar-only check is blind for the entire run (the
|
|
498
|
+
* window the guard must cover). `hasActiveRun` reads the live
|
|
499
|
+
* `subagents/workflows/wf_*` transcript dirs (written from second one) and
|
|
500
|
+
* requires activity within one idle window so a stalled/crashed run still
|
|
501
|
+
* eventually reaps.
|
|
502
|
+
* @internal used by agent-deps-builders.ts
|
|
503
|
+
*/
|
|
504
|
+
hasLiveWorkflow(chatId: string): boolean {
|
|
505
|
+
return hasLiveWorkflowFn(this.buildSessionLifecycleDeps(), chatId)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/** @internal used by agent-deps-builders.ts */
|
|
509
|
+
resolveBackgroundTaskMaxMs(): number {
|
|
510
|
+
return this.claudeSessionLifecycle.backgroundTaskMaxMs
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* True while the session has at least one Claude-Code background Bash task
|
|
515
|
+
* that has not yet settled. Primary gate is set size > 0: settle events
|
|
516
|
+
* (task_notification) remove their id from the set, so the guard clears the
|
|
517
|
+
* moment the last task reports. The deadline is a zombie backstop only —
|
|
518
|
+
* it fires when a settle notification is genuinely lost (SDK crash / dropped
|
|
519
|
+
* message) and is reset on every launch and settle, so it never expires
|
|
520
|
+
* during normal execution regardless of task duration.
|
|
521
|
+
* @internal used by agent-deps-builders.ts
|
|
522
|
+
*/
|
|
523
|
+
hasPendingBackgroundTask(session: ClaudeSessionState, now: number): boolean {
|
|
524
|
+
return hasPendingBackgroundTaskFn(session, now)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Tear down a Claude session and (by default) release the OAuth-pool
|
|
529
|
+
* reservation owned by the chat.
|
|
530
|
+
*
|
|
531
|
+
* `keepReservation: true` — used by rate-limit / auth-error rotation
|
|
532
|
+
* paths that have ALREADY claimed a fresh token via `pickActive(chatId)`
|
|
533
|
+
* before calling close. Without this flag, `release(chatId)` would
|
|
534
|
+
* scan reservedBy for `owner === chatId` and drop the *new* token the
|
|
535
|
+
* rotation just claimed, leaking the rotation's reservation (audit #9d).
|
|
536
|
+
* @internal used by agent-deps-builders.ts
|
|
537
|
+
*/
|
|
538
|
+
closeClaudeSession(
|
|
539
|
+
chatId: string,
|
|
540
|
+
session: ClaudeSessionState,
|
|
541
|
+
opts?: { keepReservation?: boolean },
|
|
542
|
+
): void {
|
|
543
|
+
closeClaudeSessionFn(this.buildSessionLifecycleDeps(), chatId, session, opts)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Register the workflow disk-watch dir for an SDK session once the session
|
|
548
|
+
* token is known. No-op if the registry is absent, already registered, or
|
|
549
|
+
* the driver preference is PTY (the PTY driver registers from its own
|
|
550
|
+
* resolved transcript path in driver.ts cleanup and must not be double-fired).
|
|
551
|
+
* @internal used by agent-deps-builders.ts
|
|
552
|
+
*/
|
|
553
|
+
maybeRegisterSdkWorkflowsDir(session: ClaudeSessionState): void {
|
|
554
|
+
maybeRegisterSdkWorkflowsDirFn(this.buildSessionLifecycleDeps(), session)
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
private sweepIdleClaudeSessions(now = Date.now()): void {
|
|
558
|
+
sweepIdleClaudeSessionsFn(this.buildSessionStateQueryDeps(), now)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/** @internal used by agent-deps-builders.ts */
|
|
562
|
+
enforceClaudeSessionBudget(protectedChatId?: string): void {
|
|
563
|
+
enforceClaudeSessionBudgetFn(this.buildSessionLifecycleDeps(), protectedChatId)
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Format a refusal message when `pickActive(chatId)` returned null but the
|
|
568
|
+
* pool has tokens. Names the offending tokens so the user knows which
|
|
569
|
+
* chat to close or which token to add a quota to, instead of seeing the
|
|
570
|
+
* generic "all tokens unavailable" line that doesn't say what's holding
|
|
571
|
+
* them. `scopeSuffix` lets the subagent path tag its variant.
|
|
572
|
+
* @internal used by agent-deps-builders.ts
|
|
573
|
+
*/
|
|
574
|
+
buildPoolUnavailableMessage(reservedFor: string, scopeSuffix: string): string {
|
|
575
|
+
return buildPoolUnavailableMessageFn(this.buildSessionLifecycleDeps(), reservedFor, scopeSuffix)
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
private buildSubagentToolResponseDeps(): SubagentToolResponseDeps {
|
|
579
|
+
return agentDepsBuilders.buildSubagentToolResponseDeps(this)
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
private buildToolRespondDeps(): ToolRespondDeps {
|
|
583
|
+
return agentDepsBuilders.buildToolRespondDeps(this)
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
private buildSessionStateQueryDeps(): SessionStateQueryDeps {
|
|
587
|
+
return agentDepsBuilders.buildSessionStateQueryDeps(this)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/** @internal used by agent-deps-builders.ts */
|
|
591
|
+
subagentPendingKey(chatId: string, runId: string, toolUseId: string): string {
|
|
592
|
+
return subagentPendingKeyFn(chatId, runId, toolUseId)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/** @internal used by agent-deps-builders.ts */
|
|
596
|
+
rejectPendingResolversForChat(chatId: string): void {
|
|
597
|
+
rejectPendingResolversForChatFn({ subagentPendingResolvers: this.subagentPendingResolvers }, chatId)
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
private rejectPendingResolversForRun(chatId: string, runId: string): void {
|
|
601
|
+
rejectPendingResolversForRunFn({ subagentPendingResolvers: this.subagentPendingResolvers }, chatId, runId)
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
getActiveTurnProfile(chatId: string): SendToStartingProfile | null {
|
|
605
|
+
const active = this.activeTurns.get(chatId)
|
|
606
|
+
if (!active?.clientTraceId || active.profilingStartedAt === undefined) {
|
|
607
|
+
return null
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return {
|
|
611
|
+
traceId: active.clientTraceId,
|
|
612
|
+
startedAt: active.profilingStartedAt,
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/** @internal used by agent-deps-builders.ts */
|
|
617
|
+
clearDrainingStream(chatId: string): void {
|
|
618
|
+
this.drainingStreams.delete(chatId)
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
async stopDraining(chatId: string) {
|
|
622
|
+
return stopDrainingFn(this.buildChatManagementDeps(), chatId)
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
async ensureSlashCommandsLoaded(chatId: string): Promise<void> {
|
|
626
|
+
return ensureSlashCommandsLoadedFn(this.buildSlashCommandsDeps(), chatId)
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/** @internal used by agent-deps-builders.ts via buildRunClaudeSessionDeps / buildSpawnClaudeTurnDeps */
|
|
630
|
+
mergeLocalCatalog(commands: SlashCommand[], cwd: string): SlashCommand[] {
|
|
631
|
+
return mergeLocalCatalogFn(this.buildSlashCommandsDeps(), commands, cwd)
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
async closeChat(chatId: string) {
|
|
635
|
+
return closeChatFn(this.buildChatManagementDeps(), chatId)
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/** @internal Delegates to enqueueMessageFn — see claude-send-command.ts. */
|
|
639
|
+
async enqueueMessage(chatId: string, content: string, attachments: ChatAttachment[], options?: SendMessageOptions) {
|
|
640
|
+
return enqueueMessageFn(this.buildSendCommandDeps(), chatId, content, attachments, options)
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/** @internal Delegates to dequeueAndStartQueuedMessageFn — see claude-send-command.ts. */
|
|
644
|
+
async dequeueAndStartQueuedMessage(chatId: string, queuedMessage: QueuedChatMessage, options?: { steered?: boolean }) {
|
|
645
|
+
return dequeueAndStartQueuedMessageFn(this.buildSendCommandDeps(), chatId, queuedMessage, options)
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/** @internal Delegates to maybeStartNextQueuedMessageFn — see claude-send-command.ts. */
|
|
649
|
+
async maybeStartNextQueuedMessage(chatId: string) {
|
|
650
|
+
return maybeStartNextQueuedMessageFn(this.buildSendCommandDeps(), chatId)
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
private buildStartTurnDeps(): StartTurnDeps {
|
|
654
|
+
return agentDepsBuilders.buildStartTurnDeps(this)
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/** @internal used by agent-deps-builders.ts (via RunTurnDeps + SendCommandDeps). */
|
|
658
|
+
async startTurnForChat(args: {
|
|
659
|
+
chatId: string
|
|
660
|
+
provider: AgentProvider
|
|
661
|
+
content: string
|
|
662
|
+
attachments: ChatAttachment[]
|
|
663
|
+
model: string
|
|
664
|
+
effort?: string
|
|
665
|
+
serviceTier?: "fast"
|
|
666
|
+
planMode: boolean
|
|
667
|
+
appendUserPrompt: boolean
|
|
668
|
+
steered?: boolean
|
|
669
|
+
autoContinue?: { scheduleId: string }
|
|
670
|
+
userClearedContext?: boolean
|
|
671
|
+
profile?: SendToStartingProfile | null
|
|
672
|
+
}) {
|
|
673
|
+
return startTurnForChatFn(this.buildStartTurnDeps(), args)
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
private buildSessionRebuildDeps(): SessionRebuildDeps {
|
|
678
|
+
return agentDepsBuilders.buildSessionRebuildDeps(this)
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/** @internal used by agent-deps-builders.ts via buildStartTurnDeps */
|
|
682
|
+
recreateActiveTurnFromSession(args: {
|
|
683
|
+
chatId: string
|
|
684
|
+
provider: AgentProvider
|
|
685
|
+
model: string
|
|
686
|
+
effort?: string
|
|
687
|
+
serviceTier?: "fast"
|
|
688
|
+
planMode: boolean
|
|
689
|
+
clientTraceId?: string
|
|
690
|
+
}): ActiveTurn | undefined {
|
|
691
|
+
return recreateActiveTurnFromSessionFn(this.buildSessionRebuildDeps(), args)
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/** @internal used by agent-deps-builders.ts via buildStartTurnDeps */
|
|
695
|
+
findLastUserMessageId(chatId: string): string | null {
|
|
696
|
+
return findLastUserMessageIdFn(this.buildSessionRebuildDeps(), chatId)
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private buildSpawnClaudeTurnDeps(): SpawnClaudeTurnDeps {
|
|
700
|
+
return agentDepsBuilders.buildSpawnClaudeTurnDeps(this)
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/** @internal used by agent-deps-builders.ts via buildStartTurnDeps */
|
|
704
|
+
startClaudeTurn(args: SpawnClaudeTurnArgs): Promise<HarnessTurn> {
|
|
705
|
+
return spawnClaudeTurn(this.buildSpawnClaudeTurnDeps(), args)
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/** Delegates to sendCommandFn — see claude-send-command.ts. */
|
|
709
|
+
async send(command: Extract<ClientCommand, { type: "chat.send" }>) {
|
|
710
|
+
return sendCommandFn(this.buildSendCommandDeps(), command)
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/** @internal used by agent-deps-builders.ts via buildLoopOrchCommandDeps; Delegates to buildSubagentProviderRunForChatFn. */
|
|
714
|
+
buildSubagentProviderRunForChat(args: BuildSubagentProviderRunForChatArgs): ProviderRunStart {
|
|
715
|
+
return buildSubagentProviderRunForChatFn(this.buildSubagentWiringDeps(), args)
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* StartWorker adapter for the OrchestrationQueue: spawn the run's configured
|
|
720
|
+
* worker subagent against the task worktree (`spawn.cwd`) with the phase
|
|
721
|
+
* prompt. Origin chat + subagent are read from the persisted run config so
|
|
722
|
+
* this resolves identically on a fresh run and after a restart.
|
|
723
|
+
*/
|
|
724
|
+
/** Delegates to buildOrchWorkerFn — see claude-loop-orch-commands.ts. */
|
|
725
|
+
private async buildOrchWorker(spawn: WorkerSpawnArgs): Promise<WorkerResult> {
|
|
726
|
+
return buildOrchWorkerFn(this.buildLoopOrchCommandDeps(), spawn)
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* User-callable entry point (MCP `orch_run` + ws `orch.run`). Validates the
|
|
731
|
+
* task list into the fixed linear config, then starts the run. Returns the
|
|
732
|
+
* runId or the flat validation error list — never a partial run.
|
|
733
|
+
* Delegates to runOrchestrationFn — see claude-loop-orch-commands.ts.
|
|
734
|
+
*/
|
|
735
|
+
async runOrchestration(
|
|
736
|
+
chatId: string,
|
|
737
|
+
input: OrchRunInput,
|
|
738
|
+
): Promise<{ ok: true; runId: string } | { ok: false; errors: string[] }> {
|
|
739
|
+
return runOrchestrationFn(this.buildLoopOrchCommandDeps(), chatId, input)
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/** Cancel a run (MCP `orch_cancel_run` + ws `orch.cancelRun`). Delegates to cancelOrchRunFn. */
|
|
743
|
+
async cancelOrchRun(runId: string): Promise<void> {
|
|
744
|
+
return cancelOrchRunFn(this.buildLoopOrchCommandDeps(), runId)
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/** Canonical run detail DTO (MCP `orch_run_status` + ws `orch.getRun`). Delegates to getOrchRunDetailFn. */
|
|
748
|
+
getOrchRunDetail(runId: string): OrchRunDetail | null {
|
|
749
|
+
return getOrchRunDetailFn(this.buildLoopOrchCommandDeps(), runId)
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
async enqueue(command: Extract<ClientCommand, { type: "message.enqueue" }>) {
|
|
753
|
+
if (typeof command.autoResumeOnRateLimit === "boolean") {
|
|
754
|
+
this.autoResumeByChat.set(command.chatId, command.autoResumeOnRateLimit)
|
|
755
|
+
}
|
|
756
|
+
this.analytics.track("message_sent")
|
|
757
|
+
const queuedMessage = await this.enqueueMessage(command.chatId, command.content, command.attachments ?? [], {
|
|
758
|
+
provider: command.provider,
|
|
759
|
+
model: command.model,
|
|
760
|
+
modelOptions: command.modelOptions,
|
|
761
|
+
planMode: command.planMode,
|
|
762
|
+
})
|
|
763
|
+
return { queuedMessageId: queuedMessage.id }
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
async steer(command: Extract<ClientCommand, { type: "message.steer" }>) {
|
|
767
|
+
return steerFn(this.buildChatManagementDeps(), command)
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
async dequeue(command: Extract<ClientCommand, { type: "message.dequeue" }>) {
|
|
771
|
+
return dequeueFn(this.buildChatManagementDeps(), command)
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
async forkChat(chatId: string) {
|
|
775
|
+
return forkChatFn(this.buildChatManagementDeps(), chatId)
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
private buildRunClaudeSessionDeps(): RunClaudeSessionDeps {
|
|
779
|
+
return agentDepsBuilders.buildRunClaudeSessionDeps(this)
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/** @internal used by agent-deps-builders.ts via buildSpawnClaudeTurnDeps */
|
|
783
|
+
async runClaudeSession(session: ClaudeSessionState) {
|
|
784
|
+
return runClaudeSessionLoop(this.buildRunClaudeSessionDeps(), session)
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/** @internal used by agent-deps-builders.ts via buildChatManagementDeps */
|
|
788
|
+
async generateTitleInBackground(chatId: string, messageContent: string, cwd: string, expectedCurrentTitle: string) {
|
|
789
|
+
return generateTitleInBackgroundFn(this.buildChatManagementDeps(), chatId, messageContent, cwd, expectedCurrentTitle)
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
private buildRunTurnDeps(): RunTurnDeps {
|
|
793
|
+
return agentDepsBuilders.buildRunTurnDeps(this)
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/** @internal used by agent-deps-builders.ts via buildStartTurnDeps; Delegates to runTurnFn. */
|
|
797
|
+
async runTurn(active: ActiveTurn): Promise<void> {
|
|
798
|
+
return runTurnFn(this.buildRunTurnDeps(), active)
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/** @internal used by agent-deps-builders.ts via buildSessionErrorHandlerDeps; Delegates to resolveAutoResumeForFn. */
|
|
802
|
+
resolveAutoResumeFor(chatId: string): boolean {
|
|
803
|
+
return resolveAutoResumeForFn(this.buildAutoContinueCommandDeps(), chatId)
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/** @internal used by agent-deps-builders.ts via buildSessionErrorHandlerDeps + buildLoopOrchCommandDeps; Delegates to emitAutoContinueEventFn. */
|
|
807
|
+
async emitAutoContinueEvent(event: AutoContinueEvent): Promise<void> {
|
|
808
|
+
return emitAutoContinueEventFn(this.buildAutoContinueCommandDeps(), event)
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/** @internal used by agent-deps-builders.ts via buildRunClaudeSessionDeps + buildRunTurnDeps; Delegates to handleLimitErrorFn. */
|
|
812
|
+
async handleLimitError(chatId: string, detector: LimitDetector, error: AnyValue): Promise<boolean> {
|
|
813
|
+
return handleLimitErrorFn(this.buildSessionErrorHandlerDeps(), chatId, detector, error)
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/** @internal used by agent-deps-builders.ts via buildRunClaudeSessionDeps; Delegates to handleLimitDetectionFn. */
|
|
817
|
+
async handleLimitDetection(chatId: string, detection: LimitDetection): Promise<boolean> {
|
|
818
|
+
return handleLimitDetectionFn(this.buildSessionErrorHandlerDeps(), chatId, detection)
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/** @internal used by agent-deps-builders.ts via buildRunClaudeSessionDeps; Delegates to handleAuthFailureFn. */
|
|
822
|
+
async handleAuthFailure(
|
|
823
|
+
session: ClaudeSessionState,
|
|
824
|
+
detection: AuthErrorDetection,
|
|
825
|
+
): Promise<boolean> {
|
|
826
|
+
return handleAuthFailureFn(this.buildSessionErrorHandlerDeps(), session, detection)
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/** Delegates to fireAutoContinueFn — see claude-autocontinue-commands.ts. */
|
|
830
|
+
async fireAutoContinue(chatId: string, scheduleId: string) {
|
|
831
|
+
return fireAutoContinueFn(this.buildAutoContinueCommandDeps(), chatId, scheduleId)
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/** Delegates to acceptAutoContinueFn — see claude-autocontinue-commands.ts. */
|
|
835
|
+
async acceptAutoContinue(chatId: string, scheduleId: string, scheduledAt: number): Promise<void> {
|
|
836
|
+
return acceptAutoContinueFn(this.buildAutoContinueCommandDeps(), chatId, scheduleId, scheduledAt)
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/** Delegates to rescheduleAutoContinueFn — see claude-autocontinue-commands.ts. */
|
|
840
|
+
async rescheduleAutoContinue(chatId: string, scheduleId: string, scheduledAt: number): Promise<void> {
|
|
841
|
+
return rescheduleAutoContinueFn(this.buildAutoContinueCommandDeps(), chatId, scheduleId, scheduledAt)
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/** Delegates to cancelAutoContinueFn — see claude-autocontinue-commands.ts. */
|
|
845
|
+
async cancelAutoContinue(chatId: string, scheduleId: string, reason: "user" | "chat_deleted"): Promise<void> {
|
|
846
|
+
return cancelAutoContinueFn(this.buildAutoContinueCommandDeps(), chatId, scheduleId, reason)
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Deliver a finished `run_in_background` subagent's result back into the
|
|
851
|
+
* main chat as a fresh turn AND clear the main-agent's Claude session so the
|
|
852
|
+
* next turn starts with a fresh context window. Wired as the orchestrator's
|
|
853
|
+
* `onBackgroundRunComplete` hook. Delegates to deliverSubagentToMainFn —
|
|
854
|
+
* see claude-loop-orch-commands.ts.
|
|
855
|
+
*/
|
|
856
|
+
private async deliverSubagentToMain(
|
|
857
|
+
chatId: string,
|
|
858
|
+
runId: string,
|
|
859
|
+
outcome: BackgroundRunOutcome,
|
|
860
|
+
): Promise<void> {
|
|
861
|
+
return deliverSubagentToMainFn(this.buildLoopOrchCommandDeps(), chatId, runId, outcome)
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Arm an autonomous loop on the main chat. Validates the loop spec, ensures
|
|
866
|
+
* the tracking file exists (writes a skeleton if absent), then /clears the
|
|
867
|
+
* main-agent Claude session and enqueues the templated recurring prompt so
|
|
868
|
+
* the next turn starts the loop. Backs `mcp__kanna__setup_loop`. Delegates
|
|
869
|
+
* to setupLoopFn — see claude-loop-orch-commands.ts.
|
|
870
|
+
*/
|
|
871
|
+
async setupLoop(args: {
|
|
872
|
+
chatId: string
|
|
873
|
+
input: LoopSetupInput
|
|
874
|
+
}): Promise<SetupLoopHandlerResult> {
|
|
875
|
+
return setupLoopFn(this.buildLoopOrchCommandDeps(), args)
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/** Current armed-loop state for a chat, or null. Delegates to isLoopArmedFn — see claude-loop-orch-commands.ts. */
|
|
879
|
+
isLoopArmed(chatId: string): LoopState | null {
|
|
880
|
+
return isLoopArmedFn(this.buildLoopOrchCommandDeps(), chatId)
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Disarm an armed loop (restores tools + stops prompt re-injection). Backs
|
|
885
|
+
* the `stop_loop` MCP tool (called by the model on GOAL MET) and the
|
|
886
|
+
* user-send takeover path. No-op when no loop is armed. Delegates to
|
|
887
|
+
* stopLoopFn — see claude-loop-orch-commands.ts.
|
|
888
|
+
*/
|
|
889
|
+
async stopLoop(chatId: string, reason: "goal_met" | "user_send" | "chat_deleted"): Promise<void> {
|
|
890
|
+
return stopLoopFn(this.buildLoopOrchCommandDeps(), chatId, reason)
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/** Delegates to listLiveSchedulesFn — see claude-loop-orch-commands.ts. */
|
|
894
|
+
listLiveSchedules(chatId: string): string[] {
|
|
895
|
+
return listLiveSchedulesFn(this.buildLoopOrchCommandDeps(), chatId)
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
async killPtyInstance(chatId: string): Promise<void> {
|
|
899
|
+
return killPtyInstanceFn(this.buildClaudeSessionConfigHelpersDeps(), chatId)
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
async cancel(chatId: string, options?: { hideInterrupted?: boolean; skipQueueDrain?: boolean }) {
|
|
903
|
+
return cancelChatFn(this.buildCancelHandlerDeps(), chatId, options)
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
async respondTool(command: Extract<ClientCommand, { type: "chat.respondTool" }>) {
|
|
907
|
+
return respondToolFn(this.buildToolRespondDeps(), command)
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
async respondSubagentTool(command: Extract<ClientCommand, { type: "chat.respondSubagentTool" }>) {
|
|
911
|
+
return respondSubagentToolFn(this.buildSubagentToolResponseDeps(), command)
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
async cancelSubagentRun(
|
|
915
|
+
command: Extract<ClientCommand, { type: "chat.cancelSubagentRun" }>,
|
|
916
|
+
) {
|
|
917
|
+
cancelSubagentRunFn(this.buildSubagentToolResponseDeps(), command)
|
|
918
|
+
}
|
|
919
|
+
}
|