@elie-laloum/outpost 5.0.0 → 7.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 (647) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +11 -11
  3. package/SECURITY.md +10 -0
  4. package/dist/adapters/agents/antigravity-adapter.d.ts +3 -0
  5. package/dist/adapters/agents/antigravity-adapter.js +41 -0
  6. package/dist/adapters/agents/antigravity-adapter.js.map +1 -0
  7. package/dist/adapters/agents/antigravity-authentication.d.ts +2 -0
  8. package/dist/adapters/agents/antigravity-authentication.js +27 -0
  9. package/dist/adapters/agents/antigravity-authentication.js.map +1 -0
  10. package/dist/adapters/agents/antigravity-diagnostics.d.ts +1 -0
  11. package/dist/adapters/agents/antigravity-diagnostics.js +6 -0
  12. package/dist/adapters/agents/antigravity-diagnostics.js.map +1 -0
  13. package/dist/adapters/agents/antigravity-events.d.ts +2 -0
  14. package/dist/adapters/agents/antigravity-events.js +75 -0
  15. package/dist/adapters/agents/antigravity-events.js.map +1 -0
  16. package/dist/adapters/agents/antigravity-request.d.ts +5 -0
  17. package/dist/adapters/agents/antigravity-request.js +37 -0
  18. package/dist/adapters/agents/antigravity-request.js.map +1 -0
  19. package/dist/adapters/agents/antigravity.constants.d.ts +3 -0
  20. package/dist/adapters/agents/antigravity.constants.js +4 -0
  21. package/dist/adapters/agents/antigravity.constants.js.map +1 -0
  22. package/dist/adapters/agents/{gemini.types.d.ts → antigravity.types.d.ts} +2 -2
  23. package/dist/adapters/agents/antigravity.types.js +2 -0
  24. package/dist/adapters/agents/antigravity.types.js.map +1 -0
  25. package/dist/adapters/agents/authentication.constants.d.ts +19 -9
  26. package/dist/adapters/agents/authentication.constants.js +12 -9
  27. package/dist/adapters/agents/authentication.constants.js.map +1 -1
  28. package/dist/adapters/agents/authentication.d.ts +11 -2
  29. package/dist/adapters/agents/authentication.js +70 -47
  30. package/dist/adapters/agents/authentication.js.map +1 -1
  31. package/dist/adapters/agents/authentication.types.d.ts +20 -0
  32. package/dist/adapters/agents/authentication.types.js +2 -0
  33. package/dist/adapters/agents/authentication.types.js.map +1 -0
  34. package/dist/adapters/agents/claude-adapter.js +4 -2
  35. package/dist/adapters/agents/claude-adapter.js.map +1 -1
  36. package/dist/adapters/agents/claude-authentication.d.ts +2 -0
  37. package/dist/adapters/agents/claude-authentication.js +34 -0
  38. package/dist/adapters/agents/claude-authentication.js.map +1 -0
  39. package/dist/adapters/agents/claude-events.js +52 -9
  40. package/dist/adapters/agents/claude-events.js.map +1 -1
  41. package/dist/adapters/agents/claude-request.js +2 -0
  42. package/dist/adapters/agents/claude-request.js.map +1 -1
  43. package/dist/adapters/agents/cli-diagnostics.constants.d.ts +6 -6
  44. package/dist/adapters/agents/cli-diagnostics.constants.js +6 -6
  45. package/dist/adapters/agents/cli-diagnostics.constants.js.map +1 -1
  46. package/dist/adapters/agents/cli-diagnostics.d.ts +1 -0
  47. package/dist/adapters/agents/cli-diagnostics.js +18 -0
  48. package/dist/adapters/agents/cli-diagnostics.js.map +1 -1
  49. package/dist/adapters/agents/codex-adapter.js +4 -2
  50. package/dist/adapters/agents/codex-adapter.js.map +1 -1
  51. package/dist/adapters/agents/codex-authentication.d.ts +3 -0
  52. package/dist/adapters/agents/codex-authentication.js +47 -0
  53. package/dist/adapters/agents/codex-authentication.js.map +1 -0
  54. package/dist/adapters/agents/codex-events.js +28 -2
  55. package/dist/adapters/agents/codex-events.js.map +1 -1
  56. package/dist/adapters/agents/copilot-adapter.d.ts +3 -0
  57. package/dist/adapters/agents/copilot-adapter.js +45 -0
  58. package/dist/adapters/agents/copilot-adapter.js.map +1 -0
  59. package/dist/adapters/agents/copilot-authentication.d.ts +2 -0
  60. package/dist/adapters/agents/copilot-authentication.js +46 -0
  61. package/dist/adapters/agents/copilot-authentication.js.map +1 -0
  62. package/dist/adapters/agents/copilot-diagnostics.d.ts +1 -0
  63. package/dist/adapters/agents/copilot-diagnostics.js +6 -0
  64. package/dist/adapters/agents/copilot-diagnostics.js.map +1 -0
  65. package/dist/adapters/agents/copilot-events.d.ts +2 -0
  66. package/dist/adapters/agents/copilot-events.js +66 -0
  67. package/dist/adapters/agents/copilot-events.js.map +1 -0
  68. package/dist/adapters/agents/copilot-request.d.ts +5 -0
  69. package/dist/adapters/agents/copilot-request.js +24 -0
  70. package/dist/adapters/agents/copilot-request.js.map +1 -0
  71. package/dist/adapters/agents/copilot-usage.d.ts +3 -0
  72. package/dist/adapters/agents/copilot-usage.js +19 -0
  73. package/dist/adapters/agents/copilot-usage.js.map +1 -0
  74. package/dist/adapters/agents/copilot.types.d.ts +6 -0
  75. package/dist/adapters/agents/copilot.types.js +2 -0
  76. package/dist/adapters/agents/copilot.types.js.map +1 -0
  77. package/dist/adapters/agents/event-decoder.d.ts +2 -2
  78. package/dist/adapters/agents/event-decoder.js +6 -5
  79. package/dist/adapters/agents/event-decoder.js.map +1 -1
  80. package/dist/adapters/agents/kimi-adapter.d.ts +3 -0
  81. package/dist/adapters/agents/kimi-adapter.js +51 -0
  82. package/dist/adapters/agents/kimi-adapter.js.map +1 -0
  83. package/dist/adapters/agents/kimi-authentication.d.ts +3 -0
  84. package/dist/adapters/agents/kimi-authentication.js +63 -0
  85. package/dist/adapters/agents/kimi-authentication.js.map +1 -0
  86. package/dist/adapters/agents/kimi-diagnostics.d.ts +2 -0
  87. package/dist/adapters/agents/kimi-diagnostics.js +14 -0
  88. package/dist/adapters/agents/kimi-diagnostics.js.map +1 -0
  89. package/dist/adapters/agents/kimi-events.d.ts +2 -0
  90. package/dist/adapters/agents/kimi-events.js +55 -0
  91. package/dist/adapters/agents/kimi-events.js.map +1 -0
  92. package/dist/adapters/agents/kimi-fork.d.ts +2 -0
  93. package/dist/adapters/agents/kimi-fork.js +11 -0
  94. package/dist/adapters/agents/kimi-fork.js.map +1 -0
  95. package/dist/adapters/agents/{gemini-request.d.ts → kimi-request.d.ts} +2 -2
  96. package/dist/adapters/agents/kimi-request.js +33 -0
  97. package/dist/adapters/agents/kimi-request.js.map +1 -0
  98. package/dist/adapters/agents/kimi-usage.d.ts +2 -0
  99. package/dist/adapters/agents/kimi-usage.js +7 -0
  100. package/dist/adapters/agents/kimi-usage.js.map +1 -0
  101. package/dist/adapters/agents/kimi.constants.d.ts +13 -0
  102. package/dist/adapters/agents/kimi.constants.js +14 -0
  103. package/dist/adapters/agents/kimi.constants.js.map +1 -0
  104. package/dist/adapters/agents/kimi.types.d.ts +7 -0
  105. package/dist/adapters/agents/kimi.types.js +2 -0
  106. package/dist/adapters/agents/kimi.types.js.map +1 -0
  107. package/dist/adapters/agents/model-support.constants.d.ts +3 -1
  108. package/dist/adapters/agents/model-support.constants.js +12 -2
  109. package/dist/adapters/agents/model-support.constants.js.map +1 -1
  110. package/dist/adapters/agents/protocol-fixtures.constants.d.ts +2 -2
  111. package/dist/adapters/agents/protocol-fixtures.constants.js +131 -9
  112. package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -1
  113. package/dist/adapters/agents/protocol-fixtures.types.d.ts +1 -0
  114. package/dist/adapters/agents/protocol-fixtures.types.js.map +1 -1
  115. package/dist/adapters/agents/protocol.d.ts +1 -0
  116. package/dist/adapters/agents/protocol.js +9 -0
  117. package/dist/adapters/agents/protocol.js.map +1 -1
  118. package/dist/adapters/agents/session-usage.constants.d.ts +10 -0
  119. package/dist/adapters/agents/session-usage.constants.js +110 -0
  120. package/dist/adapters/agents/session-usage.constants.js.map +1 -0
  121. package/dist/adapters/agents/session-usage.d.ts +5 -0
  122. package/dist/adapters/agents/session-usage.js +45 -0
  123. package/dist/adapters/agents/session-usage.js.map +1 -0
  124. package/dist/adapters/agents/settings.types.d.ts +1 -0
  125. package/dist/adapters/agents/settings.types.js.map +1 -1
  126. package/dist/adapters/agents/tool-result.d.ts +2 -0
  127. package/dist/adapters/agents/tool-result.js +17 -0
  128. package/dist/adapters/agents/tool-result.js.map +1 -0
  129. package/dist/adapters/models/anthropic-response.js +3 -0
  130. package/dist/adapters/models/anthropic-response.js.map +1 -1
  131. package/dist/adapters/models/http-provider.js +6 -1
  132. package/dist/adapters/models/http-provider.js.map +1 -1
  133. package/dist/adapters/models/openai-responses.js +10 -0
  134. package/dist/adapters/models/openai-responses.js.map +1 -1
  135. package/dist/adapters/models/retry-after.d.ts +1 -0
  136. package/dist/adapters/models/retry-after.js +16 -0
  137. package/dist/adapters/models/retry-after.js.map +1 -0
  138. package/dist/application/activity-watchdog.js +1 -2
  139. package/dist/application/activity-watchdog.js.map +1 -1
  140. package/dist/application/agent-authentication.d.ts +4 -0
  141. package/dist/application/agent-authentication.js +32 -0
  142. package/dist/application/agent-authentication.js.map +1 -0
  143. package/dist/application/agent-bootstrap.constants.d.ts +2 -5
  144. package/dist/application/agent-bootstrap.constants.js +27 -4
  145. package/dist/application/agent-bootstrap.constants.js.map +1 -1
  146. package/dist/application/agent-bootstrap.js +39 -12
  147. package/dist/application/agent-bootstrap.js.map +1 -1
  148. package/dist/application/agent-bootstrap.types.d.ts +19 -0
  149. package/dist/application/agent-bootstrap.types.js +2 -0
  150. package/dist/application/agent-bootstrap.types.js.map +1 -0
  151. package/dist/application/agent-output.js +74 -8
  152. package/dist/application/agent-output.js.map +1 -1
  153. package/dist/application/agent-request.d.ts +3 -0
  154. package/dist/application/agent-request.js +11 -0
  155. package/dist/application/agent-request.js.map +1 -0
  156. package/dist/application/agent-turn.js +74 -6
  157. package/dist/application/agent-turn.js.map +1 -1
  158. package/dist/application/agent-usage.d.ts +6 -0
  159. package/dist/application/agent-usage.js +57 -0
  160. package/dist/application/agent-usage.js.map +1 -0
  161. package/dist/application/attach.js +2 -0
  162. package/dist/application/attach.js.map +1 -1
  163. package/dist/application/credential-installer.constants.d.ts +1 -0
  164. package/dist/application/credential-installer.constants.js +22 -0
  165. package/dist/application/credential-installer.constants.js.map +1 -0
  166. package/dist/application/custom-turn.js +44 -49
  167. package/dist/application/custom-turn.js.map +1 -1
  168. package/dist/application/dispatch-observation.d.ts +1 -1
  169. package/dist/application/dispatch-observation.js +141 -21
  170. package/dist/application/dispatch-observation.js.map +1 -1
  171. package/dist/application/dispatch-observation.types.d.ts +2 -0
  172. package/dist/application/dispatch-observation.types.js.map +1 -1
  173. package/dist/application/dispatch-validation.js +2 -0
  174. package/dist/application/dispatch-validation.js.map +1 -1
  175. package/dist/application/dispatch.js +1 -1
  176. package/dist/application/dispatch.js.map +1 -1
  177. package/dist/application/doctor-agent.constants.d.ts +2 -8
  178. package/dist/application/doctor-agent.constants.js +43 -6
  179. package/dist/application/doctor-agent.constants.js.map +1 -1
  180. package/dist/application/doctor-agent.d.ts +2 -1
  181. package/dist/application/doctor-agent.js +15 -3
  182. package/dist/application/doctor-agent.js.map +1 -1
  183. package/dist/application/doctor-image.js +4 -6
  184. package/dist/application/doctor-image.js.map +1 -1
  185. package/dist/application/doctor-protocol.js +6 -11
  186. package/dist/application/doctor-protocol.js.map +1 -1
  187. package/dist/application/doctor-protocol.types.d.ts +1 -1
  188. package/dist/application/doctor-protocol.types.js.map +1 -1
  189. package/dist/application/doctor-sandbox.js +2 -5
  190. package/dist/application/doctor-sandbox.js.map +1 -1
  191. package/dist/application/doctor.js +28 -10
  192. package/dist/application/doctor.js.map +1 -1
  193. package/dist/application/doctor.types.d.ts +10 -1
  194. package/dist/application/doctor.types.js.map +1 -1
  195. package/dist/application/execution.constants.d.ts +2 -0
  196. package/dist/application/execution.constants.js +2 -0
  197. package/dist/application/execution.constants.js.map +1 -1
  198. package/dist/application/execution.types.d.ts +8 -0
  199. package/dist/application/execution.types.js.map +1 -1
  200. package/dist/application/harness-budget.d.ts +3 -0
  201. package/dist/application/harness-budget.js +42 -0
  202. package/dist/application/harness-budget.js.map +1 -0
  203. package/dist/application/harness-budget.types.d.ts +5 -0
  204. package/dist/application/harness-budget.types.js +2 -0
  205. package/dist/application/harness-budget.types.js.map +1 -0
  206. package/dist/application/harness-hooks.js +34 -3
  207. package/dist/application/harness-hooks.js.map +1 -1
  208. package/dist/application/harness-loop.js +52 -24
  209. package/dist/application/harness-loop.js.map +1 -1
  210. package/dist/application/harness-model-provider.d.ts +3 -0
  211. package/dist/application/harness-model-provider.js +49 -0
  212. package/dist/application/harness-model-provider.js.map +1 -0
  213. package/dist/application/harness-model-provider.types.d.ts +10 -0
  214. package/dist/application/harness-model-provider.types.js +2 -0
  215. package/dist/application/harness-model-provider.types.js.map +1 -0
  216. package/dist/application/harness-subagent.d.ts +4 -0
  217. package/dist/application/harness-subagent.js +110 -0
  218. package/dist/application/harness-subagent.js.map +1 -0
  219. package/dist/application/harness.types.d.ts +11 -0
  220. package/dist/application/harness.types.js.map +1 -1
  221. package/dist/application/lifecycle-hooks.d.ts +1 -1
  222. package/dist/application/lifecycle-hooks.js +5 -4
  223. package/dist/application/lifecycle-hooks.js.map +1 -1
  224. package/dist/application/observed-lease.d.ts +3 -0
  225. package/dist/application/observed-lease.js +26 -0
  226. package/dist/application/observed-lease.js.map +1 -0
  227. package/dist/application/outpost.types.d.ts +3 -1
  228. package/dist/application/outpost.types.js.map +1 -1
  229. package/dist/application/output-lines.d.ts +4 -0
  230. package/dist/application/output-lines.js +28 -0
  231. package/dist/application/output-lines.js.map +1 -0
  232. package/dist/application/queue-worker.js +1 -1
  233. package/dist/application/queue-worker.js.map +1 -1
  234. package/dist/application/queue-worker.types.d.ts +1 -0
  235. package/dist/application/queue-worker.types.js.map +1 -1
  236. package/dist/application/queued-task.js +24 -5
  237. package/dist/application/queued-task.js.map +1 -1
  238. package/dist/application/recovery-archive.d.ts +3 -2
  239. package/dist/application/recovery-archive.js +9 -2
  240. package/dist/application/recovery-archive.js.map +1 -1
  241. package/dist/application/recovery-restore.d.ts +3 -2
  242. package/dist/application/recovery-restore.js +9 -2
  243. package/dist/application/recovery-restore.js.map +1 -1
  244. package/dist/application/recovery-retention.d.ts +3 -2
  245. package/dist/application/recovery-retention.js +74 -26
  246. package/dist/application/recovery-retention.js.map +1 -1
  247. package/dist/application/remote-workspace.js +5 -4
  248. package/dist/application/remote-workspace.js.map +1 -1
  249. package/dist/application/remote-workspace.types.d.ts +1 -0
  250. package/dist/application/remote-workspace.types.js.map +1 -1
  251. package/dist/application/sandbox-agents.js +19 -19
  252. package/dist/application/sandbox-agents.js.map +1 -1
  253. package/dist/application/sandbox-attach.js +12 -3
  254. package/dist/application/sandbox-attach.js.map +1 -1
  255. package/dist/application/sandbox-dispatch.js +13 -27
  256. package/dist/application/sandbox-dispatch.js.map +1 -1
  257. package/dist/application/sandbox-provision.js +15 -9
  258. package/dist/application/sandbox-provision.js.map +1 -1
  259. package/dist/application/sandbox-session.types.d.ts +7 -2
  260. package/dist/application/sandbox-session.types.js.map +1 -1
  261. package/dist/application/sandbox.js +13 -6
  262. package/dist/application/sandbox.js.map +1 -1
  263. package/dist/application/speculation-checkpoint.d.ts +6 -0
  264. package/dist/application/speculation-checkpoint.js +206 -0
  265. package/dist/application/speculation-checkpoint.js.map +1 -0
  266. package/dist/application/speculation-checkpoint.types.d.ts +24 -0
  267. package/dist/application/speculation-checkpoint.types.js +2 -0
  268. package/dist/application/speculation-checkpoint.types.js.map +1 -0
  269. package/dist/application/speculation-integration.constants.d.ts +4 -0
  270. package/dist/application/speculation-integration.constants.js +5 -0
  271. package/dist/application/speculation-integration.constants.js.map +1 -0
  272. package/dist/application/speculation-integration.d.ts +2 -0
  273. package/dist/application/speculation-integration.js +67 -0
  274. package/dist/application/speculation-integration.js.map +1 -0
  275. package/dist/application/speculation-resume.d.ts +4 -0
  276. package/dist/application/speculation-resume.js +71 -0
  277. package/dist/application/speculation-resume.js.map +1 -0
  278. package/dist/application/speculation-run.d.ts +4 -0
  279. package/dist/application/speculation-run.js +320 -0
  280. package/dist/application/speculation-run.js.map +1 -0
  281. package/dist/application/speculation-timeout.d.ts +1 -0
  282. package/dist/application/speculation-timeout.js +15 -0
  283. package/dist/application/speculation-timeout.js.map +1 -0
  284. package/dist/application/speculation.constants.d.ts +1 -0
  285. package/dist/application/speculation.constants.js +5 -1
  286. package/dist/application/speculation.constants.js.map +1 -1
  287. package/dist/application/speculation.js +41 -149
  288. package/dist/application/speculation.js.map +1 -1
  289. package/dist/application/speculation.types.d.ts +23 -0
  290. package/dist/application/speculation.types.js.map +1 -1
  291. package/dist/application/startup-recovery.js +14 -1
  292. package/dist/application/startup-recovery.js.map +1 -1
  293. package/dist/application/startup-recovery.types.d.ts +1 -0
  294. package/dist/application/startup-recovery.types.js.map +1 -1
  295. package/dist/application/stop-reason.d.ts +2 -0
  296. package/dist/application/stop-reason.js +21 -0
  297. package/dist/application/stop-reason.js.map +1 -0
  298. package/dist/application/stop-reason.types.d.ts +4 -0
  299. package/dist/application/stop-reason.types.js +2 -0
  300. package/dist/application/stop-reason.types.js.map +1 -0
  301. package/dist/application/storage-reservation.js +9 -2
  302. package/dist/application/storage-reservation.js.map +1 -1
  303. package/dist/application/task-observation.d.ts +3 -0
  304. package/dist/application/task-observation.js +22 -0
  305. package/dist/application/task-observation.js.map +1 -0
  306. package/dist/application/task-usage.js +5 -12
  307. package/dist/application/task-usage.js.map +1 -1
  308. package/dist/application/tasks.js +41 -16
  309. package/dist/application/tasks.js.map +1 -1
  310. package/dist/application/tool-execution.js +42 -19
  311. package/dist/application/tool-execution.js.map +1 -1
  312. package/dist/application/workspace.js +6 -4
  313. package/dist/application/workspace.js.map +1 -1
  314. package/dist/cli/doctor-command.js +6 -2
  315. package/dist/cli/doctor-command.js.map +1 -1
  316. package/dist/cli/init-authentication.d.ts +4 -1
  317. package/dist/cli/init-authentication.js +28 -33
  318. package/dist/cli/init-authentication.js.map +1 -1
  319. package/dist/cli/init-command.js +3 -3
  320. package/dist/cli/init-command.js.map +1 -1
  321. package/dist/cli/main.constants.d.ts +50 -13
  322. package/dist/cli/main.constants.js +70 -8
  323. package/dist/cli/main.constants.js.map +1 -1
  324. package/dist/cli/main.js +2 -1
  325. package/dist/cli/main.js.map +1 -1
  326. package/dist/cli/scaffold-files.js +1 -1
  327. package/dist/cli/scaffold-files.js.map +1 -1
  328. package/dist/cli/scaffold-validation.js +29 -22
  329. package/dist/cli/scaffold-validation.js.map +1 -1
  330. package/dist/cli/scaffold.constants.d.ts +0 -1
  331. package/dist/cli/scaffold.constants.js +6 -2
  332. package/dist/cli/scaffold.constants.js.map +1 -1
  333. package/dist/cli/scaffold.types.d.ts +8 -2
  334. package/dist/cli/scaffold.types.js.map +1 -1
  335. package/dist/cli/starters.js +1 -3
  336. package/dist/cli/starters.js.map +1 -1
  337. package/dist/domain/agent-observation.d.ts +4 -0
  338. package/dist/domain/agent-observation.js +27 -0
  339. package/dist/domain/agent-observation.js.map +1 -0
  340. package/dist/domain/agent.types.d.ts +122 -14
  341. package/dist/domain/agent.types.js.map +1 -1
  342. package/dist/domain/authentication.constants.d.ts +3 -0
  343. package/dist/domain/authentication.constants.js +11 -0
  344. package/dist/domain/authentication.constants.js.map +1 -0
  345. package/dist/domain/authentication.d.ts +3 -0
  346. package/dist/domain/authentication.js +22 -0
  347. package/dist/domain/authentication.js.map +1 -0
  348. package/dist/domain/authentication.types.d.ts +5 -0
  349. package/dist/domain/authentication.types.js +2 -0
  350. package/dist/domain/authentication.types.js.map +1 -0
  351. package/dist/domain/harness.d.ts +2 -2
  352. package/dist/domain/harness.js +6 -0
  353. package/dist/domain/harness.js.map +1 -1
  354. package/dist/domain/harness.types.d.ts +4 -3
  355. package/dist/domain/harness.types.js.map +1 -1
  356. package/dist/domain/model.types.d.ts +8 -0
  357. package/dist/domain/model.types.js.map +1 -1
  358. package/dist/domain/observation.constants.d.ts +8 -0
  359. package/dist/domain/observation.constants.js +9 -0
  360. package/dist/domain/observation.constants.js.map +1 -0
  361. package/dist/domain/observation.d.ts +2 -0
  362. package/dist/domain/observation.js +190 -0
  363. package/dist/domain/observation.js.map +1 -0
  364. package/dist/domain/observation.types.d.ts +84 -0
  365. package/dist/domain/observation.types.js +2 -0
  366. package/dist/domain/observation.types.js.map +1 -0
  367. package/dist/domain/observed-operation.d.ts +2 -0
  368. package/dist/domain/observed-operation.js +30 -0
  369. package/dist/domain/observed-operation.js.map +1 -0
  370. package/dist/domain/sandbox.types.d.ts +2 -0
  371. package/dist/domain/sandbox.types.js.map +1 -1
  372. package/dist/domain/subagent.constants.d.ts +13 -0
  373. package/dist/domain/subagent.constants.js +9 -0
  374. package/dist/domain/subagent.constants.js.map +1 -0
  375. package/dist/domain/subagent.d.ts +4 -0
  376. package/dist/domain/subagent.js +28 -0
  377. package/dist/domain/subagent.js.map +1 -0
  378. package/dist/domain/subagent.types.d.ts +13 -0
  379. package/dist/domain/subagent.types.js +2 -0
  380. package/dist/domain/subagent.types.js.map +1 -0
  381. package/dist/domain/transcript.types.d.ts +2 -0
  382. package/dist/domain/transcript.types.js.map +1 -1
  383. package/dist/domain/usage.d.ts +1 -0
  384. package/dist/domain/usage.js +16 -0
  385. package/dist/domain/usage.js.map +1 -1
  386. package/dist/domain/workflow/budget.d.ts +7 -3
  387. package/dist/domain/workflow/budget.js +26 -0
  388. package/dist/domain/workflow/budget.js.map +1 -1
  389. package/dist/domain/workflow/budget.types.d.ts +1 -1
  390. package/dist/domain/workflow/budget.types.js.map +1 -1
  391. package/dist/domain/workflow/checkpoint-validation.js +7 -1
  392. package/dist/domain/workflow/checkpoint-validation.js.map +1 -1
  393. package/dist/domain/workflow/checkpoint.js +3 -0
  394. package/dist/domain/workflow/checkpoint.js.map +1 -1
  395. package/dist/domain/workflow/gate-validation.js +14 -1
  396. package/dist/domain/workflow/gate-validation.js.map +1 -1
  397. package/dist/domain/workflow/gates.d.ts +1 -1
  398. package/dist/domain/workflow/gates.js +52 -4
  399. package/dist/domain/workflow/gates.js.map +1 -1
  400. package/dist/domain/workflow/gates.types.d.ts +15 -1
  401. package/dist/domain/workflow/gates.types.js.map +1 -1
  402. package/dist/domain/workflow/idempotency.d.ts +1 -0
  403. package/dist/domain/workflow/idempotency.js +7 -0
  404. package/dist/domain/workflow/idempotency.js.map +1 -0
  405. package/dist/domain/workflow/retry.constants.d.ts +2 -0
  406. package/dist/domain/workflow/retry.constants.js +3 -0
  407. package/dist/domain/workflow/retry.constants.js.map +1 -0
  408. package/dist/domain/workflow/retry.d.ts +4 -0
  409. package/dist/domain/workflow/retry.js +49 -0
  410. package/dist/domain/workflow/retry.js.map +1 -0
  411. package/dist/domain/workflow/task-runner.js +9 -5
  412. package/dist/domain/workflow/task-runner.js.map +1 -1
  413. package/dist/domain/workflow/task.js +6 -6
  414. package/dist/domain/workflow/task.js.map +1 -1
  415. package/dist/domain/workflow/workflow-scheduler.js +110 -72
  416. package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
  417. package/dist/domain/workflow/workflow-state.js +28 -12
  418. package/dist/domain/workflow/workflow-state.js.map +1 -1
  419. package/dist/domain/workflow.d.ts +1 -1
  420. package/dist/domain/workflow.js +1 -1
  421. package/dist/domain/workflow.js.map +1 -1
  422. package/dist/domain/workflow.types.d.ts +13 -2
  423. package/dist/domain/workflow.types.js.map +1 -1
  424. package/dist/index.d.ts +16 -11
  425. package/dist/index.js +7 -4
  426. package/dist/index.js.map +1 -1
  427. package/dist/infrastructure/conversations/capture.js +10 -0
  428. package/dist/infrastructure/conversations/capture.js.map +1 -1
  429. package/dist/infrastructure/conversations/harness-transcript.js +6 -0
  430. package/dist/infrastructure/conversations/harness-transcript.js.map +1 -1
  431. package/dist/infrastructure/conversations/harness-transcript.types.d.ts +2 -0
  432. package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -1
  433. package/dist/infrastructure/conversations/layout.js +2 -0
  434. package/dist/infrastructure/conversations/layout.js.map +1 -1
  435. package/dist/infrastructure/conversations/locate.js +7 -1
  436. package/dist/infrastructure/conversations/locate.js.map +1 -1
  437. package/dist/infrastructure/conversations/native-store.js +8 -1
  438. package/dist/infrastructure/conversations/native-store.js.map +1 -1
  439. package/dist/infrastructure/conversations/paths.js +3 -0
  440. package/dist/infrastructure/conversations/paths.js.map +1 -1
  441. package/dist/infrastructure/conversations/restore.js +7 -0
  442. package/dist/infrastructure/conversations/restore.js.map +1 -1
  443. package/dist/infrastructure/conversations/session-bundle.constants.d.ts +5 -0
  444. package/dist/infrastructure/conversations/session-bundle.constants.js +173 -0
  445. package/dist/infrastructure/conversations/session-bundle.constants.js.map +1 -0
  446. package/dist/infrastructure/conversations/session-bundle.d.ts +6 -0
  447. package/dist/infrastructure/conversations/session-bundle.js +98 -0
  448. package/dist/infrastructure/conversations/session-bundle.js.map +1 -0
  449. package/dist/infrastructure/conversations/session-bundle.types.d.ts +1 -0
  450. package/dist/infrastructure/conversations/session-bundle.types.js +2 -0
  451. package/dist/infrastructure/conversations/session-bundle.types.js.map +1 -0
  452. package/dist/infrastructure/conversations.js +4 -2
  453. package/dist/infrastructure/conversations.js.map +1 -1
  454. package/dist/infrastructure/conversations.types.d.ts +1 -1
  455. package/dist/infrastructure/conversations.types.js.map +1 -1
  456. package/dist/infrastructure/custom-reporter.js +32 -24
  457. package/dist/infrastructure/custom-reporter.js.map +1 -1
  458. package/dist/infrastructure/custom-reporter.types.d.ts +2 -0
  459. package/dist/infrastructure/custom-reporter.types.js.map +1 -1
  460. package/dist/infrastructure/git/git.constants.d.ts +1 -1
  461. package/dist/infrastructure/git/git.constants.js +1 -0
  462. package/dist/infrastructure/git/git.constants.js.map +1 -1
  463. package/dist/infrastructure/git/workspace-lease.js +4 -3
  464. package/dist/infrastructure/git/workspace-lease.js.map +1 -1
  465. package/dist/infrastructure/git/workspace.js +7 -6
  466. package/dist/infrastructure/git/workspace.js.map +1 -1
  467. package/dist/infrastructure/git/workspace.types.d.ts +1 -0
  468. package/dist/infrastructure/git/workspace.types.js.map +1 -1
  469. package/dist/infrastructure/host-credentials.constants.d.ts +1 -0
  470. package/dist/infrastructure/host-credentials.constants.js +2 -0
  471. package/dist/infrastructure/host-credentials.constants.js.map +1 -0
  472. package/dist/infrastructure/host-credentials.d.ts +4 -0
  473. package/dist/infrastructure/host-credentials.js +89 -0
  474. package/dist/infrastructure/host-credentials.js.map +1 -0
  475. package/dist/infrastructure/inspection-path.js +4 -3
  476. package/dist/infrastructure/inspection-path.js.map +1 -1
  477. package/dist/infrastructure/journal.constants.js +10 -1
  478. package/dist/infrastructure/journal.constants.js.map +1 -1
  479. package/dist/infrastructure/journal.d.ts +1 -1
  480. package/dist/infrastructure/journal.js +8 -75
  481. package/dist/infrastructure/journal.js.map +1 -1
  482. package/dist/infrastructure/journal.types.d.ts +2 -4
  483. package/dist/infrastructure/journal.types.js.map +1 -1
  484. package/dist/infrastructure/local-transport.js +9 -4
  485. package/dist/infrastructure/local-transport.js.map +1 -1
  486. package/dist/infrastructure/opentelemetry-dispatch.d.ts +3 -3
  487. package/dist/infrastructure/opentelemetry-dispatch.js +5 -4
  488. package/dist/infrastructure/opentelemetry-dispatch.js.map +1 -1
  489. package/dist/infrastructure/opentelemetry-observation.d.ts +5 -0
  490. package/dist/infrastructure/opentelemetry-observation.js +59 -0
  491. package/dist/infrastructure/opentelemetry-observation.js.map +1 -0
  492. package/dist/infrastructure/opentelemetry.js +15 -1
  493. package/dist/infrastructure/opentelemetry.js.map +1 -1
  494. package/dist/infrastructure/opentelemetry.types.d.ts +9 -1
  495. package/dist/infrastructure/opentelemetry.types.js.map +1 -1
  496. package/dist/infrastructure/reporter.d.ts +2 -2
  497. package/dist/infrastructure/reporter.js +5 -1
  498. package/dist/infrastructure/reporter.js.map +1 -1
  499. package/dist/infrastructure/repository-transport.constants.d.ts +1 -0
  500. package/dist/infrastructure/repository-transport.constants.js +2 -0
  501. package/dist/infrastructure/repository-transport.constants.js.map +1 -0
  502. package/dist/infrastructure/repository-transport.d.ts +2 -0
  503. package/dist/infrastructure/repository-transport.js +9 -0
  504. package/dist/infrastructure/repository-transport.js.map +1 -0
  505. package/dist/infrastructure/resource-activity-inspection.js +19 -24
  506. package/dist/infrastructure/resource-activity-inspection.js.map +1 -1
  507. package/dist/infrastructure/resource-activity.constants.d.ts +0 -1
  508. package/dist/infrastructure/resource-activity.constants.js +0 -1
  509. package/dist/infrastructure/resource-activity.constants.js.map +1 -1
  510. package/dist/infrastructure/resource-activity.js +20 -83
  511. package/dist/infrastructure/resource-activity.js.map +1 -1
  512. package/dist/infrastructure/s3-transport.constants.d.ts +2 -0
  513. package/dist/infrastructure/s3-transport.constants.js +3 -0
  514. package/dist/infrastructure/s3-transport.constants.js.map +1 -0
  515. package/dist/infrastructure/s3-transport.js +57 -3
  516. package/dist/infrastructure/s3-transport.js.map +1 -1
  517. package/dist/infrastructure/s3-transport.types.d.ts +1 -0
  518. package/dist/infrastructure/s3-transport.types.js.map +1 -1
  519. package/dist/infrastructure/speculation-store.constants.d.ts +3 -0
  520. package/dist/infrastructure/speculation-store.constants.js +2 -0
  521. package/dist/infrastructure/speculation-store.constants.js.map +1 -0
  522. package/dist/infrastructure/speculation-store.d.ts +4 -0
  523. package/dist/infrastructure/speculation-store.js +73 -0
  524. package/dist/infrastructure/speculation-store.js.map +1 -0
  525. package/dist/infrastructure/speculation-store.types.d.ts +12 -0
  526. package/dist/infrastructure/speculation-store.types.js +2 -0
  527. package/dist/infrastructure/speculation-store.types.js.map +1 -0
  528. package/dist/infrastructure/storage-inventory.constants.js +1 -0
  529. package/dist/infrastructure/storage-inventory.constants.js.map +1 -1
  530. package/dist/infrastructure/storage-inventory.types.d.ts +1 -1
  531. package/dist/infrastructure/storage-inventory.types.js.map +1 -1
  532. package/dist/infrastructure/storage-reservations.types.d.ts +0 -8
  533. package/dist/infrastructure/storage-reservations.types.js.map +1 -1
  534. package/dist/infrastructure/task-queue-bullmq-resources.js +3 -0
  535. package/dist/infrastructure/task-queue-bullmq-resources.js.map +1 -1
  536. package/dist/infrastructure/task-queue-http.js +29 -4
  537. package/dist/infrastructure/task-queue-http.js.map +1 -1
  538. package/dist/infrastructure/task-queue-http.types.d.ts +2 -2
  539. package/dist/infrastructure/task-queue-http.types.js.map +1 -1
  540. package/dist/infrastructure/transport-conversations.js +2 -0
  541. package/dist/infrastructure/transport-conversations.js.map +1 -1
  542. package/dist/infrastructure/transport-journal.d.ts +1 -1
  543. package/dist/infrastructure/transport-journal.js +8 -2
  544. package/dist/infrastructure/transport-journal.js.map +1 -1
  545. package/dist/infrastructure/transport-reservations.d.ts +1 -1
  546. package/dist/infrastructure/transport-reservations.js +14 -8
  547. package/dist/infrastructure/transport-reservations.js.map +1 -1
  548. package/dist/infrastructure/workflow-decision-signature.constants.d.ts +4 -0
  549. package/dist/infrastructure/workflow-decision-signature.constants.js +5 -0
  550. package/dist/infrastructure/workflow-decision-signature.constants.js.map +1 -0
  551. package/dist/infrastructure/workflow-decision-signature.d.ts +4 -0
  552. package/dist/infrastructure/workflow-decision-signature.js +83 -0
  553. package/dist/infrastructure/workflow-decision-signature.js.map +1 -0
  554. package/dist/infrastructure/workflow-decision-signature.types.d.ts +16 -0
  555. package/dist/infrastructure/workflow-decision-signature.types.js +2 -0
  556. package/dist/infrastructure/workflow-decision-signature.types.js.map +1 -0
  557. package/dist/providers/agents.d.ts +7 -2
  558. package/dist/providers/agents.js +4 -1
  559. package/dist/providers/agents.js.map +1 -1
  560. package/dist/providers/antigravity-install.constants.d.ts +2 -0
  561. package/dist/providers/antigravity-install.constants.js +28 -0
  562. package/dist/providers/antigravity-install.constants.js.map +1 -0
  563. package/dist/providers/antigravity-install.d.ts +2 -0
  564. package/dist/providers/antigravity-install.js +29 -0
  565. package/dist/providers/antigravity-install.js.map +1 -0
  566. package/dist/providers/antigravity-install.types.d.ts +4 -0
  567. package/dist/providers/antigravity-install.types.js +2 -0
  568. package/dist/providers/antigravity-install.types.js.map +1 -0
  569. package/dist/providers/container-recovery.d.ts +4 -0
  570. package/dist/providers/container-recovery.js +28 -0
  571. package/dist/providers/container-recovery.js.map +1 -0
  572. package/dist/providers/container.js +8 -0
  573. package/dist/providers/container.js.map +1 -1
  574. package/dist/providers/daytona-network.constants.d.ts +5 -0
  575. package/dist/providers/daytona-network.constants.js +8 -0
  576. package/dist/providers/daytona-network.constants.js.map +1 -0
  577. package/dist/providers/daytona-network.d.ts +4 -0
  578. package/dist/providers/daytona-network.js +33 -0
  579. package/dist/providers/daytona-network.js.map +1 -0
  580. package/dist/providers/daytona.d.ts +1 -0
  581. package/dist/providers/daytona.js +9 -3
  582. package/dist/providers/daytona.js.map +1 -1
  583. package/dist/providers/daytona.types.d.ts +2 -0
  584. package/dist/providers/daytona.types.js.map +1 -1
  585. package/dist/providers/firecracker-command.js +1 -1
  586. package/dist/providers/firecracker-command.js.map +1 -1
  587. package/dist/providers/firecracker-jailer.constants.d.ts +9 -0
  588. package/dist/providers/firecracker-jailer.constants.js +10 -0
  589. package/dist/providers/firecracker-jailer.constants.js.map +1 -0
  590. package/dist/providers/firecracker-jailer.d.ts +4 -0
  591. package/dist/providers/firecracker-jailer.js +171 -0
  592. package/dist/providers/firecracker-jailer.js.map +1 -0
  593. package/dist/providers/firecracker-machine.js +30 -8
  594. package/dist/providers/firecracker-machine.js.map +1 -1
  595. package/dist/providers/firecracker.types.d.ts +16 -0
  596. package/dist/providers/firecracker.types.js.map +1 -1
  597. package/dist/providers/vercel-network.js +1 -1
  598. package/dist/providers/vercel-network.js.map +1 -1
  599. package/dist/providers/vercel.js +6 -3
  600. package/dist/providers/vercel.js.map +1 -1
  601. package/dist/providers/versions.constants.d.ts +3 -1
  602. package/dist/providers/versions.constants.js +3 -1
  603. package/dist/providers/versions.constants.js.map +1 -1
  604. package/package.json +3 -3
  605. package/dist/adapters/agents/gemini-adapter.d.ts +0 -3
  606. package/dist/adapters/agents/gemini-adapter.js +0 -34
  607. package/dist/adapters/agents/gemini-adapter.js.map +0 -1
  608. package/dist/adapters/agents/gemini-diagnostics.d.ts +0 -2
  609. package/dist/adapters/agents/gemini-diagnostics.js +0 -15
  610. package/dist/adapters/agents/gemini-diagnostics.js.map +0 -1
  611. package/dist/adapters/agents/gemini-events.d.ts +0 -2
  612. package/dist/adapters/agents/gemini-events.js +0 -50
  613. package/dist/adapters/agents/gemini-events.js.map +0 -1
  614. package/dist/adapters/agents/gemini-request.js +0 -23
  615. package/dist/adapters/agents/gemini-request.js.map +0 -1
  616. package/dist/adapters/agents/gemini.types.js +0 -2
  617. package/dist/adapters/agents/gemini.types.js.map +0 -1
  618. package/dist/infrastructure/artifact-store.d.ts +0 -3
  619. package/dist/infrastructure/artifact-store.js +0 -110
  620. package/dist/infrastructure/artifact-store.js.map +0 -1
  621. package/dist/infrastructure/artifact-store.types.d.ts +0 -6
  622. package/dist/infrastructure/artifact-store.types.js +0 -2
  623. package/dist/infrastructure/artifact-store.types.js.map +0 -1
  624. package/dist/infrastructure/journal-retention.constants.d.ts +0 -4
  625. package/dist/infrastructure/journal-retention.constants.js +0 -5
  626. package/dist/infrastructure/journal-retention.constants.js.map +0 -1
  627. package/dist/infrastructure/journal-retention.d.ts +0 -2
  628. package/dist/infrastructure/journal-retention.js +0 -51
  629. package/dist/infrastructure/journal-retention.js.map +0 -1
  630. package/dist/infrastructure/storage-mutation-lock.constants.d.ts +0 -5
  631. package/dist/infrastructure/storage-mutation-lock.constants.js +0 -6
  632. package/dist/infrastructure/storage-mutation-lock.constants.js.map +0 -1
  633. package/dist/infrastructure/storage-mutation-lock.d.ts +0 -1
  634. package/dist/infrastructure/storage-mutation-lock.js +0 -21
  635. package/dist/infrastructure/storage-mutation-lock.js.map +0 -1
  636. package/dist/infrastructure/storage-reservations.constants.d.ts +0 -4
  637. package/dist/infrastructure/storage-reservations.constants.js +0 -5
  638. package/dist/infrastructure/storage-reservations.constants.js.map +0 -1
  639. package/dist/infrastructure/storage-reservations.d.ts +0 -2
  640. package/dist/infrastructure/storage-reservations.js +0 -150
  641. package/dist/infrastructure/storage-reservations.js.map +0 -1
  642. package/dist/infrastructure/workflow-checkpoint.d.ts +0 -3
  643. package/dist/infrastructure/workflow-checkpoint.js +0 -84
  644. package/dist/infrastructure/workflow-checkpoint.js.map +0 -1
  645. package/dist/infrastructure/workflow-checkpoint.types.d.ts +0 -6
  646. package/dist/infrastructure/workflow-checkpoint.types.js +0 -2
  647. package/dist/infrastructure/workflow-checkpoint.types.js.map +0 -1
@@ -0,0 +1,42 @@
1
+ import { invariant, OutpostError } from "../domain/errors.js";
2
+ import { addUsage } from "../domain/usage.js";
3
+ export function harnessBudget(limits, parent) {
4
+ let usage = { input: 0, cached: 0, output: 0 };
5
+ let failure;
6
+ return {
7
+ check() {
8
+ parent?.check();
9
+ if (failure)
10
+ throw failure;
11
+ },
12
+ account(result) {
13
+ parent?.account(result);
14
+ try {
15
+ if (result.usage) {
16
+ const tokens = result.usage;
17
+ for (const value of [
18
+ tokens.input,
19
+ tokens.cached,
20
+ tokens.cacheCreated ?? 0,
21
+ tokens.output,
22
+ ])
23
+ invariant(Number.isSafeInteger(value) && value >= 0, "Harness usage must contain nonnegative token counts");
24
+ invariant(tokens.cached + (tokens.cacheCreated ?? 0) <= tokens.input, "Cached tokens must be included in input usage");
25
+ usage = addUsage(usage, tokens);
26
+ }
27
+ if (!limits.usage)
28
+ return;
29
+ if (!result.usage || result.usage.complete === false)
30
+ throw new OutpostError("configuration", "Harness usage limits require a model provider that reports usage completely");
31
+ const exceeded = Object.entries(limits.usage).find(([key, value]) => (usage[key] ?? 0) > value);
32
+ if (exceeded)
33
+ throw new OutpostError("limit", `Harness exceeded its ${exceeded[0]} token budget`, { limit: "usage" });
34
+ }
35
+ catch (error) {
36
+ failure ??= error;
37
+ throw error;
38
+ }
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=harness-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-budget.js","sourceRoot":"","sources":["../../src/application/harness-budget.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,MAAM,UAAU,aAAa,CAC3B,MAAqB,EACrB,MAAsB;IAEtB,IAAI,KAAK,GAAU,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACtD,IAAI,OAAgB,CAAC;IACrB,OAAO;QACL,KAAK;YACH,MAAM,EAAE,KAAK,EAAE,CAAC;YAChB,IAAI,OAAO;gBAAE,MAAM,OAAO,CAAC;QAC7B,CAAC;QACD,OAAO,CAAC,MAAM;YACZ,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACxB,IAAI,CAAC;gBACH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC;oBAC5B,KAAK,MAAM,KAAK,IAAI;wBAClB,MAAM,CAAC,KAAK;wBACZ,MAAM,CAAC,MAAM;wBACb,MAAM,CAAC,YAAY,IAAI,CAAC;wBACxB,MAAM,CAAC,MAAM;qBACd;wBACC,SAAS,CACP,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EACzC,qDAAqD,CACtD,CAAC;oBACJ,SAAS,CACP,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,EAC1D,+CAA+C,CAChD,CAAC;oBACF,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAClC,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,KAAK;oBAAE,OAAO;gBAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,KAAK;oBAClD,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,6EAA6E,CAC9E,CAAC;gBACJ,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAChD,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CACf,CAAC,KAAK,CAAC,GAAuC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAChE,CAAC;gBACF,IAAI,QAAQ;oBACV,MAAM,IAAI,YAAY,CACpB,OAAO,EACP,wBAAwB,QAAQ,CAAC,CAAC,CAAC,eAAe,EAClD,EAAE,KAAK,EAAE,OAAO,EAAE,CACnB,CAAC;YACN,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,KAAK,KAAK,CAAC;gBAClB,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { Usage } from \"../domain/agent.types.ts\";\nimport { invariant, OutpostError } from \"../domain/errors.ts\";\nimport type { HarnessLimits } from \"../domain/harness.types.ts\";\nimport { addUsage } from \"../domain/usage.ts\";\nimport type { HarnessBudget } from \"./harness-budget.types.ts\";\n\nexport function harnessBudget(\n limits: HarnessLimits,\n parent?: HarnessBudget,\n): HarnessBudget {\n let usage: Usage = { input: 0, cached: 0, output: 0 };\n let failure: unknown;\n return {\n check() {\n parent?.check();\n if (failure) throw failure;\n },\n account(result) {\n parent?.account(result);\n try {\n if (result.usage) {\n const tokens = result.usage;\n for (const value of [\n tokens.input,\n tokens.cached,\n tokens.cacheCreated ?? 0,\n tokens.output,\n ])\n invariant(\n Number.isSafeInteger(value) && value >= 0,\n \"Harness usage must contain nonnegative token counts\",\n );\n invariant(\n tokens.cached + (tokens.cacheCreated ?? 0) <= tokens.input,\n \"Cached tokens must be included in input usage\",\n );\n usage = addUsage(usage, tokens);\n }\n if (!limits.usage) return;\n if (!result.usage || result.usage.complete === false)\n throw new OutpostError(\n \"configuration\",\n \"Harness usage limits require a model provider that reports usage completely\",\n );\n const exceeded = Object.entries(limits.usage).find(\n ([key, value]) =>\n (usage[key as Exclude<keyof Usage, \"complete\">] ?? 0) > value,\n );\n if (exceeded)\n throw new OutpostError(\n \"limit\",\n `Harness exceeded its ${exceeded[0]} token budget`,\n { limit: \"usage\" },\n );\n } catch (error) {\n failure ??= error;\n throw error;\n }\n },\n };\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { ModelResult } from "../domain/model.types.ts";
2
+ export interface HarnessBudget {
3
+ check(): void;
4
+ account(result: ModelResult): void;
5
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=harness-budget.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-budget.types.js","sourceRoot":"","sources":["../../src/application/harness-budget.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ModelResult } from \"../domain/model.types.ts\";\n\nexport interface HarnessBudget {\n check(): void;\n account(result: ModelResult): void;\n}\n"]}
@@ -22,6 +22,11 @@ export async function beforeTool(runtime, call, step) {
22
22
  call: current,
23
23
  ...context(runtime, step),
24
24
  });
25
+ runtime.emit({
26
+ kind: "hook",
27
+ phase: "before-tool",
28
+ changed: decision !== undefined,
29
+ });
25
30
  if (decision === undefined)
26
31
  continue;
27
32
  expect(decision !== null && typeof decision === "object", "before-tool hooks may return { deny } or { input }");
@@ -42,6 +47,11 @@ export async function afterTool(runtime, call, outcome, step, normalize) {
42
47
  result: current,
43
48
  ...context(runtime, step),
44
49
  });
50
+ runtime.emit({
51
+ kind: "hook",
52
+ phase: "after-tool",
53
+ changed: decision !== undefined,
54
+ });
45
55
  if (decision === undefined)
46
56
  continue;
47
57
  expect(decision !== null && typeof decision === "object" && "result" in decision, "after-tool hooks may only return { result }");
@@ -52,6 +62,11 @@ export async function afterTool(runtime, call, outcome, step, normalize) {
52
62
  export async function stopRequest(runtime, text, step) {
53
63
  for (const hook of hooks(runtime, "stop")) {
54
64
  const decision = await hook.run({ text, ...context(runtime, step) });
65
+ runtime.emit({
66
+ kind: "hook",
67
+ phase: "stop",
68
+ changed: decision !== undefined,
69
+ });
55
70
  if (decision === undefined)
56
71
  continue;
57
72
  expect(decision !== null &&
@@ -64,11 +79,19 @@ export async function stopRequest(runtime, text, step) {
64
79
  }
65
80
  async function each(runtime, phase, event, step) {
66
81
  const decisions = [];
67
- for (const hook of hooks(runtime, phase))
68
- decisions.push(await hook.run({
82
+ for (const hook of hooks(runtime, phase)) {
83
+ const before = snapshot(event);
84
+ const decision = await hook.run({
69
85
  ...event,
70
86
  ...context(runtime, step),
71
- }));
87
+ });
88
+ runtime.emit({
89
+ kind: "hook",
90
+ phase,
91
+ changed: decision !== undefined || before !== snapshot(event),
92
+ });
93
+ decisions.push(decision);
94
+ }
72
95
  return decisions;
73
96
  }
74
97
  function hooks(runtime, phase) {
@@ -87,4 +110,12 @@ function expect(condition, message) {
87
110
  if (!condition)
88
111
  throw new OutpostError("configuration", message);
89
112
  }
113
+ function snapshot(value) {
114
+ try {
115
+ return JSON.stringify(value);
116
+ }
117
+ catch {
118
+ return undefined;
119
+ }
120
+ }
90
121
  //# sourceMappingURL=harness-hooks.js.map
@@ -1 +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"]}
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 runtime.emit({\n kind: \"hook\",\n phase: \"before-tool\",\n changed: decision !== undefined,\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 runtime.emit({\n kind: \"hook\",\n phase: \"after-tool\",\n changed: decision !== undefined,\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 runtime.emit({\n kind: \"hook\",\n phase: \"stop\",\n changed: decision !== undefined,\n });\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 const before = snapshot(event);\n const decision = await hook.run({\n ...event,\n ...context(runtime, step),\n } as HarnessHookInput<Phase>);\n runtime.emit({\n kind: \"hook\",\n phase,\n changed: decision !== undefined || before !== snapshot(event),\n });\n decisions.push(decision);\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\nfunction snapshot(value: unknown): string | undefined {\n try {\n return JSON.stringify(value);\n } catch {\n return undefined;\n }\n}\n"]}
@@ -1,6 +1,5 @@
1
1
  import { OutpostError } from "../domain/errors.js";
2
2
  import { loadedSkills } from "../domain/skill.js";
3
- import { addUsage } from "../domain/usage.js";
4
3
  import { compact } from "./harness-context.js";
5
4
  import { afterModel, beforeModel, sessionInstructions, stopRequest, } from "./harness-hooks.js";
6
5
  import { executeToolCalls } from "./tool-execution.js";
@@ -56,15 +55,18 @@ export async function harnessLoop(runtime, prompt, history) {
56
55
  role: "user",
57
56
  content: [{ type: "text", text: prompt }],
58
57
  });
59
- let usage = { input: 0, cached: 0, output: 0 };
60
58
  let toolCalls = 0;
59
+ const announcedSkills = new Set();
61
60
  for (let step = 1;; step++) {
62
61
  runtime.signal.throwIfAborted();
63
62
  if (step > harness.limits.maxSteps)
64
63
  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`);
64
+ runtime.budget.check();
65
+ const newlyLoaded = [...loadedSkills(history.messages)].filter((name) => !announcedSkills.has(name));
66
+ for (const name of newlyLoaded)
67
+ announcedSkills.add(name);
68
+ if (newlyLoaded.length)
69
+ runtime.emit({ kind: "skills-loaded", names: newlyLoaded });
68
70
  runtime.emit({ kind: "step", index: step });
69
71
  await compact(runtime, history, step);
70
72
  await beforeModel(runtime, history.messages, step);
@@ -75,21 +77,21 @@ export async function harnessLoop(runtime, prompt, history) {
75
77
  ...(tools.length ? { tools } : {}),
76
78
  ...(harness.cache ? { cache: true } : {}),
77
79
  });
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
80
  await afterModel(runtime, result, step);
83
81
  const content = result.content ?? [
84
82
  { type: "text", text: result.text },
85
83
  ];
86
- for (const block of content)
84
+ for (const block of content) {
87
85
  if (block.type === "text" && block.text)
88
86
  runtime.emit({ kind: "text", text: block.text });
87
+ if (block.type === "reasoning" && block.text)
88
+ runtime.emit({ kind: "reasoning", text: block.text });
89
+ }
89
90
  const state = { history, step, toolCalls };
90
91
  const reason = result.stopReason ?? inferredStop(content);
91
92
  const answer = await stopHandlers[reason](runtime, state, result, content);
92
93
  toolCalls = state.toolCalls;
94
+ runtime.budget.check();
93
95
  if (answer !== undefined)
94
96
  return answer;
95
97
  }
@@ -101,6 +103,10 @@ async function instructions(runtime) {
101
103
  model: runtime.agent.model,
102
104
  })));
103
105
  runtime.signal.throwIfAborted();
106
+ runtime.emit({
107
+ kind: "instructions-loaded",
108
+ count: texts.filter((text) => text.trim()).length,
109
+ });
104
110
  return texts.filter((text) => text.trim()).join("\n\n");
105
111
  }
106
112
  function inferredStop(content) {
@@ -108,25 +114,47 @@ function inferredStop(content) {
108
114
  ? "tool-calls"
109
115
  : "end";
110
116
  }
111
- function exceededUsage(usage, limits) {
112
- return Object.entries(limits ?? {}).find(([key, value]) => (usage[key] ?? 0) > (value ?? Infinity))?.[0];
113
- }
114
117
  function limit(name, message) {
115
118
  return new OutpostError("limit", message, { limit: name });
116
119
  }
117
120
  async function requestModel(runtime, request) {
118
121
  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;
122
+ if (runtime.verbose)
123
+ runtime.emit({ kind: "model-request", request });
124
+ try {
125
+ const result = await receive();
126
+ if (runtime.verbose)
127
+ runtime.emit({ kind: "model-response", response: result });
128
+ return result;
129
+ }
130
+ catch (error) {
131
+ runtime.emit({
132
+ kind: "model-error",
133
+ message: error instanceof Error ? error.message : String(error),
134
+ });
135
+ throw error;
136
+ }
137
+ async function receive() {
138
+ if (!provider.stream)
139
+ return provider.request(request);
140
+ let result;
141
+ for await (const event of provider.stream(request)) {
142
+ if (event.type === "text-delta")
143
+ runtime.emit({ kind: "text-delta", text: event.text });
144
+ if (event.type === "reasoning")
145
+ runtime.emit({ kind: "reasoning", text: event.text });
146
+ if (event.type === "retry")
147
+ runtime.emit({
148
+ kind: "model-retry",
149
+ attempt: event.attempt,
150
+ ...(event.message ? { message: event.message } : {}),
151
+ });
152
+ if (event.type === "result")
153
+ result = event.result;
154
+ }
155
+ if (!result)
156
+ throw new OutpostError("response", "Model stream ended without a result");
157
+ return result;
127
158
  }
128
- if (!result)
129
- throw new OutpostError("response", "Model stream ended without a result");
130
- return result;
131
159
  }
132
160
  //# sourceMappingURL=harness-loop.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"harness-loop.js","sourceRoot":"","sources":["../../src/application/harness-loop.ts"],"names":[],"mappings":"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","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"]}
1
+ {"version":3,"file":"harness-loop.js","sourceRoot":"","sources":["../../src/application/harness-loop.ts"],"names":[],"mappings":"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","sourcesContent":["import { 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 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 toolCalls = 0;\n const announcedSkills = new Set<string>();\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 runtime.budget.check();\n const newlyLoaded = [...loadedSkills(history.messages)].filter(\n (name) => !announcedSkills.has(name),\n );\n for (const name of newlyLoaded) announcedSkills.add(name);\n if (newlyLoaded.length)\n runtime.emit({ kind: \"skills-loaded\", names: newlyLoaded });\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 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 if (block.type === \"reasoning\" && block.text)\n runtime.emit({ kind: \"reasoning\", text: block.text });\n }\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 runtime.budget.check();\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 runtime.emit({\n kind: \"instructions-loaded\",\n count: texts.filter((text) => text.trim()).length,\n });\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 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 (runtime.verbose) runtime.emit({ kind: \"model-request\", request });\n try {\n const result = await receive();\n if (runtime.verbose)\n runtime.emit({ kind: \"model-response\", response: result });\n return result;\n } catch (error) {\n runtime.emit({\n kind: \"model-error\",\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n async function receive(): Promise<ModelResult> {\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 === \"reasoning\")\n runtime.emit({ kind: \"reasoning\", text: event.text });\n if (event.type === \"retry\")\n runtime.emit({\n kind: \"model-retry\",\n attempt: event.attempt,\n ...(event.message ? { message: event.message } : {}),\n });\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}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ModelProvider } from "../domain/model.types.ts";
2
+ import type { HarnessModelScope } from "./harness-model-provider.types.ts";
3
+ export declare function harnessModelProvider(scope: HarnessModelScope): ModelProvider;
@@ -0,0 +1,49 @@
1
+ import { invariant } from "../domain/errors.js";
2
+ export function harnessModelProvider(scope) {
3
+ const { agent, signal, budget, track } = scope;
4
+ const provider = agent.harness.modelProvider;
5
+ const scoped = (request) => {
6
+ signal.throwIfAborted();
7
+ budget.check();
8
+ const { reasoning, maxOutputTokens } = agent.model;
9
+ return {
10
+ ...(reasoning === undefined ? {} : { reasoning }),
11
+ ...(maxOutputTokens === undefined ? {} : { maxOutputTokens }),
12
+ ...request,
13
+ signal,
14
+ };
15
+ };
16
+ const account = (result) => {
17
+ signal.throwIfAborted();
18
+ invariant(result && typeof result.text === "string", "Model provider must return text");
19
+ scope.account(result);
20
+ budget.account(result);
21
+ return result;
22
+ };
23
+ async function* stream(request) {
24
+ let finish;
25
+ track(new Promise((resolve) => (finish = resolve)));
26
+ try {
27
+ let received = false;
28
+ for await (const event of provider.stream(scoped(request))) {
29
+ signal.throwIfAborted();
30
+ if (event.type === "result") {
31
+ invariant(!received, "Model stream returned more than one result");
32
+ received = true;
33
+ yield { type: "result", result: account(event.result) };
34
+ continue;
35
+ }
36
+ yield event;
37
+ }
38
+ }
39
+ finally {
40
+ finish();
41
+ }
42
+ }
43
+ return {
44
+ name: provider.name,
45
+ ...(provider.stream ? { stream } : {}),
46
+ request: (request) => track(Promise.resolve().then(async () => account(await provider.request(scoped(request))))),
47
+ };
48
+ }
49
+ //# sourceMappingURL=harness-model-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-model-provider.js","sourceRoot":"","sources":["../../src/application/harness-model-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAShD,MAAM,UAAU,oBAAoB,CAAC,KAAwB;IAC3D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC/C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC;IAC7C,MAAM,MAAM,GAAG,CAAC,OAAqB,EAAgB,EAAE;QACrD,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC;QACnD,OAAO;YACL,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;YACjD,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;YAC7D,GAAG,OAAO;YACV,MAAM;SACP,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,MAAmB,EAAe,EAAE;QACnD,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,SAAS,CACP,MAAM,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EACzC,iCAAiC,CAClC,CAAC;QACF,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACtB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IACF,KAAK,SAAS,CAAC,CAAC,MAAM,CACpB,OAAqB;QAErB,IAAI,MAAmB,CAAC;QACxB,KAAK,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBAC5D,MAAM,CAAC,cAAc,EAAE,CAAC;gBACxB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC5B,SAAS,CAAC,CAAC,QAAQ,EAAE,4CAA4C,CAAC,CAAC;oBACnE,QAAQ,GAAG,IAAI,CAAC;oBAChB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;oBACxD,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CACnB,KAAK,CACH,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAChC,OAAO,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CACjD,CACF;KACJ,CAAC;AACJ,CAAC","sourcesContent":["import { invariant } from \"../domain/errors.ts\";\nimport type {\n ModelProvider,\n ModelRequest,\n ModelResult,\n ModelStreamEvent,\n} from \"../domain/model.types.ts\";\nimport type { HarnessModelScope } from \"./harness-model-provider.types.ts\";\n\nexport function harnessModelProvider(scope: HarnessModelScope): ModelProvider {\n const { agent, signal, budget, track } = scope;\n const provider = agent.harness.modelProvider;\n const scoped = (request: ModelRequest): ModelRequest => {\n signal.throwIfAborted();\n budget.check();\n const { reasoning, maxOutputTokens } = agent.model;\n return {\n ...(reasoning === undefined ? {} : { reasoning }),\n ...(maxOutputTokens === undefined ? {} : { maxOutputTokens }),\n ...request,\n signal,\n };\n };\n const account = (result: ModelResult): ModelResult => {\n signal.throwIfAborted();\n invariant(\n result && typeof result.text === \"string\",\n \"Model provider must return text\",\n );\n scope.account(result);\n budget.account(result);\n return result;\n };\n async function* stream(\n request: ModelRequest,\n ): AsyncGenerator<ModelStreamEvent> {\n let finish!: () => void;\n track(new Promise<void>((resolve) => (finish = resolve)));\n try {\n let received = false;\n for await (const event of provider.stream!(scoped(request))) {\n signal.throwIfAborted();\n if (event.type === \"result\") {\n invariant(!received, \"Model stream returned more than one result\");\n received = true;\n yield { type: \"result\", result: account(event.result) };\n continue;\n }\n yield event;\n }\n } finally {\n finish();\n }\n }\n return {\n name: provider.name,\n ...(provider.stream ? { stream } : {}),\n request: (request) =>\n track(\n Promise.resolve().then(async () =>\n account(await provider.request(scoped(request))),\n ),\n ),\n };\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { CustomAgent } from "../domain/agent.types.ts";
2
+ import type { ModelResult } from "../domain/model.types.ts";
3
+ import type { HarnessBudget } from "./harness-budget.types.ts";
4
+ export interface HarnessModelScope {
5
+ readonly agent: CustomAgent;
6
+ readonly signal: AbortSignal;
7
+ readonly budget: HarnessBudget;
8
+ track<T>(operation: Promise<T>): Promise<T>;
9
+ account(result: ModelResult, subagentId?: string): void;
10
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=harness-model-provider.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-model-provider.types.js","sourceRoot":"","sources":["../../src/application/harness-model-provider.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CustomAgent } from \"../domain/agent.types.ts\";\nimport type { ModelResult } from \"../domain/model.types.ts\";\nimport type { HarnessBudget } from \"./harness-budget.types.ts\";\n\nexport interface HarnessModelScope {\n readonly agent: CustomAgent;\n readonly signal: AbortSignal;\n readonly budget: HarnessBudget;\n track<T>(operation: Promise<T>): Promise<T>;\n account(result: ModelResult, subagentId?: string): void;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { HarnessSubagent } from "../domain/subagent.types.ts";
2
+ import type { HarnessToolContext } from "../domain/tool.types.ts";
3
+ import type { HarnessRuntime } from "./harness.types.ts";
4
+ export declare function runSubagent(runtime: HarnessRuntime, tool: HarnessSubagent, input: unknown, context: HarnessToolContext): Promise<string>;
@@ -0,0 +1,110 @@
1
+ import { join } from "node:path";
2
+ import { randomUUID } from "node:crypto";
3
+ import { OutpostError, recordRecovery } from "../domain/errors.js";
4
+ import { MAX_DELEGATION_DEPTH } from "../domain/subagent.constants.js";
5
+ import { openTranscript } from "../infrastructure/conversations/harness-transcript.js";
6
+ import { storageFor } from "./agent-storage.js";
7
+ import { harnessBudget } from "./harness-budget.js";
8
+ import { harnessHistory } from "./harness-history.js";
9
+ import { harnessLoop } from "./harness-loop.js";
10
+ import { harnessModelProvider } from "./harness-model-provider.js";
11
+ export async function runSubagent(runtime, tool, input, context) {
12
+ const validated = await tool.validate(input);
13
+ if ("issues" in validated)
14
+ throw new OutpostError("configuration", validated.issues);
15
+ if (runtime.depth >= runtime.maxDepth)
16
+ throw new OutpostError("limit", "Harness reached its delegation depth limit", { limit: "maxDelegationDepth" });
17
+ runtime.budget.check();
18
+ const agent = tool.subagent;
19
+ const budget = harnessBudget(agent.harness.limits, runtime.budget);
20
+ const id = randomUUID();
21
+ const depth = runtime.depth + 1;
22
+ const store = storageFor(agent);
23
+ let transcript;
24
+ let failure;
25
+ let text = "";
26
+ const lifecycle = (status) => runtime.emit({
27
+ kind: "subagent",
28
+ id,
29
+ callId: context.callId,
30
+ name: tool.name,
31
+ status,
32
+ ...(transcript ? { conversation: transcript.id } : {}),
33
+ });
34
+ try {
35
+ transcript = store
36
+ ? await openTranscript({
37
+ repository: runtime.repository,
38
+ store,
39
+ model: agent.model.name,
40
+ ...(runtime.conversation
41
+ ? { parentConversation: runtime.conversation }
42
+ : {}),
43
+ parentCallId: context.callId,
44
+ })
45
+ : undefined;
46
+ lifecycle("started");
47
+ text = await harnessLoop({
48
+ ...runtime,
49
+ agent,
50
+ budget,
51
+ depth,
52
+ maxDepth: Math.min(runtime.maxDepth, depth +
53
+ (agent.harness.limits.maxDelegationDepth ?? MAX_DELEGATION_DEPTH)),
54
+ conversation: transcript?.id,
55
+ tools: agent.harness.tools,
56
+ permissions: [
57
+ ...runtime.permissions,
58
+ ...(agent.harness.permissions ? [agent.harness.permissions] : []),
59
+ ],
60
+ sandbox: context.sandbox,
61
+ signal: context.signal,
62
+ modelProvider: harnessModelProvider({
63
+ agent,
64
+ signal: context.signal,
65
+ budget,
66
+ ...runtime.modelScope,
67
+ account: (result) => runtime.modelScope.account(result, id),
68
+ }),
69
+ emit: (event) => {
70
+ context.signal.throwIfAborted();
71
+ runtime.emit({ ...event, subagentId: event.subagentId ?? id });
72
+ },
73
+ }, validated.value.prompt, harnessHistory(transcript));
74
+ context.signal.throwIfAborted();
75
+ }
76
+ catch (error) {
77
+ failure = error;
78
+ }
79
+ try {
80
+ if (transcript && store)
81
+ await store.capture(transcript.id, {
82
+ repository: runtime.repository,
83
+ sandbox: context.sandbox,
84
+ staging: join(runtime.repository, ".outpost", "conversations", "harness"),
85
+ });
86
+ }
87
+ catch (error) {
88
+ if (failure)
89
+ recordRecovery(failure, {
90
+ subagentCaptureError: error,
91
+ conversation: transcript?.id,
92
+ });
93
+ failure ??= error;
94
+ }
95
+ finally {
96
+ await transcript?.close();
97
+ }
98
+ if (failure) {
99
+ if (!runtime.signal.aborted)
100
+ lifecycle("failed");
101
+ throw failure;
102
+ }
103
+ context.signal.throwIfAborted();
104
+ lifecycle("finished");
105
+ return JSON.stringify({
106
+ text,
107
+ ...(transcript ? { conversation: transcript.id } : {}),
108
+ });
109
+ }
110
+ //# sourceMappingURL=harness-subagent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-subagent.js","sourceRoot":"","sources":["../../src/application/harness-subagent.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { OutpostError, recordRecovery } from \"../domain/errors.ts\";\nimport { MAX_DELEGATION_DEPTH } from \"../domain/subagent.constants.ts\";\nimport type { HarnessSubagent } from \"../domain/subagent.types.ts\";\nimport type { HarnessToolContext } from \"../domain/tool.types.ts\";\nimport { openTranscript } from \"../infrastructure/conversations/harness-transcript.ts\";\nimport type { TranscriptHandle } from \"../infrastructure/conversations/harness-transcript.types.ts\";\nimport { storageFor } from \"./agent-storage.ts\";\nimport { harnessBudget } from \"./harness-budget.ts\";\nimport { harnessHistory } from \"./harness-history.ts\";\nimport { harnessLoop } from \"./harness-loop.ts\";\nimport { harnessModelProvider } from \"./harness-model-provider.ts\";\nimport type { HarnessRuntime } from \"./harness.types.ts\";\n\nexport async function runSubagent(\n runtime: HarnessRuntime,\n tool: HarnessSubagent,\n input: unknown,\n context: HarnessToolContext,\n): Promise<string> {\n const validated = await tool.validate(input);\n if (\"issues\" in validated)\n throw new OutpostError(\"configuration\", validated.issues);\n if (runtime.depth >= runtime.maxDepth)\n throw new OutpostError(\n \"limit\",\n \"Harness reached its delegation depth limit\",\n { limit: \"maxDelegationDepth\" },\n );\n runtime.budget.check();\n const agent = tool.subagent;\n const budget = harnessBudget(agent.harness.limits, runtime.budget);\n const id = randomUUID();\n const depth = runtime.depth + 1;\n const store = storageFor(agent);\n let transcript: TranscriptHandle | undefined;\n let failure: unknown;\n let text = \"\";\n const lifecycle = (status: \"started\" | \"finished\" | \"failed\") =>\n runtime.emit({\n kind: \"subagent\",\n id,\n callId: context.callId,\n name: tool.name,\n status,\n ...(transcript ? { conversation: transcript.id } : {}),\n });\n try {\n transcript = store\n ? await openTranscript({\n repository: runtime.repository,\n store,\n model: agent.model.name,\n ...(runtime.conversation\n ? { parentConversation: runtime.conversation }\n : {}),\n parentCallId: context.callId,\n })\n : undefined;\n lifecycle(\"started\");\n text = await harnessLoop(\n {\n ...runtime,\n agent,\n budget,\n depth,\n maxDepth: Math.min(\n runtime.maxDepth,\n depth +\n (agent.harness.limits.maxDelegationDepth ?? MAX_DELEGATION_DEPTH),\n ),\n conversation: transcript?.id,\n tools: agent.harness.tools,\n permissions: [\n ...runtime.permissions,\n ...(agent.harness.permissions ? [agent.harness.permissions] : []),\n ],\n sandbox: context.sandbox,\n signal: context.signal,\n modelProvider: harnessModelProvider({\n agent,\n signal: context.signal,\n budget,\n ...runtime.modelScope,\n account: (result) => runtime.modelScope.account(result, id),\n }),\n emit: (event) => {\n context.signal.throwIfAborted();\n runtime.emit({ ...event, subagentId: event.subagentId ?? id });\n },\n },\n validated.value.prompt,\n harnessHistory(transcript),\n );\n context.signal.throwIfAborted();\n } catch (error) {\n failure = error;\n }\n try {\n if (transcript && store)\n await store.capture(transcript.id, {\n repository: runtime.repository,\n sandbox: context.sandbox,\n staging: join(\n runtime.repository,\n \".outpost\",\n \"conversations\",\n \"harness\",\n ),\n });\n } catch (error) {\n if (failure)\n recordRecovery(failure, {\n subagentCaptureError: error,\n conversation: transcript?.id,\n });\n failure ??= error;\n } finally {\n await transcript?.close();\n }\n if (failure) {\n if (!runtime.signal.aborted) lifecycle(\"failed\");\n throw failure;\n }\n context.signal.throwIfAborted();\n lifecycle(\"finished\");\n return JSON.stringify({\n text,\n ...(transcript ? { conversation: transcript.id } : {}),\n });\n}\n"]}
@@ -1,9 +1,20 @@
1
+ import type { HarnessBudget } from "./harness-budget.types.ts";
2
+ import type { HarnessPermissions } from "../domain/permissions.types.ts";
3
+ import type { HarnessModelScope } from "./harness-model-provider.types.ts";
1
4
  import type { AgentEvent, CustomAgent } from "../domain/agent.types.ts";
2
5
  import type { ModelContentBlock, ModelMessage, ModelProvider, ModelResult, ModelToolCallBlock } from "../domain/model.types.ts";
3
6
  import type { SandboxLease } from "../domain/sandbox.types.ts";
4
7
  import type { HarnessTool } from "../domain/tool.types.ts";
5
8
  import type { DispatchOptions, TurnContext } from "./execution.types.ts";
6
9
  export interface HarnessRuntime {
10
+ readonly verbose?: boolean;
11
+ readonly repository: string;
12
+ readonly conversation?: string | undefined;
13
+ readonly budget: HarnessBudget;
14
+ readonly permissions: readonly HarnessPermissions[];
15
+ readonly depth: number;
16
+ readonly maxDepth: number;
17
+ readonly modelScope: Pick<HarnessModelScope, "track" | "account">;
7
18
  readonly agent: CustomAgent;
8
19
  readonly tools: readonly HarnessTool[];
9
20
  readonly modelProvider: ModelProvider;