0sec-cli 0.22.4 → 0.24.0

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 (208) hide show
  1. package/0.js +73 -68
  2. package/README.md +95 -61
  3. package/chunks/{adapt-loop-3CCOWE43.js → adapt-loop-TEJPXWFG.js} +4 -4
  4. package/chunks/{artifact-scraper-Z4UUIOH3.js → artifact-scraper-AJZ3LOQY.js} +2 -2
  5. package/chunks/{assumption-mining-2UAKQB6V.js → assumption-mining-EATDC4BB.js} +18 -18
  6. package/chunks/backend-connections-QE4NASAK.js +23 -0
  7. package/chunks/chunk-3XLEDCFX.js +566 -0
  8. package/chunks/{chunk-BGX53365.js → chunk-3XLFB46W.js} +5 -3
  9. package/chunks/{chunk-IXAHQICR.js → chunk-4TUR47H5.js} +8 -3
  10. package/chunks/{chunk-5WAJGLCW.js → chunk-4YRXIVPZ.js} +3 -3
  11. package/chunks/{chunk-4ZYYX5GY.js → chunk-52AWIBCT.js} +1 -1
  12. package/chunks/{chunk-TO35Y326.js → chunk-554D4AYM.js} +5 -2
  13. package/chunks/{chunk-GQ3DGHWE.js → chunk-5FHFG5P2.js} +174 -710
  14. package/chunks/chunk-5POT5OYF.js +733 -0
  15. package/chunks/chunk-62PGWN7Y.js +700 -0
  16. package/chunks/{chunk-H6Q2QAIY.js → chunk-A3EKBUEM.js} +1424 -859
  17. package/chunks/{chunk-6WQDXWQC.js → chunk-A6AZZ6XX.js} +2 -2
  18. package/chunks/{chunk-6YZE552K.js → chunk-AV5BF4V7.js} +1281 -2580
  19. package/chunks/{chunk-2WWAPKAW.js → chunk-BIJPMYFA.js} +6 -6
  20. package/chunks/{chunk-SCWWLABR.js → chunk-CIMN2AO6.js} +1 -1
  21. package/chunks/{chunk-H4DH7COV.js → chunk-CSPF47S3.js} +30 -20
  22. package/chunks/{chunk-RCRTSKQN.js → chunk-DNV3ZMPX.js} +1 -1
  23. package/chunks/{chunk-GVY3S5E5.js → chunk-E42XEJTK.js} +2 -2
  24. package/chunks/{chunk-VDOWARMJ.js → chunk-ESM447R6.js} +15 -1
  25. package/chunks/{chunk-WBRGXCU2.js → chunk-EXTN4SQV.js} +1 -1
  26. package/chunks/{chunk-QVIRWJ45.js → chunk-EYBMTELO.js} +108 -24
  27. package/chunks/chunk-FEOPHBMY.js +56 -0
  28. package/chunks/{chunk-IHPTOTLL.js → chunk-FKGFHLLS.js} +1 -1
  29. package/chunks/chunk-G2EJ3R5I.js +5198 -0
  30. package/chunks/chunk-GHEBZKUS.js +5417 -0
  31. package/chunks/chunk-GNR3APR6.js +295 -0
  32. package/chunks/{chunk-ELI3BVIK.js → chunk-H76JYUPE.js} +3 -3
  33. package/chunks/{chunk-E74LXQFY.js → chunk-HRBOZBMC.js} +1 -1
  34. package/chunks/{chunk-TM74SSHC.js → chunk-IIBNQTOK.js} +3 -2
  35. package/chunks/{chunk-UELXHK2Y.js → chunk-IK27KMVV.js} +16 -5
  36. package/chunks/{chunk-WHUAUFSX.js → chunk-J6G73WYF.js} +1 -1
  37. package/chunks/chunk-JSTLXPJS.js +284 -0
  38. package/chunks/{chunk-G2BE2FC7.js → chunk-O3ADFN2A.js} +1 -1
  39. package/chunks/chunk-O7Q2G2KW.js +117 -0
  40. package/chunks/{chunk-XODDLNBI.js → chunk-QEA2VHBD.js} +284 -33
  41. package/chunks/{chunk-C6JPA32H.js → chunk-RBOMXUYL.js} +3 -111
  42. package/chunks/{chunk-L2CCO4KE.js → chunk-RCHAFSWS.js} +838 -39
  43. package/chunks/{chunk-3BPX75OR.js → chunk-RD4FKFWR.js} +1 -1
  44. package/chunks/{chunk-DPUXXMJW.js → chunk-RPTO5FY2.js} +1 -1
  45. package/chunks/{chunk-6KFB6AYN.js → chunk-RZR2XXAK.js} +531 -17
  46. package/chunks/chunk-SGILXLR3.js +289 -0
  47. package/chunks/{chunk-E3OOBVOK.js → chunk-TOAAYJVN.js} +2 -2
  48. package/chunks/chunk-TOFIGQ63.js +83 -0
  49. package/chunks/{chunk-QWK4R3DB.js → chunk-TTDFBFNZ.js} +6 -6
  50. package/chunks/chunk-TZRHWP7R.js +736 -0
  51. package/chunks/chunk-UHUW45S3.js +164 -0
  52. package/chunks/{chunk-5JNTMWPK.js → chunk-V4BD7GSP.js} +2 -2
  53. package/chunks/{chunk-OAS5SAVZ.js → chunk-V5I5GAQH.js} +3226 -1683
  54. package/chunks/{chunk-PS5E7LUQ.js → chunk-W6IYTSZH.js} +79 -9
  55. package/chunks/{chunk-RTBZ36BD.js → chunk-WUPN3D37.js} +22 -248
  56. package/chunks/{chunk-CF3MNS3O.js → chunk-Y7KV7WV6.js} +2 -2
  57. package/chunks/{chunk-2OQOQ2FZ.js → chunk-YERUDEXT.js} +763 -688
  58. package/chunks/{chunk-CPCHLL6A.js → chunk-YJU7QACE.js} +1 -1
  59. package/chunks/{chunk-YED25PA4.js → chunk-YORL5S5V.js} +1 -1
  60. package/chunks/{chunk-YAZARMJY.js → chunk-YYOQADBB.js} +4 -3
  61. package/chunks/chunk-ZPFBQ3SD.js +127 -0
  62. package/chunks/{codex-models-Z43V3427.js → codex-models-FQPCWRPC.js} +7 -7
  63. package/chunks/{commands-EUGF4FUZ.js → commands-I5L3VD2A.js} +6187 -12196
  64. package/chunks/dashboard-B2AEGCFM.js +76 -0
  65. package/chunks/{db-NVAW4WWR.js → db-P5EIKMLP.js} +3 -3
  66. package/chunks/deep-review-I7RD5QSS.js +82 -0
  67. package/chunks/{disclose-LDNKAVRH.js → disclose-PFBWESVJ.js} +4 -2
  68. package/chunks/{dist-7RUOKPRJ.js → dist-3SWWY5FZ.js} +18 -2
  69. package/chunks/{dist-27BNG6WD.js → dist-AJU25UXA.js} +112 -63
  70. package/chunks/{dist-NG2HT5XU.js → dist-VK2M4HNW.js} +85 -1
  71. package/chunks/eval-runner-XVRX3R2Y.js +31 -0
  72. package/chunks/{exploit-agent-FCCR2HYX.js → exploit-agent-A4RTIJ4J.js} +1 -1
  73. package/chunks/{exploit-autoclimb-X5ZS5FAO.js → exploit-autoclimb-ABMMBC3M.js} +1 -1
  74. package/chunks/{exploit-climb-3JHGEO36.js → exploit-climb-BQ2SVU63.js} +2 -2
  75. package/chunks/{fix-NSNPU33B.js → fix-4YCLHFDT.js} +7 -7
  76. package/chunks/{harness-KXQOVIDQ.js → harness-DHWULEIZ.js} +3 -3
  77. package/chunks/{hunt-scan-ELTKGKC4.js → hunt-scan-DXV5H6YN.js} +16 -16
  78. package/chunks/{kernel-primitive-MT7YZSIG.js → kernel-primitive-SF4NALVR.js} +2 -2
  79. package/chunks/{kernel-vm-runner-YFRHYC6G.js → kernel-vm-runner-WEBEZEIC.js} +2 -2
  80. package/chunks/local-engine-XUG7XRKM.js +21 -0
  81. package/chunks/managed-operation-SQFMBWHG.js +60 -0
  82. package/chunks/{memsafety-scan-FCPAXIZE.js → memsafety-scan-L2Z7E7TE.js} +2 -2
  83. package/chunks/{native-loop-OFJDRHPI.js → native-loop-ZNAELJGB.js} +14 -13
  84. package/chunks/orchestrate-YHFJXGID.js +63 -0
  85. package/chunks/{prepare-72GWTRVI.js → prepare-SODWQN6O.js} +5 -5
  86. package/chunks/provider-model-discovery-QGUGL3XW.js +277 -0
  87. package/chunks/remote-workflow-runtime-XNNGI2PG.js +12 -0
  88. package/chunks/{run-WTJCZZHV.js → run-5T4Z3Q2D.js} +924 -327
  89. package/chunks/{runtime-LCJ4XSKE.js → runtime-HFFRUOPL.js} +4 -2
  90. package/chunks/{runtime-FCKOUB7V.js → runtime-MB4GEFBY.js} +7 -7
  91. package/chunks/{scan-stream-GT6GKQ3U.js → scan-stream-GXBJHCDF.js} +3 -2
  92. package/chunks/{scope-E5QZUOOH.js → scope-M7L3CD6X.js} +2 -2
  93. package/chunks/service-plugins-BGS6QKSZ.js +64 -0
  94. package/chunks/{session-store-H3Q7KCYG.js → session-store-K7I4GLNH.js} +2 -2
  95. package/chunks/{variant-candidates-SZKDCOLK.js → variant-candidates-2KSP5EHH.js} +7 -7
  96. package/chunks/{web-recon-prepass-IO3GXQMW.js → web-recon-prepass-RAXXTEWH.js} +5 -5
  97. package/chunks/workflow-runtime-V26HIJO3.js +178 -0
  98. package/dashboard/assets/abnfDiagram-VCTEODGH-CGCueOp5.js +1 -0
  99. package/dashboard/assets/arc-BjZaQcCc.js +1 -0
  100. package/dashboard/assets/architecture-7GRP2DOG-hcbO-9zX.js +1 -0
  101. package/dashboard/assets/architectureDiagram-5GKGNRK7-DReOXTSq.js +36 -0
  102. package/dashboard/assets/array-BifhSqXX.js +1 -0
  103. package/dashboard/assets/blockDiagram-I7D4REHJ-C-byT12_.js +129 -0
  104. package/dashboard/assets/c4Diagram-7LVT6UL2-DoYjz-Uv.js +38 -0
  105. package/dashboard/assets/channel-CUURBnpZ.js +1 -0
  106. package/dashboard/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  107. package/dashboard/assets/chunk-4HAMMTFA-NBNp2zdt.js +62 -0
  108. package/dashboard/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  109. package/dashboard/assets/chunk-75Z2AOVW-BHmkuP0B.js +2 -0
  110. package/dashboard/assets/chunk-DU6HZSFF-DgfLNaL2.js +127 -0
  111. package/dashboard/assets/chunk-F27PBJKO-3wwNFUgZ.js +1 -0
  112. package/dashboard/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  113. package/dashboard/assets/chunk-GMAD6QVW-Btg7huZW.js +72 -0
  114. package/dashboard/assets/chunk-GVQU2GXP-ihCURK5O.js +1 -0
  115. package/dashboard/assets/chunk-IMKFNOWR-FsXj7slg.js +231 -0
  116. package/dashboard/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  117. package/dashboard/assets/chunk-L3NEJ4N5-DorFIxJY.js +1 -0
  118. package/dashboard/assets/chunk-OSK3NFVY-DKun_KfC.js +10 -0
  119. package/dashboard/assets/chunk-P2QGCYS3-XGgiU1Bz.js +1 -0
  120. package/dashboard/assets/chunk-POPQ4Y6H-BTXEnGhJ.js +1 -0
  121. package/dashboard/assets/chunk-PWAF6VOD-DYZcGkTL.js +1 -0
  122. package/dashboard/assets/chunk-SHT3W25Y-C4WQfwf8.js +168 -0
  123. package/dashboard/assets/chunk-SVP7TREG-C4nCh0-1.js +88 -0
  124. package/dashboard/assets/chunk-TICWLB2K-DSB-IiGc.js +206 -0
  125. package/dashboard/assets/chunk-XXDRQBXY-CS6fjUcj.js +1 -0
  126. package/dashboard/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  127. package/dashboard/assets/classDiagram-ZZMXUADV-CD1Buc26.js +1 -0
  128. package/dashboard/assets/classDiagram-v2-VYDZK3BY-CD1Buc26.js +1 -0
  129. package/dashboard/assets/common-BMdQBwfR.js +5 -0
  130. package/dashboard/assets/cose-bilkent-JH36ORCC-CUjQHTML.js +1 -0
  131. package/dashboard/assets/cynefin-OW5HDTMX-BC7zCtFq.js +1 -0
  132. package/dashboard/assets/cynefinDiagram-5FMLGOSQ-CgDOOY67.js +62 -0
  133. package/dashboard/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  134. package/dashboard/assets/dagre-GXQ25YYZ-Dqc8FS9x.js +4 -0
  135. package/dashboard/assets/dagre-PrKaheQc.js +1 -0
  136. package/dashboard/assets/defaultLocale-BFoDCU3G.js +1 -0
  137. package/dashboard/assets/diagram-S7CK7UJ4-CrKqRXZb.js +30 -0
  138. package/dashboard/assets/diagram-UQ7AKVKN-Cu6Es0-v.js +41 -0
  139. package/dashboard/assets/diagram-VSXAHHWV-eK4d8FwS.js +3 -0
  140. package/dashboard/assets/diagram-VX7I27RA-bFxeFKOc.js +24 -0
  141. package/dashboard/assets/diagram-Z3DM3KII-C0ClmnhC.js +24 -0
  142. package/dashboard/assets/dist-BZh8Kb3O.js +1 -0
  143. package/dashboard/assets/ebnfDiagram-PWID7BFC-CUqxFPzf.js +1 -0
  144. package/dashboard/assets/erDiagram-RLTQ6QDP-CcYM7pLi.js +99 -0
  145. package/dashboard/assets/eventmodeling-NTZA5JFV-D8ZNnPkV.js +1 -0
  146. package/dashboard/assets/flowDiagram-HODETNUW-pDb1AYm8.js +1 -0
  147. package/dashboard/assets/ganttDiagram-EL5Y4UJY-UmZfbMyD.js +292 -0
  148. package/dashboard/assets/gitGraph-4MIJSDKK-mvNUo0ZA.js +1 -0
  149. package/dashboard/assets/gitGraphDiagram-WWUBYQGX-CvzeCxVy.js +106 -0
  150. package/dashboard/assets/graphlib-DS17s2tU.js +1 -0
  151. package/dashboard/assets/info-A6RAGUB7-DChKqZMi.js +1 -0
  152. package/dashboard/assets/infoDiagram-27XIBGKW-DjkpNtVW.js +2 -0
  153. package/dashboard/assets/init-C-OQMol4.js +1 -0
  154. package/dashboard/assets/ishikawaDiagram-5VMMS53U-8FhjJaWT.js +70 -0
  155. package/dashboard/assets/journeyDiagram-3NMN7TZE-DyNJ755f.js +139 -0
  156. package/dashboard/assets/kanban-definition-UXKFOSKX-_jCmtaY1.js +89 -0
  157. package/dashboard/assets/katex-BdBmVSus.js +257 -0
  158. package/dashboard/assets/line-Bf0nxyWf.js +1 -0
  159. package/dashboard/assets/linear-Bl6JKbf4.js +1 -0
  160. package/dashboard/assets/mermaid-parser.core-Cc6sgCzs.js +7 -0
  161. package/dashboard/assets/mermaid.core-B4yCwiN-.js +44 -0
  162. package/dashboard/assets/mindmap-definition-YA3MSWOX-D5DjWyXj.js +96 -0
  163. package/dashboard/assets/operations-B7JAWOi6.js +130 -0
  164. package/dashboard/assets/operations-QjKT0Hwi.css +1 -0
  165. package/dashboard/assets/ordinal-BDEzSJ7C.js +1 -0
  166. package/dashboard/assets/packet-AYTQ26CC-bQXLDhQC.js +1 -0
  167. package/dashboard/assets/path-fybaL0A-.js +1 -0
  168. package/dashboard/assets/pegDiagram-XKGWAZYB-Bf6a1vaf.js +1 -0
  169. package/dashboard/assets/pie-WAS4IAKB-DfzoABIi.js +1 -0
  170. package/dashboard/assets/pieDiagram-E7YTZNPT-D0L1qbch.js +39 -0
  171. package/dashboard/assets/quadrantDiagram-AXDQQJYC-CbFyy2Pe.js +7 -0
  172. package/dashboard/assets/radar-RG4KPBEZ-CZ2pyeUT.js +1 -0
  173. package/dashboard/assets/railroad-74A4TZTK-CP4Jazfd.js +1 -0
  174. package/dashboard/assets/railroad-abnf-HS5TGJTU-3MvEiHwD.js +1 -0
  175. package/dashboard/assets/railroad-ebnf-LZEXJU2U-BWto6cXE.js +1 -0
  176. package/dashboard/assets/railroad-peg-WCYAUIDC-DasEjbyf.js +1 -0
  177. package/dashboard/assets/railroadDiagram-O6MQD6OU-t7Gp9g2R.js +1 -0
  178. package/dashboard/assets/requirementDiagram-BXWQKSXE-LYmqeBXi.js +84 -0
  179. package/dashboard/assets/rough.esm-Dy-Kn_BL.js +1 -0
  180. package/dashboard/assets/sankeyDiagram-P5KCCOFB-DnpfA_94.js +40 -0
  181. package/dashboard/assets/sequenceDiagram-WJ2MYXX4-C8s3pTUE.js +162 -0
  182. package/dashboard/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  183. package/dashboard/assets/src-CaNUT1AQ.js +1 -0
  184. package/dashboard/assets/stateDiagram-D77RDMKH-BMzm6fK1.js +1 -0
  185. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-B3REMjpY.js +1 -0
  186. package/dashboard/assets/swimlanes-42K2YHIH-uJE05Tt_.js +1 -0
  187. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-CIaVMZEy.js +8 -0
  188. package/dashboard/assets/timeline-definition-24CTP7MA-BfLJMVeG.js +120 -0
  189. package/dashboard/assets/treeView-Q6P3EWNA-ZOE2enu2.js +1 -0
  190. package/dashboard/assets/treemap-WGGIJYW6-yIZoPBF5.js +1 -0
  191. package/dashboard/assets/vennDiagram-4TSXK5OY-BYJRHEaL.js +34 -0
  192. package/dashboard/assets/wardley-WFR3VGLG-D5V-jLbB.js +1 -0
  193. package/dashboard/assets/wardleyDiagram-VM6X3IG4-DgPN4nSe.js +78 -0
  194. package/dashboard/assets/xychartDiagram-S5SC5T6Z-BhkAMAOT.js +7 -0
  195. package/dashboard/index.html +3 -3
  196. package/package.json +3 -2
  197. package/worker-assets/demo-target/README.md +15 -0
  198. package/worker-assets/demo-target/include/decoder.h +27 -0
  199. package/worker-assets/demo-target/patched-decoder.c +40 -0
  200. package/worker-assets/demo-target/src/decoder.c +50 -0
  201. package/worker-assets/demo-target/witness-65537x1.bin +0 -0
  202. package/chunks/chunk-FFHRANYC.js +0 -547
  203. package/chunks/eval-runner-6Q3H52SP.js +0 -30
  204. package/chunks/orchestrate-DRZ2SVCP.js +0 -62
  205. package/chunks/service-plugins-MSK2EQP6.js +0 -62
  206. package/dashboard/assets/operations-BvB5Qpmk.css +0 -1
  207. package/dashboard/assets/operations-D8Ii01SV.js +0 -114
  208. package/dashboard/assets/zero-peek-Dzm3MT3X.png +0 -0
@@ -2,14 +2,18 @@
2
2
  import { createRequire as __0CreateRequire } from "node:module";
3
3
  const require = __0CreateRequire(import.meta.url);
4
4
  import {
5
+ DEFAULT_MAX_TOOL_ITERATIONS,
5
6
  createConsoleRuntime,
6
7
  createWorkbenchProviderBroker,
7
8
  runSmolvmWorkbench,
8
9
  snapshotSmolvmWorkspace
9
- } from "./chunk-OAS5SAVZ.js";
10
+ } from "./chunk-V5I5GAQH.js";
11
+ import {
12
+ getReleaseChannel
13
+ } from "./chunk-4TUR47H5.js";
10
14
  import {
11
15
  TOOL_DEFINITIONS
12
- } from "./chunk-H6Q2QAIY.js";
16
+ } from "./chunk-A3EKBUEM.js";
13
17
  import {
14
18
  ANALYTICS_LEVEL_ENV,
15
19
  getSmolvmWorkbenchStatus,
@@ -17,7 +21,7 @@ import {
17
21
  levelAtLeast,
18
22
  loadCloudCredentials,
19
23
  resolveAnalyticsLevel
20
- } from "./chunk-2WWAPKAW.js";
24
+ } from "./chunk-BIJPMYFA.js";
21
25
  import {
22
26
  ScopePolicy,
23
27
  aggregateCapabilities,
@@ -30,17 +34,69 @@ import {
30
34
  readInstalledPlugin,
31
35
  reconcile,
32
36
  writeEnablement
33
- } from "./chunk-C6JPA32H.js";
37
+ } from "./chunk-RBOMXUYL.js";
34
38
  import {
39
+ BackendIdSchema,
35
40
  DEFAULT_ALLOW_MODEL_SELF_EXTENSION,
36
41
  SERVICE_PLUGIN_CATALOG,
37
42
  VERSION,
38
43
  findingSchema,
39
44
  homeStateDir
40
- } from "./chunk-6KFB6AYN.js";
45
+ } from "./chunk-RZR2XXAK.js";
46
+
47
+ // packages/cli/src/backend-client-mode.ts
48
+ function remoteBackendClientId(args) {
49
+ if (!["workflow", "runs", "sessions", "mcp-server"].includes(args[0] ?? "")) return void 0;
50
+ const engineUrls = [];
51
+ const tokenEnvs = [];
52
+ const selections = [];
53
+ const valueFlags = /* @__PURE__ */ new Set(["--template", "--revision", "--target", "--workspace", "--scope", "--model", "--inputs", "--time-cap", "--cost-cap", "--db-path", "--format", "--backends-config", "--tools", "--scan-id", "--timeout", "--rate-limit", "--engagement-profile", "--session", "--config", "--response", "--after", "--branch-from-entry"]);
54
+ for (let index = 1; index < args.length; index++) {
55
+ const argument = args[index];
56
+ if (argument === "--") break;
57
+ if (argument === "--engine-url") {
58
+ engineUrls.push(args[++index]);
59
+ continue;
60
+ }
61
+ if (argument.startsWith("--engine-url=")) {
62
+ engineUrls.push(argument.slice(13));
63
+ continue;
64
+ }
65
+ if (argument === "--engine-token-env") {
66
+ tokenEnvs.push(args[++index]);
67
+ continue;
68
+ }
69
+ if (argument.startsWith("--engine-token-env=")) {
70
+ tokenEnvs.push(argument.slice(19));
71
+ continue;
72
+ }
73
+ if (argument === "--backend") {
74
+ selections.push(args[++index]);
75
+ continue;
76
+ }
77
+ if (argument.startsWith("--backend=")) {
78
+ selections.push(argument.slice(10));
79
+ continue;
80
+ }
81
+ if (valueFlags.has(argument)) index++;
82
+ }
83
+ if (engineUrls.length || tokenEnvs.length) {
84
+ if (selections.length || engineUrls.length !== 1 || tokenEnvs.length !== 1) throw new Error("Select either one --backend or one --engine-url with --engine-token-env.");
85
+ if (!engineUrls[0] || engineUrls[0].length > 4096 || !tokenEnvs[0] || !/^[A-Za-z_][A-Za-z0-9_]{0,127}$/.test(tokenEnvs[0])) throw new Error("Invalid direct engine attachment options.");
86
+ const url = new URL(engineUrls[0]);
87
+ const loopback = url.hostname === "localhost" || url.hostname === "[::1]" || /^127\.(?:\d{1,3}\.){2}\d{1,3}$/.test(url.hostname);
88
+ if (url.username || url.password || url.search || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) throw new Error("Engine URL must be credential-free HTTPS or loopback HTTP, without query or fragment.");
89
+ return "attached-engine";
90
+ }
91
+ if (!selections.length) return void 0;
92
+ if (selections.length !== 1) throw new Error("Select exactly one registered remote backend.");
93
+ const selected = BackendIdSchema.parse(selections[0]);
94
+ if (selected === "local") throw new Error("--backend local is not a remote selection. Omit --backend to preserve configured local execution.");
95
+ return selected;
96
+ }
41
97
 
42
98
  // packages/cli/src/workbench.ts
43
- import { chmodSync, existsSync as existsSync2, lstatSync as lstatSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync3, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
99
+ import { chmodSync, existsSync as existsSync2, lstatSync as lstatSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync4, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
44
100
  import { homedir as homedir2 } from "node:os";
45
101
  import { dirname as dirname5, isAbsolute as isAbsolute2, join as join8 } from "node:path";
46
102
 
@@ -48,7 +104,7 @@ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join8 } from "n
48
104
  import { existsSync, lstatSync, realpathSync } from "node:fs";
49
105
  import { dirname, join } from "node:path";
50
106
  import { fileURLToPath } from "node:url";
51
- function currentWorkbenchAssets(moduleUrl = import.meta.url) {
107
+ function currentWorkbenchAssets(moduleUrl = import.meta.url, executablePath = process.execPath) {
52
108
  let directory = dirname(fileURLToPath(moduleUrl));
53
109
  for (let depth = 0; depth < 5; depth++) {
54
110
  for (const candidate of [directory, join(directory, "dist")]) {
@@ -59,13 +115,67 @@ function currentWorkbenchAssets(moduleUrl = import.meta.url) {
59
115
  if (parent === directory) break;
60
116
  directory = parent;
61
117
  }
118
+ if (moduleUrl.includes("/$bunfs/")) {
119
+ const candidate = join(dirname(executablePath), "..", "lib", "workbench-cli");
120
+ const entry = join(candidate, "0.js");
121
+ if (existsSync(entry) && lstatSync(entry).isFile() && !lstatSync(entry).isSymbolicLink()) return { cliDist: realpathSync(candidate) };
122
+ }
62
123
  throw new Error("Current workbench CLI distribution is unavailable. Build/install the current CLI bundle before isolated execution; an older image CLI is not used.");
63
124
  }
64
125
 
65
126
  // packages/cli/src/workbench-console-protocol.ts
66
127
  import { isAbsolute, relative, resolve, sep } from "node:path";
128
+ import { createHash } from "node:crypto";
129
+ import { constants, openSync, closeSync, fstatSync, lstatSync as lstatSync2, readSync, realpathSync as realpathSync2 } from "node:fs";
67
130
  var WORKBENCH_FRAME_BYTES = 8 * 1024 * 1024;
68
131
  var WORKBENCH_MAX_PENDING = 64;
132
+ var WORKBENCH_SOURCE_CONTEXT_LIMIT = 8;
133
+ function validateWorkbenchSourceLesson(value, workspace, scopePath) {
134
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid source lesson");
135
+ const record = value;
136
+ if (Object.keys(record).some((key) => !["title", "summary", "sourceLinks"].includes(key))) throw new Error("Unexpected source lesson fields");
137
+ const { title, summary } = record;
138
+ if (typeof title !== "string" || !title.trim() || title.length > 200 || typeof summary !== "string" || !summary.trim() || summary.length > 2e3) throw new Error("Invalid source lesson prose");
139
+ const text = title + "\n" + summary;
140
+ if (/[\u0000-\u0008\u000b\u000c\u000e-\u001f]/.test(text) || /-----BEGIN .*PRIVATE KEY-----|\b(?:sk-[a-zA-Z0-9_-]{16,}|ghp_[a-zA-Z0-9]{20,}|github_pat_[a-zA-Z0-9_]{20,}|Bearer\s+[a-zA-Z0-9_.-]{16,})|(?:password|api[_ -]?key|access[_ -]?token|secret)\s*[:=]\s*["']?[^\s"']{8,}/i.test(text)) throw new Error("Source lesson may contain credentials");
141
+ if (Array.isArray(record.sourceLinks) && record.sourceLinks.some((link) => !link || typeof link !== "object" || Object.keys(link).some((key) => !["path", "hash"].includes(key)))) throw new Error("Unexpected source lesson link fields");
142
+ return { title: title.trim(), summary: summary.trim(), ...validateWorkbenchSourceContext(record, workspace, scopePath) };
143
+ }
144
+ function validateWorkbenchSourceContext(value, workspace, scopePath) {
145
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid workbench source context");
146
+ const links = value.sourceLinks;
147
+ if (!Array.isArray(links) || !links.length || links.length > 16) throw new Error("Invalid workbench source links");
148
+ const root = realpathSync2(workspace);
149
+ const scope = realpathSync2(scopePath);
150
+ if (scope !== root && !scope.startsWith(root + sep)) throw new Error("Workbench source scope is outside workspace");
151
+ const sourceLinks = links.map((link) => {
152
+ if (!link || typeof link !== "object" || Array.isArray(link)) throw new Error("Invalid workbench source link");
153
+ const { path, hash } = link;
154
+ if (typeof path !== "string" || !path || path.length > 1024 || path.includes("\0") || path.includes("\\") || isAbsolute(path) || path.split("/").some((part) => !part || part === "." || part === "..") || typeof hash !== "string" || !/^sha256:[a-f0-9]{64}$/.test(hash)) throw new Error("Invalid workbench source path or hash");
155
+ const full = resolve(root, path);
156
+ if (full !== scope && !full.startsWith(scope + sep)) throw new Error("Workbench source is outside approved local scope");
157
+ let cursor = root;
158
+ for (const component of path.split("/")) {
159
+ cursor = resolve(cursor, component);
160
+ if (lstatSync2(cursor).isSymbolicLink()) throw new Error("Workbench source symlink refused");
161
+ }
162
+ const fd = openSync(full, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
163
+ try {
164
+ const stat = fstatSync(fd);
165
+ if (!stat.isFile() || stat.nlink !== 1 || stat.size > 1048576) throw new Error("Invalid workbench source file");
166
+ const bytes = Buffer.alloc(1048577);
167
+ let size = 0;
168
+ let read;
169
+ while (size < bytes.length && (read = readSync(fd, bytes, size, bytes.length - size, size)) > 0) size += read;
170
+ const after = fstatSync(fd);
171
+ if (size > 1048576 || stat.size !== size || stat.size !== after.size || stat.mtimeMs !== after.mtimeMs || stat.ctimeMs !== after.ctimeMs || realpathSync2(full) !== full || `sha256:${createHash("sha256").update(bytes.subarray(0, size)).digest("hex")}` !== hash) throw new Error("Workbench source changed or digest mismatch");
172
+ } finally {
173
+ closeSync(fd);
174
+ }
175
+ return { path, hash };
176
+ });
177
+ return { sourceLinks };
178
+ }
69
179
  function encodeWorkbenchFrame(frame) {
70
180
  const encoded = JSON.stringify(frame);
71
181
  if (Buffer.byteLength(encoded) > WORKBENCH_FRAME_BYTES) throw new Error("Workbench protocol frame exceeds its byte limit");
@@ -137,7 +247,7 @@ function serializeWorkbenchConfig(config, workspace) {
137
247
  if (config[key] !== void 0) throw new Error(`Host ${key} cannot execute through the workbench controller`);
138
248
  }
139
249
  const result = { workspaceRoot: "/workspace", target: mapWorkbenchTarget(config.target ?? "", workspace) };
140
- for (const key of ["role", "tools", "scanId", "maxToolIterations", "allowScanners", "systemPrompt", "autonomyMode", "refineObjective", "allowModelSelfExtension", "costModel", "contextWindowTokens", "compaction", "initialMessages"]) {
250
+ for (const key of ["role", "tools", "codebaseLearning", "scanId", "maxToolIterations", "allowScanners", "systemPrompt", "autonomyMode", "refineObjective", "allowModelSelfExtension", "costModel", "contextWindowTokens", "compaction", "initialMessages"]) {
141
251
  if (config[key] !== void 0) result[key] = structuredClone(config[key]);
142
252
  }
143
253
  if (config.maxTurnTokens !== void 0 && Number.isFinite(config.maxTurnTokens)) result.maxTurnTokens = config.maxTurnTokens;
@@ -161,7 +271,7 @@ function serializeWorkbenchConfig(config, workspace) {
161
271
  }
162
272
  function mapWorkbenchCliArguments(args, workspace) {
163
273
  const targetFlags = /* @__PURE__ */ new Set(["--target", "-t", "--repo"]);
164
- const pathFlags = /* @__PURE__ */ new Set(["--scope", "--db-path", "--workspace", "--workspace-root", "--cwd", "--output", "-o", "--config"]);
274
+ const pathFlags = /* @__PURE__ */ new Set(["--scope", "--db-path", "--workspace", "--workspace-root", "--cwd", "--output", "-o", "--config", "--inputs"]);
165
275
  const result = [...args];
166
276
  for (let index = 0; index < result.length; index++) {
167
277
  const argument = result[index];
@@ -180,9 +290,9 @@ function mapWorkbenchCliArguments(args, workspace) {
180
290
 
181
291
  // packages/cli/src/workbench-console-session.ts
182
292
  import { randomUUID } from "node:crypto";
183
- import { realpathSync as realpathSync2 } from "node:fs";
293
+ import { realpathSync as realpathSync3, statSync } from "node:fs";
184
294
  import { mkdir, mkdtemp as mkdtemp2, realpath as realpath2 } from "node:fs/promises";
185
- import { join as join3 } from "node:path";
295
+ import { join as join3, sep as sep2 } from "node:path";
186
296
 
187
297
  // packages/cli/src/workbench-plugins.ts
188
298
  import { lstat, mkdtemp, realpath, rm } from "node:fs/promises";
@@ -278,7 +388,7 @@ function servicePluginSecretRedactor(connections) {
278
388
 
279
389
  // packages/cli/src/workbench-console-session.ts
280
390
  var EVENTS = /* @__PURE__ */ new Set(["onHarnessUpdate", "onAssistantDelta", "onReasoningDelta", "onToolStart", "onToolResult", "onUsage", "onNotice", "onCompaction"]);
281
- var DECISIONS = /* @__PURE__ */ new Set(["requestScope", "requestLocalScope", "approveTool", "escalateScopedAudit", "askOperator", "historyList", "historyRead"]);
391
+ var DECISIONS = /* @__PURE__ */ new Set(["requestScope", "requestLocalScope", "approveTool", "escalateScopedAudit", "askOperator", "historyList", "historyRead", "sourceLessons"]);
282
392
  function validateOptions(options) {
283
393
  if (options.provider.provider !== "chatgpt-codex" || options.selection.provider && options.selection.provider !== "chatgpt-codex" || !options.provider.models.includes(options.selection.model)) throw new Error("Workbench requires an explicit host provider/model grant");
284
394
  for (const model of Object.values(options.selection.agentModels ?? {})) if (model !== "auto" && !options.provider.models.includes(model)) throw new Error("Workbench worker model is outside the host provider grant");
@@ -298,7 +408,7 @@ var Controller = class {
298
408
  this.init = init;
299
409
  this.cli = cli;
300
410
  validateOptions(options);
301
- this.workspace = realpathSync2(options.workbench.workspaceRoot ?? process.cwd());
411
+ this.workspace = realpathSync3(options.workbench.workspaceRoot ?? process.cwd());
302
412
  this.execution = { backend: "smolvm", status: "pending", runId: this.runId, workspacePath: this.workspace, guestWorkspacePath: "/workspace", imageDigest: options.workbench.imageDigest, cpus: options.workbench.cpus, memoryMb: options.workbench.memoryMb };
303
413
  this.ready = new Promise((resolve2, reject) => {
304
414
  this.resolveReady = resolve2;
@@ -349,7 +459,7 @@ var Controller = class {
349
459
  async start() {
350
460
  if (this.started) return this.ready;
351
461
  this.started = true;
352
- this.status("pending", "Starting isolated workbench");
462
+ this.status("pending", "Preparing workspace");
353
463
  let stagedPlugins;
354
464
  this.lifetime = setTimeout(() => this.abort.abort(new Error("Workbench lifetime expired")), this.options.lifetimeMs ?? 30 * 6e4);
355
465
  this.lifetime.unref();
@@ -359,7 +469,7 @@ var Controller = class {
359
469
  const artifacts = this.options.artifactDirectory ?? await realpath2(await mkdtemp2(join3(root, "run-")));
360
470
  const reader = new WorkbenchFrameReader();
361
471
  const launch = guestCommand(this.options, this.cli);
362
- const connections = this.cli ? [] : (await import("./service-plugins-MSK2EQP6.js")).loadServicePluginConnections(this.options.pluginHomeDir).filter((item) => item.enabled);
472
+ const connections = this.cli ? [] : (await import("./service-plugins-BGS6QKSZ.js")).loadServicePluginConnections(this.options.pluginHomeDir).filter((item) => item.enabled);
363
473
  const servicePluginConnections = validateGuestServicePluginConnections(connections, this.options.network);
364
474
  this.redact = servicePluginSecretRedactor(servicePluginConnections);
365
475
  const plugins = stagedPlugins = await prepareWorkbenchPlugins(this.workspace, this.options.pluginHomeDir);
@@ -367,6 +477,7 @@ var Controller = class {
367
477
  image: this.options.workbench.image,
368
478
  stateRoot: this.options.workbench.stateRoot,
369
479
  workspaceRoot: this.workspace,
480
+ onStartupProgress: (message) => this.status("pending", message),
370
481
  command: launch.command,
371
482
  environment: { ZERO_PROVIDER: "chatgpt-codex", ZERO_NO_TELEMETRY: "1", DO_NOT_TRACK: "1" },
372
483
  network: this.options.network,
@@ -504,18 +615,25 @@ var Controller = class {
504
615
  }
505
616
  return result;
506
617
  }
507
- async close() {
618
+ async close(beforeRelease) {
508
619
  if (!this.started) {
509
620
  await this.options.provider.close?.();
510
621
  return;
511
622
  }
512
623
  let exited = false;
513
624
  try {
514
- await Promise.race([this.request("close"), new Promise((resolve2) => setTimeout(resolve2, 1e3))]);
625
+ await Promise.race([this.request("close"), new Promise((_, reject) => setTimeout(() => reject(new Error("Workbench close acknowledgement timed out")), 1e3))]);
626
+ await beforeRelease?.();
627
+ this.write({ type: "release" });
628
+ this.input?.end();
515
629
  await Promise.race([this.done?.then(() => {
516
630
  exited = true;
517
631
  }), new Promise((resolve2) => setTimeout(resolve2, 1e3))]);
518
- } catch {
632
+ } catch (error) {
633
+ this.abort.abort();
634
+ const result = await this.done;
635
+ if (result?.cleanupFailed) throw new Error(result.error ?? "Workbench teardown could not be confirmed");
636
+ if (beforeRelease) await beforeRelease();
519
637
  } finally {
520
638
  if (!exited) this.abort.abort();
521
639
  const result = await this.done;
@@ -524,17 +642,42 @@ var Controller = class {
524
642
  }
525
643
  };
526
644
  function createWorkbenchConsoleSession(options) {
527
- const workspace = realpathSync2(options.workbench.workspaceRoot ?? options.config.workspaceRoot ?? process.cwd());
645
+ const workspace = realpathSync3(options.workbench.workspaceRoot ?? options.config.workspaceRoot ?? process.cwd());
528
646
  const config = { ...options.config, scanId: options.config.scanId ?? `console-${randomUUID()}` };
529
647
  const serial = serializeWorkbenchConfig(config, workspace);
530
648
  const callbacks = [...DECISIONS].filter((name) => name === "historyList" || name === "historyRead" ? !!config.conversationHistory : typeof config[name] === "function");
531
- const scopeEnforcement = getScopeEnforcementState(workspace);
649
+ const sourceLearningEnabled = config.codebaseLearning === true && config.role !== "verify" && !/^(1|true)$/i.test(process.env.ZERO_DISABLE_HUNT_MEMORY ?? "");
650
+ if (sourceLearningEnabled && options.readSourceLessons) callbacks.push("sourceLessons");
651
+ const scopeEnforcement = getScopeEnforcementState(workspace, options.pluginHomeDir);
532
652
  const controller = new Controller({ ...options, workbench: { ...options.workbench, workspaceRoot: workspace } }, { config: serial, callbacks, scopeEnforcement }, false);
533
653
  let messages = structuredClone(config.initialMessages ?? config.initialCheckpoint?.messages ?? []);
534
654
  let checkpoint = config.initialCheckpoint;
535
655
  let target = config.target ?? "";
536
656
  let scope = config.scope;
537
657
  let localScopePath = config.initialCheckpoint?.localScopePath ?? void 0;
658
+ let explicitYoloSourceGrant = !!options.workbench.workspaceRoot && config.autonomyMode === "yolo";
659
+ let sourceScopePath = config.initialCheckpoint?.localScopePath ?? (!scopeEnforcement.enabled || explicitYoloSourceGrant ? workspace : void 0);
660
+ const authorizedSourceRoot = (guestPath) => {
661
+ if (!sourceScopePath || typeof guestPath !== "string") return void 0;
662
+ try {
663
+ const requested = realpathSync3(hostWorkspacePath(guestPath, workspace));
664
+ const approved = realpathSync3(sourceScopePath);
665
+ if (!statSync(requested).isDirectory()) return void 0;
666
+ if (requested === approved || explicitYoloSourceGrant && (requested === workspace || requested.startsWith(workspace + sep2))) return requested;
667
+ } catch {
668
+ }
669
+ return void 0;
670
+ };
671
+ const sourceArtifacts = /* @__PURE__ */ new Set();
672
+ let sourceFrames = 0;
673
+ let sourcePersistence = Promise.resolve();
674
+ const flushSourceContext = async () => {
675
+ try {
676
+ await sourcePersistence;
677
+ } catch {
678
+ throw new Error("Workbench source context persistence failed");
679
+ }
680
+ };
538
681
  let autonomyMode = config.autonomyMode ?? "standard";
539
682
  let systemPrompt = config.systemPrompt ?? "";
540
683
  let tools = config.tools ?? [];
@@ -556,6 +699,20 @@ function createWorkbenchConsoleSession(options) {
556
699
  });
557
700
  };
558
701
  controller.decision = async (name, args) => {
702
+ if (name === "sourceLessons") {
703
+ if (!sourceLearningEnabled || !sourceScopePath || !options.readSourceLessons || /^(1|true)$/i.test(process.env.ZERO_DISABLE_HUNT_MEMORY ?? "") || args.length !== 1 || typeof args[0] !== "string") return [];
704
+ const requested = authorizedSourceRoot(args[0]);
705
+ if (!requested) return [];
706
+ await flushSourceContext();
707
+ const notes = await options.readSourceLessons({ workspaceRoot: workspace, scopePath: requested });
708
+ return notes.slice(0, 6).flatMap((note) => {
709
+ try {
710
+ return [validateWorkbenchSourceLesson(note, workspace, requested)];
711
+ } catch {
712
+ return [];
713
+ }
714
+ });
715
+ }
559
716
  if (name === "historyList") return config.conversationHistory.list(...args);
560
717
  if (name === "historyRead") return config.conversationHistory.read(...args);
561
718
  const callback = config[name];
@@ -566,7 +723,9 @@ function createWorkbenchConsoleSession(options) {
566
723
  const value = await callback(request);
567
724
  if (!value) return null;
568
725
  const resolution = value;
569
- return { scopePath: guestWorkspacePath(resolution.scopePath, workspace) };
726
+ const guestPath = guestWorkspacePath(resolution.scopePath, workspace);
727
+ sourceScopePath = hostWorkspacePath(guestPath, workspace);
728
+ return { scopePath: guestPath };
570
729
  }
571
730
  if (name === "requestScope") {
572
731
  const request = args[0];
@@ -578,7 +737,40 @@ function createWorkbenchConsoleSession(options) {
578
737
  return callback(...args);
579
738
  };
580
739
  controller.receive = (frame) => {
581
- if (frame.type === "state") {
740
+ if (frame.type === "source-lesson") {
741
+ if (++sourceFrames > 128) throw new Error("Workbench source export limit reached");
742
+ if (!sourceLearningEnabled || !options.onSourceLesson || !sourceScopePath || /^(1|true)$/i.test(process.env.ZERO_DISABLE_HUNT_MEMORY ?? "")) return;
743
+ const lessonScope = frame.scopePath === void 0 ? sourceScopePath : authorizedSourceRoot(frame.scopePath);
744
+ if (!lessonScope) return;
745
+ let lesson;
746
+ try {
747
+ lesson = validateWorkbenchSourceLesson(frame.lesson, workspace, lessonScope);
748
+ } catch {
749
+ return;
750
+ }
751
+ const key = JSON.stringify({ scopePath: lessonScope, lesson });
752
+ if (sourceArtifacts.has(key)) return;
753
+ sourceArtifacts.add(key);
754
+ const scopePath = lessonScope;
755
+ sourcePersistence = sourcePersistence.then(() => options.onSourceLesson(lesson, { workspaceRoot: workspace, scopePath, scanId: config.scanId, runId: controller.runId }));
756
+ void sourcePersistence.catch(() => {
757
+ });
758
+ } else if (frame.type === "source-context") {
759
+ if (++sourceFrames > 128) throw new Error("Workbench source context export limit reached");
760
+ if (!sourceLearningEnabled || !options.onSourceContext || !sourceScopePath || /^(1|true)$/i.test(process.env.ZERO_DISABLE_HUNT_MEMORY ?? "")) return;
761
+ let artifact;
762
+ try {
763
+ artifact = validateWorkbenchSourceContext(frame.artifact, workspace, sourceScopePath);
764
+ } catch {
765
+ return;
766
+ }
767
+ const key = JSON.stringify(artifact);
768
+ if (sourceArtifacts.has(key)) return;
769
+ sourceArtifacts.add(key);
770
+ sourcePersistence = sourcePersistence.then(() => options.onSourceContext(artifact, { workspaceRoot: workspace, scanId: config.scanId, runId: controller.runId }));
771
+ void sourcePersistence.catch(() => {
772
+ });
773
+ } else if (frame.type === "state") {
582
774
  const state = frame.snapshot;
583
775
  if (!state || state.scanId !== config.scanId || !Array.isArray(state.messages) || state.messages.length > 1e4 || !Array.isArray(state.tools)) throw new Error("Invalid guest session state");
584
776
  messages = state.messages;
@@ -628,6 +820,10 @@ function createWorkbenchConsoleSession(options) {
628
820
  scopeEnforcement,
629
821
  setAutonomyMode(mode) {
630
822
  autonomyMode = mode;
823
+ if (mode === "yolo" && options.workbench.workspaceRoot) {
824
+ explicitYoloSourceGrant = true;
825
+ sourceScopePath ??= workspace;
826
+ }
631
827
  queue("autonomy", mode);
632
828
  },
633
829
  configureEngagement(selection) {
@@ -638,7 +834,7 @@ function createWorkbenchConsoleSession(options) {
638
834
  else queue("configure", value);
639
835
  },
640
836
  configureWorkspace(path) {
641
- if (realpathSync2(path) !== workspace) throw new Error("The SmolVM workspace grant is fixed for this chat; start a new chat to change it");
837
+ if (realpathSync3(path) !== workspace) throw new Error("The SmolVM workspace grant is fixed for this chat; start a new chat to change it");
642
838
  },
643
839
  reconfigureRuntime(selection) {
644
840
  if (selection.env !== void 0 || selection.provider && selection.provider !== "chatgpt-codex" || selection.model && !options.provider.models.includes(selection.model) || Object.values(selection.agentModels ?? {}).some((model) => model !== "auto" && !options.provider.models.includes(model))) throw new Error("Runtime selection is outside workbench provider grant");
@@ -656,24 +852,62 @@ function createWorkbenchConsoleSession(options) {
656
852
  async send(text, callbacks2, sendOptions) {
657
853
  if (active) throw new Error("Workbench turn already active");
658
854
  active = true;
659
- render = callbacks2;
855
+ let partialText = "";
856
+ const partialTools = [];
857
+ const partialUsage = { inputTokens: 0, outputTokens: 0 };
858
+ let usageReport;
859
+ render = {
860
+ ...callbacks2,
861
+ onAssistantDelta: (text2) => {
862
+ partialText += text2;
863
+ callbacks2?.onAssistantDelta?.(text2);
864
+ },
865
+ onToolResult: (call, result) => {
866
+ partialTools.push({ call, result });
867
+ callbacks2?.onToolResult?.(call, result);
868
+ },
869
+ onUsage: (usage) => {
870
+ partialUsage.inputTokens += usage.inputTokens;
871
+ partialUsage.outputTokens += usage.outputTokens;
872
+ usageReport = usage;
873
+ callbacks2?.onUsage?.(usage);
874
+ }
875
+ };
876
+ const messageCountBeforeTurn = messages.length;
660
877
  let cancelTimer;
661
878
  const cancel = () => {
879
+ if (controller.execution.status === "pending") {
880
+ controller.abort.abort(new Error("Operator cancelled workbench startup"));
881
+ return;
882
+ }
662
883
  try {
663
884
  controller.write({ type: "cancel" });
664
885
  } catch {
665
886
  }
666
- cancelTimer = setTimeout(() => controller.abort.abort(new Error("Operator cancelled workbench turn")), 2e3);
887
+ cancelTimer ??= setTimeout(() => controller.abort.abort(new Error("Operator cancelled workbench turn")), 2e3);
667
888
  };
668
889
  sendOptions?.signal?.addEventListener("abort", cancel, { once: true });
669
890
  try {
891
+ if (sendOptions?.signal?.aborted) cancel();
670
892
  await Promise.all(deferred.splice(0));
671
893
  await controller.start();
672
- if (sendOptions?.signal?.aborted) cancel();
894
+ sendOptions?.signal?.throwIfAborted();
673
895
  controller.status("running");
674
896
  engineWorkStarted = true;
675
897
  lastOutcome = await controller.request("send", { text, generateTitle: sendOptions?.generateTitle });
898
+ await flushSourceContext();
676
899
  return lastOutcome;
900
+ } catch (error) {
901
+ if (sendOptions?.signal?.aborted) {
902
+ const result = await controller.done;
903
+ if ((!result || !result.cleanupFailed) && controller.abort.signal.aborted) {
904
+ controller.status("stopped");
905
+ if (messages.length === messageCountBeforeTurn) messages.push({ role: "user", content: [{ type: "text", text }] });
906
+ if (partialText && messages.at(-1)?.role !== "assistant") messages.push({ role: "assistant", content: [{ type: "text", text: partialText }] });
907
+ return lastOutcome = { assistantText: partialText, toolCalls: partialTools, usage: partialUsage, budget: { tokensUsed: usageReport?.turnTokensUsed ?? partialUsage.inputTokens + partialUsage.outputTokens, tokenBudget: usageReport?.turnTokenBudget ?? options.config.maxTurnTokens ?? Infinity, iterations: usageReport?.iterations ?? 0, maxToolIterations: usageReport?.maxToolIterations ?? options.config.maxToolIterations ?? DEFAULT_MAX_TOOL_ITERATIONS }, stopReason: "cancelled" };
908
+ }
909
+ }
910
+ throw error;
677
911
  } finally {
678
912
  clearTimeout(cancelTimer);
679
913
  active = false;
@@ -699,7 +933,8 @@ function createWorkbenchConsoleSession(options) {
699
933
  },
700
934
  cleanup() {
701
935
  return cleanupPromise ??= (async () => {
702
- await controller.close();
936
+ await controller.close(flushSourceContext);
937
+ await flushSourceContext();
703
938
  if (engineWorkStarted && controller.done) await options.onFindings?.(findings, { outcome: lastOutcome });
704
939
  })();
705
940
  }
@@ -813,6 +1048,13 @@ var PROVIDER_DEFS = [
813
1048
  envVars: ["XAI_API_KEY", "ZERO_XAI_OAUTH_REFRESH_TOKEN"],
814
1049
  hint: "sign in with your xAI account, or set XAI_API_KEY from console.x.ai (endpoint override: XAI_BASE_URL)"
815
1050
  },
1051
+ {
1052
+ id: "cline",
1053
+ label: "Cline / ClinePass",
1054
+ methods: ["api-key"],
1055
+ envVars: ["CLINE_API_KEY"],
1056
+ hint: "set CLINE_API_KEY from app.cline.bot Settings > API Keys; choose cline-pass/* for your active ClinePass plan (endpoint override: CLINE_BASE_URL)"
1057
+ },
816
1058
  {
817
1059
  id: "opencode",
818
1060
  label: "OpenCode Zen",
@@ -3153,8 +3395,9 @@ function serializeSubmission(payload, target, env) {
3153
3395
  if (!target.sentryKey || !payload.diagnostic) return serializePayload(payload);
3154
3396
  const diagnostic = payload.diagnostic;
3155
3397
  const cliVersion = VERSION;
3156
- const commit = /^[0-9a-f]{40}$/i.test("531d93617a529a487a9d94e6c20886903ffc40ec") ? "531d93617a529a487a9d94e6c20886903ffc40ec".toLowerCase() : void 0;
3157
- const environment = env["NODE_ENV"] === "development" ? "development" : env["NODE_ENV"] === "production" || true ? "production" : "development";
3398
+ const commit = /^[0-9a-f]{40}$/i.test("9503df38cef03a732fa8d03df7d2c2a7bbe67a2e") ? "9503df38cef03a732fa8d03df7d2c2a7bbe67a2e".toLowerCase() : void 0;
3399
+ const releaseChannel = getReleaseChannel(env);
3400
+ const environment = releaseChannel === "beta" ? "production" : "development";
3158
3401
  const event = JSON.stringify({
3159
3402
  event_id: diagnostic.eventId,
3160
3403
  timestamp: Date.parse(payload.timestamp) / 1e3,
@@ -3165,6 +3408,7 @@ function serializeSubmission(payload, target, env) {
3165
3408
  environment,
3166
3409
  tags: {
3167
3410
  cli_version: cliVersion,
3411
+ release_channel: releaseChannel,
3168
3412
  ...commit ? { build_commit: commit } : {},
3169
3413
  kind: diagnostic.kind,
3170
3414
  platform: diagnostic.platform,
@@ -3238,7 +3482,7 @@ function loadWorkbenchConfig(home) {
3238
3482
  const file = workbenchConfigPath(home);
3239
3483
  if (!existsSync2(file)) return void 0;
3240
3484
  try {
3241
- const stat = lstatSync2(file);
3485
+ const stat = lstatSync3(file);
3242
3486
  if (!stat.isFile() || stat.isSymbolicLink() || (stat.mode & 63) !== 0 || stat.uid !== process.getuid?.()) {
3243
3487
  throw new Error("Workbench configuration must be an operator-owned, private regular file (mode 0600).");
3244
3488
  }
@@ -3282,13 +3526,17 @@ async function launchConfiguredWorkbench(args) {
3282
3526
  return void 0;
3283
3527
  }
3284
3528
  if (process.platform === "linux" && isAdmittedSmolvmWorkbench()) return void 0;
3285
- if (["workbench", "config", "web", "dashboard", "console", "tui", "doctor", "help", "--help", "-h", "--version", "-v"].includes(args[0] ?? "") || args.length === 0) return void 0;
3529
+ if (["workbench", "config", "web", "dashboard", "console", "chat", "team", "tui", "watch", "doctor", "help", "--help", "-h", "--version", "-v"].includes(args[0] ?? "") || args.length === 0) return void 0;
3530
+ if (remoteBackendClientId(args)) return void 0;
3286
3531
  const hostSettings = loadGlobalSettings(home, { requireExecutionProfile: existsSync2(workbenchConfigPath(home)) });
3287
3532
  if (hostSettings.executionProfile !== "smolvm") return void 0;
3533
+ if (args[0] === "mcp-server") {
3534
+ throw new Error("MCP requires bidirectional stdio, which the SmolVM CLI bridge does not support. The selected SmolVM profile is unchanged; host fallback is refused. Use `0 workflow` commands in SmolVM. MCP currently requires explicitly selected host-local execution; only the operator should choose `0 workbench disable` if host execution is intended.");
3535
+ }
3288
3536
  const config = loadWorkbenchConfig(home);
3289
3537
  if (!config) throw new Error("SmolVM profile is selected but no workbench is configured. Run 0 workbench setup --image <approved-archive>.");
3290
- const workspaceRoot = realpathSync3(config.workspaceRoot ?? process.cwd());
3291
- if (!lstatSync2(workspaceRoot).isDirectory()) throw new Error("The configured workbench workspace is not a directory.");
3538
+ const workspaceRoot = realpathSync4(config.workspaceRoot ?? process.cwd());
3539
+ if (!lstatSync3(workspaceRoot).isDirectory()) throw new Error("The configured workbench workspace is not a directory.");
3292
3540
  const status = await getSmolvmWorkbenchStatus({ stateRoot: config.stateRoot, image: config.image });
3293
3541
  if (!status.platformSupported || !status.runtimeReady || !status.imageApproved) {
3294
3542
  throw new Error(status.error ?? "SmolVM runtime or approved image is unavailable. Run 0 workbench setup; host fallback is refused.");
@@ -3406,12 +3654,15 @@ export {
3406
3654
  currentWorkbenchAssets,
3407
3655
  WORKBENCH_FRAME_BYTES,
3408
3656
  WORKBENCH_MAX_PENDING,
3657
+ WORKBENCH_SOURCE_CONTEXT_LIMIT,
3658
+ validateWorkbenchSourceLesson,
3409
3659
  encodeWorkbenchFrame,
3410
3660
  WorkbenchFrameReader,
3411
3661
  installWorkbenchPlugins,
3412
3662
  validateGuestServicePluginConnections,
3413
3663
  servicePluginSecretRedactor,
3414
3664
  createWorkbenchConsoleSession,
3665
+ remoteBackendClientId,
3415
3666
  PROVIDERS,
3416
3667
  providerSupportsMethod,
3417
3668
  providerStates,