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,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-pin policy for compaction (OPT-IN).
|
|
3
|
+
*
|
|
4
|
+
* Phase 7.7 gave the compressor a deterministic pin mechanism: a message the
|
|
5
|
+
* predicate marks is pulled out before any strategy and re-inserted verbatim,
|
|
6
|
+
* so it survives compaction no matter what the (non-deterministic) LLM summary
|
|
7
|
+
* drops. What was deliberately left unbuilt is the *policy* — deciding WHICH
|
|
8
|
+
* messages to auto-pin — because auto-pinning reorders the hot agent loop's
|
|
9
|
+
* context and is a product-UX call.
|
|
10
|
+
*
|
|
11
|
+
* This module supplies that policy, but strictly opt-in: it only ever produces
|
|
12
|
+
* a predicate when the caller explicitly enables auto-pin. When disabled it
|
|
13
|
+
* returns null and the caller passes NO predicate, so the compressor falls back
|
|
14
|
+
* to its default (pin only messages already tagged `pinned:true`) and behaviour
|
|
15
|
+
* is byte-identical to before.
|
|
16
|
+
*
|
|
17
|
+
* Default policy when enabled: pin the ORIGINAL TASK — the first user turn —
|
|
18
|
+
* because that is the single fact most likely to scroll out of the recent
|
|
19
|
+
* window yet most important to keep (the coding agent's goal). Explicit
|
|
20
|
+
* `pinned:true` messages are always honored on top of it. A token cap keeps a
|
|
21
|
+
* pathologically large first turn from itself blowing the budget.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const DEFAULT_MAX_PIN_TOKENS = 2000;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Normalize the opt-in value into a config object, or null when auto-pin is off.
|
|
28
|
+
* Accepts: falsy (off), `true` (defaults on), or a config object
|
|
29
|
+
* `{ firstUserGoal?, maxPinTokens? }`.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveAutoPinConfig(opt) {
|
|
32
|
+
if (!opt) return null;
|
|
33
|
+
const cfg = typeof opt === "object" ? opt : {};
|
|
34
|
+
return {
|
|
35
|
+
firstUserGoal: cfg.firstUserGoal !== false, // default true when enabled
|
|
36
|
+
maxPinTokens: Number.isFinite(cfg.maxPinTokens)
|
|
37
|
+
? cfg.maxPinTokens
|
|
38
|
+
: DEFAULT_MAX_PIN_TOKENS,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Coarse char/4 token estimate — matches the compressor's own heuristic. */
|
|
43
|
+
function estimateTokens(text) {
|
|
44
|
+
return Math.ceil(String(text || "").length / 4);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function contentString(m) {
|
|
48
|
+
if (!m) return "";
|
|
49
|
+
return typeof m.content === "string"
|
|
50
|
+
? m.content
|
|
51
|
+
: JSON.stringify(m.content || "");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Build an `isPinned(message)` predicate for `compress({ isPinned })`, or null
|
|
56
|
+
* when auto-pin is disabled (caller then passes no predicate → default).
|
|
57
|
+
*
|
|
58
|
+
* The predicate combines explicit pins (`pinned:true`/`_pin`) with the policy's
|
|
59
|
+
* auto-selected messages, matched by identity against `messages` (compress
|
|
60
|
+
* filters the same array, so identity is stable).
|
|
61
|
+
*/
|
|
62
|
+
export function buildAutoPinPredicate(messages, opt) {
|
|
63
|
+
const cfg = resolveAutoPinConfig(opt);
|
|
64
|
+
if (!cfg) return null;
|
|
65
|
+
if (!Array.isArray(messages)) {
|
|
66
|
+
return (m) => !!m && (m.pinned === true || m._pin === true);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const auto = new Set();
|
|
70
|
+
if (cfg.firstUserGoal) {
|
|
71
|
+
const firstUser = messages.find((m) => m && m.role === "user");
|
|
72
|
+
// Skip a first turn that is itself huge — pinning it would defeat the point
|
|
73
|
+
// (it would dominate the very budget compaction is trying to reclaim).
|
|
74
|
+
if (
|
|
75
|
+
firstUser &&
|
|
76
|
+
estimateTokens(contentString(firstUser)) <= cfg.maxPinTokens
|
|
77
|
+
) {
|
|
78
|
+
auto.add(firstUser);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (m) => !!m && (m.pinned === true || m._pin === true || auto.has(m));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Explain what the policy would pin for `messages` (for `--dry-run` / logging).
|
|
87
|
+
* Returns `{ enabled, reasons: [{ role, preview, why }] }`.
|
|
88
|
+
*/
|
|
89
|
+
export function describeAutoPin(messages, opt) {
|
|
90
|
+
const cfg = resolveAutoPinConfig(opt);
|
|
91
|
+
if (!cfg) return { enabled: false, reasons: [] };
|
|
92
|
+
const reasons = [];
|
|
93
|
+
const list = Array.isArray(messages) ? messages : [];
|
|
94
|
+
for (const m of list) {
|
|
95
|
+
if (m && (m.pinned === true || m._pin === true)) {
|
|
96
|
+
reasons.push({ role: m.role, preview: preview(m), why: "explicit pin" });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (cfg.firstUserGoal) {
|
|
100
|
+
const firstUser = list.find((m) => m && m.role === "user");
|
|
101
|
+
if (
|
|
102
|
+
firstUser &&
|
|
103
|
+
estimateTokens(contentString(firstUser)) <= cfg.maxPinTokens
|
|
104
|
+
) {
|
|
105
|
+
reasons.push({
|
|
106
|
+
role: "user",
|
|
107
|
+
preview: preview(firstUser),
|
|
108
|
+
why: "original task (first user turn)",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { enabled: true, reasons };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function preview(m) {
|
|
116
|
+
return contentString(m).replace(/\s+/g, " ").slice(0, 80);
|
|
117
|
+
}
|
|
@@ -353,6 +353,74 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
353
353
|
tags: ["tool:search_files", "contract:coding-agent", "tier:mvp"],
|
|
354
354
|
},
|
|
355
355
|
},
|
|
356
|
+
{
|
|
357
|
+
name: "code_intelligence",
|
|
358
|
+
title: "Code Intelligence",
|
|
359
|
+
kind: "analysis",
|
|
360
|
+
tier: "extension",
|
|
361
|
+
description:
|
|
362
|
+
"Semantic code navigation via a Language Server (LSP): resolve a symbol's " +
|
|
363
|
+
"definition, find its references, get type/hover info, list document or " +
|
|
364
|
+
"workspace symbols, read diagnostics, or preview a rename — WITHOUT text " +
|
|
365
|
+
"guessing. Prefer this over search_files when you need exact symbol " +
|
|
366
|
+
"semantics. Positions are 1-based (line/col). Degrades gracefully to a " +
|
|
367
|
+
"'not available' result when no language server is installed for the file.",
|
|
368
|
+
inputSchema: {
|
|
369
|
+
type: "object",
|
|
370
|
+
properties: {
|
|
371
|
+
action: {
|
|
372
|
+
type: "string",
|
|
373
|
+
enum: [
|
|
374
|
+
"definition",
|
|
375
|
+
"references",
|
|
376
|
+
"hover",
|
|
377
|
+
"document_symbols",
|
|
378
|
+
"workspace_symbols",
|
|
379
|
+
"diagnostics",
|
|
380
|
+
"rename_preview",
|
|
381
|
+
],
|
|
382
|
+
description: "Which semantic query to run",
|
|
383
|
+
},
|
|
384
|
+
file: {
|
|
385
|
+
type: "string",
|
|
386
|
+
description:
|
|
387
|
+
"File path (relative to cwd). Required for every action except workspace_symbols.",
|
|
388
|
+
},
|
|
389
|
+
line: {
|
|
390
|
+
type: "integer",
|
|
391
|
+
description:
|
|
392
|
+
"1-based line number of the symbol (definition/references/hover/rename_preview).",
|
|
393
|
+
},
|
|
394
|
+
col: {
|
|
395
|
+
type: "integer",
|
|
396
|
+
description:
|
|
397
|
+
"1-based column of the symbol (definition/references/hover/rename_preview).",
|
|
398
|
+
},
|
|
399
|
+
query: {
|
|
400
|
+
type: "string",
|
|
401
|
+
description: "Symbol name to search for (workspace_symbols).",
|
|
402
|
+
},
|
|
403
|
+
new_name: {
|
|
404
|
+
type: "string",
|
|
405
|
+
description: "Proposed new identifier (rename_preview).",
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
required: ["action"],
|
|
409
|
+
},
|
|
410
|
+
...TOOL_POLICY_METADATA.code_intelligence,
|
|
411
|
+
permissions: {
|
|
412
|
+
level: "readonly",
|
|
413
|
+
scopes: ["filesystem:read", "process:spawn"],
|
|
414
|
+
},
|
|
415
|
+
telemetry: {
|
|
416
|
+
category: "analysis",
|
|
417
|
+
tags: [
|
|
418
|
+
"tool:code_intelligence",
|
|
419
|
+
"contract:coding-agent",
|
|
420
|
+
"tier:extension",
|
|
421
|
+
],
|
|
422
|
+
},
|
|
423
|
+
},
|
|
356
424
|
{
|
|
357
425
|
name: "list_dir",
|
|
358
426
|
title: "List Directory",
|
|
@@ -422,7 +490,8 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
422
490
|
properties: {
|
|
423
491
|
category: {
|
|
424
492
|
type: "string",
|
|
425
|
-
description:
|
|
493
|
+
description:
|
|
494
|
+
"Filter by category (e.g. development, automation, data)",
|
|
426
495
|
},
|
|
427
496
|
query: {
|
|
428
497
|
type: "string",
|
|
@@ -491,7 +560,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
491
560
|
agent: {
|
|
492
561
|
type: "string",
|
|
493
562
|
description:
|
|
494
|
-
|
|
563
|
+
"Optional name of a pre-defined subagent from .chainlesschain/agents/ or .claude/agents/ (e.g. \"review:security\"). Loads that file's system prompt + tool allow-list. Run `cc agents list` to see them. Explicit `role`/`tools` override the agent's values.",
|
|
495
564
|
},
|
|
496
565
|
role: {
|
|
497
566
|
type: "string",
|
|
@@ -588,7 +657,16 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
588
657
|
},
|
|
589
658
|
provider: {
|
|
590
659
|
type: "string",
|
|
591
|
-
enum: [
|
|
660
|
+
enum: [
|
|
661
|
+
"auto",
|
|
662
|
+
"tavily",
|
|
663
|
+
"brave",
|
|
664
|
+
"bocha",
|
|
665
|
+
"qianfan",
|
|
666
|
+
"duckduckgo",
|
|
667
|
+
"searxng",
|
|
668
|
+
"baidu",
|
|
669
|
+
],
|
|
592
670
|
description:
|
|
593
671
|
"Override the configured search backend for this call (default: from config / auto)",
|
|
594
672
|
},
|
|
@@ -763,11 +841,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
763
841
|
},
|
|
764
842
|
telemetry: {
|
|
765
843
|
category: "search",
|
|
766
|
-
tags: [
|
|
767
|
-
"tool:search_sessions",
|
|
768
|
-
"contract:coding-agent",
|
|
769
|
-
"tier:extension",
|
|
770
|
-
],
|
|
844
|
+
tags: ["tool:search_sessions", "contract:coding-agent", "tier:extension"],
|
|
771
845
|
},
|
|
772
846
|
},
|
|
773
847
|
]);
|
|
@@ -23,7 +23,11 @@ const TOOL_DECISIONS = Object.freeze({
|
|
|
23
23
|
REQUIRE_CONFIRMATION: "require_confirmation",
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
const PLAN_APPROVED_STATES = Object.freeze([
|
|
26
|
+
const PLAN_APPROVED_STATES = Object.freeze([
|
|
27
|
+
"approved",
|
|
28
|
+
"executing",
|
|
29
|
+
"completed",
|
|
30
|
+
]);
|
|
27
31
|
|
|
28
32
|
const READ_ONLY_GIT_SUBCOMMANDS = Object.freeze([
|
|
29
33
|
"status",
|
|
@@ -64,6 +68,20 @@ const TOOL_POLICY_METADATA = Object.freeze({
|
|
|
64
68
|
approvalFlow: "auto",
|
|
65
69
|
isReadOnly: true,
|
|
66
70
|
},
|
|
71
|
+
code_intelligence: {
|
|
72
|
+
// Read-only semantic navigation via LSP (definition/references/hover/
|
|
73
|
+
// symbols/diagnostics/rename-preview). It never mutates the workspace — a
|
|
74
|
+
// rename returns a preview, not an applied edit — so it is auto-approved and
|
|
75
|
+
// available in plan mode, like search_files.
|
|
76
|
+
riskLevel: RISK_LEVELS.LOW,
|
|
77
|
+
category: TOOL_CATEGORIES.ANALYZE,
|
|
78
|
+
availableInPlanMode: true,
|
|
79
|
+
planModeBehavior: "allow",
|
|
80
|
+
requiresPlanApproval: false,
|
|
81
|
+
requiresConfirmation: false,
|
|
82
|
+
approvalFlow: "auto",
|
|
83
|
+
isReadOnly: true,
|
|
84
|
+
},
|
|
67
85
|
edit_file: {
|
|
68
86
|
riskLevel: RISK_LEVELS.MEDIUM,
|
|
69
87
|
category: TOOL_CATEGORIES.WRITE,
|
|
@@ -295,7 +313,9 @@ function isDangerousGitCommand(command) {
|
|
|
295
313
|
case "checkout":
|
|
296
314
|
// Discard working-tree changes: `checkout -- <path>`, `checkout .`,
|
|
297
315
|
// or `-f`/`--force` (a plain branch checkout is not flagged).
|
|
298
|
-
return
|
|
316
|
+
return (
|
|
317
|
+
lower.includes("--") || lower.includes(".") || has("-f", "--force")
|
|
318
|
+
);
|
|
299
319
|
case "restore":
|
|
300
320
|
// Worktree restore discards changes; a pure `--staged` restore only
|
|
301
321
|
// unstages and is recoverable.
|
|
@@ -321,9 +341,9 @@ function isDangerousGitCommand(command) {
|
|
|
321
341
|
// or an explicit `--delete --force`.
|
|
322
342
|
return rest.includes("-D") || (has("--delete") && has("-f", "--force"));
|
|
323
343
|
case "stash":
|
|
324
|
-
return ["drop", "clear"].includes(
|
|
344
|
+
return ["drop", "clear"].includes(lower[0] || "");
|
|
325
345
|
case "reflog":
|
|
326
|
-
return ["expire", "delete"].includes(
|
|
346
|
+
return ["expire", "delete"].includes(lower[0] || "");
|
|
327
347
|
case "update-ref":
|
|
328
348
|
return has("-d", "--delete");
|
|
329
349
|
case "filter-branch":
|
|
@@ -333,9 +353,14 @@ function isDangerousGitCommand(command) {
|
|
|
333
353
|
return lower.some((t) => t.startsWith("--prune"));
|
|
334
354
|
case "rebase":
|
|
335
355
|
// History rewrite; control sub-actions (--abort/--continue/etc.) are safe.
|
|
336
|
-
return ![
|
|
337
|
-
|
|
338
|
-
|
|
356
|
+
return ![
|
|
357
|
+
"--abort",
|
|
358
|
+
"--continue",
|
|
359
|
+
"--skip",
|
|
360
|
+
"--quit",
|
|
361
|
+
"--edit-todo",
|
|
362
|
+
"--show-current-patch",
|
|
363
|
+
].includes(lower[0] || "");
|
|
339
364
|
default:
|
|
340
365
|
return false;
|
|
341
366
|
}
|
|
@@ -13,11 +13,20 @@
|
|
|
13
13
|
* 3 models) and 2.1.152 switches to the configured fallback when the primary
|
|
14
14
|
* model is "not found".
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* provider
|
|
16
|
+
* Cross-provider fallback (v2): a fallback entry may name a DIFFERENT provider
|
|
17
|
+
* as `provider:model` (e.g. `openai:gpt-4o`, `ollama:qwen2.5:7b`). A cross-
|
|
18
|
+
* provider hop swaps provider + baseUrl + apiKey too, resolving the target
|
|
19
|
+
* provider's connection from BUILT_IN_PROVIDERS + its `apiKeyEnv`. SECURITY: a
|
|
20
|
+
* cross-provider hop is used ONLY when the user EXPLICITLY named that provider in
|
|
21
|
+
* the fallback chain AND the target provider's API key is present in the env —
|
|
22
|
+
* we never reuse the primary provider's key against a different vendor (that
|
|
23
|
+
* would be the silent auth-substitution this project forbids). A cross-provider
|
|
24
|
+
* entry whose key is missing is SKIPPED with a clear reason, not attempted with
|
|
25
|
+
* the wrong credential.
|
|
18
26
|
*/
|
|
19
27
|
|
|
20
28
|
import { chatWithTools } from "./agent-core.js";
|
|
29
|
+
import { BUILT_IN_PROVIDERS } from "../lib/llm-providers.js";
|
|
21
30
|
|
|
22
31
|
// Claude Code caps the fallback chain at 3 backups; mirror that here so a
|
|
23
32
|
// mis-configured comma list can't fan out into an unbounded retry storm.
|
|
@@ -142,6 +151,85 @@ export function normalizeFallbackModels(input) {
|
|
|
142
151
|
return out;
|
|
143
152
|
}
|
|
144
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Parse a fallback entry into `{ provider, model }`. A `provider:model` prefix
|
|
156
|
+
* is recognized ONLY when the prefix is a KNOWN provider name — so an
|
|
157
|
+
* ollama-style model id that itself contains a colon (`qwen2.5:7b`) is NOT
|
|
158
|
+
* mis-split, while `ollama:qwen2.5:7b` correctly yields provider `ollama` +
|
|
159
|
+
* model `qwen2.5:7b`. A plain `model` (no known-provider prefix) means
|
|
160
|
+
* "same provider" (provider: null).
|
|
161
|
+
*
|
|
162
|
+
* @param {string} entry
|
|
163
|
+
* @param {Set<string>} [knownProviders] provider names to recognize as prefixes
|
|
164
|
+
* @returns {{ provider: string|null, model: string }}
|
|
165
|
+
*/
|
|
166
|
+
export function parseFallbackEntry(entry, knownProviders) {
|
|
167
|
+
const known =
|
|
168
|
+
knownProviders || new Set(Object.keys(BUILT_IN_PROVIDERS || {}));
|
|
169
|
+
const s = String(entry || "").trim();
|
|
170
|
+
const idx = s.indexOf(":");
|
|
171
|
+
if (idx > 0) {
|
|
172
|
+
const head = s.slice(0, idx);
|
|
173
|
+
const rest = s.slice(idx + 1);
|
|
174
|
+
if (rest && known.has(head)) {
|
|
175
|
+
return { provider: head, model: rest };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return { provider: null, model: s };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Resolve a fallback entry into a concrete call target. For a SAME-provider hop
|
|
183
|
+
* (no known provider prefix), only the model changes. For a CROSS-provider hop,
|
|
184
|
+
* resolve the target provider's baseUrl + apiKey (from its `apiKeyEnv` in the
|
|
185
|
+
* environment); if the target needs a key and none is set, the hop is
|
|
186
|
+
* `unavailable` (skipped) — we never fall back onto a different vendor with the
|
|
187
|
+
* wrong/absent credential.
|
|
188
|
+
*
|
|
189
|
+
* @param {string} entry
|
|
190
|
+
* @param {object} [opts] { env, providers, knownProviders }
|
|
191
|
+
* @returns {{ model, provider?, baseUrl?, apiKey?, crossProvider:boolean } | { unavailable:true, reason:string, model:string, provider:string }}
|
|
192
|
+
*/
|
|
193
|
+
export function resolveFallbackTarget(entry, opts = {}) {
|
|
194
|
+
const env = opts.env || process.env;
|
|
195
|
+
const providers = opts.providers || BUILT_IN_PROVIDERS || {};
|
|
196
|
+
const { provider, model } = parseFallbackEntry(
|
|
197
|
+
entry,
|
|
198
|
+
opts.knownProviders || new Set(Object.keys(providers)),
|
|
199
|
+
);
|
|
200
|
+
if (!provider) {
|
|
201
|
+
return { model, crossProvider: false };
|
|
202
|
+
}
|
|
203
|
+
const def = providers[provider];
|
|
204
|
+
if (!def) {
|
|
205
|
+
return {
|
|
206
|
+
unavailable: true,
|
|
207
|
+
reason: `unknown provider "${provider}"`,
|
|
208
|
+
provider,
|
|
209
|
+
model,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
let apiKey = null;
|
|
213
|
+
if (def.apiKeyEnv) {
|
|
214
|
+
apiKey = env[def.apiKeyEnv] || null;
|
|
215
|
+
if (!apiKey) {
|
|
216
|
+
return {
|
|
217
|
+
unavailable: true,
|
|
218
|
+
reason: `${provider} fallback skipped: ${def.apiKeyEnv} not set`,
|
|
219
|
+
provider,
|
|
220
|
+
model,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
model,
|
|
226
|
+
provider,
|
|
227
|
+
baseUrl: def.baseUrl || null,
|
|
228
|
+
apiKey,
|
|
229
|
+
crossProvider: true,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
145
233
|
/**
|
|
146
234
|
* Build a chatFn that walks an ordered fallback chain when the primary fails.
|
|
147
235
|
*
|
|
@@ -168,6 +256,9 @@ export function makeFallbackChatFn(opts = {}) {
|
|
|
168
256
|
const isModelNotFound = opts.isModelNotFound || isModelNotFoundError;
|
|
169
257
|
const onFallback = opts.onFallback;
|
|
170
258
|
|
|
259
|
+
const env = opts.env || process.env;
|
|
260
|
+
const providers = opts.providers || BUILT_IN_PROVIDERS || {};
|
|
261
|
+
|
|
171
262
|
return async function chatWithFallback(messages, options = {}) {
|
|
172
263
|
try {
|
|
173
264
|
return await baseChatFn(messages, options);
|
|
@@ -175,8 +266,30 @@ export function makeFallbackChatFn(opts = {}) {
|
|
|
175
266
|
let err = firstErr;
|
|
176
267
|
let lastTried = options.model;
|
|
177
268
|
for (const candidate of models) {
|
|
178
|
-
|
|
179
|
-
|
|
269
|
+
const target = resolveFallbackTarget(candidate, { env, providers });
|
|
270
|
+
// A cross-provider hop whose key is absent (or an unknown provider) is
|
|
271
|
+
// skipped — never attempted with the wrong credential. Surface why.
|
|
272
|
+
if (target.unavailable) {
|
|
273
|
+
if (typeof onFallback === "function") {
|
|
274
|
+
try {
|
|
275
|
+
onFallback({
|
|
276
|
+
from: lastTried,
|
|
277
|
+
to: candidate,
|
|
278
|
+
skipped: true,
|
|
279
|
+
reason: target.reason,
|
|
280
|
+
error: err?.message || String(err),
|
|
281
|
+
});
|
|
282
|
+
} catch {
|
|
283
|
+
/* best-effort */
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
// Skip a no-op hop (same provider + same model just attempted).
|
|
289
|
+
const sameModel = target.model === lastTried;
|
|
290
|
+
const sameProvider =
|
|
291
|
+
!target.crossProvider || target.provider === options.provider;
|
|
292
|
+
if (!target.model || (sameModel && sameProvider)) continue;
|
|
180
293
|
// Only advance the chain for transient failures or a missing primary;
|
|
181
294
|
// a real bad-request / auth error is surfaced immediately.
|
|
182
295
|
if (!isRetryable(err) && !isModelNotFound(err)) throw err;
|
|
@@ -184,16 +297,30 @@ export function makeFallbackChatFn(opts = {}) {
|
|
|
184
297
|
try {
|
|
185
298
|
onFallback({
|
|
186
299
|
from: lastTried,
|
|
187
|
-
to:
|
|
300
|
+
to: target.crossProvider
|
|
301
|
+
? `${target.provider}:${target.model}`
|
|
302
|
+
: target.model,
|
|
303
|
+
crossProvider: target.crossProvider,
|
|
188
304
|
error: err?.message || String(err),
|
|
189
305
|
});
|
|
190
306
|
} catch {
|
|
191
307
|
// Notification is best-effort — never mask the retry.
|
|
192
308
|
}
|
|
193
309
|
}
|
|
194
|
-
lastTried =
|
|
310
|
+
lastTried = target.model;
|
|
311
|
+
// Build the per-hop options: same-provider swaps only the model; a
|
|
312
|
+
// cross-provider hop also swaps provider/baseUrl/apiKey.
|
|
313
|
+
const hopOptions = target.crossProvider
|
|
314
|
+
? {
|
|
315
|
+
...options,
|
|
316
|
+
model: target.model,
|
|
317
|
+
provider: target.provider,
|
|
318
|
+
baseUrl: target.baseUrl,
|
|
319
|
+
apiKey: target.apiKey,
|
|
320
|
+
}
|
|
321
|
+
: { ...options, model: target.model };
|
|
195
322
|
try {
|
|
196
|
-
return await baseChatFn(messages,
|
|
323
|
+
return await baseChatFn(messages, hopOptions);
|
|
197
324
|
} catch (nextErr) {
|
|
198
325
|
err = nextErr;
|
|
199
326
|
}
|