chainlesschain 0.162.125 → 0.162.127
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 +2 -2
- package/src/assets/web-panel/assets/{AIOps-DcqNhZhA.js → AIOps-CsHJh6tT.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BigtmPoq.js → ActionButton-ClDr78Wl.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-1J_X_HF4.js → Analytics-CQQBX5mv.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DlcDG_a_.js → AppLayout-DIofBNeG.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-Do-y8_3w.js → Audit-d8pxGJLK.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-S2Df-50Y.js → Backup-ChZb31ek.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-D5kgWJfk.js → BaseInput-CQsSXb5v.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-aUcp3kN1.js → Chat-C_mjILx8.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-B545kWla.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-DTg1U7Xs.js → Checkbox-CWFmVuo8.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-YO9ZZ4Ky.js → Codegen-DwicePOQ.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BHonE9fU.js → Col-B36SnRdL.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DA2AlEFh.js → Community-C_sZ2HhK.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DULxLRNg.js → Compact-B2jzDcUl.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BZqfuuZL.js → Compliance-BD58_IHe.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CJe3vyMS.js → Cowork-VIBdGc4D.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CeV8AtRu.js → Cron-CDTVWUmV.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CAg66zS5.js → Crosschain-D5DkGNKU.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Dtup5JZm.js → DID-B23ae8PQ.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DAR_8PNy.js → Dashboard-DTG5MsSx.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-K5bTaCYN.js → Dropdown-D35RRnMZ.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C890uErx.js → EmailListRenderer-DRvY2nPk.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-B-Tj_8yM.js → FamilyGuardDashboard-BT_eESkk.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C6WZ98ni.js → Federation-CxX9F7IL.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D-LTfGWd.js → FormItemContext-C1xDz6D8.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-C80DK4W7.js → GenericCardRenderer-CjBOAXcO.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Cjvvv3zW.js → Git-I9I9NkPO.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-C0BND77H.js → Governance-BiigWxQW.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BL9kTtSu.js → Inference-C0KrSCgh.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CnVTBmJf.js → KnowledgeGraph-B1Nd54ow.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CbCbg7K6.js → Logs-CeOtvYIo.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-CG5On-fH.js → Marketplace-CRhgvAVQ.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-AYYDZZK7.js → McpTools-BIJNah-H.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-tMWbMDQq.js → Memory-D6gsbo4e.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BAOsf4wB.js → MobileBridge-DDkIKA6U.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BT-2komQ.js → MobileProjects-BBkI02Lf.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BFwfC63n.js → Mtc-BziHK7HS.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-DYG3CWdH.js → MtcAudit-CWXjbkeF.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-KJwd0yWT.js → Multisig-9jNF_VWa.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BmL5dNWm.js → NLProgramming-BUdF7I2G.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DmkaVaMc.js → Notes-D5ls1r1T.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-tmVQszDZ.js → NotificationSettings-B2WX_TMX.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BtrR7anf.js → OrderTableRenderer-COSzdTcE.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-pppktQyW.js → Organization-tzWIgnbM.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-D3lBoQDA.js → Overflow-Ca1gp_3S.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BgE2qGlZ.js → P2P-XnfDfRK9.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-D26Bz5gS.js → PdhVaultBrowser-23Susb25.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BR8no2Xe.js → Permissions-CnkhYPqt.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DabbyQEF.js → PersonalDataHub-CZ1UasJc.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-n4sNpEz8.js → Pipeline-DC1oC84K.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CGNp4n8M.js → Privacy-CdqayaCE.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CAVA5VsX.js → ProjectInit-DS7NbGQL.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-GCgkfM7A.js → ProjectSettings-fdzwup3n.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BYK17p52.js → Projects-FvodeZob.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DpUT5W-d.js → Providers-IxYyzeSI.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-ZJxTb7vi.js → QuickAsk-BAtFET-B.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CIzFRDk1.js → Recommend-DCNRV9Vr.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-lQ_WDNZn.js → Reputation-lg2JmIai.js} +1 -1
- package/src/assets/web-panel/assets/{Row-1MEtrgtF.js → Row-BAhyDuri.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-SSgcPPl4.js → RssFeed-BA_3issD.js} +2 -2
- package/src/assets/web-panel/assets/{Search-CcTMOGNY.js → Search-CJheUJDl.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BA1KMaDx.js → Security-D2VczQDD.js} +3 -3
- package/src/assets/web-panel/assets/{Services-_aj7czZn.js → Services-7ZFAzqVR.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BWgg_0Zr.js → Skeleton-CsBoTasD.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C2ZIziYM.js → Skills-DT_j_gj0.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CYxp4axY.js → Sla-C9D5geJx.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C7Csp1jV.js → SpeechSettings-CWCNVW42.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-svGeswiw.js → SyncSettings-TYCbf2kk.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-ClISj6oK.js → Tasks-CbRoXu1G.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CmO-Fp7r.js → Templates-CxBjIrkJ.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-a3Ac3lxz.js → Tenant-NKVyFsPM.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DyJIRh81.js → Terminal-D5aAL5_H.js} +2 -2
- package/src/assets/web-panel/assets/TimelineRenderer-CD1JE0Rb.js +1 -0
- package/src/assets/web-panel/assets/{Tokens-DJW0KqV4.js → Tokens-CdepBSYe.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-0HeTi4r6.js → Trigger-Br3n_PEh.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-aFym34eo.js → Trust-CSac0pMf.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CYhszHJv.js → UkeySign-BiWo43zc.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BbJxPF9X.js → VideoEditing-Dj50GuoF.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DDthEwiu.js → Wallet-CQK_g4_U.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DQ6McYPg.js → WebAuthn-D8mBl1NC.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-CnF8zRsi.js → WorkflowEditor-CHeS_vab.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Dzkx2gTP.js → chat-CbeOf_lH.js} +1 -1
- package/src/assets/web-panel/assets/{colors-35T51Oo5.js → colors-CTFiyfed.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-TtzNrlu1.js → compact-item-CZsh8FXE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-Y1LkWrYb.js → createContext-UPhnXsap.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BFRqfgsk.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BOYw1BgS.js → hasIn-CCqQtSY-.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2od7Bgx.js → index-1d4pat4L.js} +1 -1
- package/src/assets/web-panel/assets/{index-NM9Oke2k.js → index-86dmMEZY.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dof7lWA_.js → index-B-OcSTNA.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7dCBw_M.js → index-B1tylGKq.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqhwG1ox.js → index-BAcem_Qs.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZ16GlOs.js → index-BKADY9Iw.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPGNc2tF.js → index-Be0uH7m1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAizH273.js → index-Bga0UuWA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFhlelzN.js → index-Blgzobgm.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6tG4B25.js → index-BwPULPuj.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjeUZxE5.js → index-CIQVlE9u.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLqC2sRT.js → index-CMi91z74.js} +1 -1
- package/src/assets/web-panel/assets/{index-hyqEKkBT.js → index-CNteMctn.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cs82BHAj.js → index-CQHQiYAO.js} +1 -1
- package/src/assets/web-panel/assets/{index-zF77jnI2.js → index-CVKFSFkX.js} +1 -1
- package/src/assets/web-panel/assets/{index-G4ClSmJc.js → index-CctoAd9I.js} +1 -1
- package/src/assets/web-panel/assets/{index-DhMSOd_2.js → index-CdiuRSqw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWgNn9As.js → index-Cy83zglX.js} +3 -3
- package/src/assets/web-panel/assets/{index-Bw1iOGhM.js → index-DBJjqjxL.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4BgCBa3.js → index-DFbyobqi.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKRlWHUp.js → index-DcJxrM1F.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7aKAZzS.js → index-DgXn2sWa.js} +1 -1
- package/src/assets/web-panel/assets/{index-D47robkX.js → index-Dkn1r09O.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVrUs6rf.js → index-DmScDPXc.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bs69SI96.js → index-DpTaXoo4.js} +1 -1
- package/src/assets/web-panel/assets/index-DqADH38Q.js +1 -0
- package/src/assets/web-panel/assets/{index-BxWUEFKy.js → index-DvaDSd9k.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtlJWaSP.js → index-LIFKNtNq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGPEaeB1.js → index-LyzbfmcN.js} +1 -1
- package/src/assets/web-panel/assets/index-Pbx8iJt_.js +1 -0
- package/src/assets/web-panel/assets/{index-KgXrlfNF.js → index-WGmri9tu.js} +1 -1
- package/src/assets/web-panel/assets/{index-XIuZV9by.js → index-Yd1x-xhs.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dhfw-BXs.js → index-_OOipSkX.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dx0hIfC-.js → index-dwBroN51.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7Wt5feN.js → index-e6tj_vqt.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdyFg4FI.js → index-lOxvi-gf.js} +1 -1
- package/src/assets/web-panel/assets/{index-8jffdb6b.js → index-qTrskpW-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmkG479D.js → index-uH-glcG6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSpFe6j5.js → index-z5pyzCXj.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DD5y5msp.js → initDefaultProps-K95PVa57.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BuoutMia.js → motion-DwTSyvvW.js} +1 -1
- package/src/assets/web-panel/assets/{move-DkpjqOXg.js → move-BuRSogkN.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BmGJD-v-.js → mtc-parser-twEnPl1V.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DftUE0Sz.js → omit-CdPhebkX.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DDRb9FIu.js → pickAttrs-CGcIpdPi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DPgtxOOD.js → placementArrow-DixkX9VV.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BQFRzFeZ.js → responsiveObserve-C74t3rB5.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DQ4lmUSz.js → slide-TcNt6K6l.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C1TR4ZiQ.js → statusUtils-mpTN9mrS.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B-Suj978.js → styleChecker-Bwg8zmIj.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Q7bDZ3EI.js → useFlexGapSupport-Cz4mN4sW.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DHjRLyQH.js → useFs-DF9zRfbI.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-lQOvCvCr.js → usePersonalDataHub-BcQ4O2UK.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-Ie0g4-p3.js → vnode-juM2dgAV.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CHP0YEoH.js → zoom-c4aJj-vC.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +41 -2
- package/src/commands/compliance.js +3 -1
- package/src/commands/review.js +47 -17
- package/src/commands/session.js +11 -2
- package/src/gateways/ws/message-dispatcher.js +145 -165
- package/src/gateways/ws/ws-session-gateway.js +39 -5
- package/src/harness/jsonl-session-store.js +39 -12
- package/src/harness/worktree-isolator.js +5 -0
- package/src/lib/agent-core.js +1 -0
- package/src/lib/audit-logger.js +3 -1
- package/src/lib/chat-core.js +5 -2
- package/src/lib/chat-intent-service.js +68 -21
- package/src/lib/config-manager.js +25 -1
- package/src/lib/credential-guard.js +43 -1
- package/src/lib/git-integration.js +5 -0
- package/src/lib/interaction-adapter.js +32 -11
- package/src/lib/jsonl-session-store.js +1 -0
- package/src/lib/llm-config-defaults.js +37 -0
- package/src/lib/mcp-oauth.js +76 -10
- package/src/lib/permission-engine.js +4 -1
- package/src/lib/personal-data-hub-wiring.js +14 -0
- package/src/lib/pipeline-orchestrator.js +20 -2
- package/src/lib/project-detector.js +44 -3
- package/src/lib/project-instructions.js +13 -0
- package/src/lib/repl-denials.js +137 -0
- package/src/lib/safe-json.js +22 -0
- package/src/lib/sandbox-v2.js +7 -6
- package/src/lib/search-command.js +65 -0
- package/src/lib/settings-hooks.cjs +133 -0
- package/src/lib/settings-loader.cjs +16 -7
- package/src/lib/social-graph.js +3 -1
- package/src/lib/stream-retry.js +27 -0
- package/src/lib/turn-context.js +15 -5
- package/src/repl/agent-repl.js +81 -8
- package/src/runtime/__tests__/message-roles.test.js +36 -3
- package/src/runtime/agent-core.js +175 -50
- package/src/runtime/coding-agent-contract-shared.cjs +9 -2
- package/src/runtime/coding-agent-shell-policy.cjs +23 -2
- package/src/runtime/file-ref-expander.js +51 -7
- package/src/runtime/headless-runner.js +83 -2
- package/src/runtime/headless-stream.js +69 -3
- package/src/runtime/mcp-config.js +42 -1
- package/src/runtime/message-roles.js +14 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Pg7dIsiE.js +0 -1
- package/src/assets/web-panel/assets/TimelineRenderer-acXS5N5h.js +0 -1
- package/src/assets/web-panel/assets/devWarning-D_lwLZ6O.js +0 -1
- package/src/assets/web-panel/assets/index-CEwuCM44.js +0 -1
- package/src/assets/web-panel/assets/index-DzzgU4IU.js +0 -1
|
@@ -106,199 +106,179 @@ export function createWsMessageDispatcher(server) {
|
|
|
106
106
|
"llm.chat": () => server._handleLlmChat(id, ws, message),
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
109
|
+
// Static core routes take precedence and are dispatched directly. The
|
|
110
|
+
// feature handler maps below are consulted ONLY when no static route
|
|
111
|
+
// matches — so a feature topic can never shadow a core protocol route
|
|
112
|
+
// (auth/cancel/ping/execute), and we no longer allocate a closure for all
|
|
113
|
+
// ~79 feature keys on every message (the old per-message Object.keys loops
|
|
114
|
+
// built the entire route table each dispatch). Only the matched handler
|
|
115
|
+
// runs.
|
|
116
|
+
const staticHandler = routes[type];
|
|
117
|
+
if (staticHandler) {
|
|
118
|
+
return staticHandler();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Phase I — Hosted Session API streaming routes (stream.run). Each
|
|
122
|
+
// intermediate event goes out as { id, type:"stream.event", event } and
|
|
123
|
+
// the final response is sent by the normal ok/err wrapper.
|
|
124
|
+
if (SESSION_CORE_STREAMING_HANDLERS[type]) {
|
|
125
|
+
const controller = new AbortController();
|
|
126
|
+
const client = server.clients.get(clientId);
|
|
127
|
+
if (client) {
|
|
128
|
+
client._streamAborts = client._streamAborts || new Map();
|
|
129
|
+
client._streamAborts.set(id, controller);
|
|
130
|
+
}
|
|
131
|
+
const sender = (payload) => server._send(ws, { id, ...payload });
|
|
132
|
+
const context = { server, ws, clientId };
|
|
133
|
+
try {
|
|
134
|
+
const result = await SESSION_CORE_STREAMING_HANDLERS[type](
|
|
135
|
+
message,
|
|
136
|
+
sender,
|
|
137
|
+
controller.signal,
|
|
138
|
+
context,
|
|
139
|
+
);
|
|
140
|
+
server._send(ws, { id, type: `${type}.end`, ...result });
|
|
141
|
+
} catch (err) {
|
|
142
|
+
server._send(ws, {
|
|
143
|
+
id,
|
|
144
|
+
type: "error",
|
|
145
|
+
code: "STREAM_RUN_ERROR",
|
|
146
|
+
message: err?.message || String(err),
|
|
147
|
+
});
|
|
148
|
+
} finally {
|
|
149
|
+
if (client?._streamAborts) client._streamAborts.delete(id);
|
|
150
|
+
}
|
|
151
|
+
return;
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
// Video Editing streaming routes
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
});
|
|
177
|
-
} finally {
|
|
178
|
-
if (client?._streamAborts) client._streamAborts.delete(id);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
155
|
+
if (VIDEO_STREAMING_HANDLERS[type]) {
|
|
156
|
+
const controller = new AbortController();
|
|
157
|
+
const client = server.clients.get(clientId);
|
|
158
|
+
if (client) {
|
|
159
|
+
client._streamAborts = client._streamAborts || new Map();
|
|
160
|
+
client._streamAborts.set(id, controller);
|
|
161
|
+
}
|
|
162
|
+
const sender = (payload) => server._send(ws, { id, ...payload });
|
|
163
|
+
try {
|
|
164
|
+
const result = await VIDEO_STREAMING_HANDLERS[type](
|
|
165
|
+
message,
|
|
166
|
+
sender,
|
|
167
|
+
controller.signal,
|
|
168
|
+
);
|
|
169
|
+
server._send(ws, { id, type: `${type}.end`, ...result });
|
|
170
|
+
} catch (err) {
|
|
171
|
+
server._send(ws, {
|
|
172
|
+
id,
|
|
173
|
+
type: "error",
|
|
174
|
+
code: "VIDEO_STREAM_ERROR",
|
|
175
|
+
message: err?.message || String(err),
|
|
176
|
+
});
|
|
177
|
+
} finally {
|
|
178
|
+
if (client?._streamAborts) client._streamAborts.delete(id);
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
// Video Editing request/response routes
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
code: "VIDEO_ERROR",
|
|
198
|
-
message: err?.message || String(err),
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
};
|
|
184
|
+
if (VIDEO_HANDLERS[type]) {
|
|
185
|
+
try {
|
|
186
|
+
const result = await VIDEO_HANDLERS[type](message);
|
|
187
|
+
server._send(ws, { id, type: `${type}.response`, ...result });
|
|
188
|
+
} catch (err) {
|
|
189
|
+
server._send(ws, {
|
|
190
|
+
id,
|
|
191
|
+
type: "error",
|
|
192
|
+
code: "VIDEO_ERROR",
|
|
193
|
+
message: err?.message || String(err),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return;
|
|
202
197
|
}
|
|
203
198
|
|
|
204
199
|
// Personal Data Hub topics — same 10 surfaces as the Electron IPC
|
|
205
200
|
// (see desktop-app-vue/src/main/ipc/personal-data-hub-ipc.js). Each
|
|
206
201
|
// handler returns { result } or { error }; we wrap with the standard
|
|
207
202
|
// response envelope so renderer code is shell-agnostic.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (out && out.error) {
|
|
213
|
-
server._send(ws, {
|
|
214
|
-
id,
|
|
215
|
-
type: "error",
|
|
216
|
-
code: "PERSONAL_DATA_HUB_ERROR",
|
|
217
|
-
message: out.error,
|
|
218
|
-
});
|
|
219
|
-
} else {
|
|
220
|
-
server._send(ws, {
|
|
221
|
-
id,
|
|
222
|
-
type: `${hubType}.response`,
|
|
223
|
-
result: out && out.result !== undefined ? out.result : out,
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
} catch (err) {
|
|
203
|
+
if (PERSONAL_DATA_HUB_HANDLERS[type]) {
|
|
204
|
+
try {
|
|
205
|
+
const out = await PERSONAL_DATA_HUB_HANDLERS[type](message);
|
|
206
|
+
if (out && out.error) {
|
|
227
207
|
server._send(ws, {
|
|
228
208
|
id,
|
|
229
209
|
type: "error",
|
|
230
210
|
code: "PERSONAL_DATA_HUB_ERROR",
|
|
231
|
-
message:
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Phase 5.7 — streaming sync routes. Adapter progress events are
|
|
238
|
-
// pushed as `<topic>.event` messages tagged with the request id;
|
|
239
|
-
// the final report comes as `<topic>.end`.
|
|
240
|
-
for (const streamType of Object.keys(
|
|
241
|
-
PERSONAL_DATA_HUB_STREAMING_HANDLERS,
|
|
242
|
-
)) {
|
|
243
|
-
routes[streamType] = async () => {
|
|
244
|
-
const sender = (payload) => server._send(ws, { id, ...payload });
|
|
245
|
-
try {
|
|
246
|
-
const out = await PERSONAL_DATA_HUB_STREAMING_HANDLERS[streamType](
|
|
247
|
-
message,
|
|
248
|
-
sender,
|
|
249
|
-
);
|
|
250
|
-
server._send(ws, {
|
|
251
|
-
id,
|
|
252
|
-
type: `${streamType}.end`,
|
|
253
|
-
...(out && out.result !== undefined
|
|
254
|
-
? { result: out.result }
|
|
255
|
-
: out || {}),
|
|
211
|
+
message: out.error,
|
|
256
212
|
});
|
|
257
|
-
}
|
|
213
|
+
} else {
|
|
258
214
|
server._send(ws, {
|
|
259
215
|
id,
|
|
260
|
-
type:
|
|
261
|
-
|
|
262
|
-
message: err?.message || String(err),
|
|
216
|
+
type: `${type}.response`,
|
|
217
|
+
result: out && out.result !== undefined ? out.result : out,
|
|
263
218
|
});
|
|
264
219
|
}
|
|
265
|
-
}
|
|
220
|
+
} catch (err) {
|
|
221
|
+
server._send(ws, {
|
|
222
|
+
id,
|
|
223
|
+
type: "error",
|
|
224
|
+
code: "PERSONAL_DATA_HUB_ERROR",
|
|
225
|
+
message: err?.message || String(err),
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
return;
|
|
266
229
|
}
|
|
267
230
|
|
|
268
|
-
// Phase
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
231
|
+
// Phase 5.7 — streaming sync routes. Adapter progress events are pushed
|
|
232
|
+
// as `<topic>.event` messages tagged with the request id; the final
|
|
233
|
+
// report comes as `<topic>.end`.
|
|
234
|
+
if (PERSONAL_DATA_HUB_STREAMING_HANDLERS[type]) {
|
|
235
|
+
const sender = (payload) => server._send(ws, { id, ...payload });
|
|
236
|
+
try {
|
|
237
|
+
const out = await PERSONAL_DATA_HUB_STREAMING_HANDLERS[type](
|
|
238
|
+
message,
|
|
239
|
+
sender,
|
|
240
|
+
);
|
|
241
|
+
server._send(ws, {
|
|
242
|
+
id,
|
|
243
|
+
type: `${type}.end`,
|
|
244
|
+
...(out && out.result !== undefined
|
|
245
|
+
? { result: out.result }
|
|
246
|
+
: out || {}),
|
|
247
|
+
});
|
|
248
|
+
} catch (err) {
|
|
249
|
+
server._send(ws, {
|
|
250
|
+
id,
|
|
251
|
+
type: "error",
|
|
252
|
+
code: "PERSONAL_DATA_HUB_STREAM_ERROR",
|
|
253
|
+
message: err?.message || String(err),
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return;
|
|
288
257
|
}
|
|
289
258
|
|
|
290
|
-
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
type:
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
259
|
+
// Phase I — Hosted Session API (session-core, memory, beta, usage)
|
|
260
|
+
if (SESSION_CORE_HANDLERS[type]) {
|
|
261
|
+
try {
|
|
262
|
+
const result = await SESSION_CORE_HANDLERS[type](message);
|
|
263
|
+
server._send(ws, { id, type: `${type}.response`, ...result });
|
|
264
|
+
} catch (err) {
|
|
265
|
+
server._send(ws, {
|
|
266
|
+
id,
|
|
267
|
+
type: "error",
|
|
268
|
+
code: "SESSION_CORE_ERROR",
|
|
269
|
+
message: err?.message || String(err),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
298
272
|
return;
|
|
299
273
|
}
|
|
300
274
|
|
|
301
|
-
|
|
275
|
+
server._send(ws, {
|
|
276
|
+
id,
|
|
277
|
+
type: "error",
|
|
278
|
+
code: "UNKNOWN_TYPE",
|
|
279
|
+
message: `Unknown message type: ${type}`,
|
|
280
|
+
});
|
|
281
|
+
return;
|
|
302
282
|
},
|
|
303
283
|
};
|
|
304
284
|
}
|
|
@@ -123,6 +123,33 @@ export class WSSessionManager {
|
|
|
123
123
|
this.maxPendingPatches = Number.isFinite(options.maxPendingPatches)
|
|
124
124
|
? options.maxPendingPatches
|
|
125
125
|
: 50;
|
|
126
|
+
// The entry-count caps above bound how MANY patches are kept, but a SINGLE
|
|
127
|
+
// proposed patch (a client-reachable `patch-propose`) could still carry an
|
|
128
|
+
// unbounded number of files, each with unbounded before/after/diff content
|
|
129
|
+
// — all held in memory AND serialized to disk by _persistSessionState. One
|
|
130
|
+
// file with a multi-GB diff string is enough to OOM. Bound a single patch's
|
|
131
|
+
// payload: cap the file count and truncate each content field.
|
|
132
|
+
this.maxPatchFiles = Number.isFinite(options.maxPatchFiles)
|
|
133
|
+
? options.maxPatchFiles
|
|
134
|
+
: 200;
|
|
135
|
+
this.maxPatchContentChars = Number.isFinite(options.maxPatchContentChars)
|
|
136
|
+
? options.maxPatchContentChars
|
|
137
|
+
: 512 * 1024; // 512 KB per before/after/diff field
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Truncate a patch content field (before/after/diff) to maxPatchContentChars,
|
|
142
|
+
* appending a visible marker. Preserves the null-vs-string distinction (a null
|
|
143
|
+
* field stays null — it signals create/delete ops). Pure.
|
|
144
|
+
*/
|
|
145
|
+
_capPatchContent(value) {
|
|
146
|
+
if (value == null) return null;
|
|
147
|
+
const s = String(value);
|
|
148
|
+
if (s.length <= this.maxPatchContentChars) return s;
|
|
149
|
+
return (
|
|
150
|
+
s.slice(0, this.maxPatchContentChars) +
|
|
151
|
+
`\n…[truncated for storage: field was ${s.length} chars]`
|
|
152
|
+
);
|
|
126
153
|
}
|
|
127
154
|
|
|
128
155
|
_normalizeEnabledToolNames(enabledToolNames) {
|
|
@@ -854,8 +881,13 @@ export class WSSessionManager {
|
|
|
854
881
|
const session = this.sessions.get(sessionId);
|
|
855
882
|
if (!session) return null;
|
|
856
883
|
|
|
857
|
-
const
|
|
858
|
-
if (
|
|
884
|
+
const rawFiles = Array.isArray(payload.files) ? payload.files : [];
|
|
885
|
+
if (rawFiles.length === 0) return null;
|
|
886
|
+
// Cap the per-patch file count; a proposal touching more than this is
|
|
887
|
+
// pathological for review. Excess files are dropped (count recorded below)
|
|
888
|
+
// so one message can't pin unbounded memory / disk.
|
|
889
|
+
const files = rawFiles.slice(0, this.maxPatchFiles);
|
|
890
|
+
const droppedFiles = rawFiles.length - files.length;
|
|
859
891
|
|
|
860
892
|
const patchId = `patch-${this._generateId()}`;
|
|
861
893
|
const now = new Date().toISOString();
|
|
@@ -866,9 +898,9 @@ export class WSSessionManager {
|
|
|
866
898
|
index,
|
|
867
899
|
path: file.path || `unknown-${index}`,
|
|
868
900
|
op,
|
|
869
|
-
before:
|
|
870
|
-
after:
|
|
871
|
-
diff:
|
|
901
|
+
before: this._capPatchContent(file.before),
|
|
902
|
+
after: this._capPatchContent(file.after),
|
|
903
|
+
diff: this._capPatchContent(file.diff),
|
|
872
904
|
stats,
|
|
873
905
|
};
|
|
874
906
|
});
|
|
@@ -895,6 +927,8 @@ export class WSSessionManager {
|
|
|
895
927
|
fileCount: normalizedFiles.length,
|
|
896
928
|
added: totalStats.added,
|
|
897
929
|
removed: totalStats.removed,
|
|
930
|
+
// Surfaced so the reviewer/UI knows the proposal was capped for storage.
|
|
931
|
+
...(droppedFiles > 0 ? { droppedFiles } : {}),
|
|
898
932
|
},
|
|
899
933
|
};
|
|
900
934
|
|
|
@@ -113,20 +113,36 @@ export function readEvents(sessionId) {
|
|
|
113
113
|
return events;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* A replayable chat message must be a `{ role, content }` object — guard
|
|
118
|
+
* against a corrupt / partially-written / hand-edited event whose `data` is
|
|
119
|
+
* missing, null, or not a message (it would otherwise inject `undefined` into
|
|
120
|
+
* the resumed history and break the next LLM request).
|
|
121
|
+
*/
|
|
122
|
+
function isReplayableMessage(m) {
|
|
123
|
+
return Boolean(m) && typeof m === "object" && typeof m.role === "string";
|
|
124
|
+
}
|
|
125
|
+
|
|
116
126
|
export function rebuildMessages(sessionId) {
|
|
117
127
|
const events = readEvents(sessionId);
|
|
118
128
|
const messages = [];
|
|
119
129
|
let lastCompactIndex = -1;
|
|
120
130
|
|
|
131
|
+
// A `compact` event carries the pre-compaction snapshot in data.messages. A
|
|
132
|
+
// malformed compact line (type present but data null / messages not an array)
|
|
133
|
+
// must not crash the resume — skip it and look further back.
|
|
121
134
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
122
|
-
|
|
135
|
+
const e = events[i];
|
|
136
|
+
if (e && e.type === "compact" && Array.isArray(e.data?.messages)) {
|
|
123
137
|
lastCompactIndex = i;
|
|
124
138
|
break;
|
|
125
139
|
}
|
|
126
140
|
}
|
|
127
141
|
|
|
128
|
-
if (lastCompactIndex >= 0
|
|
129
|
-
|
|
142
|
+
if (lastCompactIndex >= 0) {
|
|
143
|
+
for (const m of events[lastCompactIndex].data.messages) {
|
|
144
|
+
if (isReplayableMessage(m)) messages.push(m);
|
|
145
|
+
}
|
|
130
146
|
}
|
|
131
147
|
|
|
132
148
|
const startIndex = lastCompactIndex >= 0 ? lastCompactIndex + 1 : 0;
|
|
@@ -134,9 +150,11 @@ export function rebuildMessages(sessionId) {
|
|
|
134
150
|
for (let i = startIndex; i < events.length; i++) {
|
|
135
151
|
const event = events[i];
|
|
136
152
|
if (
|
|
137
|
-
event
|
|
138
|
-
event.type === "
|
|
139
|
-
|
|
153
|
+
event &&
|
|
154
|
+
(event.type === "user_message" ||
|
|
155
|
+
event.type === "assistant_message" ||
|
|
156
|
+
event.type === "system") &&
|
|
157
|
+
isReplayableMessage(event.data)
|
|
140
158
|
) {
|
|
141
159
|
messages.push(event.data);
|
|
142
160
|
}
|
|
@@ -145,6 +163,19 @@ export function rebuildMessages(sessionId) {
|
|
|
145
163
|
return messages;
|
|
146
164
|
}
|
|
147
165
|
|
|
166
|
+
/** ISO string for a numeric ms timestamp, or "" when missing / non-finite /
|
|
167
|
+
* invalid — `new Date(undefined).toISOString()` (and `new Date("garbage")`)
|
|
168
|
+
* throw "Invalid time value", and one corrupt event must not crash a whole
|
|
169
|
+
* `cc session list` / `cc session search`. Exported so command-layer readers of
|
|
170
|
+
* the same (hand-editable) JSONL share the guard. */
|
|
171
|
+
export function toIsoSafe(ts) {
|
|
172
|
+
if (ts == null) return ""; // null/undefined → "" (Number(null) is 0 = epoch)
|
|
173
|
+
const n = Number(ts);
|
|
174
|
+
if (!Number.isFinite(n)) return "";
|
|
175
|
+
const d = new Date(n);
|
|
176
|
+
return Number.isNaN(d.getTime()) ? "" : d.toISOString();
|
|
177
|
+
}
|
|
178
|
+
|
|
148
179
|
export function listJsonlSessions(options = {}) {
|
|
149
180
|
const dir = getSessionsDir();
|
|
150
181
|
if (!existsSync(dir)) return [];
|
|
@@ -167,12 +198,8 @@ export function listJsonlSessions(options = {}) {
|
|
|
167
198
|
provider: startEvent?.data?.provider || "",
|
|
168
199
|
model: startEvent?.data?.model || "",
|
|
169
200
|
message_count: messageCount,
|
|
170
|
-
created_at: startEvent
|
|
171
|
-
|
|
172
|
-
: "",
|
|
173
|
-
updated_at: lastEvent
|
|
174
|
-
? new Date(lastEvent.timestamp).toISOString()
|
|
175
|
-
: "",
|
|
201
|
+
created_at: toIsoSafe(startEvent?.timestamp),
|
|
202
|
+
updated_at: toIsoSafe(lastEvent?.timestamp),
|
|
176
203
|
_lastTs: lastEvent?.timestamp || 0,
|
|
177
204
|
_eventCount: events.length,
|
|
178
205
|
};
|
|
@@ -550,6 +550,11 @@ function _hasUncommittedChanges(worktreePath) {
|
|
|
550
550
|
const output = execSync("git status --porcelain", {
|
|
551
551
|
cwd: worktreePath,
|
|
552
552
|
encoding: "utf-8",
|
|
553
|
+
// A worktree with many dirty files produces >1 MB of porcelain output and
|
|
554
|
+
// would ENOBUFS on the default cap — the catch below then reports "clean"
|
|
555
|
+
// (fail-OPEN), which could let a caller discard a worktree full of
|
|
556
|
+
// uncommitted work. Give it the same 64 MB headroom as gitExec.
|
|
557
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
553
558
|
});
|
|
554
559
|
return output.trim().length > 0;
|
|
555
560
|
} catch (_e) {
|
package/src/lib/agent-core.js
CHANGED
package/src/lib/audit-logger.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import crypto from "crypto";
|
|
7
|
+
import { safeJsonParse } from "./safe-json.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Event types for audit logging.
|
|
@@ -232,7 +233,8 @@ export function queryLogs(db, filters = {}) {
|
|
|
232
233
|
const rows = db.prepare(sql).all(...params);
|
|
233
234
|
return rows.map((r) => ({
|
|
234
235
|
...r,
|
|
235
|
-
|
|
236
|
+
// One corrupt details cell must not throw out of the whole query.
|
|
237
|
+
details: safeJsonParse(r.details, null),
|
|
236
238
|
success: r.success === 1,
|
|
237
239
|
}));
|
|
238
240
|
}
|
package/src/lib/chat-core.js
CHANGED
|
@@ -13,8 +13,8 @@ import { BUILT_IN_PROVIDERS } from "./llm-providers.js";
|
|
|
13
13
|
import { appendTokenUsage } from "../harness/jsonl-session-store.js";
|
|
14
14
|
import {
|
|
15
15
|
isRetryableStreamError,
|
|
16
|
-
STREAM_RETRY_MAX,
|
|
17
16
|
STREAM_RETRY_BASE_MS,
|
|
17
|
+
resolveStreamRetryMax,
|
|
18
18
|
} from "./stream-retry.js";
|
|
19
19
|
|
|
20
20
|
// A streaming chat call must not hang forever if the API accepts the connection
|
|
@@ -513,6 +513,9 @@ export async function* chatStream(messages, options) {
|
|
|
513
513
|
// any token still terminates the generator cleanly.
|
|
514
514
|
const streamPromise = (async () => {
|
|
515
515
|
try {
|
|
516
|
+
// Budget honors CC_MAX_RETRIES / CLAUDE_CODE_MAX_RETRIES (capped 15),
|
|
517
|
+
// same as the agent path.
|
|
518
|
+
const maxRetries = resolveStreamRetryMax();
|
|
516
519
|
let attempt = 0;
|
|
517
520
|
for (;;) {
|
|
518
521
|
try {
|
|
@@ -524,7 +527,7 @@ export async function* chatStream(messages, options) {
|
|
|
524
527
|
// zero-output retry safety (cc agent parity). Stall aborts (180s) and
|
|
525
528
|
// HTTP/auth errors are not retryable and surface immediately.
|
|
526
529
|
if (
|
|
527
|
-
attempt >=
|
|
530
|
+
attempt >= maxRetries ||
|
|
528
531
|
tokensEmitted > 0 ||
|
|
529
532
|
!isRetryableStreamError(err)
|
|
530
533
|
) {
|