chainlesschain 0.162.161 → 0.162.162
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/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-DMn528q-.js → AIOps-ClI2ALgv.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-D9ZcDCJL.js → ActionButton-BDjRcJaK.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-A_K-8PX0.js → Analytics-DikSRsaT.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-D4pFW3X6.js → AppLayout-9mLhMFmz.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-Dz46COAd.js → Artifacts-BSr88BrH.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-cbMjbyg0.js → Audit-CdvyimOF.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Dtf88GAj.js → BackgroundAgents-D3_hCedh.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-C5KRxn52.js → Backup-Cyvv9RHf.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Dd2UK3BN.js → BaseInput-BZM14kt8.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-lptKTFdG.js → Chat-DrQSokVz.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-C2KLtwHz.js → ChatBubbleRenderer-HwJR-C6B.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-_yspG6rG.js → Checkbox-bFLYeWMV.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BGq_GAha.js → Codegen-7mN7xJXT.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CePor71g.js → Col-DAB5ZWm7.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CLOWhIT7.js → Community-B_1TymaK.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CivJt2vT.js → Compact-Bq1uSWLJ.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Btmo1GGE.js → Compliance-CyiE1jEe.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Ct35OlG4.js → Cowork-Cpk0D7vm.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CTc2GmhB.js → Cron-d_Lv3rdB.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-ZtiBETk1.js → Crosschain-DMqhHjMR.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BNqMQQXw.js → DID-Br-oPuBw.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BmzZd-9V.js → Dashboard-CfLW_RaP.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CMVgvP2M.js → Dropdown-DZnTOExV.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CcqQFAfT.js → EmailListRenderer-DHIUHDv1.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CTqB1_4V.js → FamilyGuardDashboard-Bw3t3myu.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CiKOOzlb.js → Federation-D9cpQPAY.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Wk-OT0gr.js → FormItemContext-Jdczr9Mr.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DbEQT6ue.js → GenericCardRenderer-BT8ZMpC5.js} +1 -1
- package/src/assets/web-panel/assets/{Git-0ZvCPSD9.js → Git-DjARip2b.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CmVuKkPb.js → Governance-BgWbSRcj.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CTWE3Jwg.js → Inference-CfouJciM.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CBEIF00L.js → KnowledgeGraph-50l7mrAr.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DLhxDwVG.js → Logs-rq50H84B.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-DUPIEdQH.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BgsCBrnc.js → Marketplace-BYgPDmHU.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-ClBUGDS2.js → McpTools-5DVgcFdx.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CnG_ZnYw.js → Memory-B70LPk7f.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BUOAbR1Z.js → MobileBridge-De8ssA5Y.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-D10VISps.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CLjt4kCD.js → Mtc-RJsOTsIA.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-f24U9Aes.js → MtcAudit-Crh-6BEK.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-GrmGQbSq.js → Multisig-wuoR5l3x.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DADaWn-n.js → NLProgramming-U2Mji4fZ.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-xtf5RX6C.js → Notes-CdTZAyDH.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-Cd27Rgtx.js → NotificationSettings-C-FucWE7.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-fXRxlDjl.js → OrderTableRenderer-DCYFTeaI.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-joCFlNB0.js → Organization-an3OF85L.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-B1HoURq0.js → Overflow-C-1vmYFe.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DiwsKbT7.js → P2P-Cwh47xKg.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Xe-BsW6S.js → PdhVaultBrowser-Dm38GT0k.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-C23qi8kl.js → Permissions-DS2Y8awD.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BS1syX2f.js → PersonalDataHub-BQNziA0I.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DRYwwDyh.js → Pipeline-DF85L1ue.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BQKaDHPH.js → Privacy-BuLornF-.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BC6F9xiG.js → ProjectInit-C3Y31IwX.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-ClFPc1Nd.js → ProjectSettings-BCPiI8aD.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BZ6s4k6g.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CLWuOUNt.js → Providers-D3Wp022X.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DiqULTxb.js → QrScannerModal-CUJfQkH4.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-9A03P-E_.js → QuickAsk-UAc0EO8l.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CJZAnbq_.js → Recommend-BaxKupcs.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C9A1R77h.js → RemoteSession-C75NNnXZ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BIZc6Rky.js → Reputation-BVXynZAk.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DfIPNtuG.js → Row-C5MRZ0bi.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-C5znFcQ1.js → RssFeed-DAKkEYka.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DSs2z3OX.js → Search-DvWv9YOA.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CV6LcrLY.js → Security-B5peafW1.js} +4 -4
- package/src/assets/web-panel/assets/{Services-cmhoX0Xj.js → Services-UQmvPEaG.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-tCsg2po7.js → Skeleton-C3bhWpuF.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BK1KUDiy.js → Skills-DfkKf9_H.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-yRgyeA82.js → Sla-DqMSjlBM.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-c1mo1mlp.js → SpeechSettings-C-WbxWUX.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-koIAfuT3.js → SyncSettings-CYuHZ4N2.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DkkreAaB.js → Tasks-CyeAyB9d.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-fy5Ctf9M.js → Templates-BTCeQnpq.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-Bw70Jf6S.js → Tenant-BifQuA9Y.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BKh6Rx-4.js → Terminal-Bx_9Bocf.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Dg54WP0c.js → TimelineRenderer-BX0RFCOm.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BvvD5SxJ.js → Tokens-CGHrCmUS.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-B7Ug9x4e.js → Trigger-DlqaY4SO.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BjvuMORY.js → Trust-DfOmj-ay.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CZqhkx8p.js → UkeySign-B72jH5fE.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-ClR50lhX.js → VideoEditing-BT-63fqv.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DlfppYjx.js → Wallet-Dsul3sHr.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BirgVr8B.js → WebAuthn-Izkwwdgy.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-B8DP_bax.js → WorkflowEditor-D3FHSiH1.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DA8AUZzL.js → chat-CmVz5z3U.js} +1 -1
- package/src/assets/web-panel/assets/{colors-C38pLGp1.js → colors-CuLgyJBp.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-81rtr98o.js → compact-item-Ml1YkXpw.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D34ixq8t.js → createContext-BvjJ48bs.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DhiGrbsh.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D4bzqTrZ.js → hasIn-DVC0157C.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_2VYPr1.js → index-4SBta3d7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoVgZw_b.js → index-4wcgvPoF.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZRJRItm0.js → index-B0S8NzO6.js} +1 -1
- package/src/assets/web-panel/assets/index-B7a1TrU6.js +1 -0
- package/src/assets/web-panel/assets/{index-CuS-UPoj.js → index-BUt8kTIB.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtGxuQrO.js → index-B_EvG_GW.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0QArPQt.js → index-BbPtzB8M.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd3KuNK5.js → index-BbepULSc.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbhE3j5j.js → index-BfuKP4qe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXd2_LmH.js → index-BiC6dQZG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CP5alL4t.js → index-BjHBpRYZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BvL_3J_n.js → index-BpFJHiTv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFyWKOBD.js → index-BydjdZnl.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ddk0e_Pi.js → index-BzG-x9p4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BS3M5H9V.js → index-Bzr0rB5T.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkHqMnn3.js → index-C229ABfy.js} +1 -1
- package/src/assets/web-panel/assets/index-C2B1KRja.js +1 -0
- package/src/assets/web-panel/assets/{index-D6GfvEQG.js → index-CFYVQMvu.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqIhLAbA.js → index-CXkJH-lK.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8mkLM4x.js → index-C_H_S-DY.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0Ih7Hwn.js → index-C_XuRgGn.js} +1 -1
- package/src/assets/web-panel/assets/{index-COe_cOLJ.js → index-C_vRgTl9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIP62a6r.js → index-Ck_52dz_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BP-zkXK8.js → index-CmFNvNLZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3zCCZRS.js → index-CudmwNBV.js} +3 -3
- package/src/assets/web-panel/assets/{index-DFHa1HIg.js → index-Cw0Rjy87.js} +1 -1
- package/src/assets/web-panel/assets/{index-BvD7b2IK.js → index-D3lD5qap.js} +1 -1
- package/src/assets/web-panel/assets/{index-DakfFZ-k.js → index-DC_OI9H2.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvfCEJG-.js → index-DDGaOWBV.js} +1 -1
- package/src/assets/web-panel/assets/{index-E1OJRXs4.js → index-DJyN28Et.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dmo3dFHb.js → index-DYXHFr4r.js} +1 -1
- package/src/assets/web-panel/assets/{index-tKiC8T-4.js → index-Dt5KMjwJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-fI5sXMLg.js → index-DuGszaWY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUQLXLQM.js → index-DukDVXCv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMgnRwrK.js → index-KMqhcF7l.js} +1 -1
- package/src/assets/web-panel/assets/{index-F76w1NiL.js → index-KjgKdZe-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBFSo1NF.js → index-QXzlT9KD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlxEphl7.js → index-vG4XSJ1d.js} +1 -1
- package/src/assets/web-panel/assets/{index-9qoVpPt6.js → index-wvb_FtaV.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-ByyvflIR.js → initDefaultProps-BDgd2YZ8.js} +1 -1
- package/src/assets/web-panel/assets/{motion-B3FQm2By.js → motion-ErtrXdYe.js} +1 -1
- package/src/assets/web-panel/assets/{move-BSfns6Ef.js → move-_GPPNCgs.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CTG1Ieri.js → mtc-parser-DRLL-8V2.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DObM_2j6.js → omit-p86sl023.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DOfelQ1t.js → pickAttrs-BTu7cMLH.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CHZILds_.js → placementArrow-BEKz6Isr.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-REbucKSx.js → responsiveObserve-Ck42c9MP.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C6EZzD7o.js → slide-1CEvuPsB.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BxkWS-g3.js → statusUtils-BDfdx1GJ.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Chklyoq6.js → styleChecker-B4K46m5w.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CRVwKrrI.js → useFlexGapSupport-DoIVpJNq.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DV24ik_J.js → useFs-DdAWi-ln.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-C7vIo4Pg.js → usePersonalDataHub-iUu6k8dx.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-By-v5GlF.js → vnode-DZz4R6Tw.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-B1w9Am3r.js → zoom-DXlf9sA3.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/review.js +6 -1
- package/src/data/changelog.json +7 -2
- package/src/lib/agents.js +19 -0
- package/src/lib/background-agent-supervisor.js +34 -7
- package/src/lib/docs-drift.js +166 -0
- package/src/lib/doctor-checkup.js +76 -0
- package/src/lib/hook-event-bus.cjs +0 -0
- package/src/lib/json-schema-output.js +30 -1
- package/src/lib/json-schema-validate.js +691 -0
- package/src/lib/lsp/__tests__/diagnostics-scheduler.test.js +93 -0
- package/src/lib/lsp/diagnostics-scheduler.js +127 -0
- package/src/lib/operation-fingerprint.js +95 -0
- package/src/lib/plugin-runtime/capabilities.js +371 -0
- package/src/lib/plugin-runtime/manifest.js +30 -0
- package/src/lib/remote-approval-bridge.js +16 -0
- package/src/lib/review-pipeline.js +227 -0
- package/src/lib/runtime-checkup.js +318 -0
- package/src/lib/session-lifecycle.js +305 -0
- package/src/lib/settings-hook-events.cjs +39 -13
- package/src/lib/subagent-contract.js +383 -0
- package/src/lib/telemetry-ids.js +190 -0
- package/src/lib/turn-binding.js +397 -0
- package/src/runtime/agent-core.js +13 -6
- package/src/assets/web-panel/assets/MarkdownRenderer-DxywvhTU.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-Dnt_9-WB.js +0 -1
- package/src/assets/web-panel/assets/Projects-Dn-f5aYe.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CHDIEOeN.js +0 -1
- package/src/assets/web-panel/assets/index-CY1NURWZ.js +0 -1
- package/src/assets/web-panel/assets/index-DokUYqpq.js +0 -1
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified session lifecycle state machine (P0#4 "会话生命周期可靠性 —
|
|
3
|
+
* 统一状态机" from CLAUDE_CODE_IDE_GAP_ANALYSIS.md).
|
|
4
|
+
*
|
|
5
|
+
* A running agent session is described by THREE divergent representations that
|
|
6
|
+
* grew independently and disagree on vocabulary:
|
|
7
|
+
*
|
|
8
|
+
* 1. supervisor `status` — running | completed | failed | stopped | lost
|
|
9
|
+
* (liveness reconciliation, owns the terminal verdict). See
|
|
10
|
+
* background-agent-supervisor.js.
|
|
11
|
+
* 2. worker `phase` — starting | working | idle | needs_input |
|
|
12
|
+
* waiting_permission (the live sub-state WHILE running). See
|
|
13
|
+
* [[background-agent-phase.js]].
|
|
14
|
+
* 3. IDE connection state — starting | ready | running | disconnected |
|
|
15
|
+
* crashed (the transport/process view the VS Code / JetBrains panel keeps).
|
|
16
|
+
*
|
|
17
|
+
* None of the three alone can answer the question that matters on reconnect:
|
|
18
|
+
* "is a dangerous tool call about to be silently retried?" The gap doc's P0#4
|
|
19
|
+
* asks for ONE state machine — starting / ready / running / waitingApproval /
|
|
20
|
+
* cancelling / disconnected / recovering / completed / failed / stopped — that
|
|
21
|
+
* every producer folds into, so the supervisor, the IDE bridge and the resume
|
|
22
|
+
* path reason about the same lifecycle.
|
|
23
|
+
*
|
|
24
|
+
* This module is that single source of truth. It is pure (no fs / process /
|
|
25
|
+
* clock): `deriveSessionState` collapses the three axes into one canonical
|
|
26
|
+
* state with a documented precedence, `canTransition` encodes the legal graph,
|
|
27
|
+
* and `requiresIdempotencyGuard` marks the `recovering` window during which a
|
|
28
|
+
* resumed session MUST re-check a dangerous tool's ledger before re-executing
|
|
29
|
+
* (the "危险工具恢复时不得静默重试" invariant) rather than blindly replaying it.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The canonical unified lifecycle. camelCase mirrors the gap doc's wording.
|
|
34
|
+
* `ready` is the parked/idle steady state (transport open, no active turn);
|
|
35
|
+
* `running` is a live turn. The three terminal states are mutually exclusive
|
|
36
|
+
* and absorbing.
|
|
37
|
+
*/
|
|
38
|
+
export const SESSION_STATES = Object.freeze({
|
|
39
|
+
STARTING: "starting",
|
|
40
|
+
READY: "ready",
|
|
41
|
+
RUNNING: "running",
|
|
42
|
+
WAITING_APPROVAL: "waitingApproval",
|
|
43
|
+
CANCELLING: "cancelling",
|
|
44
|
+
DISCONNECTED: "disconnected",
|
|
45
|
+
RECOVERING: "recovering",
|
|
46
|
+
COMPLETED: "completed",
|
|
47
|
+
FAILED: "failed",
|
|
48
|
+
STOPPED: "stopped",
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const ALL_STATES = new Set(Object.values(SESSION_STATES));
|
|
52
|
+
|
|
53
|
+
/** Terminal (absorbing) states — a session can never leave one. */
|
|
54
|
+
const TERMINAL_STATES = new Set([
|
|
55
|
+
SESSION_STATES.COMPLETED,
|
|
56
|
+
SESSION_STATES.FAILED,
|
|
57
|
+
SESSION_STATES.STOPPED,
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Every vocabulary the three producers emit → canonical unified state. Callers
|
|
62
|
+
* that hold a native representation (a supervisor status, a worker phase, an
|
|
63
|
+
* IDE connection state) map it here before reasoning about the lifecycle.
|
|
64
|
+
*/
|
|
65
|
+
const STATE_ALIASES = new Map([
|
|
66
|
+
// canonical
|
|
67
|
+
["starting", SESSION_STATES.STARTING],
|
|
68
|
+
["ready", SESSION_STATES.READY],
|
|
69
|
+
["running", SESSION_STATES.RUNNING],
|
|
70
|
+
["waitingapproval", SESSION_STATES.WAITING_APPROVAL],
|
|
71
|
+
["cancelling", SESSION_STATES.CANCELLING],
|
|
72
|
+
["disconnected", SESSION_STATES.DISCONNECTED],
|
|
73
|
+
["recovering", SESSION_STATES.RECOVERING],
|
|
74
|
+
["completed", SESSION_STATES.COMPLETED],
|
|
75
|
+
["failed", SESSION_STATES.FAILED],
|
|
76
|
+
["stopped", SESSION_STATES.STOPPED],
|
|
77
|
+
// worker phase (background-agent-phase.js)
|
|
78
|
+
["working", SESSION_STATES.RUNNING],
|
|
79
|
+
["turn", SESSION_STATES.RUNNING],
|
|
80
|
+
["idle", SESSION_STATES.READY],
|
|
81
|
+
["needs_input", SESSION_STATES.WAITING_APPROVAL],
|
|
82
|
+
["needs-input", SESSION_STATES.WAITING_APPROVAL],
|
|
83
|
+
["awaiting_input", SESSION_STATES.WAITING_APPROVAL],
|
|
84
|
+
["question", SESSION_STATES.WAITING_APPROVAL],
|
|
85
|
+
["waiting_permission", SESSION_STATES.WAITING_APPROVAL],
|
|
86
|
+
["waiting-permission", SESSION_STATES.WAITING_APPROVAL],
|
|
87
|
+
["waiting_approval", SESSION_STATES.WAITING_APPROVAL],
|
|
88
|
+
["awaiting_approval", SESSION_STATES.WAITING_APPROVAL],
|
|
89
|
+
// supervisor liveness — a running process that vanished is a failure.
|
|
90
|
+
["lost", SESSION_STATES.FAILED],
|
|
91
|
+
// IDE connection / transport
|
|
92
|
+
["connected", SESSION_STATES.READY],
|
|
93
|
+
["reconnecting", SESSION_STATES.RECOVERING],
|
|
94
|
+
["resuming", SESSION_STATES.RECOVERING],
|
|
95
|
+
["reattaching", SESSION_STATES.RECOVERING],
|
|
96
|
+
["cancelled", SESSION_STATES.STOPPED],
|
|
97
|
+
["canceled", SESSION_STATES.STOPPED],
|
|
98
|
+
["cancelling", SESSION_STATES.CANCELLING],
|
|
99
|
+
["stopping", SESSION_STATES.CANCELLING],
|
|
100
|
+
["crashed", SESSION_STATES.FAILED],
|
|
101
|
+
["error", SESSION_STATES.FAILED],
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Normalize any producer's state/status/phase token to a canonical unified
|
|
106
|
+
* state, or null when absent / unrecognized. Case- and whitespace-tolerant;
|
|
107
|
+
* never throws.
|
|
108
|
+
*/
|
|
109
|
+
export function normalizeSessionState(value) {
|
|
110
|
+
if (typeof value !== "string") return null;
|
|
111
|
+
return STATE_ALIASES.get(value.trim().toLowerCase()) || null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Legal transition graph. Terminal states have no outgoing edges. */
|
|
115
|
+
const TRANSITIONS = Object.freeze({
|
|
116
|
+
starting: [
|
|
117
|
+
"ready",
|
|
118
|
+
"running",
|
|
119
|
+
"waitingApproval",
|
|
120
|
+
"disconnected",
|
|
121
|
+
"failed",
|
|
122
|
+
"stopped",
|
|
123
|
+
],
|
|
124
|
+
ready: [
|
|
125
|
+
"running",
|
|
126
|
+
"waitingApproval",
|
|
127
|
+
"cancelling",
|
|
128
|
+
"disconnected",
|
|
129
|
+
"completed",
|
|
130
|
+
"failed",
|
|
131
|
+
"stopped",
|
|
132
|
+
],
|
|
133
|
+
running: [
|
|
134
|
+
"ready",
|
|
135
|
+
"waitingApproval",
|
|
136
|
+
"cancelling",
|
|
137
|
+
"disconnected",
|
|
138
|
+
"completed",
|
|
139
|
+
"failed",
|
|
140
|
+
"stopped",
|
|
141
|
+
],
|
|
142
|
+
waitingApproval: [
|
|
143
|
+
"running",
|
|
144
|
+
"ready",
|
|
145
|
+
"cancelling",
|
|
146
|
+
"disconnected",
|
|
147
|
+
"completed",
|
|
148
|
+
"failed",
|
|
149
|
+
"stopped",
|
|
150
|
+
],
|
|
151
|
+
// a turn may finish (or die) before a cancel lands, so completed/failed are legal.
|
|
152
|
+
cancelling: ["stopped", "failed", "completed", "disconnected"],
|
|
153
|
+
disconnected: ["recovering", "failed", "stopped", "completed"],
|
|
154
|
+
recovering: [
|
|
155
|
+
"ready",
|
|
156
|
+
"running",
|
|
157
|
+
"waitingApproval",
|
|
158
|
+
"disconnected",
|
|
159
|
+
"completed",
|
|
160
|
+
"failed",
|
|
161
|
+
"stopped",
|
|
162
|
+
],
|
|
163
|
+
completed: [],
|
|
164
|
+
failed: [],
|
|
165
|
+
stopped: [],
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
/** Is `state` a terminal (absorbing) state? */
|
|
169
|
+
export function isTerminalSessionState(state) {
|
|
170
|
+
return TERMINAL_STATES.has(state);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** Is `state` a live (non-terminal, known) state? */
|
|
174
|
+
export function isActiveSessionState(state) {
|
|
175
|
+
return ALL_STATES.has(state) && !TERMINAL_STATES.has(state);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Is `from → to` a legal transition? A self-transition (from === to) is always
|
|
180
|
+
* allowed (idempotent re-assert of the current state). Unknown states → false.
|
|
181
|
+
*/
|
|
182
|
+
export function canTransitionSessionState(from, to) {
|
|
183
|
+
if (!ALL_STATES.has(from) || !ALL_STATES.has(to)) return false;
|
|
184
|
+
if (from === to) return true;
|
|
185
|
+
return TRANSITIONS[from].includes(to);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* States during which a resumed/reconnected session must NOT silently replay a
|
|
190
|
+
* dangerous tool call — it has to re-check the command ledger first (P0#4
|
|
191
|
+
* "危险工具恢复时不得静默重试"). `recovering` is the reattach/replay window;
|
|
192
|
+
* `disconnected` is guarded too because the very next legal step is recovery
|
|
193
|
+
* and a re-dispatch across the gap is exactly the at-most-once hazard.
|
|
194
|
+
*/
|
|
195
|
+
export function requiresIdempotencyGuard(state) {
|
|
196
|
+
return (
|
|
197
|
+
state === SESSION_STATES.RECOVERING || state === SESSION_STATES.DISCONNECTED
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Collapse the three divergent axes into ONE canonical unified state.
|
|
203
|
+
*
|
|
204
|
+
* Precedence (strongest first), each documented by WHY it outranks the next:
|
|
205
|
+
* 1. terminal `status` (completed/failed/stopped/lost) — a settled verdict
|
|
206
|
+
* from the supervisor is authoritative and absorbing; nothing un-settles it.
|
|
207
|
+
* 2. `recovering` (connection reconnecting/resuming, or explicit flag) — an
|
|
208
|
+
* active reattach is the state that carries the idempotency guard, so it
|
|
209
|
+
* must surface even mid-cancel.
|
|
210
|
+
* 3. `disconnected` (connection lost) — the transport is gone; we cannot
|
|
211
|
+
* observe cancel/approval progress, so report the disconnect, not a stale
|
|
212
|
+
* inner phase.
|
|
213
|
+
* 4. `cancelling` (cancel requested, not yet settled) — outranks approval /
|
|
214
|
+
* running because a pending cancel is what the operator is waiting on.
|
|
215
|
+
* 5. `waitingApproval` (pendingApprovals > 0 OR a blocking worker phase) — a
|
|
216
|
+
* human decision blocks progress; mirrors phaseGroupKey's approval-wins rule.
|
|
217
|
+
* 6. worker phase: working/turn → running, idle → ready, starting → starting.
|
|
218
|
+
* 7. fallback: a running session with an unknown/absent phase is `running`
|
|
219
|
+
* (never idle) — the safe default, matching phaseGroupKey.
|
|
220
|
+
*
|
|
221
|
+
* @param {object} input
|
|
222
|
+
* @param {string} [input.status] supervisor liveness status
|
|
223
|
+
* @param {string} [input.phase] worker sub-phase
|
|
224
|
+
* @param {string} [input.connection] IDE transport state
|
|
225
|
+
* @param {boolean} [input.cancelRequested] a cancel is in flight
|
|
226
|
+
* @param {boolean} [input.recovering] an explicit reattach/replay flag
|
|
227
|
+
* @param {number} [input.pendingApprovals] count of blocking approvals
|
|
228
|
+
* @returns {string} a canonical SESSION_STATES value
|
|
229
|
+
*/
|
|
230
|
+
export function deriveSessionState(input) {
|
|
231
|
+
const s = input && typeof input === "object" ? input : {};
|
|
232
|
+
const status = normalizeSessionState(s.status);
|
|
233
|
+
const connection = normalizeSessionState(s.connection);
|
|
234
|
+
const phase = normalizeSessionState(s.phase);
|
|
235
|
+
|
|
236
|
+
// 1. terminal verdict absorbs everything.
|
|
237
|
+
if (status && TERMINAL_STATES.has(status)) return status;
|
|
238
|
+
|
|
239
|
+
// 2. active recovery (explicit flag or a reconnecting/resuming transport).
|
|
240
|
+
if (s.recovering === true || connection === SESSION_STATES.RECOVERING) {
|
|
241
|
+
return SESSION_STATES.RECOVERING;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// 3. transport gone.
|
|
245
|
+
if (connection === SESSION_STATES.DISCONNECTED)
|
|
246
|
+
return SESSION_STATES.DISCONNECTED;
|
|
247
|
+
|
|
248
|
+
// 4. cancel in flight (flag, or a producer that reported a cancelling state).
|
|
249
|
+
if (
|
|
250
|
+
s.cancelRequested === true ||
|
|
251
|
+
phase === SESSION_STATES.CANCELLING ||
|
|
252
|
+
connection === SESSION_STATES.CANCELLING
|
|
253
|
+
) {
|
|
254
|
+
return SESSION_STATES.CANCELLING;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// 5. blocked on a human decision.
|
|
258
|
+
if (
|
|
259
|
+
Number(s.pendingApprovals) > 0 ||
|
|
260
|
+
phase === SESSION_STATES.WAITING_APPROVAL
|
|
261
|
+
) {
|
|
262
|
+
return SESSION_STATES.WAITING_APPROVAL;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// 6. steady sub-states from the worker phase.
|
|
266
|
+
if (phase === SESSION_STATES.RUNNING) return SESSION_STATES.RUNNING;
|
|
267
|
+
if (phase === SESSION_STATES.READY) return SESSION_STATES.READY;
|
|
268
|
+
if (phase === SESSION_STATES.STARTING) return SESSION_STATES.STARTING;
|
|
269
|
+
if (connection === SESSION_STATES.STARTING) return SESSION_STATES.STARTING;
|
|
270
|
+
if (connection === SESSION_STATES.READY) return SESSION_STATES.READY;
|
|
271
|
+
|
|
272
|
+
// 7. a running session with no legible phase is running, never idle.
|
|
273
|
+
if (status === SESSION_STATES.RUNNING) return SESSION_STATES.RUNNING;
|
|
274
|
+
|
|
275
|
+
// nothing legible at all → the session is starting up.
|
|
276
|
+
return SESSION_STATES.STARTING;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Human-readable one-liner for a canonical state (dashboards / logs). */
|
|
280
|
+
export function describeSessionState(state) {
|
|
281
|
+
switch (state) {
|
|
282
|
+
case SESSION_STATES.STARTING:
|
|
283
|
+
return "starting: process spawned, first turn not begun";
|
|
284
|
+
case SESSION_STATES.READY:
|
|
285
|
+
return "ready: transport open, parked between turns";
|
|
286
|
+
case SESSION_STATES.RUNNING:
|
|
287
|
+
return "running: a turn is executing";
|
|
288
|
+
case SESSION_STATES.WAITING_APPROVAL:
|
|
289
|
+
return "waiting for approval: a human decision blocks progress";
|
|
290
|
+
case SESSION_STATES.CANCELLING:
|
|
291
|
+
return "cancelling: a cancel is in flight, not yet settled";
|
|
292
|
+
case SESSION_STATES.DISCONNECTED:
|
|
293
|
+
return "disconnected: transport lost, session may still be alive";
|
|
294
|
+
case SESSION_STATES.RECOVERING:
|
|
295
|
+
return "recovering: reattaching; dangerous tools must re-check the ledger";
|
|
296
|
+
case SESSION_STATES.COMPLETED:
|
|
297
|
+
return "completed: finished successfully (terminal)";
|
|
298
|
+
case SESSION_STATES.FAILED:
|
|
299
|
+
return "failed: ended in error or was lost (terminal)";
|
|
300
|
+
case SESSION_STATES.STOPPED:
|
|
301
|
+
return "stopped: cancelled by the user (terminal)";
|
|
302
|
+
default:
|
|
303
|
+
return "unknown session state";
|
|
304
|
+
}
|
|
305
|
+
}
|
|
@@ -18,6 +18,24 @@
|
|
|
18
18
|
|
|
19
19
|
const { collectHooks } = require("./settings-hooks.cjs");
|
|
20
20
|
const { runHooks } = require("./hook-runner.cjs");
|
|
21
|
+
const { buildHookEnvelope } = require("./hook-event-bus.cjs");
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Stamp a unified-bus delivery id (event_id) onto a hook payload (P2 event bus).
|
|
25
|
+
* Additive — a hook that ignores it is unaffected; a hook that reads it gets a
|
|
26
|
+
* stable per-delivery id for correlation / `cc hook replay`. traceId/parentId
|
|
27
|
+
* are threaded when the caller provides them (else null).
|
|
28
|
+
*/
|
|
29
|
+
function withDeliveryId(event, payload, { sessionId, traceId, parentId } = {}) {
|
|
30
|
+
const env = buildHookEnvelope({
|
|
31
|
+
eventType: event,
|
|
32
|
+
data: payload,
|
|
33
|
+
sessionId: sessionId || payload.session_id || null,
|
|
34
|
+
traceId: traceId || null,
|
|
35
|
+
parentId: parentId || null,
|
|
36
|
+
});
|
|
37
|
+
return { ...payload, event_id: env.event_id };
|
|
38
|
+
}
|
|
21
39
|
|
|
22
40
|
/**
|
|
23
41
|
* Split collected hooks into the blocking (sync) set and the fire-and-forget
|
|
@@ -70,12 +88,16 @@ function runUserPromptSubmitHooks(
|
|
|
70
88
|
if (matched.length === 0) return { blocked: false, additionalContext: null };
|
|
71
89
|
const { sync } = partitionAsyncHooks(matched);
|
|
72
90
|
if (sync.length === 0) return { blocked: false, additionalContext: null };
|
|
73
|
-
const payload =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
const payload = withDeliveryId(
|
|
92
|
+
"UserPromptSubmit",
|
|
93
|
+
{
|
|
94
|
+
hook_event_name: "UserPromptSubmit",
|
|
95
|
+
prompt: String(prompt || ""),
|
|
96
|
+
cwd,
|
|
97
|
+
session_id: sessionId || null,
|
|
98
|
+
},
|
|
99
|
+
{ sessionId },
|
|
100
|
+
);
|
|
79
101
|
const outcome = runHooks(sync, payload, {
|
|
80
102
|
cwd,
|
|
81
103
|
event: "UserPromptSubmit",
|
|
@@ -129,12 +151,16 @@ function runSessionStartHooks(settingsHooks, { source, cwd, sessionId } = {}) {
|
|
|
129
151
|
if (!settingsHooks) return { additionalContext: null };
|
|
130
152
|
const matched = collectHooks(settingsHooks, "SessionStart", source || "");
|
|
131
153
|
if (matched.length === 0) return { additionalContext: null };
|
|
132
|
-
const payload =
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
154
|
+
const payload = withDeliveryId(
|
|
155
|
+
"SessionStart",
|
|
156
|
+
{
|
|
157
|
+
hook_event_name: "SessionStart",
|
|
158
|
+
source: source || "startup",
|
|
159
|
+
cwd,
|
|
160
|
+
session_id: sessionId || null,
|
|
161
|
+
},
|
|
162
|
+
{ sessionId },
|
|
163
|
+
);
|
|
138
164
|
const outcome = runHooks(matched, payload, { cwd, event: "SessionStart" });
|
|
139
165
|
return { additionalContext: aggregateContext(outcome.results) };
|
|
140
166
|
}
|
|
@@ -159,7 +185,7 @@ function runObserveHooks(
|
|
|
159
185
|
if (sync.length === 0) return { decision: "continue", results: [] };
|
|
160
186
|
return runHooks(
|
|
161
187
|
sync,
|
|
162
|
-
{ hook_event_name: event, cwd, ...payload },
|
|
188
|
+
withDeliveryId(event, { hook_event_name: event, cwd, ...payload }),
|
|
163
189
|
{ cwd, event },
|
|
164
190
|
);
|
|
165
191
|
}
|