chainlesschain 0.162.148 → 0.162.150
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 +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-DwpCCp64.js → AIOps-CBLvrjeG.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C9pBYocA.js → ActionButton-DYv2GtE0.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BWAkeXxK.js → Analytics-CL6PZ-Ww.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CivFGH6B.js → AppLayout-xuyHt4uA.js} +3 -3
- package/src/assets/web-panel/assets/{Audit-Cm8hRpZm.js → Audit-DOvSVycq.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DXdFMsE8.js → Backup-DMhfTswr.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-uAwSTeql.js → BaseInput-CQxDdm63.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-KU8eeJJE.js → Chat-BEeNhK2a.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-8nul8eTq.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-C6AMDkjd.js → Checkbox-CL04O-ER.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-t2moDxcO.js → Codegen-C50o-n7x.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DCcsRRhN.js → Col-CH-bDkzs.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DtB-8SAC.js → Community-DqAIMvSe.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CZm8THYA.js → Compact-C43fo_my.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-LiQgC7g1.js → Compliance-BERnMrdP.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CA8SAxht.js → Cowork-Baw3w1gp.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-CtRaF1wD.js → Cron-BEqAHF1-.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-6-br6Hub.js → Crosschain-CvnmKwK4.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Do2EccrL.js → DID-iMPxgVdt.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-wrXcbzGe.js → Dashboard--4SJX3YR.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-p3FsT245.js → Dropdown-BgLV6xgz.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D95A2L8q.js → EmailListRenderer-Bvb8oUD8.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-cLuJW2zo.js → FamilyGuardDashboard-DpXPjJB5.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Brgq_cbN.js → Federation-BbFfJ1Xi.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DWLCkNgh.js → FormItemContext-DeGq1B-q.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BBqUfQd6.js → GenericCardRenderer-CNW7s9zM.js} +1 -1
- package/src/assets/web-panel/assets/{Git-8F090w4I.js → Git-L1PjW-lT.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CCogEbxb.js → Governance-PK-X58to.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CfLD7v7C.js → Inference-BePWEH-d.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DDuHJewd.js → KnowledgeGraph-LF_sBvdL.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CE8KSEVC.js → Logs-BKkfk9hy.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-DmwpZmhT.js → Marketplace-BNMqUDla.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Bf7AazU8.js → McpTools-w4WPiyz2.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-D0QU_00S.js → Memory-DUKMVGNi.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-yXS9xdhx.js → MobileBridge-BWhiEyTJ.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BuDUoGUP.js → MobileProjects-Ocf5JEkX.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BYyHy28p.js → Mtc-D2B6MMhU.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-CK0aqpiZ.js → MtcAudit-DdYjCq1O.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-mNimKYeb.js → Multisig-Cb1hfuUZ.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-AioAJ0YA.js → NLProgramming-CTeImGp7.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CVVNCLHE.js → Notes-BjYNc7eQ.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-C4ABj-TK.js → NotificationSettings-Dn_NtRXQ.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DIp8Xcbd.js → OrderTableRenderer-DVYYIizh.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-uozl_gWK.js → Organization-Be2Kmr5j.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BCZOM2hK.js → Overflow-Cu_-qRlR.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CArcaiaj.js → P2P-DD2HoGzE.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Sgq2Srr8.js → PdhVaultBrowser-BRI7DVth.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BYrQrXnH.js → Permissions-C9Srcs2M.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BzHStAbz.js → PersonalDataHub-CUqcMgo1.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-k7KqxX1M.js → Pipeline-HBrQGLXt.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-IumTUWqx.js → Privacy-D-B0vjwh.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BRyImYTf.js → ProjectInit-eTeLIu9e.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BFIqTBFk.js → ProjectSettings-DrRqCsC6.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Dpid9CDg.js → Projects-1G9DNOhI.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-CyyFnUPs.js → Providers-RkTZzpxP.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-C82cRx-X.js → QrScannerModal-BSCUgsgC.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DGxDF521.js → QuickAsk-CHgyM3Bz.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Cns-Am1y.js → Recommend-0lry4OZq.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-R7OqAIlg.js → RemoteSession-Cn45UroZ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D7mgPIYV.js → Reputation-Q-Zjb707.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B3lEURyd.js → Row-BdM70oda.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-9_UVrpBt.js → RssFeed-DmOAKKap.js} +2 -2
- package/src/assets/web-panel/assets/{Search-ClZeO80q.js → Search-Dwavbm07.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BNNJczEp.js → Security-DukXFCnk.js} +3 -3
- package/src/assets/web-panel/assets/{Services-C5SjrWUj.js → Services-BIlRnITu.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Ci_obQ-g.js → Skeleton-YYVQdhhQ.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DdebN15P.js → Skills-B8_iYHz2.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-OinZP2vi.js → Sla-BdVrhT31.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CxzbNF51.js → SpeechSettings-CD3ggRx7.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-D06N_66b.js → SyncSettings-Bp02VZFH.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BdEdW0AZ.js → Tasks-DEVmCEsr.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-F1ctKmPa.js → Templates-B6czWc4N.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CVz1Urot.js → Tenant-BCJLv17r.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-CD132d2Y.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-Doitzjmf.js → TimelineRenderer-ZB-CvkZl.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BpyVRpVA.js → Tokens-BnSY0S-s.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-nWhWYTbU.js → Trigger-VZw9Oy2w.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DK_G-wLx.js → Trust-pZq7Hjd2.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B5yBUojO.js → UkeySign-DnQaqk4q.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C5D51qAe.js → VideoEditing-BEUfmvJV.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CLbL9K7v.js → Wallet-CoZKMXJ2.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DZUelI3V.js → WebAuthn-CBOGVx1I.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-8RPxt4KW.js → WorkflowEditor-huSKn7TT.js} +1 -1
- package/src/assets/web-panel/assets/{chat-4N4tOA3d.js → chat-A_3w6FBO.js} +1 -1
- package/src/assets/web-panel/assets/{colors-zbbGVrua.js → colors-D1Bem9Oy.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-D7iMkbnE.js → compact-item-CJYJj0oO.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CBzPJv-w.js → createContext-BkbFiKT4.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-WDr3_M_N.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-bHdrQSqZ.js → hasIn-CKvUafVY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbE5D0WL.js → index-AjrSPnvv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCr0geV9.js → index-B8i0lViZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiG1IZao.js → index-B9Svn0zc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1s0Bz9O.js → index-BHdHSX06.js} +1 -1
- package/src/assets/web-panel/assets/{index-QFObYeo1.js → index-BHdailyo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnBOpqv3.js → index-BJwlEnYo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdmMoYN1.js → index-BOoAQjJz.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUyjUkY7.js → index-BSgWxAOG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqdPyWm5.js → index-BdutMsne.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmqlJed-.js → index-BiDWxzbn.js} +1 -1
- package/src/assets/web-panel/assets/{index-S74FpAIn.js → index-By5a0T_W.js} +1 -1
- package/src/assets/web-panel/assets/{index-kmh1TxRa.js → index-C-WIY-FQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTIjjXry.js → index-C37f6iey.js} +1 -1
- package/src/assets/web-panel/assets/{index-BS4_Mwk6.js → index-C9bWmTcO.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBNr77E1.js → index-CBaosWRO.js} +1 -1
- package/src/assets/web-panel/assets/{index-QNAG4JtR.js → index-CBlBVJ_m.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bqmx24kh.js → index-CD62EEGo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQfu1U78.js → index-CUj-l7GM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJ4ZGyW0.js → index-CVS8Ymuq.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ci009ijp.js → index-ChkXUj3f.js} +1 -1
- package/src/assets/web-panel/assets/{index-oDKNgCsP.js → index-Cj0OZ-37.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZb8F8YG.js → index-Co3OFL0t.js} +1 -1
- package/src/assets/web-panel/assets/{index-308gCGh7.js → index-Crp8CbRg.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPxkoKgA.js → index-D22zNXiS.js} +1 -1
- package/src/assets/web-panel/assets/{index-xYCm6W2h.js → index-DTs_D1OL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtbbdLnf.js → index-DfgCdFrN.js} +3 -3
- package/src/assets/web-panel/assets/{index-BsKehmmS.js → index-DjYrecNb.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkxK86vf.js → index-DpW9cf3e.js} +1 -1
- package/src/assets/web-panel/assets/index-Dwix3p4g.js +1 -0
- package/src/assets/web-panel/assets/{index-CvRMA9uT.js → index-F--HuPG1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE9j5YgT.js → index-Fuk6t_3K.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7b1hGry.js → index-JEAGMii9.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1YDh7Wr.js → index-PF-mpv8K.js} +1 -1
- package/src/assets/web-panel/assets/index-SHaoZ0CA.js +1 -0
- package/src/assets/web-panel/assets/{index-CQ6NcfWz.js → index-b-sbVdjQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyoNgbXl.js → index-pyvMVX8r.js} +1 -1
- package/src/assets/web-panel/assets/{index-DISWAYce.js → index-qNTtOVi_.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4XKpj6c.js → index-tgO8iza6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CahryTX0.js → index-ttDQVhZy.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BD55yNBt.js → initDefaultProps-DtrnfsZH.js} +1 -1
- package/src/assets/web-panel/assets/{motion-B5Bbe77U.js → motion-D4zqSaX3.js} +1 -1
- package/src/assets/web-panel/assets/{move-CTvIqHEH.js → move-CGFGOUQj.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BkNyPQKB.js → mtc-parser-DH2HvkJl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BaXJXgHA.js → omit-jJ2at5HX.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Bw6-YTxH.js → pickAttrs-CRyMT1Fv.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BLdbkLqJ.js → placementArrow-DZ_CX0Pt.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-IVYkzntU.js → responsiveObserve-wruHk-h5.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DFMFwwtY.js → slide-BGgx8q67.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CURYRtZ1.js → statusUtils-Do5M7gKm.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Cfz63s1r.js → styleChecker-CRa-GZpX.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-COJL0KE3.js → useFlexGapSupport-BxPcq6pj.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-YLLojQQf.js → useFs-v5O2ZcJm.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BF_21qUC.js → usePersonalDataHub--z2FU0Px.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-9ZpkA7bb.js → vnode-1emidVKd.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DhtAfhl8.js → zoom-CcJaRyHs.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/assets/web-panel/remote-session-sw.js +43 -0
- package/src/command-manifest.json +22 -1
- package/src/commands/a2a.js +19 -4
- package/src/commands/activitypub.js +20 -3
- package/src/commands/agent.js +71 -10
- package/src/commands/audit.js +40 -24
- package/src/commands/codeintel.js +320 -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 +255 -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 +474 -0
- 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 +463 -0
- 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/gateways/ws/message-dispatcher.js +48 -2
- package/src/gateways/ws/remote-session-protocol.js +140 -42
- package/src/gateways/ws/ws-server.js +1 -1
- package/src/harness/jsonl-session-store.js +12 -5
- package/src/harness/plugin-manager.js +16 -4
- package/src/harness/prompt-compressor.js +27 -1
- package/src/harness/remote-command-ledger.js +189 -0
- package/src/harness/remote-session-push-apns.js +246 -0
- package/src/harness/remote-session-push-errors.js +15 -0
- package/src/harness/remote-session-push-fcm.js +9 -25
- package/src/harness/remote-session-push-huawei.js +174 -0
- package/src/harness/remote-session-push-oppo.js +171 -0
- package/src/harness/remote-session-push-senders.js +42 -0
- package/src/harness/remote-session-push-vivo.js +179 -0
- package/src/harness/remote-session-push-web.js +299 -0
- package/src/harness/remote-session-push-xiaomi.js +99 -0
- package/src/harness/worktree-isolator.js +16 -6
- package/src/index.js +6 -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 +4 -0
- package/src/lib/agent-economy.js +262 -29
- package/src/lib/agent-network.js +7 -1
- package/src/lib/agent-sandbox.js +161 -5
- package/src/lib/agent-team/task-lease.js +434 -0
- package/src/lib/agent-team/team-budget.js +165 -0
- package/src/lib/agent-team/team-mailbox.js +106 -0
- package/src/lib/agent-team/team-runner.js +282 -0
- package/src/lib/agent-team/team-worktree.js +236 -0
- package/src/lib/agents.js +18 -0
- package/src/lib/async-hook-supervisor.cjs +391 -0
- package/src/lib/audit-logger.js +7 -6
- package/src/lib/autonomous-developer.js +60 -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 +251 -0
- package/src/lib/eval/tasks.js +626 -0
- package/src/lib/eval/trend.js +200 -0
- 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__/code-intelligence.integration.test.js +129 -0
- package/src/lib/lsp/__tests__/code-intelligence.test.js +228 -0
- package/src/lib/lsp/__tests__/jsonrpc-stream.test.js +104 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +269 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +333 -0
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -0
- package/src/lib/lsp/benchmark.js +257 -0
- package/src/lib/lsp/code-intelligence.js +356 -0
- package/src/lib/lsp/jsonrpc-stream.js +139 -0
- package/src/lib/lsp/lsp-client.js +339 -0
- package/src/lib/lsp/lsp-manager.js +375 -0
- package/src/lib/lsp/lsp-server-registry.js +196 -0
- 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-monitor-supervisor.js +238 -0
- package/src/lib/plugin-runtime/__tests__/remote-source.test.js +256 -0
- package/src/lib/plugin-runtime/agents.js +51 -0
- package/src/lib/plugin-runtime/bin.js +100 -0
- package/src/lib/plugin-runtime/hooks.js +100 -0
- package/src/lib/plugin-runtime/install.js +396 -0
- package/src/lib/plugin-runtime/lsp.js +75 -0
- package/src/lib/plugin-runtime/manifest.js +458 -0
- package/src/lib/plugin-runtime/mcp.js +89 -0
- package/src/lib/plugin-runtime/monitors.js +100 -0
- package/src/lib/plugin-runtime/policy.js +152 -0
- package/src/lib/plugin-runtime/reload.js +79 -0
- package/src/lib/plugin-runtime/remote-source.js +240 -0
- package/src/lib/plugin-runtime/scopes.js +197 -0
- package/src/lib/plugin-runtime/settings.js +119 -0
- package/src/lib/plugin-runtime/signature.js +107 -0
- package/src/lib/plugin-runtime/skills.js +43 -0
- package/src/lib/plugin-runtime/trust.js +140 -0
- package/src/lib/pqc-manager.js +64 -0
- package/src/lib/reputation-optimizer.js +101 -0
- package/src/lib/sandbox-egress-proxy.js +262 -0
- package/src/lib/sandbox-fs-policy.js +112 -0
- package/src/lib/sandbox-network-policy.js +151 -0
- package/src/lib/sandbox-v2.js +24 -18
- package/src/lib/scim-manager.js +36 -0
- package/src/lib/session-manager.js +5 -2
- package/src/lib/settings-hook-events.cjs +78 -6
- package/src/lib/settings-hooks.cjs +30 -3
- package/src/lib/settings-loader.cjs +35 -1
- package/src/lib/siem-exporter.js +45 -0
- package/src/lib/skill-loader.js +38 -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 +237 -0
- 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 +417 -6
- package/src/runtime/__tests__/auto-pin.test.js +104 -0
- package/src/runtime/agent-core.js +771 -104
- package/src/runtime/auto-pin.js +117 -0
- package/src/runtime/coding-agent-contract-shared.cjs +82 -8
- package/src/runtime/coding-agent-policy.cjs +32 -7
- package/src/runtime/fallback-model.js +134 -7
- package/src/runtime/headless-runner.js +388 -108
- package/src/runtime/mcp-config.js +46 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DCNfbdlx.js +0 -1
- package/src/assets/web-panel/assets/Terminal-BvAK_Zel.js +0 -3
- package/src/assets/web-panel/assets/devWarning-C2Z5LRgq.js +0 -1
- package/src/assets/web-panel/assets/index-BGp6Yr-Y.js +0 -1
- package/src/assets/web-panel/assets/index-BXiw9dQf.js +0 -1
package/src/lib/stress-tester.js
CHANGED
|
@@ -95,6 +95,71 @@ export function ensureStressTables(db) {
|
|
|
95
95
|
`);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Rehydrate _runs/_results from the persisted stress_test_runs/
|
|
100
|
+
* stress_test_results tables. The `cc` CLI runs every command in a fresh
|
|
101
|
+
* process, so without this the Maps start empty and a run recorded in a prior
|
|
102
|
+
* invocation is invisible (`cc stress list` shows "No stress tests recorded.";
|
|
103
|
+
* `cc stress show <id>` throws "Stress test not found"). Call after
|
|
104
|
+
* ensureStressTables(db).
|
|
105
|
+
*/
|
|
106
|
+
export function loadFromDb(db) {
|
|
107
|
+
if (!db) return 0;
|
|
108
|
+
_runs.clear();
|
|
109
|
+
_results.clear();
|
|
110
|
+
|
|
111
|
+
const resultRows = db.prepare(`SELECT * FROM stress_test_results`).all();
|
|
112
|
+
for (const row of resultRows) {
|
|
113
|
+
let bottlenecks = [];
|
|
114
|
+
let capacityRecommendations = [];
|
|
115
|
+
try {
|
|
116
|
+
bottlenecks = row.bottlenecks ? JSON.parse(row.bottlenecks) : [];
|
|
117
|
+
} catch {
|
|
118
|
+
bottlenecks = [];
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
capacityRecommendations = row.capacity_recommendations
|
|
122
|
+
? JSON.parse(row.capacity_recommendations)
|
|
123
|
+
: [];
|
|
124
|
+
} catch {
|
|
125
|
+
capacityRecommendations = [];
|
|
126
|
+
}
|
|
127
|
+
_results.set(row.test_id, {
|
|
128
|
+
resultId: row.result_id,
|
|
129
|
+
testId: row.test_id,
|
|
130
|
+
tps: row.tps,
|
|
131
|
+
avgResponseTime: row.avg_response_time,
|
|
132
|
+
p50ResponseTime: row.p50_response_time,
|
|
133
|
+
p95ResponseTime: row.p95_response_time,
|
|
134
|
+
p99ResponseTime: row.p99_response_time,
|
|
135
|
+
errorRate: row.error_rate,
|
|
136
|
+
bottlenecks,
|
|
137
|
+
capacityRecommendations,
|
|
138
|
+
createdAt: row.created_at,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const runRows = db.prepare(`SELECT * FROM stress_test_runs`).all();
|
|
143
|
+
for (const row of runRows) {
|
|
144
|
+
_runs.set(row.test_id, {
|
|
145
|
+
testId: row.test_id,
|
|
146
|
+
loadLevel: row.load_level,
|
|
147
|
+
concurrency: row.concurrency,
|
|
148
|
+
requestsPerSecond: row.requests_per_second,
|
|
149
|
+
duration: row.duration,
|
|
150
|
+
status: row.status,
|
|
151
|
+
startedAt: row.started_at,
|
|
152
|
+
completedAt: row.completed_at ?? null,
|
|
153
|
+
// _seq is a per-process monotonic tiebreaker; started_at is the primary
|
|
154
|
+
// sort key. Reassign in load order — ties (same ms) are the only case it
|
|
155
|
+
// affects and are cosmetic for history ordering.
|
|
156
|
+
_seq: ++_seq,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return _runs.size + _results.size;
|
|
161
|
+
}
|
|
162
|
+
|
|
98
163
|
/* ── Synthetic metrics ─────────────────────────────────────── */
|
|
99
164
|
|
|
100
165
|
// Deterministic quasi-random: stable across runs for the same inputs. Tests
|
|
@@ -169,6 +169,81 @@ export function ensureTechLearningTables(db) {
|
|
|
169
169
|
);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Rehydrate _profiles/_practices from the persisted tech_stack_profiles/
|
|
174
|
+
* learned_practices tables. The `cc` CLI runs every command in a fresh process,
|
|
175
|
+
* so without this the Maps start empty and a profile/practice recorded in a
|
|
176
|
+
* prior invocation is invisible (`cc tech profile` returns null, `cc tech
|
|
177
|
+
* practices` shows nothing, `cc tech recommend` can't infer the latest stack).
|
|
178
|
+
* Call after ensureTechLearningTables(db). The profile's frameworks/databases/
|
|
179
|
+
* tools/libraries are not stored as columns — they are reconstructed from the
|
|
180
|
+
* classified tech_stack exactly as analyzeTechStack derives them.
|
|
181
|
+
*/
|
|
182
|
+
export function loadFromDb(db) {
|
|
183
|
+
if (!db) return 0;
|
|
184
|
+
_profiles.clear();
|
|
185
|
+
_practices.clear();
|
|
186
|
+
|
|
187
|
+
const profileRows = db.prepare(`SELECT * FROM tech_stack_profiles`).all();
|
|
188
|
+
for (const row of profileRows) {
|
|
189
|
+
let classified = [];
|
|
190
|
+
let deps = [];
|
|
191
|
+
let languages = [];
|
|
192
|
+
try {
|
|
193
|
+
classified = row.tech_stack ? JSON.parse(row.tech_stack) : [];
|
|
194
|
+
} catch {
|
|
195
|
+
classified = [];
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
deps = row.dependencies ? JSON.parse(row.dependencies) : [];
|
|
199
|
+
} catch {
|
|
200
|
+
deps = [];
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
languages = row.languages ? JSON.parse(row.languages) : [];
|
|
204
|
+
} catch {
|
|
205
|
+
languages = [];
|
|
206
|
+
}
|
|
207
|
+
const byType = (t) =>
|
|
208
|
+
classified.filter((d) => d.type === t).map((d) => d.name);
|
|
209
|
+
_profiles.set(row.project_path, {
|
|
210
|
+
profileId: row.profile_id,
|
|
211
|
+
projectPath: row.project_path,
|
|
212
|
+
languages,
|
|
213
|
+
frameworks: byType(TECH_TYPES.FRAMEWORK),
|
|
214
|
+
databases: byType(TECH_TYPES.DATABASE),
|
|
215
|
+
tools: byType(TECH_TYPES.TOOL),
|
|
216
|
+
libraries: byType(TECH_TYPES.LIBRARY),
|
|
217
|
+
totalDependencies: deps.length,
|
|
218
|
+
analysisTimestamp: row.analysis_timestamp,
|
|
219
|
+
createdAt: row.created_at,
|
|
220
|
+
updatedAt: row.updated_at,
|
|
221
|
+
_seq: ++_seq,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const practiceRows = db.prepare(`SELECT * FROM learned_practices`).all();
|
|
226
|
+
for (const row of practiceRows) {
|
|
227
|
+
_practices.set(row.practice_id, {
|
|
228
|
+
practiceId: row.practice_id,
|
|
229
|
+
techType: row.tech_type,
|
|
230
|
+
techName: row.tech_name,
|
|
231
|
+
patternName: row.pattern_name,
|
|
232
|
+
level: row.level,
|
|
233
|
+
description: row.description ?? "",
|
|
234
|
+
codeExample: row.code_example ?? "",
|
|
235
|
+
usageCount: row.usage_count ?? 0,
|
|
236
|
+
score: row.score ?? 0,
|
|
237
|
+
source: row.source,
|
|
238
|
+
learnedAt: row.learned_at,
|
|
239
|
+
updatedAt: row.updated_at,
|
|
240
|
+
_seq: ++_seq,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return _profiles.size + _practices.size;
|
|
245
|
+
}
|
|
246
|
+
|
|
172
247
|
/* ── Parsers for dependency manifests ──────────────────────── */
|
|
173
248
|
|
|
174
249
|
function _readIfExists(filePath) {
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TelemetryRecorder (Phase 7) — a dependency-free, OpenTelemetry-SHAPED span +
|
|
3
|
+
* metrics recorder for the agent's real execution (model calls, tool calls,
|
|
4
|
+
* cache, retries, failures). The plan asks to "引入 OpenTelemetry,覆盖模型、
|
|
5
|
+
* 工具、缓存、重试和失败分类" — but pulling the `@opentelemetry/*` SDK in (a
|
|
6
|
+
* heavy dep tree that also needs a running collector) is the wrong default for a
|
|
7
|
+
* ~2 MB CLI. This records the SAME span/attribute model and can emit OTLP JSON
|
|
8
|
+
* (`toOtlp()`) so a real collector can ingest it later, without the dependency.
|
|
9
|
+
*
|
|
10
|
+
* It captures the plan's metric set — per-name durations (avg/p50/p95/max),
|
|
11
|
+
* counters (token / cost / cache-hit / retry), and failure classification — and
|
|
12
|
+
* `summary()` renders them. The clock is injected so tests are deterministic.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
let _seq = 0;
|
|
16
|
+
function spanId() {
|
|
17
|
+
_seq = (_seq + 1) % Number.MAX_SAFE_INTEGER;
|
|
18
|
+
// 16-hex-ish id derived from a monotonic counter (deterministic, no RNG —
|
|
19
|
+
// Math.random is intentionally avoided so callers can snapshot/replay).
|
|
20
|
+
return _seq.toString(16).padStart(16, "0");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class TelemetryRecorder {
|
|
24
|
+
constructor({
|
|
25
|
+
now = () => Date.now(),
|
|
26
|
+
serviceName = "chainlesschain-cli",
|
|
27
|
+
} = {}) {
|
|
28
|
+
this._now = typeof now === "function" ? now : () => now;
|
|
29
|
+
this.serviceName = serviceName;
|
|
30
|
+
this._spans = []; // completed spans
|
|
31
|
+
this._counters = new Map(); // name → { total, byAttr }
|
|
32
|
+
this._failures = new Map(); // category → count
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Start a span. Returns a handle; call `.end()` (optionally with a status /
|
|
37
|
+
* extra attributes) to record it. Nesting is expressed via `parentId`.
|
|
38
|
+
*/
|
|
39
|
+
startSpan(name, attributes = {}, { parentId = null } = {}) {
|
|
40
|
+
const id = spanId();
|
|
41
|
+
const start = this._now();
|
|
42
|
+
const attrs = { ...attributes };
|
|
43
|
+
const events = [];
|
|
44
|
+
const self = this;
|
|
45
|
+
let ended = false;
|
|
46
|
+
return {
|
|
47
|
+
id,
|
|
48
|
+
name,
|
|
49
|
+
setAttribute(k, v) {
|
|
50
|
+
attrs[k] = v;
|
|
51
|
+
return this;
|
|
52
|
+
},
|
|
53
|
+
addEvent(evName, evAttrs = {}) {
|
|
54
|
+
events.push({
|
|
55
|
+
name: evName,
|
|
56
|
+
time: self._now(),
|
|
57
|
+
attributes: { ...evAttrs },
|
|
58
|
+
});
|
|
59
|
+
return this;
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Record a failure on this span, classified into a category (defaults to
|
|
63
|
+
* the error name) so `summary().failures` aggregates by cause.
|
|
64
|
+
*/
|
|
65
|
+
recordException(err, category) {
|
|
66
|
+
const cat = category || err?.code || err?.name || "error";
|
|
67
|
+
attrs["failure.category"] = cat;
|
|
68
|
+
attrs["error"] = true;
|
|
69
|
+
events.push({
|
|
70
|
+
name: "exception",
|
|
71
|
+
time: self._now(),
|
|
72
|
+
attributes: {
|
|
73
|
+
"exception.message": err?.message || String(err),
|
|
74
|
+
"exception.category": cat,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
self._failures.set(cat, (self._failures.get(cat) || 0) + 1);
|
|
78
|
+
return this;
|
|
79
|
+
},
|
|
80
|
+
end(extra = {}) {
|
|
81
|
+
if (ended) return; // idempotent
|
|
82
|
+
ended = true;
|
|
83
|
+
const endTime = self._now();
|
|
84
|
+
Object.assign(attrs, extra.attributes || {});
|
|
85
|
+
const status = extra.status || (attrs.error ? "error" : "ok");
|
|
86
|
+
self._spans.push({
|
|
87
|
+
id,
|
|
88
|
+
parentId,
|
|
89
|
+
name,
|
|
90
|
+
startTime: start,
|
|
91
|
+
endTime,
|
|
92
|
+
durationMs: endTime - start,
|
|
93
|
+
status,
|
|
94
|
+
attributes: attrs,
|
|
95
|
+
events,
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Increment a named counter (tokens, cost, cache.hit, retry, …). */
|
|
102
|
+
counter(name, value = 1, attributes = {}) {
|
|
103
|
+
const entry = this._counters.get(name) || { total: 0, byAttr: {} };
|
|
104
|
+
entry.total += value;
|
|
105
|
+
for (const [k, v] of Object.entries(attributes)) {
|
|
106
|
+
const key = `${k}=${v}`;
|
|
107
|
+
entry.byAttr[key] = (entry.byAttr[key] || 0) + value;
|
|
108
|
+
}
|
|
109
|
+
this._counters.set(name, entry);
|
|
110
|
+
return entry.total;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_percentile(sorted, p) {
|
|
114
|
+
if (sorted.length === 0) return 0;
|
|
115
|
+
// nearest-rank
|
|
116
|
+
const rank = Math.ceil((p / 100) * sorted.length);
|
|
117
|
+
return sorted[Math.min(rank, sorted.length) - 1];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Aggregate metrics across everything recorded so far. */
|
|
121
|
+
summary() {
|
|
122
|
+
const byName = {};
|
|
123
|
+
for (const s of this._spans) {
|
|
124
|
+
(byName[s.name] = byName[s.name] || []).push(s);
|
|
125
|
+
}
|
|
126
|
+
const durations = {};
|
|
127
|
+
for (const [name, spans] of Object.entries(byName)) {
|
|
128
|
+
const ds = spans.map((s) => s.durationMs).sort((a, b) => a - b);
|
|
129
|
+
const total = ds.reduce((a, b) => a + b, 0);
|
|
130
|
+
const errors = spans.filter((s) => s.status === "error").length;
|
|
131
|
+
durations[name] = {
|
|
132
|
+
count: spans.length,
|
|
133
|
+
errors,
|
|
134
|
+
totalMs: total,
|
|
135
|
+
avgMs: Math.round(total / spans.length),
|
|
136
|
+
p50Ms: this._percentile(ds, 50),
|
|
137
|
+
p95Ms: this._percentile(ds, 95),
|
|
138
|
+
maxMs: ds[ds.length - 1] || 0,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const counters = {};
|
|
142
|
+
for (const [name, entry] of this._counters) {
|
|
143
|
+
counters[name] = { total: entry.total, byAttr: { ...entry.byAttr } };
|
|
144
|
+
}
|
|
145
|
+
const failures = {};
|
|
146
|
+
let failureTotal = 0;
|
|
147
|
+
for (const [cat, n] of this._failures) {
|
|
148
|
+
failures[cat] = n;
|
|
149
|
+
failureTotal += n;
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
spanCount: this._spans.length,
|
|
153
|
+
durations,
|
|
154
|
+
counters,
|
|
155
|
+
failures,
|
|
156
|
+
failureTotal,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** OTLP/JSON-shaped export (resourceSpans) — ingestible by an OTel collector. */
|
|
161
|
+
toOtlp() {
|
|
162
|
+
return {
|
|
163
|
+
resourceSpans: [
|
|
164
|
+
{
|
|
165
|
+
resource: {
|
|
166
|
+
attributes: [
|
|
167
|
+
{ key: "service.name", value: { stringValue: this.serviceName } },
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
scopeSpans: [
|
|
171
|
+
{
|
|
172
|
+
scope: { name: "chainlesschain.cli" },
|
|
173
|
+
spans: this._spans.map((s) => ({
|
|
174
|
+
traceId: "0".repeat(32),
|
|
175
|
+
spanId: s.id,
|
|
176
|
+
parentSpanId: s.parentId || "",
|
|
177
|
+
name: s.name,
|
|
178
|
+
startTimeUnixNano: s.startTime * 1e6,
|
|
179
|
+
endTimeUnixNano: s.endTime * 1e6,
|
|
180
|
+
status: { code: s.status === "error" ? 2 : 1 },
|
|
181
|
+
attributes: Object.entries(s.attributes).map(([k, v]) => ({
|
|
182
|
+
key: k,
|
|
183
|
+
value:
|
|
184
|
+
typeof v === "number"
|
|
185
|
+
? { doubleValue: v }
|
|
186
|
+
: typeof v === "boolean"
|
|
187
|
+
? { boolValue: v }
|
|
188
|
+
: { stringValue: String(v) },
|
|
189
|
+
})),
|
|
190
|
+
events: s.events.map((e) => ({
|
|
191
|
+
name: e.name,
|
|
192
|
+
timeUnixNano: e.time * 1e6,
|
|
193
|
+
attributes: Object.entries(e.attributes).map(([k, v]) => ({
|
|
194
|
+
key: k,
|
|
195
|
+
value: { stringValue: String(v) },
|
|
196
|
+
})),
|
|
197
|
+
})),
|
|
198
|
+
})),
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
spans() {
|
|
207
|
+
return this._spans.slice();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
reset() {
|
|
211
|
+
this._spans = [];
|
|
212
|
+
this._counters = new Map();
|
|
213
|
+
this._failures = new Map();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Render a summary as a compact text block. */
|
|
218
|
+
export function formatTelemetry(summary) {
|
|
219
|
+
const lines = [];
|
|
220
|
+
lines.push(`Telemetry: ${summary.spanCount} span(s)`);
|
|
221
|
+
for (const [name, d] of Object.entries(summary.durations)) {
|
|
222
|
+
lines.push(
|
|
223
|
+
` ${name}: n=${d.count}${d.errors ? ` err=${d.errors}` : ""} ` +
|
|
224
|
+
`avg=${d.avgMs}ms p50=${d.p50Ms}ms p95=${d.p95Ms}ms max=${d.maxMs}ms`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
for (const [name, c] of Object.entries(summary.counters)) {
|
|
228
|
+
lines.push(` ${name}: ${c.total}`);
|
|
229
|
+
}
|
|
230
|
+
if (summary.failureTotal > 0) {
|
|
231
|
+
const parts = Object.entries(summary.failures)
|
|
232
|
+
.map(([cat, n]) => `${cat}=${n}`)
|
|
233
|
+
.join(", ");
|
|
234
|
+
lines.push(` failures: ${summary.failureTotal} (${parts})`);
|
|
235
|
+
}
|
|
236
|
+
return lines.join("\n");
|
|
237
|
+
}
|
package/src/lib/tenant-saas.js
CHANGED
|
@@ -830,6 +830,113 @@ export function _resetState() {
|
|
|
830
830
|
_seq = 0;
|
|
831
831
|
}
|
|
832
832
|
|
|
833
|
+
/**
|
|
834
|
+
* Rehydrate the in-memory Maps from the persisted saas_* tables. The CLI runs
|
|
835
|
+
* every subcommand in a fresh node process, so these module-level Maps start
|
|
836
|
+
* empty each invocation. Every write dual-writes (Map + INSERT OR REPLACE) but
|
|
837
|
+
* every read (getTenant/listTenants/getUsage/getActiveSubscription/
|
|
838
|
+
* listSubscriptions/getSaasStats) is Map-only, and nothing SELECTed the tables
|
|
839
|
+
* back — so a tenant created in one invocation was invisible in the next
|
|
840
|
+
* (`No tenants.` / `Tenant not found`), and every follow-up subscribe/record/
|
|
841
|
+
* check-quota/configure/delete threw "Tenant not found". Call after
|
|
842
|
+
* ensureTenantTables(db).
|
|
843
|
+
*/
|
|
844
|
+
export function loadFromDb(db) {
|
|
845
|
+
if (!db) return 0;
|
|
846
|
+
ensureTenantTables(db);
|
|
847
|
+
_tenants.clear();
|
|
848
|
+
_subscriptions.clear();
|
|
849
|
+
_usage.clear();
|
|
850
|
+
_slugIndex.clear();
|
|
851
|
+
_tenantSubs.clear();
|
|
852
|
+
_tenantUsage.clear();
|
|
853
|
+
|
|
854
|
+
for (const r of db
|
|
855
|
+
.prepare(
|
|
856
|
+
`SELECT id, name, slug, config, status, plan, db_path, owner_id,
|
|
857
|
+
created_at, updated_at, deleted_at
|
|
858
|
+
FROM saas_tenants ORDER BY created_at ASC`,
|
|
859
|
+
)
|
|
860
|
+
.all()) {
|
|
861
|
+
// One corrupt config cell must not sink the whole tenant list.
|
|
862
|
+
let config = null;
|
|
863
|
+
try {
|
|
864
|
+
config = r.config ? JSON.parse(r.config) : null;
|
|
865
|
+
} catch {
|
|
866
|
+
config = null;
|
|
867
|
+
}
|
|
868
|
+
_tenants.set(r.id, {
|
|
869
|
+
id: r.id,
|
|
870
|
+
name: r.name,
|
|
871
|
+
slug: r.slug,
|
|
872
|
+
config,
|
|
873
|
+
status: r.status,
|
|
874
|
+
plan: r.plan,
|
|
875
|
+
dbPath: r.db_path || null,
|
|
876
|
+
ownerId: r.owner_id || null,
|
|
877
|
+
createdAt: Number(r.created_at),
|
|
878
|
+
updatedAt: Number(r.updated_at),
|
|
879
|
+
deletedAt: r.deleted_at == null ? null : Number(r.deleted_at),
|
|
880
|
+
_seq: ++_seq,
|
|
881
|
+
});
|
|
882
|
+
if (r.slug) _slugIndex.set(r.slug, r.id);
|
|
883
|
+
_tenantSubs.set(r.id, new Set());
|
|
884
|
+
_tenantUsage.set(r.id, new Set());
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
for (const r of db
|
|
888
|
+
.prepare(
|
|
889
|
+
`SELECT id, tenant_id, metric, value, period, recorded_at
|
|
890
|
+
FROM saas_usage ORDER BY recorded_at ASC`,
|
|
891
|
+
)
|
|
892
|
+
.all()) {
|
|
893
|
+
_usage.set(r.id, {
|
|
894
|
+
id: r.id,
|
|
895
|
+
tenantId: r.tenant_id,
|
|
896
|
+
metric: r.metric,
|
|
897
|
+
value: Number(r.value),
|
|
898
|
+
period: r.period,
|
|
899
|
+
recordedAt: Number(r.recorded_at),
|
|
900
|
+
_seq: ++_seq,
|
|
901
|
+
});
|
|
902
|
+
if (!_tenantUsage.has(r.tenant_id))
|
|
903
|
+
_tenantUsage.set(r.tenant_id, new Set());
|
|
904
|
+
_tenantUsage.get(r.tenant_id).add(r.id);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
for (const r of db
|
|
908
|
+
.prepare(
|
|
909
|
+
`SELECT id, tenant_id, plan, status, started_at, expires_at, cancelled_at,
|
|
910
|
+
payment_method, amount, created_at
|
|
911
|
+
FROM saas_subscriptions ORDER BY created_at ASC`,
|
|
912
|
+
)
|
|
913
|
+
.all()) {
|
|
914
|
+
let paymentMethod = null;
|
|
915
|
+
try {
|
|
916
|
+
paymentMethod = r.payment_method ? JSON.parse(r.payment_method) : null;
|
|
917
|
+
} catch {
|
|
918
|
+
paymentMethod = null;
|
|
919
|
+
}
|
|
920
|
+
_subscriptions.set(r.id, {
|
|
921
|
+
id: r.id,
|
|
922
|
+
tenantId: r.tenant_id,
|
|
923
|
+
plan: r.plan,
|
|
924
|
+
status: r.status,
|
|
925
|
+
startedAt: Number(r.started_at),
|
|
926
|
+
expiresAt: r.expires_at == null ? null : Number(r.expires_at),
|
|
927
|
+
cancelledAt: r.cancelled_at == null ? null : Number(r.cancelled_at),
|
|
928
|
+
paymentMethod,
|
|
929
|
+
amount: r.amount == null ? null : Number(r.amount),
|
|
930
|
+
createdAt: Number(r.created_at),
|
|
931
|
+
_seq: ++_seq,
|
|
932
|
+
});
|
|
933
|
+
if (!_tenantSubs.has(r.tenant_id)) _tenantSubs.set(r.tenant_id, new Set());
|
|
934
|
+
_tenantSubs.get(r.tenant_id).add(r.id);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
return _tenants.size + _usage.size + _subscriptions.size;
|
|
938
|
+
}
|
|
939
|
+
|
|
833
940
|
/* ═══════════════════════════════════════════════════════════════
|
|
834
941
|
* Phase 97 V2 — Tenant Maturity + Subscription Lifecycle
|
|
835
942
|
* Strictly additive. Legacy surface above is preserved.
|
|
@@ -65,6 +65,73 @@ export function ensureTerraformTables(db) {
|
|
|
65
65
|
`);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Rehydrate _workspaces/_runs from the persisted terraform_workspaces/
|
|
70
|
+
* terraform_runs tables. The `cc` CLI runs every command in a fresh process, so
|
|
71
|
+
* without this the Maps start empty and a workspace/run created in a prior
|
|
72
|
+
* invocation is invisible (`cc terraform workspaces`/`runs` show nothing;
|
|
73
|
+
* `cc terraform plan <id>` throws "Workspace not found" for a persisted
|
|
74
|
+
* workspace). Call after ensureTerraformTables(db).
|
|
75
|
+
*/
|
|
76
|
+
export function loadFromDb(db) {
|
|
77
|
+
if (!db) return 0;
|
|
78
|
+
_workspaces.clear();
|
|
79
|
+
_runs.clear();
|
|
80
|
+
|
|
81
|
+
const wsRows = db.prepare(`SELECT * FROM terraform_workspaces`).all();
|
|
82
|
+
for (const row of wsRows) {
|
|
83
|
+
let variables = {};
|
|
84
|
+
let providers = [];
|
|
85
|
+
try {
|
|
86
|
+
variables = row.variables ? JSON.parse(row.variables) : {};
|
|
87
|
+
} catch {
|
|
88
|
+
variables = {};
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
providers = row.providers ? JSON.parse(row.providers) : [];
|
|
92
|
+
} catch {
|
|
93
|
+
providers = [];
|
|
94
|
+
}
|
|
95
|
+
_workspaces.set(row.id, {
|
|
96
|
+
id: row.id,
|
|
97
|
+
name: row.name,
|
|
98
|
+
description: row.description ?? "",
|
|
99
|
+
terraformVersion: row.terraform_version,
|
|
100
|
+
workingDirectory: row.working_directory,
|
|
101
|
+
autoApply: !!row.auto_apply,
|
|
102
|
+
status: row.status,
|
|
103
|
+
lastRunId: row.last_run_id ?? null,
|
|
104
|
+
lastRunAt: row.last_run_at ?? null,
|
|
105
|
+
stateVersion: row.state_version ?? 0,
|
|
106
|
+
variables,
|
|
107
|
+
providers,
|
|
108
|
+
createdAt: row.created_at ?? null,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const runRows = db.prepare(`SELECT * FROM terraform_runs`).all();
|
|
113
|
+
for (const row of runRows) {
|
|
114
|
+
_runs.set(row.id, {
|
|
115
|
+
id: row.id,
|
|
116
|
+
workspaceId: row.workspace_id,
|
|
117
|
+
runType: row.run_type,
|
|
118
|
+
status: row.status,
|
|
119
|
+
planOutput: row.plan_output ?? null,
|
|
120
|
+
applyOutput: row.apply_output ?? null,
|
|
121
|
+
resourcesAdded: row.resources_added ?? 0,
|
|
122
|
+
resourcesChanged: row.resources_changed ?? 0,
|
|
123
|
+
resourcesDestroyed: row.resources_destroyed ?? 0,
|
|
124
|
+
triggeredBy: row.triggered_by ?? null,
|
|
125
|
+
startedAt: row.started_at ?? null,
|
|
126
|
+
completedAt: row.completed_at ?? null,
|
|
127
|
+
errorMessage: row.error_message ?? null,
|
|
128
|
+
createdAt: row.created_at ?? null,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return _workspaces.size + _runs.size;
|
|
133
|
+
}
|
|
134
|
+
|
|
68
135
|
/* ── Workspace Management ─────────────────────────────────── */
|
|
69
136
|
|
|
70
137
|
export function listWorkspaces(filter = {}) {
|