chainlesschain 0.166.129 → 0.166.130

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.
Files changed (168) hide show
  1. package/README.md +8 -2
  2. package/package.json +1 -1
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/assets/{AIOps-CjPaaF2r.js → AIOps-o-rFKEYL.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-_zlP_Z6z.js → ActionButton-Dzv1ReHF.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-C7X31L8l.js → Analytics-Bt7H_jrh.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-BmYa34Se.js → AppLayout-CgynsRFP.js} +4 -4
  9. package/src/assets/web-panel/assets/{Artifacts-B_YKNjlp.js → Artifacts-gghOGDyE.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-5JsI67XQ.js → Audit-DBXn-AZ6.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-BL3QbzvS.js → BackgroundAgents--dxPftKa.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-BRmg-gTa.js → Backup-D9Zf_2tH.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-DNE7mT3K.js → BaseInput-DDTOjovq.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-OYwAopdM.js → Chat-2ETqdBLn.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Dtxw3Wgt.js → ChatBubbleRenderer-DSg2Xs8G.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-nMgYkH8H.js → Checkbox-B5uzaLLP.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-B9G2ngLI.js → Codegen-4ieEEIwt.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-i0owJaGP.js → Col-D3I2kUGu.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-B3Ta0mI_.js → Community-DeYxFMJb.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-DDXrvvm-.js → Compact-5GigOmb8.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-Bn4Uq6U1.js → Compliance-DLVjbVUh.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-CO5NKD6r.js → Cowork-DfUKa0T5.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-ByjNese0.js → Cron-_RpktpO5.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-BN1FUYyi.js → Crosschain-7x6xdbwH.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-CUFX5RL3.js → DID-ccVhToC1.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-D_2FDPBP.js → Dashboard-DhygcaoK.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-lGOMtIzb.js → Dropdown-DFplwXK7.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-DA3Qf1S2.js → EmailListRenderer-Bm01soCN.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-DLcnicCr.js → EvolutionSettings-C4v--DkD.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BPOSaIN1.js → FamilyGuardDashboard-ChQXDBA3.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-DzJUCQq8.js → Federation-C0yomE-M.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-DVx1XNKx.js → FormItemContext-DtT3ZEZK.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-BkqzO_lh.js → GenericCardRenderer-DgITtFRv.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-Dr_rdT_j.js → Git-CCY42R8S.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-DyVkZddw.js → Governance-N66Bwvqg.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-IN2YDd4v.js → Inference-BkbPuR_2.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-Ceiy4n6N.js → KnowledgeGraph-B3PibXdA.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-d7pIEAX2.js → Logs-CUtNB_N6.js} +2 -2
  39. package/src/assets/web-panel/assets/{MarkdownRenderer-DmSl0MNI.js → MarkdownRenderer-D-V4dOe3.js} +1 -1
  40. package/src/assets/web-panel/assets/{Marketplace-uVE7U14g.js → Marketplace-DLNJb6Nr.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-DUfBM--y.js → McpTools-2zGjJb5K.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-6gkcR02J.js → Memory-9rNZ1EvR.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-Cl6ys2O9.js → MobileBridge-Cw7sAAgn.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-5P8jN4gf.js → MobileProjects-8XACrqqy.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-DtiT1Kol.js → Mtc-mg02JNy-.js} +4 -4
  46. package/src/assets/web-panel/assets/{MtcAudit-DZz8iiTE.js → MtcAudit-B1Vkhj2l.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-DFH3-fBJ.js → Multisig-BQEeA7GG.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-BYNuDOt-.js → NLProgramming-BIbkjZV3.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-BCY4jgYy.js → Notes-DIwhkZNY.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-Bk2ltghU.js → NotificationSettings-Cj9175ce.js} +1 -1
  51. package/src/assets/web-panel/assets/OrderTableRenderer-IfNpXT2R.js +1 -0
  52. package/src/assets/web-panel/assets/{Organization-CY4_mSiV.js → Organization-DPFp6G9o.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-CaRUAOY_.js → Overflow-ky9UfGv4.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-Bd96rBWQ.js → P2P-tXck8GLq.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-JjnExxan.js → PdhVaultBrowser-DSvpQl9k.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-CW1PUJB0.js → Permissions-CKPkdLj-.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-BNn9alTk.js → PersonalDataHub-DnqXc12l.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-01_PBiUu.js → Pipeline-BKjFU_kd.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-BP4DlVGb.js → Privacy-ChC-J5Tn.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-CAMnQj4n.js → ProjectInit-ByFZG9sY.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-DKxV5On_.js → ProjectSettings-Bbv1Kiw-.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-B_4kRnM8.js → Projects-QYyGW31-.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-DeqqZyUv.js → Providers-CJLnWw0r.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-fFkycCT4.js → QrScannerModal-er_HkLCI.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-Ln6qQidy.js → QuickAsk-DoXU0np9.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-DeENA-y0.js → Recommend-DCo_vuaf.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-CRxSYxo4.js → RemoteSession-CLuL925Z.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-B2kU2F0l.js → Reputation-CNNCA_-M.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-lV_nLlFq.js → Row-Vu4j631i.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-Df21mCdF.js → RssFeed-C18B4xiy.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-8_Dz4qU9.js → Search-DxiqccE2.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-Cl5-PEcp.js → Security-Droe_hHI.js} +3 -3
  73. package/src/assets/web-panel/assets/{Services-C5qgCqA7.js → Services-CwmmyXzq.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-ASRgSh_Y.js → Skeleton-CrFs6rUL.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-DWx01ZJ7.js → Skills-Dp-d2miK.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-I2gbgtW8.js → Sla-2DFXVbK4.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-BqTikzfe.js → SpeechSettings-Cdd9lCoy.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-D3zCpBFV.js → SyncSettings-CxQhcYSk.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-DjMWII45.js → Tasks-BHWVRfXx.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-Cq7qDnHX.js → Templates-DNFk3a5_.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-DEasKDpQ.js → Tenant-B6X6dPo8.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-J6fLkTzi.js → Terminal-BuUNoLGM.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-CNvWrWN-.js → TimelineRenderer-DThrBYj8.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-BSgHJCKH.js → Tokens-CA_u4Blu.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-DgGU_D0o.js → Trigger-CXrW4Nry.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-BANlv-uB.js → Trust-DHcLpNy3.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-qh8GPRsU.js → UkeySign-B_fni4C2.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-DBiGTB4H.js → VideoEditing-g9nf2EhS.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-DMUFR7cL.js → Wallet-C8pOjIve.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-DP9nQQzW.js → WebAuthn-BaKNjxZt.js} +2 -2
  91. package/src/assets/web-panel/assets/{WorkflowEditor-DT_6jDkL.js → WorkflowEditor-CX030Wb1.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-C_kELmV6.js → chat-BpJsXlTK.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-DE-ZxAv_.js → colors-CUNg0-fh.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-BowulLDi.js → compact-item-C3tFHnhu.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-DCh8oMBQ.js → createContext-B8rTvO61.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-B4_IVU_n.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-Be7mK-iw.js → hasIn-CU6RIciB.js} +1 -1
  98. package/src/assets/web-panel/assets/index--6BUI55w.js +1 -0
  99. package/src/assets/web-panel/assets/{index-Ao-LXr-d.js → index-111hR8WZ.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-4KkYmFy5.js → index-1L0tt7G2.js} +1 -1
  101. package/src/assets/web-panel/assets/index-5Q1bepcM.js +1 -0
  102. package/src/assets/web-panel/assets/{index-lN916819.js → index-6EwPIfXu.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Ck6MYKVN.js → index-B10Ia2KL.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-C_VnSUjh.js → index-B1SLBLli.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DOebEvgn.js → index-B8_VQAav.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BdzVLz-c.js → index-BG4zuFf0.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DEDVYN7D.js → index-BJjEAoDb.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DSRKtgJg.js → index-BMuPJra-.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-DSqZBvQM.js → index-BOCjph-k.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-_cYsz4df.js → index-BOlAutGy.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-nLHTuHoT.js → index-BPWJw4Ji.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C2pCquZC.js → index-BpBaOWmV.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DMKo49Um.js → index-BzhobTgZ.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BDIIR8g6.js → index-CDlHvQtw.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DLCzaLH4.js → index-CEIoRm_c.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-D3lOYd9_.js → index-CLQjdKmE.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-6OluUVJJ.js → index-CPF7Vqri.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CwJfLNqv.js → index-CPmgKQcl.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DbrQO1p9.js → index-CcpMHPWd.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-B-3EDOlf.js → index-Cyksnofp.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Cvy4vdVW.js → index-CyyhilXV.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-3Ql7xQLn.js → index-D4njcYFw.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BlzMqaWB.js → index-Dc9pcin6.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DMDaGPxG.js → index-DfAC55QA.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CKmC6ugN.js → index-DgNCfwvg.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DN1AT3FH.js → index-DvfhIBNZ.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CL2hAUWh.js → index-Hbzd9WeI.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DPX3N4T8.js → index-IiS7WoUl.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CXvy8HrM.js → index-K2Uqqkr1.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DjC2TJeH.js → index-KgR1f2Gq.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-OH54KMLN.js → index-X6e0cGRU.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CecGCLWI.js → index-Xa6TlaD7.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BwY31W-u.js → index-YczWc2_0.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-CUXfwAhF.js → index-h_ANnbR8.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-Qx8cTReg.js → index-k7QsBwyo.js} +3 -3
  136. package/src/assets/web-panel/assets/{index-LVrxqU88.js → index-lo9rgpyj.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-BNhziAal.js → initDefaultProps-FI8D7E2x.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-fUkbJz38.js → motion-B1hpJYSD.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-rFx211Cl.js → move-Vl1vUReW.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-CEP1wN3R.js → mtc-parser-6Cu2aFME.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-DacHd_Zm.js → omit-VRKL8iSO.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-Dqp58Ep2.js → pickAttrs-DZfWsOe0.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-Cv6Rm0pV.js → placementArrow-qmcOUc4W.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-rNE0p9ZW.js → responsiveObserve-BLB6SsSw.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-C97JxD4S.js → slide-41jdYeSH.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-Cxk1gV9M.js → statusUtils-Yn8OQ5ey.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-CbtKKsPo.js → styleChecker-4CEwz9Zd.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-CQATs2JQ.js → useFlexGapSupport-BClv53kR.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-6c7qrpE_.js → useFs-Bugo8HuF.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-OjxtBGe7.js → usePersonalDataHub-B-q2ElB0.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-CSlXfUSh.js → vnode-ejVeFJ0x.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-Cc1qKiSZ.js → zoom-DM1y_KKP.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/constants.js +1 -1
  155. package/src/data/changelog.json +14 -1
  156. package/src/lib/goal-assess.js +4 -1
  157. package/src/lib/goal-check-evidence.js +77 -9
  158. package/src/lib/goal-model-call.js +107 -0
  159. package/src/lib/goal-workspace-evidence.js +299 -0
  160. package/src/lib/llm-onboarding-catalog.json +1 -1
  161. package/src/lib/llm-providers.js +1 -0
  162. package/src/lib/task-model-selector.js +1 -1
  163. package/src/runtime/agent-core.js +27 -1
  164. package/src/runtime/headless-runner.js +201 -107
  165. package/src/assets/web-panel/assets/OrderTableRenderer-OdeXEGAn.js +0 -1
  166. package/src/assets/web-panel/assets/devWarning-BVvJAp91.js +0 -1
  167. package/src/assets/web-panel/assets/index-B7IhCfsh.js +0 -1
  168. package/src/assets/web-panel/assets/index-BMrbe_Ey.js +0 -1
@@ -0,0 +1,299 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ import executionBroker from "./process-execution-broker/index.js";
5
+ import {
6
+ fileStatIdentity,
7
+ sameFileStatIdentity,
8
+ samePathHandleFileIdentity,
9
+ } from "./secure-file-identity.js";
10
+
11
+ const fsp = fs.promises;
12
+ const sha256 = (value) =>
13
+ `sha256:${createHash("sha256").update(value).digest("hex")}`;
14
+ const fail = (code) => {
15
+ throw Object.assign(new Error(code), { goalWorkspaceCode: code });
16
+ };
17
+ const LIMITS = Object.freeze({
18
+ maxFiles: 50_000,
19
+ maxBytes: 512 * 1024 * 1024,
20
+ maxFileBytes: 64 * 1024 * 1024,
21
+ maxMs: 15_000,
22
+ });
23
+
24
+ function inside(root, target) {
25
+ const relative = path.relative(root, target);
26
+ return (
27
+ relative !== ".." &&
28
+ !relative.startsWith(`..${path.sep}`) &&
29
+ !path.isAbsolute(relative)
30
+ );
31
+ }
32
+
33
+ function samePath(left, right) {
34
+ return process.platform === "win32"
35
+ ? left.toLowerCase() === right.toLowerCase()
36
+ : left === right;
37
+ }
38
+
39
+ async function hasGitAncestor(root) {
40
+ for (let current = root; ; current = path.dirname(current)) {
41
+ try {
42
+ await fsp.lstat(path.join(current, ".git"));
43
+ return true;
44
+ } catch (error) {
45
+ if (error.code !== "ENOENT") throw error;
46
+ }
47
+ if (path.dirname(current) === current) return false;
48
+ }
49
+ }
50
+
51
+ function gitFiles(root, maxFiles) {
52
+ // No shell, index writes, filters, hooks, or inherited Git redirection. The
53
+ // broker remains the sole process boundary; no provider credentials needed.
54
+ const env = Object.fromEntries(
55
+ Object.entries(process.env).filter(([key]) =>
56
+ /^(path|systemroot|windir|temp|tmp|home|userprofile)$/i.test(key),
57
+ ),
58
+ );
59
+ const result = executionBroker.spawnSync(
60
+ "git",
61
+ [
62
+ "-c",
63
+ "core.fsmonitor=false",
64
+ "ls-files",
65
+ "-z",
66
+ "--cached",
67
+ "--others",
68
+ "--exclude-standard",
69
+ "--",
70
+ ".",
71
+ ],
72
+ {
73
+ cwd: root,
74
+ shell: false,
75
+ windowsHide: true,
76
+ encoding: "utf8",
77
+ timeout: 5000,
78
+ maxBuffer: 8 * 1024 * 1024,
79
+ origin: "headless-goal:workspace-evidence",
80
+ scope: "headless-goal",
81
+ policy: "allow",
82
+ env: { ...env, GIT_OPTIONAL_LOCKS: "0", GIT_TERMINAL_PROMPT: "0" },
83
+ },
84
+ );
85
+ if (result.error || result.signal || result.status !== 0)
86
+ fail("source-list-unavailable");
87
+ const files = [...new Set(result.stdout.split("\0").filter(Boolean))].sort();
88
+ if (files.length > maxFiles) fail("resource-limit");
89
+ return files;
90
+ }
91
+
92
+ async function directoryFiles(root, check, maxFiles) {
93
+ const files = [];
94
+ let entries = 0;
95
+ const walk = async (relative) => {
96
+ check();
97
+ const dir = await fsp.opendir(path.join(root, relative));
98
+ for await (const entry of dir) {
99
+ check();
100
+ if (++entries > maxFiles) fail("resource-limit");
101
+ const name = path.join(relative, entry.name);
102
+ if (entry.name === ".git") continue;
103
+ if (entry.isDirectory()) await walk(name);
104
+ else files.push(name);
105
+ }
106
+ };
107
+ await walk("");
108
+ return files.sort();
109
+ }
110
+
111
+ /** Read-only content evidence. Git scope is tracked + nonignored files under
112
+ * cwd; artifact reads also cover ignored output files. No Git scope is silently
113
+ * replaced by a smaller directory scan when Git fails. This detects ordinary
114
+ * concurrent changes, not a hostile writer that can perform undetectable ABA.
115
+ */
116
+ export async function captureGoalWorkspace(
117
+ cwd,
118
+ call,
119
+ { signal, limits = {} } = {},
120
+ ) {
121
+ const bounds = { ...LIMITS, ...limits };
122
+ const started = Date.now();
123
+ let rootHandle;
124
+ const check = () => {
125
+ if (signal?.aborted) fail("cancelled");
126
+ if (Date.now() - started > bounds.maxMs) fail("resource-limit");
127
+ };
128
+ try {
129
+ check();
130
+ const artifact = call?.tool === "read_file";
131
+ const workspaceTool = call?.tool === "run_shell";
132
+ if (!artifact && !workspaceTool) fail("tool-scope-unavailable");
133
+ const root = await fsp.realpath(path.resolve(cwd));
134
+ const rootStat = await fsp.stat(root, { bigint: true });
135
+ if (!rootStat.isDirectory()) fail("workspace-unavailable");
136
+ rootHandle = await fsp.open(root, fs.constants.O_RDONLY);
137
+ const rootDevice = (await rootHandle.stat({ bigint: true })).dev;
138
+ const workspaceId = sha256(
139
+ JSON.stringify([
140
+ root,
141
+ String(rootStat.dev),
142
+ String(rootStat.ino),
143
+ String(rootStat.birthtimeNs),
144
+ ]),
145
+ );
146
+ let scope;
147
+ let list;
148
+ if (artifact) {
149
+ if (typeof call.args?.path !== "string" || !call.args.path)
150
+ fail("artifact-path-unavailable");
151
+ const target = path.resolve(root, call.args.path);
152
+ if (!inside(root, target) || target === root) fail("outside-workspace");
153
+ scope = "artifact";
154
+ list = async () => [path.relative(root, target)];
155
+ } else if (await hasGitAncestor(root)) {
156
+ scope = "git-visible-files-under-cwd";
157
+ list = async () => gitFiles(root, bounds.maxFiles);
158
+ } else {
159
+ scope = "directory-files-under-cwd";
160
+ list = () => directoryFiles(root, check, bounds.maxFiles);
161
+ }
162
+ const files = await list();
163
+ check();
164
+ const content = createHash("sha256");
165
+ const freshness = createHash("sha256");
166
+ const identities = [];
167
+ const artifacts = [];
168
+ let totalBytes = 0;
169
+ for (const relative of files) {
170
+ check();
171
+ const target = path.resolve(root, relative);
172
+ if (!inside(root, target)) fail("outside-workspace");
173
+ // Canonical parents must stay within this exact workspace. Symlinks,
174
+ // submodules, special files and unreadable entries are not partial proof.
175
+ let before;
176
+ try {
177
+ before = await fsp.lstat(target, { bigint: true });
178
+ } catch (error) {
179
+ // Deleted tracked files are part of the current source version. A
180
+ // missing requested artifact, however, cannot support completion.
181
+ if (scope !== "git-visible-files-under-cwd" || error.code !== "ENOENT")
182
+ throw error;
183
+ content.update(
184
+ JSON.stringify({ path: relative, missing: true }) + "\n",
185
+ );
186
+ freshness.update(
187
+ JSON.stringify({ path: relative, missing: true }) + "\n",
188
+ );
189
+ identities.push([target, null]);
190
+ continue;
191
+ }
192
+ const canonical = await fsp.realpath(target);
193
+ if (!samePath(canonical, target) || !inside(root, canonical))
194
+ fail("linked-entry");
195
+ if (!before.isFile() || before.nlink !== 1n) fail("unsupported-entry");
196
+ if (before.size > BigInt(bounds.maxFileBytes)) fail("resource-limit");
197
+ totalBytes += Number(before.size);
198
+ if (totalBytes > bounds.maxBytes) fail("resource-limit");
199
+ let handle;
200
+ try {
201
+ handle = await fsp.open(
202
+ target,
203
+ fs.constants.O_RDONLY |
204
+ (fs.constants.O_NOFOLLOW || 0) |
205
+ (fs.constants.O_NONBLOCK || 0),
206
+ );
207
+ const opened = await handle.stat({ bigint: true });
208
+ if (!samePathHandleFileIdentity(before, opened, rootDevice))
209
+ fail("workspace-changed");
210
+ const digest = createHash("sha256");
211
+ const buffer = Buffer.alloc(64 * 1024);
212
+ let size = 0;
213
+ while (true) {
214
+ check();
215
+ const { bytesRead } = await handle.read(
216
+ buffer,
217
+ 0,
218
+ buffer.length,
219
+ null,
220
+ );
221
+ if (bytesRead === 0) break;
222
+ size += bytesRead;
223
+ if (size > Number(before.size)) fail("workspace-changed");
224
+ digest.update(buffer.subarray(0, bytesRead));
225
+ }
226
+ const after = await fsp.lstat(target, { bigint: true });
227
+ if (
228
+ size !== Number(before.size) ||
229
+ !sameFileStatIdentity(before, after) ||
230
+ !samePathHandleFileIdentity(
231
+ after,
232
+ await handle.stat({ bigint: true }),
233
+ rootDevice,
234
+ )
235
+ )
236
+ fail("workspace-changed");
237
+ const entry = {
238
+ path: relative.split(path.sep).join("/"),
239
+ size,
240
+ digest: `sha256:${digest.digest("hex")}`,
241
+ };
242
+ content.update(JSON.stringify(entry) + "\n");
243
+ freshness.update(
244
+ JSON.stringify([entry.path, fileStatIdentity(after)]) + "\n",
245
+ );
246
+ identities.push([target, after]);
247
+ if (artifact) artifacts.push(entry);
248
+ } finally {
249
+ await handle?.close();
250
+ }
251
+ }
252
+ if (JSON.stringify(await list()) !== JSON.stringify(files))
253
+ fail("workspace-changed");
254
+ check();
255
+ for (const [target, stat] of identities) {
256
+ check();
257
+ let current = null;
258
+ try {
259
+ current = await fsp.lstat(target, { bigint: true });
260
+ } catch (error) {
261
+ if (error.code !== "ENOENT") throw error;
262
+ }
263
+ if (
264
+ stat === null
265
+ ? current !== null
266
+ : !current || !sameFileStatIdentity(stat, current)
267
+ )
268
+ fail("workspace-changed");
269
+ }
270
+ const finalRoot = await fsp.stat(root, { bigint: true });
271
+ if (
272
+ (await fsp.realpath(path.resolve(cwd))) !== root ||
273
+ finalRoot.ino !== rootStat.ino ||
274
+ finalRoot.dev !== rootStat.dev ||
275
+ finalRoot.birthtimeNs !== rootStat.birthtimeNs
276
+ )
277
+ fail("workspace-changed");
278
+ check();
279
+ return {
280
+ verified: true,
281
+ scope,
282
+ workspaceId,
283
+ digest: `sha256:${content.digest("hex")}`,
284
+ freshnessDigest: `sha256:${freshness.digest("hex")}`,
285
+ fileCount: files.length,
286
+ totalBytes,
287
+ ...(artifact ? { artifacts } : {}),
288
+ };
289
+ } catch (error) {
290
+ // File/provider text is not a diagnostic channel. Missing/denied/unstable
291
+ // coverage remains unavailable and must not become a positive verdict.
292
+ return {
293
+ verified: false,
294
+ reason: error.goalWorkspaceCode || "workspace-unavailable",
295
+ };
296
+ } finally {
297
+ await rootHandle?.close();
298
+ }
299
+ }
@@ -10,7 +10,7 @@
10
10
  "label": "Volcengine / Doubao (volcengine)",
11
11
  "cliLabel": "Volcengine (火山引擎/豆包)",
12
12
  "baseUrl": "https://ark.cn-beijing.volces.com/api/v3",
13
- "defaultModel": "deepseek-v4-1-flash-260910",
13
+ "defaultModel": "deepseek-v4-1-flash-economy-261017",
14
14
  "needsKey": true,
15
15
  "visionModel": "doubao-seed-2-0-lite-260215"
16
16
  },
@@ -91,6 +91,7 @@ export const BUILT_IN_PROVIDERS = {
91
91
  baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
92
92
  apiKeyEnv: "VOLCENGINE_API_KEY",
93
93
  models: [
94
+ "deepseek-v4-1-flash-economy-261017",
94
95
  "deepseek-v4-1-flash-260910",
95
96
  "deepseek-v4-flash-ga-260731",
96
97
  "deepseek-v4-flash-260425",
@@ -24,7 +24,7 @@ export const TaskType = {
24
24
  */
25
25
  const TASK_MODEL_MAP = {
26
26
  [TaskType.CHAT]: {
27
- volcengine: "deepseek-v4-1-flash-260910",
27
+ volcengine: "deepseek-v4-1-flash-economy-261017",
28
28
  openai: "gpt-4o-mini",
29
29
  anthropic: "claude-sonnet-4-6",
30
30
  deepseek: "deepseek-chat",
@@ -13581,6 +13581,31 @@ const _CHECKPOINT_READ_ONLY = new Set([
13581
13581
  "search_sessions",
13582
13582
  ]);
13583
13583
 
13584
+ function isCheckpointReadOnly(toolContext, toolName, toolArgs) {
13585
+ if (_CHECKPOINT_READ_ONLY.has(toolName)) return true;
13586
+ if (
13587
+ toolName !== "git" ||
13588
+ toolContext.externalToolExecutors?.git ||
13589
+ !isReadOnlyGitCommand(toolArgs?.command)
13590
+ )
13591
+ return false;
13592
+ const command = normalizeGitCommand(toolArgs.command);
13593
+ if (gitToolInputError(command)) return false;
13594
+ // Read commands can explicitly write output or invoke external drivers.
13595
+ // Keep their recovery snapshot, including abbreviated long options.
13596
+ const args = tokenizeShellWords(command).slice(1);
13597
+ const separator = args.indexOf("--");
13598
+ return !(separator < 0 ? args : args.slice(0, separator)).some((arg) => {
13599
+ const option = arg.split("=", 1)[0];
13600
+ return (
13601
+ option.startsWith("--") &&
13602
+ ["--output", "--ext-diff", "--textconv"].some((flag) =>
13603
+ flag.startsWith(option),
13604
+ )
13605
+ );
13606
+ });
13607
+ }
13608
+
13584
13609
  // Rolling cap on auto-checkpoints per agent session — the engine prunes the
13585
13610
  // oldest beyond this so a long run can't accumulate unbounded refs.
13586
13611
  const MAX_AUTO_CHECKPOINTS_PER_SESSION = 100;
@@ -13603,7 +13628,7 @@ function _loadCheckpointStore() {
13603
13628
  */
13604
13629
  async function _autoCheckpointBeforeTool(toolContext, toolName, toolArgs) {
13605
13630
  if (!toolContext?.autoCheckpoint) return null;
13606
- if (_CHECKPOINT_READ_ONLY.has(toolName)) return null;
13631
+ if (isCheckpointReadOnly(toolContext, toolName, toolArgs)) return null;
13607
13632
  const cwd = toolContext.cwd || process.cwd();
13608
13633
  try {
13609
13634
  const store = await _loadCheckpointStore();
@@ -17279,6 +17304,7 @@ export async function* agentLoop(messages, options) {
17279
17304
  try {
17280
17305
  managedCheckpointHandle = beginManagedToolCheckpoint({
17281
17306
  enabled: toolContext.managedCheckpoint === true,
17307
+ readOnly: isCheckpointReadOnly(toolContext, toolName, toolArgs),
17282
17308
  broker,
17283
17309
  workspaceRoot: toolContext.cwd || process.cwd(),
17284
17310
  stateDir: toolContext.managedCheckpointStateDir || undefined,