chainlesschain 0.162.174 → 0.162.176
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 +10 -10
- package/src/assets/web-panel/assets/{AIOps-Dcl-X1Hw.js → AIOps-BDLu5Elz.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-ClMh9HzT.js → ActionButton-DH5us-CK.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DPj0rSQ5.js → Analytics-BZ0u8IFG.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-L8781rE8.js → Artifacts-Br2YBbh_.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CffB6WIP.js → Audit-C3C6a482.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BkLhayyY.js → BackgroundAgents-CzHvebcj.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BQnwFI78.js → Backup-DZNHYDFd.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-xuUGHQch.js → BaseInput-VRiC4fIx.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-feQXwWrg.js → Chat-Cm08WWAD.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CGHYrugQ.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-DVaIiUGW.js → Checkbox-DtByk7d7.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-D2kEnzeU.js → Codegen-CphXXOfD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-azDoyusS.js → Col-Hz86TnLR.js} +1 -1
- package/src/assets/web-panel/assets/{Community-OZdnPWM5.js → Community-HP03ltpD.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-VDMvBN-C.js → Compact-B_N1mqQz.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CPJ_zgQ1.js → Compliance-CVztRpi8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-iRBwcsOA.js → Cowork-wUVOyZih.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DrxrspUz.js → Cron-DW5TLJKw.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-D-rkAZXF.js → Crosschain-CrAFGhWH.js} +1 -1
- package/src/assets/web-panel/assets/{DID-5Pp1Xnmr.js → DID-pA-oD8ke.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-BWj_E0Ie.js → Dropdown-EweJcsek.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BT-wgSEh.js → EmailListRenderer-C9xVLPG4.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-1PzH23pa.js → FamilyGuardDashboard-CDcEEqlu.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BxMIXGC6.js → Federation-DtZda9A_.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CyJobBln.js → FormItemContext-CiYdcVz3.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-YkjFuQTN.js → GenericCardRenderer-DA13uwA0.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C2a98Wp_.js → Git-DzRhZD1O.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DKL3Fl84.js → Governance-D5RMgOSb.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BJ2cQC_3.js → Inference-BgrPfSNk.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DBAsOngt.js → KnowledgeGraph-DzjnD571.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-COt8g9LO.js → Logs-BhWzVDtN.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-3Lfht1Fd.js → MarkdownRenderer-BDape9cx.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-C9Zk9Pb2.js → Marketplace-DJtL5GV7.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DDWDFWPO.js → McpTools-CZcQygI7.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BRmVye_o.js → Memory-DUWSDUUu.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CppBbWpD.js → MobileBridge-BTwq2WKY.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CcWpeGa6.js → Mtc-BiGugEQm.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-BcllEq0K.js → MtcAudit-DY7a6gUe.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BFD1CarL.js → Multisig-BQbDu_w7.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-QNXXYvjz.js → NLProgramming-CM2wXTLv.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-07YwgQVy.js → Notes-DI6gGs1v.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-bOccEInE.js → NotificationSettings-BsZOLWAB.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DlRi29WL.js → OrderTableRenderer-C48mu09U.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CBaezzEr.js → Organization-Cds0_tXr.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bl5NohFO.js → Overflow-WunYMD87.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CLMal9Aw.js → P2P-Bo6j4DDv.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CGO0NITk.js → PdhVaultBrowser-Bh2XPD5f.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CPSw48E2.js → Permissions-EMvMMC8N.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-CDM5n134.js → PersonalDataHub-AX3ypUDV.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-BdsqG7WV.js → Pipeline-BOx8HOgL.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B6L4E-M7.js → Privacy-tBeTVQVM.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DXPyZKRs.js → ProjectInit-CVYg1W4M.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BrCC3xYT.js → ProjectSettings-Dvt5I7y1.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BYmuHC2q.js → Projects-Cc7FC9-e.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-CbCe2eUl.js → Providers-Ct8xqY-E.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DkukgCrR.js → QrScannerModal-Cni8Ooja.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D-htOrV8.js → QuickAsk-BJVLKdxr.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Bm7SIfzu.js → Recommend-DPG8Rbbm.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C9rP-iMc.js → RemoteSession-DsdR7dCt.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-kGlUgbsl.js → Reputation-Csg1YM-b.js} +1 -1
- package/src/assets/web-panel/assets/{Row-PBupbbUA.js → Row-D9DoFoEf.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-njlwKUGK.js → RssFeed-BsvKrXMS.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DLdEmgBw.js → Search-DFUStfgQ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-SXGPSHdu.js → Security-ILg1zxdK.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CuFGnNsb.js → Services-Dd41PCaY.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CtUC0mDa.js → Skeleton-Bzo1cN80.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-P1qgOVFn.js → Skills-BDHh17P0.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CsppE8YV.js → Sla-jl7UTiRY.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Cq1oG56m.js → SpeechSettings-BePa-RF6.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DdKW6V-C.js → SyncSettings-DiqqDKGZ.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BCc9san5.js → Tasks-DYQ_6lxj.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CcHC1dMA.js → Templates-JiDeI06L.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CA4PqU22.js → Tenant-hhgI6zwS.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-DHWTSvOy.js → TimelineRenderer-B8uB5Llk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Ddz-P_yh.js → Tokens-C3b_6r2z.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-ePmrmLZ1.js → Trigger-tIP7HKVe.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DmuK1CCE.js → Trust-vjoc11vJ.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CqqBuRrT.js → UkeySign-DUPBnGuH.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BGlR3uWM.js → VideoEditing-CBvhUY5T.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Ba_Qx6Ga.js → Wallet-DUaQ0uA5.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-29neXKt2.js → WebAuthn-DllSivjE.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-lD0lR0UQ.js → WorkflowEditor-xc8D3uO6.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B3stH01u.js → chat-BVicU7oA.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Czly56MN.js → colors-DJzLmhLm.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-C0TkbkAJ.js → compact-item-BvYRfThE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BJmpSlf1.js → createContext-DGXxCBKR.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D1q-zw7u.js → hasIn-SBDJB1y4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV-twjNO.js → index-1SdDS6lR.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-kTvMq7.js → index-9gdI7uUW.js} +1 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +1 -0
- package/src/assets/web-panel/assets/{index-Bm_-RKal.js → index-BJZf9DhV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQftlZn-.js → index-BO1itZaY.js} +3 -3
- package/src/assets/web-panel/assets/{index-Dw3L_smW.js → index-BTrBGBJs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7sFKQ53.js → index-BYqz4Wrr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlvsSuBC.js → index-Bf-ctERC.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChESIe5r.js → index-CKyEivf8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaqEHaCg.js → index-CdGY9P8a.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZeoKL6t.js → index-Cf-O_g_8.js} +1 -1
- package/src/assets/web-panel/assets/{index-XWV8JWMc.js → index-CloCgBUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpMIdPJ0.js → index-CoJAO1Lm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgS8XUBU.js → index-Crk5NTb0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmUta2lw.js → index-Cs2rmLFt.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dpz_7sf-.js → index-CtwqO5qo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRcQsPez.js → index-D7HimK0M.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEt2-3x5.js → index-DCdRAgjy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHvPlzWJ.js → index-DCqRS6da.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDHXx65P.js → index-DHVLJ8q0.js} +1 -1
- package/src/assets/web-panel/assets/{index-K4YaPDOn.js → index-DKrvvWm4.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1pOqU7D.js → index-DMarmfrv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAhrn9EJ.js → index-DRfiXB_p.js} +1 -1
- package/src/assets/web-panel/assets/{index-cPjWjvmW.js → index-Dm_77jgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-C27TnOoT.js → index-DnjPdvR6.js} +1 -1
- package/src/assets/web-panel/assets/{index-upY9rkGZ.js → index-DonCnfMr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbvNJUwu.js → index-DvUTDYXX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVwJ3jht.js → index-FxZzRyE1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIF6XHIi.js → index-MjC4G09d.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8KqsomG.js → index-VMfwIH5G.js} +1 -1
- package/src/assets/web-panel/assets/{index-8GKykbS4.js → index-YJkzy8ZF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpGs96FC.js → index-d5BVd-cL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DO8xOwxi.js → index-e4fXH_WO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cu_4HaUS.js → index-hxTODbM1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf7Gr3NG.js → index-lpaGoTH3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBqAm8es.js → index-wcCL-miV.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZDUhX41Z.js → index-xfluRkCT.js} +1 -1
- package/src/assets/web-panel/assets/index-ycwAfC-i.js +1 -0
- package/src/assets/web-panel/assets/{index-z8ATo2aQ.js → index-z1ZylsLq.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-QWEXi6-t.js → initDefaultProps-C1zO1KnY.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BfrQwvV1.js → motion-CWLtEGmC.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dn7x0H9t.js → move-DzD_C3Vm.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-F61D_TgE.js → mtc-parser-D880PYJl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-4SQZ39PF.js → omit-CFR_z2ov.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-C7DTe126.js → pickAttrs-srIhgrSC.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-40NeyzDK.js → placementArrow-C1rXpibP.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BiUJ6qWs.js → responsiveObserve-C30gRcSS.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CacJTM3f.js → slide-CvtKiMfV.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-K812HB-k.js → statusUtils-DNHO7ITG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CKeHA2eM.js → styleChecker-Dt_Sl-g4.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CKl4FqXF.js → useFlexGapSupport-Cjev42Gh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DPoiJjSZ.js → useFs-Baxglj2V.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-aHwBspmt.js → usePersonalDataHub-B4NkcLaP.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DrA-GuCT.js → vnode-mIRkdT7o.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-G3LMswgy.js → zoom-HzI5DlH_.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/auth/npm-auth.js +30 -5
- package/src/commands/agenda.js +64 -2
- package/src/commands/agent.js +45 -3
- package/src/commands/background-session.js +103 -0
- package/src/commands/config.js +70 -5
- package/src/commands/context.js +36 -2
- package/src/commands/hub.js +19 -1
- package/src/commands/memory.js +21 -6
- package/src/commands/permissions.js +57 -1
- package/src/commands/plugin.js +2 -0
- package/src/commands/review.js +23 -11
- package/src/commands/routine.js +31 -8
- package/src/commands/session.js +11 -3
- package/src/commands/team.js +20 -7
- package/src/commands/update.js +65 -10
- package/src/esm-bridge.js +3 -0
- package/src/gateways/terminal/PtyManager.js +8 -1
- package/src/gateways/ws/message-dispatcher.js +3 -0
- package/src/gateways/ws/session-protocol.js +26 -0
- package/src/gateways/ws/ws-agent-handler.js +107 -69
- package/src/gateways/ws/ws-server.js +92 -4
- package/src/harness/jsonl-session-store.js +13 -6
- package/src/harness/mcp-client.js +200 -1
- package/src/index.js +123 -55
- package/src/lazy-dispatch.js +86 -85
- package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +15 -0
- package/src/lib/agent-coordinator.js +4 -0
- package/src/lib/agent-ipc-bus.js +32 -2
- package/src/lib/agent-sandbox.js +16 -2
- package/src/lib/agent-schedule-store.js +55 -0
- package/src/lib/agent-tool-admission.js +104 -0
- package/src/lib/api-key-helper.js +10 -2
- package/src/lib/async-hook-supervisor.cjs +26 -4
- package/src/lib/background-interaction-resolver.js +71 -0
- package/src/lib/background-session-transport.js +59 -1
- package/src/lib/changelog.js +19 -11
- package/src/lib/channels/channel-manager.js +6 -0
- package/src/lib/channels/telegram-channel.js +11 -1
- package/src/lib/channels/webhook-channel.js +15 -3
- package/src/lib/checkpoint-store.js +10 -2
- package/src/lib/cloud/bundle.js +12 -2
- package/src/lib/code-review.js +32 -8
- package/src/lib/computer-use/control-backend.js +18 -3
- package/src/lib/context-breakdown.js +46 -0
- package/src/lib/context-source-ledger.js +43 -0
- package/src/lib/crash-reporter.js +6 -0
- package/src/lib/diff-review-follow-up.js +154 -0
- package/src/lib/downloader.js +17 -3
- package/src/lib/ensure-utf8.js +11 -3
- package/src/lib/event-runtime-producer.js +58 -0
- package/src/lib/event-runtime-store.js +354 -0
- package/src/lib/event-runtime-worker.js +109 -0
- package/src/lib/execution-backend.js +72 -21
- package/src/lib/git-integration.js +19 -4
- package/src/lib/hook-manager.js +34 -15
- package/src/lib/hook-runner.cjs +48 -3
- package/src/lib/hooks-v2-producers.js +15 -0
- package/src/lib/hooks-v2-runtime.js +70 -21
- package/src/lib/host-adb-bridge.js +111 -21
- package/src/lib/ide-context.js +128 -1
- package/src/lib/interaction-adapter.js +39 -0
- package/src/lib/ipc-attach-protocol.js +98 -0
- package/src/lib/json-schema-validate.js +190 -36
- package/src/lib/lan-pairing-preflight.js +13 -2
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
- package/src/lib/lsp/lsp-client.js +18 -1
- package/src/lib/lsp/lsp-manager.js +4 -0
- package/src/lib/lsp/lsp-server-registry.js +11 -0
- package/src/lib/mcp-oauth.js +8 -2
- package/src/lib/npm-invocation.js +29 -0
- package/src/lib/packer/pkg-runner.js +13 -2
- package/src/lib/packer/precheck.js +33 -16
- package/src/lib/packer/web-panel-builder.js +16 -2
- package/src/lib/permission-rules.cjs +5 -1
- package/src/lib/personal-data-hub-aichat-wizard.js +22 -6
- package/src/lib/personal-data-hub-wiring.js +27 -3
- package/src/lib/plan-mode.js +204 -11
- package/src/lib/plugin-monitor-supervisor.js +39 -4
- package/src/lib/plugin-runtime/bin.js +45 -0
- package/src/lib/plugin-runtime/hooks.js +14 -1
- package/src/lib/plugin-runtime/install.js +2 -1
- package/src/lib/plugin-runtime/lsp.js +3 -0
- package/src/lib/plugin-runtime/mcp.js +8 -1
- package/src/lib/plugin-runtime/monitors.js +4 -0
- package/src/lib/plugin-runtime/plugin-options.js +74 -7
- package/src/lib/plugin-runtime/signature.js +45 -0
- package/src/lib/pr-create.js +21 -8
- package/src/lib/pr-link-ledger.js +15 -3
- package/src/lib/process-execution-broker/credential-agent.js +295 -0
- package/src/lib/process-execution-broker/index.js +440 -14
- package/src/lib/process-execution-broker/patch-child-process.js +2 -3
- package/src/lib/process-execution-broker/platform-sandbox.js +351 -0
- package/src/lib/process-manager.js +18 -3
- package/src/lib/provenance-api.js +6 -0
- package/src/lib/proxy-bootstrap.js +19 -0
- package/src/lib/publish-workspace.js +14 -6
- package/src/lib/repl-rewind.js +9 -4
- package/src/lib/secret-store.js +159 -0
- package/src/lib/service-manager.js +64 -29
- package/src/lib/session-hooks.js +328 -473
- package/src/lib/session-telemetry-middleware.js +6 -0
- package/src/lib/settings-hook-events.cjs +61 -1
- package/src/lib/settings-hooks.cjs +4 -0
- package/src/lib/side-effect-ledger.js +22 -0
- package/src/lib/sub-agent-context.js +5 -0
- package/src/lib/sub-agent-profiles.js +4 -0
- package/src/lib/trace-api.js +6 -0
- package/src/lib/turn-context.js +14 -8
- package/src/lib/unattended-action-policy.js +83 -0
- package/src/lib/update-notice.js +9 -45
- package/src/lib/with-file-lock.js +7 -0
- package/src/lib/ws-server.js +1 -0
- package/src/repl/agent-repl.js +71 -13
- package/src/repl/clipboard-copy.js +8 -2
- package/src/repl/pr-comments.js +30 -7
- package/src/runtime/agent-core.js +439 -87
- package/src/runtime/agent-runtime.js +1 -0
- package/src/runtime/coding-agent-contract-shared.cjs +52 -0
- package/src/runtime/coding-agent-policy.cjs +20 -0
- package/src/runtime/diagnostics.js +73 -8
- package/src/runtime/headless-runner.js +63 -0
- package/src/runtime/headless-stream.js +269 -17
- package/src/runtime/mcp-config.js +16 -1
- package/src/workers/background-agent-worker.js +80 -1
- package/src/assets/web-panel/assets/AppLayout-7iSKDmlI.js +0 -9
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DcbUHeGW.js +0 -1
- package/src/assets/web-panel/assets/Dashboard-BAKYNavw.js +0 -3
- package/src/assets/web-panel/assets/MobileProjects-C4GKn1dH.js +0 -1
- package/src/assets/web-panel/assets/Terminal-Fj7ea0In.js +0 -3
- package/src/assets/web-panel/assets/devWarning-CDI8Sbaj.js +0 -1
- package/src/assets/web-panel/assets/index-96LBR96V.js +0 -1
- package/src/assets/web-panel/assets/index-DyQkiW24.js +0 -1
package/src/lib/session-hooks.js
CHANGED
|
@@ -1,236 +1,219 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Session
|
|
3
|
-
* the tool-level PreToolUse/PostToolUse hooks already wired in
|
|
4
|
-
* `runtime/agent-core.js`.
|
|
2
|
+
* Session hooks - 会话级钩子触发工具
|
|
5
3
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Semantics (matches existing PreToolUse convention):
|
|
14
|
-
* - Fire-and-forget by default: hook failures NEVER break the host flow
|
|
15
|
-
* - `fireUserPromptSubmit` / `fireAssistantResponse` are opt-in helpers
|
|
16
|
-
* that parse stdout JSON directives ({rewrittenPrompt,abort} /
|
|
17
|
-
* {rewrittenResponse,suppress}) for callers that want control flow
|
|
18
|
-
* - No-op when hookDb is null (REPL without DB)
|
|
19
|
-
* - Helper-side timeout protects against runaway hooks even if
|
|
20
|
-
* hook-manager's per-hook timeout is misconfigured
|
|
21
|
-
* - Swallowed errors are persisted to hook_execution_log when possible
|
|
4
|
+
* 用于 agent-repl 的三件套会话级钩子:
|
|
5
|
+
* - SessionStart
|
|
6
|
+
* - UserPromptSubmit
|
|
7
|
+
* - AssistantResponse
|
|
8
|
+
* - SessionEnd
|
|
9
|
+
* - Notification
|
|
22
10
|
*/
|
|
23
11
|
|
|
24
|
-
import {
|
|
12
|
+
import { HookEvents, executeHooks } from "./hook-manager.js";
|
|
25
13
|
|
|
26
|
-
|
|
27
|
-
* Events this helper is allowed to fire. Guards against typos that
|
|
28
|
-
* would otherwise silently no-op inside executeHooks' event filter.
|
|
29
|
-
*/
|
|
14
|
+
// 会话钩子白名单
|
|
30
15
|
export const SESSION_HOOK_EVENTS = Object.freeze([
|
|
31
16
|
HookEvents.SessionStart,
|
|
32
17
|
HookEvents.UserPromptSubmit,
|
|
33
18
|
HookEvents.AssistantResponse,
|
|
34
19
|
HookEvents.SessionEnd,
|
|
20
|
+
HookEvents.Notification,
|
|
35
21
|
]);
|
|
36
22
|
|
|
37
|
-
|
|
38
|
-
* Helper-side wall-clock cap. Per-hook timeout still lives in the
|
|
39
|
-
* registered hook row; this is a belt-and-suspenders bound so a
|
|
40
|
-
* misconfigured hook can never wedge the REPL.
|
|
41
|
-
*/
|
|
42
|
-
const HELPER_TIMEOUT_MS = Number(
|
|
43
|
-
process.env.CC_SESSION_HOOK_TIMEOUT_MS || 15000,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Internal deps — exposed for tests via `_deps` injection.
|
|
48
|
-
* Keeping this mutable lets vitest swap out timer/log writers without
|
|
49
|
-
* resorting to vi.mock (which doesn't intercept inlined CJS).
|
|
50
|
-
*/
|
|
23
|
+
// 依赖注入点(用于测试)
|
|
51
24
|
export const _deps = {
|
|
52
25
|
executeHooks,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// Best-effort persistence to hook_execution_log; never throws.
|
|
56
|
-
if (!hookDb || typeof hookDb.prepare !== "function") return;
|
|
57
|
-
try {
|
|
58
|
-
const stmt = hookDb.prepare(
|
|
59
|
-
`INSERT INTO hook_execution_log
|
|
60
|
-
(hook_id, event, success, error, executed_at)
|
|
61
|
-
VALUES (?, ?, ?, ?, ?)`,
|
|
62
|
-
);
|
|
63
|
-
stmt.run(
|
|
64
|
-
null,
|
|
65
|
-
eventName,
|
|
66
|
-
0,
|
|
67
|
-
String(err && err.message ? err.message : err),
|
|
68
|
-
new Date().toISOString(),
|
|
69
|
-
);
|
|
70
|
-
} catch {
|
|
71
|
-
/* table may not exist yet — silent */
|
|
72
|
-
}
|
|
26
|
+
logFailure: (_db, event, error) => {
|
|
27
|
+
console.error(`[session-hooks] Failed to fire ${event}:`, error);
|
|
73
28
|
},
|
|
74
29
|
};
|
|
75
30
|
|
|
76
31
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* @
|
|
82
|
-
* @param {string} eventName one of SESSION_HOOK_EVENTS
|
|
83
|
-
* @param {object} [context] forwarded to hook matcher + handler env
|
|
84
|
-
* @returns {Promise<Array>}
|
|
32
|
+
* 通用会话钩子触发函数
|
|
33
|
+
* @param {object} db - 数据库实例
|
|
34
|
+
* @param {string} event - 钩子事件名
|
|
35
|
+
* @param {object} [context={}] - 钩子上下文
|
|
36
|
+
* @returns {Promise<Array>} 钩子执行结果数组
|
|
85
37
|
*/
|
|
86
|
-
export async function fireSessionHook(
|
|
87
|
-
|
|
88
|
-
if (!SESSION_HOOK_EVENTS.includes(
|
|
89
|
-
throw new Error(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
38
|
+
export async function fireSessionHook(db, event, context = {}) {
|
|
39
|
+
// 白名单验证
|
|
40
|
+
if (!SESSION_HOOK_EVENTS.includes(event)) {
|
|
41
|
+
throw new Error(`"${event}" is not a session hook event`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 如果没有数据库,空操作
|
|
45
|
+
if (!db) {
|
|
46
|
+
return [];
|
|
93
47
|
}
|
|
94
48
|
|
|
95
49
|
try {
|
|
96
|
-
|
|
50
|
+
// 注入时间戳
|
|
51
|
+
const ctxWithTimestamp = {
|
|
97
52
|
timestamp: new Date().toISOString(),
|
|
98
53
|
...context,
|
|
99
54
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Hook failures must never break the REPL — but we record them
|
|
107
|
-
_deps.logFailure(hookDb, eventName, err);
|
|
55
|
+
|
|
56
|
+
// 执行钩子
|
|
57
|
+
const results = await _deps.executeHooks(db, event, ctxWithTimestamp);
|
|
58
|
+
return Array.isArray(results) ? results : [];
|
|
59
|
+
} catch (error) {
|
|
60
|
+
_deps.logFailure(db, event, error);
|
|
108
61
|
return [];
|
|
109
62
|
}
|
|
110
63
|
}
|
|
111
64
|
|
|
112
65
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* {"abort": true, "reason": "..."} — skip agentLoop entirely
|
|
118
|
-
*
|
|
119
|
-
* First matching directive wins (priority order from executeHooks).
|
|
120
|
-
* Malformed JSON / no directive → no change (pure observation).
|
|
121
|
-
*
|
|
66
|
+
* 触发用户提交提示词钩子
|
|
67
|
+
* @param {object} db - 数据库实例
|
|
68
|
+
* @param {string} prompt - 用户提示词
|
|
69
|
+
* @param {object} [context={}] - 上下文
|
|
122
70
|
* @returns {Promise<{prompt: string, abort: boolean, reason?: string, results: Array}>}
|
|
123
71
|
*/
|
|
124
|
-
export async function fireUserPromptSubmit(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
context = {},
|
|
128
|
-
) {
|
|
129
|
-
const results = await fireSessionHook(hookDb, HookEvents.UserPromptSubmit, {
|
|
72
|
+
export async function fireUserPromptSubmit(db, prompt, context = {}) {
|
|
73
|
+
const results = await fireSessionHook(db, HookEvents.UserPromptSubmit, {
|
|
74
|
+
prompt,
|
|
130
75
|
...context,
|
|
131
|
-
prompt: originalPrompt,
|
|
132
76
|
});
|
|
133
77
|
|
|
134
|
-
let
|
|
78
|
+
let rewrittenPrompt = prompt;
|
|
135
79
|
let abort = false;
|
|
136
|
-
let
|
|
80
|
+
let abortReason;
|
|
137
81
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
break;
|
|
82
|
+
// 处理钩子返回的指令
|
|
83
|
+
for (const result of results) {
|
|
84
|
+
if (!result.success) continue;
|
|
85
|
+
try {
|
|
86
|
+
const output = result.stdout ? JSON.parse(result.stdout) : {};
|
|
87
|
+
if (output.rewrittenPrompt) {
|
|
88
|
+
rewrittenPrompt = output.rewrittenPrompt;
|
|
89
|
+
}
|
|
90
|
+
if (output.abort) {
|
|
91
|
+
abort = true;
|
|
92
|
+
abortReason = output.reason || "aborted by hook";
|
|
93
|
+
}
|
|
94
|
+
} catch {
|
|
95
|
+
// 忽略解析错误
|
|
153
96
|
}
|
|
154
97
|
}
|
|
155
98
|
|
|
156
|
-
return {
|
|
99
|
+
return {
|
|
100
|
+
prompt: rewrittenPrompt,
|
|
101
|
+
abort,
|
|
102
|
+
reason: abortReason,
|
|
103
|
+
results,
|
|
104
|
+
};
|
|
157
105
|
}
|
|
158
106
|
|
|
159
107
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* {"suppress": true, "reason": "..."} — drop the response entirely
|
|
165
|
-
*
|
|
166
|
-
* Common use: PII / secret scrubbing, watermark injection, profanity
|
|
167
|
-
* filter on the model's final string before it reaches the terminal.
|
|
168
|
-
*
|
|
108
|
+
* 触发助手响应钩子(已存在,重写增强)
|
|
109
|
+
* @param {object} db - 数据库实例
|
|
110
|
+
* @param {string} response - 助手响应
|
|
111
|
+
* @param {object} [context={}] - 上下文
|
|
169
112
|
* @returns {Promise<{response: string, suppress: boolean, reason?: string, results: Array}>}
|
|
170
113
|
*/
|
|
171
|
-
export async function fireAssistantResponse(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
context = {},
|
|
175
|
-
) {
|
|
176
|
-
const results = await fireSessionHook(hookDb, HookEvents.AssistantResponse, {
|
|
114
|
+
export async function fireAssistantResponse(db, response, context = {}) {
|
|
115
|
+
const results = await fireSessionHook(db, HookEvents.AssistantResponse, {
|
|
116
|
+
response,
|
|
177
117
|
...context,
|
|
178
|
-
response: originalResponse,
|
|
179
118
|
});
|
|
180
119
|
|
|
181
|
-
let
|
|
120
|
+
let rewrittenResponse = response;
|
|
182
121
|
let suppress = false;
|
|
183
|
-
let
|
|
122
|
+
let suppressReason;
|
|
184
123
|
|
|
185
|
-
for (const
|
|
186
|
-
if (!
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
response = directive.rewrittenResponse;
|
|
199
|
-
break;
|
|
124
|
+
for (const result of results) {
|
|
125
|
+
if (!result.success) continue;
|
|
126
|
+
try {
|
|
127
|
+
const output = result.stdout ? JSON.parse(result.stdout) : {};
|
|
128
|
+
if (output.rewrittenResponse) {
|
|
129
|
+
rewrittenResponse = output.rewrittenResponse;
|
|
130
|
+
}
|
|
131
|
+
if (output.suppress) {
|
|
132
|
+
suppress = true;
|
|
133
|
+
suppressReason = output.reason || "suppressed by hook";
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
// 忽略解析错误
|
|
200
137
|
}
|
|
201
138
|
}
|
|
202
139
|
|
|
203
|
-
return {
|
|
140
|
+
return {
|
|
141
|
+
response: rewrittenResponse,
|
|
142
|
+
suppress,
|
|
143
|
+
reason: suppressReason,
|
|
144
|
+
results,
|
|
145
|
+
};
|
|
204
146
|
}
|
|
205
147
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return JSON.parse(trimmed);
|
|
215
|
-
} catch {
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
148
|
+
/**
|
|
149
|
+
* 触发会话开始钩子
|
|
150
|
+
* @param {object} db - 数据库实例
|
|
151
|
+
* @param {object} [context={}] - 上下文
|
|
152
|
+
* @returns {Promise<Array>}
|
|
153
|
+
*/
|
|
154
|
+
export async function fireSessionStart(db, context = {}) {
|
|
155
|
+
return fireSessionHook(db, HookEvents.SessionStart, context);
|
|
218
156
|
}
|
|
219
157
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
158
|
+
/**
|
|
159
|
+
* 触发会话结束钩子
|
|
160
|
+
* @param {object} db - 数据库实例
|
|
161
|
+
* @param {object} [context={}] - 上下文
|
|
162
|
+
* @returns {Promise<Array>}
|
|
163
|
+
*/
|
|
164
|
+
export async function fireSessionEnd(db, context = {}) {
|
|
165
|
+
return fireSessionHook(db, HookEvents.SessionEnd, context);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Historical callers use "Stop" for the terminal lifecycle event; retain the
|
|
169
|
+
// alias while the canonical hook event remains SessionEnd.
|
|
170
|
+
export const fireSessionStop = fireSessionEnd;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 获取钩子数据库实例
|
|
174
|
+
* @returns {null} 暂未实现
|
|
175
|
+
*/
|
|
176
|
+
export function getHookDb() {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 触发设置钩子
|
|
182
|
+
* @param {object} db - 数据库实例
|
|
183
|
+
* @param {object} context - 上下文
|
|
184
|
+
* @returns {Promise<{abort: boolean}>}
|
|
185
|
+
*/
|
|
186
|
+
export async function fireSetup(db, context) {
|
|
187
|
+
return { abort: false };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Fire Notification hooks. Notifications are best-effort and may return a
|
|
191
|
+
* suppress/message directive without ever breaking the host session. */
|
|
192
|
+
export async function fireNotification(db, message, context = {}) {
|
|
193
|
+
const results = await fireSessionHook(db, HookEvents.Notification, {
|
|
194
|
+
message,
|
|
195
|
+
...context,
|
|
229
196
|
});
|
|
230
|
-
|
|
197
|
+
for (const result of results) {
|
|
198
|
+
if (!result?.success) continue;
|
|
199
|
+
const raw = result.stdout ?? result.output ?? result.result;
|
|
200
|
+
let directive = raw && typeof raw === "object" ? raw : null;
|
|
201
|
+
if (!directive && typeof raw === "string") {
|
|
202
|
+
try {
|
|
203
|
+
directive = JSON.parse(raw.trim());
|
|
204
|
+
} catch {
|
|
205
|
+
directive = null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (directive && typeof directive === "object") {
|
|
209
|
+
return { directive, results };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return { directive: null, results };
|
|
231
213
|
}
|
|
232
214
|
|
|
233
|
-
//
|
|
215
|
+
// Session Hooks V2 governance overlay. Kept in this module so the command and
|
|
216
|
+
// the library expose one stable surface to the CLI and its consumers.
|
|
234
217
|
export const SHOK_PROFILE_MATURITY_V2 = Object.freeze({
|
|
235
218
|
PENDING: "pending",
|
|
236
219
|
ACTIVE: "active",
|
|
@@ -244,209 +227,150 @@ export const SHOK_INVOCATION_LIFECYCLE_V2 = Object.freeze({
|
|
|
244
227
|
FAILED: "failed",
|
|
245
228
|
CANCELLED: "cancelled",
|
|
246
229
|
});
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
[
|
|
256
|
-
SHOK_PROFILE_MATURITY_V2.ACTIVE,
|
|
257
|
-
new Set([
|
|
258
|
-
SHOK_PROFILE_MATURITY_V2.DISABLED,
|
|
259
|
-
SHOK_PROFILE_MATURITY_V2.RETIRED,
|
|
260
|
-
]),
|
|
261
|
-
],
|
|
262
|
-
[
|
|
263
|
-
SHOK_PROFILE_MATURITY_V2.DISABLED,
|
|
264
|
-
new Set([
|
|
265
|
-
SHOK_PROFILE_MATURITY_V2.ACTIVE,
|
|
266
|
-
SHOK_PROFILE_MATURITY_V2.RETIRED,
|
|
267
|
-
]),
|
|
268
|
-
],
|
|
269
|
-
[SHOK_PROFILE_MATURITY_V2.RETIRED, new Set()],
|
|
270
|
-
]);
|
|
271
|
-
const _shokPTerminal = new Set([SHOK_PROFILE_MATURITY_V2.RETIRED]);
|
|
272
|
-
const _shokITrans = new Map([
|
|
273
|
-
[
|
|
274
|
-
SHOK_INVOCATION_LIFECYCLE_V2.QUEUED,
|
|
275
|
-
new Set([
|
|
276
|
-
SHOK_INVOCATION_LIFECYCLE_V2.RUNNING,
|
|
277
|
-
SHOK_INVOCATION_LIFECYCLE_V2.CANCELLED,
|
|
278
|
-
]),
|
|
279
|
-
],
|
|
280
|
-
[
|
|
281
|
-
SHOK_INVOCATION_LIFECYCLE_V2.RUNNING,
|
|
282
|
-
new Set([
|
|
283
|
-
SHOK_INVOCATION_LIFECYCLE_V2.COMPLETED,
|
|
284
|
-
SHOK_INVOCATION_LIFECYCLE_V2.FAILED,
|
|
285
|
-
SHOK_INVOCATION_LIFECYCLE_V2.CANCELLED,
|
|
286
|
-
]),
|
|
287
|
-
],
|
|
288
|
-
[SHOK_INVOCATION_LIFECYCLE_V2.COMPLETED, new Set()],
|
|
289
|
-
[SHOK_INVOCATION_LIFECYCLE_V2.FAILED, new Set()],
|
|
290
|
-
[SHOK_INVOCATION_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
291
|
-
]);
|
|
292
|
-
const _shokPsV2 = new Map();
|
|
293
|
-
const _shokIsV2 = new Map();
|
|
294
|
-
let _shokMaxActive = 12,
|
|
295
|
-
_shokMaxPending = 25,
|
|
296
|
-
_shokIdleMs = 30 * 24 * 60 * 60 * 1000,
|
|
297
|
-
_shokStuckMs = 30 * 1000;
|
|
298
|
-
function _shokPos(n, label) {
|
|
230
|
+
const _sp = new Map(),
|
|
231
|
+
_si = new Map();
|
|
232
|
+
let _maxActive = 12,
|
|
233
|
+
_maxPending = 25,
|
|
234
|
+
_idleMs = 30 * 24 * 60 * 60 * 1000,
|
|
235
|
+
_stuckMs = 30000;
|
|
236
|
+
const clone = (x) => ({ ...x, metadata: { ...(x.metadata || {}) } });
|
|
237
|
+
const pos = (n, name) => {
|
|
299
238
|
const v = Math.floor(Number(n));
|
|
300
239
|
if (!Number.isFinite(v) || v <= 0)
|
|
301
|
-
throw new Error(`${
|
|
240
|
+
throw new Error(`${name} must be positive integer`);
|
|
302
241
|
return v;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
if (!
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
if (!
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
export
|
|
336
|
-
|
|
337
|
-
}
|
|
242
|
+
};
|
|
243
|
+
const profile = (id) => {
|
|
244
|
+
const p = _sp.get(id);
|
|
245
|
+
if (!p) throw new Error(`shok profile ${id} not found`);
|
|
246
|
+
return p;
|
|
247
|
+
};
|
|
248
|
+
const invocation = (id) => {
|
|
249
|
+
const i = _si.get(id);
|
|
250
|
+
if (!i) throw new Error(`shok invocation ${id} not found`);
|
|
251
|
+
return i;
|
|
252
|
+
};
|
|
253
|
+
const transition = (map, from, to, label) => {
|
|
254
|
+
if (!map[from]?.includes(to))
|
|
255
|
+
throw new Error(`invalid ${label} transition ${from} → ${to}`);
|
|
256
|
+
};
|
|
257
|
+
const PT = {
|
|
258
|
+
pending: ["active", "retired"],
|
|
259
|
+
active: ["disabled", "retired"],
|
|
260
|
+
disabled: ["active", "retired"],
|
|
261
|
+
retired: [],
|
|
262
|
+
};
|
|
263
|
+
const IT = {
|
|
264
|
+
queued: ["running", "cancelled"],
|
|
265
|
+
running: ["completed", "failed", "cancelled"],
|
|
266
|
+
completed: [],
|
|
267
|
+
failed: [],
|
|
268
|
+
cancelled: [],
|
|
269
|
+
};
|
|
270
|
+
export const setMaxActiveShokProfilesPerOwnerV2 = (n) => {
|
|
271
|
+
_maxActive = pos(n, "maxActiveShokProfilesPerOwner");
|
|
272
|
+
};
|
|
273
|
+
export const getMaxActiveShokProfilesPerOwnerV2 = () => _maxActive;
|
|
274
|
+
export const setMaxPendingShokInvocationsPerProfileV2 = (n) => {
|
|
275
|
+
_maxPending = pos(n, "maxPendingShokInvocationsPerProfile");
|
|
276
|
+
};
|
|
277
|
+
export const getMaxPendingShokInvocationsPerProfileV2 = () => _maxPending;
|
|
278
|
+
export const setShokProfileIdleMsV2 = (n) => {
|
|
279
|
+
_idleMs = pos(n, "shokProfileIdleMs");
|
|
280
|
+
};
|
|
281
|
+
export const getShokProfileIdleMsV2 = () => _idleMs;
|
|
282
|
+
export const setShokInvocationStuckMsV2 = (n) => {
|
|
283
|
+
_stuckMs = pos(n, "shokInvocationStuckMs");
|
|
284
|
+
};
|
|
285
|
+
export const getShokInvocationStuckMsV2 = () => _stuckMs;
|
|
338
286
|
export function _resetStateSessionHooksV2() {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
346
|
-
export function registerShokProfileV2({
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
287
|
+
_sp.clear();
|
|
288
|
+
_si.clear();
|
|
289
|
+
_maxActive = 12;
|
|
290
|
+
_maxPending = 25;
|
|
291
|
+
_idleMs = 30 * 24 * 60 * 60 * 1000;
|
|
292
|
+
_stuckMs = 30000;
|
|
293
|
+
}
|
|
294
|
+
export function registerShokProfileV2({
|
|
295
|
+
id,
|
|
296
|
+
owner,
|
|
297
|
+
event = "preTurn",
|
|
298
|
+
metadata = {},
|
|
299
|
+
} = {}) {
|
|
300
|
+
if (!id || !owner) throw new Error("shok profile id and owner required");
|
|
301
|
+
if (_sp.has(id)) throw new Error(`shok profile ${id} already registered`);
|
|
351
302
|
const now = Date.now();
|
|
352
303
|
const p = {
|
|
353
304
|
id,
|
|
354
305
|
owner,
|
|
355
|
-
event
|
|
356
|
-
status:
|
|
306
|
+
event,
|
|
307
|
+
status: "pending",
|
|
357
308
|
createdAt: now,
|
|
358
309
|
updatedAt: now,
|
|
359
310
|
activatedAt: null,
|
|
360
311
|
retiredAt: null,
|
|
361
312
|
lastTouchedAt: now,
|
|
362
|
-
metadata: { ...
|
|
313
|
+
metadata: { ...metadata },
|
|
363
314
|
};
|
|
364
|
-
|
|
365
|
-
return
|
|
366
|
-
}
|
|
367
|
-
function _shokCountActive(owner) {
|
|
368
|
-
let n = 0;
|
|
369
|
-
for (const p of _shokPsV2.values())
|
|
370
|
-
if (p.owner === owner && p.status === SHOK_PROFILE_MATURITY_V2.ACTIVE) n++;
|
|
371
|
-
return n;
|
|
315
|
+
_sp.set(id, p);
|
|
316
|
+
return clone(p);
|
|
372
317
|
}
|
|
373
318
|
export function activateShokProfileV2(id) {
|
|
374
|
-
const p =
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
319
|
+
const p = profile(id);
|
|
320
|
+
transition(PT, p.status, "active", "shok profile");
|
|
321
|
+
const active = [..._sp.values()].filter(
|
|
322
|
+
(x) => x.owner === p.owner && x.status === "active",
|
|
323
|
+
).length;
|
|
324
|
+
if (p.status !== "disabled" && active >= _maxActive)
|
|
379
325
|
throw new Error(`max active shok profiles for owner ${p.owner} reached`);
|
|
380
326
|
const now = Date.now();
|
|
381
|
-
p.status =
|
|
327
|
+
p.status = "active";
|
|
382
328
|
p.updatedAt = now;
|
|
383
329
|
p.lastTouchedAt = now;
|
|
384
|
-
|
|
385
|
-
return
|
|
330
|
+
p.activatedAt ||= now;
|
|
331
|
+
return clone(p);
|
|
386
332
|
}
|
|
387
333
|
export function disableShokProfileV2(id) {
|
|
388
|
-
const p =
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
p.status = SHOK_PROFILE_MATURITY_V2.DISABLED;
|
|
334
|
+
const p = profile(id);
|
|
335
|
+
transition(PT, p.status, "disabled", "shok profile");
|
|
336
|
+
p.status = "disabled";
|
|
392
337
|
p.updatedAt = Date.now();
|
|
393
|
-
return
|
|
338
|
+
return clone(p);
|
|
394
339
|
}
|
|
395
340
|
export function retireShokProfileV2(id) {
|
|
396
|
-
const p =
|
|
397
|
-
|
|
398
|
-
_shokCheckP(p.status, SHOK_PROFILE_MATURITY_V2.RETIRED);
|
|
341
|
+
const p = profile(id);
|
|
342
|
+
transition(PT, p.status, "retired", "shok profile");
|
|
399
343
|
const now = Date.now();
|
|
400
|
-
p.status =
|
|
344
|
+
p.status = "retired";
|
|
401
345
|
p.updatedAt = now;
|
|
402
|
-
|
|
403
|
-
return
|
|
346
|
+
p.retiredAt ||= now;
|
|
347
|
+
return clone(p);
|
|
404
348
|
}
|
|
405
349
|
export function touchShokProfileV2(id) {
|
|
406
|
-
const p =
|
|
407
|
-
if (
|
|
408
|
-
if (_shokPTerminal.has(p.status))
|
|
350
|
+
const p = profile(id);
|
|
351
|
+
if (p.status === "retired")
|
|
409
352
|
throw new Error(`cannot touch terminal shok profile ${id}`);
|
|
410
|
-
|
|
411
|
-
p
|
|
412
|
-
p.updatedAt = now;
|
|
413
|
-
return { ...p, metadata: { ...p.metadata } };
|
|
414
|
-
}
|
|
415
|
-
export function getShokProfileV2(id) {
|
|
416
|
-
const p = _shokPsV2.get(id);
|
|
417
|
-
if (!p) return null;
|
|
418
|
-
return { ...p, metadata: { ...p.metadata } };
|
|
419
|
-
}
|
|
420
|
-
export function listShokProfilesV2() {
|
|
421
|
-
return [..._shokPsV2.values()].map((p) => ({
|
|
422
|
-
...p,
|
|
423
|
-
metadata: { ...p.metadata },
|
|
424
|
-
}));
|
|
425
|
-
}
|
|
426
|
-
function _shokCountPending(profileId) {
|
|
427
|
-
let n = 0;
|
|
428
|
-
for (const i of _shokIsV2.values())
|
|
429
|
-
if (
|
|
430
|
-
i.profileId === profileId &&
|
|
431
|
-
(i.status === SHOK_INVOCATION_LIFECYCLE_V2.QUEUED ||
|
|
432
|
-
i.status === SHOK_INVOCATION_LIFECYCLE_V2.RUNNING)
|
|
433
|
-
)
|
|
434
|
-
n++;
|
|
435
|
-
return n;
|
|
353
|
+
p.lastTouchedAt = p.updatedAt = Date.now();
|
|
354
|
+
return clone(p);
|
|
436
355
|
}
|
|
356
|
+
export const getShokProfileV2 = (id) =>
|
|
357
|
+
_sp.has(id) ? clone(_sp.get(id)) : null;
|
|
358
|
+
export const listShokProfilesV2 = () => [..._sp.values()].map(clone);
|
|
437
359
|
export function createShokInvocationV2({
|
|
438
360
|
id,
|
|
439
361
|
profileId,
|
|
440
|
-
payload,
|
|
441
|
-
metadata,
|
|
362
|
+
payload = "",
|
|
363
|
+
metadata = {},
|
|
442
364
|
} = {}) {
|
|
443
|
-
if (!id
|
|
444
|
-
|
|
445
|
-
if (
|
|
446
|
-
throw new Error(
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
365
|
+
if (!id || !profileId)
|
|
366
|
+
throw new Error("shok invocation id and profileId required");
|
|
367
|
+
if (_si.has(id) || !_sp.has(profileId))
|
|
368
|
+
throw new Error("invalid shok invocation");
|
|
369
|
+
const pending = [..._si.values()].filter(
|
|
370
|
+
(x) =>
|
|
371
|
+
x.profileId === profileId && ["queued", "running"].includes(x.status),
|
|
372
|
+
).length;
|
|
373
|
+
if (pending >= _maxPending)
|
|
450
374
|
throw new Error(
|
|
451
375
|
`max pending shok invocations for profile ${profileId} reached`,
|
|
452
376
|
);
|
|
@@ -454,159 +378,90 @@ export function createShokInvocationV2({
|
|
|
454
378
|
const i = {
|
|
455
379
|
id,
|
|
456
380
|
profileId,
|
|
457
|
-
payload
|
|
458
|
-
status:
|
|
381
|
+
payload,
|
|
382
|
+
status: "queued",
|
|
459
383
|
createdAt: now,
|
|
460
384
|
updatedAt: now,
|
|
461
385
|
startedAt: null,
|
|
462
386
|
settledAt: null,
|
|
463
|
-
metadata: { ...
|
|
387
|
+
metadata: { ...metadata },
|
|
464
388
|
};
|
|
465
|
-
|
|
466
|
-
return
|
|
467
|
-
}
|
|
468
|
-
export function runningShokInvocationV2(id) {
|
|
469
|
-
const i = _shokIsV2.get(id);
|
|
470
|
-
if (!i) throw new Error(`shok invocation ${id} not found`);
|
|
471
|
-
_shokCheckI(i.status, SHOK_INVOCATION_LIFECYCLE_V2.RUNNING);
|
|
472
|
-
const now = Date.now();
|
|
473
|
-
i.status = SHOK_INVOCATION_LIFECYCLE_V2.RUNNING;
|
|
474
|
-
i.updatedAt = now;
|
|
475
|
-
if (!i.startedAt) i.startedAt = now;
|
|
476
|
-
return { ...i, metadata: { ...i.metadata } };
|
|
477
|
-
}
|
|
478
|
-
export function completeShokInvocationV2(id) {
|
|
479
|
-
const i = _shokIsV2.get(id);
|
|
480
|
-
if (!i) throw new Error(`shok invocation ${id} not found`);
|
|
481
|
-
_shokCheckI(i.status, SHOK_INVOCATION_LIFECYCLE_V2.COMPLETED);
|
|
482
|
-
const now = Date.now();
|
|
483
|
-
i.status = SHOK_INVOCATION_LIFECYCLE_V2.COMPLETED;
|
|
484
|
-
i.updatedAt = now;
|
|
485
|
-
if (!i.settledAt) i.settledAt = now;
|
|
486
|
-
return { ...i, metadata: { ...i.metadata } };
|
|
487
|
-
}
|
|
488
|
-
export function failShokInvocationV2(id, reason) {
|
|
489
|
-
const i = _shokIsV2.get(id);
|
|
490
|
-
if (!i) throw new Error(`shok invocation ${id} not found`);
|
|
491
|
-
_shokCheckI(i.status, SHOK_INVOCATION_LIFECYCLE_V2.FAILED);
|
|
492
|
-
const now = Date.now();
|
|
493
|
-
i.status = SHOK_INVOCATION_LIFECYCLE_V2.FAILED;
|
|
494
|
-
i.updatedAt = now;
|
|
495
|
-
if (!i.settledAt) i.settledAt = now;
|
|
496
|
-
if (reason) i.metadata.failReason = String(reason);
|
|
497
|
-
return { ...i, metadata: { ...i.metadata } };
|
|
389
|
+
_si.set(id, i);
|
|
390
|
+
return clone(i);
|
|
498
391
|
}
|
|
499
|
-
|
|
500
|
-
const i =
|
|
501
|
-
|
|
502
|
-
_shokCheckI(i.status, SHOK_INVOCATION_LIFECYCLE_V2.CANCELLED);
|
|
392
|
+
function setInvocation(id, to, extra = {}) {
|
|
393
|
+
const i = invocation(id);
|
|
394
|
+
transition(IT, i.status, to, "shok invocation");
|
|
503
395
|
const now = Date.now();
|
|
504
|
-
i
|
|
505
|
-
i.
|
|
506
|
-
if (
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
export
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
396
|
+
Object.assign(i, extra, { status: to, updatedAt: now });
|
|
397
|
+
if (to === "running") i.startedAt ||= now;
|
|
398
|
+
if (["completed", "failed", "cancelled"].includes(to)) i.settledAt ||= now;
|
|
399
|
+
return clone(i);
|
|
400
|
+
}
|
|
401
|
+
export const runningShokInvocationV2 = (id) => setInvocation(id, "running");
|
|
402
|
+
export const completeShokInvocationV2 = (id) => setInvocation(id, "completed");
|
|
403
|
+
export const failShokInvocationV2 = (id, reason) =>
|
|
404
|
+
setInvocation(
|
|
405
|
+
id,
|
|
406
|
+
"failed",
|
|
407
|
+
reason
|
|
408
|
+
? { metadata: { ...invocation(id).metadata, failReason: String(reason) } }
|
|
409
|
+
: {},
|
|
410
|
+
);
|
|
411
|
+
export const cancelShokInvocationV2 = (id, reason) =>
|
|
412
|
+
setInvocation(
|
|
413
|
+
id,
|
|
414
|
+
"cancelled",
|
|
415
|
+
reason
|
|
416
|
+
? {
|
|
417
|
+
metadata: {
|
|
418
|
+
...invocation(id).metadata,
|
|
419
|
+
cancelReason: String(reason),
|
|
420
|
+
},
|
|
421
|
+
}
|
|
422
|
+
: {},
|
|
423
|
+
);
|
|
424
|
+
export const getShokInvocationV2 = (id) =>
|
|
425
|
+
_si.has(id) ? clone(_si.get(id)) : null;
|
|
426
|
+
export const listShokInvocationsV2 = () => [..._si.values()].map(clone);
|
|
427
|
+
export function autoDisableIdleShokProfilesV2({ now = Date.now() } = {}) {
|
|
523
428
|
const flipped = [];
|
|
524
|
-
for (const p of
|
|
525
|
-
if (
|
|
526
|
-
p.status
|
|
527
|
-
|
|
528
|
-
) {
|
|
529
|
-
p.status = SHOK_PROFILE_MATURITY_V2.DISABLED;
|
|
530
|
-
p.updatedAt = t;
|
|
429
|
+
for (const p of _sp.values())
|
|
430
|
+
if (p.status === "active" && now - p.lastTouchedAt >= _idleMs) {
|
|
431
|
+
p.status = "disabled";
|
|
432
|
+
p.updatedAt = now;
|
|
531
433
|
flipped.push(p.id);
|
|
532
434
|
}
|
|
533
435
|
return { flipped, count: flipped.length };
|
|
534
436
|
}
|
|
535
|
-
export function autoFailStuckShokInvocationsV2({ now } = {}) {
|
|
536
|
-
const t = now ?? Date.now();
|
|
437
|
+
export function autoFailStuckShokInvocationsV2({ now = Date.now() } = {}) {
|
|
537
438
|
const flipped = [];
|
|
538
|
-
for (const i of
|
|
539
|
-
if (
|
|
540
|
-
i.status
|
|
541
|
-
i.
|
|
542
|
-
t - i.startedAt >= _shokStuckMs
|
|
543
|
-
) {
|
|
544
|
-
i.status = SHOK_INVOCATION_LIFECYCLE_V2.FAILED;
|
|
545
|
-
i.updatedAt = t;
|
|
546
|
-
if (!i.settledAt) i.settledAt = t;
|
|
439
|
+
for (const i of _si.values())
|
|
440
|
+
if (i.status === "running" && now - i.startedAt >= _stuckMs) {
|
|
441
|
+
i.status = "failed";
|
|
442
|
+
i.updatedAt = i.settledAt = now;
|
|
547
443
|
i.metadata.failReason = "auto-fail-stuck";
|
|
548
444
|
flipped.push(i.id);
|
|
549
445
|
}
|
|
550
446
|
return { flipped, count: flipped.length };
|
|
551
447
|
}
|
|
552
448
|
export function getSessionHooksGovStatsV2() {
|
|
553
|
-
const profilesByStatus =
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
for (const i of
|
|
449
|
+
const profilesByStatus = Object.fromEntries(
|
|
450
|
+
Object.values(SHOK_PROFILE_MATURITY_V2).map((x) => [x, 0]),
|
|
451
|
+
);
|
|
452
|
+
const invocationsByStatus = Object.fromEntries(
|
|
453
|
+
Object.values(SHOK_INVOCATION_LIFECYCLE_V2).map((x) => [x, 0]),
|
|
454
|
+
);
|
|
455
|
+
for (const p of _sp.values()) profilesByStatus[p.status]++;
|
|
456
|
+
for (const i of _si.values()) invocationsByStatus[i.status]++;
|
|
561
457
|
return {
|
|
562
|
-
totalShokProfilesV2:
|
|
563
|
-
totalShokInvocationsV2:
|
|
564
|
-
maxActiveShokProfilesPerOwner:
|
|
565
|
-
maxPendingShokInvocationsPerProfile:
|
|
566
|
-
shokProfileIdleMs:
|
|
567
|
-
shokInvocationStuckMs:
|
|
458
|
+
totalShokProfilesV2: _sp.size,
|
|
459
|
+
totalShokInvocationsV2: _si.size,
|
|
460
|
+
maxActiveShokProfilesPerOwner: _maxActive,
|
|
461
|
+
maxPendingShokInvocationsPerProfile: _maxPending,
|
|
462
|
+
shokProfileIdleMs: _idleMs,
|
|
463
|
+
shokInvocationStuckMs: _stuckMs,
|
|
568
464
|
profilesByStatus,
|
|
569
465
|
invocationsByStatus,
|
|
570
466
|
};
|
|
571
467
|
}
|
|
572
|
-
|
|
573
|
-
/**
|
|
574
|
-
* Fire settings.json Stop hooks (observe-only) — fires at the END of EVERY
|
|
575
|
-
* agent turn/loop iteration, BEFORE waiting for the next user input.
|
|
576
|
-
* Aligns with Claude Code hook spec.
|
|
577
|
-
*
|
|
578
|
-
* Fires regardless of outcome: normal completion, error, max iterations,
|
|
579
|
-
* user interrupt, or tool stop. Does NOT fire on final process exit
|
|
580
|
-
* (use SessionEnd/Shutdown hooks for that case).
|
|
581
|
-
*
|
|
582
|
-
* @param {Object} opts
|
|
583
|
-
* @param {string} opts.sessionId - Current session ID
|
|
584
|
-
* @param {string} opts.transcriptPath - Path to transcript file
|
|
585
|
-
* @param {string} [opts.stopReason="end_turn"] - Reason the turn stopped:
|
|
586
|
-
* "end_turn", "error", "max_iterations", "user_interrupt", "tool_stop"
|
|
587
|
-
* @param {string} [opts.finalResponse=""] - Final assistant response text
|
|
588
|
-
* @param {number} [opts.toolCount=0] - Number of tool calls made this turn
|
|
589
|
-
* @param {number} [opts.durationMs=0] - Turn duration in milliseconds
|
|
590
|
-
* @param {Error|string} [opts.error] - Error object if stopReason is "error"
|
|
591
|
-
* @returns {Promise<Array>} Hook execution results
|
|
592
|
-
*/
|
|
593
|
-
export async function fireSessionStop({
|
|
594
|
-
sessionId,
|
|
595
|
-
transcriptPath,
|
|
596
|
-
stopReason = "end_turn",
|
|
597
|
-
finalResponse = "",
|
|
598
|
-
toolCount = 0,
|
|
599
|
-
durationMs = 0,
|
|
600
|
-
error = null,
|
|
601
|
-
}) {
|
|
602
|
-
return runSettingsHooks("Stop", {
|
|
603
|
-
session_id: sessionId,
|
|
604
|
-
transcript_path: transcriptPath,
|
|
605
|
-
stop_reason: stopReason,
|
|
606
|
-
final_response: finalResponse,
|
|
607
|
-
tool_count: toolCount,
|
|
608
|
-
duration_ms: durationMs,
|
|
609
|
-
error: error ? String(error.message ?? error) : "",
|
|
610
|
-
timestamp: new Date().toISOString(),
|
|
611
|
-
});
|
|
612
|
-
}
|