chainlesschain 0.165.1 → 0.165.3
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 +248 -2
- package/package.json +4 -1
- package/src/assets/web-panel/assets/{AIOps-CYxFDrcm.js → AIOps-BiHNUlbU.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CPBtdiU2.js → ActionButton-D-UFjDRQ.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Dayq7Dp7.js → Analytics-DazVsDgW.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-6U7bPb2s.js → AppLayout-DXh9UfNJ.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-D2Iqg_3D.js → Artifacts-CZ6tsceY.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CdoOB7WV.js → Audit-RyxnBr_h.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DrnAVB8w.js → BackgroundAgents-BWS51Q6X.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CesMi5cy.js → Backup-BRtPcUul.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DaX9ptax.js → BaseInput-CGd4vZYY.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-OrwOPxDS.js → Chat-h8ijVwCg.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CvPZFRxM.js → ChatBubbleRenderer-D7tcdDS9.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DiHbcysC.js → Checkbox-NyF6dPl8.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CbgCkaBJ.js → Codegen-Ci4OOxr5.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Du5hgrh4.js → Col-CwTkc9BM.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DsPOBW-p.js → Community-DW_tM82m.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BwHIFkNC.js → Compact-DEvHRV4S.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BvrDQSgd.js → Compliance-BbjBEEfD.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-gwAE6arx.js → Cowork-10IXBaBa.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-DW-0l4uF.js → Cron-BZkbpd5I.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-j-NsLesB.js → Crosschain-CFQ8L_6v.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CibVEBOI.js → DID-BDF6AkXe.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-W4z9vSfe.js → Dashboard-CoOdWMi4.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DAcrkKxG.js → Dropdown-DEsGmu8Y.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-6GXah-89.js → EmailListRenderer-BS89SWlK.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-TKDCq8Ku.js → FamilyGuardDashboard-C1FpCHiI.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BXBLlcNm.js → Federation-BzvpVmLA.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BoJJBkG3.js → FormItemContext-BeC259PQ.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-okjsl46v.js → GenericCardRenderer-azgG3bmV.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Rvs7i6nn.js → Git-BmSSowc5.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CHSUxXXS.js → Governance-CTBCSyQZ.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-V3BlfxsB.js → Inference-DA5xyk4a.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-C_NlD4aR.js → KnowledgeGraph-D1gPHNig.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Nn4LNxhA.js → Logs-BPmLf1AR.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-SVAgNnkt.js → MarkdownRenderer-SVLOg49H.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DEmjFcg-.js → Marketplace-DtUFcR0E.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DlopXipI.js → McpTools-DS_kqBv-.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BG3ynX60.js → Memory-Fvh7XL7V.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DeRzWOfT.js → MobileBridge-C7itAP45.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-DGbP36-3.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-BoPbOv1C.js → Mtc-B57MiNLK.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-un-rTHp7.js → MtcAudit-BXfCUcM7.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-Ds0oveEB.js → Multisig-yaJ-ZcF6.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D09JI-yY.js → NLProgramming-CoaUCKrO.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DTRhiKJn.js → Notes-BKLM_65R.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BAnnNCim.js → NotificationSettings-DoDtK9uZ.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Yr-1fSYi.js → OrderTableRenderer-BJ28TGr-.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-S9EAolpj.js → Organization-MuGsdoIb.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CqcLKqJ8.js → Overflow-BLUN9J4R.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Dw0F9EcU.js → P2P-DWuoBUPd.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BDRwUevN.js → PdhVaultBrowser-CUi37YPj.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-D3_c3nKB.js → Permissions-BYQg2pcr.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CxdMV98x.js → PersonalDataHub-CAxoV2xu.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-CgjNQFLI.js → Pipeline-B33wGvIO.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BHghIIht.js → Privacy-A8yXTORP.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-De6pqaKM.js → ProjectInit-D49I2I1O.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Bg4ZkNYQ.js → ProjectSettings-Ci73jJDw.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CF-yD6Cn.js +1 -0
- package/src/assets/web-panel/assets/Providers-D-etEhg5.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-DA2f3Wts.js → QrScannerModal-Brza0ykJ.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-C1FeHDqp.js → QuickAsk-DFydhjxL.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-B5guaUMN.js → Recommend-DLF8_NhA.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-PDADSds3.js → RemoteSession-dyuStW3x.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-eTlRhgvK.js → Reputation-5F3tA6yw.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D7AqSGY0.js → Row-Ca2A57S5.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-JiuLm4Ja.js → RssFeed-B0bxBkq_.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CwruahW3.js → Search-CFNvHalZ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CdhqaR0b.js → Security-DSoH3Hav.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CU0ZIlcT.js → Services-BHpfEmBQ.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CtduPfAb.js → Skeleton-Dsh-QNmn.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CROXm6AY.js → Skills-BhT1NkSU.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DiZiABFD.js → Sla-DY9snPeJ.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-B5pLcXUw.js → SpeechSettings-CWaX0_Cx.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DBX6J1Oe.js → SyncSettings-B690y_TC.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BLyRJd3-.js → Tasks-2N-w3zWd.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BKa5qzmk.js → Templates-BjwQOQYC.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DnD3a4M6.js → Tenant-CUqHErxY.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DEitQeTb.js → Terminal-C13rXvNy.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CjHggTDq.js → TimelineRenderer-CpbWcya_.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CsGT7sfl.js → Tokens-BXHLGXYC.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-yr4rFDrW.js → Trigger-1e5i65o3.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CLvu1Sjp.js → Trust-FLGqNHs5.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B0m7yUP8.js → UkeySign-BbaR_LJB.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C0VvP4lc.js → VideoEditing-NOp4RIov.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-kllBAG1M.js → Wallet-B7DW7bG4.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-C54UQNLx.js → WebAuthn-BptSUWix.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-B7y8qSvU.js → WorkflowEditor-CAJnDOXS.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DRzTh8CJ.js → chat-I8LgG1-Z.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BSMwSnCx.js → colors-CWe7SOVD.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BTg602H5.js → compact-item-Cx3u3CA3.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-B6EGsdvp.js → createContext-CgD5ArwY.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DLv_872g.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DDKqJ8RD.js → hasIn-BfQWiXN8.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5CsBShd.js → index-3iKP9OTJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dfv2lKu3.js → index-87gMxqhN.js} +1 -1
- package/src/assets/web-panel/assets/{index-C66NpWy5.js → index-B1cX4Rxu.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBT3YeQ9.js → index-B6yChzt1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVTAl5N2.js → index-BREnPKGo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CwPUZbMI.js → index-BUAR7RY-.js} +1 -1
- package/src/assets/web-panel/assets/{index-th2ihDc0.js → index-Bi24S7Dw.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmAubjDi.js → index-BiI-xPRH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUEU48o1.js → index-BuEQSorC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf23wVMs.js → index-Bx7BNIRH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRqt4fO-.js → index-C-rIKccl.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_JzIXUq.js → index-C0nDKhWv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DiW0sDkz.js → index-C0ztiqtB.js} +1 -1
- package/src/assets/web-panel/assets/{index-BICn3Qh1.js → index-C1UjHdgZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpTHIRfZ.js → index-CAUnl4Jv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co7oM1qr.js → index-CMu16vPC.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNxg61YP.js → index-CNYFQxAW.js} +1 -1
- package/src/assets/web-panel/assets/{index-XFe-1twF.js → index-CQDKYbnv.js} +1 -1
- package/src/assets/web-panel/assets/{index-p2HYn89m.js → index-CWZ3REg6.js} +3 -3
- package/src/assets/web-panel/assets/{index-Bx044qDj.js → index-CcX4FSPf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMuGd2--.js → index-Cd79NQAx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGNklbP6.js → index-CdRkCwm4.js} +1 -1
- package/src/assets/web-panel/assets/index-CdiGCibe.js +1 -0
- package/src/assets/web-panel/assets/{index-rjzk9z1Q.js → index-Cy_cCJlr.js} +1 -1
- package/src/assets/web-panel/assets/{index-323Hhxxt.js → index-DAVy98u7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDTvsX8t.js → index-DCJEY2T0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLdrHhML.js → index-DFb-XIKy.js} +1 -1
- package/src/assets/web-panel/assets/{index-pqfux8vZ.js → index-DGMYTN5W.js} +1 -1
- package/src/assets/web-panel/assets/index-D_0z-gyz.js +1 -0
- package/src/assets/web-panel/assets/{index-u2YVld9W.js → index-Dcdm_Z2c.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmAInUkX.js → index-DeizoQVZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHfLYwcW.js → index-DlIyt1qF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWGax2QW.js → index-DmgtY58H.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dc77VR3H.js → index-DmrdUwzU.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1naNj4U.js → index-Doc0Ftpd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsR7Y2NG.js → index-DsQcURkA.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQlHFN_g.js → index-DslTuqro.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqFXGzzC.js → index-V-kIHzAV.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1GFfuqN.js → index-e8BM1yY1.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C3Djh9fa.js → initDefaultProps-DiBszVdG.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BzqFmbSe.js → motion-BGIFFozv.js} +1 -1
- package/src/assets/web-panel/assets/{move-DJo_FFaW.js → move-D5W7mp7B.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-_tlTiBvk.js → mtc-parser-JFIlxJ7F.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CB2ZyxUg.js → omit-CQ3o6LIU.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DZwIFD4u.js → pickAttrs-R8MIlXo3.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DxZY0dgk.js → placementArrow-sW7ylSky.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CzzGt7GL.js → responsiveObserve-Cnl39Vbz.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BaIK52yz.js → slide-sn8tFd14.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-3-FHu9_M.js → statusUtils-IKKY_QxZ.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BkRT68fK.js → styleChecker-BNpV4Nqs.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DHYwKS-s.js → useFlexGapSupport-BWyT_eoU.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DVVUhV8p.js → useFs-D09p6_U9.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CkrFKAzQ.js → usePersonalDataHub-CzW3TkJZ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BuBLFz0c.js → vnode-3s3WoAKB.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-kpm6LtXU.js → zoom-Cjy_673s.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/cowork.js +280 -5
- package/src/commands/plugin.js +819 -64
- package/src/commands/session-location.js +318 -7
- package/src/constants.js +2 -2
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/action-protocol.js +1 -1
- package/src/harness/jsonl-session-store.js +638 -2
- package/src/harness/prompt-compressor.js +4 -0
- package/src/lib/background-agent-keeper-client.js +29 -0
- package/src/lib/background-agent-keeper-protocol.js +78 -3
- package/src/lib/background-agent-launch-barrier.js +74 -0
- package/src/lib/background-agent-supervisor.js +208 -34
- package/src/lib/background-turn-bootstrap-protocol.js +4 -0
- package/src/lib/cowork-task-runner.js +70 -0
- package/src/lib/cowork-workflow.js +42 -9
- package/src/lib/doctor-checkup.js +34 -10
- package/src/lib/dynamic-workflow-draft.js +535 -0
- package/src/lib/dynamic-workflow-facade.js +11 -11
- package/src/lib/dynamic-workflow-runtime.js +2974 -0
- package/src/lib/execution-location-contract.js +111 -7
- package/src/lib/execution-location-runtime.js +3 -1
- package/src/lib/execution-location-target.js +910 -0
- package/src/lib/llm-providers.js +1 -0
- package/src/lib/mcp-call-ledger-store.js +35 -0
- package/src/lib/mcp-call-ledger.js +30 -0
- package/src/lib/plugin-runtime/__tests__/remote-source.test.js +34 -16
- package/src/lib/plugin-runtime/install.js +4956 -657
- package/src/lib/plugin-runtime/manifest.js +3 -1
- package/src/lib/plugin-runtime/marketplace-artifact-readback.js +671 -31
- package/src/lib/plugin-runtime/marketplace-catalog.js +68 -2
- package/src/lib/plugin-runtime/marketplace-impact.js +208 -15
- package/src/lib/plugin-runtime/marketplace-network.js +317 -0
- package/src/lib/plugin-runtime/marketplace-pac-worker.js +15 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +25 -2
- package/src/lib/plugin-runtime/marketplace-source-cache.js +359 -0
- package/src/lib/plugin-runtime/policy.js +21 -6
- package/src/lib/plugin-runtime/publisher-trust.js +332 -0
- package/src/lib/plugin-runtime/remote-source.js +323 -27
- package/src/lib/plugin-runtime/scopes.js +317 -41
- package/src/lib/plugin-runtime/transaction-journal.js +806 -0
- package/src/lib/public-ide-capability-manifest.js +1 -1
- package/src/lib/remote-membership-coordinator.js +8 -6
- package/src/lib/sub-agent-context.js +268 -2
- package/src/lib/task-model-selector.js +1 -1
- package/src/lib/with-file-lock.js +266 -27
- package/src/runtime/agent-core.js +595 -41
- package/src/workers/background-agent-keeper.js +147 -24
- package/src/workers/background-agent-worker.js +383 -134
- package/src/workers/background-turn-bootstrap.js +13 -8
- package/src/assets/web-panel/assets/MobileProjects-Tyd3o2A0.js +0 -1
- package/src/assets/web-panel/assets/Projects-CP8vPvzs.js +0 -1
- package/src/assets/web-panel/assets/Providers-CUnHbNf-.js +0 -1
- package/src/assets/web-panel/assets/devWarning-Dol8jLEP.js +0 -1
- package/src/assets/web-panel/assets/index-C3QX5tOl.js +0 -1
- package/src/assets/web-panel/assets/index-xYybvEic.js +0 -1
|
@@ -3583,6 +3583,10 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3583
3583
|
sessionId: context.sessionId || null,
|
|
3584
3584
|
turnId: context.turnId || null,
|
|
3585
3585
|
toolCallId: context.toolCallId || null,
|
|
3586
|
+
workflowEffectId: context.workflowEffectId || null,
|
|
3587
|
+
workflowChildEffectId: context.workflowChildEffectId || null,
|
|
3588
|
+
workflowChildSequence: context.workflowChildSequence || null,
|
|
3589
|
+
workflowEffectProtocol: context.workflowEffectProtocol || null,
|
|
3586
3590
|
// Parent LLM config — documented at toolContext as forwarded to
|
|
3587
3591
|
// spawn_sub_agent for provider/key inheritance; without this line it
|
|
3588
3592
|
// never actually reached executeToolInner (sub-agents silently fell
|
|
@@ -4969,6 +4973,10 @@ async function executeToolInner(
|
|
|
4969
4973
|
sessionId,
|
|
4970
4974
|
turnId,
|
|
4971
4975
|
toolCallId,
|
|
4976
|
+
workflowEffectId = null,
|
|
4977
|
+
workflowChildEffectId = null,
|
|
4978
|
+
workflowChildSequence = null,
|
|
4979
|
+
workflowEffectProtocol = null,
|
|
4972
4980
|
planManager = null,
|
|
4973
4981
|
permissionRules = null,
|
|
4974
4982
|
effectiveAllowedToolNames = null,
|
|
@@ -6713,6 +6721,10 @@ async function executeToolInner(
|
|
|
6713
6721
|
interaction,
|
|
6714
6722
|
sessionId,
|
|
6715
6723
|
llmOptions,
|
|
6724
|
+
workflowEffectId,
|
|
6725
|
+
workflowChildEffectId,
|
|
6726
|
+
workflowChildSequence,
|
|
6727
|
+
workflowEffectProtocol,
|
|
6716
6728
|
subAgentDepth,
|
|
6717
6729
|
subAgentBudget,
|
|
6718
6730
|
sessionBudget,
|
|
@@ -7646,6 +7658,9 @@ async function executeToolInner(
|
|
|
7646
7658
|
? event
|
|
7647
7659
|
: {
|
|
7648
7660
|
...event,
|
|
7661
|
+
...(["model", "semantic-compaction"].includes(event?.source)
|
|
7662
|
+
? { workflowRequestSource: event.source }
|
|
7663
|
+
: {}),
|
|
7649
7664
|
source:
|
|
7650
7665
|
event?.source === "semantic-compaction"
|
|
7651
7666
|
? "semantic-compaction"
|
|
@@ -7721,6 +7736,9 @@ async function executeToolInner(
|
|
|
7721
7736
|
toolAdmission,
|
|
7722
7737
|
cwd,
|
|
7723
7738
|
llmOptions: skillLlmOptions,
|
|
7739
|
+
...(strictUsageTelemetry === true && workflowChildEffectId
|
|
7740
|
+
? { workflowEffectId: workflowChildEffectId }
|
|
7741
|
+
: {}),
|
|
7724
7742
|
...(sessionBudget ? { sessionBudget } : {}),
|
|
7725
7743
|
...(permissionRules ? { permissionRules } : {}),
|
|
7726
7744
|
...(hostManagedToolPolicy
|
|
@@ -7811,7 +7829,12 @@ async function executeToolInner(
|
|
|
7811
7829
|
toolsUsed: result.toolsUsed,
|
|
7812
7830
|
});
|
|
7813
7831
|
} catch (err) {
|
|
7814
|
-
if (
|
|
7832
|
+
if (
|
|
7833
|
+
err?.runtimeLedgerPersistence === true ||
|
|
7834
|
+
err?.workflowEffectOutcomeUnknown === true
|
|
7835
|
+
) {
|
|
7836
|
+
throw err;
|
|
7837
|
+
}
|
|
7815
7838
|
if (
|
|
7816
7839
|
signal?.aborted ||
|
|
7817
7840
|
skillExecutionSignal?.aborted ||
|
|
@@ -8035,6 +8058,14 @@ async function executeToolInner(
|
|
|
8035
8058
|
ledgerTicket = await ledger.begin({
|
|
8036
8059
|
sessionId,
|
|
8037
8060
|
turnId,
|
|
8061
|
+
...(workflowEffectId
|
|
8062
|
+
? {
|
|
8063
|
+
workflowEffectId,
|
|
8064
|
+
workflowChildEffectId,
|
|
8065
|
+
workflowChildSequence,
|
|
8066
|
+
workflowEffectProtocol,
|
|
8067
|
+
}
|
|
8068
|
+
: {}),
|
|
8038
8069
|
toolName: localToolExecutor.toolName,
|
|
8039
8070
|
serverName: localToolExecutor.serverName,
|
|
8040
8071
|
input: mcpWireInput,
|
|
@@ -8108,12 +8139,20 @@ async function executeToolInner(
|
|
|
8108
8139
|
localToolExecutor.toolName,
|
|
8109
8140
|
mcpWireInput,
|
|
8110
8141
|
];
|
|
8111
|
-
if (signal || mcpDispatchAdmission) {
|
|
8142
|
+
if (signal || mcpDispatchAdmission || workflowEffectId) {
|
|
8112
8143
|
callArguments.push({
|
|
8113
8144
|
...(signal ? { signal } : {}),
|
|
8114
8145
|
...(mcpDispatchAdmission
|
|
8115
8146
|
? { dispatchAdmission: mcpDispatchAdmission }
|
|
8116
8147
|
: {}),
|
|
8148
|
+
...(workflowEffectId
|
|
8149
|
+
? {
|
|
8150
|
+
workflowEffectId,
|
|
8151
|
+
workflowChildEffectId,
|
|
8152
|
+
workflowChildSequence,
|
|
8153
|
+
workflowEffectProtocol,
|
|
8154
|
+
}
|
|
8155
|
+
: {}),
|
|
8117
8156
|
});
|
|
8118
8157
|
}
|
|
8119
8158
|
pendingResult = Reflect.apply(
|
|
@@ -8242,8 +8281,9 @@ async function executeToolInner(
|
|
|
8242
8281
|
);
|
|
8243
8282
|
}
|
|
8244
8283
|
|
|
8284
|
+
let settledLedgerRecord;
|
|
8245
8285
|
try {
|
|
8246
|
-
await ledgerTicket.settle(
|
|
8286
|
+
settledLedgerRecord = await ledgerTicket.settle(
|
|
8247
8287
|
protocolError
|
|
8248
8288
|
? {
|
|
8249
8289
|
status: "failed",
|
|
@@ -8265,11 +8305,26 @@ async function executeToolInner(
|
|
|
8265
8305
|
}
|
|
8266
8306
|
|
|
8267
8307
|
const mcpLedgerId = safeMcpProperty(ledgerTicket, "ledgerId") || null;
|
|
8308
|
+
const mcpLedgerPrewritePersisted =
|
|
8309
|
+
safeMcpProperty(ledgerTicket, "prewritePersisted") === true;
|
|
8310
|
+
const mcpLedgerSettlementPersisted =
|
|
8311
|
+
safeMcpProperty(settledLedgerRecord, "settlementPersistence") ===
|
|
8312
|
+
"persisted";
|
|
8268
8313
|
try {
|
|
8269
8314
|
if (result && typeof result === "object") {
|
|
8270
|
-
return attachDescriptor({
|
|
8315
|
+
return attachDescriptor({
|
|
8316
|
+
...result,
|
|
8317
|
+
mcpLedgerId,
|
|
8318
|
+
mcpLedgerPrewritePersisted,
|
|
8319
|
+
mcpLedgerSettlementPersisted,
|
|
8320
|
+
});
|
|
8271
8321
|
}
|
|
8272
|
-
return attachDescriptor({
|
|
8322
|
+
return attachDescriptor({
|
|
8323
|
+
result,
|
|
8324
|
+
mcpLedgerId,
|
|
8325
|
+
mcpLedgerPrewritePersisted,
|
|
8326
|
+
mcpLedgerSettlementPersisted,
|
|
8327
|
+
});
|
|
8273
8328
|
} catch (projectionError) {
|
|
8274
8329
|
return attachDescriptor({
|
|
8275
8330
|
error:
|
|
@@ -8296,7 +8351,18 @@ async function executeToolInner(
|
|
|
8296
8351
|
interaction &&
|
|
8297
8352
|
typeof interaction.requestHostTool === "function"
|
|
8298
8353
|
) {
|
|
8299
|
-
const hostedResult =
|
|
8354
|
+
const hostedResult = workflowEffectId
|
|
8355
|
+
? await interaction.requestHostTool(
|
|
8356
|
+
name,
|
|
8357
|
+
args,
|
|
8358
|
+
Object.freeze({
|
|
8359
|
+
workflowEffectId,
|
|
8360
|
+
workflowChildEffectId,
|
|
8361
|
+
workflowChildSequence,
|
|
8362
|
+
workflowEffectProtocol,
|
|
8363
|
+
}),
|
|
8364
|
+
)
|
|
8365
|
+
: await interaction.requestHostTool(name, args);
|
|
8300
8366
|
if (hostedResult?.success === false) {
|
|
8301
8367
|
return attachDescriptor({
|
|
8302
8368
|
error:
|
|
@@ -8959,7 +9025,12 @@ function _backgroundSubAgentResultText(entry) {
|
|
|
8959
9025
|
|
|
8960
9026
|
function _throwBackgroundSubAgentUsageFailure(entry) {
|
|
8961
9027
|
const error = entry?.outcome?.fatalError;
|
|
8962
|
-
if (
|
|
9028
|
+
if (
|
|
9029
|
+
error?.runtimeLedgerPersistence === true ||
|
|
9030
|
+
error?.workflowEffectOutcomeUnknown === true
|
|
9031
|
+
) {
|
|
9032
|
+
throw error;
|
|
9033
|
+
}
|
|
8963
9034
|
}
|
|
8964
9035
|
|
|
8965
9036
|
function _throwSettledBackgroundUsageFailure(map) {
|
|
@@ -9514,6 +9585,9 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
9514
9585
|
? u
|
|
9515
9586
|
: {
|
|
9516
9587
|
...u,
|
|
9588
|
+
...(["model", "semantic-compaction"].includes(u?.source)
|
|
9589
|
+
? { workflowRequestSource: u.source }
|
|
9590
|
+
: {}),
|
|
9517
9591
|
source:
|
|
9518
9592
|
u?.source === "semantic-compaction"
|
|
9519
9593
|
? "semantic-compaction"
|
|
@@ -9663,6 +9737,9 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
9663
9737
|
cwd: ctx.cwd,
|
|
9664
9738
|
profile: profile || null,
|
|
9665
9739
|
llmOptions: subLlmOptions,
|
|
9740
|
+
...(ctx.strictUsageTelemetry === true && ctx.workflowChildEffectId
|
|
9741
|
+
? { workflowEffectId: ctx.workflowChildEffectId }
|
|
9742
|
+
: {}),
|
|
9666
9743
|
depth: currentDepth + 1, // nested spawns see their own level
|
|
9667
9744
|
// Same shared counter object so the child's own spawns draw from the run's
|
|
9668
9745
|
// single total-sub-agent pool (breadth cap spans the whole tree).
|
|
@@ -9864,7 +9941,8 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
9864
9941
|
return {
|
|
9865
9942
|
result: subCtx.result,
|
|
9866
9943
|
error: err.message,
|
|
9867
|
-
...(err?.runtimeLedgerPersistence === true
|
|
9944
|
+
...(err?.runtimeLedgerPersistence === true ||
|
|
9945
|
+
err?.workflowEffectOutcomeUnknown === true
|
|
9868
9946
|
? { fatalError: err }
|
|
9869
9947
|
: {}),
|
|
9870
9948
|
};
|
|
@@ -9997,7 +10075,12 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
9997
10075
|
completedAt: subCtx.completedAt,
|
|
9998
10076
|
});
|
|
9999
10077
|
|
|
10000
|
-
if (
|
|
10078
|
+
if (
|
|
10079
|
+
err?.runtimeLedgerPersistence === true ||
|
|
10080
|
+
err?.workflowEffectOutcomeUnknown === true
|
|
10081
|
+
) {
|
|
10082
|
+
throw err;
|
|
10083
|
+
}
|
|
10001
10084
|
|
|
10002
10085
|
return {
|
|
10003
10086
|
error: `Sub-agent failed: ${err.message}`,
|
|
@@ -10077,6 +10160,72 @@ function _hasCompleteProviderUsage(usage) {
|
|
|
10077
10160
|
);
|
|
10078
10161
|
}
|
|
10079
10162
|
|
|
10163
|
+
const PROVIDER_REQUEST_ID_RE = /^[\x21-\x7e]{1,512}$/;
|
|
10164
|
+
const PROVIDER_RECEIPT_ID_RE = /^[A-Za-z0-9._:-]{1,256}$/;
|
|
10165
|
+
|
|
10166
|
+
function _normalizeProviderRequestId(value) {
|
|
10167
|
+
if (value == null) return null;
|
|
10168
|
+
if (typeof value !== "string" || !PROVIDER_REQUEST_ID_RE.test(value)) {
|
|
10169
|
+
throw new TypeError(
|
|
10170
|
+
"providerRequestId must be 1-512 printable ASCII characters",
|
|
10171
|
+
);
|
|
10172
|
+
}
|
|
10173
|
+
return value;
|
|
10174
|
+
}
|
|
10175
|
+
|
|
10176
|
+
function _physicalProviderRequestId(logicalRequestId, attempt) {
|
|
10177
|
+
if (!logicalRequestId) return null;
|
|
10178
|
+
const retry = Number(attempt);
|
|
10179
|
+
if (!Number.isSafeInteger(retry) || retry <= 0) return logicalRequestId;
|
|
10180
|
+
const suffix = `-r${retry}`;
|
|
10181
|
+
return `${logicalRequestId.slice(0, 512 - suffix.length)}${suffix}`;
|
|
10182
|
+
}
|
|
10183
|
+
|
|
10184
|
+
function _providerReceiptId(value) {
|
|
10185
|
+
return typeof value === "string" && PROVIDER_RECEIPT_ID_RE.test(value)
|
|
10186
|
+
? value
|
|
10187
|
+
: null;
|
|
10188
|
+
}
|
|
10189
|
+
|
|
10190
|
+
function _isOfficialOpenAIEndpoint(provider, baseUrl) {
|
|
10191
|
+
if (provider !== "openai") return false;
|
|
10192
|
+
try {
|
|
10193
|
+
const parsed = new URL(String(baseUrl));
|
|
10194
|
+
return (
|
|
10195
|
+
parsed.protocol === "https:" &&
|
|
10196
|
+
parsed.hostname.toLowerCase() === "api.openai.com" &&
|
|
10197
|
+
!parsed.port &&
|
|
10198
|
+
!parsed.username &&
|
|
10199
|
+
!parsed.password
|
|
10200
|
+
);
|
|
10201
|
+
} catch {
|
|
10202
|
+
return false;
|
|
10203
|
+
}
|
|
10204
|
+
}
|
|
10205
|
+
|
|
10206
|
+
/**
|
|
10207
|
+
* Capture only provider-returned identifiers. X-Client-Request-Id is a
|
|
10208
|
+
* trace/correlation header, not an idempotency guarantee, so a locally sent
|
|
10209
|
+
* client id alone is deliberately not called a receipt.
|
|
10210
|
+
*/
|
|
10211
|
+
function _openAIProviderRequestReceipt(response, data, clientRequestId) {
|
|
10212
|
+
if (!clientRequestId) return null;
|
|
10213
|
+
const requestId = _providerReceiptId(
|
|
10214
|
+
response?.headers?.get?.("x-request-id"),
|
|
10215
|
+
);
|
|
10216
|
+
const responseId = _providerReceiptId(data?.id);
|
|
10217
|
+
if (!requestId && !responseId) return null;
|
|
10218
|
+
return Object.freeze({
|
|
10219
|
+
protocol: "cc-provider-request-receipt/v1",
|
|
10220
|
+
provider: "openai",
|
|
10221
|
+
clientRequestId,
|
|
10222
|
+
requestId,
|
|
10223
|
+
responseId,
|
|
10224
|
+
requestIdentitySemantics: "trace-only",
|
|
10225
|
+
independentlyReadable: false,
|
|
10226
|
+
});
|
|
10227
|
+
}
|
|
10228
|
+
|
|
10080
10229
|
/**
|
|
10081
10230
|
* Send a chat completion request with tool definitions.
|
|
10082
10231
|
* Supports 8 providers: ollama, anthropic, openai, deepseek, dashscope, gemini, mistral, volcengine
|
|
@@ -10095,6 +10244,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10095
10244
|
signal,
|
|
10096
10245
|
} = options;
|
|
10097
10246
|
|
|
10247
|
+
const providerRequestId = _normalizeProviderRequestId(
|
|
10248
|
+
options.providerRequestId,
|
|
10249
|
+
);
|
|
10250
|
+
|
|
10098
10251
|
const tools = getEffectiveToolDefinitions(options);
|
|
10099
10252
|
|
|
10100
10253
|
const lastUserMsg = [...rawMessages].reverse().find((m) => m.role === "user");
|
|
@@ -10140,6 +10293,7 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10140
10293
|
),
|
|
10141
10294
|
{
|
|
10142
10295
|
signal,
|
|
10296
|
+
retries: options.workflowEffectId ? 0 : undefined,
|
|
10143
10297
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
10144
10298
|
...(typeof options.onStreamRetry === "function"
|
|
10145
10299
|
? {
|
|
@@ -10289,6 +10443,7 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10289
10443
|
),
|
|
10290
10444
|
{
|
|
10291
10445
|
signal,
|
|
10446
|
+
retries: options.workflowEffectId ? 0 : undefined,
|
|
10292
10447
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
10293
10448
|
...(typeof options.onStreamRetry === "function"
|
|
10294
10449
|
? {
|
|
@@ -10381,6 +10536,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10381
10536
|
`Unsupported provider: ${provider}. Supported: ollama, anthropic, openai, deepseek, dashscope, mistral, gemini, volcengine`,
|
|
10382
10537
|
);
|
|
10383
10538
|
}
|
|
10539
|
+
const supportsOpenAIRequestIdentity = _isOfficialOpenAIEndpoint(
|
|
10540
|
+
provider,
|
|
10541
|
+
url,
|
|
10542
|
+
);
|
|
10384
10543
|
|
|
10385
10544
|
const envKey = providerApiKeyEnvs[provider] || "OPENAI_API_KEY";
|
|
10386
10545
|
const key = apiKey || process.env[envKey];
|
|
@@ -10392,7 +10551,7 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10392
10551
|
dashscope: "qwen-turbo",
|
|
10393
10552
|
mistral: "mistral-large-latest",
|
|
10394
10553
|
gemini: "gemini-2.0-flash",
|
|
10395
|
-
volcengine: "
|
|
10554
|
+
volcengine: "deepseek-v4-flash-260425",
|
|
10396
10555
|
};
|
|
10397
10556
|
|
|
10398
10557
|
// Real token streaming (--include-partial-messages) for every OpenAI-compatible
|
|
@@ -10401,7 +10560,7 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10401
10560
|
// delta-fragmented tool_calls into the standard {message, usage} shape.
|
|
10402
10561
|
if (typeof options.onToken === "function") {
|
|
10403
10562
|
return await _retryStreamingChat(
|
|
10404
|
-
() =>
|
|
10563
|
+
(attempt = 0) =>
|
|
10405
10564
|
_chatOpenAIStreaming(
|
|
10406
10565
|
`${url}/chat/completions`,
|
|
10407
10566
|
{
|
|
@@ -10421,9 +10580,13 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10421
10580
|
options.onStall,
|
|
10422
10581
|
options.streamStallMs,
|
|
10423
10582
|
options.streamStallTimeoutMs,
|
|
10583
|
+
supportsOpenAIRequestIdentity
|
|
10584
|
+
? _physicalProviderRequestId(providerRequestId, attempt)
|
|
10585
|
+
: null,
|
|
10424
10586
|
),
|
|
10425
10587
|
{
|
|
10426
10588
|
signal,
|
|
10589
|
+
retries: options.workflowEffectId ? 0 : undefined,
|
|
10427
10590
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
10428
10591
|
...(typeof options.onStreamRetry === "function"
|
|
10429
10592
|
? {
|
|
@@ -10444,6 +10607,9 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10444
10607
|
headers: {
|
|
10445
10608
|
"Content-Type": "application/json",
|
|
10446
10609
|
Authorization: `Bearer ${key}`,
|
|
10610
|
+
...(supportsOpenAIRequestIdentity && providerRequestId
|
|
10611
|
+
? { "X-Client-Request-Id": providerRequestId }
|
|
10612
|
+
: {}),
|
|
10447
10613
|
},
|
|
10448
10614
|
signal,
|
|
10449
10615
|
body: JSON.stringify({
|
|
@@ -10466,6 +10632,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10466
10632
|
}
|
|
10467
10633
|
const choice = data.choices[0];
|
|
10468
10634
|
const out = { message: choice.message };
|
|
10635
|
+
const providerReceipt = supportsOpenAIRequestIdentity
|
|
10636
|
+
? _openAIProviderRequestReceipt(response, data, providerRequestId)
|
|
10637
|
+
: null;
|
|
10638
|
+
if (providerReceipt) out.providerReceipt = providerReceipt;
|
|
10469
10639
|
if (_hasCompleteProviderUsage(data.usage)) {
|
|
10470
10640
|
// OpenAI/DeepSeek/volcengine report cached prompt tokens AS PART of
|
|
10471
10641
|
// prompt_tokens — split them out so cost prices the cached prefix at the
|
|
@@ -10708,7 +10878,7 @@ export async function _retryStreamingChat(streamFn, opts = {}) {
|
|
|
10708
10878
|
for (;;) {
|
|
10709
10879
|
const attemptStartedAt = now();
|
|
10710
10880
|
try {
|
|
10711
|
-
return await streamFn();
|
|
10881
|
+
return await streamFn(attempt);
|
|
10712
10882
|
} catch (err) {
|
|
10713
10883
|
if (attempt >= retries || !_isRetryableStreamError(err, signal))
|
|
10714
10884
|
throw err;
|
|
@@ -11188,6 +11358,7 @@ function _openaiCachedTokens(usage) {
|
|
|
11188
11358
|
|
|
11189
11359
|
function _openaiInitState() {
|
|
11190
11360
|
return {
|
|
11361
|
+
responseId: null,
|
|
11191
11362
|
text: "",
|
|
11192
11363
|
tools: [],
|
|
11193
11364
|
inputTokens: null,
|
|
@@ -11208,6 +11379,7 @@ function _openaiReduceLine(state, raw, onToken) {
|
|
|
11208
11379
|
} catch {
|
|
11209
11380
|
return state;
|
|
11210
11381
|
}
|
|
11382
|
+
if (!state.responseId) state.responseId = _providerReceiptId(obj.id);
|
|
11211
11383
|
const delta = obj.choices?.[0]?.delta;
|
|
11212
11384
|
if (delta?.content) {
|
|
11213
11385
|
state.text += delta.content;
|
|
@@ -11294,12 +11466,16 @@ async function _chatOpenAIStreaming(
|
|
|
11294
11466
|
onStall,
|
|
11295
11467
|
stallMs,
|
|
11296
11468
|
stallTimeoutMs,
|
|
11469
|
+
providerRequestId = null,
|
|
11297
11470
|
) {
|
|
11298
11471
|
const response = await fetch(apiUrl, {
|
|
11299
11472
|
method: "POST",
|
|
11300
11473
|
headers: {
|
|
11301
11474
|
"Content-Type": "application/json",
|
|
11302
11475
|
Authorization: `Bearer ${apiKey}`,
|
|
11476
|
+
...(providerRequestId
|
|
11477
|
+
? { "X-Client-Request-Id": providerRequestId }
|
|
11478
|
+
: {}),
|
|
11303
11479
|
},
|
|
11304
11480
|
signal,
|
|
11305
11481
|
body: JSON.stringify(body),
|
|
@@ -11333,9 +11509,23 @@ async function _chatOpenAIStreaming(
|
|
|
11333
11509
|
} catch (err) {
|
|
11334
11510
|
if (_streamErrorDisposition(err, signal, state.text) === "rethrow")
|
|
11335
11511
|
throw err;
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11512
|
+
const out = _finalizeTruncatedStream(_openaiFinalize, state);
|
|
11513
|
+
const providerReceipt = _openAIProviderRequestReceipt(
|
|
11514
|
+
response,
|
|
11515
|
+
{ id: state.responseId },
|
|
11516
|
+
providerRequestId,
|
|
11517
|
+
);
|
|
11518
|
+
if (providerReceipt) out.providerReceipt = providerReceipt;
|
|
11519
|
+
return out;
|
|
11520
|
+
}
|
|
11521
|
+
const out = _openaiFinalize(state);
|
|
11522
|
+
const providerReceipt = _openAIProviderRequestReceipt(
|
|
11523
|
+
response,
|
|
11524
|
+
{ id: state.responseId },
|
|
11525
|
+
providerRequestId,
|
|
11526
|
+
);
|
|
11527
|
+
if (providerReceipt) out.providerReceipt = providerReceipt;
|
|
11528
|
+
return out;
|
|
11339
11529
|
}
|
|
11340
11530
|
|
|
11341
11531
|
/**
|
|
@@ -11632,6 +11822,7 @@ function _managedCheckpointUncoveredWriterReason(toolContext) {
|
|
|
11632
11822
|
* { type: "tool-executing", tool, args }
|
|
11633
11823
|
* { type: "tool-result", tool, result, error }
|
|
11634
11824
|
* { type: "model-usage-started", callId, provider, model, source }
|
|
11825
|
+
* { type: "provider-request-receipt", source, workflowEffectId, clientRequestId, requestId, responseId }
|
|
11635
11826
|
* { type: "token-usage", callId, provider, model, usage, source? }
|
|
11636
11827
|
* { type: "model-usage-unknown", callId, provider, model, source, code }
|
|
11637
11828
|
* { type: "response-complete", content }
|
|
@@ -11655,6 +11846,154 @@ function _newModelUsageCallId(source = "model") {
|
|
|
11655
11846
|
return `${prefix}-${randomUUID()}`;
|
|
11656
11847
|
}
|
|
11657
11848
|
|
|
11849
|
+
const WORKFLOW_EFFECT_ID_RE = /^sha256:[a-f0-9]{64}$/;
|
|
11850
|
+
const WORKFLOW_CHILD_EFFECT_PROTOCOL = "cc-workflow-child-effect/v1";
|
|
11851
|
+
const WORKFLOW_TOOL_CALL_ID_RE = /^[\x21-\x7e]{1,512}$/;
|
|
11852
|
+
|
|
11853
|
+
function _normalizeWorkflowEffectId(value) {
|
|
11854
|
+
if (value == null) return null;
|
|
11855
|
+
if (typeof value !== "string" || !WORKFLOW_EFFECT_ID_RE.test(value)) {
|
|
11856
|
+
throw new TypeError("workflowEffectId must be a canonical sha256 identity");
|
|
11857
|
+
}
|
|
11858
|
+
return value;
|
|
11859
|
+
}
|
|
11860
|
+
|
|
11861
|
+
function _workflowProviderRequestId(workflowEffectId, source, sequence) {
|
|
11862
|
+
if (!workflowEffectId) return null;
|
|
11863
|
+
return `ccwf_${createHash("sha256")
|
|
11864
|
+
.update(
|
|
11865
|
+
`${workflowEffectId}\0${String(source || "model")}\0${String(sequence)}`,
|
|
11866
|
+
"utf8",
|
|
11867
|
+
)
|
|
11868
|
+
.digest("hex")}`;
|
|
11869
|
+
}
|
|
11870
|
+
|
|
11871
|
+
function _workflowToolEffectBinding(
|
|
11872
|
+
workflowEffectId,
|
|
11873
|
+
sequence,
|
|
11874
|
+
toolCallId,
|
|
11875
|
+
toolName,
|
|
11876
|
+
) {
|
|
11877
|
+
if (!workflowEffectId) return null;
|
|
11878
|
+
if (
|
|
11879
|
+
!Number.isSafeInteger(sequence) ||
|
|
11880
|
+
sequence < 1 ||
|
|
11881
|
+
typeof toolCallId !== "string" ||
|
|
11882
|
+
!WORKFLOW_TOOL_CALL_ID_RE.test(toolCallId) ||
|
|
11883
|
+
typeof toolName !== "string" ||
|
|
11884
|
+
!toolName
|
|
11885
|
+
) {
|
|
11886
|
+
const error = new TypeError(
|
|
11887
|
+
"workflow-bound tool call identity is malformed",
|
|
11888
|
+
);
|
|
11889
|
+
error.code = "CC_WORKFLOW_CHILD_EFFECT_IDENTITY_INVALID";
|
|
11890
|
+
throw error;
|
|
11891
|
+
}
|
|
11892
|
+
const childEffectId = `sha256:${createHash("sha256")
|
|
11893
|
+
.update(
|
|
11894
|
+
`${workflowEffectId}\0tool\0${String(sequence)}\0${toolCallId}\0${toolName}`,
|
|
11895
|
+
"utf8",
|
|
11896
|
+
)
|
|
11897
|
+
.digest("hex")}`;
|
|
11898
|
+
return Object.freeze({
|
|
11899
|
+
workflowEffectProtocol: WORKFLOW_CHILD_EFFECT_PROTOCOL,
|
|
11900
|
+
workflowEffectId,
|
|
11901
|
+
workflowChildEffectId: childEffectId,
|
|
11902
|
+
workflowChildSequence: sequence,
|
|
11903
|
+
});
|
|
11904
|
+
}
|
|
11905
|
+
|
|
11906
|
+
function _workflowNestedToolOutcomeUnknown(binding, toolName, result) {
|
|
11907
|
+
if (!binding || safeMcpProperty(result, "outcomeUnknown") !== true) {
|
|
11908
|
+
return null;
|
|
11909
|
+
}
|
|
11910
|
+
const error = new Error(
|
|
11911
|
+
`Workflow-bound nested tool ${toolName} has an unknown outcome and requires reconciliation`,
|
|
11912
|
+
);
|
|
11913
|
+
error.code = "CC_WORKFLOW_NESTED_TOOL_OUTCOME_UNKNOWN";
|
|
11914
|
+
error.workflowEffectOutcomeUnknown = true;
|
|
11915
|
+
error.workflowEffectId = binding.workflowEffectId;
|
|
11916
|
+
error.workflowChildEffectId = binding.workflowChildEffectId;
|
|
11917
|
+
return error;
|
|
11918
|
+
}
|
|
11919
|
+
|
|
11920
|
+
function _workflowCompactionOutcomeUnknown(
|
|
11921
|
+
cause,
|
|
11922
|
+
code = "CC_WORKFLOW_COMPACTION_PROVIDER_OUTCOME_UNKNOWN",
|
|
11923
|
+
message = "Workflow-bound semantic compaction provider outcome is unknown",
|
|
11924
|
+
) {
|
|
11925
|
+
const error = new Error(message, cause ? { cause } : undefined);
|
|
11926
|
+
error.code = code;
|
|
11927
|
+
error.workflowEffectOutcomeUnknown = true;
|
|
11928
|
+
error.compactionFailureReported = false;
|
|
11929
|
+
return error;
|
|
11930
|
+
}
|
|
11931
|
+
|
|
11932
|
+
function _markWorkflowCompactionFailureReported(error) {
|
|
11933
|
+
if (error?.workflowEffectOutcomeUnknown === true) {
|
|
11934
|
+
error.compactionFailureReported = true;
|
|
11935
|
+
}
|
|
11936
|
+
return error;
|
|
11937
|
+
}
|
|
11938
|
+
|
|
11939
|
+
function _snapshotProviderRequestReceipt(
|
|
11940
|
+
value,
|
|
11941
|
+
expectedClientRequestId,
|
|
11942
|
+
expectedProvider,
|
|
11943
|
+
) {
|
|
11944
|
+
if (value == null) return null;
|
|
11945
|
+
if (isProxy(value)) {
|
|
11946
|
+
throw new TypeError("provider request receipt must not be a Proxy");
|
|
11947
|
+
}
|
|
11948
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
11949
|
+
const expectedFields = [
|
|
11950
|
+
"clientRequestId",
|
|
11951
|
+
"independentlyReadable",
|
|
11952
|
+
"protocol",
|
|
11953
|
+
"provider",
|
|
11954
|
+
"requestId",
|
|
11955
|
+
"requestIdentitySemantics",
|
|
11956
|
+
"responseId",
|
|
11957
|
+
];
|
|
11958
|
+
const fields = Object.keys(descriptors).sort();
|
|
11959
|
+
const hasOnlyDataFields =
|
|
11960
|
+
fields.length === expectedFields.length &&
|
|
11961
|
+
fields.every(
|
|
11962
|
+
(field, index) =>
|
|
11963
|
+
field === expectedFields[index] &&
|
|
11964
|
+
Object.hasOwn(descriptors[field], "value") &&
|
|
11965
|
+
descriptors[field].enumerable === true,
|
|
11966
|
+
);
|
|
11967
|
+
if (
|
|
11968
|
+
!value ||
|
|
11969
|
+
typeof value !== "object" ||
|
|
11970
|
+
Array.isArray(value) ||
|
|
11971
|
+
!hasOnlyDataFields ||
|
|
11972
|
+
descriptors.protocol.value !== "cc-provider-request-receipt/v1" ||
|
|
11973
|
+
!/^[a-z0-9][a-z0-9._-]{0,63}$/.test(descriptors.provider.value || "") ||
|
|
11974
|
+
descriptors.provider.value !== expectedProvider ||
|
|
11975
|
+
descriptors.clientRequestId.value !== expectedClientRequestId ||
|
|
11976
|
+
descriptors.requestIdentitySemantics.value !== "trace-only" ||
|
|
11977
|
+
descriptors.independentlyReadable.value !== false
|
|
11978
|
+
) {
|
|
11979
|
+
throw new TypeError("provider request receipt is malformed");
|
|
11980
|
+
}
|
|
11981
|
+
const requestId = _providerReceiptId(descriptors.requestId.value);
|
|
11982
|
+
const responseId = _providerReceiptId(descriptors.responseId.value);
|
|
11983
|
+
if (!requestId && !responseId) {
|
|
11984
|
+
throw new TypeError("provider request receipt has no provider identifier");
|
|
11985
|
+
}
|
|
11986
|
+
return Object.freeze({
|
|
11987
|
+
protocol: "cc-provider-request-receipt/v1",
|
|
11988
|
+
provider: descriptors.provider.value,
|
|
11989
|
+
clientRequestId: expectedClientRequestId,
|
|
11990
|
+
requestId,
|
|
11991
|
+
responseId,
|
|
11992
|
+
requestIdentitySemantics: "trace-only",
|
|
11993
|
+
independentlyReadable: false,
|
|
11994
|
+
});
|
|
11995
|
+
}
|
|
11996
|
+
|
|
11658
11997
|
function _runtimeUsageBoundaryFailure(error, code, fallbackMessage) {
|
|
11659
11998
|
const failure =
|
|
11660
11999
|
error && (typeof error === "object" || typeof error === "function")
|
|
@@ -11824,7 +12163,7 @@ function _assertStrictUsageObserver(observer, phase) {
|
|
|
11824
12163
|
function _autoCompactionUsageState(options) {
|
|
11825
12164
|
let state = _autoCompactionUsageStates.get(options);
|
|
11826
12165
|
if (!state) {
|
|
11827
|
-
state = { calls: [] };
|
|
12166
|
+
state = { calls: [], callSequence: null };
|
|
11828
12167
|
_autoCompactionUsageStates.set(options, state);
|
|
11829
12168
|
}
|
|
11830
12169
|
return state;
|
|
@@ -11848,27 +12187,59 @@ function _instrumentAutoCompactorUsage(compactor, options) {
|
|
|
11848
12187
|
const original = installed?.original || compactor.llmQuery;
|
|
11849
12188
|
const state = _autoCompactionUsageState(options);
|
|
11850
12189
|
const wrapper = async function instrumentedCompactionQuery(...args) {
|
|
12190
|
+
const workflowEffectId = _normalizeWorkflowEffectId(
|
|
12191
|
+
options.workflowEffectId,
|
|
12192
|
+
);
|
|
12193
|
+
const callSequence =
|
|
12194
|
+
Number.isSafeInteger(state.callSequence) && state.callSequence > 0
|
|
12195
|
+
? state.callSequence
|
|
12196
|
+
: null;
|
|
12197
|
+
if (workflowEffectId && callSequence == null) {
|
|
12198
|
+
throw _runtimeUsageBoundaryFailure(
|
|
12199
|
+
null,
|
|
12200
|
+
"CC_COMPACTION_REQUEST_SEQUENCE_REQUIRED",
|
|
12201
|
+
"Workflow-bound semantic compaction requires a stable call sequence",
|
|
12202
|
+
);
|
|
12203
|
+
}
|
|
12204
|
+
const providerRequestId = _workflowProviderRequestId(
|
|
12205
|
+
workflowEffectId,
|
|
12206
|
+
"semantic-compaction",
|
|
12207
|
+
callSequence,
|
|
12208
|
+
);
|
|
11851
12209
|
const call = {
|
|
11852
12210
|
callId: _newModelUsageCallId("semantic-compaction"),
|
|
11853
|
-
provider: options.provider ||
|
|
11854
|
-
model: options.model ||
|
|
12211
|
+
provider: options.provider || "ollama",
|
|
12212
|
+
model: options.model || "unknown",
|
|
11855
12213
|
source: "semantic-compaction",
|
|
12214
|
+
workflowEffectId,
|
|
12215
|
+
callSequence,
|
|
12216
|
+
providerRequestId,
|
|
12217
|
+
providerReceipt: null,
|
|
11856
12218
|
observerError: null,
|
|
11857
12219
|
observerFailed: false,
|
|
11858
12220
|
boundaryNotified: false,
|
|
11859
12221
|
};
|
|
11860
12222
|
state.calls.push(call);
|
|
12223
|
+
const boundaryEvent = {
|
|
12224
|
+
type: "model-usage-started",
|
|
12225
|
+
callId: call.callId,
|
|
12226
|
+
provider: call.provider,
|
|
12227
|
+
model: call.model,
|
|
12228
|
+
source: call.source,
|
|
12229
|
+
...(providerRequestId
|
|
12230
|
+
? {
|
|
12231
|
+
workflowEffectId,
|
|
12232
|
+
callSequence,
|
|
12233
|
+
providerRequestId,
|
|
12234
|
+
requestIdentitySemantics: "trace-only",
|
|
12235
|
+
}
|
|
12236
|
+
: {}),
|
|
12237
|
+
};
|
|
11861
12238
|
try {
|
|
11862
12239
|
if (typeof options.onUsageBoundary === "function") {
|
|
11863
12240
|
// Synchronous and before `original`: a host can durably append the
|
|
11864
12241
|
// start row, and any append failure prevents provider spend.
|
|
11865
|
-
const observation = options.onUsageBoundary(
|
|
11866
|
-
type: "model-usage-started",
|
|
11867
|
-
callId: call.callId,
|
|
11868
|
-
provider: call.provider,
|
|
11869
|
-
model: call.model,
|
|
11870
|
-
source: call.source,
|
|
11871
|
-
});
|
|
12242
|
+
const observation = options.onUsageBoundary(boundaryEvent);
|
|
11872
12243
|
if (observation && typeof observation.then === "function") {
|
|
11873
12244
|
void Promise.resolve(observation).catch(() => {});
|
|
11874
12245
|
const error = new Error(
|
|
@@ -11879,13 +12250,54 @@ function _instrumentAutoCompactorUsage(compactor, options) {
|
|
|
11879
12250
|
}
|
|
11880
12251
|
call.boundaryNotified = true;
|
|
11881
12252
|
}
|
|
12253
|
+
if (
|
|
12254
|
+
providerRequestId &&
|
|
12255
|
+
typeof options.onProviderRequestBoundary === "function"
|
|
12256
|
+
) {
|
|
12257
|
+
const observation = options.onProviderRequestBoundary(boundaryEvent);
|
|
12258
|
+
if (observation && typeof observation.then === "function") {
|
|
12259
|
+
void Promise.resolve(observation).catch(() => {});
|
|
12260
|
+
throw _runtimeUsageBoundaryFailure(
|
|
12261
|
+
null,
|
|
12262
|
+
"CC_PROVIDER_REQUEST_BOUNDARY_ASYNC",
|
|
12263
|
+
"Provider request boundary observer must be synchronous",
|
|
12264
|
+
);
|
|
12265
|
+
}
|
|
12266
|
+
}
|
|
11882
12267
|
} catch (error) {
|
|
11883
12268
|
call.observerError = error;
|
|
11884
12269
|
call.observerFailed = true;
|
|
11885
12270
|
throw error;
|
|
11886
12271
|
}
|
|
11887
12272
|
|
|
11888
|
-
|
|
12273
|
+
const requestBinding = providerRequestId
|
|
12274
|
+
? Object.freeze({
|
|
12275
|
+
workflowEffectId,
|
|
12276
|
+
callSequence,
|
|
12277
|
+
source: "semantic-compaction",
|
|
12278
|
+
providerRequestId,
|
|
12279
|
+
requestIdentitySemantics: "trace-only",
|
|
12280
|
+
})
|
|
12281
|
+
: null;
|
|
12282
|
+
try {
|
|
12283
|
+
const result = await original.apply(
|
|
12284
|
+
this,
|
|
12285
|
+
requestBinding ? [...args, requestBinding] : args,
|
|
12286
|
+
);
|
|
12287
|
+
call.providerReceipt = providerRequestId
|
|
12288
|
+
? _snapshotProviderRequestReceipt(
|
|
12289
|
+
result?.providerReceipt,
|
|
12290
|
+
providerRequestId,
|
|
12291
|
+
call.provider,
|
|
12292
|
+
)
|
|
12293
|
+
: null;
|
|
12294
|
+
return result;
|
|
12295
|
+
} catch (error) {
|
|
12296
|
+
if (workflowEffectId) {
|
|
12297
|
+
throw _workflowCompactionOutcomeUnknown(error);
|
|
12298
|
+
}
|
|
12299
|
+
throw error;
|
|
12300
|
+
}
|
|
11889
12301
|
};
|
|
11890
12302
|
|
|
11891
12303
|
try {
|
|
@@ -11939,7 +12351,7 @@ async function _getAutoCompactor(options) {
|
|
|
11939
12351
|
? options.compactionLlmQuery
|
|
11940
12352
|
: options.chatFn
|
|
11941
12353
|
? null
|
|
11942
|
-
: async (prompt) => {
|
|
12354
|
+
: async (prompt, requestBinding = null) => {
|
|
11943
12355
|
const maxOutputTokens = Math.min(
|
|
11944
12356
|
4096,
|
|
11945
12357
|
Math.max(
|
|
@@ -11958,14 +12370,17 @@ async function _getAutoCompactor(options) {
|
|
|
11958
12370
|
onToken: undefined,
|
|
11959
12371
|
onStall: undefined,
|
|
11960
12372
|
onStreamRetry: undefined,
|
|
12373
|
+
providerRequestId:
|
|
12374
|
+
requestBinding?.providerRequestId || undefined,
|
|
11961
12375
|
maxOutputTokens,
|
|
11962
12376
|
},
|
|
11963
12377
|
);
|
|
11964
12378
|
return {
|
|
11965
12379
|
summary: response?.message?.content || "",
|
|
11966
12380
|
usage: response?.usage || null,
|
|
11967
|
-
provider: options.provider ||
|
|
11968
|
-
model: options.model ||
|
|
12381
|
+
provider: options.provider || "ollama",
|
|
12382
|
+
model: options.model || "unknown",
|
|
12383
|
+
providerReceipt: response?.providerReceipt || null,
|
|
11969
12384
|
};
|
|
11970
12385
|
};
|
|
11971
12386
|
compressor = new PromptCompressor({
|
|
@@ -12205,6 +12620,7 @@ export async function* agentLoop(messages, options) {
|
|
|
12205
12620
|
await import("../lib/iteration-budget.js");
|
|
12206
12621
|
const budget = options.iterationBudget || new IterationBudget();
|
|
12207
12622
|
const signal = options.signal || null;
|
|
12623
|
+
const workflowEffectId = _normalizeWorkflowEffectId(options.workflowEffectId);
|
|
12208
12624
|
// Optional OpenTelemetry recorder (TelemetryRecorder). When present, the loop
|
|
12209
12625
|
// emits model/tool/retry spans + a per-run counter; when absent, zero cost.
|
|
12210
12626
|
const recorder = options.recorder || null;
|
|
@@ -12215,6 +12631,7 @@ export async function* agentLoop(messages, options) {
|
|
|
12215
12631
|
options.runId ||
|
|
12216
12632
|
`run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
12217
12633
|
let automaticCompactionSettlementBlocked = false;
|
|
12634
|
+
let workflowChildEffectSequence = 0;
|
|
12218
12635
|
|
|
12219
12636
|
const fileMutationScope = normalizeExactFileMutationScope(
|
|
12220
12637
|
options.fileMutationScope,
|
|
@@ -12314,6 +12731,7 @@ export async function* agentLoop(messages, options) {
|
|
|
12314
12731
|
mcpDispatchAdmission: hermeticExecution
|
|
12315
12732
|
? null
|
|
12316
12733
|
: options.mcpDispatchAdmission || null,
|
|
12734
|
+
workflowEffectId,
|
|
12317
12735
|
// A loop-local identity prevents one session's lazy instruction commits
|
|
12318
12736
|
// from suppressing first-access delivery in another session at the same
|
|
12319
12737
|
// cwd. Hosts may inject a stable identity across resumed turns.
|
|
@@ -12507,10 +12925,13 @@ export async function* agentLoop(messages, options) {
|
|
|
12507
12925
|
// attempt inside one logical `llmCall`, where this generator cannot durably
|
|
12508
12926
|
// bracket each transport attempt. Strict call-ledger sessions therefore
|
|
12509
12927
|
// disable that recovery path and surface the configured provider's failure
|
|
12510
|
-
// as unknown
|
|
12928
|
+
// as unknown. A workflow-bound request does the same: a hidden fallback
|
|
12929
|
+
// would be a second physical provider attempt under one durable effect.
|
|
12930
|
+
// Legacy sessions keep the existing self-healing behavior.
|
|
12511
12931
|
if (
|
|
12512
12932
|
options.runnableProviderFallback !== false &&
|
|
12513
|
-
options.strictUsageTelemetry !== true
|
|
12933
|
+
options.strictUsageTelemetry !== true &&
|
|
12934
|
+
workflowEffectId == null
|
|
12514
12935
|
) {
|
|
12515
12936
|
const { makeRunnableProviderFallback } =
|
|
12516
12937
|
await import("../lib/runnable-provider.js");
|
|
@@ -12654,6 +13075,7 @@ export async function* agentLoop(messages, options) {
|
|
|
12654
13075
|
if (compactor && compactor.shouldAutoCompact(messages)) {
|
|
12655
13076
|
compactionUsageState = _autoCompactionUsageState(options);
|
|
12656
13077
|
compactionUsageState.calls = [];
|
|
13078
|
+
compactionUsageState.callSequence = budget.consumed;
|
|
12657
13079
|
// This is the canonical pre-provider authority snapshot. A local
|
|
12658
13080
|
// micro-compact may change the working input, but the durable CAS must
|
|
12659
13081
|
// still compare against the transcript state that existed before any
|
|
@@ -12750,6 +13172,16 @@ export async function* agentLoop(messages, options) {
|
|
|
12750
13172
|
}
|
|
12751
13173
|
compactionUsageCall = compactionUsageState.calls.at(-1) || null;
|
|
12752
13174
|
const compactionUsage = _compactionTokenUsage(stats);
|
|
13175
|
+
if (compactionUsageCall?.providerReceipt) {
|
|
13176
|
+
yield {
|
|
13177
|
+
type: "provider-request-receipt",
|
|
13178
|
+
callId: compactionUsageCall.callId,
|
|
13179
|
+
workflowEffectId,
|
|
13180
|
+
callSequence: compactionUsageCall.callSequence,
|
|
13181
|
+
source: "semantic-compaction",
|
|
13182
|
+
...compactionUsageCall.providerReceipt,
|
|
13183
|
+
};
|
|
13184
|
+
}
|
|
12753
13185
|
if (stats.degraded === true) {
|
|
12754
13186
|
const usageOutcomeUnknown = stats.summaryUsageUnknown === true;
|
|
12755
13187
|
const projectedStats = usageOutcomeUnknown
|
|
@@ -12816,6 +13248,15 @@ export async function* agentLoop(messages, options) {
|
|
|
12816
13248
|
backgroundSubAgents,
|
|
12817
13249
|
backgroundUsageFailureState,
|
|
12818
13250
|
);
|
|
13251
|
+
if (workflowEffectId) {
|
|
13252
|
+
throw _markWorkflowCompactionFailureReported(
|
|
13253
|
+
_workflowCompactionOutcomeUnknown(
|
|
13254
|
+
null,
|
|
13255
|
+
"CC_WORKFLOW_COMPACTION_USAGE_UNKNOWN",
|
|
13256
|
+
"Workflow-bound semantic compaction usage is unknown",
|
|
13257
|
+
),
|
|
13258
|
+
);
|
|
13259
|
+
}
|
|
12819
13260
|
return;
|
|
12820
13261
|
}
|
|
12821
13262
|
if (
|
|
@@ -12869,6 +13310,15 @@ export async function* agentLoop(messages, options) {
|
|
|
12869
13310
|
backgroundSubAgents,
|
|
12870
13311
|
backgroundUsageFailureState,
|
|
12871
13312
|
);
|
|
13313
|
+
if (workflowEffectId) {
|
|
13314
|
+
throw _markWorkflowCompactionFailureReported(
|
|
13315
|
+
_workflowCompactionOutcomeUnknown(
|
|
13316
|
+
error,
|
|
13317
|
+
"CC_WORKFLOW_COMPACTION_SETTLEMENT_UNKNOWN",
|
|
13318
|
+
"Workflow-bound semantic compaction settlement is unknown",
|
|
13319
|
+
),
|
|
13320
|
+
);
|
|
13321
|
+
}
|
|
12872
13322
|
return;
|
|
12873
13323
|
}
|
|
12874
13324
|
if (!hermeticExecution) {
|
|
@@ -12916,6 +13366,12 @@ export async function* agentLoop(messages, options) {
|
|
|
12916
13366
|
} catch (_e) {
|
|
12917
13367
|
if (isAbortError(_e) || signal?.aborted) throw _e;
|
|
12918
13368
|
if (_e?.runtimeLedgerPersistence === true) throw _e;
|
|
13369
|
+
if (
|
|
13370
|
+
_e?.workflowEffectOutcomeUnknown === true &&
|
|
13371
|
+
_e?.compactionFailureReported === true
|
|
13372
|
+
) {
|
|
13373
|
+
throw _e;
|
|
13374
|
+
}
|
|
12919
13375
|
if (compactionObserverFailure === _e) throw _e;
|
|
12920
13376
|
const observerFailure = compactionUsageState?.calls?.find(
|
|
12921
13377
|
(call) => call.observerFailed && call.observerError === _e,
|
|
@@ -12942,6 +13398,13 @@ export async function* agentLoop(messages, options) {
|
|
|
12942
13398
|
backgroundSubAgents,
|
|
12943
13399
|
backgroundUsageFailureState,
|
|
12944
13400
|
);
|
|
13401
|
+
if (workflowEffectId) {
|
|
13402
|
+
throw _markWorkflowCompactionFailureReported(
|
|
13403
|
+
_e?.workflowEffectOutcomeUnknown === true
|
|
13404
|
+
? _e
|
|
13405
|
+
: _workflowCompactionOutcomeUnknown(_e),
|
|
13406
|
+
);
|
|
13407
|
+
}
|
|
12945
13408
|
return;
|
|
12946
13409
|
}
|
|
12947
13410
|
yield {
|
|
@@ -13048,12 +13511,28 @@ export async function* agentLoop(messages, options) {
|
|
|
13048
13511
|
throwIfAborted(signal);
|
|
13049
13512
|
_throwBackgroundUsageFailureState(backgroundUsageFailureState);
|
|
13050
13513
|
_throwSettledBackgroundUsageFailure(backgroundSubAgents);
|
|
13514
|
+
const providerRequestId = _workflowProviderRequestId(
|
|
13515
|
+
workflowEffectId,
|
|
13516
|
+
"model",
|
|
13517
|
+
budget.consumed,
|
|
13518
|
+
);
|
|
13519
|
+
const providerCallOptions = providerRequestId
|
|
13520
|
+
? { ...effectiveToolOptions, providerRequestId }
|
|
13521
|
+
: effectiveToolOptions;
|
|
13051
13522
|
const modelUsageCall = {
|
|
13052
13523
|
type: "model-usage-started",
|
|
13053
13524
|
callId: _newModelUsageCallId("model"),
|
|
13054
13525
|
provider: options.provider || "ollama",
|
|
13055
13526
|
model: options.model || "unknown",
|
|
13056
13527
|
source: "model",
|
|
13528
|
+
...(providerRequestId
|
|
13529
|
+
? {
|
|
13530
|
+
workflowEffectId,
|
|
13531
|
+
callSequence: budget.consumed,
|
|
13532
|
+
providerRequestId,
|
|
13533
|
+
requestIdentitySemantics: "trace-only",
|
|
13534
|
+
}
|
|
13535
|
+
: {}),
|
|
13057
13536
|
};
|
|
13058
13537
|
// The consumer receives this boundary before `.next()` resumes into the
|
|
13059
13538
|
// provider call, so a durable append failure can prevent spend.
|
|
@@ -13079,6 +13558,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13079
13558
|
}
|
|
13080
13559
|
|
|
13081
13560
|
let result;
|
|
13561
|
+
let providerReceipt = null;
|
|
13082
13562
|
try {
|
|
13083
13563
|
result = await _withSpan(
|
|
13084
13564
|
recorder,
|
|
@@ -13089,7 +13569,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13089
13569
|
"agent.iteration": budget.consumed,
|
|
13090
13570
|
...(modelIdAttrs || {}),
|
|
13091
13571
|
},
|
|
13092
|
-
() => llmCall(callMessages,
|
|
13572
|
+
() => llmCall(callMessages, providerCallOptions),
|
|
13093
13573
|
(span, r) => {
|
|
13094
13574
|
const t = _usageTokens(r?.usage);
|
|
13095
13575
|
if (t) {
|
|
@@ -13130,6 +13610,13 @@ export async function* agentLoop(messages, options) {
|
|
|
13130
13610
|
},
|
|
13131
13611
|
"model_error",
|
|
13132
13612
|
);
|
|
13613
|
+
providerReceipt = providerRequestId
|
|
13614
|
+
? _snapshotProviderRequestReceipt(
|
|
13615
|
+
result?.providerReceipt,
|
|
13616
|
+
providerRequestId,
|
|
13617
|
+
modelUsageCall.provider,
|
|
13618
|
+
)
|
|
13619
|
+
: null;
|
|
13133
13620
|
} catch (error) {
|
|
13134
13621
|
// Never retain provider error text in the usage ledger. Pause on a fixed
|
|
13135
13622
|
// unknown settlement, then rethrow only after the consumer resumes.
|
|
@@ -13150,6 +13637,20 @@ export async function* agentLoop(messages, options) {
|
|
|
13150
13637
|
if (recorder) recorder.counter("agent.model.calls", 1);
|
|
13151
13638
|
const msg = result?.message;
|
|
13152
13639
|
|
|
13640
|
+
if (providerReceipt) {
|
|
13641
|
+
// Yield the provider-returned identifiers before billable usage. A host
|
|
13642
|
+
// that stops after a cost boundary still retains the exact request/effect
|
|
13643
|
+
// binding. This is trace evidence only, never an exactly-once assertion.
|
|
13644
|
+
yield {
|
|
13645
|
+
type: "provider-request-receipt",
|
|
13646
|
+
callId: modelUsageCall.callId,
|
|
13647
|
+
workflowEffectId,
|
|
13648
|
+
callSequence: budget.consumed,
|
|
13649
|
+
source: modelUsageCall.source,
|
|
13650
|
+
...providerReceipt,
|
|
13651
|
+
};
|
|
13652
|
+
}
|
|
13653
|
+
|
|
13153
13654
|
// Close the already-persisted call boundary before honoring an abort that
|
|
13154
13655
|
// raced with a successful provider response. Once the transport returned,
|
|
13155
13656
|
// dropping this settlement would strand a durable `started` row forever.
|
|
@@ -13375,7 +13876,13 @@ export async function* agentLoop(messages, options) {
|
|
|
13375
13876
|
} catch {
|
|
13376
13877
|
toolArgs = {};
|
|
13377
13878
|
}
|
|
13378
|
-
|
|
13879
|
+
const workflowBinding = _workflowToolEffectBinding(
|
|
13880
|
+
workflowEffectId,
|
|
13881
|
+
workflowEffectId ? (workflowChildEffectSequence += 1) : 0,
|
|
13882
|
+
call.id,
|
|
13883
|
+
call.function.name,
|
|
13884
|
+
);
|
|
13885
|
+
return { call, toolArgs, workflowBinding };
|
|
13379
13886
|
});
|
|
13380
13887
|
// Yield every start boundary before dispatch. Async-generator consumers
|
|
13381
13888
|
// persist each boundary before asking for the next item, so by the time
|
|
@@ -13384,20 +13891,21 @@ export async function* agentLoop(messages, options) {
|
|
|
13384
13891
|
try {
|
|
13385
13892
|
throwIfAborted(signal);
|
|
13386
13893
|
_throwBackgroundUsageFailureState(backgroundUsageFailureState);
|
|
13387
|
-
for (const { call, toolArgs } of prepared) {
|
|
13894
|
+
for (const { call, toolArgs, workflowBinding } of prepared) {
|
|
13388
13895
|
yield {
|
|
13389
13896
|
type: "tool-executing",
|
|
13390
13897
|
tool: call.function.name,
|
|
13391
13898
|
args: toolArgs,
|
|
13392
13899
|
tool_use_id: call.id,
|
|
13393
13900
|
turn_id: `${runId}:t${budget.consumed}`,
|
|
13901
|
+
...(workflowBinding || {}),
|
|
13394
13902
|
};
|
|
13395
|
-
startedPrepared.push({ call, toolArgs });
|
|
13903
|
+
startedPrepared.push({ call, toolArgs, workflowBinding });
|
|
13396
13904
|
throwIfAborted(signal);
|
|
13397
13905
|
}
|
|
13398
13906
|
_throwBackgroundUsageFailureState(backgroundUsageFailureState);
|
|
13399
13907
|
} catch (admissionFailure) {
|
|
13400
|
-
for (const { call } of startedPrepared) {
|
|
13908
|
+
for (const { call, workflowBinding } of startedPrepared) {
|
|
13401
13909
|
yield {
|
|
13402
13910
|
type: "tool-result",
|
|
13403
13911
|
tool: call.function.name,
|
|
@@ -13405,6 +13913,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13405
13913
|
error: "tool execution cancelled before dispatch",
|
|
13406
13914
|
tool_use_id: call.id,
|
|
13407
13915
|
turn_id: `${runId}:t${budget.consumed}`,
|
|
13916
|
+
...(workflowBinding || {}),
|
|
13408
13917
|
};
|
|
13409
13918
|
}
|
|
13410
13919
|
throw admissionFailure;
|
|
@@ -13412,18 +13921,30 @@ export async function* agentLoop(messages, options) {
|
|
|
13412
13921
|
// Only after every start has been consumed do we kick every read off.
|
|
13413
13922
|
// Settle each promise into {result,error} so an abort before its ordered
|
|
13414
13923
|
// result is consumed can never surface an unhandled rejection.
|
|
13415
|
-
const inflight = prepared.map(({ call, toolArgs }) => {
|
|
13924
|
+
const inflight = prepared.map(({ call, toolArgs, workflowBinding }) => {
|
|
13416
13925
|
const promise = executeTool(call.function.name, toolArgs, {
|
|
13417
13926
|
...toolContext,
|
|
13418
13927
|
toolCallId: call.id,
|
|
13419
13928
|
turnId: `${runId}:t${budget.consumed}`,
|
|
13929
|
+
...(workflowBinding || {}),
|
|
13420
13930
|
}).then(
|
|
13421
13931
|
(result) => ({ result, error: null }),
|
|
13422
|
-
(err) => ({
|
|
13932
|
+
(err) => ({
|
|
13933
|
+
result: {
|
|
13934
|
+
error: err.message,
|
|
13935
|
+
...(workflowBinding
|
|
13936
|
+
? {
|
|
13937
|
+
code: "CC_WORKFLOW_NESTED_TOOL_EXECUTION_THROWN",
|
|
13938
|
+
outcomeUnknown: true,
|
|
13939
|
+
}
|
|
13940
|
+
: {}),
|
|
13941
|
+
},
|
|
13942
|
+
error: err.message,
|
|
13943
|
+
}),
|
|
13423
13944
|
);
|
|
13424
|
-
return { call, toolArgs, promise };
|
|
13945
|
+
return { call, toolArgs, workflowBinding, promise };
|
|
13425
13946
|
});
|
|
13426
|
-
for (const { call, toolArgs, promise } of inflight) {
|
|
13947
|
+
for (const { call, toolArgs, workflowBinding, promise } of inflight) {
|
|
13427
13948
|
throwIfAborted(signal);
|
|
13428
13949
|
_throwBackgroundUsageFailureState(backgroundUsageFailureState);
|
|
13429
13950
|
const { result: toolResult, error: toolError } = await promise;
|
|
@@ -13463,9 +13984,16 @@ export async function* agentLoop(messages, options) {
|
|
|
13463
13984
|
error: toolError,
|
|
13464
13985
|
tool_use_id: call.id,
|
|
13465
13986
|
turn_id: `${runId}:t${budget.consumed}`,
|
|
13987
|
+
...(workflowBinding || {}),
|
|
13466
13988
|
permission_decision_id: decision?.id || null,
|
|
13467
13989
|
permission_decision: decision,
|
|
13468
13990
|
};
|
|
13991
|
+
const nestedOutcomeUnknown = _workflowNestedToolOutcomeUnknown(
|
|
13992
|
+
workflowBinding,
|
|
13993
|
+
call.function.name,
|
|
13994
|
+
toolResult,
|
|
13995
|
+
);
|
|
13996
|
+
if (nestedOutcomeUnknown) throw nestedOutcomeUnknown;
|
|
13469
13997
|
messages.push({
|
|
13470
13998
|
role: "tool",
|
|
13471
13999
|
content: toolContent,
|
|
@@ -13610,6 +14138,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13610
14138
|
|
|
13611
14139
|
let managedCheckpointHandle = null;
|
|
13612
14140
|
let managedCheckpointPreparationError = null;
|
|
14141
|
+
let workflowBinding = null;
|
|
13613
14142
|
try {
|
|
13614
14143
|
managedCheckpointHandle = beginManagedToolCheckpoint({
|
|
13615
14144
|
enabled: toolContext.managedCheckpoint === true,
|
|
@@ -13663,12 +14192,19 @@ export async function* agentLoop(messages, options) {
|
|
|
13663
14192
|
// event. Consumers use that event to bind hooks, telemetry and turns to
|
|
13664
14193
|
// an actual invocation.
|
|
13665
14194
|
if (!managedCheckpointPreparationError) {
|
|
14195
|
+
workflowBinding = _workflowToolEffectBinding(
|
|
14196
|
+
workflowEffectId,
|
|
14197
|
+
workflowEffectId ? (workflowChildEffectSequence += 1) : 0,
|
|
14198
|
+
call.id,
|
|
14199
|
+
toolName,
|
|
14200
|
+
);
|
|
13666
14201
|
yield {
|
|
13667
14202
|
type: "tool-executing",
|
|
13668
14203
|
tool: toolName,
|
|
13669
14204
|
args: toolArgs,
|
|
13670
14205
|
tool_use_id: call.id,
|
|
13671
14206
|
turn_id: `${runId}:t${budget.consumed}`,
|
|
14207
|
+
...(workflowBinding || {}),
|
|
13672
14208
|
};
|
|
13673
14209
|
// The event yield is a host persistence boundary. A detached child's
|
|
13674
14210
|
// fatal usage write can settle while the consumer handles it; fence
|
|
@@ -13686,6 +14222,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13686
14222
|
error: "authoritative background usage persistence failure",
|
|
13687
14223
|
tool_use_id: call.id,
|
|
13688
14224
|
turn_id: `${runId}:t${budget.consumed}`,
|
|
14225
|
+
...(workflowBinding || {}),
|
|
13689
14226
|
};
|
|
13690
14227
|
throw backgroundFailure;
|
|
13691
14228
|
}
|
|
@@ -13735,6 +14272,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13735
14272
|
...toolContext,
|
|
13736
14273
|
toolCallId: call.id,
|
|
13737
14274
|
turnId: `${runId}:t${budget.consumed}`,
|
|
14275
|
+
...(workflowBinding || {}),
|
|
13738
14276
|
}),
|
|
13739
14277
|
(span, r) => {
|
|
13740
14278
|
span.setAttribute(
|
|
@@ -13774,7 +14312,15 @@ export async function* agentLoop(messages, options) {
|
|
|
13774
14312
|
);
|
|
13775
14313
|
} catch (err) {
|
|
13776
14314
|
if (err?.runtimeLedgerPersistence === true) throw err;
|
|
13777
|
-
toolResult = {
|
|
14315
|
+
toolResult = {
|
|
14316
|
+
error: err.message,
|
|
14317
|
+
...(workflowBinding
|
|
14318
|
+
? {
|
|
14319
|
+
code: "CC_WORKFLOW_NESTED_TOOL_EXECUTION_THROWN",
|
|
14320
|
+
outcomeUnknown: true,
|
|
14321
|
+
}
|
|
14322
|
+
: {}),
|
|
14323
|
+
};
|
|
13778
14324
|
toolError = err.message;
|
|
13779
14325
|
}
|
|
13780
14326
|
}
|
|
@@ -13878,10 +14424,18 @@ export async function* agentLoop(messages, options) {
|
|
|
13878
14424
|
error: toolError,
|
|
13879
14425
|
tool_use_id: call.id,
|
|
13880
14426
|
turn_id: `${runId}:t${budget.consumed}`,
|
|
14427
|
+
...(workflowBinding || {}),
|
|
13881
14428
|
permission_decision_id: decision?.id || null,
|
|
13882
14429
|
permission_decision: decision,
|
|
13883
14430
|
};
|
|
13884
14431
|
|
|
14432
|
+
const nestedOutcomeUnknown = _workflowNestedToolOutcomeUnknown(
|
|
14433
|
+
workflowBinding,
|
|
14434
|
+
toolName,
|
|
14435
|
+
toolResult,
|
|
14436
|
+
);
|
|
14437
|
+
if (nestedOutcomeUnknown) throw nestedOutcomeUnknown;
|
|
14438
|
+
|
|
13885
14439
|
messages.push({
|
|
13886
14440
|
role: "tool",
|
|
13887
14441
|
content: toolContent,
|