@wardby/cli 0.6.0 → 0.7.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 (576) hide show
  1. package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
  2. package/dist/claude-coding-worker/driver.d.ts +21 -3
  3. package/dist/claude-coding-worker/driver.js +125 -17
  4. package/dist/claude-coding-worker/main.js +34 -6
  5. package/dist/claude-coding-worker/sdk.js +12 -1
  6. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  7. package/dist/claude-coding-worker/tool-socket.js +111 -0
  8. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  9. package/dist/claude-coding-worker/transcript.js +77 -0
  10. package/dist/cli-help.d.ts +1 -1
  11. package/dist/cli-help.js +1 -0
  12. package/dist/cli.js +24 -10
  13. package/dist/coding/continuation-wording.d.ts +35 -0
  14. package/dist/coding/continuation-wording.js +73 -0
  15. package/dist/coding/linked-issue-note.d.ts +23 -0
  16. package/dist/coding/linked-issue-note.js +47 -0
  17. package/dist/coding/merge-wording.d.ts +28 -0
  18. package/dist/coding/merge-wording.js +78 -0
  19. package/dist/coding/pr-description-note.d.ts +9 -0
  20. package/dist/coding/pr-description-note.js +32 -0
  21. package/dist/coding/profile.d.ts +46 -126
  22. package/dist/coding/profile.js +45 -4
  23. package/dist/coding/protected-path-wording.d.ts +8 -0
  24. package/dist/coding/protected-path-wording.js +1 -1
  25. package/dist/coding/protocol.d.ts +264 -346
  26. package/dist/coding/protocol.js +235 -12
  27. package/dist/coding/redact.d.ts +3 -0
  28. package/dist/coding/redact.js +12 -0
  29. package/dist/coding/registry/allowlist.d.ts +12 -0
  30. package/dist/coding/registry/allowlist.js +14 -1
  31. package/dist/coding/registry/audit-mode.d.ts +153 -0
  32. package/dist/coding/registry/audit-mode.js +304 -0
  33. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  34. package/dist/coding/registry/lockfile-shared.js +128 -0
  35. package/dist/coding/registry/lockfiles.js +1 -1
  36. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  37. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  38. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  39. package/dist/coding/registry/npm-lockfile.js +4 -6
  40. package/dist/coding/registry/npm.js +78 -8
  41. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  42. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  43. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  44. package/dist/coding/registry/pypi-plan.js +406 -0
  45. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  46. package/dist/coding/registry/pypi-requirements.js +155 -0
  47. package/dist/coding/registry/pypi.d.ts +3 -27
  48. package/dist/coding/registry/pypi.js +40 -154
  49. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  50. package/dist/coding/registry/refusal-hints.js +61 -0
  51. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  52. package/dist/coding/registry/refusal-wording.js +56 -0
  53. package/dist/coding/registry/report.d.ts +70 -8
  54. package/dist/coding/registry/report.js +112 -5
  55. package/dist/coding/registry/types.d.ts +58 -8
  56. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  57. package/dist/coding/registry/yarn-lockfile.js +367 -0
  58. package/dist/coding/services/catalog.d.ts +37 -351
  59. package/dist/coding/transcript/claude-code.d.ts +13 -0
  60. package/dist/coding/transcript/claude-code.js +273 -0
  61. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  62. package/dist/coding/transcript/download-protocol.js +18 -0
  63. package/dist/coding/transcript/format.d.ts +20 -0
  64. package/dist/coding/transcript/format.js +32 -0
  65. package/dist/coding/transcript/recorder.d.ts +51 -0
  66. package/dist/coding/transcript/recorder.js +225 -0
  67. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  68. package/dist/coding/transcript/resume/checkout.js +203 -0
  69. package/dist/coding/transcript/resume/command.d.ts +17 -0
  70. package/dist/coding/transcript/resume/command.js +176 -0
  71. package/dist/coding/transcript/resume/download.d.ts +20 -0
  72. package/dist/coding/transcript/resume/download.js +153 -0
  73. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  74. package/dist/coding/transcript/resume/launch.js +128 -0
  75. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  76. package/dist/coding/transcript/resume/session-file.js +79 -0
  77. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  78. package/dist/coding/transcript/resume/stand-in.js +49 -0
  79. package/dist/coding-worker/artifact.d.ts +8 -3
  80. package/dist/coding-worker/artifact.js +3 -1
  81. package/dist/coding-worker/debug-trace.d.ts +6 -5
  82. package/dist/coding-worker/debug-trace.js +13 -18
  83. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  84. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  85. package/dist/coding-worker/driver.d.ts +4 -3
  86. package/dist/coding-worker/driver.js +116 -38
  87. package/dist/coding-worker/errors.d.ts +1 -0
  88. package/dist/coding-worker/errors.js +32 -0
  89. package/dist/coding-worker/task-note.d.ts +11 -0
  90. package/dist/coding-worker/task-note.js +13 -0
  91. package/dist/coding-worker/types.d.ts +11 -0
  92. package/dist/config/dependency-cache.d.ts +23 -0
  93. package/dist/config/dependency-cache.js +32 -0
  94. package/dist/config/providers.d.ts +12 -3
  95. package/dist/config/providers.js +55 -5
  96. package/dist/config/test-simulators.d.ts +82 -0
  97. package/dist/config/test-simulators.js +305 -0
  98. package/dist/core/async-context.d.ts +2 -0
  99. package/dist/core/async-context.js +12 -0
  100. package/dist/core/budget-events.d.ts +108 -0
  101. package/dist/core/budget-events.js +346 -0
  102. package/dist/core/budget-groups.d.ts +50 -1
  103. package/dist/core/budget-groups.js +236 -27
  104. package/dist/core/budget-stopped-head.d.ts +46 -0
  105. package/dist/core/budget-stopped-head.js +81 -0
  106. package/dist/core/budget-topup.d.ts +51 -0
  107. package/dist/core/budget-topup.js +156 -0
  108. package/dist/core/budget-wording.d.ts +16 -2
  109. package/dist/core/budget-wording.js +40 -2
  110. package/dist/core/coding-queue.d.ts +2 -1
  111. package/dist/core/coding-queue.js +7 -0
  112. package/dist/core/cron.d.ts +19 -1
  113. package/dist/core/cron.js +17 -0
  114. package/dist/core/datastores.js +1 -1
  115. package/dist/core/deferred-coding.d.ts +14 -0
  116. package/dist/core/deferred-coding.js +62 -0
  117. package/dist/core/delegation-child.d.ts +25 -0
  118. package/dist/core/delegation-child.js +37 -0
  119. package/dist/core/dispatch.d.ts +42 -0
  120. package/dist/core/dispatch.js +131 -56
  121. package/dist/core/engine-native.js +1 -1
  122. package/dist/core/error-code.d.ts +38 -0
  123. package/dist/core/error-code.js +168 -0
  124. package/dist/core/grants.d.ts +19 -6
  125. package/dist/core/grants.js +55 -6
  126. package/dist/core/host-events.d.ts +18 -2
  127. package/dist/core/host-events.js +284 -24
  128. package/dist/core/host-status.d.ts +85 -3
  129. package/dist/core/host-status.js +298 -20
  130. package/dist/core/issue-bridge.d.ts +50 -6
  131. package/dist/core/issue-bridge.js +124 -33
  132. package/dist/core/issue-events.d.ts +1 -1
  133. package/dist/core/issue-events.js +4 -10
  134. package/dist/core/issue-status.d.ts +1 -1
  135. package/dist/core/issue-status.js +54 -26
  136. package/dist/core/logger.d.ts +5 -0
  137. package/dist/core/logger.js +14 -1
  138. package/dist/core/lost-run-children.d.ts +6 -0
  139. package/dist/core/lost-run-children.js +32 -0
  140. package/dist/core/mark-ready.d.ts +34 -0
  141. package/dist/core/mark-ready.js +152 -0
  142. package/dist/core/markdown-code.d.ts +8 -0
  143. package/dist/core/markdown-code.js +107 -0
  144. package/dist/core/memory-tools.js +7 -0
  145. package/dist/core/merge-order-check.d.ts +2 -1
  146. package/dist/core/merge-order-check.js +8 -1
  147. package/dist/core/notification-templates.d.ts +1 -7
  148. package/dist/core/notification-templates.js +36 -2
  149. package/dist/core/pull-request-state-sync.js +2 -2
  150. package/dist/core/reconciler.d.ts +4 -3
  151. package/dist/core/reconciler.js +8 -1
  152. package/dist/core/related-pull-requests.d.ts +11 -3
  153. package/dist/core/related-pull-requests.js +27 -14
  154. package/dist/core/reply-parts.d.ts +21 -0
  155. package/dist/core/reply-parts.js +73 -0
  156. package/dist/core/review-fix.d.ts +1 -1
  157. package/dist/core/review-fix.js +2 -1
  158. package/dist/core/review-host-checks.d.ts +1 -1
  159. package/dist/core/review-host-tools.d.ts +3 -0
  160. package/dist/core/review-host-tools.js +99 -13
  161. package/dist/core/review-reads.d.ts +55 -0
  162. package/dist/core/review-reads.js +233 -0
  163. package/dist/core/run-status.d.ts +12 -0
  164. package/dist/core/run-status.js +12 -0
  165. package/dist/core/runner.d.ts +80 -34
  166. package/dist/core/runner.js +439 -144
  167. package/dist/core/schedule-start.d.ts +12 -0
  168. package/dist/core/schedule-start.js +14 -0
  169. package/dist/core/secret-broker-config.d.ts +10 -74
  170. package/dist/core/secret-guard.d.ts +46 -0
  171. package/dist/core/secret-guard.js +104 -0
  172. package/dist/core/secret-guarded-stores.d.ts +12 -0
  173. package/dist/core/secret-guarded-stores.js +41 -0
  174. package/dist/core/secret-spans.d.ts +50 -0
  175. package/dist/core/secret-spans.js +94 -0
  176. package/dist/core/stop-run.d.ts +46 -0
  177. package/dist/core/stop-run.js +61 -0
  178. package/dist/core/workflow-events.d.ts +14 -2
  179. package/dist/core/workflow-events.js +4 -0
  180. package/dist/core/workflow-run-events.d.ts +5 -3
  181. package/dist/core/workflow-run-events.js +43 -8
  182. package/dist/core/zod-json-schema.d.ts +4 -0
  183. package/dist/core/zod-json-schema.js +39 -0
  184. package/dist/core/zod3-window.d.ts +35 -0
  185. package/dist/core/zod3-window.js +124 -0
  186. package/dist/generated/prisma/browser.d.ts +34 -3
  187. package/dist/generated/prisma/client.d.ts +34 -3
  188. package/dist/generated/prisma/commonInputTypes.d.ts +220 -60
  189. package/dist/generated/prisma/enums.d.ts +10 -0
  190. package/dist/generated/prisma/enums.js +8 -0
  191. package/dist/generated/prisma/internal/class.d.ts +44 -0
  192. package/dist/generated/prisma/internal/class.js +4 -4
  193. package/dist/generated/prisma/internal/prismaNamespace.d.ts +428 -9
  194. package/dist/generated/prisma/internal/prismaNamespace.js +92 -1
  195. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +95 -0
  196. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +92 -1
  197. package/dist/generated/prisma/models/Agent.d.ts +106 -8
  198. package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
  199. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +229 -1
  200. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  201. package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
  202. package/dist/generated/prisma/models/CodingRun.d.ts +1637 -1
  203. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  204. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  205. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  206. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  207. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +39 -1
  208. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
  209. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  210. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  211. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  212. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  213. package/dist/generated/prisma/models/Run.d.ts +738 -2
  214. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  215. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  216. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  217. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  218. package/dist/generated/prisma/models.d.ts +4 -0
  219. package/dist/help-index.json +1320 -69
  220. package/dist/import/create.js +32 -3
  221. package/dist/import/neutral-schema.d.ts +50 -281
  222. package/dist/import/neutral-schema.js +5 -4
  223. package/dist/knowledge/check.d.ts +1 -1
  224. package/dist/knowledge/cli.d.ts +11 -1
  225. package/dist/knowledge/cli.js +37 -4
  226. package/dist/knowledge/concept.d.ts +3 -19
  227. package/dist/knowledge/location.d.ts +31 -0
  228. package/dist/knowledge/location.js +78 -0
  229. package/dist/mcp/auth/access.d.ts +10 -2
  230. package/dist/mcp/auth/access.js +15 -1
  231. package/dist/mcp/auth/ownership.d.ts +7 -7
  232. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  233. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  234. package/dist/mcp/host-events/github-ingress.d.ts +2 -0
  235. package/dist/mcp/host-events/github-ingress.js +2 -1
  236. package/dist/mcp/index.d.ts +6 -0
  237. package/dist/mcp/index.js +58 -10
  238. package/dist/mcp/server.d.ts +13 -0
  239. package/dist/mcp/server.js +33 -14
  240. package/dist/mcp/tools/agents.d.ts +4 -0
  241. package/dist/mcp/tools/agents.js +198 -16
  242. package/dist/mcp/tools/datastore.js +17 -8
  243. package/dist/mcp/tools/grants.js +9 -3
  244. package/dist/mcp/tools/memory.js +11 -1
  245. package/dist/mcp/tools/notification-channels.js +2 -2
  246. package/dist/mcp/tools/packages.d.ts +2 -0
  247. package/dist/mcp/tools/packages.js +195 -0
  248. package/dist/mcp/tools/repositories.js +18 -5
  249. package/dist/mcp/tools/run-access.d.ts +16 -0
  250. package/dist/mcp/tools/run-access.js +25 -0
  251. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  252. package/dist/mcp/tools/run-transcript-download.js +129 -0
  253. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  254. package/dist/mcp/tools/run-transcript.js +70 -0
  255. package/dist/mcp/tools/runs.js +34 -12
  256. package/dist/mcp/tools/scheduling.js +3 -1
  257. package/dist/mcp/tools/secret-elicitation-form.js +5 -0
  258. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  259. package/dist/mcp/tools/secret-elicitation-server.js +10 -61
  260. package/dist/mcp/tools/secrets.js +2 -2
  261. package/dist/mcp/tools/stop-run.d.ts +2 -0
  262. package/dist/mcp/tools/stop-run.js +82 -0
  263. package/dist/mcp/tools/subagents.js +2 -2
  264. package/dist/mcp/tools/tools.d.ts +1 -1
  265. package/dist/mcp/tools/tools.js +25 -9
  266. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  267. package/dist/mcp/transport/stdio-link-host.js +67 -0
  268. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  269. package/dist/mcp/transport/streamable-http.js +41 -1
  270. package/dist/native-worker/docker-launcher.d.ts +38 -2
  271. package/dist/native-worker/docker-launcher.js +65 -5
  272. package/dist/native-worker/gateway-server.d.ts +41 -3
  273. package/dist/native-worker/gateway-server.js +124 -27
  274. package/dist/native-worker/gateway.d.ts +27 -1
  275. package/dist/native-worker/gateway.js +70 -4
  276. package/dist/native-worker/http-server.d.ts +3 -1
  277. package/dist/native-worker/http-server.js +11 -7
  278. package/dist/native-worker/http-transport.js +1 -1
  279. package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
  280. package/dist/native-worker/kubernetes-launcher.js +43 -3
  281. package/dist/native-worker/launch.d.ts +18 -1
  282. package/dist/native-worker/launch.js +6 -1
  283. package/dist/native-worker/ledger.d.ts +18 -2
  284. package/dist/native-worker/ledger.js +57 -4
  285. package/dist/native-worker/loopback.js +3 -8
  286. package/dist/native-worker/main.d.ts +2 -1
  287. package/dist/native-worker/main.js +14 -3
  288. package/dist/native-worker/protocol.d.ts +129 -577
  289. package/dist/native-worker/protocol.js +47 -1
  290. package/dist/native-worker/sandbox-executor.d.ts +17 -2
  291. package/dist/native-worker/sandbox-executor.js +78 -4
  292. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  293. package/dist/native-worker/stderr-redaction.js +237 -0
  294. package/dist/native-worker/stdio.d.ts +1 -1
  295. package/dist/native-worker/stdio.js +6 -5
  296. package/dist/native-worker/warm-pool.d.ts +2 -2
  297. package/dist/native-worker/warm-pool.js +4 -4
  298. package/dist/native-worker/worker.js +28 -2
  299. package/dist/observability/metrics.js +6 -1
  300. package/dist/providers/auth/self-hosted.d.ts +1 -1
  301. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  302. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  303. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  304. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  305. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  306. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  307. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  308. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  309. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  310. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  311. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  312. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  313. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  314. package/dist/providers/coding-proxy/hold.js +86 -0
  315. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  316. package/dist/providers/coding-proxy/interrupted.js +104 -0
  317. package/dist/providers/coding-proxy/memory-ledger.d.ts +15 -2
  318. package/dist/providers/coding-proxy/memory-ledger.js +84 -8
  319. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  320. package/dist/providers/coding-proxy/metering.js +27 -4
  321. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -2
  322. package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
  323. package/dist/providers/coding-proxy/proxy.d.ts +14 -1
  324. package/dist/providers/coding-proxy/proxy.js +166 -14
  325. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  326. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  327. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  328. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  329. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  330. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  331. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  332. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  333. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  334. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  335. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  336. package/dist/providers/coding-proxy/registry/service.js +579 -112
  337. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  338. package/dist/providers/coding-proxy/registry/store.js +54 -1
  339. package/dist/providers/coding-proxy/runtime.d.ts +4 -0
  340. package/dist/providers/coding-proxy/runtime.js +78 -16
  341. package/dist/providers/coding-proxy/server.d.ts +6 -1
  342. package/dist/providers/coding-proxy/server.js +45 -1
  343. package/dist/providers/coding-proxy/types.d.ts +65 -1
  344. package/dist/providers/datastore/types.d.ts +5 -0
  345. package/dist/providers/engine/types.d.ts +17 -2
  346. package/dist/providers/engine/types.js +17 -0
  347. package/dist/providers/executor/composition.d.ts +10 -3
  348. package/dist/providers/executor/composition.js +47 -7
  349. package/dist/providers/executor/container.d.ts +361 -8
  350. package/dist/providers/executor/container.js +1136 -91
  351. package/dist/providers/executor/dbos-status.d.ts +31 -0
  352. package/dist/providers/executor/dbos-status.js +64 -0
  353. package/dist/providers/executor/dbos.d.ts +50 -1
  354. package/dist/providers/executor/dbos.js +207 -20
  355. package/dist/providers/executor/deferred.d.ts +12 -24
  356. package/dist/providers/executor/deferred.js +10 -29
  357. package/dist/providers/executor/in-process.d.ts +9 -1
  358. package/dist/providers/executor/in-process.js +14 -4
  359. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  360. package/dist/providers/executor/linked-issue-reader.js +30 -0
  361. package/dist/providers/executor/routing.d.ts +2 -0
  362. package/dist/providers/executor/routing.js +4 -0
  363. package/dist/providers/executor/types.d.ts +13 -0
  364. package/dist/providers/index.d.ts +2 -1
  365. package/dist/providers/issue-tracker/types.d.ts +17 -0
  366. package/dist/providers/issue-tracker/types.js +39 -1
  367. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  368. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  369. package/dist/providers/jobs/docker-isolation.d.ts +8 -0
  370. package/dist/providers/jobs/docker-isolation.js +17 -0
  371. package/dist/providers/jobs/docker.d.ts +1 -0
  372. package/dist/providers/jobs/docker.js +27 -2
  373. package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
  374. package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
  375. package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
  376. package/dist/providers/jobs/kubernetes-api.js +10 -0
  377. package/dist/providers/jobs/kubernetes-client.js +10 -1
  378. package/dist/providers/jobs/kubernetes-isolation.d.ts +2 -0
  379. package/dist/providers/jobs/kubernetes-isolation.js +17 -1
  380. package/dist/providers/jobs/kubernetes.d.ts +6 -1
  381. package/dist/providers/jobs/kubernetes.js +105 -16
  382. package/dist/providers/jobs/types.d.ts +33 -0
  383. package/dist/providers/jobs/types.js +13 -1
  384. package/dist/providers/llm/anthropic.js +5 -1
  385. package/dist/providers/llm/bedrock.d.ts +0 -12
  386. package/dist/providers/llm/bedrock.js +4 -0
  387. package/dist/providers/llm/claude-messages.d.ts +3 -1
  388. package/dist/providers/llm/claude-messages.js +4 -1
  389. package/dist/providers/llm/claude-provider.d.ts +2 -2
  390. package/dist/providers/llm/claude-provider.js +2 -2
  391. package/dist/providers/llm/openai.d.ts +2 -2
  392. package/dist/providers/llm/openai.js +6 -2
  393. package/dist/providers/llm/routing.d.ts +2 -2
  394. package/dist/providers/llm/routing.js +2 -2
  395. package/dist/providers/llm/types.d.ts +12 -2
  396. package/dist/providers/review-host/github-events.d.ts +9 -1
  397. package/dist/providers/review-host/github-events.js +34 -12
  398. package/dist/providers/review-host/github.d.ts +29 -2
  399. package/dist/providers/review-host/github.js +224 -29
  400. package/dist/providers/review-host/local.d.ts +8 -4
  401. package/dist/providers/review-host/local.js +49 -31
  402. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  403. package/dist/providers/review-host/patch-pages.js +176 -0
  404. package/dist/providers/review-host/review-format.d.ts +19 -1
  405. package/dist/providers/review-host/review-format.js +38 -7
  406. package/dist/providers/review-host/types.d.ts +134 -2
  407. package/dist/providers/review-host/types.js +8 -0
  408. package/dist/providers/storage/gcs.d.ts +63 -0
  409. package/dist/providers/storage/gcs.js +69 -0
  410. package/dist/providers/storage/index.d.ts +15 -0
  411. package/dist/providers/storage/index.js +14 -0
  412. package/dist/providers/storage/local.d.ts +24 -0
  413. package/dist/providers/storage/local.js +92 -0
  414. package/dist/providers/storage/meter.d.ts +14 -0
  415. package/dist/providers/storage/meter.js +34 -0
  416. package/dist/providers/storage/s3.d.ts +41 -0
  417. package/dist/providers/storage/s3.js +107 -0
  418. package/dist/providers/storage/types.d.ts +37 -3
  419. package/dist/providers/storage/types.js +21 -4
  420. package/dist/providers/vcs/git.d.ts +33 -2
  421. package/dist/providers/vcs/git.js +324 -22
  422. package/dist/providers/vcs/github-remote.d.ts +26 -3
  423. package/dist/providers/vcs/github-remote.js +124 -14
  424. package/dist/providers/vcs/github.d.ts +214 -6
  425. package/dist/providers/vcs/github.js +447 -45
  426. package/dist/providers/vcs/index.js +8 -1
  427. package/dist/providers/vcs/pr-description.d.ts +127 -0
  428. package/dist/providers/vcs/pr-description.js +270 -0
  429. package/dist/providers/vcs/remote.d.ts +33 -1
  430. package/dist/providers/vcs/routing.d.ts +4 -2
  431. package/dist/providers/vcs/routing.js +6 -0
  432. package/dist/providers/vcs/types.d.ts +80 -3
  433. package/dist/quickstart/coding-seed.d.ts +14 -3
  434. package/dist/quickstart/coding-seed.js +213 -4
  435. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  436. package/dist/quickstart/reviewer-prompt.js +6 -6
  437. package/dist/quickstart-images.json +1 -1
  438. package/dist/sandbox/generated/zod.bundle.js +62 -1
  439. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  440. package/dist/sandbox/host-functions.d.ts +1 -0
  441. package/dist/sandbox/host-functions.js +6 -11
  442. package/dist/sandbox/secret-broker.js +3 -4
  443. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  444. package/dist/sandbox/zod-params.d.ts +37 -5
  445. package/dist/sandbox/zod-params.js +181 -26
  446. package/dist/serve.js +8 -1
  447. package/dist/viewer/api-schema.d.ts +349 -2627
  448. package/dist/viewer/api-schema.js +7 -0
  449. package/dist/viewer/build-schemas.js +6 -2
  450. package/dist/viewer/openapi.js +2 -4
  451. package/dist/wardby-bin.js +10 -0
  452. package/docs/agent-recipes.md +58 -20
  453. package/docs/code-review-agents.md +551 -41
  454. package/docs/coding-agent-setup.md +489 -7
  455. package/docs/coding-packages.md +1033 -90
  456. package/docs/coding-services.md +27 -12
  457. package/docs/coding-worker-byo-images.md +20 -0
  458. package/docs/coding-worker-isolation.md +105 -30
  459. package/docs/getting-started-gke.md +124 -137
  460. package/docs/getting-started-identity-provider.md +10 -1
  461. package/docs/getting-started.md +9 -0
  462. package/docs/jira-agents.md +17 -8
  463. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  464. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  465. package/docs/knowledge/delegation-admission-slots.md +52 -0
  466. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  467. package/docs/knowledge/import-rename-target.md +52 -0
  468. package/docs/knowledge/index.md +57 -0
  469. package/docs/knowledge/log.md +9 -0
  470. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  471. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  472. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  473. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  474. package/docs/knowledge/overview-cli.md +74 -0
  475. package/docs/knowledge/overview-coding-proxy.md +72 -0
  476. package/docs/knowledge/overview-coding.md +72 -0
  477. package/docs/knowledge/overview-config.md +60 -0
  478. package/docs/knowledge/overview-core.md +72 -0
  479. package/docs/knowledge/overview-deploy.md +83 -0
  480. package/docs/knowledge/overview-mcp.md +61 -0
  481. package/docs/knowledge/overview-prisma.md +72 -0
  482. package/docs/knowledge/overview-providers.md +89 -0
  483. package/docs/knowledge/overview-sandbox.md +83 -0
  484. package/docs/knowledge/overview-surfaces.md +83 -0
  485. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  486. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  487. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  488. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  489. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  490. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  491. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  492. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  493. package/docs/knowledge/warm-input-publication.md +30 -0
  494. package/docs/knowledge/workspace-staging-failure.md +54 -0
  495. package/docs/knowledge.md +54 -14
  496. package/docs/native-sandbox.md +119 -23
  497. package/docs/observability.md +4 -0
  498. package/docs/security-deployment.md +33 -2
  499. package/docs/slack-notifications.md +35 -19
  500. package/docs/tool-secrets.md +42 -10
  501. package/docs/viewer-api.openapi.yml +1 -1
  502. package/help/admin-viewer.md +24 -2
  503. package/help/architecture-agent.md +11 -6
  504. package/help/build-worker-image.md +3 -1
  505. package/help/builder-agent.md +19 -6
  506. package/help/code-review-agents.md +177 -6
  507. package/help/coding-packages.md +156 -6
  508. package/help/cost-attribution.md +9 -5
  509. package/help/creating-agents.md +14 -1
  510. package/help/dependency-cache.md +143 -0
  511. package/help/deploy-gke.md +15 -8
  512. package/help/errors/budget-exhausted.md +187 -0
  513. package/help/errors/budget-group-exhausted.md +5 -1
  514. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  515. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  516. package/help/errors/continuation-closed.md +9 -12
  517. package/help/errors/delegation-conflict.md +24 -0
  518. package/help/errors/file-list-truncated.md +45 -0
  519. package/help/errors/full-read-required.md +49 -0
  520. package/help/errors/github-account-not-allowed.md +4 -0
  521. package/help/errors/graph-incomplete.md +43 -0
  522. package/help/errors/graph-limit.md +43 -0
  523. package/help/errors/merge-conflict.md +49 -0
  524. package/help/errors/native-sandbox-gateway-error.md +20 -0
  525. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  526. package/help/errors/native-sandbox-worker-exited.md +3 -2
  527. package/help/errors/package-not-allowed-pending.md +52 -0
  528. package/help/errors/package-not-allowed.md +51 -0
  529. package/help/errors/package-refusals.md +43 -0
  530. package/help/errors/patch-cursor-malformed.md +31 -0
  531. package/help/errors/run-lost.md +39 -0
  532. package/help/errors/run-transcript-download.md +44 -0
  533. package/help/errors/secret-in-value.md +69 -0
  534. package/help/errors/target-merge.md +40 -0
  535. package/help/fix-merge-conflicts.md +73 -0
  536. package/help/github-app-setup.md +132 -0
  537. package/help/github.md +22 -0
  538. package/help/identity-and-access.md +2 -0
  539. package/help/jira.md +23 -6
  540. package/help/knowledge.md +16 -7
  541. package/help/local-repositories.md +1 -1
  542. package/help/low-power-mode.md +7 -1
  543. package/help/merge-order-check.md +5 -0
  544. package/help/native-capabilities.md +29 -1
  545. package/help/native-sandbox.md +15 -1
  546. package/help/operating-agents.md +5 -0
  547. package/help/package-audit-mode.md +91 -0
  548. package/help/related-pull-requests.md +10 -7
  549. package/help/resume-runs-locally.md +131 -0
  550. package/help/review-fix-rounds.md +33 -1
  551. package/help/sharing-agents.md +59 -0
  552. package/help/slack-notifications.md +19 -5
  553. package/help/status-comments.md +31 -0
  554. package/help/stop-run.md +58 -0
  555. package/help/troubleshooting/budgets.md +28 -0
  556. package/help/troubleshooting/coding-workers.md +78 -7
  557. package/package.json +17 -10
  558. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  559. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  560. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  561. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  562. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  563. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  564. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  565. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  566. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  567. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  568. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  569. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  570. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  571. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  572. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  573. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  574. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  575. package/prisma/schema.prisma +311 -97
  576. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -0,0 +1,31 @@
1
+ import { type TranscriptMeta } from "./download.js";
2
+ export type Git = (args: string[], cwd: string) => Promise<string>;
3
+ export declare const realGit: Git;
4
+ export interface CheckoutOptions {
5
+ /** Where the command runs (a clone of the repository, for hosted runs). */
6
+ cwd: string;
7
+ /** --dir: the checkout directory. Default: a sibling `<repo>-run-<short run id>`. */
8
+ dir?: string;
9
+ /** --here: use cwd as it is; no checkout. */
10
+ here?: boolean;
11
+ /**
12
+ * Whether the link came from this machine (a loopback origin). A `local:` repository names a path on
13
+ * the server's machine; from any other origin, checking it out would let that server point the
14
+ * importer at any repository here, so it is refused unless the user chose --dir or --here.
15
+ */
16
+ linkIsLoopback?: boolean;
17
+ git?: Git;
18
+ }
19
+ export interface Checkout {
20
+ dir: string;
21
+ /** What is checked out: the branch name, or the base commit. */
22
+ ref: string;
23
+ /** "created", "reused" (an earlier import's worktree) or "here". */
24
+ outcome: "created" | "reused" | "here";
25
+ warnings: string[];
26
+ }
27
+ /** owner/name from a GitHub remote URL (https, ssh or scp form); undefined for anything else. */
28
+ export declare function githubRemoteRepository(url: string): string | undefined;
29
+ /** Fixed code: a remote server named a local: repository on this machine. */
30
+ export declare const LOCAL_REPOSITORY_REFUSED = "local_repository_refused";
31
+ export declare function prepareCheckout(meta: TranscriptMeta, opts: CheckoutOptions): Promise<Checkout>;
@@ -0,0 +1,203 @@
1
+ /**
2
+ * The checkout a resumed session continues in: a detached git worktree at
3
+ * the run's branch (detached, so it works while that branch is checked out
4
+ * elsewhere).
5
+ *
6
+ * - `local:/abs/path` repositories: the worktree comes from that repository.
7
+ * - Hosted repositories: the current directory must be a clone of the run's
8
+ * repository; the branch is fetched from the matching remote.
9
+ * - A branch that no longer exists (a failed run that pushed nothing) falls
10
+ * back to the run's base commit, with a warning.
11
+ *
12
+ * git runs with argument arrays (no shell), and every ref and path from the
13
+ * server is validated before it reaches git.
14
+ */
15
+ import { execFile } from "node:child_process";
16
+ import { existsSync, realpathSync } from "node:fs";
17
+ import { basename, dirname, isAbsolute, join, resolve } from "node:path";
18
+ import { promisify } from "node:util";
19
+ import { isLocalRepository, normalizeGitHubRepository, normalizeGitRef, normalizeLocalRepository, } from "../../protocol.js";
20
+ import { ResumeError } from "./download.js";
21
+ const execFileAsync = promisify(execFile);
22
+ const SHA = /^[0-9a-f]{7,64}$/i;
23
+ export const realGit = async (args, cwd) => {
24
+ const { stdout } = await execFileAsync("git", args, {
25
+ cwd,
26
+ maxBuffer: 16 * 1024 * 1024,
27
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
28
+ });
29
+ return stdout.trim();
30
+ };
31
+ async function tryGit(git, args, cwd) {
32
+ try {
33
+ return await git(args, cwd);
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ }
39
+ /** owner/name from a GitHub remote URL (https, ssh or scp form); undefined for anything else. */
40
+ export function githubRemoteRepository(url) {
41
+ const trimmed = url.trim();
42
+ const scp = /^[^@/\s]+@github\.com:(.+)$/i.exec(trimmed);
43
+ let path;
44
+ if (scp)
45
+ path = scp[1];
46
+ else {
47
+ try {
48
+ const parsed = new URL(trimmed);
49
+ if (parsed.hostname.toLowerCase() === "github.com" && ["https:", "ssh:", "git:"].includes(parsed.protocol)) {
50
+ path = parsed.pathname;
51
+ }
52
+ }
53
+ catch {
54
+ return undefined;
55
+ }
56
+ }
57
+ if (!path)
58
+ return undefined;
59
+ try {
60
+ return normalizeGitHubRepository(path.replace(/^\/+|\/+$/g, ""));
61
+ }
62
+ catch {
63
+ return undefined;
64
+ }
65
+ }
66
+ function shortRunId(runId) {
67
+ return runId.slice(-8);
68
+ }
69
+ function validRef(ref) {
70
+ if (!ref)
71
+ return undefined;
72
+ try {
73
+ return normalizeGitRef(ref);
74
+ }
75
+ catch {
76
+ return undefined;
77
+ }
78
+ }
79
+ async function commonDir(git, dir) {
80
+ const out = await tryGit(git, ["rev-parse", "--path-format=absolute", "--git-common-dir"], dir);
81
+ return out ? realpathSync(out) : undefined;
82
+ }
83
+ /**
84
+ * Creates the worktree, or reuses one an earlier import made for the same repository. A reused
85
+ * worktree is left as it is (it may hold local work), with a warning when its HEAD is elsewhere.
86
+ */
87
+ async function addWorktree(git, repoDir, dir, commit, warnings) {
88
+ if (existsSync(dir)) {
89
+ const [mine, theirs] = await Promise.all([commonDir(git, repoDir), commonDir(git, dir)]);
90
+ if (!mine || !theirs || mine !== theirs) {
91
+ throw new ResumeError(`${dir} already exists and is not a checkout of this repository. Pass --dir <path> or --here.`);
92
+ }
93
+ const [head, wanted] = await Promise.all([
94
+ tryGit(git, ["rev-parse", "--verify", "--quiet", "HEAD"], dir),
95
+ tryGit(git, ["rev-parse", "--verify", "--quiet", `${commit}^{commit}`], repoDir),
96
+ ]);
97
+ if (!head || !wanted || head !== wanted) {
98
+ warnings.push(`The existing worktree at ${dir} is at ${head ?? "an unknown commit"}, not the run's ${wanted ?? commit}. ` +
99
+ "It was left as it is (it may hold your local work); check out the run's commit there, or pass --dir <path>.");
100
+ }
101
+ return "reused";
102
+ }
103
+ try {
104
+ await git(["worktree", "add", "--detach", dir, commit], repoDir);
105
+ }
106
+ catch {
107
+ throw new ResumeError(`git could not create a worktree at ${dir}. Pass --dir <path>, or --here to use this directory.`);
108
+ }
109
+ return "created";
110
+ }
111
+ /** Fixed code: a remote server named a local: repository on this machine. */
112
+ export const LOCAL_REPOSITORY_REFUSED = "local_repository_refused";
113
+ export async function prepareCheckout(meta, opts) {
114
+ const git = opts.git ?? realGit;
115
+ const branch = validRef(meta.resultBranch ?? meta.headRef);
116
+ const baseSha = meta.baseSha && SHA.test(meta.baseSha) ? meta.baseSha : undefined;
117
+ if (opts.here)
118
+ return { dir: resolve(opts.cwd), ref: branch ?? baseSha ?? "", outcome: "here", warnings: [] };
119
+ const warnings = [];
120
+ const fallbackWarning = (why) => `${why}; checked out the run's base commit ${baseSha} instead. The run's changes are not in this checkout.`;
121
+ if (isLocalRepository(meta.repository)) {
122
+ if (!opts.linkIsLoopback && opts.dir === undefined) {
123
+ throw new ResumeError(`${LOCAL_REPOSITORY_REFUSED}: the run's repository is a local: folder on the server's machine, but this ` +
124
+ "link is from another machine. Pass --here to continue in the current directory, or --dir <path> to " +
125
+ "check the run out from that folder here anyway.");
126
+ }
127
+ let repoDir;
128
+ try {
129
+ repoDir = normalizeLocalRepository(meta.repository).slice("local:".length);
130
+ }
131
+ catch {
132
+ throw new ResumeError("The run's local repository path is invalid.");
133
+ }
134
+ if (!existsSync(repoDir))
135
+ throw new ResumeError(`The run's repository ${repoDir} does not exist on this machine.`);
136
+ let commit;
137
+ let ref = branch;
138
+ if (branch)
139
+ commit = await tryGit(git, ["rev-parse", "--verify", "--quiet", `refs/heads/${branch}^{commit}`], repoDir);
140
+ if (!commit) {
141
+ if (!baseSha || !(await tryGit(git, ["rev-parse", "--verify", "--quiet", `${baseSha}^{commit}`], repoDir))) {
142
+ throw new ResumeError(`The run's branch ${branch ?? "(none)"} and base commit are not in ${repoDir}.`);
143
+ }
144
+ warnings.push(fallbackWarning(`The branch ${branch ?? "(none)"} is not in ${repoDir}`));
145
+ commit = baseSha;
146
+ ref = baseSha;
147
+ }
148
+ const dir = opts.dir
149
+ ? resolve(opts.cwd, opts.dir)
150
+ : join(dirname(repoDir), `${basename(repoDir)}-run-${shortRunId(meta.runId)}`);
151
+ const outcome = await addWorktree(git, repoDir, dir, commit, warnings);
152
+ return { dir, ref: ref, outcome, warnings };
153
+ }
154
+ let repository;
155
+ try {
156
+ repository = normalizeGitHubRepository(meta.repository);
157
+ }
158
+ catch {
159
+ throw new ResumeError("The run's repository is not one wardby resume can check out. Pass --here to skip the checkout.");
160
+ }
161
+ const cloneUrl = `https://github.com/${repository}.git`;
162
+ const top = await tryGit(git, ["rev-parse", "--show-toplevel"], opts.cwd);
163
+ if (!top) {
164
+ throw new ResumeError(`Run this inside a clone of ${repository} (git clone ${cloneUrl}), or pass --here to skip the checkout.`);
165
+ }
166
+ const remotes = (await tryGit(git, ["remote"], top))?.split("\n").filter(Boolean) ?? [];
167
+ let remote;
168
+ for (const name of remotes) {
169
+ const url = await tryGit(git, ["remote", "get-url", name], top);
170
+ if (url && githubRemoteRepository(url) === repository) {
171
+ remote = name;
172
+ break;
173
+ }
174
+ }
175
+ if (!remote) {
176
+ throw new ResumeError(`This directory is not a clone of ${repository}. Run the command inside one (git clone ${cloneUrl}), or pass --here to skip the checkout.`);
177
+ }
178
+ let commit;
179
+ let ref = branch;
180
+ if (branch && (await tryGit(git, ["fetch", "--quiet", remote, `refs/heads/${branch}`], top)) !== undefined) {
181
+ commit = await tryGit(git, ["rev-parse", "--verify", "--quiet", "FETCH_HEAD^{commit}"], top);
182
+ }
183
+ if (!commit) {
184
+ if (!baseSha)
185
+ throw new ResumeError(`The run's branch ${branch ?? "(none)"} could not be fetched from ${remote}.`);
186
+ let found = await tryGit(git, ["rev-parse", "--verify", "--quiet", `${baseSha}^{commit}`], top);
187
+ if (!found && (await tryGit(git, ["fetch", "--quiet", remote, baseSha], top)) !== undefined) {
188
+ found = await tryGit(git, ["rev-parse", "--verify", "--quiet", `${baseSha}^{commit}`], top);
189
+ }
190
+ if (!found)
191
+ throw new ResumeError(`Neither the run's branch nor its base commit could be fetched from ${remote}.`);
192
+ warnings.push(fallbackWarning(`The branch ${branch ?? "(none)"} could not be fetched from ${remote}`));
193
+ commit = found;
194
+ ref = baseSha;
195
+ }
196
+ const dir = opts.dir
197
+ ? isAbsolute(opts.dir)
198
+ ? opts.dir
199
+ : resolve(opts.cwd, opts.dir)
200
+ : join(dirname(top), `${basename(top)}-run-${shortRunId(meta.runId)}`);
201
+ const outcome = await addWorktree(git, top, dir, commit, warnings);
202
+ return { dir, ref: ref, outcome, warnings };
203
+ }
@@ -0,0 +1,17 @@
1
+ import { type Git } from "./checkout.js";
2
+ export declare const RESUME_USAGE = "usage: wardby resume - [--dir <path> | --here] [--force] [--print]\n wardby resume '<link>' [options]\n\nContinue a wardby coding run's Claude Code session on this machine. Get the\nlink (valid for 10 minutes) from the get_run_transcript MCP tool. With \"-\",\npaste the link when asked (or pipe it in): this keeps it out of your shell\nhistory and the process list, where a link given as an argument stays while\nClaude Code runs.\n\n --dir <path> Check the run out here (default: a sibling <repo>-run-<id>)\n --here Use the current directory as it is; no checkout\n --force Replace a different session file already imported for this run\n --print Print the claude command instead of starting it";
3
+ export interface ResumeDeps {
4
+ cwd?: string;
5
+ sessionsRoot?: string;
6
+ fetch?: typeof globalThis.fetch;
7
+ git?: Git;
8
+ claudeVersion?: () => Promise<string | undefined>;
9
+ launch?: (cwd: string, args: string[]) => Promise<number>;
10
+ out?: (line: string) => void;
11
+ /** Reads the link for "-" (default: standard input). */
12
+ readLink?: () => Promise<string>;
13
+ }
14
+ /** Returns the process exit code. */
15
+ export declare function resumeCommand(argv: string[], deps?: ResumeDeps): Promise<number>;
16
+ /** Removes the link and its token, in every form they could be quoted, from a message. */
17
+ export declare function withoutLink(message: string, rawLink: string): string;
@@ -0,0 +1,176 @@
1
+ /**
2
+ * `wardby resume '<link>'`: continue a wardby coding run's Claude Code
3
+ * session on this machine. The link comes from the get_run_transcript MCP
4
+ * tool. Downloads and verifies the transcript, writes it under
5
+ * ~/.wardby/sessions/<runId>/, checks out the run's branch, and starts
6
+ * `claude --resume` there with the stand-in tool server.
7
+ *
8
+ * Runs without a database or any server configuration. Output never
9
+ * includes the link (it is a credential until it expires).
10
+ */
11
+ import { parseArgs } from "node:util";
12
+ import { createInterface } from "node:readline";
13
+ import { downloadTranscript, isLoopbackLink, parseResumeLink, ResumeError } from "./download.js";
14
+ import { writeSessionFile } from "./session-file.js";
15
+ import { prepareCheckout } from "./checkout.js";
16
+ import { WORKER_WORKSPACE, claudeArgs, claudeVersion, launchClaude, mcpConfig, moveNote, parseClaudeVersion, printableCommand, UNKNOWN_VERSION_NOTE, writeMcpConfig, } from "./launch.js";
17
+ export const RESUME_USAGE = `usage: wardby resume - [--dir <path> | --here] [--force] [--print]
18
+ wardby resume '<link>' [options]
19
+
20
+ Continue a wardby coding run's Claude Code session on this machine. Get the
21
+ link (valid for 10 minutes) from the get_run_transcript MCP tool. With "-",
22
+ paste the link when asked (or pipe it in): this keeps it out of your shell
23
+ history and the process list, where a link given as an argument stays while
24
+ Claude Code runs.
25
+
26
+ --dir <path> Check the run out here (default: a sibling <repo>-run-<id>)
27
+ --here Use the current directory as it is; no checkout
28
+ --force Replace a different session file already imported for this run
29
+ --print Print the claude command instead of starting it`;
30
+ /** Largest link read from standard input. */
31
+ const MAX_LINK_BYTES = 8192;
32
+ /** Reads the link from standard input: one pasted line on a terminal, else the piped text. */
33
+ async function readLinkFromStdin(out) {
34
+ if (process.stdin.isTTY) {
35
+ out("Paste the get_run_transcript link and press Enter:");
36
+ const rl = createInterface({ input: process.stdin, terminal: false });
37
+ try {
38
+ for await (const line of rl)
39
+ return line.slice(0, MAX_LINK_BYTES);
40
+ return "";
41
+ }
42
+ finally {
43
+ rl.close();
44
+ }
45
+ }
46
+ let text = "";
47
+ for await (const chunk of process.stdin) {
48
+ text += String(chunk);
49
+ if (text.length > MAX_LINK_BYTES)
50
+ throw new ResumeError("The link read from standard input is too long.");
51
+ }
52
+ return text;
53
+ }
54
+ /** Returns the process exit code. */
55
+ export async function resumeCommand(argv, deps = {}) {
56
+ const out = deps.out ?? ((line) => process.stderr.write(`${line}\n`));
57
+ let parsed;
58
+ try {
59
+ parsed = parseArgs({
60
+ args: argv,
61
+ allowPositionals: true,
62
+ options: {
63
+ dir: { type: "string" },
64
+ here: { type: "boolean" },
65
+ force: { type: "boolean" },
66
+ print: { type: "boolean" },
67
+ help: { type: "boolean", short: "h" },
68
+ },
69
+ });
70
+ }
71
+ catch {
72
+ out(RESUME_USAGE);
73
+ return 2;
74
+ }
75
+ const { values, positionals } = parsed;
76
+ if (values.help) {
77
+ out(RESUME_USAGE);
78
+ return 0;
79
+ }
80
+ if (positionals.length !== 1 || (values.dir !== undefined && values.here)) {
81
+ out(RESUME_USAGE);
82
+ return 2;
83
+ }
84
+ const cwd = deps.cwd ?? process.cwd();
85
+ let rawLink = positionals[0];
86
+ try {
87
+ if (rawLink === "-")
88
+ rawLink = (await (deps.readLink ?? (() => readLinkFromStdin(out)))()).trim();
89
+ const link = parseResumeLink(rawLink);
90
+ out(`Downloading the transcript from ${link.origin} ...`);
91
+ const transcript = await downloadTranscript(link, deps.fetch);
92
+ const { meta } = transcript;
93
+ if (meta.provider !== "claude-code") {
94
+ throw new ResumeError(`Resuming ${meta.provider} runs locally is not supported yet.`);
95
+ }
96
+ // Check out first, so a refused checkout leaves nothing behind.
97
+ const checkout = await prepareCheckout(meta, {
98
+ cwd,
99
+ dir: values.dir,
100
+ here: values.here,
101
+ git: deps.git,
102
+ linkIsLoopback: isLoopbackLink(link),
103
+ });
104
+ const session = await writeSessionFile(transcript, { root: deps.sessionsRoot, force: values.force });
105
+ const from = WORKER_WORKSPACE;
106
+ const configPath = await writeMcpConfig(session.dir, mcpConfig({ checkout: checkout.dir, from }));
107
+ const versionText = await (deps.claudeVersion ?? claudeVersion)();
108
+ const version = versionText ? parseClaudeVersion(versionText) : undefined;
109
+ const args = claudeArgs({
110
+ sessionFile: session.path,
111
+ mcpConfigPath: configPath,
112
+ note: moveNote({
113
+ runId: meta.runId,
114
+ ref: checkout.ref,
115
+ from,
116
+ checkout: checkout.dir,
117
+ // prepareCheckout checks out the base commit only when the run's branch is missing.
118
+ runChanges: checkout.outcome === "here" ? undefined : checkout.ref !== meta.baseSha,
119
+ }),
120
+ version,
121
+ });
122
+ out(`Run: ${meta.runId}`);
123
+ out(`Session file: ${session.path}` +
124
+ (session.outcome === "same"
125
+ ? " (already imported)"
126
+ : session.outcome === "continued"
127
+ ? " (kept: it holds your local continuation)"
128
+ : session.outcome === "replaced"
129
+ ? " (replaced)"
130
+ : ""));
131
+ out(`MCP config: ${configPath}`);
132
+ out(`Checkout: ${checkout.dir} at ${checkout.ref}` +
133
+ (checkout.outcome === "reused" ? " (existing worktree reused)" : checkout.outcome === "here" ? " (as is)" : ""));
134
+ for (const warning of checkout.warnings)
135
+ out(`Warning: ${warning}`);
136
+ if (!version)
137
+ out(`Note: ${UNKNOWN_VERSION_NOTE}`);
138
+ out(`To remove the import later: delete ${session.dir}${checkout.outcome === "created" ? ` and run git worktree remove ${checkout.dir}` : ""}.`);
139
+ const command = printableCommand(checkout.dir, args);
140
+ if (values.print || !versionText) {
141
+ if (!versionText && !values.print)
142
+ out("Claude Code (claude) was not found on PATH. Install it, then run:");
143
+ process.stdout.write(`${command}\n`);
144
+ return 0;
145
+ }
146
+ out("Starting Claude Code ...");
147
+ return await (deps.launch ?? launchClaude)(checkout.dir, args);
148
+ }
149
+ catch (error) {
150
+ if (error instanceof ResumeError) {
151
+ out(`wardby resume: ${error.message}`);
152
+ return 1;
153
+ }
154
+ // Unexpected (a file system or git failure): its message, with the link removed by exact value.
155
+ out(`wardby resume: ${withoutLink(error instanceof Error ? error.message : String(error), rawLink)}`);
156
+ return 1;
157
+ }
158
+ }
159
+ /** Removes the link and its token, in every form they could be quoted, from a message. */
160
+ export function withoutLink(message, rawLink) {
161
+ const values = new Set([rawLink, rawLink.trim()]);
162
+ try {
163
+ const token = new URL(rawLink.trim()).searchParams.get("t");
164
+ if (token)
165
+ for (const v of [token, encodeURIComponent(token)])
166
+ values.add(v);
167
+ }
168
+ catch {
169
+ // Not a URL: only the raw value can appear.
170
+ }
171
+ let result = message;
172
+ for (const value of [...values].filter(Boolean).sort((a, b) => b.length - a.length)) {
173
+ result = result.split(value).join("[link]");
174
+ }
175
+ return result;
176
+ }
@@ -0,0 +1,20 @@
1
+ import { type TranscriptDownloadMeta } from "../download-protocol.js";
2
+ export declare class ResumeError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export type TranscriptMeta = TranscriptDownloadMeta;
6
+ export interface DownloadedTranscript {
7
+ meta: TranscriptMeta;
8
+ /** The stored object: gzip bytes, verified against the server's sha256. */
9
+ gzip: Buffer;
10
+ }
11
+ /** Whether the link points at this machine. */
12
+ export declare function isLoopbackLink(link: URL): boolean;
13
+ /** Checks the link's shape without echoing it. */
14
+ export declare function parseResumeLink(raw: string): URL;
15
+ export declare function downloadTranscript(link: URL, fetchImpl?: typeof globalThis.fetch, maxBytes?: number): Promise<DownloadedTranscript>;
16
+ /**
17
+ * Reads a response body up to `max` bytes, streaming, so a missing or false Content-Length cannot
18
+ * make it read an unbounded body. Refuses a Content-Length that is not a whole number.
19
+ */
20
+ export declare function readBounded(res: Response, max: number): Promise<Buffer>;
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Downloads a run transcript from a get_run_transcript link and verifies it.
3
+ *
4
+ * The link is a bearer credential: it is only ever sent to the server it
5
+ * names, over HTTPS (plain HTTP only to this machine's loopback, where a
6
+ * stdio MCP server serves it), and no message here quotes it.
7
+ */
8
+ import { createHash } from "node:crypto";
9
+ import { RUN_TRANSCRIPT_DOWNLOAD_PATH as DOWNLOAD_PATH, TRANSCRIPT_META_HEADER as META_HEADER, TRANSCRIPT_SESSION_HEADER as SESSION_HEADER, TRANSCRIPT_SHA256_HEADER as SHA256_HEADER, } from "../download-protocol.js";
10
+ /** Above the server's largest stored transcript (64 MiB before compression). */
11
+ const MAX_DOWNLOAD_BYTES = 80 * 1024 * 1024;
12
+ const SESSION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13
+ /** Run ids are cuids; anything else is refused before it names a path. */
14
+ const RUN_ID = /^[a-z0-9]{8,64}$/i;
15
+ const SHA256 = /^[0-9a-f]{64}$/;
16
+ export class ResumeError extends Error {
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = "ResumeError";
20
+ }
21
+ }
22
+ const LOOPBACK = new Set(["127.0.0.1", "localhost", "[::1]"]);
23
+ /** Largest refusal body read (a JSON error code). */
24
+ const MAX_ERROR_BYTES = 4096;
25
+ const PROVIDER = /^[a-z0-9-]{1,40}$/;
26
+ /** C0, DEL and C1 controls: never printed from server data (terminal escapes). */
27
+ // eslint-disable-next-line no-control-regex -- refusing untrusted control characters.
28
+ const CONTROL = /[\u0000-\u001f\u007f-\u009f]/;
29
+ /** Whether the link points at this machine. */
30
+ export function isLoopbackLink(link) {
31
+ return LOOPBACK.has(link.hostname);
32
+ }
33
+ /** Checks the link's shape without echoing it. */
34
+ export function parseResumeLink(raw) {
35
+ let url;
36
+ try {
37
+ url = new URL(raw.trim());
38
+ }
39
+ catch {
40
+ throw new ResumeError("That is not a get_run_transcript download link. Copy the whole link from the tool's result.");
41
+ }
42
+ const secure = url.protocol === "https:" || (url.protocol === "http:" && LOOPBACK.has(url.hostname));
43
+ if (!secure) {
44
+ throw new ResumeError("The download link must use https (or http to this machine). Refusing to send it over plain http.");
45
+ }
46
+ if (url.username || url.password || !url.pathname.endsWith(DOWNLOAD_PATH) || !url.searchParams.get("t")) {
47
+ throw new ResumeError("That is not a get_run_transcript download link. Copy the whole link from the tool's result.");
48
+ }
49
+ return url;
50
+ }
51
+ const REFUSALS = {
52
+ link_invalid: "The link is invalid or has expired (links work for 10 minutes). Call get_run_transcript again for a new one.",
53
+ not_found: "The server has no transcript you can read for this run.",
54
+ transcript_expired: "The run's transcript has been deleted after the server's retention period.",
55
+ transcript_unavailable: "The server could not read the stored transcript. Try again later, or ask your operator.",
56
+ transcript_corrupt: "The stored transcript no longer matches what was recorded; the server refused to send it.",
57
+ };
58
+ function parseMeta(header) {
59
+ let meta;
60
+ try {
61
+ meta = JSON.parse(Buffer.from(header ?? "", "base64url").toString("utf8"));
62
+ }
63
+ catch {
64
+ throw new ResumeError("The server's response is missing the run's details. Is the server running a matching wardby version?");
65
+ }
66
+ // Every string here may be printed or reach git: no control characters.
67
+ const str = (v) => typeof v === "string" && !CONTROL.test(v);
68
+ const optional = (v) => v === null || str(v);
69
+ if (!meta ||
70
+ !str(meta.runId) ||
71
+ !RUN_ID.test(meta.runId) ||
72
+ !str(meta.sessionId) ||
73
+ !SESSION_ID.test(meta.sessionId) ||
74
+ !str(meta.provider) ||
75
+ !PROVIDER.test(meta.provider) ||
76
+ !str(meta.repository) ||
77
+ !str(meta.headRef) ||
78
+ !optional(meta.resultBranch) ||
79
+ !optional(meta.baseSha) ||
80
+ !str(meta.sha256) ||
81
+ !SHA256.test(meta.sha256)) {
82
+ throw new ResumeError("The server's response has invalid run details.");
83
+ }
84
+ return meta;
85
+ }
86
+ export async function downloadTranscript(link, fetchImpl = globalThis.fetch, maxBytes = MAX_DOWNLOAD_BYTES) {
87
+ let res;
88
+ try {
89
+ res = await fetchImpl(link, { redirect: "error", headers: { accept: "application/gzip" } });
90
+ }
91
+ catch {
92
+ throw new ResumeError(`Could not reach ${link.origin}. Check your connection (for a stdio MCP server: is it still running?).`);
93
+ }
94
+ if (!res.ok) {
95
+ let code = "";
96
+ try {
97
+ const body = await readBounded(res, MAX_ERROR_BYTES);
98
+ code = JSON.parse(body.toString("utf8")).error;
99
+ }
100
+ catch {
101
+ // Not a wardby refusal body.
102
+ }
103
+ const message = typeof code === "string" && Object.hasOwn(REFUSALS, code) ? REFUSALS[code] : undefined;
104
+ throw new ResumeError(message ?? `The server refused the download (HTTP ${res.status}).`);
105
+ }
106
+ const gzip = await readBounded(res, maxBytes);
107
+ const meta = parseMeta(res.headers.get(META_HEADER));
108
+ const sha = createHash("sha256").update(gzip).digest("hex");
109
+ if (res.headers.get(SHA256_HEADER) !== meta.sha256 || sha !== meta.sha256) {
110
+ throw new ResumeError("The downloaded transcript does not match the server's checksum. Nothing was written; try again.");
111
+ }
112
+ if (res.headers.get(SESSION_HEADER) !== meta.sessionId) {
113
+ throw new ResumeError("The server's response has invalid run details.");
114
+ }
115
+ return { meta, gzip };
116
+ }
117
+ /**
118
+ * Reads a response body up to `max` bytes, streaming, so a missing or false Content-Length cannot
119
+ * make it read an unbounded body. Refuses a Content-Length that is not a whole number.
120
+ */
121
+ export async function readBounded(res, max) {
122
+ const declared = res.headers.get("content-length");
123
+ if (declared !== null && !/^\d+$/.test(declared.trim())) {
124
+ throw new ResumeError("The server's response has an invalid length.");
125
+ }
126
+ if (declared !== null && Number(declared) > max) {
127
+ await res.body?.cancel().catch(() => undefined);
128
+ throw new ResumeError("The transcript is larger than wardby resume accepts.");
129
+ }
130
+ if (!res.body)
131
+ return Buffer.alloc(0);
132
+ const reader = res.body.getReader();
133
+ const chunks = [];
134
+ let total = 0;
135
+ for (;;) {
136
+ let chunk;
137
+ try {
138
+ chunk = await reader.read();
139
+ }
140
+ catch {
141
+ throw new ResumeError("The download was interrupted. Try again.");
142
+ }
143
+ if (chunk.done || !chunk.value)
144
+ break;
145
+ total += chunk.value.byteLength;
146
+ if (total > max) {
147
+ await reader.cancel().catch(() => undefined);
148
+ throw new ResumeError("The transcript is larger than wardby resume accepts.");
149
+ }
150
+ chunks.push(chunk.value);
151
+ }
152
+ return Buffer.concat(chunks);
153
+ }
@@ -0,0 +1,38 @@
1
+ /** Where the run's commands ran in the worker (run_command's workspace, claude-tool-runner/main.mjs). */
2
+ export declare const WORKER_WORKSPACE = "/workspace";
3
+ /** This install's wardby entry point, for the MCP config to start the stand-in with. */
4
+ export declare function wardbyBinPath(): string;
5
+ /**
6
+ * `runChanges`: true when the checkout is at the run's branch, false when it fell back to the base
7
+ * commit, undefined for --here (the importer did not choose what is checked out).
8
+ */
9
+ export declare function moveNote(opts: {
10
+ runId: string;
11
+ ref: string;
12
+ from: string;
13
+ checkout: string;
14
+ runChanges?: boolean;
15
+ }): string;
16
+ export declare function mcpConfig(opts: {
17
+ checkout: string;
18
+ from: string;
19
+ node?: string;
20
+ bin?: string;
21
+ }): unknown;
22
+ /** Writes the MCP config next to the session file (mode 0600, atomically). */
23
+ export declare function writeMcpConfig(dir: string, config: unknown): Promise<string>;
24
+ export declare function parseClaudeVersion(output: string): [number, number, number] | undefined;
25
+ /** `claude --version`, or undefined when claude is not on PATH. */
26
+ export declare function claudeVersion(): Promise<string | undefined>;
27
+ export declare const UNKNOWN_VERSION_NOTE = "Could not read the Claude Code version: the command includes --system-prompt-snapshot off (Claude Code 2.1.257 or later); remove that flag for an older version.";
28
+ export declare function claudeArgs(opts: {
29
+ sessionFile: string;
30
+ mcpConfigPath: string;
31
+ note: string;
32
+ version: [number, number, number] | undefined;
33
+ }): string[];
34
+ /** POSIX shell quoting, for printing a command the user can paste. */
35
+ export declare function shellQuote(arg: string): string;
36
+ export declare function printableCommand(cwd: string, args: string[]): string;
37
+ /** Runs claude in the checkout with this terminal; resolves with its exit code. */
38
+ export declare function launchClaude(cwd: string, args: string[]): Promise<number>;