chainlesschain 0.162.148 → 0.162.149
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-BJif14yR.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C9pBYocA.js → ActionButton-CXek6gJY.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BWAkeXxK.js → Analytics-BgQhdAJi.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-CivFGH6B.js → AppLayout-DTYl5NtR.js} +3 -3
- package/src/assets/web-panel/assets/{Audit-Cm8hRpZm.js → Audit-BzATQAeR.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DXdFMsE8.js → Backup-BzdPEQhL.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-uAwSTeql.js → BaseInput-BM0KVh8E.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-KU8eeJJE.js → Chat-D7fHXHkz.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Wm34RR-b.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-C6AMDkjd.js → Checkbox-CAiSQ9vO.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-t2moDxcO.js → Codegen-Df40CrEe.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DCcsRRhN.js → Col-DIT2fNFU.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DtB-8SAC.js → Community-CSTIbW2k.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CZm8THYA.js → Compact-DtqXZZUi.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-LiQgC7g1.js → Compliance-CUtzw6o7.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CA8SAxht.js → Cowork-CezmlnmU.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CtRaF1wD.js → Cron-P4BITarg.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-6-br6Hub.js → Crosschain-BRRiYwvq.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Do2EccrL.js → DID-L5ijB9i4.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-wrXcbzGe.js → Dashboard-CFxro4ob.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-p3FsT245.js → Dropdown-BmAFCQ71.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D95A2L8q.js → EmailListRenderer-DJBCEuon.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-cLuJW2zo.js → FamilyGuardDashboard-z4oLq6eT.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Brgq_cbN.js → Federation-DsVCpHMF.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DWLCkNgh.js → FormItemContext-DP3bP5th.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BBqUfQd6.js → GenericCardRenderer-BAXP2Gc6.js} +1 -1
- package/src/assets/web-panel/assets/{Git-8F090w4I.js → Git-I3g_bAw9.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CCogEbxb.js → Governance-jHS5-ioS.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CfLD7v7C.js → Inference-CPL7sfx9.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DDuHJewd.js → KnowledgeGraph-Jf236h4C.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CE8KSEVC.js → Logs-Cm2tcSKg.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-DmwpZmhT.js → Marketplace-CZK82rhi.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Bf7AazU8.js → McpTools-CZCeji7a.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-D0QU_00S.js → Memory-3l2KVS9k.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-yXS9xdhx.js → MobileBridge-VYdpoLh6.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BuDUoGUP.js → MobileProjects-CiB9cmm1.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BYyHy28p.js → Mtc-wCFZbBuL.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-CK0aqpiZ.js → MtcAudit-1a3THIyG.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-mNimKYeb.js → Multisig-DMzLB2hG.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-AioAJ0YA.js → NLProgramming-D9wZbf6l.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CVVNCLHE.js → Notes-hrFe2ZM-.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C4ABj-TK.js → NotificationSettings-CHGX5Jwm.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +1 -0
- package/src/assets/web-panel/assets/{Organization-uozl_gWK.js → Organization-By7FkhtY.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BCZOM2hK.js → Overflow--khGSzJn.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CArcaiaj.js → P2P-CAG9dH35.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Sgq2Srr8.js → PdhVaultBrowser-B3SQZmK9.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BYrQrXnH.js → Permissions-D35ec6JA.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BzHStAbz.js → PersonalDataHub-CxBF7hW_.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-k7KqxX1M.js → Pipeline-s6EtOO1s.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-IumTUWqx.js → Privacy-BbJYmWmO.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BRyImYTf.js → ProjectInit-VGQq1jMT.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BFIqTBFk.js → ProjectSettings-B1ew3Teh.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CyyFnUPs.js → Providers-mrO47FIK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-C82cRx-X.js → QrScannerModal-IJF2mHyw.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DGxDF521.js → QuickAsk-CU0wN_Z0.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Cns-Am1y.js → Recommend-DhN37R6G.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-R7OqAIlg.js → RemoteSession-D_xOX_hu.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D7mgPIYV.js → Reputation-D_Ssv7uH.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B3lEURyd.js → Row-Kx5dKxX7.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-9_UVrpBt.js → RssFeed-BlGwqZkY.js} +2 -2
- package/src/assets/web-panel/assets/{Search-ClZeO80q.js → Search-hLFQzxpb.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BNNJczEp.js → Security-DMlvsVt4.js} +3 -3
- package/src/assets/web-panel/assets/{Services-C5SjrWUj.js → Services-Bd0Qsj2m.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Ci_obQ-g.js → Skeleton-DFclq9X3.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DdebN15P.js → Skills-BNtln2qY.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-OinZP2vi.js → Sla-Dch5H19G.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CxzbNF51.js → SpeechSettings-2UfQcU1g.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-D06N_66b.js → SyncSettings-CD9YQr4i.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BdEdW0AZ.js → Tasks-BNu-7MzI.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-F1ctKmPa.js → Templates-D1n9CaIR.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CVz1Urot.js → Tenant-DenL3iBW.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-ZzU0Io1Y.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-Doitzjmf.js → TimelineRenderer-D87IfukO.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BpyVRpVA.js → Tokens-BkiZc8E3.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-nWhWYTbU.js → Trigger-BNRSytGN.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DK_G-wLx.js → Trust-Bwbd4X2m.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B5yBUojO.js → UkeySign-B8O2bs0o.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C5D51qAe.js → VideoEditing-C2fL8zmH.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CLbL9K7v.js → Wallet-BORYDdE1.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DZUelI3V.js → WebAuthn-C0V5S2FM.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-8RPxt4KW.js → WorkflowEditor-2dR0fcHL.js} +1 -1
- package/src/assets/web-panel/assets/{chat-4N4tOA3d.js → chat-BmuAFAn8.js} +1 -1
- package/src/assets/web-panel/assets/{colors-zbbGVrua.js → colors-CN3smMcK.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-D7iMkbnE.js → compact-item-DCnxb4kW.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CBzPJv-w.js → createContext-vlR43pHn.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-bHdrQSqZ.js → hasIn-D04tHYFd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbE5D0WL.js → index-0DnaZGkC.js} +1 -1
- package/src/assets/web-panel/assets/{index-308gCGh7.js → index-430S68MN.js} +1 -1
- package/src/assets/web-panel/assets/{index-kmh1TxRa.js → index-B78xL3s2.js} +1 -1
- package/src/assets/web-panel/assets/{index-QFObYeo1.js → index-BTPEZTk1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZb8F8YG.js → index-BXRg8GFQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE9j5YgT.js → index-BasvsWDM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiG1IZao.js → index-BeGDEXFs.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bqmx24kh.js → index-BqhASEL4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCr0geV9.js → index-BudvKQfG.js} +1 -1
- package/src/assets/web-panel/assets/{index-S74FpAIn.js → index-C-6NO5il.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyoNgbXl.js → index-C5Sxb1sE.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtbbdLnf.js → index-CP9m9Ggr.js} +3 -3
- package/src/assets/web-panel/assets/{index-CkxK86vf.js → index-CTOCnIQ7.js} +1 -1
- package/src/assets/web-panel/assets/index-Cg2ldRfU.js +1 -0
- package/src/assets/web-panel/assets/{index-BTIjjXry.js → index-ClhAHDK3.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7b1hGry.js → index-CnXebZLL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPxkoKgA.js → index-CngCC8hC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ci009ijp.js → index-Cr-A0FYJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdmMoYN1.js → index-CsAsCPJ6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBNr77E1.js → index-D28DeAAB.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1s0Bz9O.js → index-D5LZVZ0L.js} +1 -1
- package/src/assets/web-panel/assets/{index-oDKNgCsP.js → index-D65_XseV.js} +1 -1
- package/src/assets/web-panel/assets/{index-QNAG4JtR.js → index-D8vwp4qp.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQfu1U78.js → index-DDwLgQY9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnBOpqv3.js → index-DIpY0qM5.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQ6NcfWz.js → index-DTWg-18U.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4XKpj6c.js → index-DTtRscUa.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1YDh7Wr.js → index-DYAtmqiv.js} +1 -1
- package/src/assets/web-panel/assets/{index-CvRMA9uT.js → index-D_n8_vfI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CahryTX0.js → index-DbADHwhr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJ4ZGyW0.js → index-DbVsQBOH.js} +1 -1
- package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +1 -0
- package/src/assets/web-panel/assets/{index-xYCm6W2h.js → index-HhNjnCfe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BS4_Mwk6.js → index-ToUh2b1-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DISWAYce.js → index-TslMTwNy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmqlJed-.js → index-_FIkN3jd.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqdPyWm5.js → index-hpvvtAZ3.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsKehmmS.js → index-jzR7Ujuw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUyjUkY7.js → index-ljuBiQW9.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BD55yNBt.js → initDefaultProps-C3wUb4je.js} +1 -1
- package/src/assets/web-panel/assets/{motion-B5Bbe77U.js → motion-D-jYFUNA.js} +1 -1
- package/src/assets/web-panel/assets/{move-CTvIqHEH.js → move-tqb8nwJ2.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BkNyPQKB.js → mtc-parser-DSOjMJMz.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BaXJXgHA.js → omit-CJ7VimIW.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Bw6-YTxH.js → pickAttrs-qXiG1iT3.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BLdbkLqJ.js → placementArrow-CkGBcy1Z.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-IVYkzntU.js → responsiveObserve-D3WvTlLO.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DFMFwwtY.js → slide-BEE2ftge.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CURYRtZ1.js → statusUtils-CsfBpxiG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Cfz63s1r.js → styleChecker-xPrIiJPI.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-COJL0KE3.js → useFlexGapSupport-C5Yd-SCR.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-YLLojQQf.js → useFs-D_MDS8HI.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BF_21qUC.js → usePersonalDataHub-BqJh-usA.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-9ZpkA7bb.js → vnode-chm_p-gz.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DhtAfhl8.js → zoom-3-YDNz0Z.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/agent.js +44 -5
- package/src/commands/codeintel.js +252 -0
- package/src/commands/eval.js +248 -0
- package/src/commands/plugin.js +354 -0
- package/src/commands/team.js +456 -0
- package/src/gateways/ws/message-dispatcher.js +45 -2
- package/src/gateways/ws/remote-session-protocol.js +37 -0
- package/src/gateways/ws/ws-server.js +1 -1
- package/src/harness/prompt-compressor.js +27 -1
- package/src/harness/remote-command-ledger.js +158 -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/index.js +6 -0
- package/src/lib/agent-core.js +2 -0
- 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 +266 -0
- package/src/lib/agent-team/team-worktree.js +204 -0
- package/src/lib/agents.js +18 -0
- package/src/lib/async-hook-supervisor.cjs +305 -0
- package/src/lib/eval/runner.js +163 -0
- package/src/lib/eval/tasks.js +456 -0
- package/src/lib/eval/trend.js +185 -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 +258 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +264 -0
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -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 +318 -0
- package/src/lib/lsp/lsp-manager.js +323 -0
- package/src/lib/lsp/lsp-server-registry.js +196 -0
- package/src/lib/plugin-monitor-supervisor.js +238 -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 +388 -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 +144 -0
- package/src/lib/plugin-runtime/reload.js +79 -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/sandbox-egress-proxy.js +162 -0
- package/src/lib/sandbox-network-policy.js +134 -0
- package/src/lib/sandbox-v2.js +10 -4
- package/src/lib/settings-hook-events.cjs +78 -6
- package/src/lib/settings-hooks.cjs +29 -3
- package/src/lib/settings-loader.cjs +35 -1
- package/src/lib/skill-loader.js +18 -0
- package/src/lib/telemetry/span-recorder.js +237 -0
- package/src/repl/agent-repl.js +400 -4
- package/src/runtime/agent-core.js +546 -52
- 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 +353 -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/OrderTableRenderer-DIp8Xcbd.js +0 -1
- package/src/assets/web-panel/assets/Projects-Dpid9CDg.js +0 -1
- package/src/assets/web-panel/assets/Terminal-BvAK_Zel.js +0 -3
- package/src/assets/web-panel/assets/devWarning-C2Z5LRgq.js +0 -1
- package/src/assets/web-panel/assets/index-BGp6Yr-Y.js +0 -1
- package/src/assets/web-panel/assets/index-BXiw9dQf.js +0 -1
package/src/commands/agent.js
CHANGED
|
@@ -177,6 +177,19 @@ export function registerAgentCommand(program) {
|
|
|
177
177
|
"Run shell commands in an ephemeral Docker sandbox (network disabled by default)",
|
|
178
178
|
)
|
|
179
179
|
.option("--sandbox-network", "Allow network access inside --sandbox")
|
|
180
|
+
.option(
|
|
181
|
+
"--otlp <file>",
|
|
182
|
+
"Write the agent run's OpenTelemetry spans (model/tool/retry) as OTLP/JSON to <file>",
|
|
183
|
+
)
|
|
184
|
+
.option(
|
|
185
|
+
"--auto-rewake",
|
|
186
|
+
"When an async `asyncRewake` hook (e.g. a background test) fails at turn end, re-engage the agent to fix it (bounded by --max-rewakes)",
|
|
187
|
+
)
|
|
188
|
+
.option(
|
|
189
|
+
"--max-rewakes <n>",
|
|
190
|
+
"Max auto-rewake re-drives per run (default 1); implies --auto-rewake",
|
|
191
|
+
(v) => parseInt(v, 10),
|
|
192
|
+
)
|
|
180
193
|
.option(
|
|
181
194
|
"--bg, --background",
|
|
182
195
|
"Start as a detached background agent and return its id immediately",
|
|
@@ -252,7 +265,7 @@ export function registerAgentCommand(program) {
|
|
|
252
265
|
)
|
|
253
266
|
.option(
|
|
254
267
|
"--fallback-model <model>",
|
|
255
|
-
"Backup model(s) to try in order when the primary fails (transient error or model-not-found). Repeatable or comma-separated; up to 3. Defaults to config llm.fallbackModels.
|
|
268
|
+
"Backup model(s) to try in order when the primary fails (transient error or model-not-found). Repeatable or comma-separated; up to 3. A `provider:model` entry (e.g. openai:gpt-4o) falls back cross-provider, using that provider's API key from its env var (skipped if unset — never reuses the primary key). Defaults to config llm.fallbackModels.",
|
|
256
269
|
(val, prev) => (prev || []).concat([val]),
|
|
257
270
|
)
|
|
258
271
|
.option(
|
|
@@ -509,6 +522,7 @@ export function registerAgentCommand(program) {
|
|
|
509
522
|
// over a settings model. Applied once here so every branch (headless +
|
|
510
523
|
// interactive, which all read options.model) picks it up; env vars are
|
|
511
524
|
// set on the process so the agent loop + child tools inherit them.
|
|
525
|
+
let settingsSandbox = null;
|
|
512
526
|
try {
|
|
513
527
|
const { loadSettingsConfig } =
|
|
514
528
|
await import("../lib/settings-loader.cjs");
|
|
@@ -520,6 +534,7 @@ export function registerAgentCommand(program) {
|
|
|
520
534
|
process.env[k] = v;
|
|
521
535
|
}
|
|
522
536
|
if (!options.model && sc.model) options.model = sc.model;
|
|
537
|
+
settingsSandbox = sc.sandbox || null;
|
|
523
538
|
} catch {
|
|
524
539
|
// settings overrides are best-effort 鈥?never block the run
|
|
525
540
|
}
|
|
@@ -651,10 +666,22 @@ export function registerAgentCommand(program) {
|
|
|
651
666
|
const fallbackChatFn = fallbackModels.length
|
|
652
667
|
? makeFallbackChatFn({
|
|
653
668
|
fallbackModels,
|
|
654
|
-
onFallback: ({
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
669
|
+
onFallback: ({
|
|
670
|
+
from,
|
|
671
|
+
to,
|
|
672
|
+
error,
|
|
673
|
+
skipped,
|
|
674
|
+
reason,
|
|
675
|
+
crossProvider,
|
|
676
|
+
}) =>
|
|
677
|
+
skipped
|
|
678
|
+
? process.stderr.write(
|
|
679
|
+
`Note: fallback "${to}" skipped (${reason}).\n`,
|
|
680
|
+
)
|
|
681
|
+
: process.stderr.write(
|
|
682
|
+
`Note: model "${from}" failed (${error}); retrying with ` +
|
|
683
|
+
`${crossProvider ? "cross-provider " : ""}fallback "${to}".\n`,
|
|
684
|
+
),
|
|
658
685
|
})
|
|
659
686
|
: undefined;
|
|
660
687
|
|
|
@@ -822,6 +849,7 @@ export function registerAgentCommand(program) {
|
|
|
822
849
|
const agentSandbox = normalizeAgentSandbox(options.sandbox, {
|
|
823
850
|
cwd: process.cwd(),
|
|
824
851
|
network: options.sandboxNetwork === true,
|
|
852
|
+
settings: settingsSandbox,
|
|
825
853
|
});
|
|
826
854
|
// Resume requested onto a session with no headless (JSONL) transcript?
|
|
827
855
|
// Warn instead of silently starting empty 鈥?headless resume rebuilds
|
|
@@ -864,6 +892,16 @@ export function registerAgentCommand(program) {
|
|
|
864
892
|
additionalDirectories,
|
|
865
893
|
sandbox: agentSandbox,
|
|
866
894
|
autoCheckpoint,
|
|
895
|
+
// --otlp <file>: capture + export the run's OTel spans as OTLP/JSON.
|
|
896
|
+
otlp: options.otlp || null,
|
|
897
|
+
// --auto-rewake / --max-rewakes: bounded re-drive on async-hook failure.
|
|
898
|
+
// --max-rewakes implies --auto-rewake (a positive budget turns it on).
|
|
899
|
+
autoRewake:
|
|
900
|
+
options.autoRewake === true ||
|
|
901
|
+
(Number.isFinite(options.maxRewakes) && options.maxRewakes > 0),
|
|
902
|
+
maxRewakes: Number.isFinite(options.maxRewakes)
|
|
903
|
+
? options.maxRewakes
|
|
904
|
+
: undefined,
|
|
867
905
|
maxTurns,
|
|
868
906
|
// commander maps --no-file-refs 鈫?options.fileRefs === false
|
|
869
907
|
expandFileRefs: options.fileRefs !== false,
|
|
@@ -975,6 +1013,7 @@ export function registerAgentCommand(program) {
|
|
|
975
1013
|
sandbox: normalizeAgentSandbox(options.sandbox, {
|
|
976
1014
|
cwd: process.cwd(),
|
|
977
1015
|
network: options.sandboxNetwork === true,
|
|
1016
|
+
settings: settingsSandbox,
|
|
978
1017
|
}),
|
|
979
1018
|
autoCheckpoint,
|
|
980
1019
|
// --vim: start the REPL in vim-mode editing (also CC_VIM=1 or /vim).
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cc code-intel — semantic code navigation via the Language Server Protocol.
|
|
3
|
+
*
|
|
4
|
+
* End-to-end surface for the LSP code-intelligence layer (Phase 2 of the CLI
|
|
5
|
+
* optimization plan). Proves the stack works without touching the contended
|
|
6
|
+
* agent-core; the agent `code_intelligence` tool is wired separately.
|
|
7
|
+
*
|
|
8
|
+
* cc code-intel status # which servers are installed
|
|
9
|
+
* cc code-intel def <file> <line> <col> # go to definition
|
|
10
|
+
* cc code-intel refs <file> <line> <col> # find references
|
|
11
|
+
* cc code-intel hover <file> <line> <col> # type / doc info
|
|
12
|
+
* cc code-intel symbols <file> # document symbols
|
|
13
|
+
* cc code-intel wsymbols <query> # workspace symbol search
|
|
14
|
+
* cc code-intel diag <file> # diagnostics
|
|
15
|
+
* cc code-intel rename <file> <line> <col> <newName> # preview a rename
|
|
16
|
+
*
|
|
17
|
+
* Positions are 1-based (line/col), matching editor gutters.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import chalk from "chalk";
|
|
21
|
+
import { logger } from "../lib/logger.js";
|
|
22
|
+
|
|
23
|
+
function num(v, name) {
|
|
24
|
+
const n = Number.parseInt(v, 10);
|
|
25
|
+
if (!Number.isFinite(n) || n < 1) {
|
|
26
|
+
throw new Error(`${name} must be a positive integer (1-based), got "${v}"`);
|
|
27
|
+
}
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function withCI(fn, { json } = {}) {
|
|
32
|
+
const { CodeIntelligence } = await import("../lib/lsp/code-intelligence.js");
|
|
33
|
+
// coldStart: each CLI invocation spawns a fresh server, so wait for the
|
|
34
|
+
// project to load before querying (the warm agent path leaves this off).
|
|
35
|
+
const ci = new CodeIntelligence({
|
|
36
|
+
projectRoot: process.cwd(),
|
|
37
|
+
coldStart: true,
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
const result = await fn(ci);
|
|
41
|
+
if (json) {
|
|
42
|
+
console.log(JSON.stringify(result, null, 2));
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
} finally {
|
|
46
|
+
await ci.dispose();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function reportUnavailable(res) {
|
|
51
|
+
logger.warn(
|
|
52
|
+
chalk.yellow(`LSP unavailable: ${res.reason}`) +
|
|
53
|
+
chalk.gray(
|
|
54
|
+
"\n → falling back to text search (`cc search` / agent search_files)",
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
process.exitCode = 3;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function fmtLoc(l) {
|
|
61
|
+
const pos = `${chalk.cyan(l.file)}:${chalk.yellow(l.line)}:${l.col}`;
|
|
62
|
+
return l.snippet ? `${pos} ${chalk.gray(l.snippet)}` : pos;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function registerCodeIntelCommand(program) {
|
|
66
|
+
const ci = program
|
|
67
|
+
.command("code-intel")
|
|
68
|
+
.alias("ci")
|
|
69
|
+
.description(
|
|
70
|
+
"Semantic code navigation via LSP (definition/references/symbols/diagnostics)",
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
ci.command("status")
|
|
74
|
+
.description("Show which language servers are installed and detectable")
|
|
75
|
+
.option("--json", "Output as JSON")
|
|
76
|
+
.action(async (options) => {
|
|
77
|
+
const { probeServers, supportedExtensions } =
|
|
78
|
+
await import("../lib/lsp/lsp-server-registry.js");
|
|
79
|
+
// Surface plugin-contributed servers too (Phase 3: .lsp.json).
|
|
80
|
+
const { ensurePluginLspServers } =
|
|
81
|
+
await import("../lib/plugin-runtime/lsp.js");
|
|
82
|
+
ensurePluginLspServers({ cwd: process.cwd() });
|
|
83
|
+
const servers = probeServers(process.cwd());
|
|
84
|
+
if (options.json) {
|
|
85
|
+
console.log(
|
|
86
|
+
JSON.stringify(
|
|
87
|
+
{ servers, extensions: supportedExtensions() },
|
|
88
|
+
null,
|
|
89
|
+
2,
|
|
90
|
+
),
|
|
91
|
+
);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
logger.log(chalk.bold("LSP servers:"));
|
|
95
|
+
for (const s of servers) {
|
|
96
|
+
const mark = s.available ? chalk.green("✔") : chalk.gray("✖");
|
|
97
|
+
const where = s.available
|
|
98
|
+
? chalk.gray(s.command)
|
|
99
|
+
: chalk.gray("not installed");
|
|
100
|
+
logger.log(` ${mark} ${s.id.padEnd(28)} ${where}`);
|
|
101
|
+
}
|
|
102
|
+
const anyAvail = servers.some((s) => s.available);
|
|
103
|
+
if (!anyAvail) {
|
|
104
|
+
logger.log(
|
|
105
|
+
chalk.yellow(
|
|
106
|
+
"\nNo language servers found. Install one to enable semantic navigation, e.g.:\n",
|
|
107
|
+
) + chalk.gray(" npm i -g typescript-language-server typescript"),
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
ci.command("def <file> <line> <col>")
|
|
113
|
+
.description("Go to definition of the symbol at file:line:col")
|
|
114
|
+
.option("--json", "Output as JSON")
|
|
115
|
+
.action(async (file, line, col, options) => {
|
|
116
|
+
const res = await withCI(
|
|
117
|
+
(c) => c.definition(file, num(line, "line"), num(col, "col")),
|
|
118
|
+
options,
|
|
119
|
+
);
|
|
120
|
+
if (!res.available) return reportUnavailable(res);
|
|
121
|
+
if (options.json) return;
|
|
122
|
+
if (!res.locations.length)
|
|
123
|
+
return logger.log(chalk.gray("No definition found."));
|
|
124
|
+
for (const l of res.locations) logger.log(fmtLoc(l));
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
ci.command("refs <file> <line> <col>")
|
|
128
|
+
.description("Find references to the symbol at file:line:col")
|
|
129
|
+
.option("--no-decl", "Exclude the declaration itself")
|
|
130
|
+
.option("--json", "Output as JSON")
|
|
131
|
+
.action(async (file, line, col, options) => {
|
|
132
|
+
const res = await withCI(
|
|
133
|
+
(c) =>
|
|
134
|
+
c.references(file, num(line, "line"), num(col, "col"), {
|
|
135
|
+
includeDeclaration: options.decl !== false,
|
|
136
|
+
}),
|
|
137
|
+
options,
|
|
138
|
+
);
|
|
139
|
+
if (!res.available) return reportUnavailable(res);
|
|
140
|
+
if (options.json) return;
|
|
141
|
+
logger.log(chalk.bold(`${res.locations.length} reference(s):`));
|
|
142
|
+
for (const l of res.locations) logger.log(" " + fmtLoc(l));
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
ci.command("hover <file> <line> <col>")
|
|
146
|
+
.description("Show type/doc info for the symbol at file:line:col")
|
|
147
|
+
.option("--json", "Output as JSON")
|
|
148
|
+
.action(async (file, line, col, options) => {
|
|
149
|
+
const res = await withCI(
|
|
150
|
+
(c) => c.hover(file, num(line, "line"), num(col, "col")),
|
|
151
|
+
options,
|
|
152
|
+
);
|
|
153
|
+
if (!res.available) return reportUnavailable(res);
|
|
154
|
+
if (options.json) return;
|
|
155
|
+
logger.log(res.contents || chalk.gray("No hover info."));
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
ci.command("symbols <file>")
|
|
159
|
+
.description("List symbols declared in a document")
|
|
160
|
+
.option("--json", "Output as JSON")
|
|
161
|
+
.action(async (file, options) => {
|
|
162
|
+
const res = await withCI((c) => c.documentSymbols(file), options);
|
|
163
|
+
if (!res.available) return reportUnavailable(res);
|
|
164
|
+
if (options.json) return;
|
|
165
|
+
for (const s of res.symbols) {
|
|
166
|
+
const loc = chalk.gray(`${s.line}:${s.col}`);
|
|
167
|
+
const kind = chalk.magenta(s.kind.padEnd(10));
|
|
168
|
+
const container = s.container ? chalk.gray(` (${s.container})`) : "";
|
|
169
|
+
logger.log(` ${loc} ${kind} ${s.name}${container}`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
ci.command("wsymbols <query>")
|
|
174
|
+
.description("Search symbols across the workspace by name")
|
|
175
|
+
.option("--json", "Output as JSON")
|
|
176
|
+
.action(async (query, options) => {
|
|
177
|
+
const res = await withCI((c) => c.workspaceSymbols(query), options);
|
|
178
|
+
if (!res.available) return reportUnavailable(res);
|
|
179
|
+
if (options.json) return;
|
|
180
|
+
logger.log(chalk.bold(`${res.symbols.length} symbol(s):`));
|
|
181
|
+
for (const s of res.symbols) {
|
|
182
|
+
logger.log(
|
|
183
|
+
` ${chalk.magenta(s.kind.padEnd(10))} ${s.name} ${chalk.gray(`${s.file}:${s.line}`)}`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
ci.command("diag <file>")
|
|
189
|
+
.description("Show diagnostics (errors/warnings) for a file")
|
|
190
|
+
.option(
|
|
191
|
+
"--timeout <ms>",
|
|
192
|
+
"How long to wait for the server to publish",
|
|
193
|
+
"5000",
|
|
194
|
+
)
|
|
195
|
+
.option("--json", "Output as JSON")
|
|
196
|
+
.action(async (file, options) => {
|
|
197
|
+
const res = await withCI(
|
|
198
|
+
(c) =>
|
|
199
|
+
c.diagnostics(file, { timeoutMs: num(options.timeout, "timeout") }),
|
|
200
|
+
options,
|
|
201
|
+
);
|
|
202
|
+
if (!res.available) return reportUnavailable(res);
|
|
203
|
+
if (options.json) return;
|
|
204
|
+
if (!res.diagnostics.length)
|
|
205
|
+
return logger.log(chalk.green("No diagnostics."));
|
|
206
|
+
for (const d of res.diagnostics) {
|
|
207
|
+
const sev =
|
|
208
|
+
d.severity === "error"
|
|
209
|
+
? chalk.red(d.severity)
|
|
210
|
+
: d.severity === "warning"
|
|
211
|
+
? chalk.yellow(d.severity)
|
|
212
|
+
: chalk.gray(d.severity);
|
|
213
|
+
logger.log(
|
|
214
|
+
` ${chalk.gray(`${d.line}:${d.col}`)} ${sev} ${d.message}${d.code ? chalk.gray(` [${d.code}]`) : ""}`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
ci.command("rename <file> <line> <col> <newName>")
|
|
220
|
+
.description(
|
|
221
|
+
"Preview a symbol rename across files (does NOT apply the edit)",
|
|
222
|
+
)
|
|
223
|
+
.option("--json", "Output as JSON")
|
|
224
|
+
.action(async (file, line, col, newName, options) => {
|
|
225
|
+
const res = await withCI(
|
|
226
|
+
(c) =>
|
|
227
|
+
c.renamePreview(file, num(line, "line"), num(col, "col"), newName),
|
|
228
|
+
options,
|
|
229
|
+
);
|
|
230
|
+
if (!res.available) return reportUnavailable(res);
|
|
231
|
+
if (options.json) return;
|
|
232
|
+
const total = res.edits.reduce((n, f) => n + f.edits.length, 0);
|
|
233
|
+
logger.log(
|
|
234
|
+
chalk.bold(
|
|
235
|
+
`Rename would touch ${res.edits.length} file(s), ${total} edit(s):`,
|
|
236
|
+
),
|
|
237
|
+
);
|
|
238
|
+
for (const f of res.edits) {
|
|
239
|
+
logger.log(` ${chalk.cyan(f.file)} — ${f.edits.length} edit(s)`);
|
|
240
|
+
for (const e of f.edits) {
|
|
241
|
+
logger.log(chalk.gray(` ${e.line}:${e.col} → "${e.newText}"`));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
logger.log(
|
|
245
|
+
chalk.gray(
|
|
246
|
+
"\n(preview only — apply with your editor or agent edit tools)",
|
|
247
|
+
),
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return ci;
|
|
252
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc eval` — reliability eval harness (Phase 7). Runs a suite of self-checking
|
|
3
|
+
* coding tasks against the real agent and reports the task-success rate.
|
|
4
|
+
*
|
|
5
|
+
* Each task gets a fresh temp workspace; the agent is invoked headlessly
|
|
6
|
+
* (`cc agent -p` in that cwd with acceptEdits so it can write files) and the
|
|
7
|
+
* task's objective check() decides pass/fail. `--dry-run` swaps in a no-op agent
|
|
8
|
+
* so the harness + report can be exercised without a model.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
import { spawn } from "child_process";
|
|
15
|
+
import { runEvalSuite } from "../lib/eval/runner.js";
|
|
16
|
+
import { getSuite } from "../lib/eval/tasks.js";
|
|
17
|
+
import {
|
|
18
|
+
TelemetryRecorder,
|
|
19
|
+
formatTelemetry,
|
|
20
|
+
} from "../lib/telemetry/span-recorder.js";
|
|
21
|
+
import { computeTrend, formatTrend } from "../lib/eval/trend.js";
|
|
22
|
+
|
|
23
|
+
/** Append a run summary as one JSONL line to the history file. */
|
|
24
|
+
function appendHistory(file, record) {
|
|
25
|
+
fs.appendFileSync(file, JSON.stringify(record) + "\n", "utf8");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Read a JSONL eval-history file into an array of run records (skips bad lines). */
|
|
29
|
+
function readHistory(file) {
|
|
30
|
+
if (!fs.existsSync(file)) return [];
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const line of fs.readFileSync(file, "utf8").split(/\r?\n/)) {
|
|
33
|
+
const t = line.trim();
|
|
34
|
+
if (!t) continue;
|
|
35
|
+
try {
|
|
36
|
+
out.push(JSON.parse(t));
|
|
37
|
+
} catch {
|
|
38
|
+
/* skip a corrupt history line rather than abort the report */
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
45
|
+
// This file is src/commands/eval.js → the CLI entry is bin/chainlesschain.js.
|
|
46
|
+
const BIN = path.resolve(__dirname, "..", "..", "bin", "chainlesschain.js");
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build a runAgent that shells out to a headless `cc agent -p` in the task's
|
|
50
|
+
* workspace. acceptEdits lets it write files without an interactive prompt.
|
|
51
|
+
*/
|
|
52
|
+
function makeHeadlessRunAgent(opts = {}) {
|
|
53
|
+
return function runAgent({ prompt, cwd, timeoutMs }) {
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
const args = [
|
|
56
|
+
BIN,
|
|
57
|
+
"agent",
|
|
58
|
+
"-p",
|
|
59
|
+
prompt,
|
|
60
|
+
"--permission-mode",
|
|
61
|
+
"acceptEdits",
|
|
62
|
+
"--output-format",
|
|
63
|
+
"text",
|
|
64
|
+
];
|
|
65
|
+
if (opts.model) args.push("--model", opts.model);
|
|
66
|
+
if (opts.provider) args.push("--provider", opts.provider);
|
|
67
|
+
const child = spawn(process.execPath, args, {
|
|
68
|
+
cwd,
|
|
69
|
+
env: { ...process.env, CLAUDECODE: "1" },
|
|
70
|
+
windowsHide: true,
|
|
71
|
+
});
|
|
72
|
+
let out = "";
|
|
73
|
+
let err = "";
|
|
74
|
+
let settled = false;
|
|
75
|
+
const done = (result) => {
|
|
76
|
+
if (settled) return;
|
|
77
|
+
settled = true;
|
|
78
|
+
resolve(result);
|
|
79
|
+
};
|
|
80
|
+
const timer = setTimeout(() => {
|
|
81
|
+
try {
|
|
82
|
+
child.kill("SIGTERM");
|
|
83
|
+
} catch {
|
|
84
|
+
/* already gone */
|
|
85
|
+
}
|
|
86
|
+
done({
|
|
87
|
+
ok: false,
|
|
88
|
+
output: out,
|
|
89
|
+
error: `timed out after ${timeoutMs || 120000}ms`,
|
|
90
|
+
});
|
|
91
|
+
}, timeoutMs || 120000);
|
|
92
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
93
|
+
child.stdout?.on("data", (d) => (out += d.toString("utf8")));
|
|
94
|
+
child.stderr?.on("data", (d) => (err += d.toString("utf8")));
|
|
95
|
+
child.on("error", (e) => {
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
done({ ok: false, output: out, error: e.message });
|
|
98
|
+
});
|
|
99
|
+
child.on("close", (code) => {
|
|
100
|
+
clearTimeout(timer);
|
|
101
|
+
done({ ok: code === 0, output: out, error: code === 0 ? null : err });
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function registerEvalCommand(program, { logger } = {}) {
|
|
108
|
+
const log = logger || console;
|
|
109
|
+
program
|
|
110
|
+
.command("eval")
|
|
111
|
+
.description(
|
|
112
|
+
"Run the reliability eval suite (self-checking coding tasks) and report the task-success rate",
|
|
113
|
+
)
|
|
114
|
+
.option("--suite <name>", "Suite to run", "builtin")
|
|
115
|
+
.option("--model <model>", "Model for the agent runs")
|
|
116
|
+
.option("--provider <provider>", "Provider for the agent runs")
|
|
117
|
+
.option("--json", "Output the summary as JSON")
|
|
118
|
+
.option("--keep", "Keep the per-task temp workspaces (debug)")
|
|
119
|
+
.option(
|
|
120
|
+
"--otlp <file>",
|
|
121
|
+
"Write OpenTelemetry (OTLP/JSON) spans for the run to a file",
|
|
122
|
+
)
|
|
123
|
+
.option(
|
|
124
|
+
"--dry-run",
|
|
125
|
+
"Use a no-op agent (exercise the harness/report without a model)",
|
|
126
|
+
)
|
|
127
|
+
.option(
|
|
128
|
+
"--history <file>",
|
|
129
|
+
"Append this run's summary (JSONL) for trend tracking",
|
|
130
|
+
)
|
|
131
|
+
.option(
|
|
132
|
+
"--label <label>",
|
|
133
|
+
"Tag this run in the history (e.g. a version/commit)",
|
|
134
|
+
)
|
|
135
|
+
.option(
|
|
136
|
+
"--trend",
|
|
137
|
+
"Report the pass-rate trend from --history instead of running (CI gate)",
|
|
138
|
+
)
|
|
139
|
+
.option(
|
|
140
|
+
"--regression-threshold <pct>",
|
|
141
|
+
"With --trend: pass-rate drop (in points) that fails the gate on its own",
|
|
142
|
+
"0",
|
|
143
|
+
)
|
|
144
|
+
.action(async (options) => {
|
|
145
|
+
// Trend mode: don't run the suite — read the recorded history and report
|
|
146
|
+
// the pass-rate trend + per-task regressions. This is the release-pipeline
|
|
147
|
+
// consumer (the runs themselves need a real model; the report is pure).
|
|
148
|
+
if (options.trend) {
|
|
149
|
+
if (!options.history) {
|
|
150
|
+
(log.error || console.error)("--trend requires --history <file>");
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const runs = readHistory(options.history);
|
|
155
|
+
const threshold =
|
|
156
|
+
Math.max(0, Number(options.regressionThreshold) || 0) / 100;
|
|
157
|
+
const trend = computeTrend(runs, { regressionThreshold: threshold });
|
|
158
|
+
if (options.json) console.log(JSON.stringify(trend, null, 2));
|
|
159
|
+
else (log.log || console.log)(formatTrend(trend));
|
|
160
|
+
if (trend.regressed) process.exitCode = 1;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let tasks;
|
|
165
|
+
try {
|
|
166
|
+
tasks = getSuite(options.suite);
|
|
167
|
+
} catch (err) {
|
|
168
|
+
log.error ? log.error(err.message) : console.error(err.message);
|
|
169
|
+
process.exitCode = 1;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const runAgent = options.dryRun
|
|
173
|
+
? async () => ({ ok: true, output: "(dry-run: no agent)" })
|
|
174
|
+
: makeHeadlessRunAgent({
|
|
175
|
+
model: options.model,
|
|
176
|
+
provider: options.provider,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// OTel-shaped telemetry for the run (per-task span + failure class).
|
|
180
|
+
const recorder = new TelemetryRecorder({ serviceName: "cc-eval" });
|
|
181
|
+
|
|
182
|
+
const summary = await runEvalSuite(tasks, {
|
|
183
|
+
runAgent,
|
|
184
|
+
recorder,
|
|
185
|
+
keepWorkspaces: options.keep === true,
|
|
186
|
+
onResult: options.json
|
|
187
|
+
? undefined
|
|
188
|
+
: (r) =>
|
|
189
|
+
(log.info || console.log)(
|
|
190
|
+
` ${r.pass ? "✔" : "✗"} ${r.id} (${r.ms}ms)` +
|
|
191
|
+
(r.error
|
|
192
|
+
? ` — ${r.error}`
|
|
193
|
+
: r.detail
|
|
194
|
+
? ` — ${r.detail}`
|
|
195
|
+
: ""),
|
|
196
|
+
),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (options.otlp) {
|
|
200
|
+
try {
|
|
201
|
+
fs.writeFileSync(
|
|
202
|
+
options.otlp,
|
|
203
|
+
JSON.stringify(recorder.toOtlp(), null, 2),
|
|
204
|
+
"utf8",
|
|
205
|
+
);
|
|
206
|
+
} catch (e) {
|
|
207
|
+
(log.error || console.error)(` otlp write failed: ${e.message}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Append to the trend history (a compact record — pass counts + per-task
|
|
212
|
+
// pass/fail + a timestamp/label — so `cc eval --trend` can chart it).
|
|
213
|
+
if (options.history) {
|
|
214
|
+
try {
|
|
215
|
+
appendHistory(options.history, {
|
|
216
|
+
ranAt: new Date().toISOString(),
|
|
217
|
+
label: options.label || null,
|
|
218
|
+
passed: summary.passed,
|
|
219
|
+
total: summary.total,
|
|
220
|
+
passRate: summary.passRate,
|
|
221
|
+
results: (summary.results || []).map((r) => ({
|
|
222
|
+
id: r.id,
|
|
223
|
+
pass: r.pass,
|
|
224
|
+
})),
|
|
225
|
+
});
|
|
226
|
+
} catch (e) {
|
|
227
|
+
(log.error || console.error)(` history write failed: ${e.message}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (options.json) {
|
|
232
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
233
|
+
} else {
|
|
234
|
+
// Per-task lines already streamed via onResult; print the summary +
|
|
235
|
+
// the telemetry metrics (durations / failure classification).
|
|
236
|
+
const pct = (summary.passRate * 100).toFixed(1);
|
|
237
|
+
(log.log || console.log)(
|
|
238
|
+
`\nEval: ${summary.passed}/${summary.total} passed (${pct}%) in ${summary.ms}ms`,
|
|
239
|
+
);
|
|
240
|
+
if (summary.telemetry) {
|
|
241
|
+
(log.log || console.log)("\n" + formatTelemetry(summary.telemetry));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Non-zero exit when not every task passed — usable as a CI gate.
|
|
245
|
+
if (summary.passed < summary.total) process.exitCode = 1;
|
|
246
|
+
});
|
|
247
|
+
return program;
|
|
248
|
+
}
|