chainlesschain 0.162.149 → 0.162.151
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/README.md +1 -1
- package/package.json +3 -2
- package/src/assets/web-panel/assets/{AIOps-BJif14yR.js → AIOps-DuEOzebi.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CXek6gJY.js → ActionButton-C6GiJa5H.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BgQhdAJi.js → Analytics-BBIiL_pO.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DTYl5NtR.js → AppLayout-CuI2gZRy.js} +3 -3
- package/src/assets/web-panel/assets/{Audit-BzATQAeR.js → Audit-CbUjfr-K.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BzdPEQhL.js → Backup-CsSW9ljf.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BM0KVh8E.js → BaseInput-kM3rLe7F.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-D7fHXHkz.js → Chat-kfE51YN3.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Wm34RR-b.js → ChatBubbleRenderer-Bg2FTW6A.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-CAiSQ9vO.js → Checkbox-jYb1uj-M.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Df40CrEe.js → Codegen-X9XiD5Lj.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DIT2fNFU.js → Col-BfbHu1xI.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CSTIbW2k.js → Community-c4oJMFS-.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DtqXZZUi.js → Compact-BFmnZpH7.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CUtzw6o7.js → Compliance-s9shVHBS.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CezmlnmU.js → Cowork-C5da--TC.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-P4BITarg.js → Cron-9kNbyNE4.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BRRiYwvq.js → Crosschain-C1k3NJD4.js} +1 -1
- package/src/assets/web-panel/assets/{DID-L5ijB9i4.js → DID-DkheEvNK.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CFxro4ob.js → Dashboard-C3FuSGmJ.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BmAFCQ71.js → Dropdown-CAV6FMFD.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DJBCEuon.js → EmailListRenderer-Cc-Ulc4l.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-z4oLq6eT.js → FamilyGuardDashboard-8CitHEtv.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DsVCpHMF.js → Federation-DFSZ5KDt.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DP3bP5th.js → FormItemContext-CEWCtnG2.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BAXP2Gc6.js → GenericCardRenderer-CwRzNzmX.js} +1 -1
- package/src/assets/web-panel/assets/{Git-I3g_bAw9.js → Git-0rgDM7cJ.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-jHS5-ioS.js → Governance-CfBKtK9F.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CPL7sfx9.js → Inference-CzcUVvud.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Jf236h4C.js → KnowledgeGraph-Dwc4YL4A.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Cm2tcSKg.js → Logs-DgFPwR2F.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-CZK82rhi.js → Marketplace-DnpPTbGU.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CZCeji7a.js → McpTools-DRxxINyW.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-3l2KVS9k.js → Memory-OhmW_6Z3.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-VYdpoLh6.js → MobileBridge-DkTW-RK5.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CiB9cmm1.js → MobileProjects-DpCGV_lI.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-wCFZbBuL.js → Mtc--vmkL0AS.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-1a3THIyG.js → MtcAudit-DGoFWjD4.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-DMzLB2hG.js → Multisig-B4kWgq95.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D9wZbf6l.js → NLProgramming-YQwvommE.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-hrFe2ZM-.js → Notes-CgjtUADJ.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CHGX5Jwm.js → NotificationSettings-6JDrpBG5.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-PM6IlxjO.js +1 -0
- package/src/assets/web-panel/assets/{Organization-By7FkhtY.js → Organization-8McOT_OF.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow--khGSzJn.js → Overflow-DAZpSCGc.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CAG9dH35.js → P2P-B7l2ZWLy.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-B3SQZmK9.js → PdhVaultBrowser-W1Ud-NAL.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-D35ec6JA.js → Permissions-Czm_w9u_.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CxBF7hW_.js → PersonalDataHub-B4F0_ZVM.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-s6EtOO1s.js → Pipeline-B37aFiWv.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BbJYmWmO.js → Privacy-94KBnRrD.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-VGQq1jMT.js → ProjectInit-B5h8_dlh.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B1ew3Teh.js → ProjectSettings-lmeI3Lpm.js} +2 -2
- package/src/assets/web-panel/assets/Projects-D5AYOasl.js +1 -0
- package/src/assets/web-panel/assets/{Providers-mrO47FIK.js → Providers-B3cNWwJg.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-IJF2mHyw.js → QrScannerModal-CHRvOw1R.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CU0wN_Z0.js → QuickAsk-D1JMgFEd.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DhN37R6G.js → Recommend-EYWGR79p.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-D_xOX_hu.js → RemoteSession-BAMC2pJt.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D_Ssv7uH.js → Reputation-X2Hk1XG_.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Kx5dKxX7.js → Row-Eq98LRtU.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BlGwqZkY.js → RssFeed-i76s6z_o.js} +2 -2
- package/src/assets/web-panel/assets/{Search-hLFQzxpb.js → Search-D_Es7CAI.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DMlvsVt4.js → Security-kayD2e94.js} +3 -3
- package/src/assets/web-panel/assets/{Services-Bd0Qsj2m.js → Services-Ctsm6ul8.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DFclq9X3.js → Skeleton-CRNYlfdf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BNtln2qY.js → Skills-DkZYpF4-.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Dch5H19G.js → Sla-DXkoBcOP.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-2UfQcU1g.js → SpeechSettings-DXi_GI1d.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CD9YQr4i.js → SyncSettings-rNKpfomn.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BNu-7MzI.js → Tasks-XF4uPtG-.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D1n9CaIR.js → Templates-i0Hzfeyu.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DenL3iBW.js → Tenant-sMpHAi27.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-BoZvaYAl.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-D87IfukO.js → TimelineRenderer-yuC6K7Rf.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BkiZc8E3.js → Tokens-B8O8i0s6.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BNRSytGN.js → Trigger-Bv6yrlCr.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Bwbd4X2m.js → Trust-C4mW95Ev.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B8O2bs0o.js → UkeySign-DV6yKaHn.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C2fL8zmH.js → VideoEditing-UI479-sD.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BORYDdE1.js → Wallet-M5oV9EVP.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-C0V5S2FM.js → WebAuthn-DDyDHPDR.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-2dR0fcHL.js → WorkflowEditor-RoBv4rqk.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BmuAFAn8.js → chat-Cw1mE5LS.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CN3smMcK.js → colors-BFP62Gwf.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DCnxb4kW.js → compact-item-17HL6pyC.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-vlR43pHn.js → createContext-D55X4fZX.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CqbHYuRc.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D04tHYFd.js → hasIn-D3E5mNsP.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbVsQBOH.js → index--44J50mc.js} +1 -1
- package/src/assets/web-panel/assets/{index-TslMTwNy.js → index-ASPYTzMK.js} +1 -1
- package/src/assets/web-panel/assets/{index-CTOCnIQ7.js → index-BC6zxOlU.js} +1 -1
- package/src/assets/web-panel/assets/{index-ljuBiQW9.js → index-BEa1RW4c.js} +1 -1
- package/src/assets/web-panel/assets/{index-jzR7Ujuw.js → index-BQmZg5si.js} +1 -1
- package/src/assets/web-panel/assets/{index-BudvKQfG.js → index-BY_xZ2jy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CP9m9Ggr.js → index-BgN5G5vF.js} +3 -3
- package/src/assets/web-panel/assets/{index-Cr-A0FYJ.js → index-BnGpft-Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5LZVZ0L.js → index-Bq83UBDr.js} +1 -1
- package/src/assets/web-panel/assets/{index-ToUh2b1-.js → index-Bzpp2z2S.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbADHwhr.js → index-CFYGn88j.js} +1 -1
- package/src/assets/web-panel/assets/{index-ClhAHDK3.js → index-CGyTos4p.js} +1 -1
- package/src/assets/web-panel/assets/index-CKBI1U5K.js +1 -0
- package/src/assets/web-panel/assets/{index-C-6NO5il.js → index-CLEzsZ8A.js} +1 -1
- package/src/assets/web-panel/assets/{index-D8vwp4qp.js → index-CR9rNUvi.js} +1 -1
- package/src/assets/web-panel/assets/{index-_FIkN3jd.js → index-CW6LLoJO.js} +1 -1
- package/src/assets/web-panel/assets/{index-D65_XseV.js → index-C_MfcrLf.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnXebZLL.js → index-Cdvk2_2q.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_n8_vfI.js → index-CjCwi7we.js} +1 -1
- package/src/assets/web-panel/assets/index-CkLp6DTO.js +1 -0
- package/src/assets/web-panel/assets/{index-DDwLgQY9.js → index-CvCFKojj.js} +1 -1
- package/src/assets/web-panel/assets/{index-430S68MN.js → index-D4LHSde4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXRg8GFQ.js → index-DCLu84x-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTtRscUa.js → index-DD_qGBrt.js} +1 -1
- package/src/assets/web-panel/assets/{index-BasvsWDM.js → index-DIRvdwBX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BeGDEXFs.js → index-DOjA8bvj.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsAsCPJ6.js → index-Da27u6j0.js} +1 -1
- package/src/assets/web-panel/assets/{index-D28DeAAB.js → index-DkBVYlE4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CngCC8hC.js → index-DtAnPBWP.js} +1 -1
- package/src/assets/web-panel/assets/{index-B78xL3s2.js → index-DzG7mkgW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIpY0qM5.js → index-H9_X1Cg_.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5Sxb1sE.js → index-ITeEHb8L.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTPEZTk1.js → index-KtLJXn4s.js} +1 -1
- package/src/assets/web-panel/assets/{index-hpvvtAZ3.js → index-RYZgFIwo.js} +1 -1
- package/src/assets/web-panel/assets/{index-HhNjnCfe.js → index-gAVxDiTZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTWg-18U.js → index-paVubXzn.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqhASEL4.js → index-tUH_6bdJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYAtmqiv.js → index-tVRPgYGr.js} +1 -1
- package/src/assets/web-panel/assets/{index-0DnaZGkC.js → index-uSsiwgZ2.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C3wUb4je.js → initDefaultProps-Ckp7xVZS.js} +1 -1
- package/src/assets/web-panel/assets/{motion-D-jYFUNA.js → motion-DUZgCpn6.js} +1 -1
- package/src/assets/web-panel/assets/{move-tqb8nwJ2.js → move-B2rttglH.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DSOjMJMz.js → mtc-parser-BYWcLTuN.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CJ7VimIW.js → omit-DhHqKeFx.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-qXiG1iT3.js → pickAttrs-ANpJaWMO.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CkGBcy1Z.js → placementArrow-CfZWe7CA.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D3WvTlLO.js → responsiveObserve-D7Xz2y-R.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BEE2ftge.js → slide-DekqCBY9.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CsfBpxiG.js → statusUtils-BET6XU7h.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-xPrIiJPI.js → styleChecker-qHmJjV62.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-C5Yd-SCR.js → useFlexGapSupport-BoMCTNyu.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-D_MDS8HI.js → useFs-TdW-NgFC.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BqJh-usA.js → usePersonalDataHub-Dyox7wCu.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-chm_p-gz.js → vnode-XUn5S8CP.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-3-YDNz0Z.js → zoom-Ls77i8hn.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-manifest.json +8 -1
- package/src/commands/a2a.js +19 -4
- package/src/commands/activitypub.js +20 -3
- package/src/commands/agent.js +27 -5
- package/src/commands/audit.js +40 -24
- package/src/commands/changelog.js +148 -0
- package/src/commands/codeintel.js +68 -0
- package/src/commands/collab.js +15 -2
- package/src/commands/compliance.js +5 -0
- package/src/commands/config.js +4 -1
- package/src/commands/dao.js +86 -14
- package/src/commands/dev.js +2 -0
- package/src/commands/did.js +7 -1
- package/src/commands/dlp.js +23 -1
- package/src/commands/economy.js +29 -3
- package/src/commands/eval.js +7 -0
- package/src/commands/evomap.js +26 -0
- package/src/commands/governance.js +17 -3
- package/src/commands/hardening.js +18 -0
- package/src/commands/incentive.js +5 -0
- package/src/commands/init.js +46 -2
- package/src/commands/kg.js +4 -0
- package/src/commands/loop.js +6 -1
- package/src/commands/lowcode.js +15 -2
- package/src/commands/marketplace.js +40 -6
- package/src/commands/matrix.js +20 -1
- package/src/commands/memory.js +4 -1
- package/src/commands/mtc.js +7 -1
- package/src/commands/nostr.js +31 -4
- package/src/commands/note.js +7 -4
- package/src/commands/plugin.js +125 -5
- package/src/commands/pqc.js +5 -0
- package/src/commands/reputation.js +10 -1
- package/src/commands/scim.js +6 -0
- package/src/commands/session.js +32 -10
- package/src/commands/siem.js +11 -0
- package/src/commands/sla.js +18 -3
- package/src/commands/social.js +38 -5
- package/src/commands/sso.js +10 -2
- package/src/commands/stress.js +23 -4
- package/src/commands/team.js +9 -2
- package/src/commands/tech.js +2 -0
- package/src/commands/tenant.js +10 -1
- package/src/commands/terraform.js +6 -0
- package/src/commands/update.js +1 -1
- package/src/commands/zkp.js +20 -0
- package/src/data/changelog.json +189 -0
- package/src/gateways/ws/message-dispatcher.js +5 -2
- package/src/gateways/ws/remote-session-protocol.js +110 -42
- package/src/harness/jsonl-session-store.js +12 -5
- package/src/harness/plugin-manager.js +16 -4
- package/src/harness/remote-command-ledger.js +46 -15
- package/src/harness/worktree-isolator.js +16 -6
- package/src/index.js +2 -0
- package/src/lib/__tests__/logger.test.js +5 -2
- package/src/lib/a2a-protocol.js +25 -1
- package/src/lib/activitypub-bridge.js +61 -0
- package/src/lib/agent-core.js +2 -0
- package/src/lib/agent-economy.js +262 -29
- package/src/lib/agent-network.js +7 -1
- package/src/lib/agent-team/team-runner.js +25 -9
- package/src/lib/agent-team/team-worktree.js +36 -4
- package/src/lib/async-hook-supervisor.cjs +102 -16
- package/src/lib/audit-logger.js +7 -6
- package/src/lib/autonomous-developer.js +60 -0
- package/src/lib/changelog.js +252 -0
- package/src/lib/chat-core.js +17 -4
- package/src/lib/collaboration-governance.js +56 -0
- package/src/lib/community-governance.js +68 -0
- package/src/lib/compliance-manager.js +63 -0
- package/src/lib/cross-chain.js +5 -0
- package/src/lib/dao-governance.js +151 -2
- package/src/lib/did-manager.js +23 -10
- package/src/lib/dlp-engine.js +70 -0
- package/src/lib/eval/runner.js +89 -1
- package/src/lib/eval/tasks.js +170 -0
- package/src/lib/eval/trend.js +16 -1
- package/src/lib/evolution-system.js +92 -0
- package/src/lib/evomap-federation.js +55 -0
- package/src/lib/evomap-governance.js +94 -0
- package/src/lib/fatal-handler.js +17 -1
- package/src/lib/hardening-manager.js +73 -0
- package/src/lib/hierarchical-memory.js +14 -8
- package/src/lib/knowledge-exporter.js +8 -2
- package/src/lib/knowledge-graph.js +79 -0
- package/src/lib/llm-providers.js +23 -14
- package/src/lib/logger.js +4 -1
- package/src/lib/lsp/__tests__/benchmark.test.js +88 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +11 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +69 -0
- package/src/lib/lsp/benchmark.js +257 -0
- package/src/lib/lsp/lsp-client.js +30 -9
- package/src/lib/lsp/lsp-manager.js +54 -2
- package/src/lib/lsp/lsp-server-registry.js +15 -4
- package/src/lib/matrix-bridge.js +84 -0
- package/src/lib/memory-manager.js +5 -3
- package/src/lib/nostr-bridge.js +53 -0
- package/src/lib/permission-engine.js +22 -4
- package/src/lib/plugin-runtime/__tests__/remote-source.test.js +256 -0
- package/src/lib/plugin-runtime/hooks.js +20 -4
- package/src/lib/plugin-runtime/install.js +9 -1
- package/src/lib/plugin-runtime/monitors.js +20 -4
- package/src/lib/plugin-runtime/policy.js +9 -1
- package/src/lib/plugin-runtime/remote-source.js +240 -0
- package/src/lib/plugin-runtime/signature.js +16 -0
- package/src/lib/pqc-manager.js +64 -0
- package/src/lib/reputation-optimizer.js +101 -0
- package/src/lib/sandbox-egress-proxy.js +195 -59
- package/src/lib/sandbox-fs-policy.js +112 -0
- package/src/lib/sandbox-network-policy.js +44 -5
- package/src/lib/sandbox-v2.js +14 -14
- package/src/lib/scim-manager.js +36 -0
- package/src/lib/session-manager.js +5 -2
- package/src/lib/settings-hooks.cjs +1 -0
- package/src/lib/siem-exporter.js +45 -0
- package/src/lib/skill-loader.js +20 -2
- package/src/lib/skill-marketplace.js +83 -0
- package/src/lib/sla-manager.js +88 -0
- package/src/lib/social-manager.js +74 -0
- package/src/lib/stress-tester.js +65 -0
- package/src/lib/tech-learning-engine.js +75 -0
- package/src/lib/telemetry/span-recorder.js +12 -1
- package/src/lib/tenant-saas.js +107 -0
- package/src/lib/terraform-manager.js +67 -0
- package/src/lib/token-incentive.js +180 -29
- package/src/lib/wallet-manager.js +81 -35
- package/src/lib/zkp-engine.js +87 -0
- package/src/repl/agent-repl.js +17 -2
- package/src/runtime/__tests__/auto-pin.test.js +104 -0
- package/src/runtime/agent-core.js +241 -68
- package/src/runtime/auto-pin.js +117 -0
- package/src/runtime/headless-runner.js +35 -0
- package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +0 -1
- package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +0 -1
- package/src/assets/web-panel/assets/Terminal-ZzU0Io1Y.js +0 -3
- package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +0 -1
- package/src/assets/web-panel/assets/index-Cg2ldRfU.js +0 -1
- package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +0 -1
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
* flight — a rapid PostToolUse hook can't stack N copies of itself;
|
|
24
24
|
* - a maxConcurrent cap — overflow is DROPPED with a recorded skip, never
|
|
25
25
|
* queued unbounded;
|
|
26
|
-
* - a per-hook timeout that kills the child
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* - a per-hook timeout that TREE-kills the child (shell + the real command it
|
|
27
|
+
* spawned — a bare child.kill would orphan the grandchild);
|
|
28
|
+
* - tree-reaping of every child on stopAll() / process 'exit', so a session
|
|
29
|
+
* never leaves an orphan hook process.
|
|
29
30
|
*
|
|
30
31
|
* `_deps.spawn` / `_deps.now` are injected so the whole supervisor is unit-
|
|
31
32
|
* testable with fake child processes (no real shell).
|
|
@@ -37,6 +38,12 @@ const { tryParseDecision } = require("./hook-runner.cjs");
|
|
|
37
38
|
const DEFAULT_TIMEOUT_MS = 60000;
|
|
38
39
|
const MAX_TIMEOUT_MS = 600000;
|
|
39
40
|
const DEFAULT_MAX_CONCURRENT = 4;
|
|
41
|
+
// Ring cap on undrained records (parity with PluginMonitorSupervisor's
|
|
42
|
+
// OUTPUT_RING): drainResults()/drainRewakes() normally clear each turn, but a
|
|
43
|
+
// stalled/absent drain over a high-frequency hook would otherwise grow these
|
|
44
|
+
// arrays without bound. Keep only the most recent RESULT_RING; older records
|
|
45
|
+
// are dropped oldest-first.
|
|
46
|
+
const RESULT_RING = 500;
|
|
40
47
|
|
|
41
48
|
class AsyncHookSupervisor {
|
|
42
49
|
constructor(opts = {}) {
|
|
@@ -46,20 +53,87 @@ class AsyncHookSupervisor {
|
|
|
46
53
|
: DEFAULT_MAX_CONCURRENT;
|
|
47
54
|
this._deps = {
|
|
48
55
|
spawn: opts.spawn || cpDefault.spawn,
|
|
56
|
+
spawnSync: opts.spawnSync || cpDefault.spawnSync,
|
|
49
57
|
now: opts.now || (() => Date.now()),
|
|
50
58
|
};
|
|
51
59
|
this._running = new Map(); // key -> { child, timer }
|
|
52
60
|
this._results = []; // completed records awaiting drainResults()
|
|
53
61
|
this._rewakes = []; // failed asyncRewake records awaiting drainRewakes()
|
|
54
62
|
this._stopped = false;
|
|
63
|
+
// The exit reaper is installed LAZILY (on first spawn), not in the ctor:
|
|
64
|
+
// a supervisor that never dispatches a hook (or the many built in tests)
|
|
65
|
+
// must not leave a permanent `process.once('exit')` listener behind —
|
|
66
|
+
// that accumulates across sessions/instances into a MaxListenersExceeded
|
|
67
|
+
// leak. Mirrors PluginMonitorSupervisor._installExitHook.
|
|
55
68
|
this._exitHook = () => this.stopAll();
|
|
56
|
-
|
|
69
|
+
this._exitHookInstalled = false;
|
|
57
70
|
}
|
|
58
71
|
|
|
59
72
|
_key(hook) {
|
|
60
73
|
return `${hook.event || ""}::${hook.command}`;
|
|
61
74
|
}
|
|
62
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Kill a hook child's WHOLE process tree. Hooks run with `shell: true`, so the
|
|
78
|
+
* real command is a grandchild of the shell — a plain `child.kill()` only
|
|
79
|
+
* signals the shell (POSIX: reparents + keeps the command running; Windows:
|
|
80
|
+
* killing cmd.exe never touches its children), orphaning the actual hook
|
|
81
|
+
* process. POSIX: the child is spawned detached (its own group), so a negative
|
|
82
|
+
* pid signals the whole group. Windows: `taskkill /T` walks the tree. Both are
|
|
83
|
+
* SYNCHRONOUS (spawnSync / process.kill) so this is safe inside stopAll() and
|
|
84
|
+
* the process 'exit' reaper, where async work would be cut off. A child with no
|
|
85
|
+
* real pid (the unit-test fakes) falls back to its own `.kill()`.
|
|
86
|
+
*/
|
|
87
|
+
_killChildTree(child, signal = "SIGTERM") {
|
|
88
|
+
if (!child) return;
|
|
89
|
+
const pid = child.pid;
|
|
90
|
+
if (typeof pid !== "number" || pid <= 0) {
|
|
91
|
+
try {
|
|
92
|
+
child.kill(signal);
|
|
93
|
+
} catch {
|
|
94
|
+
/* already gone / fake with no kill */
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
if (process.platform === "win32") {
|
|
100
|
+
const r = this._deps.spawnSync(
|
|
101
|
+
"taskkill",
|
|
102
|
+
["/pid", String(pid), "/T", "/F"],
|
|
103
|
+
{ windowsHide: true },
|
|
104
|
+
);
|
|
105
|
+
// If taskkill couldn't launch, fall back to a direct kill.
|
|
106
|
+
if (r && r.error) child.kill(signal);
|
|
107
|
+
} else {
|
|
108
|
+
// Negative pid → the whole process group (requires the detached spawn).
|
|
109
|
+
try {
|
|
110
|
+
process.kill(-pid, signal);
|
|
111
|
+
} catch {
|
|
112
|
+
child.kill(signal);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
try {
|
|
117
|
+
child.kill(signal);
|
|
118
|
+
} catch {
|
|
119
|
+
/* already gone */
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Install the process-exit reaper exactly once, only when a child exists. */
|
|
125
|
+
_installExitHook() {
|
|
126
|
+
if (this._exitHookInstalled) return;
|
|
127
|
+
this._exitHookInstalled = true;
|
|
128
|
+
process.once("exit", this._exitHook);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Append a result record, bounded to the most recent RESULT_RING. */
|
|
132
|
+
_pushResult(rec) {
|
|
133
|
+
this._results.push(rec);
|
|
134
|
+
if (this._results.length > RESULT_RING) this._results.shift();
|
|
135
|
+
}
|
|
136
|
+
|
|
63
137
|
/**
|
|
64
138
|
* Dispatch a batch of async hooks fire-and-forget. Returns IMMEDIATELY with a
|
|
65
139
|
* per-hook disposition (`{command, dispatched, reason?}`) — it never awaits a
|
|
@@ -100,7 +174,7 @@ class AsyncHookSupervisor {
|
|
|
100
174
|
});
|
|
101
175
|
// Record the skip so the caller/agent can SEE that a hook was dropped
|
|
102
176
|
// (silent truncation would read as "the hook ran and said nothing").
|
|
103
|
-
this.
|
|
177
|
+
this._pushResult({
|
|
104
178
|
command: hook.command,
|
|
105
179
|
event: hook.event || null,
|
|
106
180
|
ok: false,
|
|
@@ -121,6 +195,9 @@ class AsyncHookSupervisor {
|
|
|
121
195
|
}
|
|
122
196
|
|
|
123
197
|
_spawnOne(hook, payload, opts) {
|
|
198
|
+
// A live child now exists — arm the exit reaper so a session never leaves
|
|
199
|
+
// an orphan hook process (installed once, only from here).
|
|
200
|
+
this._installExitHook();
|
|
124
201
|
const key = this._key(hook);
|
|
125
202
|
const started = this._deps.now();
|
|
126
203
|
const rawTimeout = Number(
|
|
@@ -136,6 +213,10 @@ class AsyncHookSupervisor {
|
|
|
136
213
|
child = this._deps.spawn(hook.command, {
|
|
137
214
|
cwd: opts.cwd || process.cwd(),
|
|
138
215
|
shell: true,
|
|
216
|
+
// POSIX: own process group so a timeout / stopAll can signal the whole
|
|
217
|
+
// tree (shell + the real hook command), not just the shell wrapper.
|
|
218
|
+
// No-op on Windows, where the tree is reaped via `taskkill /T` instead.
|
|
219
|
+
detached: process.platform !== "win32",
|
|
139
220
|
env: {
|
|
140
221
|
...process.env,
|
|
141
222
|
CLAUDE_HOOK_EVENT: hook.event || payload.hook_event_name || "",
|
|
@@ -158,6 +239,13 @@ class AsyncHookSupervisor {
|
|
|
158
239
|
this._running.set(key, rec);
|
|
159
240
|
|
|
160
241
|
try {
|
|
242
|
+
// `.end(data)` flushes ASYNCHRONOUSLY: if the hook exited before consuming
|
|
243
|
+
// stdin (a fast command), the write fails with an async EPIPE emitted as an
|
|
244
|
+
// 'error' event on the stream — NOT a sync throw this catch can see. With no
|
|
245
|
+
// listener that becomes an uncaught exception that crashes the process (seen
|
|
246
|
+
// on Linux CI). Attach a no-op error handler first so a closed-stdin write
|
|
247
|
+
// is swallowed as the non-fatal condition it is.
|
|
248
|
+
child.stdin?.on("error", () => {});
|
|
161
249
|
child.stdin?.end(JSON.stringify(payload));
|
|
162
250
|
} catch {
|
|
163
251
|
/* stdin may already be closed — non-fatal */
|
|
@@ -171,11 +259,9 @@ class AsyncHookSupervisor {
|
|
|
171
259
|
|
|
172
260
|
const timer = setTimeout(() => {
|
|
173
261
|
killedByTimeout = true;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
/* already gone */
|
|
178
|
-
}
|
|
262
|
+
// Tree-kill: a hook that spawned a subprocess (e.g. `npm test`) must not
|
|
263
|
+
// leave that subprocess orphaned when it exceeds its timeout.
|
|
264
|
+
this._killChildTree(child, "SIGTERM");
|
|
179
265
|
}, timeout);
|
|
180
266
|
if (typeof timer.unref === "function") timer.unref();
|
|
181
267
|
rec.timer = timer;
|
|
@@ -240,11 +326,12 @@ class AsyncHookSupervisor {
|
|
|
240
326
|
ts: now,
|
|
241
327
|
ms: fields.started != null ? now - fields.started : 0,
|
|
242
328
|
};
|
|
243
|
-
this.
|
|
329
|
+
this._pushResult(rec);
|
|
244
330
|
// A rewake fires only for a hook that OPTED IN and finished in a failure
|
|
245
331
|
// state — a passing async check should not re-engage the agent.
|
|
246
332
|
if (hook.asyncRewake && !rec.ok) {
|
|
247
333
|
this._rewakes.push(rec);
|
|
334
|
+
if (this._rewakes.length > RESULT_RING) this._rewakes.shift();
|
|
248
335
|
}
|
|
249
336
|
}
|
|
250
337
|
|
|
@@ -283,11 +370,9 @@ class AsyncHookSupervisor {
|
|
|
283
370
|
} catch {
|
|
284
371
|
/* ignore */
|
|
285
372
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
/* already gone */
|
|
290
|
-
}
|
|
373
|
+
// Tree-kill (not a bare child.kill) so a session end / process exit never
|
|
374
|
+
// leaves an orphaned hook subprocess — the guarantee this class documents.
|
|
375
|
+
this._killChildTree(rec.child, "SIGTERM");
|
|
291
376
|
this._running.delete(key);
|
|
292
377
|
}
|
|
293
378
|
try {
|
|
@@ -295,6 +380,7 @@ class AsyncHookSupervisor {
|
|
|
295
380
|
} catch {
|
|
296
381
|
/* ignore */
|
|
297
382
|
}
|
|
383
|
+
this._exitHookInstalled = false;
|
|
298
384
|
}
|
|
299
385
|
}
|
|
300
386
|
|
package/src/lib/audit-logger.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import crypto from "crypto";
|
|
7
7
|
import { safeJsonParse } from "./safe-json.js";
|
|
8
|
+
import { escapeLike } from "./sql-like.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Event types for audit logging.
|
|
@@ -183,13 +184,13 @@ export function queryLogs(db, filters = {}) {
|
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
if (filters.operation) {
|
|
186
|
-
sql += " AND operation LIKE ?";
|
|
187
|
-
params.push(`%${filters.operation}%`);
|
|
187
|
+
sql += " AND operation LIKE ? ESCAPE '\\'";
|
|
188
|
+
params.push(`%${escapeLike(filters.operation)}%`);
|
|
188
189
|
}
|
|
189
190
|
|
|
190
191
|
if (filters.actor) {
|
|
191
|
-
sql += " AND actor LIKE ?";
|
|
192
|
-
params.push(`%${filters.actor}%`);
|
|
192
|
+
sql += " AND actor LIKE ? ESCAPE '\\'";
|
|
193
|
+
params.push(`%${escapeLike(filters.actor)}%`);
|
|
193
194
|
}
|
|
194
195
|
|
|
195
196
|
if (filters.riskLevel) {
|
|
@@ -214,8 +215,8 @@ export function queryLogs(db, filters = {}) {
|
|
|
214
215
|
|
|
215
216
|
if (filters.search) {
|
|
216
217
|
// Search in operation field (primary search field for CLI)
|
|
217
|
-
sql += " AND operation LIKE ?";
|
|
218
|
-
params.push(`%${filters.search}%`);
|
|
218
|
+
sql += " AND operation LIKE ? ESCAPE '\\'";
|
|
219
|
+
params.push(`%${escapeLike(filters.search)}%`);
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
sql += " ORDER BY created_at DESC";
|
|
@@ -151,6 +151,66 @@ export function ensureAutonomousDevTables(db) {
|
|
|
151
151
|
);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Rehydrate _sessions/_adrs from the persisted dev_sessions/
|
|
156
|
+
* architecture_decisions tables. The `cc` CLI runs every command in a fresh
|
|
157
|
+
* process, so without this the Maps start empty and a session/ADR created in a
|
|
158
|
+
* prior invocation is invisible (`cc dev list`/`show`/`adrs` show nothing) and
|
|
159
|
+
* every mutation — recordADR, advancePhase, etc. — throws "Session not found"
|
|
160
|
+
* against the empty Map. Call after ensureAutonomousDevTables(db).
|
|
161
|
+
*/
|
|
162
|
+
export function loadFromDb(db) {
|
|
163
|
+
if (!db) return 0;
|
|
164
|
+
_sessions.clear();
|
|
165
|
+
_adrs.clear();
|
|
166
|
+
|
|
167
|
+
const parse = (v, fallback) => {
|
|
168
|
+
if (v == null) return fallback;
|
|
169
|
+
try {
|
|
170
|
+
return JSON.parse(v);
|
|
171
|
+
} catch {
|
|
172
|
+
return fallback;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const sessionRows = db.prepare(`SELECT * FROM dev_sessions`).all();
|
|
177
|
+
for (const row of sessionRows) {
|
|
178
|
+
_sessions.set(row.session_id, {
|
|
179
|
+
sessionId: row.session_id,
|
|
180
|
+
requirement: row.requirement,
|
|
181
|
+
currentPhase: row.current_phase,
|
|
182
|
+
status: row.status,
|
|
183
|
+
autonomyLevel: row.autonomy_level ?? 2,
|
|
184
|
+
codeChanges: parse(row.code_changes, []),
|
|
185
|
+
testResults: parse(row.test_results, null),
|
|
186
|
+
reviewFeedback: parse(row.review_feedback, null),
|
|
187
|
+
startedAt: row.started_at,
|
|
188
|
+
completedAt: row.completed_at ?? null,
|
|
189
|
+
createdBy: row.created_by ?? null,
|
|
190
|
+
updatedAt: row.updated_at,
|
|
191
|
+
_seq: ++_seq,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const adrRows = db.prepare(`SELECT * FROM architecture_decisions`).all();
|
|
196
|
+
for (const row of adrRows) {
|
|
197
|
+
_adrs.set(row.adr_id, {
|
|
198
|
+
adrId: row.adr_id,
|
|
199
|
+
sessionId: row.session_id,
|
|
200
|
+
title: row.title,
|
|
201
|
+
context: row.context,
|
|
202
|
+
decision: row.decision,
|
|
203
|
+
consequences: row.consequences ?? "",
|
|
204
|
+
alternatives: parse(row.alternatives, []),
|
|
205
|
+
status: row.status,
|
|
206
|
+
createdAt: row.created_at,
|
|
207
|
+
_seq: ++_seq,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return _sessions.size + _adrs.size;
|
|
212
|
+
}
|
|
213
|
+
|
|
154
214
|
/* ── Catalogs ──────────────────────────────────────────────── */
|
|
155
215
|
|
|
156
216
|
export function listAutonomyLevels() {
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The `cc changelog` data source.
|
|
9
|
+
*
|
|
10
|
+
* The canonical update record is the repository-root `CHANGELOG.md`, which is
|
|
11
|
+
* organized by PRODUCT version (`## [v5.0.3.x]`). Each block references the CLI
|
|
12
|
+
* npm version (`chainlesschain 0.162.x`) it shipped. This parser distills that
|
|
13
|
+
* into a CLI-focused view: it keeps only blocks that actually reference a CLI
|
|
14
|
+
* npm version, and within each block keeps only the CLI-relevant sub-sections.
|
|
15
|
+
*
|
|
16
|
+
* At publish time `scripts/build-changelog.mjs` runs `parseChangelog` over the
|
|
17
|
+
* root CHANGELOG and writes the result to `src/data/changelog.json`, which is
|
|
18
|
+
* bundled with the npm package. `loadChangelog()` reads that file (with a
|
|
19
|
+
* fallback to parsing a raw CHANGELOG.md for in-repo dev use).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// Signals that a `### ` sub-section HEADING is about the CLI npm package rather
|
|
23
|
+
// than the desktop app / Android / iOS / PDH portions of the same product
|
|
24
|
+
// release. CASE-SENSITIVE on purpose: real CLI notes write the acronym "CLI"
|
|
25
|
+
// (e.g. "cc CLI 0.162.150", "CLI 安全"), whereas PDH/Android bundle-roll notes
|
|
26
|
+
// write the version tag lowercase ("(pdh 0.4.6 / cli 0.162.48)"). Matching only
|
|
27
|
+
// uppercase "CLI" keeps collector releases that merely bundle a cli bump out of
|
|
28
|
+
// the CLI view. Heading-only (not body) for the same reason.
|
|
29
|
+
const CLI_HEADING_SIGNAL = /\bCLI\b|命令行/;
|
|
30
|
+
|
|
31
|
+
// A block with no `### ` sub-sections is a CLI release only if its header or
|
|
32
|
+
// preamble uses CLI-publish language. Same case-sensitivity: a lowercase
|
|
33
|
+
// bundle-roll "cli 0.162.x" mention is not enough.
|
|
34
|
+
const CLI_PUBLISH_SIGNAL = /\bCLI\b|命令行|catch-up/;
|
|
35
|
+
|
|
36
|
+
// CLI npm versions are 3-segment (0.162.x). The `(?<![\d.])` / `(?!\.\d)` guards
|
|
37
|
+
// stop a 4-segment PRODUCT version (v5.0.3.134) from matching as "5.0.3".
|
|
38
|
+
const V = "(?<![\\d.])(\\d+\\.\\d+\\.\\d+)(?!\\.\\d)";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Extract every CLI npm version token referenced in a block of text and return
|
|
42
|
+
* the "primary" one (the highest semver — the released target in a
|
|
43
|
+
* `0.162.149 → 0.162.150` style note).
|
|
44
|
+
*
|
|
45
|
+
* @param {string} text
|
|
46
|
+
* @returns {{ primary: string|null, all: string[] }}
|
|
47
|
+
*/
|
|
48
|
+
export function extractCliVersions(text) {
|
|
49
|
+
const found = new Set();
|
|
50
|
+
const patterns = [
|
|
51
|
+
// "cc CLI 0.162.150", "CLI 0.162.150"
|
|
52
|
+
new RegExp(`(?:cc\\s+)?cli\\s+${V}`, "gi"),
|
|
53
|
+
// "chainlesschain` 0.162.149 → **0.162.150**" (capture the arrow target)
|
|
54
|
+
new RegExp(
|
|
55
|
+
`chainlesschain[\`\\s]+(?:\\d+\\.\\d+\\.\\d+\\s*(?:→|->)\\s*)?\\*{0,2}${V}`,
|
|
56
|
+
"gi",
|
|
57
|
+
),
|
|
58
|
+
// bare "cli 0.162.71" inside "(pdh 0.4.25 / cli 0.162.71)"
|
|
59
|
+
new RegExp(`\\bcli\\s+${V}`, "gi"),
|
|
60
|
+
// "→ 0.162.150" / "→ **0.162.150**"
|
|
61
|
+
new RegExp(`(?:→|->)\\s*\\*{0,2}${V}`, "gi"),
|
|
62
|
+
];
|
|
63
|
+
for (const re of patterns) {
|
|
64
|
+
let m;
|
|
65
|
+
while ((m = re.exec(text)) !== null) {
|
|
66
|
+
found.add(m[1]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// The CLI npm package (`chainlesschain`) is on the 0.x alpha track; the
|
|
70
|
+
// product line is 5.x. Keeping only major-0 tokens discards any product
|
|
71
|
+
// version (v5.0.3.x) or desktop-app-vue (5.0.3-alpha.x) tokens that slip past
|
|
72
|
+
// the context regexes, so the "primary" is always a real CLI npm version.
|
|
73
|
+
const all = [...found].filter((v) => v.startsWith("0."));
|
|
74
|
+
const primary =
|
|
75
|
+
all.length === 0
|
|
76
|
+
? null
|
|
77
|
+
: all.reduce(
|
|
78
|
+
(best, v) => (compareSemver(v, best) > 0 ? v : best),
|
|
79
|
+
all[0],
|
|
80
|
+
);
|
|
81
|
+
return { primary, all };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Numeric semver compare for plain X.Y.Z (no prerelease). */
|
|
85
|
+
export function compareSemver(a, b) {
|
|
86
|
+
const pa = a.split(".").map(Number);
|
|
87
|
+
const pb = b.split(".").map(Number);
|
|
88
|
+
for (let i = 0; i < 3; i++) {
|
|
89
|
+
if ((pa[i] || 0) !== (pb[i] || 0)) return (pa[i] || 0) - (pb[i] || 0);
|
|
90
|
+
}
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Parse a raw CHANGELOG.md string into CLI-focused release entries.
|
|
96
|
+
*
|
|
97
|
+
* @param {string} md
|
|
98
|
+
* @returns {Array<{
|
|
99
|
+
* productVersion: string,
|
|
100
|
+
* cliVersion: string|null,
|
|
101
|
+
* cliVersions: string[],
|
|
102
|
+
* date: string|null,
|
|
103
|
+
* title: string,
|
|
104
|
+
* sections: Array<{ heading: string, body: string }>,
|
|
105
|
+
* }>}
|
|
106
|
+
*/
|
|
107
|
+
export function parseChangelog(md) {
|
|
108
|
+
const lines = md.split(/\r?\n/);
|
|
109
|
+
const blocks = [];
|
|
110
|
+
let current = null;
|
|
111
|
+
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
const h2 = line.match(/^##\s+(.+)$/);
|
|
114
|
+
if (h2 && !line.startsWith("###")) {
|
|
115
|
+
if (current) blocks.push(current);
|
|
116
|
+
current = { header: h2[1].trim(), lines: [] };
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (current) current.lines.push(line);
|
|
120
|
+
}
|
|
121
|
+
if (current) blocks.push(current);
|
|
122
|
+
|
|
123
|
+
const releases = [];
|
|
124
|
+
for (const block of blocks) {
|
|
125
|
+
const parsed = parseBlockHeader(block.header);
|
|
126
|
+
const bodyText = block.lines.join("\n");
|
|
127
|
+
const fullText = block.header + "\n" + bodyText;
|
|
128
|
+
|
|
129
|
+
const { primary, all } = extractCliVersions(fullText);
|
|
130
|
+
// A release must reference a CLI npm version at all.
|
|
131
|
+
if (!primary) continue;
|
|
132
|
+
|
|
133
|
+
// CLI-relevance gate is decided by section HEADINGS (or, for a section-less
|
|
134
|
+
// block, by CLI-publish language) — not by a bare bundled-cli mention.
|
|
135
|
+
const sections = extractCliSections(block.lines, block.header);
|
|
136
|
+
if (!sections) continue;
|
|
137
|
+
|
|
138
|
+
releases.push({
|
|
139
|
+
productVersion: parsed.version,
|
|
140
|
+
cliVersion: primary,
|
|
141
|
+
cliVersions: all.sort(compareSemver),
|
|
142
|
+
date: parsed.date,
|
|
143
|
+
title: parsed.title,
|
|
144
|
+
sections,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return releases;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Parse "## [v5.0.3.134] - 2026-07-03 — title" into parts. */
|
|
151
|
+
function parseBlockHeader(header) {
|
|
152
|
+
const tag = header.match(/\[([^\]]+)\]/);
|
|
153
|
+
const version = tag ? tag[1] : header;
|
|
154
|
+
const rest = header.replace(/\[[^\]]+\]\s*/, "");
|
|
155
|
+
const dateMatch = rest.match(/(\d{4}-\d{2}-\d{2})/);
|
|
156
|
+
const date = dateMatch ? dateMatch[1] : null;
|
|
157
|
+
// Title = text after the em dash separator, else whatever remains.
|
|
158
|
+
let title = "";
|
|
159
|
+
const emDash = rest.split(/\s+—\s+/);
|
|
160
|
+
if (emDash.length > 1) {
|
|
161
|
+
title = emDash.slice(1).join(" — ").trim();
|
|
162
|
+
} else {
|
|
163
|
+
title = rest
|
|
164
|
+
.replace(/^-\s*/, "")
|
|
165
|
+
.replace(/\d{4}-\d{2}-\d{2}/, "")
|
|
166
|
+
.trim();
|
|
167
|
+
}
|
|
168
|
+
return { version, date, title };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Split a block body into `### ` sub-sections and keep only CLI-relevant ones.
|
|
173
|
+
*
|
|
174
|
+
* Returns:
|
|
175
|
+
* - an array of CLI sections, when the block is a CLI release; or
|
|
176
|
+
* - `null`, when the block is NOT a CLI release (all-non-CLI sub-sections, e.g.
|
|
177
|
+
* a PDH/Android collector release that merely bundles a new cli version).
|
|
178
|
+
*
|
|
179
|
+
* @param {string[]} bodyLines
|
|
180
|
+
* @param {string} header
|
|
181
|
+
* @returns {Array<{heading:string, body:string}>|null}
|
|
182
|
+
*/
|
|
183
|
+
function extractCliSections(bodyLines, header) {
|
|
184
|
+
const sections = [];
|
|
185
|
+
const preamble = [];
|
|
186
|
+
let cur = null;
|
|
187
|
+
for (const line of bodyLines) {
|
|
188
|
+
const h3 = line.match(/^###\s+(.+)$/);
|
|
189
|
+
if (h3) {
|
|
190
|
+
if (cur) sections.push(cur);
|
|
191
|
+
cur = { heading: h3[1].trim(), lines: [] };
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (cur) cur.lines.push(line);
|
|
195
|
+
else preamble.push(line); // before the first ### (blockquote summary etc.)
|
|
196
|
+
}
|
|
197
|
+
if (cur) sections.push(cur);
|
|
198
|
+
|
|
199
|
+
if (sections.length === 0) {
|
|
200
|
+
// Section-less block: CLI release only if the `##` TITLE names the CLI.
|
|
201
|
+
// The preamble is NOT consulted — every block carries a boilerplate
|
|
202
|
+
// "Version surfaces: CLI 0.162.x → ..." line, so a body match would let
|
|
203
|
+
// every PDH/Android release through.
|
|
204
|
+
if (!CLI_PUBLISH_SIGNAL.test(header)) return null;
|
|
205
|
+
const body = preamble.join("\n").trim();
|
|
206
|
+
return body ? [{ heading: "", body }] : [];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const cliSections = sections
|
|
210
|
+
.filter((s) => CLI_HEADING_SIGNAL.test(s.heading))
|
|
211
|
+
.map((s) => ({ heading: s.heading, body: s.lines.join("\n").trim() }));
|
|
212
|
+
|
|
213
|
+
// Has `### ` sections but none are CLI-headed → not a CLI release.
|
|
214
|
+
return cliSections.length > 0 ? cliSections : null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Resolve and load the CLI changelog data.
|
|
219
|
+
*
|
|
220
|
+
* Order is CHANGELOG-FIRST so the data can never go stale: when the repo-root
|
|
221
|
+
* CHANGELOG.md is reachable (source checkout / dev / this monorepo) it is parsed
|
|
222
|
+
* live, always reflecting the latest edits. The bundled `src/data/changelog.json`
|
|
223
|
+
* (a build artifact, refreshed at `prepublishOnly`) is only the fallback for an
|
|
224
|
+
* installed npm package, where CHANGELOG.md is not shipped.
|
|
225
|
+
*
|
|
226
|
+
* @returns {{ source: string, releases: Array }}
|
|
227
|
+
*/
|
|
228
|
+
export function loadChangelog() {
|
|
229
|
+
const changelogCandidates = [
|
|
230
|
+
path.join(__dirname, "..", "..", "CHANGELOG.md"), // packages/cli/CHANGELOG.md
|
|
231
|
+
path.join(__dirname, "..", "..", "..", "..", "CHANGELOG.md"), // repo root
|
|
232
|
+
];
|
|
233
|
+
for (const p of changelogCandidates) {
|
|
234
|
+
if (fs.existsSync(p)) {
|
|
235
|
+
return {
|
|
236
|
+
source: "CHANGELOG.md",
|
|
237
|
+
releases: parseChangelog(fs.readFileSync(p, "utf-8")),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Installed npm package: CHANGELOG.md isn't shipped, use the bundled artifact.
|
|
242
|
+
const jsonPath = path.join(__dirname, "..", "data", "changelog.json");
|
|
243
|
+
if (fs.existsSync(jsonPath)) {
|
|
244
|
+
try {
|
|
245
|
+
const data = JSON.parse(fs.readFileSync(jsonPath, "utf-8"));
|
|
246
|
+
if (Array.isArray(data.releases)) return data;
|
|
247
|
+
} catch {
|
|
248
|
+
/* fall through to empty */
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { source: null, releases: [] };
|
|
252
|
+
}
|
package/src/lib/chat-core.js
CHANGED
|
@@ -134,6 +134,11 @@ export async function streamOllama(
|
|
|
134
134
|
const reader = response.body.getReader();
|
|
135
135
|
const decoder = new TextDecoder();
|
|
136
136
|
let fullResponse = "";
|
|
137
|
+
// Buffer incomplete lines across reads: an NDJSON line can be split across two
|
|
138
|
+
// stream chunks (TCP doesn't align to '\n'), so parsing each chunk in
|
|
139
|
+
// isolation would drop the split line entirely (both halves fail JSON.parse).
|
|
140
|
+
// Keep the trailing partial for the next read — same pattern as streamAnthropic.
|
|
141
|
+
let buf = "";
|
|
137
142
|
|
|
138
143
|
try {
|
|
139
144
|
while (true) {
|
|
@@ -141,10 +146,12 @@ export async function streamOllama(
|
|
|
141
146
|
if (done) break;
|
|
142
147
|
guard.bump();
|
|
143
148
|
|
|
144
|
-
|
|
145
|
-
const lines =
|
|
149
|
+
buf += decoder.decode(value, { stream: true });
|
|
150
|
+
const lines = buf.split("\n");
|
|
151
|
+
buf = lines.pop() || "";
|
|
146
152
|
|
|
147
153
|
for (const line of lines) {
|
|
154
|
+
if (!line) continue;
|
|
148
155
|
try {
|
|
149
156
|
const json = JSON.parse(line);
|
|
150
157
|
if (json.message?.content) {
|
|
@@ -225,6 +232,11 @@ export async function streamOpenAI(
|
|
|
225
232
|
const reader = response.body.getReader();
|
|
226
233
|
const decoder = new TextDecoder();
|
|
227
234
|
let fullResponse = "";
|
|
235
|
+
// Buffer incomplete lines across reads: an SSE `data:` line can be split
|
|
236
|
+
// across two stream chunks, so parsing each chunk in isolation would drop the
|
|
237
|
+
// split line (both halves fail JSON.parse) — losing content and usage. Keep
|
|
238
|
+
// the trailing partial for the next read — same pattern as streamAnthropic.
|
|
239
|
+
let buf = "";
|
|
228
240
|
|
|
229
241
|
try {
|
|
230
242
|
while (true) {
|
|
@@ -232,8 +244,9 @@ export async function streamOpenAI(
|
|
|
232
244
|
if (done) break;
|
|
233
245
|
guard.bump();
|
|
234
246
|
|
|
235
|
-
|
|
236
|
-
const lines =
|
|
247
|
+
buf += decoder.decode(value, { stream: true });
|
|
248
|
+
const lines = buf.split("\n");
|
|
249
|
+
buf = lines.pop() || "";
|
|
237
250
|
|
|
238
251
|
for (const line of lines) {
|
|
239
252
|
if (line.startsWith("data: ")) {
|
|
@@ -129,6 +129,62 @@ export function ensureGovernanceTables(db) {
|
|
|
129
129
|
);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Rehydrate _decisions/_agentLevels from the persisted governance_decisions/
|
|
134
|
+
* autonomy_levels tables. The `cc` CLI runs every command in a fresh process, so
|
|
135
|
+
* without this the Maps start empty and a decision/level set in a prior
|
|
136
|
+
* invocation is invisible (`cc collab decisions`/`show`/`agents` show nothing),
|
|
137
|
+
* decision voting throws "not found", and setAutonomyLevel on a cold Map takes
|
|
138
|
+
* the INSERT branch on an already-persisted agent_id → PRIMARY KEY conflict.
|
|
139
|
+
* Call after ensureGovernanceTables(db).
|
|
140
|
+
*/
|
|
141
|
+
export function loadFromDb(db) {
|
|
142
|
+
if (!db) return 0;
|
|
143
|
+
_decisions.clear();
|
|
144
|
+
_agentLevels.clear();
|
|
145
|
+
|
|
146
|
+
const parse = (v, fallback) => {
|
|
147
|
+
if (v == null) return fallback;
|
|
148
|
+
try {
|
|
149
|
+
return JSON.parse(v);
|
|
150
|
+
} catch {
|
|
151
|
+
return fallback;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const decisionRows = db.prepare(`SELECT * FROM governance_decisions`).all();
|
|
156
|
+
for (const row of decisionRows) {
|
|
157
|
+
_decisions.set(row.decision_id, {
|
|
158
|
+
decisionId: row.decision_id,
|
|
159
|
+
type: row.type,
|
|
160
|
+
proposal: row.proposal,
|
|
161
|
+
status: row.status,
|
|
162
|
+
votes: parse(row.votes, {}),
|
|
163
|
+
resolution: row.resolution ?? null,
|
|
164
|
+
executedAt: row.executed_at ?? null,
|
|
165
|
+
createdAt: row.created_at,
|
|
166
|
+
updatedAt: row.updated_at,
|
|
167
|
+
_seq: ++_seq,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const levelRows = db.prepare(`SELECT * FROM autonomy_levels`).all();
|
|
172
|
+
for (const row of levelRows) {
|
|
173
|
+
_agentLevels.set(row.agent_id, {
|
|
174
|
+
agentId: row.agent_id,
|
|
175
|
+
currentLevel: row.current_level,
|
|
176
|
+
permissions: parse(row.permissions, []),
|
|
177
|
+
adjustmentHistory: parse(row.adjustment_history, []),
|
|
178
|
+
lastReviewAt: row.last_review_at ?? null,
|
|
179
|
+
createdAt: row.created_at,
|
|
180
|
+
updatedAt: row.updated_at,
|
|
181
|
+
_seq: ++_seq,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return _decisions.size + _agentLevels.size;
|
|
186
|
+
}
|
|
187
|
+
|
|
132
188
|
/* ── Catalogs ──────────────────────────────────────────────── */
|
|
133
189
|
|
|
134
190
|
export function listDecisionTypes() {
|