chainlesschain 0.165.3 → 0.165.4
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 +151 -29
- package/package.json +2 -2
- package/src/assets/web-panel/assets/{AIOps-BiHNUlbU.js → AIOps-C__nnraW.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-D-UFjDRQ.js → ActionButton-CsKWHEZ-.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DazVsDgW.js → Analytics-BhIjfjWO.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DXh9UfNJ.js → AppLayout-BjuXFzWZ.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CZ6tsceY.js → Artifacts-k6whDkZJ.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-RyxnBr_h.js → Audit-C4FBMYRh.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BWS51Q6X.js → BackgroundAgents-C_vRrSXk.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BRtPcUul.js → Backup-CngFZeVp.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CGd4vZYY.js → BaseInput-B_H9EBRm.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-h8ijVwCg.js → Chat-DLEC5kt7.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-xijcWkJe.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-NyF6dPl8.js → Checkbox-m3ClR4xh.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Ci4OOxr5.js → Codegen-CmLSFrgp.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CwTkc9BM.js → Col-DFGQteHN.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DW_tM82m.js → Community-EUUVORHE.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DEvHRV4S.js → Compact-2PSg0Yr7.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BbjBEEfD.js → Compliance-CcKur7gB.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-10IXBaBa.js → Cowork-DK_Fezfa.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-BZkbpd5I.js → Cron-Dbw89xl7.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CFQ8L_6v.js → Crosschain-CH66h_Ec.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BDF6AkXe.js → DID-D1igRb17.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CoOdWMi4.js → Dashboard-DVAsrobk.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DEsGmu8Y.js → Dropdown-Dl7W8AQs.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BS89SWlK.js → EmailListRenderer-D5tpaEQC.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-C1FpCHiI.js → FamilyGuardDashboard-O_VQf8gq.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BzvpVmLA.js → Federation-BTVcgS9n.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BeC259PQ.js → FormItemContext-BRnkJAIz.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-azgG3bmV.js → GenericCardRenderer-8OWSCkDj.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BmSSowc5.js → Git-WXLYTQj2.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CTBCSyQZ.js → Governance-BezaUhtc.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DA5xyk4a.js → Inference-CuRay3Gu.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-D1gPHNig.js → KnowledgeGraph-DfWLDW1m.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BPmLf1AR.js → Logs-C55y2pPY.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-hDpWdiBc.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-DtUFcR0E.js → Marketplace-Dk08Uycg.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DS_kqBv-.js → McpTools-C11fSB5V.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-Fvh7XL7V.js → Memory-mr0eZc97.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C7itAP45.js → MobileBridge-C0iCSRbb.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-CY-xMG8Z.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-B57MiNLK.js → Mtc-Bplqc_Wc.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-BXfCUcM7.js → MtcAudit-BlzwsoSM.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-yaJ-ZcF6.js → Multisig-BBLmTty6.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CoaUCKrO.js → NLProgramming-DtT1uf1W.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BKLM_65R.js → Notes-DcqQAxTK.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DoDtK9uZ.js → NotificationSettings-cb0kWoZe.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BJ28TGr-.js → OrderTableRenderer-kw9HZQNN.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-MuGsdoIb.js → Organization-DlTlbkUN.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BLUN9J4R.js → Overflow-pp1qs-oY.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DWuoBUPd.js → P2P-BESLnyYz.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CUi37YPj.js → PdhVaultBrowser-B-J1mGuf.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BYQg2pcr.js → Permissions-B36PeT1_.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CAxoV2xu.js → PersonalDataHub-CTK2ad-3.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-B33wGvIO.js → Pipeline-zJNGXsac.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-A8yXTORP.js → Privacy-b9fz0Qf0.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D49I2I1O.js → ProjectInit-DjZbZgiB.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Ci73jJDw.js → ProjectSettings-C-hHJXlD.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BC9KSDM6.js +1 -0
- package/src/assets/web-panel/assets/Providers-Dz-CAYYU.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-Brza0ykJ.js → QrScannerModal-A0yoQ3-3.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DFydhjxL.js → QuickAsk-DrFgFJNC.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DLF8_NhA.js → Recommend-KC8hF1g4.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-dyuStW3x.js → RemoteSession-DGTPIk6u.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-5F3tA6yw.js → Reputation-QmbwM7Yk.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Ca2A57S5.js → Row-BxjJylia.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B0bxBkq_.js → RssFeed-B7Wda1J6.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CFNvHalZ.js → Search-_plQ_YSA.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DSoH3Hav.js → Security-CD2YJZfx.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BHpfEmBQ.js → Services-qQE7NmwE.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Dsh-QNmn.js → Skeleton-DgQqkFf7.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BhT1NkSU.js → Skills-C4C0oFFt.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DY9snPeJ.js → Sla-Px2N2B5c.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CWaX0_Cx.js → SpeechSettings-DN6C3lQd.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-B690y_TC.js → SyncSettings-jm5aH_m7.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-2N-w3zWd.js → Tasks-DlkJcv67.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BjwQOQYC.js → Templates-DyrTHUBs.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CUqHErxY.js → Tenant-mC434PtL.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-C13rXvNy.js → Terminal-o0_s3NgK.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CpbWcya_.js → TimelineRenderer-DAGlAXOw.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BXHLGXYC.js → Tokens-BnulS_bs.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-1e5i65o3.js → Trigger-suQbVXYM.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-FLGqNHs5.js → Trust-DbIJAPo5.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BbaR_LJB.js → UkeySign-CQNpbIHi.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-NOp4RIov.js → VideoEditing-D8aWCERk.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-B7DW7bG4.js → Wallet-CuLpYfZc.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-BptSUWix.js → WebAuthn-CsfG8ZMc.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-CAJnDOXS.js → WorkflowEditor-BYsEAZbd.js} +1 -1
- package/src/assets/web-panel/assets/{chat-I8LgG1-Z.js → chat-FT4Um3-I.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CWe7SOVD.js → colors-CKbS_Wlt.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cx3u3CA3.js → compact-item-CFJtzuJM.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CgD5ArwY.js → createContext-B9kSRW6K.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DJZ0gAMu.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BfQWiXN8.js → hasIn-DR-x0Xpi.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAVy98u7.js → index-7jHr_A_k.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlIyt1qF.js → index-B3ZX81mK.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWZ3REg6.js → index-B7osrXqy.js} +3 -3
- package/src/assets/web-panel/assets/{index-DGMYTN5W.js → index-BGbPnC5x.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFb-XIKy.js → index-BI5hP_qy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAUnl4Jv.js → index-BK3TiKVq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUAR7RY-.js → index-BVPU43b1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd79NQAx.js → index-BW-t9n-q.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiI-xPRH.js → index-BfFCQHL3.js} +1 -1
- package/src/assets/web-panel/assets/index-Bizb4hkw.js +1 -0
- package/src/assets/web-panel/assets/{index-B6yChzt1.js → index-Bt4fS2eL.js} +1 -1
- package/src/assets/web-panel/assets/{index-e8BM1yY1.js → index-BwR7yc2h.js} +1 -1
- package/src/assets/web-panel/assets/{index-V-kIHzAV.js → index-Bzz0C1BZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bx7BNIRH.js → index-C2JvmYRc.js} +1 -1
- package/src/assets/web-panel/assets/{index-87gMxqhN.js → index-CGaXUsIs.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cy_cCJlr.js → index-CJmIQ9XR.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1UjHdgZ.js → index-C_enk9I_.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi24S7Dw.js → index-Cr2FLUsD.js} +1 -1
- package/src/assets/web-panel/assets/{index-CcX4FSPf.js → index-CvrCCqJt.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmrdUwzU.js → index-D4LfPvWA.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dcdm_Z2c.js → index-DMGmg497.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCJEY2T0.js → index-DShSkww-.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0ztiqtB.js → index-DTxNy0ZU.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-rIKccl.js → index-DW4BWjTk.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdRkCwm4.js → index-DWdqx7zI.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0nDKhWv.js → index-Dap9c3eD.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQDKYbnv.js → index-DcfxhKXR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuEQSorC.js → index-DdkIhfi-.js} +1 -1
- package/src/assets/web-panel/assets/{index-3iKP9OTJ.js → index-DeSgw-WV.js} +1 -1
- package/src/assets/web-panel/assets/{index-Doc0Ftpd.js → index-DiNUEpSQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BREnPKGo.js → index-DjEP7WkH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNYFQxAW.js → index-DtkFqPVA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DslTuqro.js → index-KqDaCApw.js} +1 -1
- package/src/assets/web-panel/assets/index-OHSl-xCh.js +1 -0
- package/src/assets/web-panel/assets/{index-CMu16vPC.js → index-OSzjTzGM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsQcURkA.js → index-QBSeNVO3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DeizoQVZ.js → index-WE08gMJP.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1cX4Rxu.js → index-r2VI1Ikk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmgtY58H.js → index-tqSEHPRT.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DiBszVdG.js → initDefaultProps-Dd7n7VgI.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BGIFFozv.js → motion-BwxouRw1.js} +1 -1
- package/src/assets/web-panel/assets/{move-D5W7mp7B.js → move-DObN0PG9.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-JFIlxJ7F.js → mtc-parser-B3nOUQc7.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CQ3o6LIU.js → omit-o9WU2Nbl.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-R8MIlXo3.js → pickAttrs-CL_vvfQ_.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-sW7ylSky.js → placementArrow-CYrM2tyK.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Cnl39Vbz.js → responsiveObserve-k_06cQ96.js} +1 -1
- package/src/assets/web-panel/assets/{slide-sn8tFd14.js → slide-CPKG0pxS.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-IKKY_QxZ.js → statusUtils-BDDEeLTw.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BNpV4Nqs.js → styleChecker-Cmb7RTh7.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BWyT_eoU.js → useFlexGapSupport-e2IedC4N.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-D09p6_U9.js → useFs-CE_gxVnm.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CzW3TkJZ.js → usePersonalDataHub-BkMIIKMz.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-3s3WoAKB.js → vnode-DW886XV1.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cjy_673s.js → zoom-Dwo_adaf.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +105 -35
- package/src/commands/artifacts.js +363 -33
- package/src/commands/cowork.js +202 -36
- package/src/commands/session-budget.js +155 -0
- package/src/commands/session-location.js +948 -0
- package/src/commands/session.js +72 -46
- package/src/data/changelog.json +13 -0
- package/src/gateways/ws/artifact-protocol.js +77 -13
- package/src/gateways/ws/session-protocol.js +391 -24
- package/src/gateways/ws/ws-agent-handler.js +191 -14
- package/src/gateways/ws/ws-server.js +14 -3
- package/src/gateways/ws/ws-session-gateway.js +101 -5
- package/src/harness/jsonl-session-store.js +1210 -0
- package/src/lib/agent-team/team-runner.js +43 -13
- package/src/lib/artifact-access-ledger.js +461 -0
- package/src/lib/artifact-cleanup-ledger.js +861 -0
- package/src/lib/artifact-deletion-ledger.js +677 -0
- package/src/lib/artifact-store.js +256 -51
- package/src/lib/command-lifecycle-report.js +8 -4
- package/src/lib/cowork-adapter.js +9 -5
- package/src/lib/cowork-task-runner.js +20 -0
- package/src/lib/cowork-workflow.js +178 -20
- package/src/lib/direct-model-usage.js +62 -22
- package/src/lib/dynamic-workflow-runtime.js +3184 -111
- package/src/lib/execution-location-result-apply.js +339 -0
- package/src/lib/execution-location-result-artifact.js +271 -0
- package/src/lib/execution-location-result-review.js +253 -0
- package/src/lib/execution-location-result-store.js +331 -0
- package/src/lib/execution-location-result.js +617 -0
- package/src/lib/execution-location-target.js +236 -1
- package/src/lib/managed-tool-checkpoint.js +47 -4
- package/src/lib/process-execution-broker/workspace-transaction.js +3 -0
- package/src/lib/session-budget-production-root.js +376 -0
- package/src/lib/session-budget-runtime.js +109 -18
- package/src/lib/session-budget-usage.js +63 -0
- package/src/lib/session-host-snapshot.js +19 -2
- package/src/lib/session-resource-budget.js +766 -105
- package/src/lib/sub-agent-context.js +69 -22
- package/src/lib/web-ui-server.js +12 -1
- package/src/repl/agent-repl.js +237 -16
- package/src/runtime/agent-core.js +123 -0
- package/src/runtime/headless-runner.js +135 -46
- package/src/runtime/headless-stream.js +133 -25
- package/src/runtime/policies/agent-policy.js +10 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-D7tcdDS9.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-SVLOg49H.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-DGbP36-3.js +0 -1
- package/src/assets/web-panel/assets/Projects-CF-yD6Cn.js +0 -1
- package/src/assets/web-panel/assets/Providers-D-etEhg5.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DLv_872g.js +0 -1
- package/src/assets/web-panel/assets/index-CdiGCibe.js +0 -1
- package/src/assets/web-panel/assets/index-D_0z-gyz.js +0 -1
|
@@ -23,6 +23,12 @@ import {
|
|
|
23
23
|
import { isGitRepo } from "./git-integration.js";
|
|
24
24
|
import { markRuntimeLedgerPersistenceError } from "./runtime-usage-ledger.js";
|
|
25
25
|
import { IterationBudget } from "./iteration-budget.js";
|
|
26
|
+
import {
|
|
27
|
+
beginSessionBudgetUsage,
|
|
28
|
+
markSessionBudgetUsageUnknown,
|
|
29
|
+
recordSessionBudgetUsage,
|
|
30
|
+
rejectSessionBudgetUsageUnknown,
|
|
31
|
+
} from "./session-budget-usage.js";
|
|
26
32
|
|
|
27
33
|
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
28
34
|
|
|
@@ -162,6 +168,8 @@ export class SubAgentContext {
|
|
|
162
168
|
* work cannot begin without a durable parent boundary.
|
|
163
169
|
* @param {function} [options.onUsageSettlement] - Synchronous observer for
|
|
164
170
|
* real child token-usage/model-usage-unknown settlements.
|
|
171
|
+
* @param {function} [options.onProviderReceipt] - Synchronous observer for
|
|
172
|
+
* a provider-returned receipt before the matching usage settlement.
|
|
165
173
|
* @param {function} [options.onToolCallBoundary] - Synchronous observer for
|
|
166
174
|
* real child tool-executing boundaries.
|
|
167
175
|
* @param {function} [options.onToolCallSettlement] - Synchronous observer for
|
|
@@ -284,6 +292,10 @@ export class SubAgentContext {
|
|
|
284
292
|
typeof options.onUsageSettlement === "function"
|
|
285
293
|
? options.onUsageSettlement
|
|
286
294
|
: null;
|
|
295
|
+
this._onProviderReceipt =
|
|
296
|
+
typeof options.onProviderReceipt === "function"
|
|
297
|
+
? options.onProviderReceipt
|
|
298
|
+
: null;
|
|
287
299
|
this._onToolCallBoundary =
|
|
288
300
|
typeof options.onToolCallBoundary === "function"
|
|
289
301
|
? options.onToolCallBoundary
|
|
@@ -690,6 +702,7 @@ export class SubAgentContext {
|
|
|
690
702
|
const pendingToolCalls = new Map();
|
|
691
703
|
let observeUsageBoundary = null;
|
|
692
704
|
let observeUsageSettlement = null;
|
|
705
|
+
let observeProviderReceipt = null;
|
|
693
706
|
let observeToolBoundary = null;
|
|
694
707
|
let observeToolSettlement = null;
|
|
695
708
|
const providerReceiptForSettlement = (event) => {
|
|
@@ -739,6 +752,17 @@ export class SubAgentContext {
|
|
|
739
752
|
requireSyncUsageObserver(this._onUsageSettlement, event, "settlement");
|
|
740
753
|
pendingUsageCalls.delete(callId);
|
|
741
754
|
};
|
|
755
|
+
observeProviderReceipt = (event) => {
|
|
756
|
+
const callId = requireUsageCallId(event, "receipt");
|
|
757
|
+
if (!pendingUsageCalls.has(callId)) {
|
|
758
|
+
throw runtimeUsageObserverFailure(
|
|
759
|
+
null,
|
|
760
|
+
"CC_USAGE_RECEIPT_BOUNDARY_MISSING",
|
|
761
|
+
`Child provider receipt has no matching boundary: ${callId}`,
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
requireSyncUsageObserver(this._onProviderReceipt, event, "receipt");
|
|
765
|
+
};
|
|
742
766
|
|
|
743
767
|
// agentLoop yields model-usage-started before provider work. Its consumer
|
|
744
768
|
// runs synchronously before requesting the next event, so a durable host
|
|
@@ -747,6 +771,9 @@ export class SubAgentContext {
|
|
|
747
771
|
// directly, before its provider query, rather than yielding a start event.
|
|
748
772
|
options.onUsageBoundary = observeUsageBoundary;
|
|
749
773
|
options.onUsageSettlement = observeUsageSettlement;
|
|
774
|
+
if (this._onProviderReceipt) {
|
|
775
|
+
options.onProviderReceipt = observeProviderReceipt;
|
|
776
|
+
}
|
|
750
777
|
options.strictUsageTelemetry = true;
|
|
751
778
|
|
|
752
779
|
observeToolBoundary = (event) => {
|
|
@@ -869,21 +896,28 @@ export class SubAgentContext {
|
|
|
869
896
|
}
|
|
870
897
|
}
|
|
871
898
|
if (event.type === "provider-request-receipt") {
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
)
|
|
899
|
+
const receipt = Object.freeze({
|
|
900
|
+
protocol: event.protocol,
|
|
901
|
+
provider: event.provider,
|
|
902
|
+
workflowEffectId: event.workflowEffectId,
|
|
903
|
+
callId: event.callId,
|
|
904
|
+
callSequence: event.callSequence,
|
|
905
|
+
source: event.source,
|
|
906
|
+
clientRequestId: event.clientRequestId,
|
|
907
|
+
requestId: event.requestId || null,
|
|
908
|
+
responseId: event.responseId || null,
|
|
909
|
+
requestIdentitySemantics: event.requestIdentitySemantics,
|
|
910
|
+
independentlyReadable: event.independentlyReadable,
|
|
911
|
+
});
|
|
912
|
+
this._providerRequestReceipts.push(receipt);
|
|
913
|
+
if (strictUsageTelemetry && this._onProviderReceipt) {
|
|
914
|
+
observeProviderReceipt({
|
|
915
|
+
type: "provider-request-receipt",
|
|
916
|
+
...receipt,
|
|
917
|
+
workflowRequestSource: receipt.source,
|
|
918
|
+
providerReceipt: { ...receipt },
|
|
919
|
+
});
|
|
920
|
+
}
|
|
887
921
|
}
|
|
888
922
|
|
|
889
923
|
if (event.type === "token-usage") {
|
|
@@ -914,13 +948,11 @@ export class SubAgentContext {
|
|
|
914
948
|
// call into a permanently open `started` row.
|
|
915
949
|
// Attributed usage was already charged by the nested child sharing
|
|
916
950
|
// this same authority, so only direct usage is folded here.
|
|
917
|
-
|
|
918
|
-
this.sessionBudget
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
});
|
|
923
|
-
}
|
|
951
|
+
recordSessionBudgetUsage(
|
|
952
|
+
this.sessionBudget,
|
|
953
|
+
event,
|
|
954
|
+
"sub-agent usage settlement",
|
|
955
|
+
);
|
|
924
956
|
if (this._onUsage) {
|
|
925
957
|
// Forward real usage to the spawner. A nested child's event already
|
|
926
958
|
// carries its own attribution frame — preserve it (deepest wins).
|
|
@@ -954,6 +986,11 @@ export class SubAgentContext {
|
|
|
954
986
|
observeUsageBoundary(event);
|
|
955
987
|
}
|
|
956
988
|
}
|
|
989
|
+
beginSessionBudgetUsage(
|
|
990
|
+
this.sessionBudget,
|
|
991
|
+
event,
|
|
992
|
+
"sub-agent provider call",
|
|
993
|
+
);
|
|
957
994
|
}
|
|
958
995
|
|
|
959
996
|
if (event.type === "tool-executing" && strictUsageTelemetry) {
|
|
@@ -990,6 +1027,10 @@ export class SubAgentContext {
|
|
|
990
1027
|
observeUsageSettlement(forwardedUnknown);
|
|
991
1028
|
forwardedUnknown.ledgerPersisted = true;
|
|
992
1029
|
}
|
|
1030
|
+
const budgetUsageUnknown = markSessionBudgetUsageUnknown(
|
|
1031
|
+
this.sessionBudget,
|
|
1032
|
+
event,
|
|
1033
|
+
);
|
|
993
1034
|
if (this._onUsage) {
|
|
994
1035
|
if (strictUsageTelemetry) {
|
|
995
1036
|
requireSyncUsageObserver(
|
|
@@ -1005,6 +1046,12 @@ export class SubAgentContext {
|
|
|
1005
1046
|
}
|
|
1006
1047
|
}
|
|
1007
1048
|
}
|
|
1049
|
+
if (budgetUsageUnknown) {
|
|
1050
|
+
rejectSessionBudgetUsageUnknown(
|
|
1051
|
+
event,
|
|
1052
|
+
"sub-agent provider call",
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1008
1055
|
}
|
|
1009
1056
|
|
|
1010
1057
|
if (event.type === "tool-executing") {
|
package/src/lib/web-ui-server.js
CHANGED
|
@@ -23,6 +23,7 @@ import crypto from "crypto";
|
|
|
23
23
|
import { fileURLToPath } from "url";
|
|
24
24
|
import { getInlineSource as getEnvelopeInlineSource } from "./web-ui-envelope.js";
|
|
25
25
|
import { CLISkillLoader } from "./skill-loader.js";
|
|
26
|
+
import { authorizeArtifactContentAccess } from "./artifact-access-ledger.js";
|
|
26
27
|
|
|
27
28
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
28
29
|
|
|
@@ -1333,6 +1334,15 @@ export function handleApiRequest(req, res, ctx = {}) {
|
|
|
1333
1334
|
res.end(JSON.stringify({ error: "Stored copy missing" }));
|
|
1334
1335
|
return;
|
|
1335
1336
|
}
|
|
1337
|
+
const accessIdHeader = req.headers["x-chainlesschain-access-id"];
|
|
1338
|
+
const authorization = authorizeArtifactContentAccess(store, {
|
|
1339
|
+
artifactId: entry.id,
|
|
1340
|
+
client: "web",
|
|
1341
|
+
action: "download",
|
|
1342
|
+
...(typeof accessIdHeader === "string"
|
|
1343
|
+
? { accessId: accessIdHeader }
|
|
1344
|
+
: {}),
|
|
1345
|
+
});
|
|
1336
1346
|
const downloadName =
|
|
1337
1347
|
entry.title && path.extname(entry.title)
|
|
1338
1348
|
? entry.title
|
|
@@ -1343,8 +1353,9 @@ export function handleApiRequest(req, res, ctx = {}) {
|
|
|
1343
1353
|
"Content-Disposition": encodeDispositionFilename(downloadName),
|
|
1344
1354
|
"Cache-Control": "no-store",
|
|
1345
1355
|
"X-Content-Type-Options": "nosniff",
|
|
1356
|
+
"X-ChainlessChain-Access-Digest": authorization.access.eventDigest,
|
|
1346
1357
|
});
|
|
1347
|
-
const stream = fs.createReadStream(storedPath);
|
|
1358
|
+
const stream = fs.createReadStream(authorization.storedPath);
|
|
1348
1359
|
stream.on("error", () => res.destroy());
|
|
1349
1360
|
stream.pipe(res);
|
|
1350
1361
|
} catch (err) {
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -79,6 +79,16 @@ import {
|
|
|
79
79
|
readSessionHostResumeState,
|
|
80
80
|
} from "../lib/session-host-snapshot.js";
|
|
81
81
|
import { acquireSessionHostLease } from "../lib/session-host-lease.js";
|
|
82
|
+
import {
|
|
83
|
+
openProductionSessionBudgetRoot,
|
|
84
|
+
sessionBudgetAdmissionError,
|
|
85
|
+
} from "../lib/session-budget-production-root.js";
|
|
86
|
+
import {
|
|
87
|
+
beginSessionBudgetUsage,
|
|
88
|
+
markSessionBudgetUsageUnknown,
|
|
89
|
+
recordSessionBudgetUsage,
|
|
90
|
+
rejectSessionBudgetUsageUnknown,
|
|
91
|
+
} from "../lib/session-budget-usage.js";
|
|
82
92
|
import {
|
|
83
93
|
SideEffectLedger,
|
|
84
94
|
classifyToolSideEffect,
|
|
@@ -236,6 +246,29 @@ export function resolveReplMeteredSessionId(useJsonl, sessionId) {
|
|
|
236
246
|
return useJsonl && sessionId ? sessionId : null;
|
|
237
247
|
}
|
|
238
248
|
|
|
249
|
+
export function combineReplSignals(...signals) {
|
|
250
|
+
const active = [...new Set(signals.filter(Boolean))];
|
|
251
|
+
if (active.length === 0) return null;
|
|
252
|
+
if (active.length === 1) return active[0];
|
|
253
|
+
return AbortSignal.any(active);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export async function closeReplSessionBudgetRootScope(scope) {
|
|
257
|
+
const root = scope?.root || null;
|
|
258
|
+
if (!root) return false;
|
|
259
|
+
const closed = await root.close();
|
|
260
|
+
scope.root = null;
|
|
261
|
+
return closed;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function releaseReplSessionHostLeaseScope(scope) {
|
|
265
|
+
const lease = scope?.lease || null;
|
|
266
|
+
if (!lease) return false;
|
|
267
|
+
const released = lease.release?.();
|
|
268
|
+
scope.lease = null;
|
|
269
|
+
return released;
|
|
270
|
+
}
|
|
271
|
+
|
|
239
272
|
function attachReplCompactionLedgerMetadata(error, callId, settled) {
|
|
240
273
|
let target = error;
|
|
241
274
|
if (!target || (typeof target !== "object" && typeof target !== "function")) {
|
|
@@ -293,6 +326,7 @@ export async function runReplMeteredModelCallWithLedger({
|
|
|
293
326
|
provider,
|
|
294
327
|
model,
|
|
295
328
|
source = "model",
|
|
329
|
+
sessionBudget = null,
|
|
296
330
|
call,
|
|
297
331
|
attachErrorMetadata = false,
|
|
298
332
|
}) {
|
|
@@ -311,6 +345,7 @@ export async function runReplMeteredModelCallWithLedger({
|
|
|
311
345
|
provider,
|
|
312
346
|
model,
|
|
313
347
|
source,
|
|
348
|
+
sessionBudget,
|
|
314
349
|
call,
|
|
315
350
|
});
|
|
316
351
|
return Object.freeze({ result, callId, usageLedgerSettled });
|
|
@@ -545,7 +580,7 @@ async function _persistAlwaysAllow(tool, args) {
|
|
|
545
580
|
/**
|
|
546
581
|
* Execute a tool call — delegates to agent-core with REPL's hookDb and cwd.
|
|
547
582
|
*/
|
|
548
|
-
async function executeTool(name, args) {
|
|
583
|
+
async function executeTool(name, args, context = {}) {
|
|
549
584
|
return coreExecuteTool(name, args, {
|
|
550
585
|
hookDb: _hookDb,
|
|
551
586
|
cwd: process.cwd(),
|
|
@@ -556,6 +591,9 @@ async function executeTool(name, args) {
|
|
|
556
591
|
settingsHooks: _settingsHooks,
|
|
557
592
|
classifyAllShell: _classifyAllShell,
|
|
558
593
|
sandbox: _sandbox,
|
|
594
|
+
sessionId: context.sessionId || null,
|
|
595
|
+
sessionBudget: context.sessionBudget || null,
|
|
596
|
+
signal: context.signal || null,
|
|
559
597
|
});
|
|
560
598
|
}
|
|
561
599
|
|
|
@@ -938,6 +976,11 @@ export async function agentLoop(messages, options) {
|
|
|
938
976
|
persistTokenUsage(options.sessionId, projectRuntimeTokenUsage(event)),
|
|
939
977
|
);
|
|
940
978
|
}
|
|
979
|
+
recordSessionBudgetUsage(
|
|
980
|
+
options.sessionBudget,
|
|
981
|
+
event,
|
|
982
|
+
"REPL usage settlement",
|
|
983
|
+
);
|
|
941
984
|
} else if (
|
|
942
985
|
event.type === "model-usage-started" ||
|
|
943
986
|
event.type === "model-usage-unknown" ||
|
|
@@ -966,6 +1009,15 @@ export async function agentLoop(messages, options) {
|
|
|
966
1009
|
),
|
|
967
1010
|
);
|
|
968
1011
|
}
|
|
1012
|
+
if (event.type === "model-usage-started") {
|
|
1013
|
+
beginSessionBudgetUsage(
|
|
1014
|
+
options.sessionBudget,
|
|
1015
|
+
event,
|
|
1016
|
+
"REPL provider call",
|
|
1017
|
+
);
|
|
1018
|
+
} else if (markSessionBudgetUsageUnknown(options.sessionBudget, event)) {
|
|
1019
|
+
rejectSessionBudgetUsageUnknown(event, "REPL provider call");
|
|
1020
|
+
}
|
|
969
1021
|
} else if (event.type === "iteration-warning") {
|
|
970
1022
|
writeOut(chalk.yellow(`\n ${event.message}\n`));
|
|
971
1023
|
} else if (event.type === "iteration-budget-exhausted") {
|
|
@@ -2630,6 +2682,17 @@ export async function runReplStartupBoundary(options, startupDependencies) {
|
|
|
2630
2682
|
}
|
|
2631
2683
|
return refuseStartup(options, startupCandidate);
|
|
2632
2684
|
}
|
|
2685
|
+
if (
|
|
2686
|
+
options.sessionBudgetRoot?.enabled === true &&
|
|
2687
|
+
startupAdmission.useJsonl !== true
|
|
2688
|
+
) {
|
|
2689
|
+
throw Object.assign(
|
|
2690
|
+
new Error(
|
|
2691
|
+
"session budget root requires durable JSONL session persistence, but JSONL storage is unavailable",
|
|
2692
|
+
),
|
|
2693
|
+
{ code: "CC_SESSION_BUDGET_JSONL_REQUIRED" },
|
|
2694
|
+
);
|
|
2695
|
+
}
|
|
2633
2696
|
|
|
2634
2697
|
// Only a frozen, branded admission capability may cross into workspace,
|
|
2635
2698
|
// pipe, config, plugin, hook, MCP, model, or tool initialization.
|
|
@@ -2660,6 +2723,7 @@ export async function runReplStartupBoundary(options, startupDependencies) {
|
|
|
2660
2723
|
null,
|
|
2661
2724
|
);
|
|
2662
2725
|
const leaseScope = options._sessionHostLeaseScope || null;
|
|
2726
|
+
const budgetScope = options._sessionBudgetRootScope || null;
|
|
2663
2727
|
const leaseSessionId = startupCandidate?.sessionId || options.sessionId;
|
|
2664
2728
|
if (
|
|
2665
2729
|
leaseScope &&
|
|
@@ -2669,9 +2733,79 @@ export async function runReplStartupBoundary(options, startupDependencies) {
|
|
|
2669
2733
|
) {
|
|
2670
2734
|
leaseScope.lease = acquireHostLease(leaseSessionId, { hostKind: "repl" });
|
|
2671
2735
|
}
|
|
2736
|
+
let workspaceOptions = options;
|
|
2737
|
+
if (options.sessionBudgetRoot?.enabled === true) {
|
|
2738
|
+
if (!leaseSessionId || !leaseScope?.lease) {
|
|
2739
|
+
throw Object.assign(
|
|
2740
|
+
new Error(
|
|
2741
|
+
"session budget root requires an acquired REPL host lease for its durable session",
|
|
2742
|
+
),
|
|
2743
|
+
{ code: "CC_SESSION_BUDGET_LEASE_REQUIRED" },
|
|
2744
|
+
);
|
|
2745
|
+
}
|
|
2746
|
+
if (!budgetScope || budgetScope.root) {
|
|
2747
|
+
throw Object.assign(
|
|
2748
|
+
new Error("REPL session budget root scope is invalid"),
|
|
2749
|
+
{ code: "CC_SESSION_BUDGET_SCOPE_INVALID" },
|
|
2750
|
+
);
|
|
2751
|
+
}
|
|
2752
|
+
const openBudgetRoot = dependencyDataFunction(
|
|
2753
|
+
startupDependencies,
|
|
2754
|
+
"openProductionSessionBudgetRoot",
|
|
2755
|
+
null,
|
|
2756
|
+
);
|
|
2757
|
+
if (typeof openBudgetRoot !== "function") {
|
|
2758
|
+
throw invalidReplRecovery(
|
|
2759
|
+
"REPL session budget root dependency is missing",
|
|
2760
|
+
"CC_REPL_STARTUP_DEPENDENCY_INVALID",
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2763
|
+
const root = openBudgetRoot(
|
|
2764
|
+
leaseSessionId,
|
|
2765
|
+
options.sessionBudgetRoot,
|
|
2766
|
+
{
|
|
2767
|
+
persist: true,
|
|
2768
|
+
signal: combineReplSignals(options.signal, leaseScope.lease.signal),
|
|
2769
|
+
table: options.sessionBudgetRoot.table,
|
|
2770
|
+
},
|
|
2771
|
+
);
|
|
2772
|
+
if (
|
|
2773
|
+
root?.enabled !== true ||
|
|
2774
|
+
!root.budget ||
|
|
2775
|
+
!root.options ||
|
|
2776
|
+
root.options.sessionBudget !== root.budget ||
|
|
2777
|
+
typeof root.close !== "function"
|
|
2778
|
+
) {
|
|
2779
|
+
try {
|
|
2780
|
+
root?.close?.();
|
|
2781
|
+
} catch {
|
|
2782
|
+
// The invalid root is rejected regardless of cleanup outcome.
|
|
2783
|
+
}
|
|
2784
|
+
throw Object.assign(new Error("REPL session budget root is invalid"), {
|
|
2785
|
+
code: "CC_SESSION_BUDGET_ROOT_INVALID",
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
2788
|
+
if (root.budget.signal?.aborted === true) {
|
|
2789
|
+
const admissionError = sessionBudgetAdmissionError(
|
|
2790
|
+
root.budget.reason?.(),
|
|
2791
|
+
"REPL startup",
|
|
2792
|
+
);
|
|
2793
|
+
try {
|
|
2794
|
+
await root.close();
|
|
2795
|
+
} catch (cleanupError) {
|
|
2796
|
+
throw new AggregateError(
|
|
2797
|
+
[admissionError, cleanupError],
|
|
2798
|
+
"REPL budget admission and authority cleanup both failed",
|
|
2799
|
+
);
|
|
2800
|
+
}
|
|
2801
|
+
throw admissionError;
|
|
2802
|
+
}
|
|
2803
|
+
budgetScope.root = root;
|
|
2804
|
+
workspaceOptions = { ...options, ...root.options };
|
|
2805
|
+
}
|
|
2672
2806
|
const trustedWorkspaceRoot = readCwd();
|
|
2673
2807
|
return enterWorkspace(trustedWorkspaceRoot, () =>
|
|
2674
|
-
startWorkspace(
|
|
2808
|
+
startWorkspace(workspaceOptions, startupAdmission),
|
|
2675
2809
|
);
|
|
2676
2810
|
}
|
|
2677
2811
|
|
|
@@ -2681,26 +2815,34 @@ export function startReplJsonlSession(
|
|
|
2681
2815
|
requestedId,
|
|
2682
2816
|
meta,
|
|
2683
2817
|
observabilityScope,
|
|
2818
|
+
options = {},
|
|
2684
2819
|
) {
|
|
2820
|
+
const requireDurable =
|
|
2821
|
+
observabilityScope != null || options.requireDurable === true;
|
|
2685
2822
|
try {
|
|
2686
2823
|
const sessionId = startSession(requestedId, {
|
|
2687
2824
|
...meta,
|
|
2688
2825
|
...(observabilityScope != null ? { observabilityScope } : {}),
|
|
2689
2826
|
});
|
|
2690
2827
|
if (
|
|
2691
|
-
|
|
2828
|
+
requireDurable &&
|
|
2692
2829
|
(typeof sessionId !== "string" || !sessionId)
|
|
2693
2830
|
) {
|
|
2694
2831
|
throw new Error("JSONL session creation returned no durable session id");
|
|
2695
2832
|
}
|
|
2696
2833
|
return sessionId || null;
|
|
2697
2834
|
} catch (error) {
|
|
2698
|
-
if (
|
|
2835
|
+
if (!requireDurable) return null;
|
|
2699
2836
|
const failure = new Error(
|
|
2700
|
-
|
|
2837
|
+
observabilityScope != null
|
|
2838
|
+
? "scoped JSONL session could not be durably created"
|
|
2839
|
+
: "budgeted JSONL session could not be durably created",
|
|
2701
2840
|
{ cause: error },
|
|
2702
2841
|
);
|
|
2703
|
-
failure.code =
|
|
2842
|
+
failure.code =
|
|
2843
|
+
observabilityScope != null
|
|
2844
|
+
? "CC_OBSERVABILITY_SCOPE_START_FAILED"
|
|
2845
|
+
: "CC_SESSION_BUDGET_SESSION_START_FAILED";
|
|
2704
2846
|
throw failure;
|
|
2705
2847
|
}
|
|
2706
2848
|
}
|
|
@@ -2708,23 +2850,45 @@ export function startReplJsonlSession(
|
|
|
2708
2850
|
/** Start the agentic REPL with non-overridable production bindings. */
|
|
2709
2851
|
export async function startAgentRepl(options = {}) {
|
|
2710
2852
|
const sessionHostLeaseScope = { lease: null };
|
|
2853
|
+
const sessionBudgetRootScope = { root: null };
|
|
2711
2854
|
const runtimeOptions = {
|
|
2712
2855
|
...options,
|
|
2713
2856
|
_sessionHostLeaseScope: sessionHostLeaseScope,
|
|
2857
|
+
_sessionBudgetRootScope: sessionBudgetRootScope,
|
|
2714
2858
|
};
|
|
2715
2859
|
try {
|
|
2716
2860
|
const result = await runReplStartupBoundary(runtimeOptions, {
|
|
2717
2861
|
prepareReplStartupResume,
|
|
2718
2862
|
refuseReplStartupResume,
|
|
2719
2863
|
acquireSessionHostLease,
|
|
2864
|
+
openProductionSessionBudgetRoot,
|
|
2720
2865
|
cwd: () => process.cwd(),
|
|
2721
2866
|
runWithHostHooksV2Workspace,
|
|
2722
2867
|
startAgentReplInWorkspace,
|
|
2723
2868
|
});
|
|
2724
|
-
if (result?.started === false)
|
|
2869
|
+
if (result?.started === false) {
|
|
2870
|
+
await closeReplSessionBudgetRootScope(sessionBudgetRootScope);
|
|
2871
|
+
releaseReplSessionHostLeaseScope(sessionHostLeaseScope);
|
|
2872
|
+
}
|
|
2725
2873
|
return result;
|
|
2726
2874
|
} catch (error) {
|
|
2727
|
-
|
|
2875
|
+
const cleanupErrors = [];
|
|
2876
|
+
try {
|
|
2877
|
+
await closeReplSessionBudgetRootScope(sessionBudgetRootScope);
|
|
2878
|
+
} catch (cleanupError) {
|
|
2879
|
+
cleanupErrors.push(cleanupError);
|
|
2880
|
+
}
|
|
2881
|
+
try {
|
|
2882
|
+
releaseReplSessionHostLeaseScope(sessionHostLeaseScope);
|
|
2883
|
+
} catch (cleanupError) {
|
|
2884
|
+
cleanupErrors.push(cleanupError);
|
|
2885
|
+
}
|
|
2886
|
+
if (cleanupErrors.length > 0) {
|
|
2887
|
+
throw new AggregateError(
|
|
2888
|
+
[error, ...cleanupErrors],
|
|
2889
|
+
"REPL startup and authority cleanup both failed",
|
|
2890
|
+
);
|
|
2891
|
+
}
|
|
2728
2892
|
throw error;
|
|
2729
2893
|
}
|
|
2730
2894
|
}
|
|
@@ -2802,6 +2966,8 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
2802
2966
|
}
|
|
2803
2967
|
};
|
|
2804
2968
|
const _sessionHostLeaseScope = options._sessionHostLeaseScope || null;
|
|
2969
|
+
const _sessionBudgetRootScope = options._sessionBudgetRootScope || null;
|
|
2970
|
+
const _sessionBudget = options.sessionBudget || null;
|
|
2805
2971
|
let _sessionHostLeaseAbortListener = null;
|
|
2806
2972
|
let _sessionHostLeaseAbortSignal = null;
|
|
2807
2973
|
const _detachSessionHostLease = () => {
|
|
@@ -2840,6 +3006,35 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
2840
3006
|
return previous;
|
|
2841
3007
|
};
|
|
2842
3008
|
_attachSessionHostLease();
|
|
3009
|
+
let _sessionBudgetAbortListener = null;
|
|
3010
|
+
let _sessionBudgetAbortSignal = null;
|
|
3011
|
+
const _detachSessionBudget = () => {
|
|
3012
|
+
if (_sessionBudgetAbortListener && _sessionBudgetAbortSignal) {
|
|
3013
|
+
_sessionBudgetAbortSignal.removeEventListener(
|
|
3014
|
+
"abort",
|
|
3015
|
+
_sessionBudgetAbortListener,
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3018
|
+
_sessionBudgetAbortListener = null;
|
|
3019
|
+
_sessionBudgetAbortSignal = null;
|
|
3020
|
+
};
|
|
3021
|
+
const _attachSessionBudget = () => {
|
|
3022
|
+
const signal = _sessionBudget?.signal;
|
|
3023
|
+
if (!signal || _sessionBudgetAbortListener) return;
|
|
3024
|
+
_sessionBudgetAbortListener = () =>
|
|
3025
|
+
_requestReplOutputClose(
|
|
3026
|
+
sessionBudgetAdmissionError(
|
|
3027
|
+
_sessionBudget.reason?.() || "session-aborted",
|
|
3028
|
+
"REPL session",
|
|
3029
|
+
),
|
|
3030
|
+
);
|
|
3031
|
+
_sessionBudgetAbortSignal = signal;
|
|
3032
|
+
signal.addEventListener("abort", _sessionBudgetAbortListener, {
|
|
3033
|
+
once: true,
|
|
3034
|
+
});
|
|
3035
|
+
if (signal.aborted) _sessionBudgetAbortListener();
|
|
3036
|
+
};
|
|
3037
|
+
_attachSessionBudget();
|
|
2843
3038
|
const _replOutputFlow = outputScope.flow;
|
|
2844
3039
|
outputScope.setFailureHandler(_requestReplOutputClose);
|
|
2845
3040
|
const _disposeReplPipeSafety = installPipeSafety(undefined, () =>
|
|
@@ -2895,7 +3090,8 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
2895
3090
|
provider: callProvider || provider,
|
|
2896
3091
|
model: callModel || model,
|
|
2897
3092
|
source,
|
|
2898
|
-
|
|
3093
|
+
sessionBudget: _sessionBudget,
|
|
3094
|
+
call: () => call({ signal: options.signal || null }),
|
|
2899
3095
|
attachErrorMetadata: includeLedgerMetadata,
|
|
2900
3096
|
});
|
|
2901
3097
|
return includeLedgerMetadata ? metered : metered.result;
|
|
@@ -2926,7 +3122,12 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
2926
3122
|
sessionId: durableSessionId,
|
|
2927
3123
|
tool,
|
|
2928
3124
|
args,
|
|
2929
|
-
execute:
|
|
3125
|
+
execute: (name, toolArgs) =>
|
|
3126
|
+
executeTool(name, toolArgs, {
|
|
3127
|
+
sessionId: durableSessionId,
|
|
3128
|
+
sessionBudget: _sessionBudget,
|
|
3129
|
+
signal: options.signal || null,
|
|
3130
|
+
}),
|
|
2930
3131
|
now: options.now || Date.now,
|
|
2931
3132
|
terminalLatch: _runtimeLedgerTerminalLatch,
|
|
2932
3133
|
});
|
|
@@ -3089,13 +3290,13 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3089
3290
|
callModel: model,
|
|
3090
3291
|
source: "semantic-compaction",
|
|
3091
3292
|
includeLedgerMetadata: true,
|
|
3092
|
-
call: () =>
|
|
3293
|
+
call: ({ signal }) =>
|
|
3093
3294
|
chatWithTools([{ role: "user", content: prompt }], {
|
|
3094
3295
|
provider,
|
|
3095
3296
|
model,
|
|
3096
3297
|
baseUrl,
|
|
3097
3298
|
apiKey,
|
|
3098
|
-
signal
|
|
3299
|
+
signal,
|
|
3099
3300
|
enabledToolNames: [],
|
|
3100
3301
|
extraToolDefinitions: [],
|
|
3101
3302
|
hostManagedToolPolicy: null,
|
|
@@ -3535,6 +3736,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3535
3736
|
options.sessionId || null,
|
|
3536
3737
|
meta,
|
|
3537
3738
|
options.observabilityScope,
|
|
3739
|
+
{ requireDurable: Boolean(_sessionBudget) },
|
|
3538
3740
|
);
|
|
3539
3741
|
if (
|
|
3540
3742
|
sessionId &&
|
|
@@ -4410,7 +4612,11 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
4410
4612
|
callProvider: request?.provider,
|
|
4411
4613
|
callModel: request?.model,
|
|
4412
4614
|
source: "model",
|
|
4413
|
-
call: () =>
|
|
4615
|
+
call: ({ signal }) =>
|
|
4616
|
+
invokeToolFreeAdvisor({
|
|
4617
|
+
...request,
|
|
4618
|
+
signal: combineReplSignals(request?.signal, signal),
|
|
4619
|
+
}),
|
|
4414
4620
|
}),
|
|
4415
4621
|
onEvent: (event) => {
|
|
4416
4622
|
if (!useJsonl || !sessionId) return;
|
|
@@ -6953,6 +7159,14 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
6953
7159
|
if (sessionArg.startsWith("resume ")) {
|
|
6954
7160
|
const resumeId = sessionArg.slice(7).trim();
|
|
6955
7161
|
try {
|
|
7162
|
+
if (_sessionBudget && resumeId !== sessionId) {
|
|
7163
|
+
throw Object.assign(
|
|
7164
|
+
new Error(
|
|
7165
|
+
"a budgeted REPL is bound to its startup session; exit and restart to resume another session",
|
|
7166
|
+
),
|
|
7167
|
+
{ code: "CC_SESSION_BUDGET_REPL_SWITCH_UNSUPPORTED" },
|
|
7168
|
+
);
|
|
7169
|
+
}
|
|
6956
7170
|
if (useJsonl) {
|
|
6957
7171
|
const initialCandidate = _prepareJsonlResumeCandidate(resumeId);
|
|
6958
7172
|
if (!initialCandidate.ok) throw initialCandidate.error;
|
|
@@ -9084,7 +9298,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
9084
9298
|
// of hanging forever. undefined → agent-core's 180s default (matches cc
|
|
9085
9299
|
// chat/ask); config.llm.streamStallTimeoutMs tunes or disables (0).
|
|
9086
9300
|
streamStallTimeoutMs: _streamStallTimeoutMs,
|
|
9087
|
-
signal: _turnAbort.signal,
|
|
9301
|
+
signal: combineReplSignals(_turnAbort.signal, options.signal),
|
|
9088
9302
|
// On an auto-detected image turn, switch to the vision LLM for this
|
|
9089
9303
|
// turn only (provider/baseUrl/apiKey unchanged, model → vision model).
|
|
9090
9304
|
provider: _visionLlm ? _visionLlm.provider : provider,
|
|
@@ -9200,12 +9414,13 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
9200
9414
|
callProvider: provider,
|
|
9201
9415
|
callModel: activeModel,
|
|
9202
9416
|
source: "model",
|
|
9203
|
-
call: () =>
|
|
9417
|
+
call: ({ signal }) =>
|
|
9204
9418
|
chatWithTools([{ role: "user", content: p }], {
|
|
9205
9419
|
model: activeModel,
|
|
9206
9420
|
provider,
|
|
9207
9421
|
baseUrl,
|
|
9208
9422
|
apiKey,
|
|
9423
|
+
signal,
|
|
9209
9424
|
enabledToolNames: [],
|
|
9210
9425
|
}),
|
|
9211
9426
|
});
|
|
@@ -9743,9 +9958,15 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
9743
9958
|
}
|
|
9744
9959
|
|
|
9745
9960
|
// Shutdown runtime
|
|
9961
|
+
_detachSessionBudget();
|
|
9962
|
+
try {
|
|
9963
|
+
await closeReplSessionBudgetRootScope(_sessionBudgetRootScope);
|
|
9964
|
+
} catch (error) {
|
|
9965
|
+
_replOutputFailure ||= error;
|
|
9966
|
+
}
|
|
9746
9967
|
_detachSessionHostLease();
|
|
9747
9968
|
try {
|
|
9748
|
-
_sessionHostLeaseScope
|
|
9969
|
+
releaseReplSessionHostLeaseScope(_sessionHostLeaseScope);
|
|
9749
9970
|
} catch (error) {
|
|
9750
9971
|
_replOutputFailure ||= error;
|
|
9751
9972
|
}
|