@elie-laloum/outpost 4.2.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +5 -3
  3. package/dist/{cli/init-authentication.constants.js → adapters/agents/authentication.constants.js} +1 -1
  4. package/dist/adapters/agents/authentication.constants.js.map +1 -0
  5. package/dist/adapters/agents/authentication.d.ts +2 -0
  6. package/dist/adapters/agents/authentication.js +52 -0
  7. package/dist/adapters/agents/authentication.js.map +1 -0
  8. package/dist/adapters/agents/claude-adapter.d.ts +2 -2
  9. package/dist/adapters/agents/claude-adapter.js +30 -2
  10. package/dist/adapters/agents/claude-adapter.js.map +1 -1
  11. package/dist/adapters/agents/claude-request.d.ts +2 -2
  12. package/dist/adapters/agents/claude-request.js +3 -3
  13. package/dist/adapters/agents/claude-request.js.map +1 -1
  14. package/dist/adapters/agents/codex-adapter.d.ts +2 -2
  15. package/dist/adapters/agents/codex-adapter.js +17 -1
  16. package/dist/adapters/agents/codex-adapter.js.map +1 -1
  17. package/dist/adapters/agents/codex-provider.d.ts +2 -2
  18. package/dist/adapters/agents/codex-provider.js +1 -1
  19. package/dist/adapters/agents/codex-provider.js.map +1 -1
  20. package/dist/adapters/agents/codex-request.d.ts +2 -2
  21. package/dist/adapters/agents/codex-request.js +3 -3
  22. package/dist/adapters/agents/codex-request.js.map +1 -1
  23. package/dist/adapters/agents/gemini-adapter.d.ts +2 -2
  24. package/dist/adapters/agents/gemini-adapter.js +20 -1
  25. package/dist/adapters/agents/gemini-adapter.js.map +1 -1
  26. package/dist/adapters/agents/gemini-request.d.ts +2 -1
  27. package/dist/adapters/agents/gemini-request.js +1 -1
  28. package/dist/adapters/agents/gemini-request.js.map +1 -1
  29. package/dist/adapters/agents/gemini.types.d.ts +2 -1
  30. package/dist/adapters/agents/gemini.types.js.map +1 -1
  31. package/dist/adapters/agents/model-support.constants.d.ts +6 -0
  32. package/dist/adapters/agents/model-support.constants.js +18 -0
  33. package/dist/adapters/agents/model-support.constants.js.map +1 -0
  34. package/dist/adapters/agents/model-support.d.ts +4 -0
  35. package/dist/adapters/agents/model-support.js +11 -0
  36. package/dist/adapters/agents/model-support.js.map +1 -0
  37. package/dist/adapters/agents/settings.types.d.ts +11 -3
  38. package/dist/adapters/agents/settings.types.js.map +1 -1
  39. package/dist/adapters/models/anthropic-model-provider.constants.d.ts +3 -0
  40. package/dist/adapters/models/anthropic-model-provider.constants.js +17 -0
  41. package/dist/adapters/models/anthropic-model-provider.constants.js.map +1 -0
  42. package/dist/adapters/models/anthropic-model-provider.d.ts +3 -0
  43. package/dist/adapters/models/anthropic-model-provider.js +31 -0
  44. package/dist/adapters/models/anthropic-model-provider.js.map +1 -0
  45. package/dist/adapters/models/anthropic-model-provider.types.d.ts +7 -0
  46. package/dist/adapters/models/anthropic-model-provider.types.js +2 -0
  47. package/dist/adapters/models/anthropic-model-provider.types.js.map +1 -0
  48. package/dist/adapters/models/anthropic-request.d.ts +4 -0
  49. package/dist/adapters/models/anthropic-request.js +81 -0
  50. package/dist/adapters/models/anthropic-request.js.map +1 -0
  51. package/dist/adapters/models/anthropic-response.d.ts +3 -0
  52. package/dist/adapters/models/anthropic-response.js +55 -0
  53. package/dist/adapters/models/anthropic-response.js.map +1 -0
  54. package/dist/adapters/models/anthropic-stream.d.ts +2 -0
  55. package/dist/adapters/models/anthropic-stream.js +96 -0
  56. package/dist/adapters/models/anthropic-stream.js.map +1 -0
  57. package/dist/adapters/models/http-provider.d.ts +3 -0
  58. package/dist/adapters/models/http-provider.js +113 -0
  59. package/dist/adapters/models/http-provider.js.map +1 -0
  60. package/dist/adapters/models/{openai-http.js → model-http.js} +1 -1
  61. package/dist/adapters/models/model-http.js.map +1 -0
  62. package/dist/adapters/models/model-protocol.types.d.ts +41 -0
  63. package/dist/adapters/models/model-protocol.types.js +2 -0
  64. package/dist/adapters/models/model-protocol.types.js.map +1 -0
  65. package/dist/adapters/models/model-request.d.ts +2 -0
  66. package/dist/adapters/models/model-request.js +18 -0
  67. package/dist/adapters/models/model-request.js.map +1 -0
  68. package/dist/adapters/models/model-response.d.ts +7 -0
  69. package/dist/adapters/models/model-response.js +41 -0
  70. package/dist/adapters/models/model-response.js.map +1 -0
  71. package/dist/adapters/models/{openai-compatible.constants.js → model.constants.js} +6 -1
  72. package/dist/adapters/models/model.constants.js.map +1 -0
  73. package/dist/adapters/models/openai-chat-stream.d.ts +2 -0
  74. package/dist/adapters/models/openai-chat-stream.js +66 -0
  75. package/dist/adapters/models/openai-chat-stream.js.map +1 -0
  76. package/dist/adapters/models/openai-chat.d.ts +4 -0
  77. package/dist/adapters/models/openai-chat.js +108 -0
  78. package/dist/adapters/models/openai-chat.js.map +1 -0
  79. package/dist/adapters/models/openai-model-provider.d.ts +3 -0
  80. package/dist/adapters/models/openai-model-provider.js +13 -0
  81. package/dist/adapters/models/openai-model-provider.js.map +1 -0
  82. package/dist/adapters/models/openai-model-provider.types.d.ts +4 -0
  83. package/dist/adapters/models/openai-model-provider.types.js +2 -0
  84. package/dist/adapters/models/openai-model-provider.types.js.map +1 -0
  85. package/dist/adapters/models/openai-protocols.d.ts +2 -0
  86. package/dist/adapters/models/openai-protocols.js +22 -0
  87. package/dist/adapters/models/openai-protocols.js.map +1 -0
  88. package/dist/adapters/models/openai-responses-stream.d.ts +2 -0
  89. package/dist/adapters/models/openai-responses-stream.js +35 -0
  90. package/dist/adapters/models/openai-responses-stream.js.map +1 -0
  91. package/dist/adapters/models/openai-responses.d.ts +4 -0
  92. package/dist/adapters/models/openai-responses.js +107 -0
  93. package/dist/adapters/models/openai-responses.js.map +1 -0
  94. package/dist/adapters/models/openai-usage.d.ts +3 -0
  95. package/dist/adapters/models/openai-usage.js +20 -0
  96. package/dist/adapters/models/openai-usage.js.map +1 -0
  97. package/dist/adapters/models/stop-reasons.constants.d.ts +4 -0
  98. package/dist/adapters/models/stop-reasons.constants.js +19 -0
  99. package/dist/adapters/models/stop-reasons.constants.js.map +1 -0
  100. package/dist/adapters/models/stream-events.d.ts +3 -0
  101. package/dist/adapters/models/stream-events.js +22 -0
  102. package/dist/adapters/models/stream-events.js.map +1 -0
  103. package/dist/adapters/tools/edit-tools.d.ts +2 -0
  104. package/dist/adapters/tools/edit-tools.js +84 -0
  105. package/dist/adapters/tools/edit-tools.js.map +1 -0
  106. package/dist/adapters/tools/file-tools.d.ts +2 -0
  107. package/dist/adapters/tools/file-tools.js +97 -0
  108. package/dist/adapters/tools/file-tools.js.map +1 -0
  109. package/dist/adapters/tools/git-tools.d.ts +2 -0
  110. package/dist/adapters/tools/git-tools.js +54 -0
  111. package/dist/adapters/tools/git-tools.js.map +1 -0
  112. package/dist/adapters/tools/sandbox-files.d.ts +10 -0
  113. package/dist/adapters/tools/sandbox-files.js +60 -0
  114. package/dist/adapters/tools/sandbox-files.js.map +1 -0
  115. package/dist/adapters/tools/search-tools.d.ts +2 -0
  116. package/dist/adapters/tools/search-tools.js +65 -0
  117. package/dist/adapters/tools/search-tools.js.map +1 -0
  118. package/dist/adapters/tools/shell-tools.d.ts +3 -0
  119. package/dist/adapters/tools/shell-tools.js +38 -0
  120. package/dist/adapters/tools/shell-tools.js.map +1 -0
  121. package/dist/adapters/tools/tools.constants.d.ts +11 -0
  122. package/dist/adapters/tools/tools.constants.js +17 -0
  123. package/dist/adapters/tools/tools.constants.js.map +1 -0
  124. package/dist/adapters/tools/tools.types.d.ts +41 -0
  125. package/dist/adapters/tools/tools.types.js +2 -0
  126. package/dist/adapters/tools/tools.types.js.map +1 -0
  127. package/dist/application/activity-watchdog.js +15 -2
  128. package/dist/application/activity-watchdog.js.map +1 -1
  129. package/dist/application/agent-bootstrap.d.ts +2 -2
  130. package/dist/application/agent-bootstrap.js +2 -0
  131. package/dist/application/agent-bootstrap.js.map +1 -1
  132. package/dist/application/agent-storage.d.ts +3 -2
  133. package/dist/application/agent-storage.js +9 -2
  134. package/dist/application/agent-storage.js.map +1 -1
  135. package/dist/application/agent-turn.d.ts +3 -3
  136. package/dist/application/agent-turn.js +7 -1
  137. package/dist/application/agent-turn.js.map +1 -1
  138. package/dist/application/attach.js +1 -0
  139. package/dist/application/attach.js.map +1 -1
  140. package/dist/application/custom-turn.d.ts +5 -0
  141. package/dist/application/custom-turn.js +190 -0
  142. package/dist/application/custom-turn.js.map +1 -0
  143. package/dist/application/dispatch-observation.d.ts +3 -0
  144. package/dist/application/dispatch-observation.js +51 -0
  145. package/dist/application/dispatch-observation.js.map +1 -0
  146. package/dist/application/dispatch-observation.types.d.ts +5 -0
  147. package/dist/application/dispatch-observation.types.js +2 -0
  148. package/dist/application/dispatch-observation.types.js.map +1 -0
  149. package/dist/application/dispatch-validation.d.ts +2 -2
  150. package/dist/application/dispatch-validation.js.map +1 -1
  151. package/dist/application/dispatch.js +8 -3
  152. package/dist/application/dispatch.js.map +1 -1
  153. package/dist/application/doctor-image.js +3 -3
  154. package/dist/application/doctor-image.js.map +1 -1
  155. package/dist/application/doctor-protocol.js +9 -4
  156. package/dist/application/doctor-protocol.js.map +1 -1
  157. package/dist/application/doctor-sandbox.js +4 -4
  158. package/dist/application/doctor-sandbox.js.map +1 -1
  159. package/dist/application/doctor-sandbox.types.d.ts +2 -2
  160. package/dist/application/doctor-sandbox.types.js.map +1 -1
  161. package/dist/application/doctor.constants.d.ts +1 -1
  162. package/dist/application/doctor.constants.js +1 -1
  163. package/dist/application/doctor.constants.js.map +1 -1
  164. package/dist/application/doctor.js +10 -9
  165. package/dist/application/doctor.js.map +1 -1
  166. package/dist/application/doctor.types.d.ts +3 -3
  167. package/dist/application/doctor.types.js.map +1 -1
  168. package/dist/application/execution.d.ts +2 -2
  169. package/dist/application/execution.js +1 -1
  170. package/dist/application/execution.js.map +1 -1
  171. package/dist/application/execution.types.d.ts +9 -2
  172. package/dist/application/execution.types.js.map +1 -1
  173. package/dist/application/harness-context.d.ts +2 -0
  174. package/dist/application/harness-context.js +54 -0
  175. package/dist/application/harness-context.js.map +1 -0
  176. package/dist/application/harness-history.d.ts +3 -0
  177. package/dist/application/harness-history.js +17 -0
  178. package/dist/application/harness-history.js.map +1 -0
  179. package/dist/application/harness-hooks.d.ts +9 -0
  180. package/dist/application/harness-hooks.js +90 -0
  181. package/dist/application/harness-hooks.js.map +1 -0
  182. package/dist/application/harness-loop.d.ts +2 -0
  183. package/dist/application/harness-loop.js +132 -0
  184. package/dist/application/harness-loop.js.map +1 -0
  185. package/dist/application/harness.types.d.ts +55 -0
  186. package/dist/application/harness.types.js +2 -0
  187. package/dist/application/harness.types.js.map +1 -0
  188. package/dist/application/lifecycle.constants.d.ts +1 -1
  189. package/dist/application/lifecycle.constants.js +1 -1
  190. package/dist/application/lifecycle.constants.js.map +1 -1
  191. package/dist/application/outpost.types.d.ts +6 -6
  192. package/dist/application/outpost.types.js.map +1 -1
  193. package/dist/application/remote-download.js +1 -1
  194. package/dist/application/remote-download.js.map +1 -1
  195. package/dist/application/sandbox-agents.js +12 -4
  196. package/dist/application/sandbox-agents.js.map +1 -1
  197. package/dist/application/sandbox-attach.js +5 -2
  198. package/dist/application/sandbox-attach.js.map +1 -1
  199. package/dist/application/sandbox-dispatch.js +3 -3
  200. package/dist/application/sandbox-dispatch.js.map +1 -1
  201. package/dist/application/sandbox-provision.js +13 -10
  202. package/dist/application/sandbox-provision.js.map +1 -1
  203. package/dist/application/sandbox-session.types.d.ts +8 -8
  204. package/dist/application/sandbox-session.types.js.map +1 -1
  205. package/dist/application/sandbox.js +6 -3
  206. package/dist/application/sandbox.js.map +1 -1
  207. package/dist/application/speculation.js +1 -1
  208. package/dist/application/speculation.js.map +1 -1
  209. package/dist/application/speculation.types.d.ts +3 -3
  210. package/dist/application/speculation.types.js.map +1 -1
  211. package/dist/application/tasks.types.d.ts +2 -2
  212. package/dist/application/tasks.types.js.map +1 -1
  213. package/dist/application/tool-execution.d.ts +3 -0
  214. package/dist/application/tool-execution.js +211 -0
  215. package/dist/application/tool-execution.js.map +1 -0
  216. package/dist/cli/commands.js +4 -2
  217. package/dist/cli/commands.js.map +1 -1
  218. package/dist/cli/doctor-command.js +6 -6
  219. package/dist/cli/doctor-command.js.map +1 -1
  220. package/dist/cli/init-authentication.js +6 -7
  221. package/dist/cli/init-authentication.js.map +1 -1
  222. package/dist/cli/init-command.js +3 -3
  223. package/dist/cli/init-command.js.map +1 -1
  224. package/dist/cli/main.constants.d.ts +4 -4
  225. package/dist/cli/main.constants.js +4 -4
  226. package/dist/cli/main.constants.js.map +1 -1
  227. package/dist/cli/recovery-command.js +1 -1
  228. package/dist/cli/recovery-command.js.map +1 -1
  229. package/dist/cli/scaffold-files.js +5 -4
  230. package/dist/cli/scaffold-files.js.map +1 -1
  231. package/dist/cli/scaffold-validation.js +13 -10
  232. package/dist/cli/scaffold-validation.js.map +1 -1
  233. package/dist/cli/scaffold.js +8 -4
  234. package/dist/cli/scaffold.js.map +1 -1
  235. package/dist/cli/scaffold.types.d.ts +1 -1
  236. package/dist/cli/scaffold.types.js.map +1 -1
  237. package/dist/cli/starters.js +8 -8
  238. package/dist/cli/starters.js.map +1 -1
  239. package/dist/domain/agent-model.d.ts +3 -0
  240. package/dist/domain/agent-model.js +22 -0
  241. package/dist/domain/agent-model.js.map +1 -0
  242. package/dist/domain/agent.d.ts +4 -0
  243. package/dist/domain/agent.js +32 -0
  244. package/dist/domain/agent.js.map +1 -0
  245. package/dist/domain/agent.types.d.ts +69 -2
  246. package/dist/domain/agent.types.js.map +1 -1
  247. package/dist/domain/context.constants.d.ts +7 -0
  248. package/dist/domain/context.constants.js +8 -0
  249. package/dist/domain/context.constants.js.map +1 -0
  250. package/dist/domain/context.d.ts +4 -0
  251. package/dist/domain/context.js +81 -0
  252. package/dist/domain/context.js.map +1 -0
  253. package/dist/domain/context.types.d.ts +26 -0
  254. package/dist/domain/context.types.js +2 -0
  255. package/dist/domain/context.types.js.map +1 -0
  256. package/dist/domain/dispatch-telemetry.types.d.ts +12 -0
  257. package/dist/domain/dispatch-telemetry.types.js +2 -0
  258. package/dist/domain/dispatch-telemetry.types.js.map +1 -0
  259. package/dist/domain/errors.types.d.ts +1 -1
  260. package/dist/domain/errors.types.js.map +1 -1
  261. package/dist/domain/glob.d.ts +2 -0
  262. package/dist/domain/glob.js +25 -0
  263. package/dist/domain/glob.js.map +1 -0
  264. package/dist/domain/glob.types.d.ts +1 -0
  265. package/dist/domain/glob.types.js +2 -0
  266. package/dist/domain/glob.types.js.map +1 -0
  267. package/dist/domain/harness.constants.d.ts +11 -0
  268. package/dist/domain/harness.constants.js +24 -0
  269. package/dist/domain/harness.constants.js.map +1 -0
  270. package/dist/domain/harness.d.ts +2 -0
  271. package/dist/domain/harness.js +89 -0
  272. package/dist/domain/harness.js.map +1 -0
  273. package/dist/domain/harness.types.d.ts +60 -0
  274. package/dist/domain/harness.types.js +2 -0
  275. package/dist/domain/harness.types.js.map +1 -0
  276. package/dist/domain/hook.constants.d.ts +3 -0
  277. package/dist/domain/hook.constants.js +10 -0
  278. package/dist/domain/hook.constants.js.map +1 -0
  279. package/dist/domain/hook.d.ts +3 -0
  280. package/dist/domain/hook.js +25 -0
  281. package/dist/domain/hook.js.map +1 -0
  282. package/dist/domain/hook.types.d.ts +66 -0
  283. package/dist/domain/hook.types.js +2 -0
  284. package/dist/domain/hook.types.js.map +1 -0
  285. package/dist/domain/instructions.d.ts +3 -0
  286. package/dist/domain/instructions.js +25 -0
  287. package/dist/domain/instructions.js.map +1 -0
  288. package/dist/domain/model-messages.d.ts +5 -0
  289. package/dist/domain/model-messages.js +81 -0
  290. package/dist/domain/model-messages.js.map +1 -0
  291. package/dist/domain/model-messages.types.d.ts +6 -0
  292. package/dist/domain/model-messages.types.js +2 -0
  293. package/dist/domain/model-messages.types.js.map +1 -0
  294. package/dist/domain/model.constants.d.ts +4 -0
  295. package/dist/domain/model.constants.js +16 -0
  296. package/dist/domain/model.constants.js.map +1 -0
  297. package/dist/domain/model.types.d.ts +59 -2
  298. package/dist/domain/model.types.js.map +1 -1
  299. package/dist/domain/permissions.d.ts +3 -0
  300. package/dist/domain/permissions.js +92 -0
  301. package/dist/domain/permissions.js.map +1 -0
  302. package/dist/domain/permissions.types.d.ts +34 -0
  303. package/dist/domain/permissions.types.js +2 -0
  304. package/dist/domain/permissions.types.js.map +1 -0
  305. package/dist/domain/response.js +3 -2
  306. package/dist/domain/response.js.map +1 -1
  307. package/dist/domain/response.types.d.ts +12 -0
  308. package/dist/domain/response.types.js.map +1 -1
  309. package/dist/domain/skill.constants.d.ts +2 -0
  310. package/dist/domain/skill.constants.js +8 -0
  311. package/dist/domain/skill.constants.js.map +1 -0
  312. package/dist/domain/skill.d.ts +8 -0
  313. package/dist/domain/skill.js +79 -0
  314. package/dist/domain/skill.js.map +1 -0
  315. package/dist/domain/skill.types.d.ts +18 -0
  316. package/dist/domain/skill.types.js +2 -0
  317. package/dist/domain/skill.types.js.map +1 -0
  318. package/dist/domain/standard-schema.d.ts +6 -0
  319. package/dist/domain/standard-schema.js +45 -0
  320. package/dist/domain/standard-schema.js.map +1 -0
  321. package/dist/domain/tool-schema.d.ts +3 -0
  322. package/dist/domain/tool-schema.js +109 -0
  323. package/dist/domain/tool-schema.js.map +1 -0
  324. package/dist/domain/tool.constants.d.ts +4 -0
  325. package/dist/domain/tool.constants.js +36 -0
  326. package/dist/domain/tool.constants.js.map +1 -0
  327. package/dist/domain/tool.d.ts +4 -0
  328. package/dist/domain/tool.js +66 -0
  329. package/dist/domain/tool.js.map +1 -0
  330. package/dist/domain/tool.types.d.ts +62 -0
  331. package/dist/domain/tool.types.js +2 -0
  332. package/dist/domain/tool.types.js.map +1 -0
  333. package/dist/domain/transcript.d.ts +4 -0
  334. package/dist/domain/transcript.js +48 -0
  335. package/dist/domain/transcript.js.map +1 -0
  336. package/dist/domain/transcript.types.d.ts +15 -0
  337. package/dist/domain/transcript.types.js +2 -0
  338. package/dist/domain/transcript.types.js.map +1 -0
  339. package/dist/domain/workflow/workflow-state.js +13 -6
  340. package/dist/domain/workflow/workflow-state.js.map +1 -1
  341. package/dist/domain/workflow.d.ts +1 -1
  342. package/dist/domain/workflow.js.map +1 -1
  343. package/dist/domain/workflow.types.d.ts +4 -0
  344. package/dist/domain/workflow.types.js.map +1 -1
  345. package/dist/index.d.ts +34 -8
  346. package/dist/index.js +19 -4
  347. package/dist/index.js.map +1 -1
  348. package/dist/infrastructure/conversations/harness-store.d.ts +3 -0
  349. package/dist/infrastructure/conversations/harness-store.js +27 -0
  350. package/dist/infrastructure/conversations/harness-store.js.map +1 -0
  351. package/dist/infrastructure/conversations/harness-transcript.d.ts +2 -0
  352. package/dist/infrastructure/conversations/harness-transcript.js +50 -0
  353. package/dist/infrastructure/conversations/harness-transcript.js.map +1 -0
  354. package/dist/infrastructure/conversations/harness-transcript.types.d.ts +18 -0
  355. package/dist/infrastructure/conversations/harness-transcript.types.js +2 -0
  356. package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -0
  357. package/dist/infrastructure/conversations.d.ts +4 -1
  358. package/dist/infrastructure/conversations.js +3 -0
  359. package/dist/infrastructure/conversations.js.map +1 -1
  360. package/dist/infrastructure/conversations.types.d.ts +1 -0
  361. package/dist/infrastructure/conversations.types.js.map +1 -1
  362. package/dist/infrastructure/custom-reporter.d.ts +2 -0
  363. package/dist/infrastructure/custom-reporter.js +33 -0
  364. package/dist/infrastructure/custom-reporter.js.map +1 -0
  365. package/dist/infrastructure/custom-reporter.types.d.ts +13 -0
  366. package/dist/infrastructure/custom-reporter.types.js +2 -0
  367. package/dist/infrastructure/custom-reporter.types.js.map +1 -0
  368. package/dist/infrastructure/git/git.constants.d.ts +1 -1
  369. package/dist/infrastructure/git/git.constants.js +1 -0
  370. package/dist/infrastructure/git/git.constants.js.map +1 -1
  371. package/dist/infrastructure/journal.constants.d.ts +1 -0
  372. package/dist/infrastructure/journal.constants.js +2 -0
  373. package/dist/infrastructure/journal.constants.js.map +1 -0
  374. package/dist/infrastructure/journal.js +4 -1
  375. package/dist/infrastructure/journal.js.map +1 -1
  376. package/dist/infrastructure/opentelemetry-dispatch.d.ts +6 -0
  377. package/dist/infrastructure/opentelemetry-dispatch.js +70 -0
  378. package/dist/infrastructure/opentelemetry-dispatch.js.map +1 -0
  379. package/dist/infrastructure/opentelemetry.constants.d.ts +3 -0
  380. package/dist/infrastructure/opentelemetry.constants.js +3 -0
  381. package/dist/infrastructure/opentelemetry.constants.js.map +1 -1
  382. package/dist/infrastructure/opentelemetry.js +4 -0
  383. package/dist/infrastructure/opentelemetry.js.map +1 -1
  384. package/dist/infrastructure/opentelemetry.types.d.ts +3 -3
  385. package/dist/infrastructure/opentelemetry.types.js.map +1 -1
  386. package/dist/infrastructure/reporter.js +27 -2
  387. package/dist/infrastructure/reporter.js.map +1 -1
  388. package/dist/infrastructure/resource-activity-inspection.js +3 -2
  389. package/dist/infrastructure/resource-activity-inspection.js.map +1 -1
  390. package/dist/infrastructure/resource-activity.js +2 -2
  391. package/dist/infrastructure/resource-activity.js.map +1 -1
  392. package/dist/infrastructure/resource-activity.types.d.ts +2 -2
  393. package/dist/infrastructure/resource-activity.types.js.map +1 -1
  394. package/dist/infrastructure/settings.d.ts +1 -1
  395. package/dist/infrastructure/settings.js +3 -3
  396. package/dist/infrastructure/settings.js.map +1 -1
  397. package/dist/infrastructure/sse.d.ts +2 -0
  398. package/dist/infrastructure/sse.js +64 -0
  399. package/dist/infrastructure/sse.js.map +1 -0
  400. package/dist/infrastructure/sse.types.d.ts +4 -0
  401. package/dist/infrastructure/sse.types.js +2 -0
  402. package/dist/infrastructure/sse.types.js.map +1 -0
  403. package/dist/infrastructure/transport-conversations.d.ts +2 -2
  404. package/dist/infrastructure/transport-conversations.js +8 -1
  405. package/dist/infrastructure/transport-conversations.js.map +1 -1
  406. package/dist/infrastructure/transport-journal.js +2 -1
  407. package/dist/infrastructure/transport-journal.js.map +1 -1
  408. package/dist/providers/agents.d.ts +3 -3
  409. package/dist/providers/agents.js +3 -3
  410. package/dist/providers/agents.js.map +1 -1
  411. package/dist/providers/daytona.d.ts +1 -1
  412. package/dist/providers/daytona.js +1 -1
  413. package/dist/providers/daytona.js.map +1 -1
  414. package/dist/providers/docker.d.ts +1 -1
  415. package/dist/providers/docker.js +1 -1
  416. package/dist/providers/docker.js.map +1 -1
  417. package/dist/providers/factories.d.ts +2 -2
  418. package/dist/providers/factories.js +3 -3
  419. package/dist/providers/factories.js.map +1 -1
  420. package/dist/providers/firecracker.d.ts +1 -1
  421. package/dist/providers/firecracker.js +1 -1
  422. package/dist/providers/firecracker.js.map +1 -1
  423. package/dist/providers/local.d.ts +1 -1
  424. package/dist/providers/local.js +1 -1
  425. package/dist/providers/local.js.map +1 -1
  426. package/dist/providers/podman.d.ts +1 -1
  427. package/dist/providers/podman.js +1 -1
  428. package/dist/providers/podman.js.map +1 -1
  429. package/dist/providers/vercel.d.ts +1 -1
  430. package/dist/providers/vercel.js +1 -1
  431. package/dist/providers/vercel.js.map +1 -1
  432. package/package.json +1 -1
  433. package/dist/adapters/models/openai-compatible.constants.js.map +0 -1
  434. package/dist/adapters/models/openai-compatible.d.ts +0 -3
  435. package/dist/adapters/models/openai-compatible.js +0 -78
  436. package/dist/adapters/models/openai-compatible.js.map +0 -1
  437. package/dist/adapters/models/openai-compatible.types.d.ts +0 -14
  438. package/dist/adapters/models/openai-compatible.types.js +0 -2
  439. package/dist/adapters/models/openai-compatible.types.js.map +0 -1
  440. package/dist/adapters/models/openai-http.js.map +0 -1
  441. package/dist/adapters/models/openai-request.d.ts +0 -4
  442. package/dist/adapters/models/openai-request.js +0 -46
  443. package/dist/adapters/models/openai-request.js.map +0 -1
  444. package/dist/adapters/models/openai-response.d.ts +0 -3
  445. package/dist/adapters/models/openai-response.js +0 -65
  446. package/dist/adapters/models/openai-response.js.map +0 -1
  447. package/dist/cli/init-authentication.constants.js.map +0 -1
  448. /package/dist/{cli/init-authentication.constants.d.ts → adapters/agents/authentication.constants.d.ts} +0 -0
  449. /package/dist/adapters/models/{openai-http.d.ts → model-http.d.ts} +0 -0
  450. /package/dist/adapters/models/{openai-compatible.constants.d.ts → model.constants.d.ts} +0 -0
@@ -0,0 +1,54 @@
1
+ import { SUMMARY_INSTRUCTIONS } from "../domain/context.constants.js";
2
+ import { OutpostError } from "../domain/errors.js";
3
+ import { validateMessages } from "../domain/model-messages.js";
4
+ const renderers = {
5
+ text: (block) => block.text,
6
+ "tool-call": (block) => `[tool call ${block.name} ${JSON.stringify(block.input)}]`,
7
+ "tool-result": (block) => `[tool ${block.isError ? "error" : "result"}]\n${block.content}`,
8
+ reasoning: () => "",
9
+ };
10
+ export async function compact(runtime, history, step) {
11
+ const strategy = runtime.agent.harness.context;
12
+ if (!strategy)
13
+ return;
14
+ const compacted = await strategy.compact({
15
+ messages: history.messages,
16
+ step,
17
+ model: runtime.agent.model,
18
+ signal: runtime.signal,
19
+ summarize: (messages) => summarize(runtime, messages),
20
+ });
21
+ runtime.signal.throwIfAborted();
22
+ if (compacted === undefined)
23
+ return;
24
+ validateMessages(compacted);
25
+ const cleaned = compacted.map((message) => ({
26
+ ...message,
27
+ content: message.content.filter((block) => block.type !== "reasoning"),
28
+ }));
29
+ validateMessages(cleaned);
30
+ await history.replace(cleaned);
31
+ runtime.emit({
32
+ kind: "compaction",
33
+ strategy: strategy.name,
34
+ messages: cleaned.length,
35
+ });
36
+ }
37
+ async function summarize(runtime, messages) {
38
+ const result = await runtime.modelProvider.request({
39
+ model: runtime.agent.model.name,
40
+ system: SUMMARY_INSTRUCTIONS,
41
+ prompt: messages.map(render).join("\n\n") || "(no earlier messages)",
42
+ });
43
+ if ((result.stopReason ?? "end") !== "end" || !result.text.trim())
44
+ throw new OutpostError("response", "The model could not summarize history");
45
+ return result.text;
46
+ }
47
+ function render(message) {
48
+ const body = message.content
49
+ .map((block) => renderers[block.type](block))
50
+ .filter(Boolean)
51
+ .join("\n");
52
+ return `${message.role === "user" ? "User" : "Assistant"}:\n${body}`;
53
+ }
54
+ //# sourceMappingURL=harness-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-context.js","sourceRoot":"","sources":["../../src/application/harness-context.ts"],"names":[],"mappings":"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","sourcesContent":["import { SUMMARY_INSTRUCTIONS } from \"../domain/context.constants.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport { validateMessages } from \"../domain/model-messages.ts\";\nimport type { ModelContentBlock, ModelMessage } from \"../domain/model.types.ts\";\nimport type {\n BlockRenderers,\n HarnessHistory,\n HarnessRuntime,\n} from \"./harness.types.ts\";\n\nconst renderers: BlockRenderers = {\n text: (block) => block.text,\n \"tool-call\": (block) =>\n `[tool call ${block.name} ${JSON.stringify(block.input)}]`,\n \"tool-result\": (block) =>\n `[tool ${block.isError ? \"error\" : \"result\"}]\\n${block.content}`,\n reasoning: () => \"\",\n};\n\nexport async function compact(\n runtime: HarnessRuntime,\n history: HarnessHistory,\n step: number,\n): Promise<void> {\n const strategy = runtime.agent.harness.context;\n if (!strategy) return;\n const compacted = await strategy.compact({\n messages: history.messages,\n step,\n model: runtime.agent.model,\n signal: runtime.signal,\n summarize: (messages) => summarize(runtime, messages),\n });\n runtime.signal.throwIfAborted();\n if (compacted === undefined) return;\n validateMessages(compacted);\n const cleaned = compacted.map((message) => ({\n ...message,\n content: message.content.filter((block) => block.type !== \"reasoning\"),\n }));\n validateMessages(cleaned);\n await history.replace(cleaned);\n runtime.emit({\n kind: \"compaction\",\n strategy: strategy.name,\n messages: cleaned.length,\n });\n}\n\nasync function summarize(\n runtime: HarnessRuntime,\n messages: readonly ModelMessage[],\n): Promise<string> {\n const result = await runtime.modelProvider.request({\n model: runtime.agent.model.name,\n system: SUMMARY_INSTRUCTIONS,\n prompt: messages.map(render).join(\"\\n\\n\") || \"(no earlier messages)\",\n });\n if ((result.stopReason ?? \"end\") !== \"end\" || !result.text.trim())\n throw new OutpostError(\"response\", \"The model could not summarize history\");\n return result.text;\n}\n\nfunction render(message: ModelMessage): string {\n const body = message.content\n .map((block) =>\n (renderers[block.type] as (value: ModelContentBlock) => string)(block),\n )\n .filter(Boolean)\n .join(\"\\n\");\n return `${message.role === \"user\" ? \"User\" : \"Assistant\"}:\\n${body}`;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { TranscriptHandle } from "../infrastructure/conversations/harness-transcript.types.ts";
2
+ import type { HarnessHistory } from "./harness.types.ts";
3
+ export declare function harnessHistory(transcript?: TranscriptHandle): HarnessHistory;
@@ -0,0 +1,17 @@
1
+ export function harnessHistory(transcript) {
2
+ let messages = transcript?.messages ?? [];
3
+ return {
4
+ get messages() {
5
+ return messages;
6
+ },
7
+ async append(message) {
8
+ await transcript?.append({ type: "message", message });
9
+ messages = [...messages, message];
10
+ },
11
+ async replace(next) {
12
+ await transcript?.append({ type: "compaction", messages: next });
13
+ messages = [...next];
14
+ },
15
+ };
16
+ }
17
+ //# sourceMappingURL=harness-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-history.js","sourceRoot":"","sources":["../../src/application/harness-history.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,cAAc,CAAC,UAA6B;IAC1D,IAAI,QAAQ,GAA4B,UAAU,EAAE,QAAQ,IAAI,EAAE,CAAC;IACnE,OAAO;QACL,IAAI,QAAQ;YACV,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,OAAO;YAClB,MAAM,UAAU,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;YACvD,QAAQ,GAAG,CAAC,GAAG,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,MAAM,UAAU,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACjE,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { ModelMessage } from \"../domain/model.types.ts\";\nimport type { TranscriptHandle } from \"../infrastructure/conversations/harness-transcript.types.ts\";\nimport type { HarnessHistory } from \"./harness.types.ts\";\n\nexport function harnessHistory(transcript?: TranscriptHandle): HarnessHistory {\n let messages: readonly ModelMessage[] = transcript?.messages ?? [];\n return {\n get messages() {\n return messages;\n },\n async append(message) {\n await transcript?.append({ type: \"message\", message });\n messages = [...messages, message];\n },\n async replace(next) {\n await transcript?.append({ type: \"compaction\", messages: next });\n messages = [...next];\n },\n };\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import type { ModelMessage, ModelResult, ModelToolCallBlock } from "../domain/model.types.ts";
2
+ import type { ToolOutput } from "../domain/tool.types.ts";
3
+ import type { HarnessRuntime, ToolDenial, ToolOutcome } from "./harness.types.ts";
4
+ export declare function sessionInstructions(runtime: HarnessRuntime, prompt: string): Promise<readonly string[]>;
5
+ export declare function beforeModel(runtime: HarnessRuntime, messages: readonly ModelMessage[], step: number): Promise<void>;
6
+ export declare function afterModel(runtime: HarnessRuntime, result: ModelResult, step: number): Promise<void>;
7
+ export declare function beforeTool(runtime: HarnessRuntime, call: ModelToolCallBlock, step: number): Promise<ToolDenial | ModelToolCallBlock>;
8
+ export declare function afterTool(runtime: HarnessRuntime, call: ModelToolCallBlock, outcome: ToolOutcome, step: number, normalize: (output: ToolOutput) => ToolOutcome): Promise<ToolOutcome>;
9
+ export declare function stopRequest(runtime: HarnessRuntime, text: string, step: number): Promise<string | undefined>;
@@ -0,0 +1,90 @@
1
+ import { OutpostError } from "../domain/errors.js";
2
+ export async function sessionInstructions(runtime, prompt) {
3
+ const texts = [];
4
+ for (const decision of await each(runtime, "session-start", { prompt }, 0)) {
5
+ if (decision === undefined)
6
+ continue;
7
+ expect(typeof decision.instructions === "string", "session-start hooks may only return { instructions }");
8
+ texts.push(decision.instructions);
9
+ }
10
+ return texts;
11
+ }
12
+ export async function beforeModel(runtime, messages, step) {
13
+ await each(runtime, "before-model", { messages }, step);
14
+ }
15
+ export async function afterModel(runtime, result, step) {
16
+ await each(runtime, "after-model", { result }, step);
17
+ }
18
+ export async function beforeTool(runtime, call, step) {
19
+ let current = call;
20
+ for (const hook of hooks(runtime, "before-tool")) {
21
+ const decision = await hook.run({
22
+ call: current,
23
+ ...context(runtime, step),
24
+ });
25
+ if (decision === undefined)
26
+ continue;
27
+ expect(decision !== null && typeof decision === "object", "before-tool hooks may return { deny } or { input }");
28
+ if ("deny" in decision) {
29
+ expect(typeof decision.deny === "string" && decision.deny.trim() !== "", "before-tool deny reasons must be nonempty text");
30
+ return { deny: decision.deny };
31
+ }
32
+ expect("input" in decision, "before-tool hooks may return { deny } or { input }");
33
+ current = { ...current, input: decision.input };
34
+ }
35
+ return current;
36
+ }
37
+ export async function afterTool(runtime, call, outcome, step, normalize) {
38
+ let current = outcome;
39
+ for (const hook of hooks(runtime, "after-tool")) {
40
+ const decision = await hook.run({
41
+ call,
42
+ result: current,
43
+ ...context(runtime, step),
44
+ });
45
+ if (decision === undefined)
46
+ continue;
47
+ expect(decision !== null && typeof decision === "object" && "result" in decision, "after-tool hooks may only return { result }");
48
+ current = normalize(decision.result);
49
+ }
50
+ return current;
51
+ }
52
+ export async function stopRequest(runtime, text, step) {
53
+ for (const hook of hooks(runtime, "stop")) {
54
+ const decision = await hook.run({ text, ...context(runtime, step) });
55
+ if (decision === undefined)
56
+ continue;
57
+ expect(decision !== null &&
58
+ typeof decision === "object" &&
59
+ typeof decision.continue === "string" &&
60
+ decision.continue.trim() !== "", "stop hooks may only return { continue } with nonempty text");
61
+ return decision.continue;
62
+ }
63
+ return undefined;
64
+ }
65
+ async function each(runtime, phase, event, step) {
66
+ const decisions = [];
67
+ for (const hook of hooks(runtime, phase))
68
+ decisions.push(await hook.run({
69
+ ...event,
70
+ ...context(runtime, step),
71
+ }));
72
+ return decisions;
73
+ }
74
+ function hooks(runtime, phase) {
75
+ return runtime.agent.harness.hooks.filter((hook) => hook.on === phase);
76
+ }
77
+ function context(runtime, step) {
78
+ runtime.signal.throwIfAborted();
79
+ return {
80
+ sandbox: runtime.sandbox,
81
+ signal: runtime.signal,
82
+ model: runtime.agent.model,
83
+ step,
84
+ };
85
+ }
86
+ function expect(condition, message) {
87
+ if (!condition)
88
+ throw new OutpostError("configuration", message);
89
+ }
90
+ //# sourceMappingURL=harness-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-hooks.js","sourceRoot":"","sources":["../../src/application/harness-hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import { OutpostError } from \"../domain/errors.ts\";\nimport type {\n HarnessHook,\n HarnessHookContext,\n HarnessHookEvents,\n HarnessHookInput,\n HarnessHookPhase,\n HarnessHookResult,\n} from \"../domain/hook.types.ts\";\nimport type {\n ModelMessage,\n ModelResult,\n ModelToolCallBlock,\n} from \"../domain/model.types.ts\";\nimport type { ToolOutput } from \"../domain/tool.types.ts\";\nimport type {\n HarnessRuntime,\n ToolDenial,\n ToolOutcome,\n} from \"./harness.types.ts\";\n\nexport async function sessionInstructions(\n runtime: HarnessRuntime,\n prompt: string,\n): Promise<readonly string[]> {\n const texts: string[] = [];\n for (const decision of await each(runtime, \"session-start\", { prompt }, 0)) {\n if (decision === undefined) continue;\n expect(\n typeof decision.instructions === \"string\",\n \"session-start hooks may only return { instructions }\",\n );\n texts.push(decision.instructions);\n }\n return texts;\n}\n\nexport async function beforeModel(\n runtime: HarnessRuntime,\n messages: readonly ModelMessage[],\n step: number,\n): Promise<void> {\n await each(runtime, \"before-model\", { messages }, step);\n}\n\nexport async function afterModel(\n runtime: HarnessRuntime,\n result: ModelResult,\n step: number,\n): Promise<void> {\n await each(runtime, \"after-model\", { result }, step);\n}\n\nexport async function beforeTool(\n runtime: HarnessRuntime,\n call: ModelToolCallBlock,\n step: number,\n): Promise<ToolDenial | ModelToolCallBlock> {\n let current = call;\n for (const hook of hooks(runtime, \"before-tool\")) {\n const decision = await hook.run({\n call: current,\n ...context(runtime, step),\n });\n if (decision === undefined) continue;\n expect(\n decision !== null && typeof decision === \"object\",\n \"before-tool hooks may return { deny } or { input }\",\n );\n if (\"deny\" in decision) {\n expect(\n typeof decision.deny === \"string\" && decision.deny.trim() !== \"\",\n \"before-tool deny reasons must be nonempty text\",\n );\n return { deny: decision.deny };\n }\n expect(\n \"input\" in decision,\n \"before-tool hooks may return { deny } or { input }\",\n );\n current = { ...current, input: decision.input };\n }\n return current;\n}\n\nexport async function afterTool(\n runtime: HarnessRuntime,\n call: ModelToolCallBlock,\n outcome: ToolOutcome,\n step: number,\n normalize: (output: ToolOutput) => ToolOutcome,\n): Promise<ToolOutcome> {\n let current = outcome;\n for (const hook of hooks(runtime, \"after-tool\")) {\n const decision = await hook.run({\n call,\n result: current,\n ...context(runtime, step),\n });\n if (decision === undefined) continue;\n expect(\n decision !== null && typeof decision === \"object\" && \"result\" in decision,\n \"after-tool hooks may only return { result }\",\n );\n current = normalize(decision.result);\n }\n return current;\n}\n\nexport async function stopRequest(\n runtime: HarnessRuntime,\n text: string,\n step: number,\n): Promise<string | undefined> {\n for (const hook of hooks(runtime, \"stop\")) {\n const decision = await hook.run({ text, ...context(runtime, step) });\n if (decision === undefined) continue;\n expect(\n decision !== null &&\n typeof decision === \"object\" &&\n typeof decision.continue === \"string\" &&\n decision.continue.trim() !== \"\",\n \"stop hooks may only return { continue } with nonempty text\",\n );\n return decision.continue;\n }\n return undefined;\n}\n\nasync function each<Phase extends HarnessHookPhase>(\n runtime: HarnessRuntime,\n phase: Phase,\n event: HarnessHookEvents[Phase],\n step: number,\n): Promise<readonly HarnessHookResult<Phase>[]> {\n const decisions: HarnessHookResult<Phase>[] = [];\n for (const hook of hooks(runtime, phase))\n decisions.push(\n await hook.run({\n ...event,\n ...context(runtime, step),\n } as HarnessHookInput<Phase>),\n );\n return decisions;\n}\n\nfunction hooks<Phase extends HarnessHookPhase>(\n runtime: HarnessRuntime,\n phase: Phase,\n): readonly HarnessHook<Phase>[] {\n return runtime.agent.harness.hooks.filter(\n (hook): hook is HarnessHook<Phase> => hook.on === phase,\n );\n}\n\nfunction context(runtime: HarnessRuntime, step: number): HarnessHookContext {\n runtime.signal.throwIfAborted();\n return {\n sandbox: runtime.sandbox,\n signal: runtime.signal,\n model: runtime.agent.model,\n step,\n };\n}\n\nfunction expect(condition: unknown, message: string): asserts condition {\n if (!condition) throw new OutpostError(\"configuration\", message);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { HarnessHistory, HarnessRuntime } from "./harness.types.ts";
2
+ export declare function harnessLoop(runtime: HarnessRuntime, prompt: string, history: HarnessHistory): Promise<string>;
@@ -0,0 +1,132 @@
1
+ import { OutpostError } from "../domain/errors.js";
2
+ import { loadedSkills } from "../domain/skill.js";
3
+ import { addUsage } from "../domain/usage.js";
4
+ import { compact } from "./harness-context.js";
5
+ import { afterModel, beforeModel, sessionInstructions, stopRequest, } from "./harness-hooks.js";
6
+ import { executeToolCalls } from "./tool-execution.js";
7
+ const stopHandlers = {
8
+ end: async (runtime, state, result, content) => {
9
+ const message = await stopRequest(runtime, result.text, state.step);
10
+ await state.history.append({ role: "assistant", content });
11
+ if (message === undefined)
12
+ return result.text;
13
+ runtime.emit({ kind: "stop-prevented", message });
14
+ await state.history.append({
15
+ role: "user",
16
+ content: [{ type: "text", text: message }],
17
+ });
18
+ return undefined;
19
+ },
20
+ "max-tokens": async (_runtime, state) => {
21
+ throw new OutpostError("limit", `Model output reached maxOutputTokens during step ${state.step}`, { limit: "maxOutputTokens", step: state.step });
22
+ },
23
+ refusal: async (_runtime, state) => {
24
+ throw new OutpostError("response", "The model refused to continue", {
25
+ step: state.step,
26
+ });
27
+ },
28
+ "tool-calls": async (runtime, state, _result, content) => {
29
+ const calls = content.filter((block) => block.type === "tool-call");
30
+ state.toolCalls += calls.length;
31
+ const { maxToolCalls } = runtime.agent.harness.limits;
32
+ if (maxToolCalls !== undefined && state.toolCalls > maxToolCalls)
33
+ throw limit("maxToolCalls", `Harness exceeded ${maxToolCalls} tool calls`);
34
+ await state.history.append({ role: "assistant", content });
35
+ await state.history.append({
36
+ role: "user",
37
+ content: await executeToolCalls(runtime, calls, state.step, loadedSkills(state.history.messages)),
38
+ });
39
+ return undefined;
40
+ },
41
+ };
42
+ export async function harnessLoop(runtime, prompt, history) {
43
+ const { harness, model } = runtime.agent;
44
+ const system = [
45
+ await instructions(runtime),
46
+ ...(await sessionInstructions(runtime, prompt)),
47
+ ]
48
+ .filter((text) => text.trim())
49
+ .join("\n\n");
50
+ const tools = runtime.tools.map((tool) => ({
51
+ name: tool.name,
52
+ description: tool.description,
53
+ inputSchema: tool.inputSchema,
54
+ }));
55
+ await history.append({
56
+ role: "user",
57
+ content: [{ type: "text", text: prompt }],
58
+ });
59
+ let usage = { input: 0, cached: 0, output: 0 };
60
+ let toolCalls = 0;
61
+ for (let step = 1;; step++) {
62
+ runtime.signal.throwIfAborted();
63
+ if (step > harness.limits.maxSteps)
64
+ throw limit("maxSteps", `Harness reached ${harness.limits.maxSteps} steps without a final answer`);
65
+ const exceeded = exceededUsage(usage, harness.limits.usage);
66
+ if (exceeded)
67
+ throw limit("usage", `Harness exceeded its ${exceeded} token budget`);
68
+ runtime.emit({ kind: "step", index: step });
69
+ await compact(runtime, history, step);
70
+ await beforeModel(runtime, history.messages, step);
71
+ const result = await requestModel(runtime, {
72
+ model: model.name,
73
+ messages: history.messages,
74
+ ...(system ? { system } : {}),
75
+ ...(tools.length ? { tools } : {}),
76
+ ...(harness.cache ? { cache: true } : {}),
77
+ });
78
+ if (harness.limits.usage && !result.usage)
79
+ throw new OutpostError("configuration", "Harness usage limits require a model provider that reports usage");
80
+ if (result.usage)
81
+ usage = addUsage(usage, result.usage);
82
+ await afterModel(runtime, result, step);
83
+ const content = result.content ?? [
84
+ { type: "text", text: result.text },
85
+ ];
86
+ for (const block of content)
87
+ if (block.type === "text" && block.text)
88
+ runtime.emit({ kind: "text", text: block.text });
89
+ const state = { history, step, toolCalls };
90
+ const reason = result.stopReason ?? inferredStop(content);
91
+ const answer = await stopHandlers[reason](runtime, state, result, content);
92
+ toolCalls = state.toolCalls;
93
+ if (answer !== undefined)
94
+ return answer;
95
+ }
96
+ }
97
+ async function instructions(runtime) {
98
+ const texts = await Promise.all(runtime.agent.harness.instructions.map((entry) => entry.resolve({
99
+ sandbox: runtime.sandbox,
100
+ signal: runtime.signal,
101
+ model: runtime.agent.model,
102
+ })));
103
+ runtime.signal.throwIfAborted();
104
+ return texts.filter((text) => text.trim()).join("\n\n");
105
+ }
106
+ function inferredStop(content) {
107
+ return content.some((block) => block.type === "tool-call")
108
+ ? "tool-calls"
109
+ : "end";
110
+ }
111
+ function exceededUsage(usage, limits) {
112
+ return Object.entries(limits ?? {}).find(([key, value]) => (usage[key] ?? 0) > (value ?? Infinity))?.[0];
113
+ }
114
+ function limit(name, message) {
115
+ return new OutpostError("limit", message, { limit: name });
116
+ }
117
+ async function requestModel(runtime, request) {
118
+ const provider = runtime.modelProvider;
119
+ if (!provider.stream)
120
+ return provider.request(request);
121
+ let result;
122
+ for await (const event of provider.stream(request)) {
123
+ if (event.type === "text-delta")
124
+ runtime.emit({ kind: "text-delta", text: event.text });
125
+ if (event.type === "result")
126
+ result = event.result;
127
+ }
128
+ if (!result)
129
+ throw new OutpostError("response", "Model stream ended without a result");
130
+ return result;
131
+ }
132
+ //# sourceMappingURL=harness-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-loop.js","sourceRoot":"","sources":["../../src/application/harness-loop.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AASnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAO9C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EACL,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,YAAY,GAAmD;IACnE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;QAC7C,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACpE,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC;QAClD,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACzB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;SAC3C,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QACtC,MAAM,IAAI,YAAY,CACpB,OAAO,EACP,oDAAoD,KAAK,CAAC,IAAI,EAAE,EAChE,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAC/C,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QACjC,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,+BAA+B,EAAE;YAClE,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IACD,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QACvD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAC1B,CAAC,KAAK,EAA+B,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CACnE,CAAC;QACF,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC;QAChC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACtD,IAAI,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,GAAG,YAAY;YAC9D,MAAM,KAAK,CACT,cAAc,EACd,oBAAoB,YAAY,aAAa,CAC9C,CAAC;QACJ,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACzB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,MAAM,gBAAgB,CAC7B,OAAO,EACP,KAAK,EACL,KAAK,CAAC,IAAI,EACV,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CACrC;SACF,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAuB,EACvB,MAAc,EACd,OAAuB;IAEvB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC;IACzC,MAAM,MAAM,GAAG;QACb,MAAM,YAAY,CAAC,OAAO,CAAC;QAC3B,GAAG,CAAC,MAAM,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;KAChD;SACE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC7B,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,MAAM,KAAK,GAAoB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1D,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC,CAAC,CAAC;IACJ,MAAM,OAAO,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;KAC1C,CAAC,CAAC;IACH,IAAI,KAAK,GAAU,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACtD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,IAAI,IAAI,GAAG,CAAC,GAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAChC,IAAI,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ;YAChC,MAAM,KAAK,CACT,UAAU,EACV,mBAAmB,OAAO,CAAC,MAAM,CAAC,QAAQ,+BAA+B,CAC1E,CAAC;QACJ,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,QAAQ;YACV,MAAM,KAAK,CAAC,OAAO,EAAE,wBAAwB,QAAQ,eAAe,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE;YACzC,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7B,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK;YACvC,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,kEAAkE,CACnE,CAAC;QACJ,IAAI,MAAM,CAAC,KAAK;YAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACxD,MAAM,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACxC,MAAM,OAAO,GAAiC,MAAM,CAAC,OAAO,IAAI;YAC9D,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;SACpC,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,OAAO;YACzB,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI;gBACrC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,KAAK,GAAc,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3E,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QAC5B,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,OAAuB;IACjD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/C,KAAK,CAAC,OAAO,CAAC;QACZ,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK;KAC3B,CAAC,CACH,CACF,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;IAChC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,OAAqC;IACzD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC;QACxD,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC;AAED,SAAS,aAAa,CACpB,KAAY,EACZ,MAAkC;IAElC,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CACtC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAkB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,QAAQ,CAAC,CACzE,EAAE,CAAC,CAAC,CAAC,CAAC;AACT,CAAC;AAED,SAAS,KAAK,CAAC,IAAY,EAAE,OAAe;IAC1C,OAAO,IAAI,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,OAAuB,EACvB,OAAqB;IAErB,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IACvC,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,IAAI,MAA+B,CAAC;IACpC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;YAC7B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACzD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IACrD,CAAC;IACD,IAAI,CAAC,MAAM;QACT,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,qCAAqC,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { Usage } from \"../domain/agent.types.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type {\n ModelContentBlock,\n ModelRequest,\n ModelResult,\n ModelStopReason,\n ModelToolCallBlock,\n ModelToolSpec,\n} from \"../domain/model.types.ts\";\nimport { loadedSkills } from \"../domain/skill.ts\";\nimport { addUsage } from \"../domain/usage.ts\";\nimport type {\n HarnessHistory,\n HarnessRuntime,\n LoopState,\n StopHandler,\n} from \"./harness.types.ts\";\nimport { compact } from \"./harness-context.ts\";\nimport {\n afterModel,\n beforeModel,\n sessionInstructions,\n stopRequest,\n} from \"./harness-hooks.ts\";\nimport { executeToolCalls } from \"./tool-execution.ts\";\n\nconst stopHandlers: Readonly<Record<ModelStopReason, StopHandler>> = {\n end: async (runtime, state, result, content) => {\n const message = await stopRequest(runtime, result.text, state.step);\n await state.history.append({ role: \"assistant\", content });\n if (message === undefined) return result.text;\n runtime.emit({ kind: \"stop-prevented\", message });\n await state.history.append({\n role: \"user\",\n content: [{ type: \"text\", text: message }],\n });\n return undefined;\n },\n \"max-tokens\": async (_runtime, state) => {\n throw new OutpostError(\n \"limit\",\n `Model output reached maxOutputTokens during step ${state.step}`,\n { limit: \"maxOutputTokens\", step: state.step },\n );\n },\n refusal: async (_runtime, state) => {\n throw new OutpostError(\"response\", \"The model refused to continue\", {\n step: state.step,\n });\n },\n \"tool-calls\": async (runtime, state, _result, content) => {\n const calls = content.filter(\n (block): block is ModelToolCallBlock => block.type === \"tool-call\",\n );\n state.toolCalls += calls.length;\n const { maxToolCalls } = runtime.agent.harness.limits;\n if (maxToolCalls !== undefined && state.toolCalls > maxToolCalls)\n throw limit(\n \"maxToolCalls\",\n `Harness exceeded ${maxToolCalls} tool calls`,\n );\n await state.history.append({ role: \"assistant\", content });\n await state.history.append({\n role: \"user\",\n content: await executeToolCalls(\n runtime,\n calls,\n state.step,\n loadedSkills(state.history.messages),\n ),\n });\n return undefined;\n },\n};\n\nexport async function harnessLoop(\n runtime: HarnessRuntime,\n prompt: string,\n history: HarnessHistory,\n): Promise<string> {\n const { harness, model } = runtime.agent;\n const system = [\n await instructions(runtime),\n ...(await sessionInstructions(runtime, prompt)),\n ]\n .filter((text) => text.trim())\n .join(\"\\n\\n\");\n const tools: ModelToolSpec[] = runtime.tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n }));\n await history.append({\n role: \"user\",\n content: [{ type: \"text\", text: prompt }],\n });\n let usage: Usage = { input: 0, cached: 0, output: 0 };\n let toolCalls = 0;\n for (let step = 1; ; step++) {\n runtime.signal.throwIfAborted();\n if (step > harness.limits.maxSteps)\n throw limit(\n \"maxSteps\",\n `Harness reached ${harness.limits.maxSteps} steps without a final answer`,\n );\n const exceeded = exceededUsage(usage, harness.limits.usage);\n if (exceeded)\n throw limit(\"usage\", `Harness exceeded its ${exceeded} token budget`);\n runtime.emit({ kind: \"step\", index: step });\n await compact(runtime, history, step);\n await beforeModel(runtime, history.messages, step);\n const result = await requestModel(runtime, {\n model: model.name,\n messages: history.messages,\n ...(system ? { system } : {}),\n ...(tools.length ? { tools } : {}),\n ...(harness.cache ? { cache: true } : {}),\n });\n if (harness.limits.usage && !result.usage)\n throw new OutpostError(\n \"configuration\",\n \"Harness usage limits require a model provider that reports usage\",\n );\n if (result.usage) usage = addUsage(usage, result.usage);\n await afterModel(runtime, result, step);\n const content: readonly ModelContentBlock[] = result.content ?? [\n { type: \"text\", text: result.text },\n ];\n for (const block of content)\n if (block.type === \"text\" && block.text)\n runtime.emit({ kind: \"text\", text: block.text });\n const state: LoopState = { history, step, toolCalls };\n const reason = result.stopReason ?? inferredStop(content);\n const answer = await stopHandlers[reason](runtime, state, result, content);\n toolCalls = state.toolCalls;\n if (answer !== undefined) return answer;\n }\n}\n\nasync function instructions(runtime: HarnessRuntime): Promise<string> {\n const texts = await Promise.all(\n runtime.agent.harness.instructions.map((entry) =>\n entry.resolve({\n sandbox: runtime.sandbox,\n signal: runtime.signal,\n model: runtime.agent.model,\n }),\n ),\n );\n runtime.signal.throwIfAborted();\n return texts.filter((text) => text.trim()).join(\"\\n\\n\");\n}\n\nfunction inferredStop(content: readonly ModelContentBlock[]): ModelStopReason {\n return content.some((block) => block.type === \"tool-call\")\n ? \"tool-calls\"\n : \"end\";\n}\n\nfunction exceededUsage(\n usage: Usage,\n limits: Partial<Usage> | undefined,\n): string | undefined {\n return Object.entries(limits ?? {}).find(\n ([key, value]) => (usage[key as keyof Usage] ?? 0) > (value ?? Infinity),\n )?.[0];\n}\n\nfunction limit(name: string, message: string): OutpostError {\n return new OutpostError(\"limit\", message, { limit: name });\n}\n\nasync function requestModel(\n runtime: HarnessRuntime,\n request: ModelRequest,\n): Promise<ModelResult> {\n const provider = runtime.modelProvider;\n if (!provider.stream) return provider.request(request);\n let result: ModelResult | undefined;\n for await (const event of provider.stream(request)) {\n if (event.type === \"text-delta\")\n runtime.emit({ kind: \"text-delta\", text: event.text });\n if (event.type === \"result\") result = event.result;\n }\n if (!result)\n throw new OutpostError(\"response\", \"Model stream ended without a result\");\n return result;\n}\n"]}
@@ -0,0 +1,55 @@
1
+ import type { AgentEvent, CustomAgent } from "../domain/agent.types.ts";
2
+ import type { ModelContentBlock, ModelMessage, ModelProvider, ModelResult, ModelToolCallBlock } from "../domain/model.types.ts";
3
+ import type { SandboxLease } from "../domain/sandbox.types.ts";
4
+ import type { HarnessTool } from "../domain/tool.types.ts";
5
+ import type { DispatchOptions, TurnContext } from "./execution.types.ts";
6
+ export interface HarnessRuntime {
7
+ readonly agent: CustomAgent;
8
+ readonly tools: readonly HarnessTool[];
9
+ readonly modelProvider: ModelProvider;
10
+ readonly sandbox: SandboxLease;
11
+ readonly signal: AbortSignal;
12
+ emit(event: AgentEvent): void;
13
+ hold(): () => void;
14
+ }
15
+ export interface ToolCallBatch {
16
+ readonly concurrent: boolean;
17
+ readonly calls: readonly PreparedCall[];
18
+ }
19
+ export type ValidatedInput = {
20
+ readonly value: unknown;
21
+ } | {
22
+ readonly outcome: ToolOutcome;
23
+ };
24
+ export interface ToolOutcome {
25
+ readonly content: string;
26
+ readonly isError: boolean;
27
+ }
28
+ export interface HarnessHistory {
29
+ readonly messages: readonly ModelMessage[];
30
+ append(message: ModelMessage): Promise<void>;
31
+ replace(messages: readonly ModelMessage[]): Promise<void>;
32
+ }
33
+ export interface CustomTurnContext extends TurnContext {
34
+ readonly continuation?: DispatchOptions["continuation"];
35
+ }
36
+ export interface LoopState {
37
+ readonly history: HarnessHistory;
38
+ readonly step: number;
39
+ toolCalls: number;
40
+ }
41
+ export type StopHandler = (runtime: HarnessRuntime, state: LoopState, result: ModelResult, content: readonly ModelContentBlock[]) => Promise<string | undefined>;
42
+ export interface PreparedCall {
43
+ readonly call: ModelToolCallBlock;
44
+ readonly tool?: HarnessTool;
45
+ readonly input?: unknown;
46
+ readonly outcome?: ToolOutcome;
47
+ }
48
+ export interface ToolDenial {
49
+ readonly deny: string;
50
+ }
51
+ export type BlockRenderers = {
52
+ readonly [Type in ModelContentBlock["type"]]: (block: Extract<ModelContentBlock, {
53
+ type: Type;
54
+ }>) => string;
55
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=harness.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.types.js","sourceRoot":"","sources":["../../src/application/harness.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentEvent, CustomAgent } from \"../domain/agent.types.ts\";\nimport type {\n ModelContentBlock,\n ModelMessage,\n ModelProvider,\n ModelResult,\n ModelToolCallBlock,\n} from \"../domain/model.types.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport type { HarnessTool } from \"../domain/tool.types.ts\";\nimport type { DispatchOptions, TurnContext } from \"./execution.types.ts\";\n\nexport interface HarnessRuntime {\n readonly agent: CustomAgent;\n readonly tools: readonly HarnessTool[];\n readonly modelProvider: ModelProvider;\n readonly sandbox: SandboxLease;\n readonly signal: AbortSignal;\n emit(event: AgentEvent): void;\n hold(): () => void;\n}\n\nexport interface ToolCallBatch {\n readonly concurrent: boolean;\n readonly calls: readonly PreparedCall[];\n}\n\nexport type ValidatedInput =\n { readonly value: unknown } | { readonly outcome: ToolOutcome };\n\nexport interface ToolOutcome {\n readonly content: string;\n readonly isError: boolean;\n}\n\nexport interface HarnessHistory {\n readonly messages: readonly ModelMessage[];\n append(message: ModelMessage): Promise<void>;\n replace(messages: readonly ModelMessage[]): Promise<void>;\n}\n\nexport interface CustomTurnContext extends TurnContext {\n readonly continuation?: DispatchOptions[\"continuation\"];\n}\n\nexport interface LoopState {\n readonly history: HarnessHistory;\n readonly step: number;\n toolCalls: number;\n}\n\nexport type StopHandler = (\n runtime: HarnessRuntime,\n state: LoopState,\n result: ModelResult,\n content: readonly ModelContentBlock[],\n) => Promise<string | undefined>;\n\nexport interface PreparedCall {\n readonly call: ModelToolCallBlock;\n readonly tool?: HarnessTool;\n readonly input?: unknown;\n readonly outcome?: ToolOutcome;\n}\n\nexport interface ToolDenial {\n readonly deny: string;\n}\n\nexport type BlockRenderers = {\n readonly [Type in ModelContentBlock[\"type\"]]: (\n block: Extract<ModelContentBlock, { type: Type }>,\n ) => string;\n};\n"]}
@@ -1,2 +1,2 @@
1
1
  export declare const hookDeadlineMs = 600000;
2
- export declare const warmConfigurationKeys: readonly ["repository", "branch", "provider", "workspace", "copies", "hooks", "limits", "bootstrap", "conversationHome", "includeUncommitted"];
2
+ export declare const warmConfigurationKeys: readonly ["repository", "branch", "sandboxProvider", "workspace", "copies", "hooks", "limits", "bootstrap", "conversationHome", "includeUncommitted"];
@@ -2,7 +2,7 @@ export const hookDeadlineMs = 600_000;
2
2
  export const warmConfigurationKeys = [
3
3
  "repository",
4
4
  "branch",
5
- "provider",
5
+ "sandboxProvider",
6
6
  "workspace",
7
7
  "copies",
8
8
  "hooks",
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.constants.js","sourceRoot":"","sources":["../../src/application/lifecycle.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AACtC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,YAAY;IACZ,QAAQ;IACR,UAAU;IACV,WAAW;IACX,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,WAAW;IACX,kBAAkB;IAClB,oBAAoB;CACZ,CAAC","sourcesContent":["export const hookDeadlineMs = 600_000;\nexport const warmConfigurationKeys = [\n \"repository\",\n \"branch\",\n \"provider\",\n \"workspace\",\n \"copies\",\n \"hooks\",\n \"limits\",\n \"bootstrap\",\n \"conversationHome\",\n \"includeUncommitted\",\n] as const;\n"]}
1
+ {"version":3,"file":"lifecycle.constants.js","sourceRoot":"","sources":["../../src/application/lifecycle.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AACtC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,YAAY;IACZ,QAAQ;IACR,iBAAiB;IACjB,WAAW;IACX,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,WAAW;IACX,kBAAkB;IAClB,oBAAoB;CACZ,CAAC","sourcesContent":["export const hookDeadlineMs = 600_000;\nexport const warmConfigurationKeys = [\n \"repository\",\n \"branch\",\n \"sandboxProvider\",\n \"workspace\",\n \"copies\",\n \"hooks\",\n \"limits\",\n \"bootstrap\",\n \"conversationHome\",\n \"includeUncommitted\",\n] as const;\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { Transport, TransportReference } from "../domain/transport.types.ts";
2
- import type { AgentAdapter } from "../domain/agent.types.ts";
2
+ import type { Agent } from "../domain/agent.types.ts";
3
3
  import type { Command, CommandResult } from "../domain/command.types.ts";
4
4
  import type { Brief } from "../domain/prompts.types.ts";
5
5
  import type { SandboxProvider } from "../domain/sandbox.types.ts";
@@ -21,11 +21,11 @@ export interface WorkspaceOptions {
21
21
  }
22
22
  export interface Workspace extends WorkspaceRecord {
23
23
  dispatch<T = undefined>(options: Omit<SandboxOptions, Exclude<keyof WorkspaceOptions, "hooks" | "label"> | "workspace"> & DispatchOptions<T> & {
24
- readonly agent: AgentAdapter;
24
+ readonly agent: Agent;
25
25
  }): Promise<DispatchResult<T>>;
26
26
  sandbox(options?: Omit<SandboxOptions, Exclude<keyof WorkspaceOptions, "hooks" | "label"> | "workspace">): Promise<Sandbox>;
27
27
  attach(options: Omit<SandboxOptions, Exclude<keyof WorkspaceOptions, "hooks" | "label"> | "workspace"> & AttachOptions & {
28
- readonly agent: AgentAdapter;
28
+ readonly agent: Agent;
29
29
  }): Promise<AttachResult>;
30
30
  close(options?: {
31
31
  readonly preserve?: boolean;
@@ -35,8 +35,8 @@ export interface Workspace extends WorkspaceRecord {
35
35
  }
36
36
  export interface SandboxOptions extends WorkspaceOptions {
37
37
  readonly includeUncommitted?: boolean;
38
- readonly agent?: AgentAdapter;
39
- readonly provider?: SandboxProvider;
38
+ readonly agent?: Agent;
39
+ readonly sandboxProvider?: SandboxProvider;
40
40
  readonly workspace?: Workspace;
41
41
  readonly hooks?: LifecycleHooks;
42
42
  readonly signal?: AbortSignal;
@@ -48,7 +48,7 @@ export interface SandboxOptions extends WorkspaceOptions {
48
48
  }
49
49
  export interface AttachOptions {
50
50
  readonly ask?: VariableQuestion;
51
- readonly agent?: AgentAdapter;
51
+ readonly agent?: Agent;
52
52
  readonly brief?: Brief;
53
53
  readonly continuation?: {
54
54
  readonly id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"outpost.types.js","sourceRoot":"","sources":["../../src/application/outpost.types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n Transport,\n TransportReference,\n} from \"../domain/transport.types.ts\";\nimport type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport type { Command, CommandResult } from \"../domain/command.types.ts\";\nimport type { Brief } from \"../domain/prompts.types.ts\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport type {\n BranchPolicy,\n Commit,\n Disposal,\n LifecycleHooks,\n StageLimits,\n WorkspaceRecord,\n} from \"../domain/workspace.types.ts\";\nimport type { StorageReservationOptions } from \"../infrastructure/storage-reservations.types.ts\";\nimport type { Logging } from \"../infrastructure/journal.types.ts\";\nimport type {\n SandboxDiagnosticOptions,\n SandboxDiagnosticReport,\n} from \"./doctor-sandbox.types.ts\";\nimport type { DispatchOptions, Execution } from \"./execution.types.ts\";\nimport type { VariableQuestion } from \"./interactive-brief.types.ts\";\n\nexport interface WorkspaceOptions {\n readonly storageQuota?: Omit<StorageReservationOptions, \"signal\">;\n readonly signal?: AbortSignal;\n readonly repository?: string;\n readonly branch?: BranchPolicy;\n readonly copies?: readonly string[];\n readonly limits?: StageLimits;\n readonly label?: string;\n readonly hooks?: LifecycleHooks;\n}\n\nexport interface Workspace extends WorkspaceRecord {\n dispatch<T = undefined>(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n DispatchOptions<T> & { readonly agent: AgentAdapter },\n ): Promise<DispatchResult<T>>;\n sandbox(\n options?: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n >,\n ): Promise<Sandbox>;\n attach(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n AttachOptions & { readonly agent: AgentAdapter },\n ): Promise<AttachResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n integrate(): Promise<void>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nexport interface SandboxOptions extends WorkspaceOptions {\n readonly includeUncommitted?: boolean;\n readonly agent?: AgentAdapter;\n readonly provider?: SandboxProvider;\n readonly workspace?: Workspace;\n readonly hooks?: LifecycleHooks;\n readonly signal?: AbortSignal;\n readonly logging?: Logging;\n readonly bootstrap?: boolean;\n readonly conversationHome?: string;\n readonly recoveryTransport?: Transport;\n readonly activityTransport?: Transport;\n}\n\nexport interface AttachOptions {\n readonly ask?: VariableQuestion;\n readonly agent?: AgentAdapter;\n readonly brief?: Brief;\n readonly continuation?: { readonly id: string; readonly fork?: boolean };\n readonly signal?: AbortSignal;\n readonly terminal?: Command[\"terminal\"];\n}\n\nexport interface AttachResult extends CommandResult, Disposal {\n readonly commits: readonly Commit[];\n readonly branch: string;\n readonly directory: string;\n}\n\nexport interface DispatchResult<T> extends Execution<T> {\n readonly branch: string;\n readonly directory: string;\n readonly commits: readonly Commit[];\n readonly transcript?: string;\n readonly transcriptReference?: TransportReference;\n readonly logReference?: TransportReference;\n readonly log?: string;\n readonly retainedDirectory?: string;\n resume<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n fork<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n}\n\nexport type ContinuationOptions<T = undefined> = DispatchOptions<T> &\n Omit<SandboxOptions, \"agent\">;\n\nexport interface WarmDispatchResult<T> extends Omit<\n DispatchResult<T>,\n \"resume\" | \"fork\"\n> {\n resume<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n fork<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n}\n\nexport interface Sandbox {\n diagnose(\n options?: SandboxDiagnosticOptions,\n ): Promise<SandboxDiagnosticReport>;\n readonly workspace: Workspace;\n readonly root: string;\n dispatch<T = undefined>(\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n resume<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n fork<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n attach(options?: AttachOptions): Promise<AttachResult>;\n command(command: Command): Promise<CommandResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"outpost.types.js","sourceRoot":"","sources":["../../src/application/outpost.types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n Transport,\n TransportReference,\n} from \"../domain/transport.types.ts\";\nimport type { Agent } from \"../domain/agent.types.ts\";\nimport type { Command, CommandResult } from \"../domain/command.types.ts\";\nimport type { Brief } from \"../domain/prompts.types.ts\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport type {\n BranchPolicy,\n Commit,\n Disposal,\n LifecycleHooks,\n StageLimits,\n WorkspaceRecord,\n} from \"../domain/workspace.types.ts\";\nimport type { StorageReservationOptions } from \"../infrastructure/storage-reservations.types.ts\";\nimport type { Logging } from \"../infrastructure/journal.types.ts\";\nimport type {\n SandboxDiagnosticOptions,\n SandboxDiagnosticReport,\n} from \"./doctor-sandbox.types.ts\";\nimport type { DispatchOptions, Execution } from \"./execution.types.ts\";\nimport type { VariableQuestion } from \"./interactive-brief.types.ts\";\n\nexport interface WorkspaceOptions {\n readonly storageQuota?: Omit<StorageReservationOptions, \"signal\">;\n readonly signal?: AbortSignal;\n readonly repository?: string;\n readonly branch?: BranchPolicy;\n readonly copies?: readonly string[];\n readonly limits?: StageLimits;\n readonly label?: string;\n readonly hooks?: LifecycleHooks;\n}\n\nexport interface Workspace extends WorkspaceRecord {\n dispatch<T = undefined>(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n DispatchOptions<T> & { readonly agent: Agent },\n ): Promise<DispatchResult<T>>;\n sandbox(\n options?: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n >,\n ): Promise<Sandbox>;\n attach(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n AttachOptions & { readonly agent: Agent },\n ): Promise<AttachResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n integrate(): Promise<void>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nexport interface SandboxOptions extends WorkspaceOptions {\n readonly includeUncommitted?: boolean;\n readonly agent?: Agent;\n readonly sandboxProvider?: SandboxProvider;\n readonly workspace?: Workspace;\n readonly hooks?: LifecycleHooks;\n readonly signal?: AbortSignal;\n readonly logging?: Logging;\n readonly bootstrap?: boolean;\n readonly conversationHome?: string;\n readonly recoveryTransport?: Transport;\n readonly activityTransport?: Transport;\n}\n\nexport interface AttachOptions {\n readonly ask?: VariableQuestion;\n readonly agent?: Agent;\n readonly brief?: Brief;\n readonly continuation?: { readonly id: string; readonly fork?: boolean };\n readonly signal?: AbortSignal;\n readonly terminal?: Command[\"terminal\"];\n}\n\nexport interface AttachResult extends CommandResult, Disposal {\n readonly commits: readonly Commit[];\n readonly branch: string;\n readonly directory: string;\n}\n\nexport interface DispatchResult<T> extends Execution<T> {\n readonly branch: string;\n readonly directory: string;\n readonly commits: readonly Commit[];\n readonly transcript?: string;\n readonly transcriptReference?: TransportReference;\n readonly logReference?: TransportReference;\n readonly log?: string;\n readonly retainedDirectory?: string;\n resume<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n fork<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n}\n\nexport type ContinuationOptions<T = undefined> = DispatchOptions<T> &\n Omit<SandboxOptions, \"agent\">;\n\nexport interface WarmDispatchResult<T> extends Omit<\n DispatchResult<T>,\n \"resume\" | \"fork\"\n> {\n resume<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n fork<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n}\n\nexport interface Sandbox {\n diagnose(\n options?: SandboxDiagnosticOptions,\n ): Promise<SandboxDiagnosticReport>;\n readonly workspace: Workspace;\n readonly root: string;\n dispatch<T = undefined>(\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n resume<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n fork<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n attach(options?: AttachOptions): Promise<AttachResult>;\n command(command: Command): Promise<CommandResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n"]}
@@ -13,7 +13,7 @@ export async function downloadChanges(context, synchronized, transfer) {
13
13
  .split("\0")
14
14
  .filter(Boolean);
15
15
  for (const file of incoming) {
16
- if (/^\.outpost\/(locks|recovery|workspaces|logs)(\/|$)/i.test(file))
16
+ if (/^\.outpost\/(locks|recovery|workspaces|logs|conversations)(\/|$)/i.test(file))
17
17
  throw new OutpostError("workspace", "Remote file overlaps Outpost runtime state", { file });
18
18
  await safeDestination(join(transfer, "incoming"), file);
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"remote-download.js","sourceRoot":"","sources":["../../src/application/remote-download.ts"],"names":[],"mappings":"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","sourcesContent":["import { cp, mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, posix } from \"node:path\";\nimport { downloadHistory } from \"./remote-history.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport {\n fileManifest,\n parseManifest,\n sameFile,\n sameLocalFile,\n} from \"../infrastructure/file-manifest.ts\";\nimport type { FileManifestEntry } from \"../domain/sandbox.types.ts\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\nimport type {\n RemoteChanges,\n RemoteWorkspaceContext,\n} from \"./remote-workspace.types.ts\";\n\nexport async function downloadChanges(\n context: RemoteWorkspaceContext,\n synchronized: string,\n transfer: string,\n): Promise<RemoteChanges> {\n const { workspace, lease, remoteBundle, run } = context;\n const head = (await run([\"rev-parse\", \"HEAD\"])).trim(),\n patch = join(transfer, \"remote.patch\");\n await run([\"diff\", \"--binary\", \"HEAD\", `--output=${remoteBundle}.patch`]);\n await lease.download(`${remoteBundle}.patch`, patch);\n const incoming = (\n await run([\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"])\n )\n .split(\"\\0\")\n .filter(Boolean);\n for (const file of incoming) {\n if (/^\\.outpost\\/(locks|recovery|workspaces|logs)(\\/|$)/i.test(file))\n throw new OutpostError(\n \"workspace\",\n \"Remote file overlaps Outpost runtime state\",\n { file },\n );\n await safeDestination(join(transfer, \"incoming\"), file);\n }\n let manifest: readonly FileManifestEntry[] | undefined;\n if (lease.fileTransfers) {\n manifest = parseManifest(\n await lease.fileTransfers.manifest(lease.root, incoming),\n incoming,\n );\n await writeFile(join(transfer, \"manifest.json\"), JSON.stringify(manifest), {\n mode: 0o600,\n });\n const changed: FileManifestEntry[] = [];\n for (const entry of manifest) {\n const previous = context.transferred?.get(entry.path);\n if (\n previous &&\n sameFile(previous, entry) &&\n sameLocalFile(\n entry,\n await fileManifest(workspace.directory, entry.path),\n )\n ) {\n const target = await safeDestination(\n join(transfer, \"incoming\"),\n entry.path,\n );\n await mkdir(dirname(target), { recursive: true });\n await cp(\n await safeDestination(workspace.directory, entry.path),\n target,\n { dereference: false, verbatimSymlinks: true },\n );\n continue;\n }\n changed.push(entry);\n }\n await lease.fileTransfers.downloadBatch(\n lease.root,\n changed,\n join(transfer, \"incoming\"),\n );\n for (const entry of manifest) {\n if (\n !sameLocalFile(\n entry,\n await fileManifest(join(transfer, \"incoming\"), entry.path),\n )\n )\n throw new OutpostError(\"workspace\", \"Incoming file checksum mismatch\", {\n file: entry.path,\n });\n }\n } else\n for (const file of incoming) {\n await lease.download(\n posix.join(lease.root, file),\n await safeDestination(join(transfer, \"incoming\"), file),\n );\n }\n if (head !== synchronized) {\n await downloadHistory(context, synchronized, head, transfer);\n }\n\n return { head, patch, incoming, ...(manifest ? { manifest } : {}) };\n}\n"]}
1
+ {"version":3,"file":"remote-download.js","sourceRoot":"","sources":["../../src/application/remote-download.ts"],"names":[],"mappings":"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","sourcesContent":["import { cp, mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, posix } from \"node:path\";\nimport { downloadHistory } from \"./remote-history.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport {\n fileManifest,\n parseManifest,\n sameFile,\n sameLocalFile,\n} from \"../infrastructure/file-manifest.ts\";\nimport type { FileManifestEntry } from \"../domain/sandbox.types.ts\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\nimport type {\n RemoteChanges,\n RemoteWorkspaceContext,\n} from \"./remote-workspace.types.ts\";\n\nexport async function downloadChanges(\n context: RemoteWorkspaceContext,\n synchronized: string,\n transfer: string,\n): Promise<RemoteChanges> {\n const { workspace, lease, remoteBundle, run } = context;\n const head = (await run([\"rev-parse\", \"HEAD\"])).trim(),\n patch = join(transfer, \"remote.patch\");\n await run([\"diff\", \"--binary\", \"HEAD\", `--output=${remoteBundle}.patch`]);\n await lease.download(`${remoteBundle}.patch`, patch);\n const incoming = (\n await run([\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"])\n )\n .split(\"\\0\")\n .filter(Boolean);\n for (const file of incoming) {\n if (\n /^\\.outpost\\/(locks|recovery|workspaces|logs|conversations)(\\/|$)/i.test(\n file,\n )\n )\n throw new OutpostError(\n \"workspace\",\n \"Remote file overlaps Outpost runtime state\",\n { file },\n );\n await safeDestination(join(transfer, \"incoming\"), file);\n }\n let manifest: readonly FileManifestEntry[] | undefined;\n if (lease.fileTransfers) {\n manifest = parseManifest(\n await lease.fileTransfers.manifest(lease.root, incoming),\n incoming,\n );\n await writeFile(join(transfer, \"manifest.json\"), JSON.stringify(manifest), {\n mode: 0o600,\n });\n const changed: FileManifestEntry[] = [];\n for (const entry of manifest) {\n const previous = context.transferred?.get(entry.path);\n if (\n previous &&\n sameFile(previous, entry) &&\n sameLocalFile(\n entry,\n await fileManifest(workspace.directory, entry.path),\n )\n ) {\n const target = await safeDestination(\n join(transfer, \"incoming\"),\n entry.path,\n );\n await mkdir(dirname(target), { recursive: true });\n await cp(\n await safeDestination(workspace.directory, entry.path),\n target,\n { dereference: false, verbatimSymlinks: true },\n );\n continue;\n }\n changed.push(entry);\n }\n await lease.fileTransfers.downloadBatch(\n lease.root,\n changed,\n join(transfer, \"incoming\"),\n );\n for (const entry of manifest) {\n if (\n !sameLocalFile(\n entry,\n await fileManifest(join(transfer, \"incoming\"), entry.path),\n )\n )\n throw new OutpostError(\"workspace\", \"Incoming file checksum mismatch\", {\n file: entry.path,\n });\n }\n } else\n for (const file of incoming) {\n await lease.download(\n posix.join(lease.root, file),\n await safeDestination(join(transfer, \"incoming\"), file),\n );\n }\n if (head !== synchronized) {\n await downloadHistory(context, synchronized, head, transfer);\n }\n\n return { head, patch, incoming, ...(manifest ? { manifest } : {}) };\n}\n"]}