lastlight 0.15.0 → 0.16.1

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 (382) hide show
  1. package/README.md +71 -692
  2. package/dist/cli-config.js.map +1 -0
  3. package/dist/cli-format.js.map +1 -0
  4. package/dist/{cli/cli-server.d.ts → cli-server.d.ts} +26 -1
  5. package/dist/{cli/cli-server.js → cli-server.js} +40 -5
  6. package/dist/cli-server.js.map +1 -0
  7. package/dist/cli-timeline.js.map +1 -0
  8. package/dist/{cli/cli.js → cli.js} +4 -3
  9. package/dist/cli.js.map +1 -0
  10. package/dist/{cli/fork-cli.d.ts → fork-cli.d.ts} +3 -3
  11. package/dist/{cli/fork-cli.js → fork-cli.js} +28 -27
  12. package/dist/fork-cli.js.map +1 -0
  13. package/dist/{cli/oauth-cli.js → oauth-cli.js} +1 -1
  14. package/dist/oauth-cli.js.map +1 -0
  15. package/dist/{cli/setup.js → setup.js} +10 -4
  16. package/dist/setup.js.map +1 -0
  17. package/dist/{cli/skills-install.d.ts → skills-install.d.ts} +6 -0
  18. package/dist/{cli/skills-install.js → skills-install.js} +6 -2
  19. package/dist/skills-install.js.map +1 -0
  20. package/package.json +20 -65
  21. package/plugins/lastlight/.claude-plugin/plugin.json +1 -1
  22. package/agent-context/rules.md +0 -80
  23. package/agent-context/security.md +0 -69
  24. package/agent-context/soul.md +0 -21
  25. package/config/default.yaml +0 -119
  26. package/deploy/.env.production.example +0 -100
  27. package/deploy/entrypoint.sh +0 -82
  28. package/deploy/native/README.md +0 -160
  29. package/deploy/native/install.sh +0 -110
  30. package/deploy/native/lastlight.env.example +0 -95
  31. package/deploy/native/lastlight.service +0 -50
  32. package/deploy/sandbox-entrypoint.sh +0 -93
  33. package/dist/admin/auth.d.ts +0 -51
  34. package/dist/admin/auth.js +0 -121
  35. package/dist/admin/auth.js.map +0 -1
  36. package/dist/admin/chat-session-reader.d.ts +0 -39
  37. package/dist/admin/chat-session-reader.js +0 -84
  38. package/dist/admin/chat-session-reader.js.map +0 -1
  39. package/dist/admin/docker.d.ts +0 -61
  40. package/dist/admin/docker.js +0 -187
  41. package/dist/admin/docker.js.map +0 -1
  42. package/dist/admin/index.d.ts +0 -9
  43. package/dist/admin/index.js +0 -59
  44. package/dist/admin/index.js.map +0 -1
  45. package/dist/admin/routes.d.ts +0 -81
  46. package/dist/admin/routes.js +0 -1381
  47. package/dist/admin/routes.js.map +0 -1
  48. package/dist/admin/sessions.d.ts +0 -89
  49. package/dist/admin/sessions.js +0 -204
  50. package/dist/admin/sessions.js.map +0 -1
  51. package/dist/admin/tail.d.ts +0 -12
  52. package/dist/admin/tail.js +0 -145
  53. package/dist/admin/tail.js.map +0 -1
  54. package/dist/admin/version.d.ts +0 -22
  55. package/dist/admin/version.js +0 -92
  56. package/dist/admin/version.js.map +0 -1
  57. package/dist/cli/cli-config.js.map +0 -1
  58. package/dist/cli/cli-format.js.map +0 -1
  59. package/dist/cli/cli-server.js.map +0 -1
  60. package/dist/cli/cli-timeline.js.map +0 -1
  61. package/dist/cli/cli.js.map +0 -1
  62. package/dist/cli/fork-cli.js.map +0 -1
  63. package/dist/cli/oauth-cli.js.map +0 -1
  64. package/dist/cli/setup.js.map +0 -1
  65. package/dist/cli/skills-install.js.map +0 -1
  66. package/dist/config/config-resolve.d.ts +0 -28
  67. package/dist/config/config-resolve.js +0 -47
  68. package/dist/config/config-resolve.js.map +0 -1
  69. package/dist/config/config.d.ts +0 -157
  70. package/dist/config/config.js +0 -581
  71. package/dist/config/config.js.map +0 -1
  72. package/dist/config/core-pin.d.ts +0 -16
  73. package/dist/config/core-pin.js +0 -85
  74. package/dist/config/core-pin.js.map +0 -1
  75. package/dist/config/overlay-assets.d.ts +0 -20
  76. package/dist/config/overlay-assets.js +0 -114
  77. package/dist/config/overlay-assets.js.map +0 -1
  78. package/dist/config/overlay-bootstrap.d.ts +0 -44
  79. package/dist/config/overlay-bootstrap.js +0 -304
  80. package/dist/config/overlay-bootstrap.js.map +0 -1
  81. package/dist/connectors/github-webhook.d.ts +0 -45
  82. package/dist/connectors/github-webhook.js +0 -321
  83. package/dist/connectors/github-webhook.js.map +0 -1
  84. package/dist/connectors/index.d.ts +0 -18
  85. package/dist/connectors/index.js +0 -41
  86. package/dist/connectors/index.js.map +0 -1
  87. package/dist/connectors/messaging/base.d.ts +0 -42
  88. package/dist/connectors/messaging/base.js +0 -139
  89. package/dist/connectors/messaging/base.js.map +0 -1
  90. package/dist/connectors/messaging/delivery.d.ts +0 -14
  91. package/dist/connectors/messaging/delivery.js +0 -38
  92. package/dist/connectors/messaging/delivery.js.map +0 -1
  93. package/dist/connectors/messaging/index.d.ts +0 -4
  94. package/dist/connectors/messaging/index.js +0 -4
  95. package/dist/connectors/messaging/index.js.map +0 -1
  96. package/dist/connectors/messaging/session-manager.d.ts +0 -53
  97. package/dist/connectors/messaging/session-manager.js +0 -255
  98. package/dist/connectors/messaging/session-manager.js.map +0 -1
  99. package/dist/connectors/messaging/types.d.ts +0 -58
  100. package/dist/connectors/messaging/types.js +0 -7
  101. package/dist/connectors/messaging/types.js.map +0 -1
  102. package/dist/connectors/slack/connector.d.ts +0 -100
  103. package/dist/connectors/slack/connector.js +0 -341
  104. package/dist/connectors/slack/connector.js.map +0 -1
  105. package/dist/connectors/slack/index.d.ts +0 -2
  106. package/dist/connectors/slack/index.js +0 -3
  107. package/dist/connectors/slack/index.js.map +0 -1
  108. package/dist/connectors/slack/mrkdwn.d.ts +0 -8
  109. package/dist/connectors/slack/mrkdwn.js +0 -123
  110. package/dist/connectors/slack/mrkdwn.js.map +0 -1
  111. package/dist/connectors/types.d.ts +0 -61
  112. package/dist/connectors/types.js +0 -2
  113. package/dist/connectors/types.js.map +0 -1
  114. package/dist/cron/fanout.d.ts +0 -33
  115. package/dist/cron/fanout.js +0 -55
  116. package/dist/cron/fanout.js.map +0 -1
  117. package/dist/cron/jobs.d.ts +0 -18
  118. package/dist/cron/jobs.js +0 -37
  119. package/dist/cron/jobs.js.map +0 -1
  120. package/dist/cron/scheduler.d.ts +0 -45
  121. package/dist/cron/scheduler.js +0 -105
  122. package/dist/cron/scheduler.js.map +0 -1
  123. package/dist/engine/agent-executor.d.ts +0 -34
  124. package/dist/engine/agent-executor.js +0 -246
  125. package/dist/engine/agent-executor.js.map +0 -1
  126. package/dist/engine/chat/chat-runner.d.ts +0 -132
  127. package/dist/engine/chat/chat-runner.js +0 -424
  128. package/dist/engine/chat/chat-runner.js.map +0 -1
  129. package/dist/engine/chat/chat-skills.d.ts +0 -45
  130. package/dist/engine/chat/chat-skills.js +0 -184
  131. package/dist/engine/chat/chat-skills.js.map +0 -1
  132. package/dist/engine/chat/chat.d.ts +0 -54
  133. package/dist/engine/chat/chat.js +0 -316
  134. package/dist/engine/chat/chat.js.map +0 -1
  135. package/dist/engine/chat/message-batcher.d.ts +0 -32
  136. package/dist/engine/chat/message-batcher.js +0 -109
  137. package/dist/engine/chat/message-batcher.js.map +0 -1
  138. package/dist/engine/dispatcher.d.ts +0 -73
  139. package/dist/engine/dispatcher.js +0 -663
  140. package/dist/engine/dispatcher.js.map +0 -1
  141. package/dist/engine/event-shim.d.ts +0 -117
  142. package/dist/engine/event-shim.js +0 -435
  143. package/dist/engine/event-shim.js.map +0 -1
  144. package/dist/engine/executors/orchestrator.d.ts +0 -81
  145. package/dist/engine/executors/orchestrator.js +0 -365
  146. package/dist/engine/executors/orchestrator.js.map +0 -1
  147. package/dist/engine/executors/shared.d.ts +0 -189
  148. package/dist/engine/executors/shared.js +0 -616
  149. package/dist/engine/executors/shared.js.map +0 -1
  150. package/dist/engine/github/git-auth.d.ts +0 -62
  151. package/dist/engine/github/git-auth.js +0 -161
  152. package/dist/engine/github/git-auth.js.map +0 -1
  153. package/dist/engine/github/github-app-client.d.ts +0 -23
  154. package/dist/engine/github/github-app-client.js +0 -33
  155. package/dist/engine/github/github-app-client.js.map +0 -1
  156. package/dist/engine/github/github-tools.d.ts +0 -18
  157. package/dist/engine/github/github-tools.js +0 -263
  158. package/dist/engine/github/github-tools.js.map +0 -1
  159. package/dist/engine/github/github.d.ts +0 -1193
  160. package/dist/engine/github/github.js +0 -357
  161. package/dist/engine/github/github.js.map +0 -1
  162. package/dist/engine/github/profiles.d.ts +0 -279
  163. package/dist/engine/github/profiles.js +0 -42
  164. package/dist/engine/github/profiles.js.map +0 -1
  165. package/dist/engine/github/review-poster.d.ts +0 -98
  166. package/dist/engine/github/review-poster.js +0 -177
  167. package/dist/engine/github/review-poster.js.map +0 -1
  168. package/dist/engine/llm.d.ts +0 -79
  169. package/dist/engine/llm.js +0 -269
  170. package/dist/engine/llm.js.map +0 -1
  171. package/dist/engine/oauth.d.ts +0 -43
  172. package/dist/engine/oauth.js +0 -103
  173. package/dist/engine/oauth.js.map +0 -1
  174. package/dist/engine/router.d.ts +0 -29
  175. package/dist/engine/router.js +0 -680
  176. package/dist/engine/router.js.map +0 -1
  177. package/dist/engine/screen/classifier.d.ts +0 -93
  178. package/dist/engine/screen/classifier.js +0 -215
  179. package/dist/engine/screen/classifier.js.map +0 -1
  180. package/dist/engine/screen/screen.d.ts +0 -41
  181. package/dist/engine/screen/screen.js +0 -93
  182. package/dist/engine/screen/screen.js.map +0 -1
  183. package/dist/evals-api.d.ts +0 -24
  184. package/dist/evals-api.js +0 -22
  185. package/dist/evals-api.js.map +0 -1
  186. package/dist/index.d.ts +0 -1
  187. package/dist/index.js +0 -923
  188. package/dist/index.js.map +0 -1
  189. package/dist/managed-repos.d.ts +0 -30
  190. package/dist/managed-repos.js +0 -72
  191. package/dist/managed-repos.js.map +0 -1
  192. package/dist/notify/index.d.ts +0 -15
  193. package/dist/notify/index.js +0 -6
  194. package/dist/notify/index.js.map +0 -1
  195. package/dist/notify/model.d.ts +0 -57
  196. package/dist/notify/model.js +0 -89
  197. package/dist/notify/model.js.map +0 -1
  198. package/dist/notify/notifier.d.ts +0 -17
  199. package/dist/notify/notifier.js +0 -87
  200. package/dist/notify/notifier.js.map +0 -1
  201. package/dist/notify/render.d.ts +0 -21
  202. package/dist/notify/render.js +0 -59
  203. package/dist/notify/render.js.map +0 -1
  204. package/dist/notify/transports/github.d.ts +0 -26
  205. package/dist/notify/transports/github.js +0 -26
  206. package/dist/notify/transports/github.js.map +0 -1
  207. package/dist/notify/transports/slack.d.ts +0 -26
  208. package/dist/notify/transports/slack.js +0 -28
  209. package/dist/notify/transports/slack.js.map +0 -1
  210. package/dist/notify/types.d.ts +0 -95
  211. package/dist/notify/types.js +0 -16
  212. package/dist/notify/types.js.map +0 -1
  213. package/dist/providers.d.ts +0 -125
  214. package/dist/providers.js +0 -279
  215. package/dist/providers.js.map +0 -1
  216. package/dist/sandbox/docker.d.ts +0 -180
  217. package/dist/sandbox/docker.js +0 -517
  218. package/dist/sandbox/docker.js.map +0 -1
  219. package/dist/sandbox/egress-allowlist.d.ts +0 -74
  220. package/dist/sandbox/egress-allowlist.js +0 -164
  221. package/dist/sandbox/egress-allowlist.js.map +0 -1
  222. package/dist/sandbox/egress-firewall-config.d.ts +0 -127
  223. package/dist/sandbox/egress-firewall-config.js +0 -434
  224. package/dist/sandbox/egress-firewall-config.js.map +0 -1
  225. package/dist/sandbox/images.d.ts +0 -23
  226. package/dist/sandbox/images.js +0 -55
  227. package/dist/sandbox/images.js.map +0 -1
  228. package/dist/sandbox/index.d.ts +0 -112
  229. package/dist/sandbox/index.js +0 -332
  230. package/dist/sandbox/index.js.map +0 -1
  231. package/dist/sandbox/sandbox.d.ts +0 -214
  232. package/dist/sandbox/sandbox.js +0 -453
  233. package/dist/sandbox/sandbox.js.map +0 -1
  234. package/dist/sandbox/smol.d.ts +0 -162
  235. package/dist/sandbox/smol.js +0 -485
  236. package/dist/sandbox/smol.js.map +0 -1
  237. package/dist/session-log.d.ts +0 -63
  238. package/dist/session-log.js +0 -290
  239. package/dist/session-log.js.map +0 -1
  240. package/dist/state/approval-store.d.ts +0 -88
  241. package/dist/state/approval-store.js +0 -149
  242. package/dist/state/approval-store.js.map +0 -1
  243. package/dist/state/build-assets.d.ts +0 -50
  244. package/dist/state/build-assets.js +0 -154
  245. package/dist/state/build-assets.js.map +0 -1
  246. package/dist/state/db.d.ts +0 -81
  247. package/dist/state/db.js +0 -155
  248. package/dist/state/db.js.map +0 -1
  249. package/dist/state/execution-store.d.ts +0 -257
  250. package/dist/state/execution-store.js +0 -527
  251. package/dist/state/execution-store.js.map +0 -1
  252. package/dist/state/migrate.d.ts +0 -15
  253. package/dist/state/migrate.js +0 -175
  254. package/dist/state/migrate.js.map +0 -1
  255. package/dist/state/workflow-run-store.d.ts +0 -216
  256. package/dist/state/workflow-run-store.js +0 -403
  257. package/dist/state/workflow-run-store.js.map +0 -1
  258. package/dist/telemetry/index.d.ts +0 -38
  259. package/dist/telemetry/index.js +0 -253
  260. package/dist/telemetry/index.js.map +0 -1
  261. package/dist/telemetry/pi-events.d.ts +0 -12
  262. package/dist/telemetry/pi-events.js +0 -134
  263. package/dist/telemetry/pi-events.js.map +0 -1
  264. package/dist/workflows/dag.d.ts +0 -37
  265. package/dist/workflows/dag.js +0 -118
  266. package/dist/workflows/dag.js.map +0 -1
  267. package/dist/workflows/loader.d.ts +0 -53
  268. package/dist/workflows/loader.js +0 -421
  269. package/dist/workflows/loader.js.map +0 -1
  270. package/dist/workflows/loop-eval.d.ts +0 -28
  271. package/dist/workflows/loop-eval.js +0 -74
  272. package/dist/workflows/loop-eval.js.map +0 -1
  273. package/dist/workflows/phase-executor.d.ts +0 -215
  274. package/dist/workflows/phase-executor.js +0 -1144
  275. package/dist/workflows/phase-executor.js.map +0 -1
  276. package/dist/workflows/phase-ref.d.ts +0 -50
  277. package/dist/workflows/phase-ref.js +0 -91
  278. package/dist/workflows/phase-ref.js.map +0 -1
  279. package/dist/workflows/resume.d.ts +0 -58
  280. package/dist/workflows/resume.js +0 -313
  281. package/dist/workflows/resume.js.map +0 -1
  282. package/dist/workflows/runner.d.ts +0 -63
  283. package/dist/workflows/runner.js +0 -364
  284. package/dist/workflows/runner.js.map +0 -1
  285. package/dist/workflows/schema.d.ts +0 -344
  286. package/dist/workflows/schema.js +0 -460
  287. package/dist/workflows/schema.js.map +0 -1
  288. package/dist/workflows/simple.d.ts +0 -90
  289. package/dist/workflows/simple.js +0 -393
  290. package/dist/workflows/simple.js.map +0 -1
  291. package/dist/workflows/target-policy.d.ts +0 -74
  292. package/dist/workflows/target-policy.js +0 -80
  293. package/dist/workflows/target-policy.js.map +0 -1
  294. package/dist/workflows/templates.d.ts +0 -88
  295. package/dist/workflows/templates.js +0 -127
  296. package/dist/workflows/templates.js.map +0 -1
  297. package/dist/workflows/triggers.d.ts +0 -21
  298. package/dist/workflows/triggers.js +0 -45
  299. package/dist/workflows/triggers.js.map +0 -1
  300. package/dist/workflows/verdict.d.ts +0 -19
  301. package/dist/workflows/verdict.js +0 -30
  302. package/dist/workflows/verdict.js.map +0 -1
  303. package/dist/worktree/manager.d.ts +0 -43
  304. package/dist/worktree/manager.js +0 -127
  305. package/dist/worktree/manager.js.map +0 -1
  306. package/docker-compose.yml +0 -274
  307. package/sandbox.Dockerfile +0 -68
  308. package/skills/README.md +0 -42
  309. package/skills/browser-qa/SKILL.md +0 -208
  310. package/skills/browser-qa/scripts/agent-browser.mjs +0 -531
  311. package/skills/building/SKILL.md +0 -95
  312. package/skills/chat/SKILL.md +0 -36
  313. package/skills/code-review/SKILL.md +0 -82
  314. package/skills/debug-production/SKILL.md +0 -108
  315. package/skills/demo/SKILL.md +0 -228
  316. package/skills/demo/scripts/compose-demo.sh +0 -243
  317. package/skills/issue-answer/SKILL.md +0 -91
  318. package/skills/issue-comment/SKILL.md +0 -49
  319. package/skills/issue-triage/SKILL.md +0 -149
  320. package/skills/issue-triage/references/AGENT-BRIEF.md +0 -65
  321. package/skills/pr-comment/SKILL.md +0 -64
  322. package/skills/pr-review/SKILL.md +0 -148
  323. package/skills/pr-review/references/findings-schema.md +0 -89
  324. package/skills/qa-test/SKILL.md +0 -97
  325. package/skills/repo-health/SKILL.md +0 -67
  326. package/skills/security-feedback/SKILL.md +0 -173
  327. package/skills/security-feedback/references/templates.md +0 -77
  328. package/skills/security-review/SKILL.md +0 -215
  329. package/skills/security-review/references/issue-format.md +0 -302
  330. package/skills/verify/SKILL.md +0 -118
  331. package/workflows/answer.yaml +0 -44
  332. package/workflows/build.yaml +0 -129
  333. package/workflows/cron-health.yaml +0 -6
  334. package/workflows/cron-review.yaml +0 -8
  335. package/workflows/cron-security.yaml +0 -6
  336. package/workflows/cron-triage.yaml +0 -8
  337. package/workflows/demo.yaml +0 -62
  338. package/workflows/examples/bash-smoke.yaml +0 -41
  339. package/workflows/examples/parallel-review.yaml +0 -36
  340. package/workflows/examples/tdd-loop.yaml +0 -17
  341. package/workflows/explore.yaml +0 -80
  342. package/workflows/issue-comment.yaml +0 -15
  343. package/workflows/issue-triage.yaml +0 -22
  344. package/workflows/pr-comment.yaml +0 -16
  345. package/workflows/pr-fix.yaml +0 -17
  346. package/workflows/pr-review.yaml +0 -50
  347. package/workflows/prompts/answer.md +0 -68
  348. package/workflows/prompts/architect.md +0 -44
  349. package/workflows/prompts/classifier.md +0 -60
  350. package/workflows/prompts/classify-adds-info.md +0 -17
  351. package/workflows/prompts/demo.md +0 -125
  352. package/workflows/prompts/executor.md +0 -42
  353. package/workflows/prompts/explore-ask.md +0 -99
  354. package/workflows/prompts/explore-publish.md +0 -31
  355. package/workflows/prompts/explore-read.md +0 -120
  356. package/workflows/prompts/explore-synthesize.md +0 -88
  357. package/workflows/prompts/fix.md +0 -18
  358. package/workflows/prompts/guardrails.md +0 -96
  359. package/workflows/prompts/pr-fix.md +0 -26
  360. package/workflows/prompts/pr.md +0 -39
  361. package/workflows/prompts/qa-browser.md +0 -95
  362. package/workflows/prompts/qa-synth.md +0 -44
  363. package/workflows/prompts/qa-test.md +0 -60
  364. package/workflows/prompts/re-reviewer.md +0 -33
  365. package/workflows/prompts/reviewer.md +0 -60
  366. package/workflows/prompts/verify-browser.md +0 -93
  367. package/workflows/prompts/verify-synth.md +0 -44
  368. package/workflows/prompts/verify.md +0 -63
  369. package/workflows/qa-test.yaml +0 -94
  370. package/workflows/repo-health.yaml +0 -15
  371. package/workflows/security-feedback.yaml +0 -25
  372. package/workflows/security-review.yaml +0 -37
  373. package/workflows/verify.yaml +0 -93
  374. /package/dist/{cli/cli-config.d.ts → cli-config.d.ts} +0 -0
  375. /package/dist/{cli/cli-config.js → cli-config.js} +0 -0
  376. /package/dist/{cli/cli-format.d.ts → cli-format.d.ts} +0 -0
  377. /package/dist/{cli/cli-format.js → cli-format.js} +0 -0
  378. /package/dist/{cli/cli-timeline.d.ts → cli-timeline.d.ts} +0 -0
  379. /package/dist/{cli/cli-timeline.js → cli-timeline.js} +0 -0
  380. /package/dist/{cli/cli.d.ts → cli.d.ts} +0 -0
  381. /package/dist/{cli/oauth-cli.d.ts → oauth-cli.d.ts} +0 -0
  382. /package/dist/{cli/setup.d.ts → setup.d.ts} +0 -0
@@ -1,332 +0,0 @@
1
- import { execFileSync } from "child_process";
2
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
3
- import { isAbsolute, join, relative, resolve, sep } from "path";
4
- import { DockerSandbox } from "./docker.js";
5
- import { SANDBOX_IMAGE, isSandboxAvailable } from "./images.js";
6
- export { DockerSandbox } from "./docker.js";
7
- export { SANDBOX_IMAGE, SANDBOX_IMAGE_QA, isSandboxAvailable, qaImageAvailable, } from "./images.js";
8
- /**
9
- * Clean up orphaned sandbox containers from previous runs.
10
- * Called on startup to remove containers that survived a harness restart.
11
- */
12
- export function cleanupOrphanedSandboxes() {
13
- try {
14
- const out = execFileSync("docker", [
15
- "ps", "-q", "--filter", "name=lastlight-sandbox",
16
- ], { encoding: "utf-8", timeout: 5000 });
17
- const ids = out.trim().split("\n").filter(Boolean);
18
- if (ids.length > 0) {
19
- console.log(`[sandbox] Cleaning up ${ids.length} orphaned sandbox container(s)`);
20
- execFileSync("docker", ["rm", "-f", ...ids], { stdio: "ignore", timeout: 15000 });
21
- }
22
- }
23
- catch {
24
- // Docker not available or no containers — fine
25
- }
26
- }
27
- /** Cached check — only probe Docker once per process */
28
- let _sandboxAvailable = null;
29
- export function sandboxAvailable() {
30
- if (_sandboxAvailable === null) {
31
- _sandboxAvailable = isSandboxAvailable();
32
- if (_sandboxAvailable) {
33
- console.log(`[sandbox] Docker sandbox available (image: ${SANDBOX_IMAGE})`);
34
- }
35
- else {
36
- console.log(`[sandbox] Docker not available — running agents directly`);
37
- }
38
- }
39
- return _sandboxAvailable;
40
- }
41
- function isWithinDir(parent, child) {
42
- return child === parent || child.startsWith(`${parent}${sep}`);
43
- }
44
- /**
45
- * Set up the per-task worktree directory (mkdir + optional pre-clone) without
46
- * touching Docker. Used by the non-docker sandbox modes (gondolin / none) where
47
- * agentic-pi runs in-process or in a VM rather than a container, but still
48
- * wants a per-task workspace cloned from the target branch.
49
- */
50
- export function setupTaskWorktree(opts) {
51
- const sandboxBase = resolve(opts.sandboxDir || join(opts.stateDir, "sandboxes"));
52
- mkdirSync(sandboxBase, { recursive: true });
53
- const workDir = resolve(sandboxBase, opts.taskId);
54
- if (!isWithinDir(sandboxBase, workDir)) {
55
- throw new Error(`Invalid taskId path escape attempt: ${opts.taskId}`);
56
- }
57
- mkdirSync(workDir, { recursive: true });
58
- if (opts.prePopulate) {
59
- prePopulateWorkspace(workDir, opts.prePopulate);
60
- }
61
- return workDir;
62
- }
63
- /**
64
- * Create a sandbox for a task. Returns the sandbox and a cleanup function.
65
- * If Docker is not available, returns null (caller should fall back to direct execution).
66
- */
67
- export async function createTaskSandbox(opts) {
68
- if (!sandboxAvailable())
69
- return null;
70
- const sandboxBase = resolve(opts.sandboxDir || join(opts.stateDir, "sandboxes"));
71
- mkdirSync(sandboxBase, { recursive: true });
72
- const workDir = resolve(sandboxBase, opts.taskId);
73
- if (!isWithinDir(sandboxBase, workDir)) {
74
- throw new Error(`Invalid taskId path escape attempt: ${opts.taskId}`);
75
- }
76
- mkdirSync(workDir, { recursive: true });
77
- if (opts.prePopulate) {
78
- prePopulateWorkspace(workDir, opts.prePopulate);
79
- }
80
- const sandbox = new DockerSandbox({
81
- imageName: opts.imageName || SANDBOX_IMAGE,
82
- env: opts.env || {},
83
- memoryLimit: process.env.SANDBOX_MEMORY_LIMIT || undefined,
84
- dnsIp: opts.dnsIp,
85
- });
86
- try {
87
- await sandbox.create({
88
- taskId: opts.taskId,
89
- worktreePath: workDir,
90
- workspaceMount: resolveWorkspaceMount(opts.stateDir, workDir),
91
- });
92
- return {
93
- sandbox,
94
- workDir,
95
- cleanup: () => sandbox.destroy(opts.taskId),
96
- };
97
- }
98
- catch (err) {
99
- console.warn(`[sandbox] Failed to create sandbox: ${err.message}`);
100
- return null;
101
- }
102
- }
103
- /**
104
- * Decide how the sandbox container should mount `/home/agent/workspace`.
105
- *
106
- * The harness writes the per-task workspace to `workDir`, which is always
107
- * under `stateDir` (`sandboxes/<taskId>/`). In production, `stateDir` is
108
- * served by a named docker volume mounted into the harness container. A
109
- * plain `-v workDir:/home/agent/workspace` bind makes the daemon resolve
110
- * `workDir` against the *host* filesystem, where the named volume's
111
- * content is not visible — docker silently creates an empty dir at that
112
- * host path and mounts it, so the sandbox sees an empty workspace and the
113
- * skills the harness staged are never reachable.
114
- *
115
- * In volume mode we ask docker for a `volume-subpath` mount instead, so
116
- * the sandbox sees exactly the harness's view. In path mode (local dev,
117
- * or any deployment where SANDBOX_DATA_VOLUME is a host path) a normal
118
- * bind is correct because both views point at the same FS path.
119
- *
120
- * Edge case: if `opts.sandboxDir` was overridden to live outside `stateDir`,
121
- * we can't carve a volume-subpath out of the data volume — fall back to
122
- * a bind mount. That keeps the no-data-volume dev path working; the
123
- * named-volume + custom-sandboxDir combination isn't currently used.
124
- */
125
- function resolveWorkspaceMount(stateDir, workDir) {
126
- const dataVolumeRaw = process.env.SANDBOX_DATA_VOLUME || "lastlight_agent-data";
127
- if (isPathLike(dataVolumeRaw)) {
128
- return { type: "bind", hostPath: workDir };
129
- }
130
- const rel = relative(resolve(stateDir), workDir);
131
- if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
132
- return { type: "bind", hostPath: workDir };
133
- }
134
- return { type: "volume-subpath", volume: dataVolumeRaw, subpath: rel };
135
- }
136
- function isPathLike(value) {
137
- return value.startsWith("/") ||
138
- value.startsWith("./") ||
139
- value.startsWith("../") ||
140
- value.startsWith("~");
141
- }
142
- /** Marker file (at the workspace root, outside the repo so `git clean` can't
143
- * touch it) recording which run last provisioned this workspace. */
144
- const RUN_MARKER = ".lastlight-run";
145
- /**
146
- * Clone the repo into `<workDir>/<repo>` at the given branch.
147
- *
148
- * Cases:
149
- * - **Fresh dir** (no `.git`): clone. `--depth 1 --single-branch` for
150
- * read-only workflows (`pre.shallow`), `--depth 50` otherwise. For
151
- * `recreateFromBase` the branch is cut from the default branch directly
152
- * (never `clone --branch <feature>`).
153
- * - **Same run revisiting the workspace** (`.git` exists, run marker matches
154
- * `pre.runId`): preserve — this is a later phase of the same run reading
155
- * what an earlier phase wrote (architect's `plan.md`, the reviewer's
156
- * checkout). No git ops.
157
- * - **A fresh run reusing an old per-target workspace** (`.git` exists, marker
158
- * differs/absent):
159
- * - default (pr-review / pr-fix): fetch + hard-reset to the remote branch +
160
- * `git clean` that **keeps `node_modules`** so the next `npm install` is
161
- * incremental (the re-review fast path from issue #107).
162
- * - `recreateFromBase` (build): delete the stale checkout and re-clone from
163
- * the default branch — a re-triggered incomplete build starts again off
164
- * current `main` (issue #153).
165
- */
166
- export { prePopulateWorkspace as __prePopulateWorkspaceForTest };
167
- export function prePopulateWorkspace(workDir, pre) {
168
- // Token shape is asserted in src/engine/git-auth.ts before we get here,
169
- // but re-check the narrow set here too — defense in depth, this string
170
- // crosses a process boundary into git's command line.
171
- if (!/^[A-Za-z0-9_-]+$/.test(pre.token)) {
172
- throw new Error("prePopulate: refusing to embed a token outside [A-Za-z0-9_-]");
173
- }
174
- const url = `https://x-access-token:${pre.token}@github.com/${pre.owner}/${pre.repo}.git`;
175
- // The agent's cwd is `workDir` (the workspace). The harness writes
176
- // `AGENTS.md` there, so cloning into the workDir root would collide.
177
- // Instead, clone into a `<repo>/` subdirectory — keeps the layout
178
- // consistent regardless of whether the harness or the agent did the
179
- // clone, and leaves room for `.lastlight/issue-N/` scratch space at
180
- // the workspace root.
181
- const repoDir = join(workDir, pre.repo);
182
- const markerPath = join(workDir, RUN_MARKER);
183
- const scrub = (s) => typeof s === "string" ? s.replaceAll(pre.token, "[REDACTED-TOKEN]") : "";
184
- // Repo dir might already exist — from a later phase of the same run, or a
185
- // *different* run reusing a stable per-target workspace (issue #107).
186
- if (existsSync(join(repoDir, ".git"))) {
187
- const lastRun = readMarker(markerPath);
188
- // Same run (or a caller that doesn't track runs): preserve the workspace
189
- // exactly — earlier phases may have written uncommitted scratch here.
190
- if (!pre.runId || lastRun === pre.runId) {
191
- console.log(`[sandbox] Pre-clone skipped: ${repoDir} already a git repo (same run).`);
192
- return;
193
- }
194
- if (pre.recreateFromBase) {
195
- // build (#153): a prior incomplete run left a checkout on a possibly
196
- // stale feature branch. Discard it and re-clone from the default branch
197
- // (below) so the re-triggered build starts again off current `main`.
198
- try {
199
- rmSync(repoDir, { recursive: true, force: true });
200
- console.log(`[sandbox] Recreating ${repoDir} from the default branch ` +
201
- `(discarded stale workspace from run ${lastRun ?? "unknown"}).`);
202
- }
203
- catch (err) {
204
- console.warn(`[sandbox] Failed to remove stale workspace ${repoDir} ` +
205
- `(${scrub(err?.message)}); attempting a fresh clone anyway.`);
206
- }
207
- // fall through to the recreate-from-base clone below.
208
- }
209
- else {
210
- // Different run reusing this PR's workspace — refresh in place.
211
- refreshExistingClone(repoDir, markerPath, pre);
212
- return;
213
- }
214
- }
215
- const start = Date.now();
216
- const depth = pre.shallow ? "1" : "50";
217
- const shallowArgs = pre.shallow ? ["--single-branch"] : [];
218
- // Recreate-from-base workflows (build) always cut their branch from the
219
- // default branch — never `clone --branch <feature>`, which would resurrect a
220
- // stale *pushed* feature branch from an earlier incomplete run (#153).
221
- if (pre.recreateFromBase) {
222
- cloneDefaultAndCreateBranch(repoDir, url, depth, shallowArgs, pre, markerPath, start, scrub);
223
- return;
224
- }
225
- try {
226
- execFileSync("git", ["clone", "--branch", pre.branch, "--depth", depth, ...shallowArgs, url, repoDir], { stdio: "pipe", timeout: 120_000 });
227
- writeMarker(markerPath, pre.runId);
228
- const ms = Date.now() - start;
229
- console.log(`[sandbox] Pre-cloned ${pre.owner}/${pre.repo}@${pre.branch} into ${repoDir} ` +
230
- `(depth ${depth}, ${ms}ms)`);
231
- }
232
- catch (err) {
233
- const firstError = scrub(err?.message) || scrub(err?.stderr?.toString?.()) || "unknown error";
234
- const looksLikeMissingBranch = /Remote branch .* not found|not found in upstream/i.test(firstError);
235
- if (looksLikeMissingBranch) {
236
- // Build-style workflows create a brand-new branch (e.g. `lastlight/N-slug`)
237
- // and push it later. The remote doesn't have it yet at pre-clone time —
238
- // clone the default branch, then create the target branch locally so
239
- // the agent enters a workspace already on the right branch.
240
- cloneDefaultAndCreateBranch(repoDir, url, depth, shallowArgs, pre, markerPath, start, scrub);
241
- return;
242
- }
243
- // Don't kill the run on a failed pre-clone — fall through to an empty
244
- // workspace and let the agent clone via the MCP path as a backup.
245
- //
246
- // CRITICAL: execFileSync errors echo the failing command line, which
247
- // includes the auth URL `https://x-access-token:<token>@github.com/…`.
248
- // The token is scrubbed above before anything reaches the logs.
249
- console.warn(`[sandbox] Pre-clone of ${pre.owner}/${pre.repo}@${pre.branch} failed (${firstError}). ` +
250
- `Agent will need to clone via MCP.`);
251
- }
252
- }
253
- /**
254
- * Clone the repo's default branch into `repoDir` and create `pre.branch`
255
- * locally off it (`checkout -B`), then stamp the run marker. Shared by two
256
- * paths: the feature branch not existing on the remote yet (build-style first
257
- * run) and a recreate-from-base workflow deliberately re-cutting its branch
258
- * from the default (issue #153). Best-effort — on failure it logs a
259
- * token-scrubbed warning and leaves an empty workspace for the agent's MCP
260
- * clone fallback.
261
- */
262
- function cloneDefaultAndCreateBranch(repoDir, url, depth, shallowArgs, pre, markerPath, start, scrub) {
263
- try {
264
- execFileSync("git", ["clone", "--depth", depth, ...shallowArgs, url, repoDir], { stdio: "pipe", timeout: 120_000 });
265
- execFileSync("git", ["-C", repoDir, "checkout", "-B", pre.branch], { stdio: "pipe", timeout: 30_000 });
266
- writeMarker(markerPath, pre.runId);
267
- const ms = Date.now() - start;
268
- console.log(`[sandbox] Pre-cloned ${pre.owner}/${pre.repo} (default branch) into ${repoDir} ` +
269
- `and created local branch ${pre.branch} (${ms}ms)`);
270
- }
271
- catch (err) {
272
- const reason = scrub(err?.message) || scrub(err?.stderr?.toString?.()) || "unknown error";
273
- console.warn(`[sandbox] Default-branch clone of ${pre.owner}/${pre.repo} failed (${reason}). ` +
274
- `Agent will need to clone via MCP.`);
275
- }
276
- }
277
- function readMarker(markerPath) {
278
- try {
279
- return readFileSync(markerPath, "utf-8").trim() || null;
280
- }
281
- catch {
282
- return null;
283
- }
284
- }
285
- function writeMarker(markerPath, runId) {
286
- if (!runId)
287
- return;
288
- try {
289
- writeFileSync(markerPath, runId);
290
- }
291
- catch {
292
- // Best-effort — a missing marker just means the next reuse refreshes
293
- // (the safe direction), never a wrong-preserve.
294
- }
295
- }
296
- /**
297
- * Refresh a reused per-PR workspace in place: fetch the branch, hard-reset the
298
- * checkout to it, and `git clean` away stale tracked/untracked build output —
299
- * but **keep `node_modules`** (and any nested ones) so the next install is
300
- * incremental against a warm tree. The shared package cache (docker backend)
301
- * lives on a separate mount and is untouched by `git clean`.
302
- *
303
- * On any failure we leave the workspace as-is and do NOT advance the marker,
304
- * so the next run retries the refresh rather than reviewing a half-reset tree.
305
- */
306
- function refreshExistingClone(repoDir, markerPath, pre) {
307
- const scrub = (s) => typeof s === "string" ? s.replaceAll(pre.token, "[REDACTED-TOKEN]") : "";
308
- const url = `https://x-access-token:${pre.token}@github.com/${pre.owner}/${pre.repo}.git`;
309
- const depth = pre.shallow ? ["--depth", "1"] : ["--depth", "50"];
310
- const start = Date.now();
311
- try {
312
- // Fetch the branch from the authenticated URL directly so we don't depend
313
- // on the stored remote (and never persist the token into .git/config).
314
- execFileSync("git", ["-C", repoDir, "fetch", ...depth, url, pre.branch], { stdio: "pipe", timeout: 120_000 });
315
- execFileSync("git", ["-C", repoDir, "checkout", "-B", pre.branch, "FETCH_HEAD"], { stdio: "pipe", timeout: 30_000 });
316
- execFileSync("git", ["-C", repoDir, "reset", "--hard", "FETCH_HEAD"], { stdio: "pipe", timeout: 30_000 });
317
- // -x removes ignored files (stale dist/, .turbo, coverage, …); -e keeps the
318
- // dependency trees warm so install is incremental. `node_modules` with no
319
- // leading slash matches at any depth (monorepos / workspaces).
320
- execFileSync("git", ["-C", repoDir, "clean", "-fdx", "-e", "node_modules"], { stdio: "pipe", timeout: 60_000 });
321
- writeMarker(markerPath, pre.runId);
322
- const ms = Date.now() - start;
323
- console.log(`[sandbox] Refreshed reused workspace ${repoDir} → ${pre.branch} ` +
324
- `(fetch+reset+clean, node_modules kept, ${ms}ms)`);
325
- }
326
- catch (err) {
327
- const reason = scrub(err?.message) || scrub(err?.stderr?.toString?.()) || "unknown error";
328
- console.warn(`[sandbox] Refresh of reused workspace ${repoDir} failed (${reason}). ` +
329
- `Leaving it untouched; agent can re-fetch via MCP.`);
330
- }
331
- }
332
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"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"}
@@ -1,214 +0,0 @@
1
- import type { RunResult, ThinkingLevel } from "agentic-pi";
2
- import type { OtelConfig, SandboxBackend } from "../config/config.js";
3
- /**
4
- * The **Sandbox port** — the single named interface every isolation backend
5
- * (`docker`, `smol`, `gondolin`, `none`) implements. Before this seam existed,
6
- * the orchestration around the four backends was copy-pasted twin-for-twin
7
- * (`executeDocker` / `executeSmol` / `executeInProcess`). Now the orchestrator
8
- * (`src/engine/executors/orchestrator.ts`) is written once and drives any
9
- * adapter through these methods.
10
- *
11
- * See `CONTEXT.md` → "Sandbox execution" for the pinned vocabulary; in short:
12
- * - **Sandbox** (this interface) is the *port*.
13
- * - **adapters** are the concrete backends below (`DockerSandbox`,
14
- * `SmolSandbox`, `InProcessSandbox`, `FakeSandbox`). Each owns its
15
- * isolation mechanism + egress enforcement; none of that surfaces here.
16
- * - the **orchestrator** is the deep module that brackets a run.
17
- *
18
- * A Sandbox instance is created per task (the factory carries `taskId`), so the
19
- * `taskId` argument on `runAgent` / `runCommand` is threaded purely for the
20
- * underlying driver APIs.
21
- */
22
- export interface Sandbox {
23
- /** Which backend this adapter is — used only for telemetry tagging. */
24
- readonly backend: SandboxBackend;
25
- /**
26
- * Provision the workspace and any isolation primitive (container / VM /
27
- * worktree). **Owns provisioning** — each adapter orders its own
28
- * clone-vs-boot internally (docker pre-clones then mounts; smol boots then
29
- * probes the share then clones; in-process just sets up the worktree) and
30
- * returns the two paths the orchestrator needs.
31
- */
32
- provision(prePopulate?: PrePopulateSpec): Promise<ProvisionResult>;
33
- /**
34
- * Stage this phase's skill bundle into the workspace and return the skill
35
- * dirs to hand the agent (already mapped to sandbox-visible paths). The
36
- * mode (symlink vs copy), root (workspace vs cwd), and any post-stage git
37
- * exclusion are adapter-local. Returns undefined when the phase has none.
38
- */
39
- stageSkills(phaseKey: string, skillPaths: string[] | undefined): string[] | undefined;
40
- /**
41
- * Map a workspace-relative path (written to `hostWorkspaceDir`) to the
42
- * absolute path the sandboxed process sees. Used for staged `type: script`
43
- * source files. docker/smol prefix the in-sandbox workspace root; in-process
44
- * returns the host path verbatim.
45
- */
46
- sandboxPathFor(relPath: string): string;
47
- /**
48
- * Run one agent turn. Emits **parsed** event records to `onEvent` — the
49
- * `startsWith("{")` guard + `JSON.parse` of the subprocess line stream live
50
- * inside the docker/smol adapters; the in-process adapter forwards
51
- * agentic-pi's already-parsed events straight through. Returns the run's
52
- * authoritative `RunResult` when the adapter has one (in-process), else
53
- * `undefined` (docker/smol) — the orchestrator reconstructs it from the
54
- * accumulated events in that case.
55
- */
56
- runAgent(taskId: string, prompt: string, opts: RunAgentOpts, onEvent: (record: SandboxEvent) => void): Promise<RunResult | undefined>;
57
- /** Run a deterministic shell command (no LLM). Resolves with its raw result. */
58
- runCommand(taskId: string, command: string, opts: RunCommandOpts): Promise<RawCommandResult>;
59
- /** Tear down the isolation primitive (container/VM destroy; no-op in-process). */
60
- dispose(): Promise<void> | void;
61
- }
62
- /**
63
- * The **intent-only** egress value object. The orchestrator decides *what is
64
- * allowed* once (hosts already merged with any OTEL collector hosts); each
65
- * adapter translates it to its *mechanism* — docker `--dns` strict/open, smol
66
- * `--allow-host`, in-process `allowedHttpHosts` / `["*"]`. The `172.30.0.x`
67
- * constants and the `"*"` sentinel live inside the adapters, never here.
68
- */
69
- export interface EgressPolicy {
70
- /** True iff a phase opted out of the allowlist (`unrestricted_egress`). */
71
- unrestricted: boolean;
72
- /** Allowed apex hostnames when not unrestricted (incl. collector hosts). */
73
- hosts: string[];
74
- }
75
- /** The repo pre-clone descriptor handed to {@link Sandbox.provision}. */
76
- export interface PrePopulateSpec {
77
- owner: string;
78
- repo: string;
79
- branch: string;
80
- token: string;
81
- runId?: string;
82
- shallow?: boolean;
83
- /**
84
- * Recreate the checkout from the default branch on a fresh (different-run)
85
- * provision instead of refreshing the existing feature branch: delete any
86
- * leftover checkout and clone the default branch, then create `branch`
87
- * locally off it. Set for `build` so a re-triggered incomplete build starts
88
- * again from current `main` (issue #153). A same-run provision still
89
- * preserves the workspace.
90
- */
91
- recreateFromBase?: boolean;
92
- }
93
- /** What {@link Sandbox.provision} hands back to the orchestrator. */
94
- export interface ProvisionResult {
95
- /** Host dir backing the workspace (where the orchestrator stages files). */
96
- hostWorkspaceDir: string;
97
- /** Working directory the agent/command process runs in (sandbox-visible). */
98
- agentCwd: string;
99
- }
100
- export type SandboxEvent = Record<string, unknown>;
101
- export interface RunAgentOpts {
102
- model: string;
103
- thinking?: ThinkingLevel;
104
- /** agentic-pi github profile (`read` | `issues-write` | … ). */
105
- profile?: string;
106
- /** Base inner-run env (git identity); adapters merge their own OTEL/HOME. */
107
- sandboxEnv: Record<string, string>;
108
- agentCwd: string;
109
- skillDirs?: string[];
110
- webSearch?: boolean;
111
- webSearchProvider?: "tavily" | "brave" | "exa";
112
- /** Test/eval escape hatch — only honoured by the in-process adapter. */
113
- githubApiBaseUrl?: string;
114
- /**
115
- * Credential store (`auth.json`) agentic-pi points Pi's AuthStorage at for
116
- * model auth — carries OAuth subscription logins (Codex / Claude Pro /
117
- * Copilot). Only meaningful for the in-process adapter (none/gondolin), where
118
- * the model call runs host-side so a host path resolves; the docker adapter
119
- * ignores it (its model call is in-container) and relies on env tokens.
120
- */
121
- authFile?: string;
122
- }
123
- export interface RunCommandOpts {
124
- cwd: string;
125
- /** Extra env forwarded into the command (upstream phase outputs, etc.). */
126
- sandboxEnv?: Record<string, string>;
127
- timeoutSeconds: number;
128
- }
129
- export interface RawCommandResult {
130
- exitCode: number;
131
- stdout: string;
132
- stderr: string;
133
- timedOut: boolean;
134
- }
135
- /** Construction-time opts for {@link sandboxFor} / each adapter. */
136
- export interface SandboxFactoryOpts {
137
- taskId: string;
138
- egress: EgressPolicy;
139
- /** Env forwarded into the sandbox (provider keys, minted GITHUB_TOKEN, …). */
140
- env: Record<string, string>;
141
- stateDir: string;
142
- sandboxDir?: string;
143
- /** Run the agent in this `<workspace>/<repoSubdir>/` subdir (pre-seeded by the
144
- * caller) instead of the workspace root — see {@link ExecutorConfig.repoSubdir}. */
145
- repoSubdir?: string;
146
- /** Docker image override (the browser-QA image for `sandbox_image: qa`). */
147
- imageName?: string;
148
- otel?: OtelConfig;
149
- timeoutSeconds?: number;
150
- }
151
- export type SandboxFactory = (backend: SandboxBackend, opts: SandboxFactoryOpts) => Sandbox;
152
- /**
153
- * Inner-run git identity, shared by every adapter's agent path. Takes the
154
- * resolved bot login (e.g. `last-light[bot]` / `nearform-lastlight[bot]`) so
155
- * agent commits are attributed to the actual App — including a `BOT_LOGIN`
156
- * override, which the caller resolves before passing it here.
157
- */
158
- export declare function agentGitIdentityEnv(botLogin: string): Record<string, string>;
159
- /**
160
- * The single factory replacing the `if (backend === …)` ladder. Given a
161
- * backend and construction opts, returns the matching adapter. Docker's
162
- * old null-fallback is now a thrown error from `provision` (the orchestrator's
163
- * bracket surfaces it), so this never returns null.
164
- */
165
- export declare function sandboxFor(backend: SandboxBackend, opts: SandboxFactoryOpts): Sandbox;
166
- export interface FakeBehavior {
167
- /** Canned parsed pi-event records replayed through `onEvent`. */
168
- events?: SandboxEvent[];
169
- /** Throw from `runAgent` to exercise the fallback path. */
170
- throwOnRunAgent?: Error | string;
171
- /** Authoritative RunResult `runAgent` returns (else undefined → acc.build). */
172
- returnRunResult?: RunResult;
173
- /** Result `runCommand` resolves with (default exit 0, empty output). */
174
- commandResult?: RawCommandResult;
175
- /** Throw from `runCommand`. */
176
- throwOnRunCommand?: Error | string;
177
- }
178
- /**
179
- * In-memory `Sandbox` adapter for unit-testing the orchestrator without
180
- * Docker/VMs. `provision()` returns a **real** `mkdtemp` workspace (so skill
181
- * staging + artifact harvest run for real), `runAgent` replays a canned array
182
- * of pi event records through `onEvent`, and it **records** the opts it
183
- * received for assertions. Covers Last Light's orchestration, not agentic-pi's
184
- * semantics.
185
- *
186
- * Inject it via the optional `sandboxFactory` on `executeAgent`/`executeCommand`
187
- * — see {@link FakeSandbox.asFactory}.
188
- */
189
- export declare class FakeSandbox implements Sandbox {
190
- private readonly behavior;
191
- backend: SandboxBackend;
192
- egress?: EgressPolicy;
193
- env?: Record<string, string>;
194
- hostWorkspaceDir: string;
195
- agentCwd: string;
196
- stagedSkillDirs?: string[];
197
- receivedAgentOpts?: RunAgentOpts;
198
- receivedCommandOpts?: RunCommandOpts;
199
- receivedCommand?: string;
200
- provisionCalls: number;
201
- disposed: boolean;
202
- constructor(behavior?: FakeBehavior);
203
- /**
204
- * Build a {@link SandboxFactory} that always returns THIS instance, capturing
205
- * the construction opts (egress, env, backend) for later inspection.
206
- */
207
- asFactory(): SandboxFactory;
208
- provision(pre?: PrePopulateSpec): Promise<ProvisionResult>;
209
- stageSkills(phaseKey: string, skillPaths: string[] | undefined): string[] | undefined;
210
- sandboxPathFor(relPath: string): string;
211
- runAgent(_taskId: string, _prompt: string, opts: RunAgentOpts, onEvent: (record: SandboxEvent) => void): Promise<RunResult | undefined>;
212
- runCommand(_taskId: string, command: string, opts: RunCommandOpts): Promise<RawCommandResult>;
213
- dispose(): void;
214
- }