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
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Remote Session vendor push — Xiaomi (小米) push sender.
|
|
2
|
+
//
|
|
3
|
+
// A concrete implementation of the RemoteSessionPushDispatcher `sender` contract
|
|
4
|
+
// for MIUI devices, using the Xiaomi Push server API. Unlike FCM/APNs there is
|
|
5
|
+
// no JWT — auth is a static app AppSecret in the `Authorization: key=` header —
|
|
6
|
+
// so this sender is a straight form-encoded POST over plain HTTPS with an
|
|
7
|
+
// injectable `fetch` (default global), fully unit-testable with a fake
|
|
8
|
+
// transport. The payload carries only routing ids (no session content).
|
|
9
|
+
|
|
10
|
+
import { PushTokenUnregisteredError } from "./remote-session-push-errors.js";
|
|
11
|
+
|
|
12
|
+
const DEFAULT_HOST = "https://api.xmpush.xiaomi.com";
|
|
13
|
+
const SEND_PATH = "/v3/message/regid";
|
|
14
|
+
|
|
15
|
+
// Xiaomi does not use a single canonical "unregistered" code; match the reason
|
|
16
|
+
// text it returns for a stale/invalid registration id.
|
|
17
|
+
const INVALID_TOKEN_RE = /invalid|not valid|unregist|not ?exist|无效|不存在/i;
|
|
18
|
+
|
|
19
|
+
/** Sends one notification to a Xiaomi registration id. */
|
|
20
|
+
export class XiaomiPushSender {
|
|
21
|
+
constructor(options = {}) {
|
|
22
|
+
if (!options.appSecret) {
|
|
23
|
+
throw new Error("XiaomiPushSender requires an appSecret");
|
|
24
|
+
}
|
|
25
|
+
if (!options.packageName) {
|
|
26
|
+
throw new Error("XiaomiPushSender requires a packageName");
|
|
27
|
+
}
|
|
28
|
+
this.appSecret = options.appSecret;
|
|
29
|
+
this.packageName = options.packageName;
|
|
30
|
+
this.host = options.host || DEFAULT_HOST;
|
|
31
|
+
this.fetch = options.fetch || globalThis.fetch;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Bound function matching the dispatcher's `sender` contract. */
|
|
35
|
+
get handler() {
|
|
36
|
+
return (payload) => this.send(payload);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async send({ token, notification, sessionId, clientId } = {}) {
|
|
40
|
+
if (!token) throw new Error("Xiaomi send requires a registration id");
|
|
41
|
+
const params = new URLSearchParams({
|
|
42
|
+
registration_id: token,
|
|
43
|
+
restricted_package_name: this.packageName,
|
|
44
|
+
pass_through: "0", // 0 = show a notification, 1 = data-only
|
|
45
|
+
notify_type: "-1", // default sound/vibrate
|
|
46
|
+
title: notification?.title || "Approval requested",
|
|
47
|
+
description: notification?.body || "A coding session needs your approval",
|
|
48
|
+
});
|
|
49
|
+
// Routing ids only — no session content.
|
|
50
|
+
const payload = { type: "remote-session.approval-request" };
|
|
51
|
+
if (sessionId != null) payload.sessionId = String(sessionId);
|
|
52
|
+
if (clientId != null) payload.clientId = String(clientId);
|
|
53
|
+
params.set("payload", JSON.stringify(payload));
|
|
54
|
+
|
|
55
|
+
const res = await this.fetch(`${this.host}${SEND_PATH}`, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: {
|
|
58
|
+
Authorization: `key=${this.appSecret}`,
|
|
59
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
60
|
+
},
|
|
61
|
+
body: params.toString(),
|
|
62
|
+
});
|
|
63
|
+
const json = await res.json().catch(() => ({}));
|
|
64
|
+
if (res.ok && json.result === "ok" && Number(json.code) === 0) {
|
|
65
|
+
return { id: json.data?.id || null };
|
|
66
|
+
}
|
|
67
|
+
const reason = json.reason || json.description || `HTTP ${res.status}`;
|
|
68
|
+
if (INVALID_TOKEN_RE.test(String(reason))) {
|
|
69
|
+
throw new PushTokenUnregisteredError(
|
|
70
|
+
`Xiaomi registration id invalid: ${reason}`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
throw new Error(`Xiaomi push failed: ${reason}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Build a bound Xiaomi `sender` from env, or null when unconfigured.
|
|
79
|
+
*
|
|
80
|
+
* Xiaomi env:
|
|
81
|
+
* CHAINLESSCHAIN_REMOTE_SESSION_XIAOMI_APP_SECRET
|
|
82
|
+
* CHAINLESSCHAIN_REMOTE_SESSION_XIAOMI_PACKAGE_NAME
|
|
83
|
+
* CHAINLESSCHAIN_REMOTE_SESSION_XIAOMI_HOST (optional; e.g. the global host)
|
|
84
|
+
*/
|
|
85
|
+
export function createXiaomiPushSender(env = {}, options = {}) {
|
|
86
|
+
const appSecret =
|
|
87
|
+
options.appSecret || env.CHAINLESSCHAIN_REMOTE_SESSION_XIAOMI_APP_SECRET;
|
|
88
|
+
const packageName =
|
|
89
|
+
options.packageName ||
|
|
90
|
+
env.CHAINLESSCHAIN_REMOTE_SESSION_XIAOMI_PACKAGE_NAME;
|
|
91
|
+
if (!appSecret || !packageName) return null;
|
|
92
|
+
const host = options.host || env.CHAINLESSCHAIN_REMOTE_SESSION_XIAOMI_HOST;
|
|
93
|
+
return new XiaomiPushSender({
|
|
94
|
+
appSecret,
|
|
95
|
+
packageName,
|
|
96
|
+
host,
|
|
97
|
+
...options,
|
|
98
|
+
}).handler;
|
|
99
|
+
}
|
|
@@ -629,19 +629,29 @@ function _conflictStatusCode(repoDir, filePath) {
|
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
function _mapConflictType(statusCode) {
|
|
632
|
+
// NOTE: the porcelain XY code is reported relative to the ACTUAL merge, which
|
|
633
|
+
// previewWorktreeMerge/applyWorktreeAutomationCandidate run as `git merge
|
|
634
|
+
// <base>` INSIDE the agent worktree — i.e. ours=agent, theirs=base, the
|
|
635
|
+
// REVERSE of the "current merges in the agent branch" direction the candidate
|
|
636
|
+
// labels/suggestions describe. For symmetric codes (UU/AA) direction is
|
|
637
|
+
// irrelevant. For the asymmetric delete/add codes the U/D (us/them) halves
|
|
638
|
+
// must be swapped back to the label direction, otherwise the "keep the file"
|
|
639
|
+
// candidate checks out the side that DELETED it (`git checkout --ours/--theirs`
|
|
640
|
+
// → "path does not have our/their version") and throws — leaving no automated
|
|
641
|
+
// way to preserve the surviving file.
|
|
632
642
|
switch (statusCode) {
|
|
633
643
|
case "UU":
|
|
634
644
|
return "both_modified";
|
|
635
645
|
case "AA":
|
|
636
646
|
return "both_added";
|
|
637
|
-
case "DU":
|
|
638
|
-
return "deleted_by_us";
|
|
639
|
-
case "UD":
|
|
647
|
+
case "DU": // ours(agent) deleted, theirs(base) modified
|
|
640
648
|
return "deleted_by_them";
|
|
641
|
-
case "
|
|
642
|
-
return "
|
|
643
|
-
case "
|
|
649
|
+
case "UD": // ours(agent) modified, theirs(base) deleted
|
|
650
|
+
return "deleted_by_us";
|
|
651
|
+
case "AU": // added by ours(agent)
|
|
644
652
|
return "added_by_them";
|
|
653
|
+
case "UA": // added by theirs(base)
|
|
654
|
+
return "added_by_us";
|
|
645
655
|
default:
|
|
646
656
|
return "unmerged";
|
|
647
657
|
}
|
package/src/index.js
CHANGED
|
@@ -17,6 +17,8 @@ import { registerAskCommand } from "./commands/ask.js";
|
|
|
17
17
|
import { registerLlmCommand } from "./commands/llm.js";
|
|
18
18
|
import { registerHubCommand } from "./commands/hub.js";
|
|
19
19
|
import { registerAndroidCommand } from "./commands/android.js";
|
|
20
|
+
import { registerEvalCommand } from "./commands/eval.js";
|
|
21
|
+
import { registerTeamCommand } from "./commands/team.js";
|
|
20
22
|
import {
|
|
21
23
|
registerAgentCommand,
|
|
22
24
|
registerSubAgentV2Command,
|
|
@@ -58,6 +60,7 @@ import { registerRCacheCommand } from "./commands/rcache.js";
|
|
|
58
60
|
import { registerSessionCommand } from "./commands/session.js";
|
|
59
61
|
import { registerCostCommand } from "./commands/cost.js";
|
|
60
62
|
import { registerContextCommand } from "./commands/context.js";
|
|
63
|
+
import { registerCodeIntelCommand } from "./commands/codeintel.js";
|
|
61
64
|
import { registerCheckpointCommand } from "./commands/checkpoint.js";
|
|
62
65
|
import { registerGoalCommand } from "./commands/goal.js";
|
|
63
66
|
import { registerCommandCommand } from "./commands/command.js";
|
|
@@ -428,6 +431,8 @@ export function createProgram(opts = {}) {
|
|
|
428
431
|
registerHubCommand(program);
|
|
429
432
|
registerAndroidCommand(program);
|
|
430
433
|
registerAgentCommand(program);
|
|
434
|
+
registerEvalCommand(program);
|
|
435
|
+
registerTeamCommand(program);
|
|
431
436
|
registerSubAgentV2Command(program);
|
|
432
437
|
registerExecBackendV2Command(program);
|
|
433
438
|
registerTodoV2Command(program);
|
|
@@ -468,6 +473,7 @@ export function createProgram(opts = {}) {
|
|
|
468
473
|
registerSessionCommand(program);
|
|
469
474
|
registerCostCommand(program);
|
|
470
475
|
registerContextCommand(program);
|
|
476
|
+
registerCodeIntelCommand(program);
|
|
471
477
|
registerCheckpointCommand(program);
|
|
472
478
|
registerGoalCommand(program);
|
|
473
479
|
registerCommandCommand(program);
|
|
@@ -70,9 +70,12 @@ describe("quiet mode", () => {
|
|
|
70
70
|
expect(logSpy).not.toHaveBeenCalled();
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
it("does NOT suppress warn (
|
|
73
|
+
it("does NOT suppress warn (writes to console.error/stderr)", () => {
|
|
74
74
|
warn("careful");
|
|
75
|
-
|
|
75
|
+
// warn goes to stderr (not stdout) so it never pollutes machine-readable
|
|
76
|
+
// stdout like `--json`; still never suppressed by quiet mode.
|
|
77
|
+
expect(errSpy).toHaveBeenCalledTimes(1);
|
|
78
|
+
expect(logSpy).not.toHaveBeenCalled();
|
|
76
79
|
});
|
|
77
80
|
|
|
78
81
|
it("does NOT suppress error", () => {
|
package/src/lib/a2a-protocol.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* capability negotiation, and peer discovery.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
// Safe JSON-array parse for values read back from the DB (capabilities / skills /
|
|
10
9
|
// history / artifacts are stored as JSON strings). Written via JSON.stringify so
|
|
11
10
|
// normally valid, but a corrupted or externally-edited DB must not crash agent
|
|
@@ -523,6 +522,31 @@ export function getCardStatusV2(cardId) {
|
|
|
523
522
|
return _v2Cards.get(cardId)?.status || "active";
|
|
524
523
|
}
|
|
525
524
|
|
|
525
|
+
/**
|
|
526
|
+
* Hydrate the in-memory _v2Cards Map from the DB. The CLI is one-shot: _v2Cards
|
|
527
|
+
* starts empty every process, so getCardStatusV2 always fell back to "active"
|
|
528
|
+
* and setCardStatus validated transitions against a phantom "active" prev-state
|
|
529
|
+
* — even though setCardStatus dual-writes the real status to a2a_agent_cards
|
|
530
|
+
* (which `peers`/`discover` read correctly). Call after ensureA2ATables(db)
|
|
531
|
+
* before reading or transitioning a persisted card's status.
|
|
532
|
+
*/
|
|
533
|
+
export function loadCardsFromDb(db) {
|
|
534
|
+
if (!db) return 0;
|
|
535
|
+
ensureA2ATables(db);
|
|
536
|
+
_v2Cards.clear();
|
|
537
|
+
const rows = db
|
|
538
|
+
.prepare(`SELECT id, status, updated_at FROM a2a_agent_cards`)
|
|
539
|
+
.all();
|
|
540
|
+
for (const r of rows) {
|
|
541
|
+
_v2Cards.set(r.id, {
|
|
542
|
+
cardId: r.id,
|
|
543
|
+
status: r.status || "active",
|
|
544
|
+
updatedAt: r.updated_at,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
return _v2Cards.size;
|
|
548
|
+
}
|
|
549
|
+
|
|
526
550
|
// ─── Task lifecycle V2 ───────────────────────────────────────────
|
|
527
551
|
|
|
528
552
|
/**
|
|
@@ -62,6 +62,67 @@ export function ensureActivityPubTables(db) {
|
|
|
62
62
|
`);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Rehydrate _actors/_activities/_follows from the persisted ap_actors/
|
|
67
|
+
* ap_activities/ap_follows tables. The `cc` CLI runs every command in a fresh
|
|
68
|
+
* process, so without this the Maps start empty and an actor created / note
|
|
69
|
+
* published / follow made in a prior invocation is invisible (`cc ap actor
|
|
70
|
+
* list`/`outbox`/`followers`/`search` return nothing, and read paths first hit
|
|
71
|
+
* _requireActor against the empty _actors → "Actor not found"). Call after
|
|
72
|
+
* ensureActivityPubTables(db).
|
|
73
|
+
*/
|
|
74
|
+
export function loadFromDb(db) {
|
|
75
|
+
if (!db) return 0;
|
|
76
|
+
_actors.clear();
|
|
77
|
+
_activities.clear();
|
|
78
|
+
_follows.clear();
|
|
79
|
+
|
|
80
|
+
const actorRows = db.prepare(`SELECT * FROM ap_actors`).all();
|
|
81
|
+
for (const row of actorRows) {
|
|
82
|
+
const id = row.id;
|
|
83
|
+
// Derived fields (type/preferredUsername/inbox/outbox/followers/following)
|
|
84
|
+
// are not persisted — reconstruct them from id exactly as createActor does.
|
|
85
|
+
_actors.set(id, {
|
|
86
|
+
id,
|
|
87
|
+
type: "Person",
|
|
88
|
+
username: row.username ?? null,
|
|
89
|
+
preferredUsername: row.username ?? null,
|
|
90
|
+
name: row.name ?? null,
|
|
91
|
+
summary: row.summary ?? null,
|
|
92
|
+
inbox: row.inbox_url ?? `${id}/inbox`,
|
|
93
|
+
outbox: row.outbox_url ?? `${id}/outbox`,
|
|
94
|
+
followers: `${id}/followers`,
|
|
95
|
+
following: `${id}/following`,
|
|
96
|
+
isLocal: !!row.is_local,
|
|
97
|
+
createdAt: row.created_at ?? null,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const activityRows = db.prepare(`SELECT * FROM ap_activities`).all();
|
|
102
|
+
for (const row of activityRows) {
|
|
103
|
+
let activity;
|
|
104
|
+
try {
|
|
105
|
+
activity = row.object_json ? JSON.parse(row.object_json) : null;
|
|
106
|
+
} catch {
|
|
107
|
+
activity = null;
|
|
108
|
+
}
|
|
109
|
+
if (!activity || !activity.id) continue; // can't reconstruct without it
|
|
110
|
+
_activities.set(activity.id, {
|
|
111
|
+
direction: row.direction,
|
|
112
|
+
ownerId: row.owner_id,
|
|
113
|
+
activity,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const followRows = db.prepare(`SELECT * FROM ap_follows`).all();
|
|
118
|
+
for (const row of followRows) {
|
|
119
|
+
const key = `${row.follower_id}|${row.followee_id}`;
|
|
120
|
+
_follows.set(key, { state: row.state, createdAt: row.created_at ?? null });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return _actors.size + _activities.size + _follows.size;
|
|
124
|
+
}
|
|
125
|
+
|
|
65
126
|
/* ── Helpers ───────────────────────────────────────────────── */
|
|
66
127
|
|
|
67
128
|
function _now() {
|
package/src/lib/agent-core.js
CHANGED
|
@@ -28,6 +28,7 @@ export {
|
|
|
28
28
|
listBackgroundShellTasks,
|
|
29
29
|
killBackgroundShellTask,
|
|
30
30
|
killAllBackgroundShellTasks,
|
|
31
|
+
killAllBackgroundShellTasksSync,
|
|
31
32
|
reapIdleBackgroundShellTasks,
|
|
32
33
|
_ingestSearchOutput,
|
|
33
34
|
writeFileVerified,
|
|
@@ -42,4 +43,7 @@ export {
|
|
|
42
43
|
_toAnthropicMessages,
|
|
43
44
|
_anthropicThinkingParams,
|
|
44
45
|
_normalizeAnthropicResponse,
|
|
46
|
+
_resetFileFreshness,
|
|
47
|
+
_getSharedCodeIntel,
|
|
48
|
+
disposeSharedCodeIntel,
|
|
45
49
|
} from "../runtime/agent-core.js";
|
package/src/lib/agent-economy.js
CHANGED
|
@@ -109,34 +109,58 @@ export function getBalance(agentId) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
export function pay(db, fromAgent, toAgent, amount, description) {
|
|
112
|
-
if (amount
|
|
112
|
+
if (!Number.isFinite(amount) || amount <= 0)
|
|
113
|
+
throw new Error("Amount must be positive");
|
|
113
114
|
|
|
114
115
|
const fromBal = _getBalance(fromAgent);
|
|
115
116
|
if (fromBal.balance < amount) {
|
|
116
117
|
throw new Error(`Insufficient balance: ${fromBal.balance} < ${amount}`);
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
fromBal.balance -= amount;
|
|
120
120
|
const toBal = _getBalance(toAgent);
|
|
121
|
+
|
|
122
|
+
// The ledger row, the debit and the credit must all land or none of them.
|
|
123
|
+
// Without a transaction a mid-way failure would debit the sender without
|
|
124
|
+
// crediting the receiver (tokens vanish); the CLI re-hydrates from these
|
|
125
|
+
// tables, so the loss would persist.
|
|
126
|
+
const fromSnap = { balance: fromBal.balance, locked: fromBal.locked };
|
|
127
|
+
const toSnap = { balance: toBal.balance, locked: toBal.locked };
|
|
128
|
+
|
|
129
|
+
fromBal.balance -= amount;
|
|
121
130
|
toBal.balance += amount;
|
|
122
131
|
|
|
123
132
|
const txId = crypto.randomUUID();
|
|
124
133
|
const now = new Date().toISOString();
|
|
125
134
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
135
|
+
const applyWrites = () => {
|
|
136
|
+
db.prepare(
|
|
137
|
+
`INSERT INTO economy_transactions (id, from_agent, to_agent, amount, type, description, created_at)
|
|
138
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
139
|
+
).run(txId, fromAgent, toAgent, amount, "transfer", description || "", now);
|
|
130
140
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
141
|
+
db.prepare(
|
|
142
|
+
`INSERT OR REPLACE INTO economy_balances (agent_id, balance, locked, updated_at)
|
|
143
|
+
VALUES (?, ?, ?, ?)`,
|
|
144
|
+
).run(fromAgent, fromBal.balance, fromBal.locked, now);
|
|
135
145
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
db.prepare(
|
|
147
|
+
`INSERT OR REPLACE INTO economy_balances (agent_id, balance, locked, updated_at)
|
|
148
|
+
VALUES (?, ?, ?, ?)`,
|
|
149
|
+
).run(toAgent, toBal.balance, toBal.locked, now);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
if (db && typeof db.transaction === "function") {
|
|
154
|
+
db.transaction(applyWrites)();
|
|
155
|
+
} else {
|
|
156
|
+
applyWrites();
|
|
157
|
+
}
|
|
158
|
+
} catch (err) {
|
|
159
|
+
// Roll the in-memory balances back to match the rolled-back DB.
|
|
160
|
+
Object.assign(fromBal, fromSnap);
|
|
161
|
+
Object.assign(toBal, toSnap);
|
|
162
|
+
throw err;
|
|
163
|
+
}
|
|
140
164
|
|
|
141
165
|
return {
|
|
142
166
|
txId,
|
|
@@ -158,6 +182,7 @@ export function openChannel(db, partyA, partyB, depositA) {
|
|
|
158
182
|
);
|
|
159
183
|
}
|
|
160
184
|
|
|
185
|
+
const balSnap = { balance: balA.balance, locked: balA.locked };
|
|
161
186
|
if (deposit > 0) {
|
|
162
187
|
balA.balance -= deposit;
|
|
163
188
|
balA.locked += deposit;
|
|
@@ -174,12 +199,35 @@ export function openChannel(db, partyA, partyB, depositA) {
|
|
|
174
199
|
status: "open",
|
|
175
200
|
createdAt: now,
|
|
176
201
|
};
|
|
177
|
-
_channels.set(id, channel);
|
|
178
202
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
203
|
+
// Persist the channel row AND the deposit debit together. Persisting only the
|
|
204
|
+
// channel (as before) left the locked deposit still fully available in
|
|
205
|
+
// economy_balances after the next process re-hydrates — double-counted, so a
|
|
206
|
+
// party could lock a deposit and still spend the same funds via pay().
|
|
207
|
+
const applyWrites = () => {
|
|
208
|
+
db.prepare(
|
|
209
|
+
`INSERT INTO economy_channels (id, party_a, party_b, balance_a, balance_b, status, created_at)
|
|
210
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
211
|
+
).run(id, partyA, partyB, deposit, 0, "open", now);
|
|
212
|
+
if (deposit > 0) {
|
|
213
|
+
db.prepare(
|
|
214
|
+
`INSERT OR REPLACE INTO economy_balances (agent_id, balance, locked, updated_at)
|
|
215
|
+
VALUES (?, ?, ?, ?)`,
|
|
216
|
+
).run(partyA, balA.balance, balA.locked, now);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
if (db && typeof db.transaction === "function") {
|
|
222
|
+
db.transaction(applyWrites)();
|
|
223
|
+
} else {
|
|
224
|
+
applyWrites();
|
|
225
|
+
}
|
|
226
|
+
_channels.set(id, channel);
|
|
227
|
+
} catch (err) {
|
|
228
|
+
Object.assign(balA, balSnap);
|
|
229
|
+
throw err;
|
|
230
|
+
}
|
|
183
231
|
|
|
184
232
|
return channel;
|
|
185
233
|
}
|
|
@@ -189,18 +237,49 @@ export function closeChannel(db, channelId) {
|
|
|
189
237
|
if (!channel) throw new Error(`Channel not found: ${channelId}`);
|
|
190
238
|
if (channel.status === "closed") throw new Error("Channel already closed");
|
|
191
239
|
|
|
192
|
-
channel.status = "closed";
|
|
193
|
-
|
|
194
|
-
// Settle: return balances to parties
|
|
195
240
|
const balA = _getBalance(channel.partyA);
|
|
196
241
|
const balB = _getBalance(channel.partyB);
|
|
242
|
+
const aSnap = { balance: balA.balance, locked: balA.locked };
|
|
243
|
+
const bSnap = { balance: balB.balance, locked: balB.locked };
|
|
244
|
+
const prevStatus = channel.status;
|
|
245
|
+
|
|
246
|
+
channel.status = "closed";
|
|
247
|
+
// Settle: return balances to parties.
|
|
197
248
|
balA.balance += channel.balanceA;
|
|
198
249
|
balA.locked = Math.max(0, balA.locked - channel.balanceA);
|
|
199
250
|
balB.balance += channel.balanceB;
|
|
200
251
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
252
|
+
const now = new Date().toISOString();
|
|
253
|
+
// Persist the settled balances alongside the status flip. Previously only the
|
|
254
|
+
// channel status was written, so the returned deposit was lost on re-hydrate.
|
|
255
|
+
const persistBal = (agentId, bal) =>
|
|
256
|
+
db
|
|
257
|
+
.prepare(
|
|
258
|
+
`INSERT OR REPLACE INTO economy_balances (agent_id, balance, locked, updated_at)
|
|
259
|
+
VALUES (?, ?, ?, ?)`,
|
|
260
|
+
)
|
|
261
|
+
.run(agentId, bal.balance, bal.locked, now);
|
|
262
|
+
|
|
263
|
+
const applyWrites = () => {
|
|
264
|
+
db.prepare(
|
|
265
|
+
`UPDATE economy_channels SET status = 'closed' WHERE id = ?`,
|
|
266
|
+
).run(channelId);
|
|
267
|
+
persistBal(channel.partyA, balA);
|
|
268
|
+
if (channel.partyB !== channel.partyA) persistBal(channel.partyB, balB);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
if (db && typeof db.transaction === "function") {
|
|
273
|
+
db.transaction(applyWrites)();
|
|
274
|
+
} else {
|
|
275
|
+
applyWrites();
|
|
276
|
+
}
|
|
277
|
+
} catch (err) {
|
|
278
|
+
Object.assign(balA, aSnap);
|
|
279
|
+
Object.assign(balB, bSnap);
|
|
280
|
+
channel.status = prevStatus;
|
|
281
|
+
throw err;
|
|
282
|
+
}
|
|
204
283
|
|
|
205
284
|
return { ...channel };
|
|
206
285
|
}
|
|
@@ -257,9 +336,11 @@ export function getMarketListings(filter) {
|
|
|
257
336
|
return listings;
|
|
258
337
|
}
|
|
259
338
|
|
|
260
|
-
export function tradeResource(listingId, buyer, quantity) {
|
|
339
|
+
export function tradeResource(db, listingId, buyer, quantity) {
|
|
261
340
|
const listing = _market.get(listingId);
|
|
262
341
|
if (!listing) throw new Error(`Listing not found: ${listingId}`);
|
|
342
|
+
if (!Number.isFinite(quantity) || quantity <= 0)
|
|
343
|
+
throw new Error("Quantity must be positive");
|
|
263
344
|
if (listing.available < quantity) {
|
|
264
345
|
throw new Error(
|
|
265
346
|
`Insufficient availability: ${listing.available} < ${quantity}`,
|
|
@@ -272,13 +353,52 @@ export function tradeResource(listingId, buyer, quantity) {
|
|
|
272
353
|
throw new Error(`Insufficient balance: ${buyerBal.balance} < ${cost}`);
|
|
273
354
|
}
|
|
274
355
|
|
|
275
|
-
buyerBal.balance -= cost;
|
|
276
356
|
const sellerBal = _getBalance(listing.provider);
|
|
357
|
+
const buyerSnap = { balance: buyerBal.balance, locked: buyerBal.locked };
|
|
358
|
+
const sellerSnap = { balance: sellerBal.balance, locked: sellerBal.locked };
|
|
359
|
+
const listingSnap = { available: listing.available, status: listing.status };
|
|
360
|
+
|
|
361
|
+
buyerBal.balance -= cost;
|
|
277
362
|
sellerBal.balance += cost;
|
|
278
363
|
listing.available -= quantity;
|
|
279
|
-
|
|
280
364
|
if (listing.available <= 0) listing.status = "sold_out";
|
|
281
365
|
|
|
366
|
+
const now = new Date().toISOString();
|
|
367
|
+
// Persist the money movement and the listing depletion. Previously this
|
|
368
|
+
// mutated only the in-memory Maps (the fn took no db at all), so a trade
|
|
369
|
+
// reported success but never survived the next process re-hydrate — the
|
|
370
|
+
// buyer was never charged, the seller never paid, and the listing never
|
|
371
|
+
// depleted (unlimited free re-purchases). Sibling listResource/pay persist.
|
|
372
|
+
const persistBal = (agentId, bal) =>
|
|
373
|
+
db
|
|
374
|
+
.prepare(
|
|
375
|
+
`INSERT OR REPLACE INTO economy_balances (agent_id, balance, locked, updated_at)
|
|
376
|
+
VALUES (?, ?, ?, ?)`,
|
|
377
|
+
)
|
|
378
|
+
.run(agentId, bal.balance, bal.locked, now);
|
|
379
|
+
|
|
380
|
+
const applyWrites = () => {
|
|
381
|
+
persistBal(buyer, buyerBal);
|
|
382
|
+
if (listing.provider !== buyer) persistBal(listing.provider, sellerBal);
|
|
383
|
+
db.prepare(
|
|
384
|
+
`UPDATE economy_market SET available = ?, status = ? WHERE id = ?`,
|
|
385
|
+
).run(listing.available, listing.status, listingId);
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
if (db && typeof db.transaction === "function") {
|
|
390
|
+
db.transaction(applyWrites)();
|
|
391
|
+
} else if (db) {
|
|
392
|
+
applyWrites();
|
|
393
|
+
}
|
|
394
|
+
} catch (err) {
|
|
395
|
+
// Roll the in-memory Maps back to match the rolled-back DB.
|
|
396
|
+
Object.assign(buyerBal, buyerSnap);
|
|
397
|
+
Object.assign(sellerBal, sellerSnap);
|
|
398
|
+
Object.assign(listing, listingSnap);
|
|
399
|
+
throw err;
|
|
400
|
+
}
|
|
401
|
+
|
|
282
402
|
return { listingId, buyer, quantity, cost, remaining: listing.available };
|
|
283
403
|
}
|
|
284
404
|
|
|
@@ -332,7 +452,8 @@ export function getContributions(agentId) {
|
|
|
332
452
|
export function distributeRevenue(db, pool, agentIds) {
|
|
333
453
|
if (!agentIds || agentIds.length === 0)
|
|
334
454
|
throw new Error("No agents specified");
|
|
335
|
-
if (pool
|
|
455
|
+
if (!Number.isFinite(pool) || pool <= 0)
|
|
456
|
+
throw new Error("Pool must be positive");
|
|
336
457
|
|
|
337
458
|
const share = pool / agentIds.length;
|
|
338
459
|
const results = [];
|
|
@@ -364,6 +485,118 @@ export function _resetState() {
|
|
|
364
485
|
_priceList.clear();
|
|
365
486
|
}
|
|
366
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Rehydrate the DB-backed in-memory Maps from the economy_* tables. The CLI runs
|
|
490
|
+
* each `cc economy` subcommand in a fresh node process, so these module-level
|
|
491
|
+
* Maps start empty every invocation. Every write dual-writes (Map + INSERT into
|
|
492
|
+
* economy_balances/channels/market/nfts/contributions) but every read
|
|
493
|
+
* (getBalance/getMarketListings/closeChannel/tradeResource/getContributions) is
|
|
494
|
+
* Map-only and nothing SELECTed the tables back — so `balance` read back 0, and
|
|
495
|
+
* `channel close`/`trade` threw "not found" for rows that genuinely exist on
|
|
496
|
+
* disk. Call after ensureEconomyTables(db).
|
|
497
|
+
*
|
|
498
|
+
* `_priceList` has no table and stays in-memory (out of scope).
|
|
499
|
+
*/
|
|
500
|
+
export function loadFromDb(db) {
|
|
501
|
+
if (!db) return 0;
|
|
502
|
+
ensureEconomyTables(db);
|
|
503
|
+
_balances.clear();
|
|
504
|
+
_channels.clear();
|
|
505
|
+
_market.clear();
|
|
506
|
+
_nfts.clear();
|
|
507
|
+
_contributions.clear();
|
|
508
|
+
|
|
509
|
+
for (const r of db
|
|
510
|
+
.prepare(`SELECT agent_id, balance, locked FROM economy_balances`)
|
|
511
|
+
.all()) {
|
|
512
|
+
_balances.set(r.agent_id, {
|
|
513
|
+
balance: Number(r.balance) || 0,
|
|
514
|
+
locked: Number(r.locked) || 0,
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
for (const r of db
|
|
519
|
+
.prepare(
|
|
520
|
+
`SELECT id, party_a, party_b, balance_a, balance_b, status, created_at
|
|
521
|
+
FROM economy_channels ORDER BY created_at ASC`,
|
|
522
|
+
)
|
|
523
|
+
.all()) {
|
|
524
|
+
_channels.set(r.id, {
|
|
525
|
+
id: r.id,
|
|
526
|
+
partyA: r.party_a,
|
|
527
|
+
partyB: r.party_b,
|
|
528
|
+
balanceA: Number(r.balance_a) || 0,
|
|
529
|
+
balanceB: Number(r.balance_b) || 0,
|
|
530
|
+
status: r.status,
|
|
531
|
+
createdAt: r.created_at,
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
for (const r of db
|
|
536
|
+
.prepare(
|
|
537
|
+
`SELECT id, resource_type, provider, price, available, unit, status, created_at
|
|
538
|
+
FROM economy_market ORDER BY created_at ASC`,
|
|
539
|
+
)
|
|
540
|
+
.all()) {
|
|
541
|
+
_market.set(r.id, {
|
|
542
|
+
id: r.id,
|
|
543
|
+
resourceType: r.resource_type,
|
|
544
|
+
provider: r.provider,
|
|
545
|
+
price: Number(r.price),
|
|
546
|
+
available: Number(r.available) || 0,
|
|
547
|
+
unit: r.unit || "unit",
|
|
548
|
+
status: r.status,
|
|
549
|
+
createdAt: r.created_at,
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
for (const r of db
|
|
554
|
+
.prepare(
|
|
555
|
+
`SELECT id, owner, type, metadata, created_at FROM economy_nfts ORDER BY created_at ASC`,
|
|
556
|
+
)
|
|
557
|
+
.all()) {
|
|
558
|
+
// One corrupt metadata cell must not sink the whole NFT load.
|
|
559
|
+
let metadata = {};
|
|
560
|
+
try {
|
|
561
|
+
metadata = r.metadata ? JSON.parse(r.metadata) : {};
|
|
562
|
+
} catch {
|
|
563
|
+
metadata = {};
|
|
564
|
+
}
|
|
565
|
+
_nfts.set(r.id, {
|
|
566
|
+
id: r.id,
|
|
567
|
+
owner: r.owner,
|
|
568
|
+
type: r.type,
|
|
569
|
+
metadata,
|
|
570
|
+
createdAt: r.created_at,
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
for (const r of db
|
|
575
|
+
.prepare(
|
|
576
|
+
`SELECT id, agent_id, type, value, proof, created_at
|
|
577
|
+
FROM economy_contributions ORDER BY created_at ASC`,
|
|
578
|
+
)
|
|
579
|
+
.all()) {
|
|
580
|
+
if (!_contributions.has(r.agent_id)) _contributions.set(r.agent_id, []);
|
|
581
|
+
_contributions.get(r.agent_id).push({
|
|
582
|
+
id: r.id,
|
|
583
|
+
agentId: r.agent_id,
|
|
584
|
+
type: r.type,
|
|
585
|
+
value: Number(r.value) || 0,
|
|
586
|
+
proof: r.proof || "",
|
|
587
|
+
createdAt: r.created_at,
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return (
|
|
592
|
+
_balances.size +
|
|
593
|
+
_channels.size +
|
|
594
|
+
_market.size +
|
|
595
|
+
_nfts.size +
|
|
596
|
+
_contributions.size
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
|
|
367
600
|
export function _setBalance(agentId, balance, locked) {
|
|
368
601
|
_balances.set(agentId, { balance, locked: locked || 0 });
|
|
369
602
|
}
|