@elie-laloum/outpost 11.0.1 → 11.1.2

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 (577) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +9 -9
  3. package/SECURITY.md +28 -2
  4. package/dist/adapters/testing/scripted-agent.js +5 -0
  5. package/dist/adapters/testing/scripted-agent.js.map +1 -1
  6. package/dist/adapters/tools/file-tools.d.ts +2 -1
  7. package/dist/adapters/tools/file-tools.js +37 -15
  8. package/dist/adapters/tools/file-tools.js.map +1 -1
  9. package/dist/adapters/tools/filesystem-selection.constants.d.ts +1 -0
  10. package/dist/adapters/tools/filesystem-selection.constants.js +7 -0
  11. package/dist/adapters/tools/filesystem-selection.constants.js.map +1 -0
  12. package/dist/adapters/tools/git-tools.js +1 -0
  13. package/dist/adapters/tools/git-tools.js.map +1 -1
  14. package/dist/adapters/tools/search-tools.d.ts +2 -1
  15. package/dist/adapters/tools/search-tools.js +52 -22
  16. package/dist/adapters/tools/search-tools.js.map +1 -1
  17. package/dist/adapters/tools/tools.types.d.ts +3 -0
  18. package/dist/adapters/tools/tools.types.js.map +1 -1
  19. package/dist/application/attach.d.ts +4 -0
  20. package/dist/application/attach.js +20 -0
  21. package/dist/application/attach.js.map +1 -1
  22. package/dist/application/brief-renderer.d.ts +2 -3
  23. package/dist/application/brief-renderer.js +6 -4
  24. package/dist/application/brief-renderer.js.map +1 -1
  25. package/dist/application/custom-turn.js +6 -0
  26. package/dist/application/custom-turn.js.map +1 -1
  27. package/dist/application/dispatch-observation.js +15 -1
  28. package/dist/application/dispatch-observation.js.map +1 -1
  29. package/dist/application/dispatch.d.ts +4 -0
  30. package/dist/application/dispatch.js +9 -0
  31. package/dist/application/dispatch.js.map +1 -1
  32. package/dist/application/doctor-image.js +4 -2
  33. package/dist/application/doctor-image.js.map +1 -1
  34. package/dist/application/doctor-sandbox.js +3 -1
  35. package/dist/application/doctor-sandbox.js.map +1 -1
  36. package/dist/application/doctor-sandbox.types.d.ts +1 -0
  37. package/dist/application/doctor-sandbox.types.js.map +1 -1
  38. package/dist/application/doctor.js +16 -8
  39. package/dist/application/doctor.js.map +1 -1
  40. package/dist/application/doctor.types.d.ts +2 -0
  41. package/dist/application/doctor.types.js.map +1 -1
  42. package/dist/application/execution.d.ts +2 -3
  43. package/dist/application/execution.js +9 -4
  44. package/dist/application/execution.js.map +1 -1
  45. package/dist/application/execution.types.d.ts +7 -0
  46. package/dist/application/execution.types.js.map +1 -1
  47. package/dist/application/file-interactive-task.d.ts +3 -0
  48. package/dist/application/file-interactive-task.js +189 -0
  49. package/dist/application/file-interactive-task.js.map +1 -0
  50. package/dist/application/file-run-report.d.ts +6 -0
  51. package/dist/application/file-run-report.js +33 -0
  52. package/dist/application/file-run-report.js.map +1 -0
  53. package/dist/application/file-sandbox.d.ts +9 -0
  54. package/dist/application/file-sandbox.js +674 -0
  55. package/dist/application/file-sandbox.js.map +1 -0
  56. package/dist/application/file-sandbox.types.d.ts +62 -0
  57. package/dist/application/file-sandbox.types.js +2 -0
  58. package/dist/application/file-sandbox.types.js.map +1 -0
  59. package/dist/application/file-workspace-recovery.d.ts +5 -0
  60. package/dist/application/file-workspace-recovery.js +80 -0
  61. package/dist/application/file-workspace-recovery.js.map +1 -0
  62. package/dist/application/file-workspace-recovery.types.d.ts +18 -0
  63. package/dist/application/file-workspace-recovery.types.js +2 -0
  64. package/dist/application/file-workspace-recovery.types.js.map +1 -0
  65. package/dist/application/file-workspace-registry.d.ts +2 -0
  66. package/dist/application/file-workspace-registry.js +2 -0
  67. package/dist/application/file-workspace-registry.js.map +1 -0
  68. package/dist/application/file-workspace.d.ts +9 -0
  69. package/dist/application/file-workspace.js +583 -0
  70. package/dist/application/file-workspace.js.map +1 -0
  71. package/dist/application/file-workspace.types.d.ts +79 -0
  72. package/dist/application/file-workspace.types.js +2 -0
  73. package/dist/application/file-workspace.types.js.map +1 -0
  74. package/dist/application/harness-subagent.js +7 -1
  75. package/dist/application/harness-subagent.js.map +1 -1
  76. package/dist/application/harness.types.d.ts +1 -0
  77. package/dist/application/harness.types.js.map +1 -1
  78. package/dist/application/interactive-task.d.ts +2 -1
  79. package/dist/application/interactive-task.js +3 -0
  80. package/dist/application/interactive-task.js.map +1 -1
  81. package/dist/application/interactive-task.types.d.ts +20 -0
  82. package/dist/application/interactive-task.types.js.map +1 -1
  83. package/dist/application/recipe-configuration-providers.d.ts +3 -0
  84. package/dist/application/recipe-configuration-providers.js +45 -0
  85. package/dist/application/recipe-configuration-providers.js.map +1 -0
  86. package/dist/application/recipe-configuration-values.d.ts +10 -0
  87. package/dist/application/recipe-configuration-values.js +96 -0
  88. package/dist/application/recipe-configuration-values.js.map +1 -0
  89. package/dist/application/recipe-configuration.constants.d.ts +7 -0
  90. package/dist/application/recipe-configuration.constants.js +16 -0
  91. package/dist/application/recipe-configuration.constants.js.map +1 -0
  92. package/dist/application/recipe-configuration.d.ts +2 -0
  93. package/dist/application/recipe-configuration.js +52 -0
  94. package/dist/application/recipe-configuration.js.map +1 -0
  95. package/dist/application/recipe-report.constants.d.ts +5 -0
  96. package/dist/application/recipe-report.constants.js +15 -0
  97. package/dist/application/recipe-report.constants.js.map +1 -0
  98. package/dist/application/recipe-report.d.ts +4 -0
  99. package/dist/application/recipe-report.js +69 -0
  100. package/dist/application/recipe-report.js.map +1 -0
  101. package/dist/application/recipe-report.types.d.ts +33 -0
  102. package/dist/application/recipe-report.types.js +2 -0
  103. package/dist/application/recipe-report.types.js.map +1 -0
  104. package/dist/application/recipe-run.d.ts +7 -0
  105. package/dist/application/recipe-run.js +86 -0
  106. package/dist/application/recipe-run.js.map +1 -0
  107. package/dist/application/recipe.d.ts +6 -0
  108. package/dist/application/recipe.js +86 -0
  109. package/dist/application/recipe.js.map +1 -0
  110. package/dist/application/recipe.types.d.ts +22 -0
  111. package/dist/application/recipe.types.js +2 -0
  112. package/dist/application/recipe.types.js.map +1 -0
  113. package/dist/application/recipes/advanced-components.d.ts +15 -0
  114. package/dist/application/recipes/advanced-components.js +35 -0
  115. package/dist/application/recipes/advanced-components.js.map +1 -0
  116. package/dist/application/recipes/advanced-components.types.d.ts +16 -0
  117. package/dist/application/recipes/advanced-components.types.js +2 -0
  118. package/dist/application/recipes/advanced-components.types.js.map +1 -0
  119. package/dist/application/recipes/agent-components.d.ts +5 -0
  120. package/dist/application/recipes/agent-components.js +22 -0
  121. package/dist/application/recipes/agent-components.js.map +1 -0
  122. package/dist/application/recipes/agent-components.types.d.ts +32 -0
  123. package/dist/application/recipes/agent-components.types.js +2 -0
  124. package/dist/application/recipes/agent-components.types.js.map +1 -0
  125. package/dist/application/recipes/agent-preflight.d.ts +3 -0
  126. package/dist/application/recipes/agent-preflight.js +15 -0
  127. package/dist/application/recipes/agent-preflight.js.map +1 -0
  128. package/dist/application/recipes/components.types.d.ts +50 -0
  129. package/dist/application/recipes/components.types.js +2 -0
  130. package/dist/application/recipes/components.types.js.map +1 -0
  131. package/dist/application/recipes/configuration.d.ts +4 -0
  132. package/dist/application/recipes/configuration.js +76 -0
  133. package/dist/application/recipes/configuration.js.map +1 -0
  134. package/dist/application/recipes/durable-resources.d.ts +5 -0
  135. package/dist/application/recipes/durable-resources.js +183 -0
  136. package/dist/application/recipes/durable-resources.js.map +1 -0
  137. package/dist/application/recipes/durable-resources.types.d.ts +17 -0
  138. package/dist/application/recipes/durable-resources.types.js +2 -0
  139. package/dist/application/recipes/durable-resources.types.js.map +1 -0
  140. package/dist/application/recipes/durable-run.d.ts +28 -0
  141. package/dist/application/recipes/durable-run.js +89 -0
  142. package/dist/application/recipes/durable-run.js.map +1 -0
  143. package/dist/application/recipes/durable-schema.constants.d.ts +557 -0
  144. package/dist/application/recipes/durable-schema.constants.js +138 -0
  145. package/dist/application/recipes/durable-schema.constants.js.map +1 -0
  146. package/dist/application/recipes/durable-session.d.ts +8 -0
  147. package/dist/application/recipes/durable-session.js +178 -0
  148. package/dist/application/recipes/durable-session.js.map +1 -0
  149. package/dist/application/recipes/durable.types.d.ts +49 -0
  150. package/dist/application/recipes/durable.types.js +2 -0
  151. package/dist/application/recipes/durable.types.js.map +1 -0
  152. package/dist/application/recipes/errors.d.ts +2 -0
  153. package/dist/application/recipes/errors.js +21 -0
  154. package/dist/application/recipes/errors.js.map +1 -0
  155. package/dist/application/recipes/file-configuration.d.ts +3 -0
  156. package/dist/application/recipes/file-configuration.js +195 -0
  157. package/dist/application/recipes/file-configuration.js.map +1 -0
  158. package/dist/application/recipes/file-configuration.types.d.ts +26 -0
  159. package/dist/application/recipes/file-configuration.types.js +2 -0
  160. package/dist/application/recipes/file-configuration.types.js.map +1 -0
  161. package/dist/application/recipes/file-publication-report.constants.d.ts +1 -0
  162. package/dist/application/recipes/file-publication-report.constants.js +2 -0
  163. package/dist/application/recipes/file-publication-report.constants.js.map +1 -0
  164. package/dist/application/recipes/file-publication-report.d.ts +3 -0
  165. package/dist/application/recipes/file-publication-report.js +110 -0
  166. package/dist/application/recipes/file-publication-report.js.map +1 -0
  167. package/dist/application/recipes/file-run.d.ts +6 -0
  168. package/dist/application/recipes/file-run.js +263 -0
  169. package/dist/application/recipes/file-run.js.map +1 -0
  170. package/dist/application/recipes/file-validation.d.ts +3 -0
  171. package/dist/application/recipes/file-validation.js +32 -0
  172. package/dist/application/recipes/file-validation.js.map +1 -0
  173. package/dist/application/recipes/graph.d.ts +4 -0
  174. package/dist/application/recipes/graph.js +208 -0
  175. package/dist/application/recipes/graph.js.map +1 -0
  176. package/dist/application/recipes/job.d.ts +3 -0
  177. package/dist/application/recipes/job.js +100 -0
  178. package/dist/application/recipes/job.js.map +1 -0
  179. package/dist/application/recipes/native-catalog.constants.d.ts +4 -0
  180. package/dist/application/recipes/native-catalog.constants.js +930 -0
  181. package/dist/application/recipes/native-catalog.constants.js.map +1 -0
  182. package/dist/application/recipes/native-factories.d.ts +1 -0
  183. package/dist/application/recipes/native-factories.js +136 -0
  184. package/dist/application/recipes/native-factories.js.map +1 -0
  185. package/dist/application/recipes/native-schemas.constants.d.ts +2 -0
  186. package/dist/application/recipes/native-schemas.constants.js +26619 -0
  187. package/dist/application/recipes/native-schemas.constants.js.map +1 -0
  188. package/dist/application/recipes/native.d.ts +7 -0
  189. package/dist/application/recipes/native.js +184 -0
  190. package/dist/application/recipes/native.js.map +1 -0
  191. package/dist/application/recipes/observation.d.ts +4 -0
  192. package/dist/application/recipes/observation.js +88 -0
  193. package/dist/application/recipes/observation.js.map +1 -0
  194. package/dist/application/recipes/project-expressions.d.ts +3 -0
  195. package/dist/application/recipes/project-expressions.js +28 -0
  196. package/dist/application/recipes/project-expressions.js.map +1 -0
  197. package/dist/application/recipes/project.d.ts +3 -0
  198. package/dist/application/recipes/project.js +165 -0
  199. package/dist/application/recipes/project.js.map +1 -0
  200. package/dist/application/recipes/project.types.d.ts +53 -0
  201. package/dist/application/recipes/project.types.js +2 -0
  202. package/dist/application/recipes/project.types.js.map +1 -0
  203. package/dist/application/recipes/projection.d.ts +2 -0
  204. package/dist/application/recipes/projection.js +9 -0
  205. package/dist/application/recipes/projection.js.map +1 -0
  206. package/dist/application/recipes/reports.d.ts +4 -0
  207. package/dist/application/recipes/reports.js +27 -0
  208. package/dist/application/recipes/reports.js.map +1 -0
  209. package/dist/application/recipes/runtime.d.ts +4 -0
  210. package/dist/application/recipes/runtime.js +179 -0
  211. package/dist/application/recipes/runtime.js.map +1 -0
  212. package/dist/application/recipes/sandbox.d.ts +6 -0
  213. package/dist/application/recipes/sandbox.js +31 -0
  214. package/dist/application/recipes/sandbox.js.map +1 -0
  215. package/dist/application/recipes/schemas.constants.d.ts +2 -0
  216. package/dist/application/recipes/schemas.constants.js +15 -0
  217. package/dist/application/recipes/schemas.constants.js.map +1 -0
  218. package/dist/application/recipes/scope.d.ts +3 -0
  219. package/dist/application/recipes/scope.js +180 -0
  220. package/dist/application/recipes/scope.js.map +1 -0
  221. package/dist/application/recipes/service-components.d.ts +10 -0
  222. package/dist/application/recipes/service-components.js +78 -0
  223. package/dist/application/recipes/service-components.js.map +1 -0
  224. package/dist/application/recipes/service-components.types.d.ts +57 -0
  225. package/dist/application/recipes/service-components.types.js +2 -0
  226. package/dist/application/recipes/service-components.types.js.map +1 -0
  227. package/dist/application/recipes/services.d.ts +4 -0
  228. package/dist/application/recipes/services.js +60 -0
  229. package/dist/application/recipes/services.js.map +1 -0
  230. package/dist/application/recipes/speculation-usage.d.ts +3 -0
  231. package/dist/application/recipes/speculation-usage.js +69 -0
  232. package/dist/application/recipes/speculation-usage.js.map +1 -0
  233. package/dist/application/recipes/speculation.d.ts +3 -0
  234. package/dist/application/recipes/speculation.js +55 -0
  235. package/dist/application/recipes/speculation.js.map +1 -0
  236. package/dist/application/recipes/status.d.ts +4 -0
  237. package/dist/application/recipes/status.js +72 -0
  238. package/dist/application/recipes/status.js.map +1 -0
  239. package/dist/application/recipes/storage-components.d.ts +2 -0
  240. package/dist/application/recipes/storage-components.js +10 -0
  241. package/dist/application/recipes/storage-components.js.map +1 -0
  242. package/dist/application/recipes/storage-components.types.d.ts +13 -0
  243. package/dist/application/recipes/storage-components.types.js +2 -0
  244. package/dist/application/recipes/storage-components.types.js.map +1 -0
  245. package/dist/application/recipes/variables.d.ts +2 -0
  246. package/dist/application/recipes/variables.js +31 -0
  247. package/dist/application/recipes/variables.js.map +1 -0
  248. package/dist/application/recipes/variables.types.d.ts +7 -0
  249. package/dist/application/recipes/variables.types.js +2 -0
  250. package/dist/application/recipes/variables.types.js.map +1 -0
  251. package/dist/application/recipes/workflow-components.d.ts +6 -0
  252. package/dist/application/recipes/workflow-components.js +106 -0
  253. package/dist/application/recipes/workflow-components.js.map +1 -0
  254. package/dist/application/recipes/workflow-components.types.d.ts +52 -0
  255. package/dist/application/recipes/workflow-components.types.js +2 -0
  256. package/dist/application/recipes/workflow-components.types.js.map +1 -0
  257. package/dist/application/recipes/workflow-report.d.ts +3 -0
  258. package/dist/application/recipes/workflow-report.js +48 -0
  259. package/dist/application/recipes/workflow-report.js.map +1 -0
  260. package/dist/application/recipes/workflow-run.d.ts +6 -0
  261. package/dist/application/recipes/workflow-run.js +70 -0
  262. package/dist/application/recipes/workflow-run.js.map +1 -0
  263. package/dist/application/recipes/workflow-validation.d.ts +3 -0
  264. package/dist/application/recipes/workflow-validation.js +85 -0
  265. package/dist/application/recipes/workflow-validation.js.map +1 -0
  266. package/dist/application/recipes/workflow.constants.d.ts +1 -0
  267. package/dist/application/recipes/workflow.constants.js +20 -0
  268. package/dist/application/recipes/workflow.constants.js.map +1 -0
  269. package/dist/application/recipes/workflow.d.ts +6 -0
  270. package/dist/application/recipes/workflow.js +348 -0
  271. package/dist/application/recipes/workflow.js.map +1 -0
  272. package/dist/application/recipes/workspace.d.ts +4 -0
  273. package/dist/application/recipes/workspace.js +44 -0
  274. package/dist/application/recipes/workspace.js.map +1 -0
  275. package/dist/application/sandbox.d.ts +4 -0
  276. package/dist/application/sandbox.js +6 -0
  277. package/dist/application/sandbox.js.map +1 -1
  278. package/dist/application/speculation-validation.d.ts +5 -0
  279. package/dist/application/speculation-validation.js +29 -0
  280. package/dist/application/speculation-validation.js.map +1 -0
  281. package/dist/application/speculation.js +2 -24
  282. package/dist/application/speculation.js.map +1 -1
  283. package/dist/application/task-file-workspace.d.ts +8 -0
  284. package/dist/application/task-file-workspace.js +74 -0
  285. package/dist/application/task-file-workspace.js.map +1 -0
  286. package/dist/application/task-file-workspace.types.d.ts +6 -0
  287. package/dist/application/task-file-workspace.types.js +2 -0
  288. package/dist/application/task-file-workspace.types.js.map +1 -0
  289. package/dist/application/tasks.d.ts +7 -1
  290. package/dist/application/tasks.js +89 -4
  291. package/dist/application/tasks.js.map +1 -1
  292. package/dist/application/tasks.types.d.ts +28 -1
  293. package/dist/application/tasks.types.js.map +1 -1
  294. package/dist/application/workflow-job.d.ts +5 -1
  295. package/dist/application/workflow-job.js +11 -9
  296. package/dist/application/workflow-job.js.map +1 -1
  297. package/dist/application/workflow-job.types.d.ts +2 -1
  298. package/dist/application/workflow-job.types.js.map +1 -1
  299. package/dist/application/workspace-output-baseline.d.ts +5 -0
  300. package/dist/application/workspace-output-baseline.js +44 -0
  301. package/dist/application/workspace-output-baseline.js.map +1 -0
  302. package/dist/application/workspace-publication-directories.d.ts +8 -0
  303. package/dist/application/workspace-publication-directories.js +170 -0
  304. package/dist/application/workspace-publication-directories.js.map +1 -0
  305. package/dist/application/workspace-publication.d.ts +7 -0
  306. package/dist/application/workspace-publication.js +537 -0
  307. package/dist/application/workspace-publication.js.map +1 -0
  308. package/dist/application/workspace-publication.types.d.ts +37 -0
  309. package/dist/application/workspace-publication.types.js +2 -0
  310. package/dist/application/workspace-publication.types.js.map +1 -0
  311. package/dist/application/workspace-source.d.ts +8 -0
  312. package/dist/application/workspace-source.js +18 -0
  313. package/dist/application/workspace-source.js.map +1 -0
  314. package/dist/application/workspace.d.ts +2 -0
  315. package/dist/application/workspace.js +3 -0
  316. package/dist/application/workspace.js.map +1 -1
  317. package/dist/cli/commands.js +17 -2
  318. package/dist/cli/commands.js.map +1 -1
  319. package/dist/cli/doctor-command.js +6 -1
  320. package/dist/cli/doctor-command.js.map +1 -1
  321. package/dist/cli/main.constants.d.ts +191 -3
  322. package/dist/cli/main.constants.js +275 -3
  323. package/dist/cli/main.constants.js.map +1 -1
  324. package/dist/cli/main.types.d.ts +1 -1
  325. package/dist/cli/main.types.js.map +1 -1
  326. package/dist/cli/recipe-actor.d.ts +2 -0
  327. package/dist/cli/recipe-actor.js +14 -0
  328. package/dist/cli/recipe-actor.js.map +1 -0
  329. package/dist/cli/recipe-catalog.d.ts +2 -0
  330. package/dist/cli/recipe-catalog.js +54 -0
  331. package/dist/cli/recipe-catalog.js.map +1 -0
  332. package/dist/cli/recipe-command.d.ts +2 -0
  333. package/dist/cli/recipe-command.js +184 -0
  334. package/dist/cli/recipe-command.js.map +1 -0
  335. package/dist/cli/recipe-configuration-providers.d.ts +1 -0
  336. package/dist/cli/recipe-configuration-providers.js +2 -0
  337. package/dist/cli/recipe-configuration-providers.js.map +1 -0
  338. package/dist/cli/recipe-configuration-values.d.ts +1 -0
  339. package/dist/cli/recipe-configuration-values.js +2 -0
  340. package/dist/cli/recipe-configuration-values.js.map +1 -0
  341. package/dist/cli/recipe-configuration.constants.d.ts +1 -0
  342. package/dist/cli/recipe-configuration.constants.js +2 -0
  343. package/dist/cli/recipe-configuration.constants.js.map +1 -0
  344. package/dist/cli/recipe-configuration.d.ts +1 -0
  345. package/dist/cli/recipe-configuration.js +2 -0
  346. package/dist/cli/recipe-configuration.js.map +1 -0
  347. package/dist/cli/recipe-dialogue.d.ts +5 -0
  348. package/dist/cli/recipe-dialogue.js +69 -0
  349. package/dist/cli/recipe-dialogue.js.map +1 -0
  350. package/dist/cli/recipe-dialogue.types.d.ts +11 -0
  351. package/dist/cli/recipe-dialogue.types.js +2 -0
  352. package/dist/cli/recipe-dialogue.types.js.map +1 -0
  353. package/dist/cli/recipe-gates.d.ts +5 -0
  354. package/dist/cli/recipe-gates.js +51 -0
  355. package/dist/cli/recipe-gates.js.map +1 -0
  356. package/dist/cli/recipe-init.constants.d.ts +7 -0
  357. package/dist/cli/recipe-init.constants.js +64 -0
  358. package/dist/cli/recipe-init.constants.js.map +1 -0
  359. package/dist/cli/recipe-init.d.ts +2 -0
  360. package/dist/cli/recipe-init.js +39 -0
  361. package/dist/cli/recipe-init.js.map +1 -0
  362. package/dist/cli/recipe-inputs.d.ts +2 -0
  363. package/dist/cli/recipe-inputs.js +31 -0
  364. package/dist/cli/recipe-inputs.js.map +1 -0
  365. package/dist/cli/recipe-report.constants.d.ts +1 -0
  366. package/dist/cli/recipe-report.constants.js +2 -0
  367. package/dist/cli/recipe-report.constants.js.map +1 -0
  368. package/dist/cli/recipe-report.d.ts +1 -0
  369. package/dist/cli/recipe-report.js +2 -0
  370. package/dist/cli/recipe-report.js.map +1 -0
  371. package/dist/cli/recipe-report.types.d.ts +1 -0
  372. package/dist/cli/recipe-report.types.js +2 -0
  373. package/dist/cli/recipe-report.types.js.map +1 -0
  374. package/dist/cli/recipe-run.d.ts +1 -0
  375. package/dist/cli/recipe-run.js +2 -0
  376. package/dist/cli/recipe-run.js.map +1 -0
  377. package/dist/cli/recipe-terminal.d.ts +4 -0
  378. package/dist/cli/recipe-terminal.js +52 -0
  379. package/dist/cli/recipe-terminal.js.map +1 -0
  380. package/dist/cli/recipe-yaml.d.ts +3 -0
  381. package/dist/cli/recipe-yaml.js +193 -0
  382. package/dist/cli/recipe-yaml.js.map +1 -0
  383. package/dist/cli/recovery-command.js +57 -0
  384. package/dist/cli/recovery-command.js.map +1 -1
  385. package/dist/cli/recovery-file-transport.d.ts +4 -0
  386. package/dist/cli/recovery-file-transport.js +40 -0
  387. package/dist/cli/recovery-file-transport.js.map +1 -0
  388. package/dist/cli/recovery-publication-command.d.ts +2 -0
  389. package/dist/cli/recovery-publication-command.js +121 -0
  390. package/dist/cli/recovery-publication-command.js.map +1 -0
  391. package/dist/cli/recovery-workspace-command.d.ts +2 -0
  392. package/dist/cli/recovery-workspace-command.js +63 -0
  393. package/dist/cli/recovery-workspace-command.js.map +1 -0
  394. package/dist/domain/agent.types.d.ts +7 -0
  395. package/dist/domain/agent.types.js.map +1 -1
  396. package/dist/domain/conversation.types.d.ts +2 -1
  397. package/dist/domain/conversation.types.js.map +1 -1
  398. package/dist/domain/file-workspace.constants.d.ts +476 -0
  399. package/dist/domain/file-workspace.constants.js +237 -0
  400. package/dist/domain/file-workspace.constants.js.map +1 -0
  401. package/dist/domain/file-workspace.types.d.ts +133 -0
  402. package/dist/domain/file-workspace.types.js +2 -0
  403. package/dist/domain/file-workspace.types.js.map +1 -0
  404. package/dist/domain/prompts.d.ts +1 -1
  405. package/dist/domain/prompts.js.map +1 -1
  406. package/dist/domain/recipe-catalog.constants.d.ts +7 -0
  407. package/dist/domain/recipe-catalog.constants.js +14 -0
  408. package/dist/domain/recipe-catalog.constants.js.map +1 -0
  409. package/dist/domain/recipe-catalog.d.ts +2 -0
  410. package/dist/domain/recipe-catalog.js +41 -0
  411. package/dist/domain/recipe-catalog.js.map +1 -0
  412. package/dist/domain/recipe-catalog.types.d.ts +11 -0
  413. package/dist/domain/recipe-catalog.types.js +2 -0
  414. package/dist/domain/recipe-catalog.types.js.map +1 -0
  415. package/dist/domain/recipe-inputs.d.ts +5 -0
  416. package/dist/domain/recipe-inputs.js +110 -0
  417. package/dist/domain/recipe-inputs.js.map +1 -0
  418. package/dist/domain/recipe-templates.d.ts +7 -0
  419. package/dist/domain/recipe-templates.js +85 -0
  420. package/dist/domain/recipe-templates.js.map +1 -0
  421. package/dist/domain/recipe.constants.d.ts +21 -0
  422. package/dist/domain/recipe.constants.js +59 -0
  423. package/dist/domain/recipe.constants.js.map +1 -0
  424. package/dist/domain/recipe.d.ts +2 -0
  425. package/dist/domain/recipe.js +294 -0
  426. package/dist/domain/recipe.js.map +1 -0
  427. package/dist/domain/recipe.types.d.ts +52 -0
  428. package/dist/domain/recipe.types.js +2 -0
  429. package/dist/domain/recipe.types.js.map +1 -0
  430. package/dist/domain/recipes/checkpoint-store.types.d.ts +10 -0
  431. package/dist/domain/recipes/checkpoint-store.types.js +2 -0
  432. package/dist/domain/recipes/checkpoint-store.types.js.map +1 -0
  433. package/dist/domain/recipes/component.d.ts +3 -0
  434. package/dist/domain/recipes/component.js +27 -0
  435. package/dist/domain/recipes/component.js.map +1 -0
  436. package/dist/domain/recipes/component.types.d.ts +39 -0
  437. package/dist/domain/recipes/component.types.js +2 -0
  438. package/dist/domain/recipes/component.types.js.map +1 -0
  439. package/dist/domain/recipes/expression-text.d.ts +2 -0
  440. package/dist/domain/recipes/expression-text.js +22 -0
  441. package/dist/domain/recipes/expression-text.js.map +1 -0
  442. package/dist/domain/recipes/expressions.d.ts +7 -0
  443. package/dist/domain/recipes/expressions.js +209 -0
  444. package/dist/domain/recipes/expressions.js.map +1 -0
  445. package/dist/domain/recipes/expressions.types.d.ts +17 -0
  446. package/dist/domain/recipes/expressions.types.js +2 -0
  447. package/dist/domain/recipes/expressions.types.js.map +1 -0
  448. package/dist/domain/recipes/schema-walk.d.ts +3 -0
  449. package/dist/domain/recipes/schema-walk.js +151 -0
  450. package/dist/domain/recipes/schema-walk.js.map +1 -0
  451. package/dist/domain/recipes/schema-walk.types.d.ts +2 -0
  452. package/dist/domain/recipes/schema-walk.types.js +2 -0
  453. package/dist/domain/recipes/schema-walk.types.js.map +1 -0
  454. package/dist/domain/recipes/schema.constants.d.ts +41 -0
  455. package/dist/domain/recipes/schema.constants.js +59 -0
  456. package/dist/domain/recipes/schema.constants.js.map +1 -0
  457. package/dist/domain/recipes/values.d.ts +6 -0
  458. package/dist/domain/recipes/values.js +24 -0
  459. package/dist/domain/recipes/values.js.map +1 -0
  460. package/dist/domain/run-report.types.d.ts +5 -0
  461. package/dist/domain/run-report.types.js.map +1 -1
  462. package/dist/domain/sandbox.types.d.ts +14 -0
  463. package/dist/domain/sandbox.types.js.map +1 -1
  464. package/dist/domain/tool.constants.js +1 -0
  465. package/dist/domain/tool.constants.js.map +1 -1
  466. package/dist/domain/tool.js +2 -0
  467. package/dist/domain/tool.js.map +1 -1
  468. package/dist/domain/tool.types.d.ts +2 -0
  469. package/dist/domain/tool.types.js.map +1 -1
  470. package/dist/domain/workflow/checkpoint.js +28 -1
  471. package/dist/domain/workflow/checkpoint.js.map +1 -1
  472. package/dist/domain/workflow/checkpoint.types.d.ts +11 -0
  473. package/dist/domain/workflow/checkpoint.types.js.map +1 -1
  474. package/dist/domain/workflow/workflow-state.js +15 -0
  475. package/dist/domain/workflow/workflow-state.js.map +1 -1
  476. package/dist/domain/workflow.types.d.ts +1 -0
  477. package/dist/domain/workflow.types.js.map +1 -1
  478. package/dist/index.d.ts +24 -3
  479. package/dist/index.js +8 -1
  480. package/dist/index.js.map +1 -1
  481. package/dist/infrastructure/conversations/harness-store.d.ts +1 -1
  482. package/dist/infrastructure/conversations/harness-store.js +5 -5
  483. package/dist/infrastructure/conversations/harness-store.js.map +1 -1
  484. package/dist/infrastructure/conversations/harness-transcript.js +6 -3
  485. package/dist/infrastructure/conversations/harness-transcript.js.map +1 -1
  486. package/dist/infrastructure/conversations/harness-transcript.types.d.ts +1 -0
  487. package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -1
  488. package/dist/infrastructure/file-manifest.d.ts +1 -0
  489. package/dist/infrastructure/file-manifest.js +17 -4
  490. package/dist/infrastructure/file-manifest.js.map +1 -1
  491. package/dist/infrastructure/recipe-download.d.ts +2 -0
  492. package/dist/infrastructure/recipe-download.js +72 -0
  493. package/dist/infrastructure/recipe-download.js.map +1 -0
  494. package/dist/infrastructure/recipe-download.types.d.ts +4 -0
  495. package/dist/infrastructure/recipe-download.types.js +2 -0
  496. package/dist/infrastructure/recipe-download.types.js.map +1 -0
  497. package/dist/infrastructure/recipe.d.ts +7 -0
  498. package/dist/infrastructure/recipe.js +51 -0
  499. package/dist/infrastructure/recipe.js.map +1 -0
  500. package/dist/infrastructure/recipes/checkpoint-store.d.ts +3 -0
  501. package/dist/infrastructure/recipes/checkpoint-store.js +25 -0
  502. package/dist/infrastructure/recipes/checkpoint-store.js.map +1 -0
  503. package/dist/infrastructure/recipes/diagnostic.d.ts +1 -0
  504. package/dist/infrastructure/recipes/diagnostic.js +38 -0
  505. package/dist/infrastructure/recipes/diagnostic.js.map +1 -0
  506. package/dist/infrastructure/recipes/extensions.d.ts +3 -0
  507. package/dist/infrastructure/recipes/extensions.js +33 -0
  508. package/dist/infrastructure/recipes/extensions.js.map +1 -0
  509. package/dist/infrastructure/recipes/read.d.ts +1 -0
  510. package/dist/infrastructure/recipes/read.js +22 -0
  511. package/dist/infrastructure/recipes/read.js.map +1 -0
  512. package/dist/infrastructure/recipes/schema.d.ts +3 -0
  513. package/dist/infrastructure/recipes/schema.js +40 -0
  514. package/dist/infrastructure/recipes/schema.js.map +1 -0
  515. package/dist/infrastructure/recipes/workspace.d.ts +4 -0
  516. package/dist/infrastructure/recipes/workspace.js +49 -0
  517. package/dist/infrastructure/recipes/workspace.js.map +1 -0
  518. package/dist/infrastructure/transport-checkpoint.d.ts +1 -0
  519. package/dist/infrastructure/transport-checkpoint.js +3 -3
  520. package/dist/infrastructure/transport-checkpoint.js.map +1 -1
  521. package/dist/infrastructure/workspace-cleanup.d.ts +1 -0
  522. package/dist/infrastructure/workspace-cleanup.js +33 -0
  523. package/dist/infrastructure/workspace-cleanup.js.map +1 -0
  524. package/dist/infrastructure/workspace-files.constants.d.ts +6 -0
  525. package/dist/infrastructure/workspace-files.constants.js +7 -0
  526. package/dist/infrastructure/workspace-files.constants.js.map +1 -0
  527. package/dist/infrastructure/workspace-files.d.ts +6 -0
  528. package/dist/infrastructure/workspace-files.js +214 -0
  529. package/dist/infrastructure/workspace-files.js.map +1 -0
  530. package/dist/infrastructure/workspace-lock.constants.d.ts +2 -0
  531. package/dist/infrastructure/workspace-lock.constants.js +6 -0
  532. package/dist/infrastructure/workspace-lock.constants.js.map +1 -0
  533. package/dist/infrastructure/workspace-lock.d.ts +9 -0
  534. package/dist/infrastructure/workspace-lock.js +208 -0
  535. package/dist/infrastructure/workspace-lock.js.map +1 -0
  536. package/dist/infrastructure/workspace-lock.types.d.ts +20 -0
  537. package/dist/infrastructure/workspace-lock.types.js +2 -0
  538. package/dist/infrastructure/workspace-lock.types.js.map +1 -0
  539. package/dist/infrastructure/workspace-snapshot.d.ts +3 -0
  540. package/dist/infrastructure/workspace-snapshot.js +69 -0
  541. package/dist/infrastructure/workspace-snapshot.js.map +1 -0
  542. package/dist/providers/cloud-cache.js +1 -1
  543. package/dist/providers/cloud-cache.js.map +1 -1
  544. package/dist/providers/container-cache.d.ts +1 -1
  545. package/dist/providers/container-cache.js +2 -2
  546. package/dist/providers/container-cache.js.map +1 -1
  547. package/dist/providers/container-mounts.js +15 -3
  548. package/dist/providers/container-mounts.js.map +1 -1
  549. package/dist/providers/container.js +26 -2
  550. package/dist/providers/container.js.map +1 -1
  551. package/dist/providers/daytona.js +3 -2
  552. package/dist/providers/daytona.js.map +1 -1
  553. package/dist/providers/firecracker.js +4 -3
  554. package/dist/providers/firecracker.js.map +1 -1
  555. package/dist/providers/local.js +16 -1
  556. package/dist/providers/local.js.map +1 -1
  557. package/dist/providers/memory.js +16 -1
  558. package/dist/providers/memory.js.map +1 -1
  559. package/dist/providers/vercel.js +3 -2
  560. package/dist/providers/vercel.js.map +1 -1
  561. package/dist/providers/workspace-context.d.ts +3 -0
  562. package/dist/providers/workspace-context.js +31 -0
  563. package/dist/providers/workspace-context.js.map +1 -0
  564. package/dist/recipes.d.ts +7 -0
  565. package/dist/recipes.js +4 -0
  566. package/dist/recipes.js.map +1 -0
  567. package/package.json +19 -6
  568. package/recipe-configuration.schema.json +44324 -0
  569. package/recipe.schema.json +38554 -0
  570. package/recipes/catalog.json +54 -0
  571. package/recipes/compare-candidates.yaml +12 -0
  572. package/recipes/fix-and-check.yaml +22 -0
  573. package/recipes/queued-review.yaml +20 -0
  574. package/recipes/review-and-approve.yaml +27 -0
  575. package/recipes/review-change.yaml +24 -0
  576. package/recipes/review.yaml +13 -0
  577. package/recipes/update-docs.yaml +16 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # Changelog
2
2
 
3
+ ## 11.1.2
4
+
5
+ This release adds YAML workflow composition, terminal recipe dialogues and Git-free file workspaces while preserving existing Git APIs and defaults.
6
+
7
+ - Reorganize the English and French Guide around user tasks, with focused pages, preserved routes and section anchors, clearer setup paths and nine downloadable example projects. Make mobile diagrams readable without zoom and clarify desktop flow conditions. Correct journal/replay side effects, Git path handling and recovery instructions; document the local review report produced by the webhook example.
8
+ - Show every public API overload and its own property table, correctly mark required fields from mapped types, and link reference contracts to their practical guides.
9
+ - Define private vulnerability reporting through GitHub Security and security-fix support for the latest major version.
10
+ - Make recipe contract classification portable across Windows and POSIX source paths, and resolve temporary directory aliases in the macOS recovery test.
11
+ - Build public declarations before checking consumer fixture types so validation works on a fresh checkout.
12
+ - Prepare the Git-free Node image explicitly for container tests and document the required image pull.
13
+ - Create the host UID's account in the Git-free package test image, and adapt container documentation checks to the simplified setup example.
14
+ - Fix Windows output publication permission checks and relative file/directory link copies. Keep ownership and escape checks, and make recipe test cleanup, process assertions and host commands portable.
15
+
16
+ - Add explicit directory-copy, read-only/writable source-mount and ephemeral file workspaces without host Git, configuration version 3, provider workspace capabilities and file dispatch/report contracts. Preserve legacy Git APIs and configuration defaults. Journal protected output publication with conditional rollback and explicit recovery; conserve settled files and conversations for local or explicit Transport-backed portable resume. Cover independent commands, cross-process dialogue, interrupted publication and an installed CLI running with Node, Docker and tar on a host without Git. Native CLI file variants and live cloud/Firecracker validation remain unvalidated.
17
+
18
+ - Add a runnable Linear development recipe with a separate TypeScript application, validated private API-key caching, issue selection, plan approval, implementation, enforced tests and formatted observation. Extend terminal recipe interaction to unsigned gates with saved evidence and explicit decisions; signed gates retain external proof submission. Test the flow offline with real Git and simulated services; live Linear/Codex remains unvalidated.
19
+
20
+ - Handle durable recipe questions directly in the CLI: automatic terminal prompts, actor selection, saved answers and continuation without a custom runner. Add interactive/headless flags, keep JSON reporting final-only, and preserve pending questions on cancellation. Cover offline cross-process resume and real terminal input; no paid agent calls.
21
+
22
+ - Serve recipe and configuration JSON Schemas from documentation URLs under `/schemas/`, with immutable per-version copies reconstructed from stable Git tags. Preserve archives across GitHub Pages deployments, check JSON content and HTTP responses, and document editor setup in English and French.
23
+
24
+ - Complete the seven YAML composition lots with explicit experimental speculation, cumulative durable usage receipts, conflict resolvers, native reporters and OpenTelemetry. Keep machine settings in named local components, synchronize and close execution sandboxes before integration, and report resolver usage separately. Generate component documentation and enforce per-export/per-option parity classifications in CI. Add an offline community recipe and example; paid/cloud/remote-SDK validation remains absent.
25
+
26
+ - Compose YAML SQLite/HTTP/BullMQ queues, recipe and native workflow jobs, queued tasks, cron schedules and authenticated webhook services. Add explicit recipe enqueue/serve commands with native ownership, cancellation, token rotation and job identities. Verify local service composition and real Redis 7 without paid calls.
27
+
28
+ - Add durable YAML checkpoints with exact Git workspace restoration, artifacts, caches, signed gates, dialogues, quota pauses and cumulative budgets. Add recipe status/resume/answer/decide; require explicit replay and revision-fenced recovery after interruption. Exercise separate processes, preserved uncommitted files and original diff guards offline; live cloud restoration remains unvalidated.
29
+
30
+ - Compose format-3 workflows with structured JSON inputs, typed result references, conditions, transformations, local task callbacks, native loop and decision tasks, and isolated multi-repository dispatch. Preserve native scheduling and usage accounting, refuse overlapping shared workspaces, and project execution results to JSON. Add an offline example and YAML/TypeScript equivalence tests using real Git repositories.
31
+
32
+ - Compose the Outpost harness, model and decision providers, tools, skills, hooks, permissions, context strategies, routing, fallback agents and conversation stores from YAML. Format-3 agent steps accept dispatch options and structured response references. Callback extensions declare a static slot contract; schemas distinguish data schemas from component references. Compare delegated YAML and TypeScript runs offline, and exercise the compiled CLI against a local streaming model fixture.
33
+
34
+ - Extend YAML configuration with named providers, native sandbox and workspace options, portable profiles, CLI harness settings, MCP declarations, local transports and host-side secret selections. Generate option schemas from TypeScript contracts, reject dependency cycles before imports, resolve installed ESM-only extensions, and redact selected values from observation and reports. Cover local lifecycle execution and YAML/TypeScript request equivalence; cloud and paid agent calls remain unvalidated.
35
+
36
+ - Begin YAML composition parity with configuration format 2, recipe format 3, the `/recipes` registry/runtime API, explicit observation and final reports, static extension validation and a versioned public-contract inventory. Recipe execution is silent unless outputs or `--json` are requested; failures still print diagnostics.
37
+
38
+ - Add reusable YAML recipes with typed inputs, defaults and enums, dependency result references and editor schemas. Run with separate recipe and execution YAML files covering sandbox providers, CLI agents, model selection and explicit credential references; retain literal format 1 and TypeScript configuration compatibility. Add `recipe init`, allocation-free `validate`, `list` and integrity-checked `fetch`, repeated `--input` flags, three bundled Git catalogue recipes and third-party HTTPS catalogues. Fix CLI Git integration, bounded outputs and diagnostics, and final reporting after cleanup. Cover real local Git execution and cross-repository reuse; HTTP downloads are tested with simulated responses and paid agent/cloud runs remain unvalidated.
39
+
40
+ ## 11.1.1
41
+
42
+ Publication was blocked after coverage passed: the SQLite recipe example deleted its temporary directory before closing its inspection queue on Windows. No package or documentation deployment was published. Version 11.1.2 fixes cleanup order and checks examples and package consumption before coverage in CI.
43
+
44
+ ## 11.1.0
45
+
46
+ Publication was blocked by a Windows regression test that incremented an inode beyond JavaScript's safe integer precision. No package or documentation deployment was published. The fixture was corrected for the next release attempt.
47
+
3
48
  ## 11.0.1
4
49
 
5
50
  This major release adds workspace integration safeguards, portable agent profiles, execution reports and state tracking, monetary budgets, incremental preparation, cloud dependency caches, offline workflow testing and optional secret sources. Update exhaustive consumers for `FaultCode` (`guard`, `stuck`), `AgentEvent` and `ObservationEvent` (`stuck`), stopped reasons (`stuck`), `StorageCategoryName` (`runs`) and `WorkflowBudgetExceeded.dimension` (`cost`). Implementations and test doubles of `DispatchResult` and `WarmDispatchResult` must provide `report()`; custom `ObservationHub` implementations must provide `redacting` and `redact()`. Existing entry points remain available. Best-of-N speculation remains experimental, and the live-validation limits below still apply.
package/README.md CHANGED
@@ -24,6 +24,8 @@
24
24
 
25
25
  Outpost is a TypeScript library and CLI for running coding agents in sandboxes and composing their work. Give an agent a task, choose its execution environment, and collect its answer, commits and usage. Start with one request; add parallel tasks, verification loops and human decisions as your workflow grows.
26
26
 
27
+ Directory and ephemeral workspaces run commands and compatible harnesses without host Git. Configuration version 3 declares file sources, runtime storage and protected output publication; existing Git defaults stay unchanged. See the [English guide](docs/src/content/docs/guide/workspaces.md) or [French guide](docs/src/content/docs/fr/guide/workspaces.md).
28
+
27
29
  ## Why Outpost?
28
30
 
29
31
  - **Choose your agent and sandbox independently.** Run Claude Code, Codex, Antigravity, GitHub Copilot CLI or Kimi Code with Docker, Podman, Vercel or Daytona.
@@ -34,7 +36,7 @@ Outpost is a TypeScript library and CLI for running coding agents in sandboxes a
34
36
 
35
37
  ## Quickstart
36
38
 
37
- You need **Node.js 24+**, **Git**, a repository with at least one commit, and **Docker** running. This example uses Codex with account authentication: prepare its host login using the [Codex guide](https://elie-laloum.github.io/outpost/guide/codex/) before running a task. [Authentication](https://elie-laloum.github.io/outpost/guide/authentication/) covers other agents and API-key billing.
39
+ You need **Node.js 24+**, **Git**, a repository with a committed README, and **Docker** running. This example uses Codex with account authentication: prepare its host login using the [Codex guide](https://elie-laloum.github.io/outpost/guide/codex/) before running a task. [Authentication](https://elie-laloum.github.io/outpost/guide/authentication/) covers other agents and API-key billing.
38
40
 
39
41
  Install the package, then build the agent image in a dedicated directory:
40
42
 
@@ -54,7 +56,6 @@ Use an ESM directory (`"type": "module"` in `package.json`); a CommonJS reposito
54
56
  import {
55
57
  createAgent,
56
58
  createCodexHarness,
57
- createReporter,
58
59
  dispatch,
59
60
  } from "@elie-laloum/outpost";
60
61
  import { createDockerSandboxProvider } from "@elie-laloum/outpost/providers/docker";
@@ -65,17 +66,15 @@ const result = await dispatch({
65
66
  harness: createCodexHarness({ authentication: "account" }),
66
67
  }),
67
68
  sandboxProvider: createDockerSandboxProvider({ image: "outpost:dev" }),
68
- observe: createReporter(),
69
- branch: { mode: "named", name: "outpost/fix-tests" },
69
+ branch: { mode: "named", name: "outpost/readme-review" },
70
70
  brief: {
71
- text: "Fix the failing tests, run them to verify and commit the change.",
71
+ text: "Review the README setup instructions. Report problems or say none were found. Do not edit files.",
72
72
  },
73
73
  });
74
74
 
75
- // Example output:
76
- // [outpost · pass 1] running · codex
77
- // Fixed the failing tests and committed the change.
78
- // [outpost · pass 1] finished · 12.00s · status 0 · input 1200 · cache read 0 · cache write 0 · output 320
75
+ console.log(result.text);
76
+ console.log(result.commits);
77
+ // Expected commits: []
79
78
  ```
80
79
 
81
80
  `dispatch()` closes the sandbox it allocates; the named branch remains for review. Use a fresh branch name for each independent task. The agent’s answer is not an enforced test result: add explicit verification when checks must gate integration.
@@ -95,6 +94,7 @@ const result = await dispatch({
95
94
  | Build an agent with your own tools and instructions | [Custom harness](https://elie-laloum.github.io/outpost/guide/harness/) |
96
95
  | Read execution state by ID | [Execution state](https://elie-laloum.github.io/outpost/guide/run-state/) |
97
96
  | Test workflows without accounts or model calls | [Workflow testing](https://elie-laloum.github.io/outpost/guide/testing-workflows/) |
97
+ | Create, share and run YAML recipes | [YAML recipes](https://elie-laloum.github.io/outpost/guide/yaml-recipes/) |
98
98
  | Resume or recover interrupted work | [Failure recovery](https://elie-laloum.github.io/outpost/guide/recovery/) |
99
99
 
100
100
  The [Guide](https://elie-laloum.github.io/outpost/guide/introduction/) explains behavior with focused examples. The [Reference](https://elie-laloum.github.io/outpost/reference/) documents exact contracts. Both are available in English and French.
package/SECURITY.md CHANGED
@@ -2,9 +2,19 @@
2
2
 
3
3
  Outpost runs coding agents that execute arbitrary project commands. Use it with repositories and credentials appropriate for that task.
4
4
 
5
+ ## File workspaces
6
+
7
+ File workspaces can run without Git. Directory copies exclude Git and Outpost control metadata; ordinary source files remain data, including any credential files the caller selected. New copies, snapshots and publications reject outgoing links and special files; link checks expand captured aliases before parent traversal and refuse missing targets or excluded aliases. Explicit source mounts expose the complete source; writable mounts change it immediately and cleanup never rolls those effects back. Owned working roots and runtime control storage remain separate. The local provider remains unisolated.
8
+
9
+ Protected publication uses destination manifests, host-user overlap locks, same-filesystem quarantine, exclusive installation and conditional reverse rollback. These locks coordinate Outpost writers without preventing external edits. Publication is recoverable across operations, not an atomic transaction over an entire tree. Concurrent changes can leave backups and journal operations requiring explicit recovery. File snapshots establish file integrity, not disposal of unknown cloud resources or authorization to recover owners and replay interrupted work.
10
+
11
+ ## Sandbox access
12
+
5
13
  By default, Docker/Podman expose the selected checkout, Git metadata and explicit volumes. The Docker socket is not mounted by default. Containers use a chosen UID/GID, dropped capabilities, no-new-privileges and a private home. Extra devices, writable mounts and elevated hooks expand the boundary deliberately.
6
14
 
7
- Shared Git metadata is writable by the agent. A mounted sandbox is not an adversarial boundary protecting the host repository or its configuration. Outpost disables host Git hooks for its own Git commands, but a malicious repository can contain other executable configuration or project tooling. Do not run untrusted repositories with valuable host credentials. Host `local()` provides no isolation.
15
+ Shared Git metadata is writable by the agent. A mounted sandbox is not an adversarial boundary protecting the host repository or its configuration. Outpost disables host Git hooks for its own Git commands, but a malicious repository can contain other executable configuration or project tooling. Do not run untrusted repositories with valuable host credentials. Host `createLocalSandboxProvider()` provides no isolation.
16
+
17
+ ## Git and integration
8
18
 
9
19
  Workspace diff guards are integration checks, not filesystem permissions or an adversarial security boundary. They inspect only the final committed diff: an agent can modify files and restore them before the check, and uncommitted files are excluded. Use named or integration workspaces to retain refused work separately from the host checkout.
10
20
 
@@ -20,20 +30,36 @@ Portable agent profiles carry literal guidance and protocol tool restrictions, n
20
30
 
21
31
  MCP servers are programs or endpoints you choose; they receive the variables you name and act with the agent's authority. Outpost writes MCP configuration with variable references only, never secret values. Kimi and Antigravity configuration is merged into the agent home file, which is the user's own home with `createLocalSandboxProvider()`. Built-in harness servers and their HTTP bridge run inside the sandbox, so egress policies apply to them; CLI agents contact HTTP servers themselves from the sandbox. `oauth: "login"` copies the selected MCP OAuth tokens of Claude Code, Codex or Kimi from the host into the private sandbox home; a refresh there can rotate the refresh token and invalidate the host login. OAuth client secrets for the built-in harness stay in the sandbox environment.
22
32
 
33
+ ## Secrets in saved data
34
+
23
35
  Conversation transcripts, logs, bundles and patches may contain secrets. Optional `redact` expressions mask matching strings before Outpost observation receivers and supported conversation captures, including decoded text session bundles. They do not detect unknown secrets, join fragments across event boundaries, rewrite native sandbox files or temporary staging, sanitize checkpoints, returned values other than run reports or existing archives, or make arbitrary binary content safe. A masked transcript can lose data needed for native resume or signed reasoning replay. Runtime files are ignored by Git and sensitive files are created with restrictive permissions where supported. Keep API keys in environment variables or ignored `.env` files. Never embed tokens in tracked configuration, remote URLs or examples.
24
36
 
25
- Report vulnerabilities privately using the repository's security reporting channel when enabled, or contact the maintainer through the hosting profile. Do not include live credentials in reports. V1 receives fixes for reproducible security defects.
37
+ ## Reporting and supported versions
38
+
39
+ Report vulnerabilities privately through [GitHub Security](https://github.com/elie-laloum/outpost/security/advisories/new). Do not include live credentials in reports. Only the latest major version receives security fixes; upgrade to that major before requesting a fix for an older release.
40
+
41
+ ## Shared storage and ownership
26
42
 
27
43
  Explicit storage transports can send artifacts, journals, transcripts, recovery payloads, execution snapshots, observation events and operational metadata to the configured object store. Run projections share the bounded delivery and redaction limits of other observation sinks; an expired heartbeat is suspected abandonment and never authorizes replay or resource recovery. The caller owns the S3 client and credentials; they are not forwarded to agents. Use a dedicated private bucket prefix and access policy. Object revisions fence cooperating writers but do not authenticate artifact producers or operators. Stop an abandoned runner independently before releasing its checkpoint ownership; a remote PID is not proof of inactivity.
28
44
 
45
+ ## Firecracker
46
+
29
47
  The optional Firecracker jailer mode requires a trusted root supervisor and root-owned boot assets, executables, SSH trust files, jail base and cgroup v2 parent. Outpost does not elevate privileges. The VMM drops to the explicitly selected non-root UID/GID, uses the jailer's mount namespace and receives CPU, memory, swap and process limits. The supervisor remains privileged and outside the VMM cgroup; its workflow code, configuration, dependencies and transfer destinations must be trusted. Guest file downloads currently buffer individual files in the supervisor, so the VMM memory limit is not a total host-resource budget. Kernel work outside that cgroup is likewise not charged to its CPU quota. Operators own TAP setup, network filtering, parent resources and crash recovery. Control-plane resource accounting and adversarial validation of this mode remain open.
30
48
 
49
+ ## Network policies
50
+
31
51
  Egress policies restrict sandbox outbound connections, not host model-provider or decision-provider calls, image downloads or cloud control-plane traffic. Vercel domain rules inspect TLS SNI rather than encrypted HTTP Host headers; allowed CIDRs grant independent IP access and denied CIDRs take precedence. A domain allowlist is not a general defense against exfiltration through allowed services or shared infrastructure. Mounted host sockets can expose separate network capabilities. Outpost copies network configuration at provider composition.
32
52
 
33
53
  Daytona egress is sent at creation and confirmed through its network-update API before Outpost prepares the workspace or exposes the lease. A rejected confirmation fails acquisition and triggers deletion. Tier 3/4 and WRITE_SANDBOXES are required; native creation options alone do not establish this guarantee. Autonomous image startup precedes confirmation and must be trusted, without embedded secrets or startup workloads. Unsupported combinations and wildcard patterns that would implicitly grant apex access are rejected. Docker/Podman allowlists remain unsupported; local and Firecracker execution reject Outpost egress policies. See the bilingual outbound-network guide for capabilities and live-validation limits.
34
54
 
55
+ ## Approvals and idempotency
56
+
35
57
  Signed workflow gates verify an Ed25519 key bound to an approver, not a human login. The signing service must authenticate the user and their intent. Keep private keys outside worker sandboxes; trust the configured verifier and public-key source. Gate authentication requirements participate in checkpoint identity, but signatures do not authenticate checkpoint storage. Revocation rejects new proofs and does not undo already persisted decisions. HTTP queue bearer tokens authorize all queue operations; dynamic token sources allow rotation, not tenant isolation. Use trusted TLS termination for remote connections. Idempotency keys only prevent duplicate external effects when the effect service atomically deduplicates them and retains receipts throughout the replay window.
36
58
 
59
+ ## Dependency caches
60
+
37
61
  Cloud dependency caches archive only the declared download directories through a host-side Transport. Storage credentials are not installed in the sandbox. Later runs trust the bytes written by previous agents and transport writers; keep credentials out of caches and use a private prefix. Immutable cache snapshots persist until explicitly removed, including superseded or unpublished snapshots. Compatibility hashes and chunk digests provide isolation and integrity, not producer authentication.
38
62
 
63
+ ## Secret managers
64
+
39
65
  Secret-source resolution runs on the host before sandbox allocation. Outpost reads only requested names and returns immutable variables without writing the values to disk or changing process.env. Vault/OpenBao KV v2 and AWS JSON fields require fetching an enclosing document; split unrelated secrets when they must not be fetched together. Injected SDK clients are caller-owned, and their authentication configuration and caching remain the caller’s responsibility. fromSecrets discards vendor exception messages and causes; never log the returned object. The selected values become readable by every process receiving those variables. Startup snapshots do not rotate inside a running sandbox.
@@ -43,6 +43,11 @@ export function scriptedAgent(options) {
43
43
  const adapter = {
44
44
  kind: "cli",
45
45
  harness,
46
+ fileWorkspaces: {
47
+ dispatch: !options.turns.some((turn) => turn.commit),
48
+ continuation: true,
49
+ repairs: true,
50
+ },
46
51
  name: options.name ?? "scripted",
47
52
  usage: "events",
48
53
  capture: false,
@@ -1 +1 @@
1
- {"version":3,"file":"scripted-agent.js","sourceRoot":"","sources":["../../../src/adapters/testing/scripted-agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type {\n AgentEvent,\n CliAgent,\n CliHarness,\n} from \"../../domain/agent.types.ts\";\nimport { invariant, OutpostError } from \"../../domain/errors.ts\";\nimport { scriptedExecutable } from \"../../infrastructure/scripted-turn.constants.ts\";\nimport { readScriptedRecipe } from \"../../infrastructure/scripted-turn.ts\";\nimport type { ScriptedAgentOptions } from \"./scripted-agent.types.ts\";\n\nexport function scriptedAgent(options: ScriptedAgentOptions): CliAgent {\n invariant(\n options.turns.length > 0,\n \"Scripted agents require at least one turn\",\n );\n invariant(\n options.name === undefined || options.name.trim().length > 0,\n \"Scripted agent name cannot be empty\",\n );\n const conversation = randomUUID();\n const decoded = new Map<string, AgentEvent>();\n const recipes = options.turns.map((turn) => {\n const events: AgentEvent[] = [\n { kind: \"conversation\", id: conversation },\n ...structuredClone(turn.events ?? []),\n ];\n invariant(\n !turn.events?.some((event) => event.kind === \"conversation\"),\n \"Scripted agents own their conversation identifier\",\n );\n if (turn.text !== undefined) events.push({ kind: \"text\", text: turn.text });\n if (turn.usage || !events.some((event) => event.kind === \"usage\")) {\n invariant(\n !turn.usage || !events.some((event) => event.kind === \"usage\"),\n \"Declare usage in either events or usage\",\n );\n events.push({\n kind: \"usage\",\n tokens: { input: 0, cached: 0, output: 0, ...turn.usage },\n });\n }\n if (!events.some((event) => event.kind === \"finished\"))\n events.push({ kind: \"finished\" });\n const lines = events.map((event) => {\n const line = JSON.stringify(event);\n decoded.set(line, event);\n return line;\n });\n const text = JSON.stringify({\n events: lines,\n status: turn.status ?? 0,\n stderr: turn.stderr ?? \"\",\n ...(turn.commit ? { commit: turn.commit } : {}),\n });\n readScriptedRecipe(text);\n return text;\n });\n let next = 0;\n const harness: CliHarness = { kind: \"cli\", bind: () => adapter };\n const adapter: CliAgent = {\n kind: \"cli\",\n harness,\n name: options.name ?? \"scripted\",\n usage: \"events\",\n capture: false,\n resumable: true,\n forkable: false,\n requiresFinishedEvent: true,\n request(input) {\n invariant(\n !input.interactive && !input.liveInput && !input.continuation?.fork,\n \"Scripted agents do not support terminals, live input or fork\",\n );\n invariant(\n !input.continuation || input.continuation.id === conversation,\n \"Unknown scripted conversation\",\n );\n const recipe = recipes[next++];\n if (recipe === undefined)\n throw new OutpostError(\"process\", \"Scripted agent turns exhausted\");\n return {\n executable: scriptedExecutable,\n arguments: [recipe],\n stdin: input.text ?? \"\",\n };\n },\n events(line) {\n const event = decoded.get(line);\n invariant(event, \"Unexpected scripted agent event\");\n return [structuredClone(event)];\n },\n };\n return adapter;\n}\n"]}
1
+ {"version":3,"file":"scripted-agent.js","sourceRoot":"","sources":["../../../src/adapters/testing/scripted-agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type {\n AgentEvent,\n CliAgent,\n CliHarness,\n} from \"../../domain/agent.types.ts\";\nimport { invariant, OutpostError } from \"../../domain/errors.ts\";\nimport { scriptedExecutable } from \"../../infrastructure/scripted-turn.constants.ts\";\nimport { readScriptedRecipe } from \"../../infrastructure/scripted-turn.ts\";\nimport type { ScriptedAgentOptions } from \"./scripted-agent.types.ts\";\n\nexport function scriptedAgent(options: ScriptedAgentOptions): CliAgent {\n invariant(\n options.turns.length > 0,\n \"Scripted agents require at least one turn\",\n );\n invariant(\n options.name === undefined || options.name.trim().length > 0,\n \"Scripted agent name cannot be empty\",\n );\n const conversation = randomUUID();\n const decoded = new Map<string, AgentEvent>();\n const recipes = options.turns.map((turn) => {\n const events: AgentEvent[] = [\n { kind: \"conversation\", id: conversation },\n ...structuredClone(turn.events ?? []),\n ];\n invariant(\n !turn.events?.some((event) => event.kind === \"conversation\"),\n \"Scripted agents own their conversation identifier\",\n );\n if (turn.text !== undefined) events.push({ kind: \"text\", text: turn.text });\n if (turn.usage || !events.some((event) => event.kind === \"usage\")) {\n invariant(\n !turn.usage || !events.some((event) => event.kind === \"usage\"),\n \"Declare usage in either events or usage\",\n );\n events.push({\n kind: \"usage\",\n tokens: { input: 0, cached: 0, output: 0, ...turn.usage },\n });\n }\n if (!events.some((event) => event.kind === \"finished\"))\n events.push({ kind: \"finished\" });\n const lines = events.map((event) => {\n const line = JSON.stringify(event);\n decoded.set(line, event);\n return line;\n });\n const text = JSON.stringify({\n events: lines,\n status: turn.status ?? 0,\n stderr: turn.stderr ?? \"\",\n ...(turn.commit ? { commit: turn.commit } : {}),\n });\n readScriptedRecipe(text);\n return text;\n });\n let next = 0;\n const harness: CliHarness = { kind: \"cli\", bind: () => adapter };\n const adapter: CliAgent = {\n kind: \"cli\",\n harness,\n fileWorkspaces: {\n dispatch: !options.turns.some((turn) => turn.commit),\n continuation: true,\n repairs: true,\n },\n name: options.name ?? \"scripted\",\n usage: \"events\",\n capture: false,\n resumable: true,\n forkable: false,\n requiresFinishedEvent: true,\n request(input) {\n invariant(\n !input.interactive && !input.liveInput && !input.continuation?.fork,\n \"Scripted agents do not support terminals, live input or fork\",\n );\n invariant(\n !input.continuation || input.continuation.id === conversation,\n \"Unknown scripted conversation\",\n );\n const recipe = recipes[next++];\n if (recipe === undefined)\n throw new OutpostError(\"process\", \"Scripted agent turns exhausted\");\n return {\n executable: scriptedExecutable,\n arguments: [recipe],\n stdin: input.text ?? \"\",\n };\n },\n events(line) {\n const event = decoded.get(line);\n invariant(event, \"Unexpected scripted agent event\");\n return [structuredClone(event)];\n },\n };\n return adapter;\n}\n"]}
@@ -1,2 +1,3 @@
1
1
  import type { HarnessToolset } from "../../domain/tool.types.ts";
2
- export declare function createHarnessFileTools(): HarnessToolset;
2
+ import type { FileSelectionOptions } from "./tools.types.ts";
3
+ export declare function createHarnessFileTools(options?: FileSelectionOptions): HarnessToolset;
@@ -3,10 +3,15 @@ import { glob } from "../../domain/glob.js";
3
3
  import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
4
4
  import { anywhere, downloadFile, repositoryPath, withStaging, } from "./sandbox-files.js";
5
5
  import { TOOL_LIMITS } from "./tools.constants.js";
6
- export function createHarnessFileTools() {
6
+ import { filesystemSelectionScript } from "./filesystem-selection.constants.js";
7
+ import { invariant } from "../../domain/errors.js";
8
+ export function createHarnessFileTools(options = {}) {
9
+ invariant(options.selection === undefined ||
10
+ options.selection === "git" ||
11
+ options.selection === "filesystem", "File selection must be git or filesystem");
7
12
  return defineHarnessToolset({
8
13
  name: "files",
9
- tools: [readFileTool(), listFilesTool()],
14
+ tools: [readFileTool(), listFilesTool(options.selection ?? "git")],
10
15
  });
11
16
  }
12
17
  function readFileTool() {
@@ -44,10 +49,13 @@ function readFileTool() {
44
49
  }),
45
50
  });
46
51
  }
47
- function listFilesTool() {
52
+ function listFilesTool(selection) {
48
53
  return defineHarnessTool({
54
+ ...(selection === "git" ? { workspace: "git" } : {}),
49
55
  name: "list_files",
50
- description: "List files in the repository that are tracked or not ignored by Git, optionally under a directory and filtered by a glob such as src/**/*.ts; a glob without a slash matches file names at any depth.",
56
+ description: selection === "git"
57
+ ? "List files tracked or not ignored by Git, optionally under a directory and filtered by a glob."
58
+ : "List ordinary workspace files without following links or applying Git ignore rules, optionally under a directory and filtered by a glob.",
51
59
  readOnly: true,
52
60
  input: {
53
61
  type: "object",
@@ -60,23 +68,37 @@ function listFilesTool() {
60
68
  resources: (input) => ({ paths: [input.path ?? "."] }),
61
69
  async execute(input, context) {
62
70
  const scope = repositoryPath(input.path ?? ".") || ".";
71
+ const invocation = selection === "filesystem"
72
+ ? {
73
+ executable: "node",
74
+ arguments: [
75
+ "-e",
76
+ `(function(){${filesystemSelectionScript}})()`,
77
+ "list",
78
+ scope,
79
+ "{}",
80
+ ],
81
+ }
82
+ : {
83
+ executable: "git",
84
+ arguments: [
85
+ "ls-files",
86
+ "-z",
87
+ "--cached",
88
+ "--others",
89
+ "--exclude-standard",
90
+ "--",
91
+ scope,
92
+ ],
93
+ };
63
94
  const result = await context.sandbox.invoke({
64
- executable: "git",
65
- arguments: [
66
- "ls-files",
67
- "-z",
68
- "--cached",
69
- "--others",
70
- "--exclude-standard",
71
- "--",
72
- scope,
73
- ],
95
+ ...invocation,
74
96
  retain: TOOL_LIMITS.commandCharacters * 10,
75
97
  signal: context.signal,
76
98
  });
77
99
  if (result.status !== 0)
78
100
  return {
79
- content: result.stderr || "git ls-files failed",
101
+ content: result.stderr || "File listing failed",
80
102
  isError: true,
81
103
  };
82
104
  const matcher = input.pattern
@@ -1 +1 @@
1
- {"version":3,"file":"file-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/file-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { glob } from \"../../domain/glob.ts\";\nimport { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport {\n anywhere,\n downloadFile,\n repositoryPath,\n withStaging,\n} from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { ListFilesInput, ReadFileInput } from \"./tools.types.ts\";\n\nexport function createHarnessFileTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"files\",\n tools: [readFileTool(), listFilesTool()],\n });\n}\n\nfunction readFileTool() {\n return defineHarnessTool({\n name: \"read_file\",\n description:\n \"Read a UTF-8 text file relative to the repository root. Lines are numbered; use offset and limit for long files.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n offset: { type: \"integer\", minimum: 1 },\n limit: { type: \"integer\", minimum: 1, maximum: TOOL_LIMITS.readLines },\n },\n required: [\"path\"],\n additionalProperties: false,\n },\n resources: (input: ReadFileInput) => ({ paths: [input.path] }),\n execute: (input: ReadFileInput, context) =>\n withStaging(async (directory) => {\n const file = await downloadFile(\n context,\n input.path,\n join(directory, \"file\"),\n );\n const lines = file.bytes.toString(\"utf8\").split(/\\r?\\n/);\n if (lines.at(-1) === \"\") lines.pop();\n const start = (input.offset ?? 1) - 1;\n const selected = lines.slice(\n start,\n start + (input.limit ?? TOOL_LIMITS.readLines),\n );\n const width = String(start + selected.length).length;\n const body = selected\n .map(\n (line, index) =>\n `${String(start + index + 1).padStart(width)}\\t${line}`,\n )\n .join(\"\\n\");\n const end = start + selected.length;\n const note =\n end < lines.length || start > 0\n ? `\\n[lines ${start + 1}-${end} of ${lines.length}]`\n : \"\";\n return lines.length ? `${body}${note}` : \"(empty file)\";\n }),\n });\n}\n\nfunction listFilesTool() {\n return defineHarnessTool({\n name: \"list_files\",\n description:\n \"List files in the repository that are tracked or not ignored by Git, optionally under a directory and filtered by a glob such as src/**/*.ts; a glob without a slash matches file names at any depth.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n pattern: { type: \"string\", minLength: 1 },\n },\n additionalProperties: false,\n },\n resources: (input: ListFilesInput) => ({ paths: [input.path ?? \".\"] }),\n async execute(input: ListFilesInput, context) {\n const scope = repositoryPath(input.path ?? \".\") || \".\";\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"ls-files\",\n \"-z\",\n \"--cached\",\n \"--others\",\n \"--exclude-standard\",\n \"--\",\n scope,\n ],\n retain: TOOL_LIMITS.commandCharacters * 10,\n signal: context.signal,\n });\n if (result.status !== 0)\n return {\n content: result.stderr || \"git ls-files failed\",\n isError: true,\n };\n const matcher = input.pattern\n ? glob(anywhere(input.pattern), \"path\")\n : undefined;\n const files = [...new Set(result.stdout.split(\"\\0\").filter(Boolean))]\n .filter((file) => !matcher || matcher.test(file))\n .sort();\n const shown = files.slice(0, TOOL_LIMITS.listEntries);\n if (!shown.length) return \"No files found.\";\n return shown.length < files.length\n ? `${shown.join(\"\\n\")}\\n[${files.length - shown.length} more files; narrow the path or pattern]`\n : shown.join(\"\\n\");\n },\n });\n}\n"]}
1
+ {"version":3,"file":"file-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/file-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { glob } from \"../../domain/glob.ts\";\nimport { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport {\n anywhere,\n downloadFile,\n repositoryPath,\n withStaging,\n} from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type {\n FileSelectionOptions,\n ListFilesInput,\n ReadFileInput,\n} from \"./tools.types.ts\";\nimport { filesystemSelectionScript } from \"./filesystem-selection.constants.ts\";\nimport { invariant } from \"../../domain/errors.ts\";\n\nexport function createHarnessFileTools(\n options: FileSelectionOptions = {},\n): HarnessToolset {\n invariant(\n options.selection === undefined ||\n options.selection === \"git\" ||\n options.selection === \"filesystem\",\n \"File selection must be git or filesystem\",\n );\n return defineHarnessToolset({\n name: \"files\",\n tools: [readFileTool(), listFilesTool(options.selection ?? \"git\")],\n });\n}\n\nfunction readFileTool() {\n return defineHarnessTool({\n name: \"read_file\",\n description:\n \"Read a UTF-8 text file relative to the repository root. Lines are numbered; use offset and limit for long files.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n offset: { type: \"integer\", minimum: 1 },\n limit: { type: \"integer\", minimum: 1, maximum: TOOL_LIMITS.readLines },\n },\n required: [\"path\"],\n additionalProperties: false,\n },\n resources: (input: ReadFileInput) => ({ paths: [input.path] }),\n execute: (input: ReadFileInput, context) =>\n withStaging(async (directory) => {\n const file = await downloadFile(\n context,\n input.path,\n join(directory, \"file\"),\n );\n const lines = file.bytes.toString(\"utf8\").split(/\\r?\\n/);\n if (lines.at(-1) === \"\") lines.pop();\n const start = (input.offset ?? 1) - 1;\n const selected = lines.slice(\n start,\n start + (input.limit ?? TOOL_LIMITS.readLines),\n );\n const width = String(start + selected.length).length;\n const body = selected\n .map(\n (line, index) =>\n `${String(start + index + 1).padStart(width)}\\t${line}`,\n )\n .join(\"\\n\");\n const end = start + selected.length;\n const note =\n end < lines.length || start > 0\n ? `\\n[lines ${start + 1}-${end} of ${lines.length}]`\n : \"\";\n return lines.length ? `${body}${note}` : \"(empty file)\";\n }),\n });\n}\n\nfunction listFilesTool(selection: \"git\" | \"filesystem\") {\n return defineHarnessTool({\n ...(selection === \"git\" ? { workspace: \"git\" as const } : {}),\n name: \"list_files\",\n description:\n selection === \"git\"\n ? \"List files tracked or not ignored by Git, optionally under a directory and filtered by a glob.\"\n : \"List ordinary workspace files without following links or applying Git ignore rules, optionally under a directory and filtered by a glob.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n pattern: { type: \"string\", minLength: 1 },\n },\n additionalProperties: false,\n },\n resources: (input: ListFilesInput) => ({ paths: [input.path ?? \".\"] }),\n async execute(input: ListFilesInput, context) {\n const scope = repositoryPath(input.path ?? \".\") || \".\";\n const invocation =\n selection === \"filesystem\"\n ? {\n executable: \"node\",\n arguments: [\n \"-e\",\n `(function(){${filesystemSelectionScript}})()`,\n \"list\",\n scope,\n \"{}\",\n ],\n }\n : {\n executable: \"git\",\n arguments: [\n \"ls-files\",\n \"-z\",\n \"--cached\",\n \"--others\",\n \"--exclude-standard\",\n \"--\",\n scope,\n ],\n };\n const result = await context.sandbox.invoke({\n ...invocation,\n retain: TOOL_LIMITS.commandCharacters * 10,\n signal: context.signal,\n });\n if (result.status !== 0)\n return {\n content: result.stderr || \"File listing failed\",\n isError: true,\n };\n const matcher = input.pattern\n ? glob(anywhere(input.pattern), \"path\")\n : undefined;\n const files = [...new Set(result.stdout.split(\"\\0\").filter(Boolean))]\n .filter((file) => !matcher || matcher.test(file))\n .sort();\n const shown = files.slice(0, TOOL_LIMITS.listEntries);\n if (!shown.length) return \"No files found.\";\n return shown.length < files.length\n ? `${shown.join(\"\\n\")}\\n[${files.length - shown.length} more files; narrow the path or pattern]`\n : shown.join(\"\\n\");\n },\n });\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare const filesystemSelectionScript = "const fs=require('node:fs');const p=require('node:path');\nconst [mode,scope,encoded]=process.argv.slice(1);const options=JSON.parse(encoded);const root=process.cwd();let count=0,total=0;const files=[];\nconst visit=directory=>{for(const name of fs.readdirSync(p.join(root,directory)).sort()){if(name==='.git'||name==='.outpost')continue;const path=p.posix.join(directory,name),info=fs.lstatSync(p.join(root,path));if(++count>100000)throw Error('Filesystem selection exceeds entry limit');if(info.isSymbolicLink())continue;if(info.isDirectory()){visit(path);continue}if(info.isFile())files.push(path)}};\nfor(let ancestor=scope;ancestor!=='.';ancestor=p.dirname(ancestor)){if(fs.lstatSync(p.join(root,ancestor)).isSymbolicLink())throw Error('Filesystem selection cannot traverse links')}const info=fs.lstatSync(p.join(root,scope));if(info.isSymbolicLink())throw Error('Filesystem selection cannot traverse links');if(info.isDirectory())visit(scope==='.'?'':scope);else if(info.isFile())files.push(scope);\nif(mode==='list'){const text=files.join('\\0');if(Buffer.byteLength(text)>2000000)throw Error('Filesystem listing exceeds output limit');process.stdout.write(text);return}\nconst expression=new RegExp(options.pattern,options.ignore_case?'i':'');const matches=[];for(const path of files){if(options.glob&&!p.matchesGlob(path,options.glob.includes('/')?options.glob:'**/'+options.glob))continue;const info=fs.lstatSync(p.join(root,path));if(info.size>4194304)continue;total+=info.size;if(total>33554432)throw Error('Filesystem search exceeds byte limit');const file=fs.openSync(p.join(root,path),fs.constants.O_RDONLY|fs.constants.O_NOFOLLOW);let data;try{const before=fs.fstatSync(file);if(!before.isFile()||before.size>4194304)continue;const bounded=Buffer.alloc(before.size+1);let length=0;while(length<bounded.length){const read=fs.readSync(file,bounded,length,bounded.length-length,length);if(!read)break;length+=read}if(length>before.size)throw Error('Filesystem search source grew');data=bounded.subarray(0,length);const after=fs.fstatSync(file);if(before.size!==after.size||before.mtimeMs!==after.mtimeMs||before.ctimeMs!==after.ctimeMs)throw Error('Filesystem search source changed')}finally{fs.closeSync(file)}if(data.subarray(0,8000).includes(0))continue;const lines=data.toString('utf8').split(/\\r?\\n/);for(let i=0;i<lines.length;i++){if(!expression.test(lines[i]))continue;matches.push(path+':'+(i+1)+':'+lines[i]);if(Buffer.byteLength(matches.join('\\n'))>200000)throw Error('Filesystem search exceeds output limit');if(matches.length>(options.max_results??200)){process.stdout.write(matches.slice(0,-1).join('\\n')+'\\n[more matches; refine the search]');return}}}const text=matches.join('\\n');if(Buffer.byteLength(text)>200000)throw Error('Filesystem search exceeds output limit');process.stdout.write(text);";
@@ -0,0 +1,7 @@
1
+ export const filesystemSelectionScript = `const fs=require('node:fs');const p=require('node:path');
2
+ const [mode,scope,encoded]=process.argv.slice(1);const options=JSON.parse(encoded);const root=process.cwd();let count=0,total=0;const files=[];
3
+ const visit=directory=>{for(const name of fs.readdirSync(p.join(root,directory)).sort()){if(name==='.git'||name==='.outpost')continue;const path=p.posix.join(directory,name),info=fs.lstatSync(p.join(root,path));if(++count>100000)throw Error('Filesystem selection exceeds entry limit');if(info.isSymbolicLink())continue;if(info.isDirectory()){visit(path);continue}if(info.isFile())files.push(path)}};
4
+ for(let ancestor=scope;ancestor!=='.';ancestor=p.dirname(ancestor)){if(fs.lstatSync(p.join(root,ancestor)).isSymbolicLink())throw Error('Filesystem selection cannot traverse links')}const info=fs.lstatSync(p.join(root,scope));if(info.isSymbolicLink())throw Error('Filesystem selection cannot traverse links');if(info.isDirectory())visit(scope==='.'?'':scope);else if(info.isFile())files.push(scope);
5
+ if(mode==='list'){const text=files.join('\\0');if(Buffer.byteLength(text)>2000000)throw Error('Filesystem listing exceeds output limit');process.stdout.write(text);return}
6
+ const expression=new RegExp(options.pattern,options.ignore_case?'i':'');const matches=[];for(const path of files){if(options.glob&&!p.matchesGlob(path,options.glob.includes('/')?options.glob:'**/'+options.glob))continue;const info=fs.lstatSync(p.join(root,path));if(info.size>4194304)continue;total+=info.size;if(total>33554432)throw Error('Filesystem search exceeds byte limit');const file=fs.openSync(p.join(root,path),fs.constants.O_RDONLY|fs.constants.O_NOFOLLOW);let data;try{const before=fs.fstatSync(file);if(!before.isFile()||before.size>4194304)continue;const bounded=Buffer.alloc(before.size+1);let length=0;while(length<bounded.length){const read=fs.readSync(file,bounded,length,bounded.length-length,length);if(!read)break;length+=read}if(length>before.size)throw Error('Filesystem search source grew');data=bounded.subarray(0,length);const after=fs.fstatSync(file);if(before.size!==after.size||before.mtimeMs!==after.mtimeMs||before.ctimeMs!==after.ctimeMs)throw Error('Filesystem search source changed')}finally{fs.closeSync(file)}if(data.subarray(0,8000).includes(0))continue;const lines=data.toString('utf8').split(/\\r?\\n/);for(let i=0;i<lines.length;i++){if(!expression.test(lines[i]))continue;matches.push(path+':'+(i+1)+':'+lines[i]);if(Buffer.byteLength(matches.join('\\n'))>200000)throw Error('Filesystem search exceeds output limit');if(matches.length>(options.max_results??200)){process.stdout.write(matches.slice(0,-1).join('\\n')+'\\n[more matches; refine the search]');return}}}const text=matches.join('\\n');if(Buffer.byteLength(text)>200000)throw Error('Filesystem search exceeds output limit');process.stdout.write(text);`;
7
+ //# sourceMappingURL=filesystem-selection.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem-selection.constants.js","sourceRoot":"","sources":["../../../src/adapters/tools/filesystem-selection.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,yBAAyB,GAAG;;;;;qnDAK4kD,CAAC","sourcesContent":["export const filesystemSelectionScript = `const fs=require('node:fs');const p=require('node:path');\nconst [mode,scope,encoded]=process.argv.slice(1);const options=JSON.parse(encoded);const root=process.cwd();let count=0,total=0;const files=[];\nconst visit=directory=>{for(const name of fs.readdirSync(p.join(root,directory)).sort()){if(name==='.git'||name==='.outpost')continue;const path=p.posix.join(directory,name),info=fs.lstatSync(p.join(root,path));if(++count>100000)throw Error('Filesystem selection exceeds entry limit');if(info.isSymbolicLink())continue;if(info.isDirectory()){visit(path);continue}if(info.isFile())files.push(path)}};\nfor(let ancestor=scope;ancestor!=='.';ancestor=p.dirname(ancestor)){if(fs.lstatSync(p.join(root,ancestor)).isSymbolicLink())throw Error('Filesystem selection cannot traverse links')}const info=fs.lstatSync(p.join(root,scope));if(info.isSymbolicLink())throw Error('Filesystem selection cannot traverse links');if(info.isDirectory())visit(scope==='.'?'':scope);else if(info.isFile())files.push(scope);\nif(mode==='list'){const text=files.join('\\\\0');if(Buffer.byteLength(text)>2000000)throw Error('Filesystem listing exceeds output limit');process.stdout.write(text);return}\nconst expression=new RegExp(options.pattern,options.ignore_case?'i':'');const matches=[];for(const path of files){if(options.glob&&!p.matchesGlob(path,options.glob.includes('/')?options.glob:'**/'+options.glob))continue;const info=fs.lstatSync(p.join(root,path));if(info.size>4194304)continue;total+=info.size;if(total>33554432)throw Error('Filesystem search exceeds byte limit');const file=fs.openSync(p.join(root,path),fs.constants.O_RDONLY|fs.constants.O_NOFOLLOW);let data;try{const before=fs.fstatSync(file);if(!before.isFile()||before.size>4194304)continue;const bounded=Buffer.alloc(before.size+1);let length=0;while(length<bounded.length){const read=fs.readSync(file,bounded,length,bounded.length-length,length);if(!read)break;length+=read}if(length>before.size)throw Error('Filesystem search source grew');data=bounded.subarray(0,length);const after=fs.fstatSync(file);if(before.size!==after.size||before.mtimeMs!==after.mtimeMs||before.ctimeMs!==after.ctimeMs)throw Error('Filesystem search source changed')}finally{fs.closeSync(file)}if(data.subarray(0,8000).includes(0))continue;const lines=data.toString('utf8').split(/\\\\r?\\\\n/);for(let i=0;i<lines.length;i++){if(!expression.test(lines[i]))continue;matches.push(path+':'+(i+1)+':'+lines[i]);if(Buffer.byteLength(matches.join('\\\\n'))>200000)throw Error('Filesystem search exceeds output limit');if(matches.length>(options.max_results??200)){process.stdout.write(matches.slice(0,-1).join('\\\\n')+'\\\\n[more matches; refine the search]');return}}}const text=matches.join('\\\\n');if(Buffer.byteLength(text)>200000)throw Error('Filesystem search exceeds output limit');process.stdout.write(text);`;\n"]}
@@ -6,6 +6,7 @@ export function createHarnessGitTools() {
6
6
  name: "git",
7
7
  tools: [
8
8
  defineHarnessTool({
9
+ workspace: "git",
9
10
  name: "git",
10
11
  description: "Run a read-only Git command (status, diff, log or show) in the repository with extra arguments, for example log with -n 5 --oneline.",
11
12
  readOnly: true,
@@ -1 +1 @@
1
- {"version":3,"file":"git-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/git-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAG9B,MAAM,UAAU,qBAAqB;IACnC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,KAAK;QACX,KAAK,EAAE;YACL,iBAAiB,CAAC;gBAChB,IAAI,EAAE,KAAK;gBACX,WAAW,EACT,sIAAsI;gBACxI,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,iBAAiB,CAAC,EAAE;wBACzC,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;qBACxD;oBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;oBACrB,oBAAoB,EAAE,KAAK;iBAC5B;gBACD,SAAS,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,CAAC;oBAC/B,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;iBACtE,CAAC;gBACF,KAAK,CAAC,OAAO,CAAC,KAAe,EAAE,OAAO;oBACpC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACxD,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAClE,CAAC;oBACF,IAAI,OAAO;wBACT,OAAO;4BACL,OAAO,EAAE,2BAA2B,OAAO,EAAE;4BAC7C,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;wBAC1C,UAAU,EAAE,KAAK;wBACjB,SAAS,EAAE;4BACT,YAAY;4BACZ,KAAK,CAAC,OAAO;4BACb,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ;gCAC5B,CAAC,CAAC,EAAE;gCACJ,CAAC,CAAC,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;4BACvC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;yBAC3B;wBACD,KAAK,EAAE,EAAE;wBACT,MAAM,EAAE,WAAW,CAAC,iBAAiB;wBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAC;oBACH,OAAO;wBACL,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC;wBAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;qBAC7B,CAAC;gBACJ,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { commandOutput } from \"./sandbox-files.ts\";\nimport {\n GIT_BLOCKED_OPTIONS,\n GIT_READ_COMMANDS,\n TOOL_LIMITS,\n} from \"./tools.constants.ts\";\nimport type { GitInput } from \"./tools.types.ts\";\n\nexport function createHarnessGitTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"git\",\n tools: [\n defineHarnessTool({\n name: \"git\",\n description:\n \"Run a read-only Git command (status, diff, log or show) in the repository with extra arguments, for example log with -n 5 --oneline.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n command: { enum: [...GIT_READ_COMMANDS] },\n arguments: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"command\"],\n additionalProperties: false,\n },\n resources: (input: GitInput) => ({\n command: [\"git\", input.command, ...(input.arguments ?? [])].join(\" \"),\n }),\n async execute(input: GitInput, context) {\n const blocked = (input.arguments ?? []).find((argument) =>\n GIT_BLOCKED_OPTIONS.some((option) => argument.startsWith(option)),\n );\n if (blocked)\n return {\n content: `Unsupported Git option: ${blocked}`,\n isError: true,\n };\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"--no-pager\",\n input.command,\n ...(input.command === \"status\"\n ? []\n : [\"--no-ext-diff\", \"--no-textconv\"]),\n ...(input.arguments ?? []),\n ],\n stdin: \"\",\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n return {\n content: commandOutput(result),\n isError: result.status !== 0,\n };\n },\n }),\n ],\n });\n}\n"]}
1
+ {"version":3,"file":"git-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/git-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAG9B,MAAM,UAAU,qBAAqB;IACnC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,KAAK;QACX,KAAK,EAAE;YACL,iBAAiB,CAAC;gBAChB,SAAS,EAAE,KAAK;gBAChB,IAAI,EAAE,KAAK;gBACX,WAAW,EACT,sIAAsI;gBACxI,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,iBAAiB,CAAC,EAAE;wBACzC,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;qBACxD;oBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;oBACrB,oBAAoB,EAAE,KAAK;iBAC5B;gBACD,SAAS,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,CAAC;oBAC/B,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;iBACtE,CAAC;gBACF,KAAK,CAAC,OAAO,CAAC,KAAe,EAAE,OAAO;oBACpC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACxD,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAClE,CAAC;oBACF,IAAI,OAAO;wBACT,OAAO;4BACL,OAAO,EAAE,2BAA2B,OAAO,EAAE;4BAC7C,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;wBAC1C,UAAU,EAAE,KAAK;wBACjB,SAAS,EAAE;4BACT,YAAY;4BACZ,KAAK,CAAC,OAAO;4BACb,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ;gCAC5B,CAAC,CAAC,EAAE;gCACJ,CAAC,CAAC,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;4BACvC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;yBAC3B;wBACD,KAAK,EAAE,EAAE;wBACT,MAAM,EAAE,WAAW,CAAC,iBAAiB;wBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAC;oBACH,OAAO;wBACL,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC;wBAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;qBAC7B,CAAC;gBACJ,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { commandOutput } from \"./sandbox-files.ts\";\nimport {\n GIT_BLOCKED_OPTIONS,\n GIT_READ_COMMANDS,\n TOOL_LIMITS,\n} from \"./tools.constants.ts\";\nimport type { GitInput } from \"./tools.types.ts\";\n\nexport function createHarnessGitTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"git\",\n tools: [\n defineHarnessTool({\n workspace: \"git\",\n name: \"git\",\n description:\n \"Run a read-only Git command (status, diff, log or show) in the repository with extra arguments, for example log with -n 5 --oneline.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n command: { enum: [...GIT_READ_COMMANDS] },\n arguments: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"command\"],\n additionalProperties: false,\n },\n resources: (input: GitInput) => ({\n command: [\"git\", input.command, ...(input.arguments ?? [])].join(\" \"),\n }),\n async execute(input: GitInput, context) {\n const blocked = (input.arguments ?? []).find((argument) =>\n GIT_BLOCKED_OPTIONS.some((option) => argument.startsWith(option)),\n );\n if (blocked)\n return {\n content: `Unsupported Git option: ${blocked}`,\n isError: true,\n };\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"--no-pager\",\n input.command,\n ...(input.command === \"status\"\n ? []\n : [\"--no-ext-diff\", \"--no-textconv\"]),\n ...(input.arguments ?? []),\n ],\n stdin: \"\",\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n return {\n content: commandOutput(result),\n isError: result.status !== 0,\n };\n },\n }),\n ],\n });\n}\n"]}
@@ -1,2 +1,3 @@
1
1
  import type { HarnessToolset } from "../../domain/tool.types.ts";
2
- export declare function createHarnessSearchTools(): HarnessToolset;
2
+ import type { FileSelectionOptions } from "./tools.types.ts";
3
+ export declare function createHarnessSearchTools(options?: FileSelectionOptions): HarnessToolset;
@@ -1,13 +1,24 @@
1
1
  import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
2
2
  import { anywhere, repositoryPath } from "./sandbox-files.js";
3
3
  import { TOOL_LIMITS } from "./tools.constants.js";
4
- export function createHarnessSearchTools() {
5
- return defineHarnessToolset({ name: "search", tools: [searchTool()] });
4
+ import { filesystemSelectionScript } from "./filesystem-selection.constants.js";
5
+ import { invariant } from "../../domain/errors.js";
6
+ export function createHarnessSearchTools(options = {}) {
7
+ invariant(options.selection === undefined ||
8
+ options.selection === "git" ||
9
+ options.selection === "filesystem", "Search selection must be git or filesystem");
10
+ return defineHarnessToolset({
11
+ name: "search",
12
+ tools: [searchTool(options.selection ?? "git")],
13
+ });
6
14
  }
7
- function searchTool() {
15
+ function searchTool(selection) {
8
16
  return defineHarnessTool({
17
+ ...(selection === "git" ? { workspace: "git" } : {}),
9
18
  name: "search",
10
- description: "Search repository files that are tracked or not ignored by Git for an extended regular expression. Returns path:line:text matches. A glob without a slash matches file names at any depth.",
19
+ description: selection === "git"
20
+ ? "Search files tracked or not ignored by Git for an extended regular expression. Returns path:line:text matches."
21
+ : "Search ordinary workspace files for a JavaScript regular expression without following links or applying Git ignore rules. Returns path:line:text matches.",
11
22
  readOnly: true,
12
23
  input: {
13
24
  type: "object",
@@ -28,31 +39,50 @@ function searchTool() {
28
39
  resources: (input) => ({ paths: [input.path ?? "."] }),
29
40
  async execute(input, context) {
30
41
  const scope = repositoryPath(input.path ?? ".") || ".";
42
+ const invocation = selection === "filesystem"
43
+ ? {
44
+ executable: "node",
45
+ arguments: [
46
+ "-e",
47
+ `(function(){${filesystemSelectionScript}})()`,
48
+ "search",
49
+ scope,
50
+ JSON.stringify(input),
51
+ ],
52
+ }
53
+ : {
54
+ executable: "git",
55
+ arguments: [
56
+ "grep",
57
+ "--untracked",
58
+ "-n",
59
+ "-I",
60
+ "--no-color",
61
+ "--full-name",
62
+ "-E",
63
+ ...(input.ignore_case ? ["-i"] : []),
64
+ "-e",
65
+ input.pattern,
66
+ "--",
67
+ input.glob
68
+ ? `:(glob)${scope === "." ? "" : `${scope}/`}${anywhere(input.glob)}`
69
+ : scope,
70
+ ],
71
+ };
31
72
  const result = await context.sandbox.invoke({
32
- executable: "git",
33
- arguments: [
34
- "grep",
35
- "--untracked",
36
- "-n",
37
- "-I",
38
- "--no-color",
39
- "--full-name",
40
- "-E",
41
- ...(input.ignore_case ? ["-i"] : []),
42
- "-e",
43
- input.pattern,
44
- "--",
45
- input.glob
46
- ? `:(glob)${scope === "." ? "" : `${scope}/`}${anywhere(input.glob)}`
47
- : scope,
48
- ],
73
+ ...invocation,
49
74
  retain: TOOL_LIMITS.commandCharacters,
50
75
  signal: context.signal,
51
76
  });
52
77
  if (result.status === 1)
53
78
  return "No matches.";
54
79
  if (result.status !== 0)
55
- return { content: result.stderr || "git grep failed", isError: true };
80
+ return {
81
+ content: result.stderr || "File search failed",
82
+ isError: true,
83
+ };
84
+ if (!result.stdout)
85
+ return "No matches.";
56
86
  const limit = input.max_results ?? TOOL_LIMITS.searchMatches;
57
87
  const matches = result.stdout.split("\n").filter(Boolean);
58
88
  const shown = matches.slice(0, limit);
@@ -1 +1 @@
1
- {"version":3,"file":"search-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/search-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,MAAM,UAAU,wBAAwB;IACtC,OAAO,oBAAoB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,iBAAiB,CAAC;QACvB,IAAI,EAAE,QAAQ;QACd,WAAW,EACT,4LAA4L;QAC9L,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;gBACzC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;gBACtC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gBAChC,WAAW,EAAE;oBACX,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,CAAC;oBACV,OAAO,EAAE,WAAW,CAAC,aAAa;iBACnC;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,CAAC;YACrB,oBAAoB,EAAE,KAAK;SAC5B;QACD,SAAS,EAAE,CAAC,KAAkB,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACnE,KAAK,CAAC,OAAO,CAAC,KAAkB,EAAE,OAAO;YACvC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC1C,UAAU,EAAE,KAAK;gBACjB,SAAS,EAAE;oBACT,MAAM;oBACN,aAAa;oBACb,IAAI;oBACJ,IAAI;oBACJ,YAAY;oBACZ,aAAa;oBACb,IAAI;oBACJ,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACpC,IAAI;oBACJ,KAAK,CAAC,OAAO;oBACb,IAAI;oBACJ,KAAK,CAAC,IAAI;wBACR,CAAC,CAAC,UAAU,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;wBACrE,CAAC,CAAC,KAAK;iBACV;gBACD,MAAM,EAAE,WAAW,CAAC,iBAAiB;gBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,aAAa,CAAC;YAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBACrB,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,IAAI,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACxE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,IAAI,WAAW,CAAC,aAAa,CAAC;YAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACtC,OAAO,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;gBAClC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,mCAAmC;gBAC3F,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { anywhere, repositoryPath } from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { SearchInput } from \"./tools.types.ts\";\n\nexport function createHarnessSearchTools(): HarnessToolset {\n return defineHarnessToolset({ name: \"search\", tools: [searchTool()] });\n}\n\nfunction searchTool() {\n return defineHarnessTool({\n name: \"search\",\n description:\n \"Search repository files that are tracked or not ignored by Git for an extended regular expression. Returns path:line:text matches. A glob without a slash matches file names at any depth.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\", minLength: 1 },\n path: { type: \"string\" },\n glob: { type: \"string\", minLength: 1 },\n ignore_case: { type: \"boolean\" },\n max_results: {\n type: \"integer\",\n minimum: 1,\n maximum: TOOL_LIMITS.searchMatches,\n },\n },\n required: [\"pattern\"],\n additionalProperties: false,\n },\n resources: (input: SearchInput) => ({ paths: [input.path ?? \".\"] }),\n async execute(input: SearchInput, context) {\n const scope = repositoryPath(input.path ?? \".\") || \".\";\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"grep\",\n \"--untracked\",\n \"-n\",\n \"-I\",\n \"--no-color\",\n \"--full-name\",\n \"-E\",\n ...(input.ignore_case ? [\"-i\"] : []),\n \"-e\",\n input.pattern,\n \"--\",\n input.glob\n ? `:(glob)${scope === \".\" ? \"\" : `${scope}/`}${anywhere(input.glob)}`\n : scope,\n ],\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n if (result.status === 1) return \"No matches.\";\n if (result.status !== 0)\n return { content: result.stderr || \"git grep failed\", isError: true };\n const limit = input.max_results ?? TOOL_LIMITS.searchMatches;\n const matches = result.stdout.split(\"\\n\").filter(Boolean);\n const shown = matches.slice(0, limit);\n return shown.length < matches.length\n ? `${shown.join(\"\\n\")}\\n[${matches.length - shown.length} more matches; refine the search]`\n : shown.join(\"\\n\");\n },\n });\n}\n"]}
1
+ {"version":3,"file":"search-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/search-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { anywhere, repositoryPath } from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { FileSelectionOptions, SearchInput } from \"./tools.types.ts\";\nimport { filesystemSelectionScript } from \"./filesystem-selection.constants.ts\";\nimport { invariant } from \"../../domain/errors.ts\";\n\nexport function createHarnessSearchTools(\n options: FileSelectionOptions = {},\n): HarnessToolset {\n invariant(\n options.selection === undefined ||\n options.selection === \"git\" ||\n options.selection === \"filesystem\",\n \"Search selection must be git or filesystem\",\n );\n return defineHarnessToolset({\n name: \"search\",\n tools: [searchTool(options.selection ?? \"git\")],\n });\n}\n\nfunction searchTool(selection: \"git\" | \"filesystem\") {\n return defineHarnessTool({\n ...(selection === \"git\" ? { workspace: \"git\" as const } : {}),\n name: \"search\",\n description:\n selection === \"git\"\n ? \"Search files tracked or not ignored by Git for an extended regular expression. Returns path:line:text matches.\"\n : \"Search ordinary workspace files for a JavaScript regular expression without following links or applying Git ignore rules. Returns path:line:text matches.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\", minLength: 1 },\n path: { type: \"string\" },\n glob: { type: \"string\", minLength: 1 },\n ignore_case: { type: \"boolean\" },\n max_results: {\n type: \"integer\",\n minimum: 1,\n maximum: TOOL_LIMITS.searchMatches,\n },\n },\n required: [\"pattern\"],\n additionalProperties: false,\n },\n resources: (input: SearchInput) => ({ paths: [input.path ?? \".\"] }),\n async execute(input: SearchInput, context) {\n const scope = repositoryPath(input.path ?? \".\") || \".\";\n const invocation =\n selection === \"filesystem\"\n ? {\n executable: \"node\",\n arguments: [\n \"-e\",\n `(function(){${filesystemSelectionScript}})()`,\n \"search\",\n scope,\n JSON.stringify(input),\n ],\n }\n : {\n executable: \"git\",\n arguments: [\n \"grep\",\n \"--untracked\",\n \"-n\",\n \"-I\",\n \"--no-color\",\n \"--full-name\",\n \"-E\",\n ...(input.ignore_case ? [\"-i\"] : []),\n \"-e\",\n input.pattern,\n \"--\",\n input.glob\n ? `:(glob)${scope === \".\" ? \"\" : `${scope}/`}${anywhere(input.glob)}`\n : scope,\n ],\n };\n const result = await context.sandbox.invoke({\n ...invocation,\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n if (result.status === 1) return \"No matches.\";\n if (result.status !== 0)\n return {\n content: result.stderr || \"File search failed\",\n isError: true,\n };\n if (!result.stdout) return \"No matches.\";\n const limit = input.max_results ?? TOOL_LIMITS.searchMatches;\n const matches = result.stdout.split(\"\\n\").filter(Boolean);\n const shown = matches.slice(0, limit);\n return shown.length < matches.length\n ? `${shown.join(\"\\n\")}\\n[${matches.length - shown.length} more matches; refine the search]`\n : shown.join(\"\\n\");\n },\n });\n}\n"]}
@@ -1,4 +1,7 @@
1
1
  import type { GIT_READ_COMMANDS } from "./tools.constants.ts";
2
+ export interface FileSelectionOptions {
3
+ readonly selection?: "git" | "filesystem";
4
+ }
2
5
  export interface ReadFileInput {
3
6
  readonly path: string;
4
7
  readonly offset?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"tools.types.js","sourceRoot":"","sources":["../../../src/adapters/tools/tools.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { GIT_READ_COMMANDS } from \"./tools.constants.ts\";\n\nexport interface ReadFileInput {\n readonly path: string;\n readonly offset?: number;\n readonly limit?: number;\n}\n\nexport interface ListFilesInput {\n readonly path?: string;\n readonly pattern?: string;\n}\n\nexport interface WriteFileInput {\n readonly path: string;\n readonly content: string;\n}\n\nexport interface EditFileInput {\n readonly path: string;\n readonly old_text: string;\n readonly new_text: string;\n readonly replace_all?: boolean;\n}\n\nexport interface SearchInput {\n readonly pattern: string;\n readonly path?: string;\n readonly glob?: string;\n readonly ignore_case?: boolean;\n readonly max_results?: number;\n}\n\nexport interface ShellInput {\n readonly command: string;\n}\n\nexport interface GitInput {\n readonly command: (typeof GIT_READ_COMMANDS)[number];\n readonly arguments?: readonly string[];\n}\n\nexport interface ShellToolsOptions {\n readonly deadlineMs?: number;\n}\n\nexport interface SandboxFile {\n readonly staged: string;\n readonly bytes: Buffer;\n}\n"]}
1
+ {"version":3,"file":"tools.types.js","sourceRoot":"","sources":["../../../src/adapters/tools/tools.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { GIT_READ_COMMANDS } from \"./tools.constants.ts\";\n\nexport interface FileSelectionOptions {\n readonly selection?: \"git\" | \"filesystem\";\n}\n\nexport interface ReadFileInput {\n readonly path: string;\n readonly offset?: number;\n readonly limit?: number;\n}\n\nexport interface ListFilesInput {\n readonly path?: string;\n readonly pattern?: string;\n}\n\nexport interface WriteFileInput {\n readonly path: string;\n readonly content: string;\n}\n\nexport interface EditFileInput {\n readonly path: string;\n readonly old_text: string;\n readonly new_text: string;\n readonly replace_all?: boolean;\n}\n\nexport interface SearchInput {\n readonly pattern: string;\n readonly path?: string;\n readonly glob?: string;\n readonly ignore_case?: boolean;\n readonly max_results?: number;\n}\n\nexport interface ShellInput {\n readonly command: string;\n}\n\nexport interface GitInput {\n readonly command: (typeof GIT_READ_COMMANDS)[number];\n readonly arguments?: readonly string[];\n}\n\nexport interface ShellToolsOptions {\n readonly deadlineMs?: number;\n}\n\nexport interface SandboxFile {\n readonly staged: string;\n readonly bytes: Buffer;\n}\n"]}