chainlesschain 0.162.162 → 0.162.164
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 +3 -1
- package/src/assets/web-panel/assets/{AIOps-ClI2ALgv.js → AIOps-BqRkaHGb.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BDjRcJaK.js → ActionButton-DWO7OZLC.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DikSRsaT.js → Analytics-C5oaVezM.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-9mLhMFmz.js → AppLayout-CsUESDoZ.js} +3 -3
- package/src/assets/web-panel/assets/{Artifacts-BSr88BrH.js → Artifacts-Dragqu5k.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CdvyimOF.js → Audit-CQsaHctY.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D3_hCedh.js → BackgroundAgents-DdG1jNSM.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cyvv9RHf.js → Backup-DN6sjK4z.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BZM14kt8.js → BaseInput-Cxm_ZTCl.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DrQSokVz.js → Chat-DVXGmA56.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-HwJR-C6B.js → ChatBubbleRenderer-BdaCL_iE.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-bFLYeWMV.js → Checkbox-DEc4vD_A.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-7mN7xJXT.js → Codegen-CKiTcv36.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DAB5ZWm7.js → Col-Br9UUNN0.js} +1 -1
- package/src/assets/web-panel/assets/{Community-B_1TymaK.js → Community-NeUH_70T.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Bq1uSWLJ.js → Compact-BqR-z2Df.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CyiE1jEe.js → Compliance-DcWB_SgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Cpk0D7vm.js → Cowork-BfhgcudF.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-d_Lv3rdB.js → Cron-LaU29LgD.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DMqhHjMR.js → Crosschain-B2ZB9uwW.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Br-oPuBw.js → DID-BuHl38A2.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CfLW_RaP.js → Dashboard-m627yqvZ.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DZnTOExV.js → Dropdown-C7bxF8F5.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DHIUHDv1.js → EmailListRenderer-DPLPQzLp.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Bw3t3myu.js → FamilyGuardDashboard-cOiH6ike.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D9cpQPAY.js → Federation-Bvkzg88z.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Jdczr9Mr.js → FormItemContext-BTsiA7h_.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BT8ZMpC5.js → GenericCardRenderer-BGnVE5qu.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DjARip2b.js → Git-DS_j6r25.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BgWbSRcj.js → Governance-CKRG3Rsl.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CfouJciM.js → Inference-DW8INoNQ.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-50l7mrAr.js → KnowledgeGraph-BhEYeFhC.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-rq50H84B.js → Logs-wqi0uxuR.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DUPIEdQH.js → MarkdownRenderer-DS8dE8ty.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BYgPDmHU.js → Marketplace-CMlTuPLT.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-5DVgcFdx.js → McpTools-CSx4m5JJ.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-B70LPk7f.js → Memory-vnQCUy-_.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-De8ssA5Y.js → MobileBridge-BV2NA742.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-Bw0k8e1B.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-RJsOTsIA.js → Mtc-CzK_FPB1.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Crh-6BEK.js → MtcAudit-Cb7G9oL3.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-wuoR5l3x.js → Multisig-qJxlUyzr.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-U2Mji4fZ.js → NLProgramming-DqaBJ7Te.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CdTZAyDH.js → Notes-CwhTJkRi.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C-FucWE7.js → NotificationSettings-YDs4Fal4.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DCYFTeaI.js → OrderTableRenderer-CvEALpq7.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-an3OF85L.js → Organization-CEmQm9n8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-C-1vmYFe.js → Overflow-zby_P_LA.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Cwh47xKg.js → P2P-DsmDNFNT.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Dm38GT0k.js → PdhVaultBrowser-FWwFlZGF.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DS2Y8awD.js → Permissions-DuzQ6me5.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BQNziA0I.js → PersonalDataHub-DZbeN613.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DF85L1ue.js → Pipeline-CoNSVAUS.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BuLornF-.js → Privacy-OYJEAaMC.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-C3Y31IwX.js → ProjectInit-CWIapV--.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BCPiI8aD.js → ProjectSettings-CX8xMxZn.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BZ6s4k6g.js → Projects-BLCN8YyY.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D3Wp022X.js → Providers-BV_sxp75.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CUJfQkH4.js → QrScannerModal-BTnRrHRp.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-UAc0EO8l.js → QuickAsk-D1KZg018.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BaxKupcs.js → Recommend-COm5cuNg.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C75NNnXZ.js → RemoteSession-0saWEkYI.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BVXynZAk.js → Reputation-Dr7iKLS2.js} +1 -1
- package/src/assets/web-panel/assets/{Row-C5MRZ0bi.js → Row-C1vpPBcr.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DAKkEYka.js → RssFeed-CxlWrtNj.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DvWv9YOA.js → Search-BT2V8dPN.js} +1 -1
- package/src/assets/web-panel/assets/{Security-B5peafW1.js → Security-bm9V3c5k.js} +4 -4
- package/src/assets/web-panel/assets/{Services-UQmvPEaG.js → Services-CocH1yyX.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C3bhWpuF.js → Skeleton-DHItlMdd.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DfkKf9_H.js → Skills-C59sLc4w.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DqMSjlBM.js → Sla-Crj4BMc8.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C-WbxWUX.js → SpeechSettings-DX4KFceY.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CYuHZ4N2.js → SyncSettings-BD_iwQLr.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CyeAyB9d.js → Tasks-BmCTzYsH.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BTCeQnpq.js → Templates-BGUaxZYl.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BifQuA9Y.js → Tenant-BS0tJx2O.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Bx_9Bocf.js → Terminal--tHSAsld.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BX0RFCOm.js → TimelineRenderer-D9-MFxS4.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CGHrCmUS.js → Tokens-CiCB485f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DlqaY4SO.js → Trigger-SmCFuW_l.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DfOmj-ay.js → Trust-DkK3Rqe0.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B72jH5fE.js → UkeySign-CDM4LGdB.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BT-63fqv.js → VideoEditing-IDB7DJXt.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Dsul3sHr.js → Wallet-Bikj5cmt.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Izkwwdgy.js → WebAuthn-C9abWlAw.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-D3FHSiH1.js → WorkflowEditor-DrbRKVky.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CmVz5z3U.js → chat-CccCSDQf.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CuLgyJBp.js → colors-CXObXLhb.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Ml1YkXpw.js → compact-item-B5kfYAxC.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BvjJ48bs.js → createContext-DmiPBfip.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CvKrADNa.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DVC0157C.js → hasIn-Q6lYteAc.js} +1 -1
- package/src/assets/web-panel/assets/{index-C229ABfy.js → index-25Wlqps4.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ck_52dz_.js → index-33U29UNV.js} +1 -1
- package/src/assets/web-panel/assets/{index-QXzlT9KD.js → index-4oXBDczR.js} +1 -1
- package/src/assets/web-panel/assets/{index-4SBta3d7.js → index-BGYXvMc5.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0S8NzO6.js → index-BJCCa0s_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJyN28Et.js → index-BJJ5DhKI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DC_OI9H2.js → index-BLOzViJ6.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_XuRgGn.js → index-BRrbUMoG.js} +1 -1
- package/src/assets/web-panel/assets/{index-wvb_FtaV.js → index-BUFpT17Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-KMqhcF7l.js → index-BkRDiqGc.js} +1 -1
- package/src/assets/web-panel/assets/{index-vG4XSJ1d.js → index-BsfvW6my.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYXHFr4r.js → index-By-kfPED.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuGszaWY.js → index-BzFTcQsc.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXkJH-lK.js → index-C2FXdboq.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dt5KMjwJ.js → index-C5XOlTHN.js} +1 -1
- package/src/assets/web-panel/assets/{index-4wcgvPoF.js → index-CLhBDS2w.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_H_S-DY.js → index-CMq7UeoT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BydjdZnl.js → index-CVMTWNKl.js} +1 -1
- package/src/assets/web-panel/assets/{index-BjHBpRYZ.js → index-Caghi-yL.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bzr0rB5T.js → index-CdB6FuSH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbPtzB8M.js → index-CoK8-kWQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUt8kTIB.js → index-CsO3GUAY.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_vRgTl9.js → index-CwZBa20Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DukDVXCv.js → index-D-kASucw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbepULSc.js → index-D8eBw7vW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfuKP4qe.js → index-D9wgifk4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiC6dQZG.js → index-DAYCTc07.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmFNvNLZ.js → index-DF6Q8l2h.js} +1 -1
- package/src/assets/web-panel/assets/index-DTdFUWc_.js +1 -0
- package/src/assets/web-panel/assets/{index-KjgKdZe-.js → index-DgTLApS9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BpFJHiTv.js → index-DgxVJ8pg.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cw0Rjy87.js → index-DlJvIqoR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFYVQMvu.js → index-Dw4eHfsG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CudmwNBV.js → index-Rh-ytwow.js} +3 -3
- package/src/assets/web-panel/assets/{index-DDGaOWBV.js → index-StAEt2pq.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3lD5qap.js → index-bzfw951k.js} +1 -1
- package/src/assets/web-panel/assets/{index-BzG-x9p4.js → index-fSUMbMvv.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_EvG_GW.js → index-tFHy5Wol.js} +1 -1
- package/src/assets/web-panel/assets/index-zQ0M_kz-.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-BDgd2YZ8.js → initDefaultProps-BNq7X72N.js} +1 -1
- package/src/assets/web-panel/assets/{motion-ErtrXdYe.js → motion-DOf9viTc.js} +1 -1
- package/src/assets/web-panel/assets/{move-_GPPNCgs.js → move-CRHTcW4x.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DRLL-8V2.js → mtc-parser-Cyoozgm2.js} +1 -1
- package/src/assets/web-panel/assets/{omit-p86sl023.js → omit-6-TjFNru.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BTu7cMLH.js → pickAttrs-DlUmO1zi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BEKz6Isr.js → placementArrow-CFOL8mIR.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Ck42c9MP.js → responsiveObserve-BtaFK5zd.js} +1 -1
- package/src/assets/web-panel/assets/{slide-1CEvuPsB.js → slide-BIbc2bur.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BDfdx1GJ.js → statusUtils-BXX9d6-w.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B4K46m5w.js → styleChecker-BGv10Bpn.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DoIVpJNq.js → useFlexGapSupport-bKnKT8tw.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DdAWi-ln.js → useFs-FY4IL4jn.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-iUu6k8dx.js → usePersonalDataHub-Bwl9TEgu.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DZz4R6Tw.js → vnode-BM3OHxAT.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DXlf9sA3.js → zoom-D1fbFiHB.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +320 -32
- package/src/commands/agent.js +105 -11
- package/src/commands/context.js +125 -14
- package/src/commands/doctor.js +85 -1
- package/src/commands/hook.js +181 -7
- package/src/commands/plugin.js +456 -1
- package/src/commands/review.js +363 -2
- package/src/commands/session.js +191 -0
- package/src/commands/team.js +19 -1
- package/src/data/changelog.json +10 -4
- package/src/gateways/ws/remote-session-protocol.js +39 -0
- package/src/gateways/ws/session-protocol.js +55 -2
- package/src/gateways/ws/ws-agent-handler.js +50 -0
- package/src/harness/jsonl-session-store.js +60 -0
- package/src/harness/worktree-isolator.js +140 -5
- package/src/lib/agent-schedule-store.js +318 -10
- package/src/lib/agent-team/team-worktree.js +37 -2
- package/src/lib/agent-tool-admission.js +125 -0
- package/src/lib/app-preview.js +360 -0
- package/src/lib/async-hook-supervisor.cjs +54 -0
- package/src/lib/capability-manifest.js +319 -0
- package/src/lib/capability-negotiation.js +23 -12
- package/src/lib/channels/channel-manager.js +54 -2
- package/src/lib/cli-context-engineering.js +9 -2
- package/src/lib/context-breakdown.js +116 -0
- package/src/lib/diagnostic-bundle.js +230 -0
- package/src/lib/doctor-checkup.js +275 -4
- package/src/lib/execution-location.js +286 -0
- package/src/lib/headless-manifest.js +13 -40
- package/src/lib/hook-event-log.cjs +193 -0
- package/src/lib/hook-stats-store.cjs +197 -0
- package/src/lib/idempotency.js +109 -0
- package/src/lib/interaction-adapter.js +34 -4
- package/src/lib/json-schema-output.js +46 -12
- package/src/lib/json-schema-validate.js +143 -3
- package/src/lib/jsonl-session-store.js +1 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +58 -0
- package/src/lib/lsp/lsp-manager.js +56 -0
- package/src/lib/monitor-event.js +290 -0
- package/src/lib/operation-fingerprint.js +217 -0
- package/src/lib/plugin-runtime/bin.js +37 -0
- package/src/lib/plugin-runtime/capabilities.js +19 -0
- package/src/lib/plugin-runtime/capability-consent.js +203 -0
- package/src/lib/plugin-runtime/hooks.js +37 -0
- package/src/lib/plugin-runtime/lsp.js +38 -0
- package/src/lib/plugin-runtime/mcp.js +40 -0
- package/src/lib/plugin-runtime/monitors.js +37 -0
- package/src/lib/plugin-runtime/plugin-options.js +151 -0
- package/src/lib/plugin-runtime/policy.js +62 -0
- package/src/lib/plugin-runtime/scopes.js +20 -4
- package/src/lib/pr-automation-policy.js +224 -0
- package/src/lib/project-instructions.js +128 -0
- package/src/lib/remote-approval-bridge.js +66 -13
- package/src/lib/repl-goal.js +132 -0
- package/src/lib/repl-rewind.js +153 -0
- package/src/lib/review-comment-anchor.js +241 -0
- package/src/lib/review-pipeline.js +46 -7
- package/src/lib/runtime-checkup.js +221 -0
- package/src/lib/schedule-planner.js +17 -1
- package/src/lib/secret-scan.js +409 -0
- package/src/lib/session-branch.js +0 -0
- package/src/lib/settings-hook-events.cjs +13 -0
- package/src/lib/settings-loader.cjs +42 -0
- package/src/lib/side-effect-ledger-store.js +88 -0
- package/src/lib/side-effect-ledger.js +401 -0
- package/src/lib/skill-loader.js +32 -0
- package/src/lib/skill-path-scope.js +63 -0
- package/src/lib/sub-agent-context.js +110 -9
- package/src/lib/sub-agent-registry.js +19 -0
- package/src/lib/subagent-inheritance.js +112 -0
- package/src/lib/telemetry/span-recorder.js +17 -4
- package/src/lib/terminal-context.js +195 -0
- package/src/lib/turn-binding-store.js +119 -0
- package/src/lib/unattended-action-policy.js +182 -0
- package/src/lib/worktree-cleanup-safety.js +138 -0
- package/src/lib/worktree-isolator.js +8 -0
- package/src/lib/worktree-sparse.js +131 -0
- package/src/repl/agent-repl.js +280 -30
- package/src/repl/permission-tier.js +28 -0
- package/src/runtime/agent-core.js +565 -21
- package/src/runtime/coding-agent-contract-shared.cjs +60 -1
- package/src/runtime/diagnostics.js +60 -0
- package/src/runtime/headless-runner.js +393 -1
- package/src/runtime/headless-stream.js +60 -1
- package/src/assets/web-panel/assets/MobileProjects-D10VISps.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DhiGrbsh.js +0 -1
- package/src/assets/web-panel/assets/index-B7a1TrU6.js +0 -1
- package/src/assets/web-panel/assets/index-C2B1KRja.js +0 -1
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical capability manifest — the single source the CLI capability output,
|
|
3
|
+
* the VS Code / JetBrains negotiation, the protocol docs, the compatibility
|
|
4
|
+
* fixture, the behavior matrix and the release-notes capability diff all project
|
|
5
|
+
* from (P1-9 "Capability Manifest 与脱敏诊断包" of
|
|
6
|
+
* CLAUDE_CODE_IDE_INCREMENTAL_GAP_ANALYSIS_2026-07-13.md).
|
|
7
|
+
*
|
|
8
|
+
* Today the wire-protocol capability surface is hand-authored in THREE places
|
|
9
|
+
* that can silently drift:
|
|
10
|
+
* - [[capability-negotiation.js]]: `PROTOCOL_FEATURES`, `FEATURE_MIN_VERSION`,
|
|
11
|
+
* and the private `FEATURE_TO_FIELD` map.
|
|
12
|
+
* - [[headless-manifest.js]]: `buildAgentCapabilities().features` (the
|
|
13
|
+
* `cc agent --capabilities` output).
|
|
14
|
+
* - the Java twin + the shared negotiation fixture.
|
|
15
|
+
* A new v2 field added to one list but not the others parses wrong on the peer
|
|
16
|
+
* that missed it. This module is the ONE definition; every other shape is a pure
|
|
17
|
+
* projection of it, and a drift-guard test asserts the live hand-authored
|
|
18
|
+
* constants still equal the projection (see capability-manifest.test.js).
|
|
19
|
+
*
|
|
20
|
+
* Pure: no fs / process / clock. Projections are deterministic so a caller can
|
|
21
|
+
* regenerate docs/fixtures and diff them against the checked-in copies in CI.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { createHash } from "node:crypto";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* THE canonical manifest. `wireFeatures` is the negotiable additive per-line
|
|
28
|
+
* field set (order mirrors capability-negotiation.js `PROTOCOL_FEATURES`);
|
|
29
|
+
* `runtimeFeatures` are the boolean capability flags that change what the CLI
|
|
30
|
+
* can DO (not the shape of a line the client must parse) and are NOT negotiated.
|
|
31
|
+
*/
|
|
32
|
+
export const CAPABILITY_MANIFEST = Object.freeze({
|
|
33
|
+
name: "chainlesschain-cli",
|
|
34
|
+
protocolVersion: 1,
|
|
35
|
+
minProtocolVersion: 1,
|
|
36
|
+
|
|
37
|
+
wireFeatures: Object.freeze([
|
|
38
|
+
Object.freeze({
|
|
39
|
+
key: "event_seq",
|
|
40
|
+
field: "seq",
|
|
41
|
+
minVersion: 1,
|
|
42
|
+
description:
|
|
43
|
+
"every stream-json stdout line carries a monotonic per-run `seq`",
|
|
44
|
+
}),
|
|
45
|
+
Object.freeze({
|
|
46
|
+
key: "tool_use_id",
|
|
47
|
+
field: "tool_use_id",
|
|
48
|
+
minVersion: 1,
|
|
49
|
+
description:
|
|
50
|
+
'tool_use / tool_result lines carry a pairing `id` ("tu-<n>")',
|
|
51
|
+
}),
|
|
52
|
+
Object.freeze({
|
|
53
|
+
key: "trace_id",
|
|
54
|
+
field: "trace_id",
|
|
55
|
+
minVersion: 1,
|
|
56
|
+
description:
|
|
57
|
+
"each line carries a run-scoped, caller-injectable `trace_id` for IDE ↔ CLI correlation",
|
|
58
|
+
}),
|
|
59
|
+
]),
|
|
60
|
+
|
|
61
|
+
// Boolean capability flags (buildAgentCapabilities().features truthy keys).
|
|
62
|
+
runtimeFeatures: Object.freeze([
|
|
63
|
+
"bare",
|
|
64
|
+
"safe_mode",
|
|
65
|
+
"ephemeral",
|
|
66
|
+
"background",
|
|
67
|
+
"worktree",
|
|
68
|
+
"checkpoint",
|
|
69
|
+
"json_schema_output",
|
|
70
|
+
"partial_messages",
|
|
71
|
+
"interactive_approvals",
|
|
72
|
+
"permission_prompt_tool",
|
|
73
|
+
"remote_control",
|
|
74
|
+
]),
|
|
75
|
+
|
|
76
|
+
mcpFeatures: Object.freeze([
|
|
77
|
+
"config_file",
|
|
78
|
+
"registry",
|
|
79
|
+
"tool_search",
|
|
80
|
+
"oauth",
|
|
81
|
+
"managed_allowlist",
|
|
82
|
+
]),
|
|
83
|
+
sandboxEngines: Object.freeze(["docker", "bubblewrap"]),
|
|
84
|
+
|
|
85
|
+
permissionModes: Object.freeze([
|
|
86
|
+
"default",
|
|
87
|
+
"manual",
|
|
88
|
+
"auto",
|
|
89
|
+
"dontAsk",
|
|
90
|
+
"plan",
|
|
91
|
+
"acceptEdits",
|
|
92
|
+
"bypassPermissions",
|
|
93
|
+
]),
|
|
94
|
+
outputFormats: Object.freeze(["text", "json", "stream-json"]),
|
|
95
|
+
inputFormats: Object.freeze(["text", "stream-json"]),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const manifestOr = (m) =>
|
|
99
|
+
m && typeof m === "object" ? m : CAPABILITY_MANIFEST;
|
|
100
|
+
const wireFeaturesOf = (m) =>
|
|
101
|
+
Array.isArray(manifestOr(m).wireFeatures) ? manifestOr(m).wireFeatures : [];
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The negotiable wire feature keys, in canonical declared order — the value
|
|
105
|
+
* capability-negotiation.js `PROTOCOL_FEATURES` must equal.
|
|
106
|
+
* @returns {string[]}
|
|
107
|
+
*/
|
|
108
|
+
export function toProtocolFeatures(m = CAPABILITY_MANIFEST) {
|
|
109
|
+
return wireFeaturesOf(m).map((f) => f.key);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Feature → minimum protocol version, ONLY for features gated above the base
|
|
114
|
+
* version (a v1-additive field is absent, matching an empty
|
|
115
|
+
* `FEATURE_MIN_VERSION` today). Adding a v2 feature here flows the gate to the
|
|
116
|
+
* negotiator automatically.
|
|
117
|
+
* @returns {Record<string, number>}
|
|
118
|
+
*/
|
|
119
|
+
export function toFeatureMinVersion(m = CAPABILITY_MANIFEST) {
|
|
120
|
+
const out = {};
|
|
121
|
+
for (const f of wireFeaturesOf(m)) {
|
|
122
|
+
if (Number(f.minVersion) > 1) out[f.key] = Number(f.minVersion);
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Feature → the stream line field it gates (the value of the private
|
|
129
|
+
* `FEATURE_TO_FIELD` map in capability-negotiation.js).
|
|
130
|
+
* @returns {Record<string, string>}
|
|
131
|
+
*/
|
|
132
|
+
export function toFieldGate(m = CAPABILITY_MANIFEST) {
|
|
133
|
+
const out = {};
|
|
134
|
+
for (const f of wireFeaturesOf(m)) out[f.key] = f.field;
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The server negotiation offer shape consumed by
|
|
140
|
+
* capability-negotiation.js `negotiateProtocol(server, …)`.
|
|
141
|
+
* @returns {{protocolVersion:number, minProtocolVersion:number, features:string[]}}
|
|
142
|
+
*/
|
|
143
|
+
export function toServerOffer(m = CAPABILITY_MANIFEST) {
|
|
144
|
+
const mm = manifestOr(m);
|
|
145
|
+
return {
|
|
146
|
+
protocolVersion: Number(mm.protocolVersion) || 1,
|
|
147
|
+
minProtocolVersion: Number(mm.minProtocolVersion) || 1,
|
|
148
|
+
features: toProtocolFeatures(mm),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The `features` object of `cc agent --capabilities`
|
|
154
|
+
* (buildAgentCapabilities().features): every runtime flag true, every wire
|
|
155
|
+
* feature true, plus the nested `mcp` object and `sandbox_engines` list. A test
|
|
156
|
+
* asserts the live buildAgentCapabilities().features deep-equals this.
|
|
157
|
+
* @returns {object}
|
|
158
|
+
*/
|
|
159
|
+
export function toAgentFeatureFlags(m = CAPABILITY_MANIFEST) {
|
|
160
|
+
const mm = manifestOr(m);
|
|
161
|
+
const flags = {};
|
|
162
|
+
for (const key of mm.runtimeFeatures || []) flags[key] = true;
|
|
163
|
+
for (const f of wireFeaturesOf(mm)) flags[f.key] = true;
|
|
164
|
+
flags.mcp = {};
|
|
165
|
+
for (const key of mm.mcpFeatures || []) flags.mcp[key] = true;
|
|
166
|
+
flags.sandbox_engines = [...(mm.sandboxEngines || [])];
|
|
167
|
+
return flags;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* A deterministic capability fixture the VS Code / JetBrains twins can pin and
|
|
172
|
+
* assert against (the "Compatibility Fixture" the gap doc asks for). Order- and
|
|
173
|
+
* clock-independent; a `digest` lets a peer detect any change in one compare.
|
|
174
|
+
* @returns {object}
|
|
175
|
+
*/
|
|
176
|
+
export function buildCompatFixture(m = CAPABILITY_MANIFEST) {
|
|
177
|
+
const mm = manifestOr(m);
|
|
178
|
+
const body = {
|
|
179
|
+
protocolVersion: Number(mm.protocolVersion) || 1,
|
|
180
|
+
minProtocolVersion: Number(mm.minProtocolVersion) || 1,
|
|
181
|
+
features: toProtocolFeatures(mm),
|
|
182
|
+
featureFields: toFieldGate(mm),
|
|
183
|
+
featureMinVersion: toFeatureMinVersion(mm),
|
|
184
|
+
permissionModes: [...(mm.permissionModes || [])],
|
|
185
|
+
outputFormats: [...(mm.outputFormats || [])],
|
|
186
|
+
inputFormats: [...(mm.inputFormats || [])],
|
|
187
|
+
};
|
|
188
|
+
return { ...body, digest: capabilityDigest(mm) };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* A stable digest of the whole capability surface (no RNG/clock) — one string
|
|
193
|
+
* that changes iff any projected capability changed. Handy as a CI drift check.
|
|
194
|
+
* @returns {string} 16-hex-char sha256 prefix
|
|
195
|
+
*/
|
|
196
|
+
export function capabilityDigest(m = CAPABILITY_MANIFEST) {
|
|
197
|
+
const mm = manifestOr(m);
|
|
198
|
+
const canonical = {
|
|
199
|
+
protocolVersion: Number(mm.protocolVersion) || 1,
|
|
200
|
+
minProtocolVersion: Number(mm.minProtocolVersion) || 1,
|
|
201
|
+
wire: wireFeaturesOf(mm)
|
|
202
|
+
.map((f) => [f.key, f.field, Number(f.minVersion) || 1])
|
|
203
|
+
.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)),
|
|
204
|
+
runtime: [...(mm.runtimeFeatures || [])].sort(),
|
|
205
|
+
mcp: [...(mm.mcpFeatures || [])].sort(),
|
|
206
|
+
sandbox: [...(mm.sandboxEngines || [])].sort(),
|
|
207
|
+
permissionModes: [...(mm.permissionModes || [])].sort(),
|
|
208
|
+
outputFormats: [...(mm.outputFormats || [])].sort(),
|
|
209
|
+
inputFormats: [...(mm.inputFormats || [])].sort(),
|
|
210
|
+
};
|
|
211
|
+
return createHash("sha256")
|
|
212
|
+
.update(JSON.stringify(canonical))
|
|
213
|
+
.digest("hex")
|
|
214
|
+
.slice(0, 16);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* A behavior matrix row per wire feature — feature × min version × gated field ×
|
|
219
|
+
* negotiable × description. Consumed by renderProtocolDoc and by a test that a
|
|
220
|
+
* doc table matches the code.
|
|
221
|
+
* @returns {Array<{feature:string, minVersion:number, field:string, negotiable:boolean, description:string}>}
|
|
222
|
+
*/
|
|
223
|
+
export function renderBehaviorMatrix(m = CAPABILITY_MANIFEST) {
|
|
224
|
+
return wireFeaturesOf(m).map((f) => ({
|
|
225
|
+
feature: f.key,
|
|
226
|
+
minVersion: Number(f.minVersion) || 1,
|
|
227
|
+
field: f.field,
|
|
228
|
+
negotiable: true,
|
|
229
|
+
description: String(f.description || ""),
|
|
230
|
+
}));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Render the protocol capability section as Markdown (a generated doc a CI job
|
|
235
|
+
* diffs against the checked-in copy). Deterministic; ends with a trailing
|
|
236
|
+
* newline so a byte compare is stable.
|
|
237
|
+
* @returns {string}
|
|
238
|
+
*/
|
|
239
|
+
export function renderProtocolDoc(m = CAPABILITY_MANIFEST) {
|
|
240
|
+
const mm = manifestOr(m);
|
|
241
|
+
const lines = [];
|
|
242
|
+
lines.push("# Agent Protocol Capability Manifest (generated)");
|
|
243
|
+
lines.push("");
|
|
244
|
+
lines.push(
|
|
245
|
+
`Protocol version **${mm.protocolVersion}** (negotiates down to **${mm.minProtocolVersion}**).`,
|
|
246
|
+
);
|
|
247
|
+
lines.push("");
|
|
248
|
+
lines.push("## Negotiable wire features");
|
|
249
|
+
lines.push("");
|
|
250
|
+
lines.push("| Feature | Min version | Line field | Description |");
|
|
251
|
+
lines.push("| ------- | ----------- | ---------- | ----------- |");
|
|
252
|
+
for (const row of renderBehaviorMatrix(mm)) {
|
|
253
|
+
lines.push(
|
|
254
|
+
`| \`${row.feature}\` | ${row.minVersion} | \`${row.field}\` | ${row.description} |`,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
lines.push("");
|
|
258
|
+
lines.push("## Permission modes");
|
|
259
|
+
lines.push("");
|
|
260
|
+
lines.push((mm.permissionModes || []).map((x) => `\`${x}\``).join(", "));
|
|
261
|
+
lines.push("");
|
|
262
|
+
return lines.join("\n") + "\n";
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Capability diff for release notes: what changed between a previous and a next
|
|
267
|
+
* manifest (or a manifest and the current canonical one). Additive vs removed vs
|
|
268
|
+
* min-version/field changes, plus any protocol-version bump.
|
|
269
|
+
*
|
|
270
|
+
* @param {object} prev a manifest (or its compat fixture)
|
|
271
|
+
* @param {object} [next=CAPABILITY_MANIFEST]
|
|
272
|
+
* @returns {{protocolChange:{from:number,to:number}|null,
|
|
273
|
+
* addedWireFeatures:string[], removedWireFeatures:string[],
|
|
274
|
+
* changedWireFeatures:Array<{feature:string, from:object, to:object}>,
|
|
275
|
+
* addedRuntimeFeatures:string[], removedRuntimeFeatures:string[]}}
|
|
276
|
+
*/
|
|
277
|
+
export function diffCapabilities(prev, next = CAPABILITY_MANIFEST) {
|
|
278
|
+
const wireMap = (m) => {
|
|
279
|
+
const out = new Map();
|
|
280
|
+
for (const f of wireFeaturesOf(m)) {
|
|
281
|
+
out.set(f.key, {
|
|
282
|
+
field: f.field,
|
|
283
|
+
minVersion: Number(f.minVersion) || 1,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
return out;
|
|
287
|
+
};
|
|
288
|
+
const runtimeSet = (m) => new Set(manifestOr(m).runtimeFeatures || []);
|
|
289
|
+
|
|
290
|
+
const p = wireMap(prev);
|
|
291
|
+
const n = wireMap(next);
|
|
292
|
+
const addedWireFeatures = [...n.keys()].filter((k) => !p.has(k)).sort();
|
|
293
|
+
const removedWireFeatures = [...p.keys()].filter((k) => !n.has(k)).sort();
|
|
294
|
+
const changedWireFeatures = [];
|
|
295
|
+
for (const [key, nv] of n) {
|
|
296
|
+
const pv = p.get(key);
|
|
297
|
+
if (pv && (pv.field !== nv.field || pv.minVersion !== nv.minVersion)) {
|
|
298
|
+
changedWireFeatures.push({ feature: key, from: pv, to: nv });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const pr = runtimeSet(prev);
|
|
303
|
+
const nr = runtimeSet(next);
|
|
304
|
+
const addedRuntimeFeatures = [...nr].filter((k) => !pr.has(k)).sort();
|
|
305
|
+
const removedRuntimeFeatures = [...pr].filter((k) => !nr.has(k)).sort();
|
|
306
|
+
|
|
307
|
+
const pVer = Number(manifestOr(prev).protocolVersion) || 1;
|
|
308
|
+
const nVer = Number(manifestOr(next).protocolVersion) || 1;
|
|
309
|
+
const protocolChange = pVer === nVer ? null : { from: pVer, to: nVer };
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
protocolChange,
|
|
313
|
+
addedWireFeatures,
|
|
314
|
+
removedWireFeatures,
|
|
315
|
+
changedWireFeatures,
|
|
316
|
+
addedRuntimeFeatures,
|
|
317
|
+
removedRuntimeFeatures,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
@@ -36,31 +36,42 @@
|
|
|
36
36
|
* fixture __tests__/fixtures/capability-negotiation-cases.json.
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
|
+
import {
|
|
40
|
+
CAPABILITY_MANIFEST,
|
|
41
|
+
toProtocolFeatures,
|
|
42
|
+
toFeatureMinVersion,
|
|
43
|
+
toFieldGate,
|
|
44
|
+
} from "./capability-manifest.js";
|
|
45
|
+
|
|
39
46
|
/** The current protocol version the CLI speaks (mirror of PROTOCOL_VERSION). */
|
|
40
|
-
export const PROTOCOL_VERSION =
|
|
47
|
+
export const PROTOCOL_VERSION = CAPABILITY_MANIFEST.protocolVersion;
|
|
41
48
|
|
|
42
49
|
/**
|
|
43
50
|
* The oldest protocol version the CLI can still speak end-to-end (the N-1 in
|
|
44
51
|
* "N / N-1"). At v1 there is no older line shape, so min === current; once v2
|
|
45
52
|
* ships this drops to 1 so a v1-only client negotiates a v1 session.
|
|
46
53
|
*/
|
|
47
|
-
export const PROTOCOL_MIN_VERSION =
|
|
54
|
+
export const PROTOCOL_MIN_VERSION = CAPABILITY_MANIFEST.minProtocolVersion;
|
|
48
55
|
|
|
49
56
|
/**
|
|
50
57
|
* The wire-protocol features subject to negotiation — the additive per-line
|
|
51
58
|
* fields a client may or may not understand. Runtime capabilities (bare,
|
|
52
59
|
* worktree, mcp, …) are NOT negotiated: they change what the CLI can do, not
|
|
53
60
|
* the shape of a line the client must parse.
|
|
61
|
+
*
|
|
62
|
+
* P1-9: projected from the single canonical [[capability-manifest.js]] so the
|
|
63
|
+
* negotiator, `cc agent --capabilities`, the protocol docs and the Java twin can
|
|
64
|
+
* no longer drift — add a v2 field to the manifest ONCE and it flows here.
|
|
54
65
|
*/
|
|
55
|
-
export const PROTOCOL_FEATURES =
|
|
66
|
+
export const PROTOCOL_FEATURES = toProtocolFeatures();
|
|
56
67
|
|
|
57
68
|
/**
|
|
58
69
|
* Minimum protocol version a feature requires. Empty today (every current
|
|
59
|
-
* feature is a v1 additive field). When a v2 field lands,
|
|
60
|
-
* N-1 (v1) session drops it automatically.
|
|
70
|
+
* feature is a v1 additive field). When a v2 field lands, bump its manifest
|
|
71
|
+
* `minVersion` and an N-1 (v1) session drops it automatically.
|
|
61
72
|
* @type {Record<string, number>}
|
|
62
73
|
*/
|
|
63
|
-
export const FEATURE_MIN_VERSION =
|
|
74
|
+
export const FEATURE_MIN_VERSION = toFeatureMinVersion();
|
|
64
75
|
|
|
65
76
|
function intOr(value, fallback) {
|
|
66
77
|
const n = Number(value);
|
|
@@ -185,12 +196,12 @@ export function negotiateProtocol(server = {}, clientOffer = null, opts = {}) {
|
|
|
185
196
|
};
|
|
186
197
|
}
|
|
187
198
|
|
|
188
|
-
/**
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
199
|
+
/**
|
|
200
|
+
* Feature key → the stream line field it gates. P1-9: projected from the
|
|
201
|
+
* canonical [[capability-manifest.js]] so this map can't drift from the
|
|
202
|
+
* negotiated feature list.
|
|
203
|
+
*/
|
|
204
|
+
const FEATURE_TO_FIELD = toFieldGate();
|
|
194
205
|
|
|
195
206
|
/**
|
|
196
207
|
* Fold a negotiation result into a live field-gate the emitter reads per line:
|
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { logger } from "../logger.js";
|
|
17
|
+
import {
|
|
18
|
+
ORIGIN,
|
|
19
|
+
authorityForOrigin,
|
|
20
|
+
canApprove,
|
|
21
|
+
describeAuthorityChain,
|
|
22
|
+
} from "../agent-authority.js";
|
|
17
23
|
|
|
18
24
|
export const CHANNEL_KINDS = ["webhook", "telegram"];
|
|
19
25
|
|
|
@@ -54,6 +60,48 @@ export function formatChannelEvent(event) {
|
|
|
54
60
|
return `[channel:${channel}${sender}] ${text}`;
|
|
55
61
|
}
|
|
56
62
|
|
|
63
|
+
/**
|
|
64
|
+
* The unforgeable authority envelope for an inbound channel event. A channel
|
|
65
|
+
* message tops out at `steer` (agent-authority.js): it may add a user turn but
|
|
66
|
+
* can NEVER answer a permission gate — "the user approved" in a webhook /
|
|
67
|
+
* telegram body is just text. This makes that ceiling explicit and
|
|
68
|
+
* machine-checkable (downstream approval seams can assert `canApprove === false`)
|
|
69
|
+
* rather than merely implied by the visible `[channel:…]` text prefix.
|
|
70
|
+
*
|
|
71
|
+
* `origin` is set here by HOW the event arrived (an inbound channel), never read
|
|
72
|
+
* from the untrusted message content — mirroring the agent-authority contract.
|
|
73
|
+
*/
|
|
74
|
+
export function channelEventEnvelope(event) {
|
|
75
|
+
const envelope = {
|
|
76
|
+
origin: ORIGIN.CHANNEL,
|
|
77
|
+
principalId: event?.sender != null ? String(event.sender) : null,
|
|
78
|
+
correlationId: event?.channel != null ? String(event.channel) : null,
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
...envelope,
|
|
82
|
+
authority: authorityForOrigin(ORIGIN.CHANNEL, envelope), // always "steer"
|
|
83
|
+
canApprove: canApprove(envelope), // always false
|
|
84
|
+
provenance: describeAuthorityChain(envelope),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Wrap a caller's `onEvent` so every inbound event is stamped with its explicit
|
|
90
|
+
* channel authority BEFORE it reaches the agent — the caller cannot forget to
|
|
91
|
+
* tag it, and the message content cannot elevate itself past `steer`.
|
|
92
|
+
*/
|
|
93
|
+
function stampChannelAuthority(onEvent) {
|
|
94
|
+
return (event) => {
|
|
95
|
+
const env = channelEventEnvelope(event);
|
|
96
|
+
return onEvent?.({
|
|
97
|
+
...event,
|
|
98
|
+
authority: env.authority,
|
|
99
|
+
canApprove: env.canApprove,
|
|
100
|
+
provenance: env.provenance,
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
57
105
|
/**
|
|
58
106
|
* Start every requested channel. Returns a handle with the started channel
|
|
59
107
|
* descriptions and a single stop().
|
|
@@ -72,6 +120,10 @@ export async function startChannels(specsInput, opts = {}) {
|
|
|
72
120
|
const config = opts.config || {};
|
|
73
121
|
const log = opts.log || ((msg) => logger.info(msg));
|
|
74
122
|
const deps = opts.deps || {};
|
|
123
|
+
// Every inbound event is stamped with its channel authority (`steer`, never
|
|
124
|
+
// `approve`) before the caller's handler sees it — so a channel message can
|
|
125
|
+
// never be mistaken for a user approval no matter what it contains.
|
|
126
|
+
const onEvent = stampChannelAuthority(opts.onEvent);
|
|
75
127
|
|
|
76
128
|
const started = [];
|
|
77
129
|
const stopAll = () => {
|
|
@@ -95,7 +147,7 @@ export async function startChannels(specsInput, opts = {}) {
|
|
|
95
147
|
)({
|
|
96
148
|
...cfg,
|
|
97
149
|
port: spec.arg ? Number(spec.arg) : cfg.port,
|
|
98
|
-
onEvent
|
|
150
|
+
onEvent,
|
|
99
151
|
log,
|
|
100
152
|
});
|
|
101
153
|
started.push({ kind: "webhook", describe: handle.describe, ...handle });
|
|
@@ -107,7 +159,7 @@ export async function startChannels(specsInput, opts = {}) {
|
|
|
107
159
|
deps.telegram?.startTelegramChannel || startTelegramChannel
|
|
108
160
|
)({
|
|
109
161
|
...cfg,
|
|
110
|
-
onEvent
|
|
162
|
+
onEvent,
|
|
111
163
|
log,
|
|
112
164
|
});
|
|
113
165
|
started.push({
|
|
@@ -46,11 +46,17 @@ export class CLIContextEngineering {
|
|
|
46
46
|
* @param {string} [options.scope.taskId] - Task/sub-agent ID
|
|
47
47
|
* @param {string} [options.scope.role] - Sub-agent role
|
|
48
48
|
* @param {string} [options.scope.parentObjective] - Parent task objective
|
|
49
|
+
* @param {boolean} [options.memoryEnabled=true] - When false, hierarchical
|
|
50
|
+
* memory recall is suppressed even if a `db` is present. The subagent
|
|
51
|
+
* contract's `memory` boolean drives this for spawned children so a child
|
|
52
|
+
* denied memory physically cannot recall it (defense-in-depth beyond the
|
|
53
|
+
* spawn simply withholding the db).
|
|
49
54
|
*/
|
|
50
|
-
constructor({ db, permanentMemory, scope } = {}) {
|
|
55
|
+
constructor({ db, permanentMemory, scope, memoryEnabled = true } = {}) {
|
|
51
56
|
this.db = db || null;
|
|
52
57
|
this.permanentMemory = permanentMemory || null;
|
|
53
58
|
this.scope = scope || null;
|
|
59
|
+
this.memoryEnabled = memoryEnabled !== false;
|
|
54
60
|
this.errorHistory = [];
|
|
55
61
|
this.taskContext = null;
|
|
56
62
|
this._bm25 = null;
|
|
@@ -121,7 +127,8 @@ export class CLIContextEngineering {
|
|
|
121
127
|
}
|
|
122
128
|
|
|
123
129
|
// 3. Memory injection (scoped: higher threshold, namespace-aware)
|
|
124
|
-
|
|
130
|
+
// Suppressed when memoryEnabled is false (subagent contract memory:false).
|
|
131
|
+
if (this.memoryEnabled && this.db && userQuery) {
|
|
125
132
|
try {
|
|
126
133
|
const memoryQuery = this.scope
|
|
127
134
|
? `[${this.scope.role}] ${userQuery}`
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-source token attribution for `cc context --sources` — the P1
|
|
3
|
+
* large-monorepo "/context 按来源分解" lever. The base `cc context` view buckets
|
|
4
|
+
* a session's stored messages by ROLE; this adds a BY-SOURCE view that also
|
|
5
|
+
* attributes the project-memory instruction files (cc.md / CLAUDE.md / rules /
|
|
6
|
+
* @imports) that would be loaded for the current working directory, each with
|
|
7
|
+
* its own token cost and provenance — so a user can see WHICH instruction file
|
|
8
|
+
* (or message class) fills the context window.
|
|
9
|
+
*
|
|
10
|
+
* Pure: token counting for instruction files is delegated to the injected
|
|
11
|
+
* estimator (the same CJK-aware `estimateTokens` the window sizing uses);
|
|
12
|
+
* message-role buckets already arrive pre-counted. No I/O.
|
|
13
|
+
*
|
|
14
|
+
* Scope note: skills and MCP tool schemas are runtime tool definitions loaded
|
|
15
|
+
* when an agent actually runs — they are NOT part of a persisted transcript nor
|
|
16
|
+
* of the project-instruction set, so they are intentionally not attributed here.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import path from "path";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Display path for an instruction source: relative-to-cwd when the file lives
|
|
23
|
+
* inside cwd, else the absolute path (a `~/.claude/…` user-scope file, or an
|
|
24
|
+
* @import that escaped the tree, is clearer shown in full).
|
|
25
|
+
*/
|
|
26
|
+
export function relativizeInstructionPath(absPath, cwd) {
|
|
27
|
+
if (!absPath) return "";
|
|
28
|
+
if (!cwd) return absPath;
|
|
29
|
+
try {
|
|
30
|
+
const rel = path.relative(cwd, absPath);
|
|
31
|
+
if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) return absPath;
|
|
32
|
+
return rel.split(path.sep).join("/");
|
|
33
|
+
} catch {
|
|
34
|
+
return absPath;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Per-file instruction sources from `loadProjectInstructions().files`.
|
|
40
|
+
*
|
|
41
|
+
* @param {Array<{path,scope,content,truncated}>} files
|
|
42
|
+
* @param {(t:string)=>number} estimateTokens
|
|
43
|
+
* @param {string} [cwd]
|
|
44
|
+
* @returns {{ sources: Array<{scope,source,path,tokens,truncated}>, total:number }}
|
|
45
|
+
*/
|
|
46
|
+
export function breakdownInstructionSources(files, estimateTokens, cwd) {
|
|
47
|
+
const est = typeof estimateTokens === "function" ? estimateTokens : () => 0;
|
|
48
|
+
const list = Array.isArray(files) ? files : [];
|
|
49
|
+
const sources = list.map((f) => ({
|
|
50
|
+
scope: f?.scope || "project",
|
|
51
|
+
source: relativizeInstructionPath(f?.path, cwd),
|
|
52
|
+
path: f?.path || "",
|
|
53
|
+
tokens: est(typeof f?.content === "string" ? f.content : ""),
|
|
54
|
+
truncated: Boolean(f?.truncated),
|
|
55
|
+
}));
|
|
56
|
+
const total = sources.reduce((s, x) => s + x.tokens, 0);
|
|
57
|
+
return { sources, total };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// role bucket key → { label, kind } for the ranked source list.
|
|
61
|
+
const MESSAGE_SOURCE_ROWS = [
|
|
62
|
+
["system", "system messages", "message"],
|
|
63
|
+
["user", "user messages", "message"],
|
|
64
|
+
["assistant", "assistant messages", "message"],
|
|
65
|
+
["tool", "tool results", "message"],
|
|
66
|
+
["toolCalls", "tool calls", "tool_calls"],
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Merge the project-memory instruction total with the per-role message buckets
|
|
71
|
+
* into ONE ranked source list (largest first) with each source's share of the
|
|
72
|
+
* combined by-source total. The message buckets are the same ones
|
|
73
|
+
* `categorizeContext` produces; instructions are folded in as a single group so
|
|
74
|
+
* the ranked view stays readable (per-file detail lives in the instructions
|
|
75
|
+
* breakdown).
|
|
76
|
+
*
|
|
77
|
+
* @param {object} args
|
|
78
|
+
* @param {number} [args.instructionTotal=0] Σ instruction-file tokens
|
|
79
|
+
* @param {object} [args.buckets={}] categorizeContext buckets
|
|
80
|
+
* @param {object} [args.counts={}] categorizeContext counts
|
|
81
|
+
* @returns {{ sources: Array<{kind,source,tokens,count,share}>, total:number }}
|
|
82
|
+
*/
|
|
83
|
+
export function rankContextSources({
|
|
84
|
+
instructionTotal = 0,
|
|
85
|
+
buckets = {},
|
|
86
|
+
counts = {},
|
|
87
|
+
} = {}) {
|
|
88
|
+
const rows = [];
|
|
89
|
+
if (instructionTotal > 0) {
|
|
90
|
+
rows.push({
|
|
91
|
+
kind: "instructions",
|
|
92
|
+
source: "project memory (instructions)",
|
|
93
|
+
tokens: instructionTotal,
|
|
94
|
+
count: null,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
for (const [key, label, kind] of MESSAGE_SOURCE_ROWS) {
|
|
98
|
+
const tok = buckets[key] || 0;
|
|
99
|
+
if (tok > 0) {
|
|
100
|
+
rows.push({
|
|
101
|
+
kind,
|
|
102
|
+
source: label,
|
|
103
|
+
tokens: tok,
|
|
104
|
+
count: counts[key] ?? null,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const total = rows.reduce((s, x) => s + x.tokens, 0);
|
|
109
|
+
// Stable sort: tokens desc, then source name for deterministic ties.
|
|
110
|
+
rows.sort((a, b) => b.tokens - a.tokens || a.source.localeCompare(b.source));
|
|
111
|
+
const sources = rows.map((r) => ({
|
|
112
|
+
...r,
|
|
113
|
+
share: total ? r.tokens / total : 0,
|
|
114
|
+
}));
|
|
115
|
+
return { sources, total };
|
|
116
|
+
}
|