chainlesschain 0.162.151 → 0.162.153
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-DuEOzebi.js → AIOps-CBilhs1R.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C6GiJa5H.js → ActionButton-Cf-RnC5Y.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BBIiL_pO.js → Analytics-S8tkGhw0.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CuI2gZRy.js → AppLayout-CNXI3Bw5.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-CbUjfr-K.js → Audit-DF2zVFZ0.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CsSW9ljf.js → Backup-CMEiwQZL.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-kM3rLe7F.js → BaseInput-rwLw4K70.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-kfE51YN3.js → Chat-C478H8u9.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DNQsKN61.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-jYb1uj-M.js → Checkbox-D-47X635.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-X9XiD5Lj.js → Codegen-Cb9Ihed5.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BfbHu1xI.js → Col-CQsdzczt.js} +1 -1
- package/src/assets/web-panel/assets/{Community-c4oJMFS-.js → Community-DiqzeAy-.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BFmnZpH7.js → Compact-Bq-APyyF.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-s9shVHBS.js → Compliance-Dnb1YxPr.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-C5da--TC.js → Cowork-CZljerdQ.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-9kNbyNE4.js → Cron-gAdbZOq7.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-C1k3NJD4.js → Crosschain-DMPGXttD.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DkheEvNK.js → DID-C7dBDAv8.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C3FuSGmJ.js → Dashboard-ByR4VcF8.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CAV6FMFD.js → Dropdown-Bc4tbiQN.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-Cc-Ulc4l.js → EmailListRenderer-BhUN2pDw.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-8CitHEtv.js → FamilyGuardDashboard-DpJuANCD.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DFSZ5KDt.js → Federation-BEm4TvcE.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CEWCtnG2.js → FormItemContext-JnkPkhiC.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CwRzNzmX.js → GenericCardRenderer-BfCzFUIC.js} +1 -1
- package/src/assets/web-panel/assets/{Git-0rgDM7cJ.js → Git-1c0MWpmD.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CfBKtK9F.js → Governance-C_j3EBpv.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CzcUVvud.js → Inference-Cb7XRgtY.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Dwc4YL4A.js → KnowledgeGraph-DoHPvHyK.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DgFPwR2F.js → Logs-CYriKpy-.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-DnpPTbGU.js → Marketplace-BT56-GD0.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DRxxINyW.js → McpTools-B6XX_wnZ.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-OhmW_6Z3.js → Memory-DRgNuaQc.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DkTW-RK5.js → MobileBridge-B0qgvBN2.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-CRRfswf7.js +1 -0
- package/src/assets/web-panel/assets/{Mtc--vmkL0AS.js → Mtc-DnSFj9jw.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-DGoFWjD4.js → MtcAudit-c0tuz1sm.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-B4kWgq95.js → Multisig-CVLBGioX.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-YQwvommE.js → NLProgramming-CFaqmNbx.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CgjtUADJ.js → Notes-BM_mNwU_.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-6JDrpBG5.js → NotificationSettings-Sa1k3ReS.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-lWzmtqBh.js +1 -0
- package/src/assets/web-panel/assets/{Organization-8McOT_OF.js → Organization-C2blcq-P.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DAZpSCGc.js → Overflow-B3PwOJnK.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-B7l2ZWLy.js → P2P-DaB9T6tb.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-W1Ud-NAL.js → PdhVaultBrowser-BpEBZ72n.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-Czm_w9u_.js → Permissions-BTkWInyH.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B4F0_ZVM.js → PersonalDataHub-LHEwNmyL.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-B37aFiWv.js → Pipeline-DvWIxqH-.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-94KBnRrD.js → Privacy-BDbpBagU.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B5h8_dlh.js → ProjectInit-DLeMDWWv.js} +2 -2
- package/src/assets/web-panel/assets/ProjectSettings-BK3NsxIz.js +2 -0
- package/src/assets/web-panel/assets/Projects-BPWPg9zA.js +1 -0
- package/src/assets/web-panel/assets/{Providers-B3cNWwJg.js → Providers-D2EvmPAd.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CHRvOw1R.js → QrScannerModal-DAcu2fNg.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D1JMgFEd.js → QuickAsk-B7U850Yt.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-EYWGR79p.js → Recommend-bxNXLzOR.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BAMC2pJt.js → RemoteSession-BsCjAfSJ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-X2Hk1XG_.js → Reputation-DZ9LPu-R.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Eq98LRtU.js → Row-cIYkCB3Y.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-i76s6z_o.js → RssFeed-BxTNTtTp.js} +2 -2
- package/src/assets/web-panel/assets/{Search-D_Es7CAI.js → Search-DSar6GhE.js} +1 -1
- package/src/assets/web-panel/assets/{Security-kayD2e94.js → Security-oCbIGysL.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Ctsm6ul8.js → Services-D8yojrNv.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CRNYlfdf.js → Skeleton-vTA6P1eL.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DkZYpF4-.js → Skills-BXLf_KgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DXkoBcOP.js → Sla-Cpwxzz__.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DXi_GI1d.js → SpeechSettings-DcPN9kCb.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-rNKpfomn.js → SyncSettings-DY0U5Vuj.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-XF4uPtG-.js → Tasks-DKu3-sZJ.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-i0Hzfeyu.js → Templates-MD3nfWGm.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-sMpHAi27.js → Tenant-DKVnyGXM.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-DQMIZfWf.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-yuC6K7Rf.js → TimelineRenderer-CugmNZTs.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B8O8i0s6.js → Tokens-Cjvlttu6.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Bv6yrlCr.js → Trigger-CzNOEcoI.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-C4mW95Ev.js → Trust-D5jg9iPA.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DV6yKaHn.js → UkeySign-59bMlvxY.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-UI479-sD.js → VideoEditing-DmCzSBqn.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-M5oV9EVP.js → Wallet-DoFe8V6W.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DDyDHPDR.js → WebAuthn-9POLER-w.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-RoBv4rqk.js → WorkflowEditor-cFQH0Og6.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Cw1mE5LS.js → chat-D3fR2NkZ.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BFP62Gwf.js → colors-DiLEwE_P.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-17HL6pyC.js → compact-item-CGfFDdic.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D55X4fZX.js → createContext-BbIbOPL2.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-B6FRgsmP.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D3E5mNsP.js → hasIn-DqyWp63_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOjA8bvj.js → index-BCoDp6o_.js} +1 -1
- package/src/assets/web-panel/assets/{index-tVRPgYGr.js → index-BKeRBUtO.js} +1 -1
- package/src/assets/web-panel/assets/{index-RYZgFIwo.js → index-BKxvHCqz.js} +1 -1
- package/src/assets/web-panel/assets/{index-Da27u6j0.js → index-BiLP6SNu.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFYGn88j.js → index-BtcjYHgn.js} +1 -1
- package/src/assets/web-panel/assets/{index-paVubXzn.js → index-BtwvOuvO.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4LHSde4.js → index-ByE5tKjP.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_MfcrLf.js → index-C1S30j-Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkBVYlE4.js → index-C2lZXIEA.js} +1 -1
- package/src/assets/web-panel/assets/{index-ITeEHb8L.js → index-CH8gSMSA.js} +1 -1
- package/src/assets/web-panel/assets/{index-BC6zxOlU.js → index-CHpI6g_S.js} +1 -1
- package/src/assets/web-panel/assets/{index-KtLJXn4s.js → index-CIleIMTT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BY_xZ2jy.js → index-CToOzfR2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bzpp2z2S.js → index-CZQshOyI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CvCFKojj.js → index-ComvO4hy.js} +1 -1
- package/src/assets/web-panel/assets/index-Cq411qtc.js +1 -0
- package/src/assets/web-panel/assets/{index-tUH_6bdJ.js → index-CweXQM71.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cdvk2_2q.js → index-CySlHabI.js} +1 -1
- package/src/assets/web-panel/assets/{index-gAVxDiTZ.js → index-D16FSRMW.js} +1 -1
- package/src/assets/web-panel/assets/index-D1oX0DK3.js +1 -0
- package/src/assets/web-panel/assets/{index-CLEzsZ8A.js → index-D3vQv3Kq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEa1RW4c.js → index-DH6qaU1a.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQmZg5si.js → index-DPxmTldu.js} +1 -1
- package/src/assets/web-panel/assets/{index-ASPYTzMK.js → index-DQH--Uw5.js} +1 -1
- package/src/assets/web-panel/assets/{index-uSsiwgZ2.js → index-Db9UJVjj.js} +1 -1
- package/src/assets/web-panel/assets/{index-CR9rNUvi.js → index-DdLwxj-F.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq83UBDr.js → index-DdjXemK-.js} +1 -1
- package/src/assets/web-panel/assets/{index-H9_X1Cg_.js → index-DzuGkFvy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DD_qGBrt.js → index-FFlp8Jx9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnGpft-Z.js → index-Km36XQ3z.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjCwi7we.js → index-auI9fxYH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzG7mkgW.js → index-fCfaVIr7.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtAnPBWP.js → index-hVGbmc7y.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCLu84x-.js → index-kL8f4MRS.js} +1 -1
- package/src/assets/web-panel/assets/{index--44J50mc.js → index-ns6bNnGo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW6LLoJO.js → index-qHvMk0U3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIRvdwBX.js → index-rTrejDjk.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGyTos4p.js → index-tLaW5UzZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BgN5G5vF.js → index-xm1KHUEQ.js} +27 -27
- package/src/assets/web-panel/assets/{initDefaultProps-Ckp7xVZS.js → initDefaultProps-pg_7pnd6.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DUZgCpn6.js → motion-B5GoJSZL.js} +1 -1
- package/src/assets/web-panel/assets/{move-B2rttglH.js → move-BaJoe2FW.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BYWcLTuN.js → mtc-parser-CiQGbqtr.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DhHqKeFx.js → omit-BFNEsKvU.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-ANpJaWMO.js → pickAttrs-YbSoANHm.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CfZWe7CA.js → placementArrow-C40MJPIH.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D7Xz2y-R.js → responsiveObserve-LaVz2zF6.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DekqCBY9.js → slide-BkSoAGxF.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BET6XU7h.js → statusUtils-C4jWjohA.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-qHmJjV62.js → styleChecker-BGqeIh-m.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BoMCTNyu.js → useFlexGapSupport-JsR5NMrM.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-TdW-NgFC.js → useFs-DOiP38RR.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-Dyox7wCu.js → usePersonalDataHub-C-nC0ymt.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-XUn5S8CP.js → vnode-BalilHOU.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Ls77i8hn.js → zoom-DjUELqks.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +8 -1
- package/src/commands/eval.js +88 -23
- package/src/commands/plugin.js +10 -0
- package/src/commands/team.js +60 -3
- package/src/data/changelog.json +17 -2
- package/src/harness/mcp-client.js +115 -1
- package/src/harness/remote-command-ledger.js +60 -10
- package/src/lib/agent-sandbox.js +11 -5
- package/src/lib/agent-team/task-lease.js +28 -0
- package/src/lib/agent-team/team-runner.js +45 -0
- package/src/lib/config-manager.js +14 -1
- package/src/lib/eval/tasks.js +62 -41
- package/src/lib/eval/trend.js +7 -1
- package/src/lib/lsp/__tests__/lsp-client.test.js +12 -6
- package/src/lib/lsp/code-intelligence.js +55 -17
- package/src/lib/lsp/lsp-client.js +7 -1
- package/src/lib/plugin-runtime/install.js +20 -1
- package/src/lib/plugin-runtime/policy.js +13 -0
- package/src/lib/plugin-runtime/remote-source.js +34 -0
- package/src/lib/plugin-runtime/signature.js +79 -22
- package/src/lib/plugin-security.js +13 -14
- package/src/lib/sub-agent-context.js +28 -7
- package/src/lib/telemetry/span-recorder.js +30 -7
- package/src/repl/agent-repl.js +64 -21
- package/src/repl/permission-prompt.js +58 -0
- package/src/runtime/__tests__/auto-pin.test.js +27 -4
- package/src/runtime/agent-core.js +236 -1
- package/src/runtime/auto-pin.js +19 -0
- package/src/runtime/coding-agent-contract-shared.cjs +5 -0
- package/src/runtime/headless-runner.js +23 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Bg2FTW6A.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-DpCGV_lI.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-PM6IlxjO.js +0 -1
- package/src/assets/web-panel/assets/ProjectSettings-lmeI3Lpm.js +0 -2
- package/src/assets/web-panel/assets/Projects-D5AYOasl.js +0 -1
- package/src/assets/web-panel/assets/Terminal-BoZvaYAl.js +0 -3
- package/src/assets/web-panel/assets/devWarning-CqbHYuRc.js +0 -1
- package/src/assets/web-panel/assets/index-CKBI1U5K.js +0 -1
- package/src/assets/web-panel/assets/index-CkLp6DTO.js +0 -1
|
@@ -80,16 +80,19 @@ export function verifyPluginManifest({
|
|
|
80
80
|
|
|
81
81
|
const wantsSignature = requireSignature || signatureFile || publicKeyFile;
|
|
82
82
|
let signatureVerified = false;
|
|
83
|
+
let signature = null;
|
|
84
|
+
let publicKeyPem = null;
|
|
85
|
+
let publicKeySha256 = null;
|
|
83
86
|
if (wantsSignature) {
|
|
84
87
|
if (!signatureFile || !publicKeyFile) {
|
|
85
88
|
throw new Error(
|
|
86
89
|
"plugin signature verification requires --signature and --public-key",
|
|
87
90
|
);
|
|
88
91
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const keyObject = createPublicKey(
|
|
92
|
-
|
|
92
|
+
signature = readFileSync(signatureFile);
|
|
93
|
+
publicKeyPem = readFileSync(publicKeyFile, "utf8");
|
|
94
|
+
const keyObject = createPublicKey(publicKeyPem);
|
|
95
|
+
publicKeySha256 = createHash("sha256")
|
|
93
96
|
.update(keyObject.export({ type: "spki", format: "der" }))
|
|
94
97
|
.digest("hex");
|
|
95
98
|
const trusted = stringSet(trustedKeySha256);
|
|
@@ -110,16 +113,12 @@ export function verifyPluginManifest({
|
|
|
110
113
|
bytes,
|
|
111
114
|
sha256,
|
|
112
115
|
signatureVerified,
|
|
113
|
-
publicKeySha256: signatureVerified
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}),
|
|
120
|
-
)
|
|
121
|
-
.digest("hex")
|
|
122
|
-
: null,
|
|
116
|
+
publicKeySha256: signatureVerified ? publicKeySha256 : null,
|
|
117
|
+
// The raw signature material, so the installer can persist it and load-time
|
|
118
|
+
// enforcement can CRYPTOGRAPHICALLY re-verify (not merely trust a recorded
|
|
119
|
+
// boolean, which a hand-written lock file could forge).
|
|
120
|
+
signatureBase64: signatureVerified ? signature.toString("base64") : null,
|
|
121
|
+
publicKeyPem: signatureVerified ? publicKeyPem : null,
|
|
123
122
|
};
|
|
124
123
|
}
|
|
125
124
|
|
|
@@ -336,13 +336,19 @@ export class SubAgentContext {
|
|
|
336
336
|
|
|
337
337
|
// Check abort signal
|
|
338
338
|
if (this._signal?.aborted) {
|
|
339
|
-
this.forceComplete("cancelled"
|
|
339
|
+
this.forceComplete("cancelled", {
|
|
340
|
+
partialContent: lastContent,
|
|
341
|
+
artifacts,
|
|
342
|
+
});
|
|
340
343
|
break;
|
|
341
344
|
}
|
|
342
345
|
|
|
343
346
|
// Enforce token budget
|
|
344
347
|
if (this.tokenBudget && this._tokenCount >= this.tokenBudget) {
|
|
345
|
-
this.forceComplete("token-budget-exceeded"
|
|
348
|
+
this.forceComplete("token-budget-exceeded", {
|
|
349
|
+
partialContent: lastContent,
|
|
350
|
+
artifacts,
|
|
351
|
+
});
|
|
346
352
|
break;
|
|
347
353
|
}
|
|
348
354
|
|
|
@@ -355,9 +361,17 @@ export class SubAgentContext {
|
|
|
355
361
|
} catch (err) {
|
|
356
362
|
this.status = "failed";
|
|
357
363
|
this.completedAt = new Date().toISOString();
|
|
364
|
+
// Return partial work to the parent instead of discarding it: the
|
|
365
|
+
// summary is the only channel the parent model sees, so a mid-run API
|
|
366
|
+
// error (rate limit, network drop) must not erase what was already
|
|
367
|
+
// produced. Artifacts collected before the failure are kept as-is.
|
|
368
|
+
const partial =
|
|
369
|
+
lastContent && lastContent.length > 0
|
|
370
|
+
? `\n\nPartial output before failure:\n${this.summarize(lastContent)}`
|
|
371
|
+
: "";
|
|
358
372
|
this.result = {
|
|
359
|
-
summary: `Sub-agent failed: ${err.message}`,
|
|
360
|
-
artifacts
|
|
373
|
+
summary: `Sub-agent failed: ${err.message}${partial}`,
|
|
374
|
+
artifacts,
|
|
361
375
|
tokenCount: this._tokenCount,
|
|
362
376
|
toolsUsed: [...new Set(this._toolsUsed)],
|
|
363
377
|
iterationCount: this._iterationCount,
|
|
@@ -447,15 +461,22 @@ export class SubAgentContext {
|
|
|
447
461
|
/**
|
|
448
462
|
* Force-complete this sub-agent (e.g. on timeout or parent cancellation).
|
|
449
463
|
* @param {string} [reason] - Reason for force-completion
|
|
464
|
+
* @param {{partialContent?: string, artifacts?: Array}} [partial] - Work
|
|
465
|
+
* produced before the cutoff; returned to the parent instead of being
|
|
466
|
+
* discarded (a truncated run should still hand over what it has).
|
|
450
467
|
*/
|
|
451
|
-
forceComplete(reason = "forced") {
|
|
468
|
+
forceComplete(reason = "forced", partial = {}) {
|
|
452
469
|
if (this.status === "active") {
|
|
453
470
|
this.status = "completed";
|
|
454
471
|
this.completedAt = new Date().toISOString();
|
|
455
472
|
if (!this.result) {
|
|
473
|
+
const partialText =
|
|
474
|
+
partial.partialContent && partial.partialContent.length > 0
|
|
475
|
+
? `\n\nPartial output before cutoff:\n${this.summarize(partial.partialContent)}`
|
|
476
|
+
: "";
|
|
456
477
|
this.result = {
|
|
457
|
-
summary: `(Sub-agent force-completed: ${reason})`,
|
|
458
|
-
artifacts: [],
|
|
478
|
+
summary: `(Sub-agent force-completed: ${reason})${partialText}`,
|
|
479
|
+
artifacts: Array.isArray(partial.artifacts) ? partial.artifacts : [],
|
|
459
480
|
tokenCount: this._tokenCount,
|
|
460
481
|
toolsUsed: [...new Set(this._toolsUsed)],
|
|
461
482
|
iterationCount: this._iterationCount,
|
|
@@ -22,27 +22,46 @@ function spanId() {
|
|
|
22
22
|
|
|
23
23
|
// One trace per recorder (a "run"). The OTLP/OTel spec treats an ALL-ZERO
|
|
24
24
|
// traceId as INVALID, so a strict collector would drop every span exported with
|
|
25
|
-
// `"0".repeat(32)` — defeating toOtlp()'s purpose.
|
|
26
|
-
//
|
|
25
|
+
// `"0".repeat(32)` — defeating toOtlp()'s purpose. A bare counter is non-zero
|
|
26
|
+
// but resets every PROCESS, so successive CLI runs all exported trace
|
|
27
|
+
// `000…001` and a collector merged them into one giant trace. Prefix the
|
|
28
|
+
// counter with per-process entropy (start time + pid — RNG-free, so ids stay
|
|
29
|
+
// deterministic WITHIN a run) to make traces practically unique ACROSS runs.
|
|
30
|
+
const _traceBase = (
|
|
31
|
+
Date.now().toString(16).padStart(12, "0") +
|
|
32
|
+
(process.pid >>> 0).toString(16).padStart(8, "0")
|
|
33
|
+
).slice(0, 20);
|
|
27
34
|
let _traceSeq = 0;
|
|
28
35
|
function newTraceId() {
|
|
29
36
|
_traceSeq = (_traceSeq + 1) % Number.MAX_SAFE_INTEGER;
|
|
30
|
-
return _traceSeq.toString(16).padStart(
|
|
37
|
+
return _traceBase + _traceSeq.toString(16).padStart(12, "0"); // 32 hex, never all-zero
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
export class TelemetryRecorder {
|
|
34
41
|
constructor({
|
|
35
42
|
now = () => Date.now(),
|
|
36
43
|
serviceName = "chainlesschain-cli",
|
|
44
|
+
defaultAttributes = {},
|
|
37
45
|
} = {}) {
|
|
38
46
|
this._now = typeof now === "function" ? now : () => now;
|
|
39
47
|
this.serviceName = serviceName;
|
|
40
48
|
this.traceId = newTraceId(); // one trace per recorder (valid non-zero id)
|
|
49
|
+
// Stamped onto EVERY span (per-span attributes win on key collision).
|
|
50
|
+
// Used for run-level correlation: workflow.run_id / workflow.name let a
|
|
51
|
+
// collector group all model/tool/task spans of one run (Claude-Code
|
|
52
|
+
// 2.1.202 workflow-tracing attributes).
|
|
53
|
+
this.defaultAttributes = { ...defaultAttributes };
|
|
41
54
|
this._spans = []; // completed spans
|
|
42
55
|
this._counters = new Map(); // name → { total, byAttr }
|
|
43
56
|
this._failures = new Map(); // category → count
|
|
44
57
|
}
|
|
45
58
|
|
|
59
|
+
/** Set (or overwrite) an attribute stamped onto every span from now on. */
|
|
60
|
+
setDefaultAttribute(key, value) {
|
|
61
|
+
this.defaultAttributes[key] = value;
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
46
65
|
/**
|
|
47
66
|
* Start a span. Returns a handle; call `.end()` (optionally with a status /
|
|
48
67
|
* extra attributes) to record it. Nesting is expressed via `parentId`.
|
|
@@ -50,7 +69,7 @@ export class TelemetryRecorder {
|
|
|
50
69
|
startSpan(name, attributes = {}, { parentId = null } = {}) {
|
|
51
70
|
const id = spanId();
|
|
52
71
|
const start = this._now();
|
|
53
|
-
const attrs = { ...attributes };
|
|
72
|
+
const attrs = { ...this.defaultAttributes, ...attributes };
|
|
54
73
|
const events = [];
|
|
55
74
|
const self = this;
|
|
56
75
|
let ended = false;
|
|
@@ -186,8 +205,12 @@ export class TelemetryRecorder {
|
|
|
186
205
|
spanId: s.id,
|
|
187
206
|
parentSpanId: s.parentId || "",
|
|
188
207
|
name: s.name,
|
|
189
|
-
|
|
190
|
-
|
|
208
|
+
// proto3 JSON mapping: (s)fixed64/(u)int64 fields MUST be
|
|
209
|
+
// decimal STRINGS — ms×1e6 ≈ 1.8e18 exceeds 2^53, so a JSON
|
|
210
|
+
// number both violates the OTLP/JSON spec (strict collectors
|
|
211
|
+
// reject the span) and quantizes (~256 ns spacing).
|
|
212
|
+
startTimeUnixNano: String(Math.round(s.startTime * 1e6)),
|
|
213
|
+
endTimeUnixNano: String(Math.round(s.endTime * 1e6)),
|
|
191
214
|
status: { code: s.status === "error" ? 2 : 1 },
|
|
192
215
|
attributes: Object.entries(s.attributes).map(([k, v]) => ({
|
|
193
216
|
key: k,
|
|
@@ -200,7 +223,7 @@ export class TelemetryRecorder {
|
|
|
200
223
|
})),
|
|
201
224
|
events: s.events.map((e) => ({
|
|
202
225
|
name: e.name,
|
|
203
|
-
timeUnixNano: e.time * 1e6,
|
|
226
|
+
timeUnixNano: String(Math.round(e.time * 1e6)),
|
|
204
227
|
attributes: Object.entries(e.attributes).map(([k, v]) => ({
|
|
205
228
|
key: k,
|
|
206
229
|
value: { stringValue: String(v) },
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -64,7 +64,10 @@ import {
|
|
|
64
64
|
PromptCompressor,
|
|
65
65
|
getContextWindow,
|
|
66
66
|
} from "../harness/prompt-compressor.js";
|
|
67
|
-
import {
|
|
67
|
+
import {
|
|
68
|
+
buildAutoPinPredicate,
|
|
69
|
+
resolveAutoPinOption,
|
|
70
|
+
} from "../runtime/auto-pin.js";
|
|
68
71
|
import { feature } from "../lib/feature-flags.js";
|
|
69
72
|
import { recordCompressionMetric } from "../lib/compression-telemetry.js";
|
|
70
73
|
import {
|
|
@@ -102,7 +105,11 @@ import { parseThinkCommand, parseEffortCommand } from "./think-command.js";
|
|
|
102
105
|
import { parseBtwCommand, buildAsideBlock, applyAside } from "./btw-command.js";
|
|
103
106
|
import { shouldStreamLive } from "./stream-decision.js";
|
|
104
107
|
import { emptyTurnNotice } from "./empty-turn-notice.js";
|
|
105
|
-
import {
|
|
108
|
+
import {
|
|
109
|
+
buildPermissionPrompt,
|
|
110
|
+
resolveAskIdleTimeoutMs,
|
|
111
|
+
questionWithIdleTimeout,
|
|
112
|
+
} from "./permission-prompt.js";
|
|
106
113
|
import {
|
|
107
114
|
parsePermissionTier,
|
|
108
115
|
describeTier,
|
|
@@ -417,15 +424,22 @@ export async function startAgentRepl(options = {}) {
|
|
|
417
424
|
// Unset → agent-core's 180s default (matches cc chat/ask). Set to 0 to
|
|
418
425
|
// disable. Left undefined here means "use the default".
|
|
419
426
|
let _streamStallTimeoutMs;
|
|
420
|
-
// Auto-pin (
|
|
421
|
-
//
|
|
422
|
-
//
|
|
423
|
-
|
|
427
|
+
// Auto-pin (default ON since 2026-07-07): compaction pins the original task
|
|
428
|
+
// (first user turn) so it survives context compression. Resolution order:
|
|
429
|
+
// CC_AUTO_PIN env ("1"/"0") > config `context.autoPin` (true/false/object) >
|
|
430
|
+
// default on. See resolveAutoPinOption.
|
|
431
|
+
let _autoPinCfgValue;
|
|
432
|
+
// Idle timeout for interactive permission prompts (0 = wait forever).
|
|
433
|
+
// CC_PERMISSION_ASK_TIMEOUT_MS env > config permissions.askTimeoutMs > off.
|
|
434
|
+
let _askIdleTimeoutMs = resolveAskIdleTimeoutMs();
|
|
424
435
|
try {
|
|
425
436
|
const { loadConfig } = await import("../lib/config-manager.js");
|
|
426
437
|
const _cfg = loadConfig();
|
|
427
438
|
_visionModel = _cfg?.llm?.visionModel || undefined;
|
|
428
|
-
|
|
439
|
+
_autoPinCfgValue = _cfg?.context?.autoPin;
|
|
440
|
+
_askIdleTimeoutMs = resolveAskIdleTimeoutMs({
|
|
441
|
+
config: _cfg?.permissions?.askTimeoutMs,
|
|
442
|
+
});
|
|
429
443
|
const raw = _cfg?.llm?.streamStallTimeoutMs;
|
|
430
444
|
const t = Number(raw);
|
|
431
445
|
// Accept 0 (explicit disable) — only ignore absent/invalid values.
|
|
@@ -483,8 +497,8 @@ export async function startAgentRepl(options = {}) {
|
|
|
483
497
|
if (feature("PROMPT_COMPRESSOR")) {
|
|
484
498
|
_compressor = new PromptCompressor({ model, provider });
|
|
485
499
|
}
|
|
486
|
-
|
|
487
|
-
// Compaction options shared by /compact + auto-compact. Adds the
|
|
500
|
+
const _autoPinOpt = resolveAutoPinOption({ config: _autoPinCfgValue });
|
|
501
|
+
// Compaction options shared by /compact + auto-compact. Adds the
|
|
488
502
|
// pin predicate only when auto-pin is enabled; otherwise byte-identical.
|
|
489
503
|
const _compactOpts = (msgs) => {
|
|
490
504
|
const base = { preserveToolPairs: true };
|
|
@@ -555,17 +569,24 @@ export async function startAgentRepl(options = {}) {
|
|
|
555
569
|
});
|
|
556
570
|
const q = (p) => new Promise((res) => rlConfirm.question(p, res));
|
|
557
571
|
const cmd = args?.command ? ` ${args.command}` : "";
|
|
558
|
-
const
|
|
559
|
-
|
|
572
|
+
const res = await questionWithIdleTimeout(
|
|
573
|
+
q,
|
|
574
|
+
chalk.yellow(
|
|
575
|
+
`\n[ApprovalGate] ${riskLevel || "medium"} risk command:${cmd}\n` +
|
|
576
|
+
` Proceed? [y]es once / [a]lways allow / [N]o: `,
|
|
577
|
+
),
|
|
578
|
+
_askIdleTimeoutMs,
|
|
579
|
+
);
|
|
580
|
+
rlConfirm.close();
|
|
581
|
+
if (res.timedOut) {
|
|
582
|
+
process.stdout.write(
|
|
560
583
|
chalk.yellow(
|
|
561
|
-
`\n
|
|
562
|
-
` Proceed? [y]es once / [a]lways allow / [N]o: `,
|
|
584
|
+
`\n ⏱ no response in ${_askIdleTimeoutMs}ms — auto-denied\n`,
|
|
563
585
|
),
|
|
564
|
-
)
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
rlConfirm.close();
|
|
586
|
+
);
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
const ans = res.answer.trim().toLowerCase();
|
|
569
590
|
if (ans === "a" || ans === "always") {
|
|
570
591
|
const saved = await _persistAlwaysAllow(tool || "run_shell", args);
|
|
571
592
|
if (saved) {
|
|
@@ -621,10 +642,21 @@ export async function startAgentRepl(options = {}) {
|
|
|
621
642
|
// (settings/hook ask) or a `reason` (destructive-git / sensitive-file
|
|
622
643
|
// guards) — avoids the literal "null" the old template printed.
|
|
623
644
|
const header = buildPermissionPrompt({ tool, args, rule, reason });
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
.
|
|
645
|
+
const res = await questionWithIdleTimeout(
|
|
646
|
+
q,
|
|
647
|
+
chalk.yellow(`\n${header}\n Proceed? (y/N) `),
|
|
648
|
+
_askIdleTimeoutMs,
|
|
649
|
+
);
|
|
627
650
|
rl.close();
|
|
651
|
+
if (res.timedOut) {
|
|
652
|
+
process.stdout.write(
|
|
653
|
+
chalk.yellow(
|
|
654
|
+
`\n ⏱ no response in ${_askIdleTimeoutMs}ms — auto-denied\n`,
|
|
655
|
+
),
|
|
656
|
+
);
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
const ans = res.answer.trim().toLowerCase();
|
|
628
660
|
return ans === "y" || ans === "yes";
|
|
629
661
|
};
|
|
630
662
|
} catch (_err) {
|
|
@@ -2379,6 +2411,17 @@ export async function startAgentRepl(options = {}) {
|
|
|
2379
2411
|
const expanded = target.replace(/^~(?=$|[\\/])/, os.homedir());
|
|
2380
2412
|
process.chdir(path.resolve(process.cwd(), expanded));
|
|
2381
2413
|
logger.log(chalk.green(`cwd → ${process.cwd()}`));
|
|
2414
|
+
// MCP roots derive from cwd — tell connected servers to re-query
|
|
2415
|
+
// roots/list (Claude-Code 2.1.203 change-notification parity).
|
|
2416
|
+
for (const c of [_adhocMcp?.mcpClient, _bundleMcpClient]) {
|
|
2417
|
+
if (c && typeof c.notifyRootsListChanged === "function") {
|
|
2418
|
+
try {
|
|
2419
|
+
c.notifyRootsListChanged();
|
|
2420
|
+
} catch {
|
|
2421
|
+
/* best-effort */
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2382
2425
|
} catch (err) {
|
|
2383
2426
|
logger.error(`/cd failed: ${err.message}`);
|
|
2384
2427
|
}
|
|
@@ -24,3 +24,61 @@ export function buildPermissionPrompt({ tool, args, rule, reason } = {}) {
|
|
|
24
24
|
if (reason) return `[Permission] ${reason}`;
|
|
25
25
|
return `[Permission] confirm ${tool}:${detail}`;
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the idle timeout (ms) for interactive permission prompts.
|
|
30
|
+
*
|
|
31
|
+
* An unanswered prompt blocks the whole agent turn forever (e.g. the user
|
|
32
|
+
* walked away mid-run). With a timeout configured, the prompt auto-denies
|
|
33
|
+
* after `ms` of silence — deny is the only safe unattended answer.
|
|
34
|
+
*
|
|
35
|
+
* Precedence: CC_PERMISSION_ASK_TIMEOUT_MS env > config
|
|
36
|
+
* `permissions.askTimeoutMs` > default 0 (disabled — waits forever, the
|
|
37
|
+
* historical behavior). Non-finite / non-positive values disable it.
|
|
38
|
+
*
|
|
39
|
+
* @param {{env?: string, config?: unknown}} [opts] - injectable for tests
|
|
40
|
+
* @returns {number} timeout in ms, 0 = disabled
|
|
41
|
+
*/
|
|
42
|
+
export function resolveAskIdleTimeoutMs({ env, config } = {}) {
|
|
43
|
+
const envRaw =
|
|
44
|
+
env !== undefined ? env : process.env.CC_PERMISSION_ASK_TIMEOUT_MS;
|
|
45
|
+
const candidate =
|
|
46
|
+
envRaw !== undefined && envRaw !== null && envRaw !== ""
|
|
47
|
+
? Number(envRaw)
|
|
48
|
+
: typeof config === "number" || typeof config === "string"
|
|
49
|
+
? Number(config)
|
|
50
|
+
: NaN; // booleans/objects are not a timeout — disabled
|
|
51
|
+
return Number.isFinite(candidate) && candidate > 0 ? candidate : 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Race an interactive question against an idle timeout.
|
|
56
|
+
*
|
|
57
|
+
* `ask` is the readline-question-as-promise (never rejects). On timeout the
|
|
58
|
+
* caller must still close its readline interface; the stranded question
|
|
59
|
+
* callback becomes a no-op once the interface is closed.
|
|
60
|
+
*
|
|
61
|
+
* @param {(prompt: string) => Promise<string>} ask
|
|
62
|
+
* @param {string} prompt
|
|
63
|
+
* @param {number} timeoutMs - 0/negative = no timeout (plain await)
|
|
64
|
+
* @returns {Promise<{answer: string|null, timedOut: boolean}>}
|
|
65
|
+
*/
|
|
66
|
+
export async function questionWithIdleTimeout(ask, prompt, timeoutMs) {
|
|
67
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
68
|
+
return { answer: await ask(prompt), timedOut: false };
|
|
69
|
+
}
|
|
70
|
+
let timer = null;
|
|
71
|
+
try {
|
|
72
|
+
return await Promise.race([
|
|
73
|
+
ask(prompt).then((answer) => ({ answer, timedOut: false })),
|
|
74
|
+
new Promise((res) => {
|
|
75
|
+
timer = setTimeout(
|
|
76
|
+
() => res({ answer: null, timedOut: true }),
|
|
77
|
+
timeoutMs,
|
|
78
|
+
);
|
|
79
|
+
}),
|
|
80
|
+
]);
|
|
81
|
+
} finally {
|
|
82
|
+
if (timer) clearTimeout(timer);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* auto-pin policy tests
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* auto-pin policy tests. The PREDICATE layer stays opt-valued (null when the
|
|
3
|
+
* resolved option is falsy → byte-identical compaction); the EFFECTIVE default
|
|
4
|
+
* is decided by resolveAutoPinOption — ON since 2026-07-07, opt out via
|
|
5
|
+
* CC_AUTO_PIN=0 or config context.autoPin=false.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { describe, it, expect } from "vitest";
|
|
9
9
|
import {
|
|
10
10
|
resolveAutoPinConfig,
|
|
11
|
+
resolveAutoPinOption,
|
|
11
12
|
buildAutoPinPredicate,
|
|
12
13
|
describeAutoPin,
|
|
13
14
|
} from "../auto-pin.js";
|
|
@@ -102,3 +103,25 @@ describe("describeAutoPin", () => {
|
|
|
102
103
|
);
|
|
103
104
|
});
|
|
104
105
|
});
|
|
106
|
+
|
|
107
|
+
describe("resolveAutoPinOption (effective default — ON since 2026-07-07)", () => {
|
|
108
|
+
it("defaults ON when nothing is set", () => {
|
|
109
|
+
expect(resolveAutoPinOption({ env: undefined, config: undefined })).toBe(
|
|
110
|
+
true,
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
it("CC_AUTO_PIN=0 opts out; =1 forces on over a config false", () => {
|
|
114
|
+
expect(resolveAutoPinOption({ env: "0", config: true })).toBe(false);
|
|
115
|
+
expect(resolveAutoPinOption({ env: "1", config: false })).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
it("config false opts out; a config object passes through", () => {
|
|
118
|
+
expect(resolveAutoPinOption({ env: undefined, config: false })).toBe(false);
|
|
119
|
+
const cfg = { maxPinTokens: 99 };
|
|
120
|
+
expect(resolveAutoPinOption({ env: undefined, config: cfg })).toBe(cfg);
|
|
121
|
+
});
|
|
122
|
+
it("an explicit --auto-pin flag wins over everything", () => {
|
|
123
|
+
expect(resolveAutoPinOption({ flag: true, env: "0", config: false })).toBe(
|
|
124
|
+
true,
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
});
|