@elie-laloum/outpost 4.2.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +5 -3
  3. package/dist/{cli/init-authentication.constants.js → adapters/agents/authentication.constants.js} +1 -1
  4. package/dist/adapters/agents/authentication.constants.js.map +1 -0
  5. package/dist/adapters/agents/authentication.d.ts +2 -0
  6. package/dist/adapters/agents/authentication.js +52 -0
  7. package/dist/adapters/agents/authentication.js.map +1 -0
  8. package/dist/adapters/agents/claude-adapter.d.ts +2 -2
  9. package/dist/adapters/agents/claude-adapter.js +30 -2
  10. package/dist/adapters/agents/claude-adapter.js.map +1 -1
  11. package/dist/adapters/agents/claude-request.d.ts +2 -2
  12. package/dist/adapters/agents/claude-request.js +3 -3
  13. package/dist/adapters/agents/claude-request.js.map +1 -1
  14. package/dist/adapters/agents/codex-adapter.d.ts +2 -2
  15. package/dist/adapters/agents/codex-adapter.js +17 -1
  16. package/dist/adapters/agents/codex-adapter.js.map +1 -1
  17. package/dist/adapters/agents/codex-provider.d.ts +2 -2
  18. package/dist/adapters/agents/codex-provider.js +1 -1
  19. package/dist/adapters/agents/codex-provider.js.map +1 -1
  20. package/dist/adapters/agents/codex-request.d.ts +2 -2
  21. package/dist/adapters/agents/codex-request.js +3 -3
  22. package/dist/adapters/agents/codex-request.js.map +1 -1
  23. package/dist/adapters/agents/gemini-adapter.d.ts +2 -2
  24. package/dist/adapters/agents/gemini-adapter.js +20 -1
  25. package/dist/adapters/agents/gemini-adapter.js.map +1 -1
  26. package/dist/adapters/agents/gemini-request.d.ts +2 -1
  27. package/dist/adapters/agents/gemini-request.js +1 -1
  28. package/dist/adapters/agents/gemini-request.js.map +1 -1
  29. package/dist/adapters/agents/gemini.types.d.ts +2 -1
  30. package/dist/adapters/agents/gemini.types.js.map +1 -1
  31. package/dist/adapters/agents/model-support.constants.d.ts +6 -0
  32. package/dist/adapters/agents/model-support.constants.js +18 -0
  33. package/dist/adapters/agents/model-support.constants.js.map +1 -0
  34. package/dist/adapters/agents/model-support.d.ts +4 -0
  35. package/dist/adapters/agents/model-support.js +11 -0
  36. package/dist/adapters/agents/model-support.js.map +1 -0
  37. package/dist/adapters/agents/settings.types.d.ts +11 -3
  38. package/dist/adapters/agents/settings.types.js.map +1 -1
  39. package/dist/adapters/models/anthropic-model-provider.constants.d.ts +3 -0
  40. package/dist/adapters/models/anthropic-model-provider.constants.js +17 -0
  41. package/dist/adapters/models/anthropic-model-provider.constants.js.map +1 -0
  42. package/dist/adapters/models/anthropic-model-provider.d.ts +3 -0
  43. package/dist/adapters/models/anthropic-model-provider.js +31 -0
  44. package/dist/adapters/models/anthropic-model-provider.js.map +1 -0
  45. package/dist/adapters/models/anthropic-model-provider.types.d.ts +7 -0
  46. package/dist/adapters/models/anthropic-model-provider.types.js +2 -0
  47. package/dist/adapters/models/anthropic-model-provider.types.js.map +1 -0
  48. package/dist/adapters/models/anthropic-request.d.ts +4 -0
  49. package/dist/adapters/models/anthropic-request.js +81 -0
  50. package/dist/adapters/models/anthropic-request.js.map +1 -0
  51. package/dist/adapters/models/anthropic-response.d.ts +3 -0
  52. package/dist/adapters/models/anthropic-response.js +55 -0
  53. package/dist/adapters/models/anthropic-response.js.map +1 -0
  54. package/dist/adapters/models/anthropic-stream.d.ts +2 -0
  55. package/dist/adapters/models/anthropic-stream.js +96 -0
  56. package/dist/adapters/models/anthropic-stream.js.map +1 -0
  57. package/dist/adapters/models/http-provider.d.ts +3 -0
  58. package/dist/adapters/models/http-provider.js +113 -0
  59. package/dist/adapters/models/http-provider.js.map +1 -0
  60. package/dist/adapters/models/{openai-http.js → model-http.js} +1 -1
  61. package/dist/adapters/models/model-http.js.map +1 -0
  62. package/dist/adapters/models/model-protocol.types.d.ts +41 -0
  63. package/dist/adapters/models/model-protocol.types.js +2 -0
  64. package/dist/adapters/models/model-protocol.types.js.map +1 -0
  65. package/dist/adapters/models/model-request.d.ts +2 -0
  66. package/dist/adapters/models/model-request.js +18 -0
  67. package/dist/adapters/models/model-request.js.map +1 -0
  68. package/dist/adapters/models/model-response.d.ts +7 -0
  69. package/dist/adapters/models/model-response.js +41 -0
  70. package/dist/adapters/models/model-response.js.map +1 -0
  71. package/dist/adapters/models/{openai-compatible.constants.js → model.constants.js} +6 -1
  72. package/dist/adapters/models/model.constants.js.map +1 -0
  73. package/dist/adapters/models/openai-chat-stream.d.ts +2 -0
  74. package/dist/adapters/models/openai-chat-stream.js +66 -0
  75. package/dist/adapters/models/openai-chat-stream.js.map +1 -0
  76. package/dist/adapters/models/openai-chat.d.ts +4 -0
  77. package/dist/adapters/models/openai-chat.js +108 -0
  78. package/dist/adapters/models/openai-chat.js.map +1 -0
  79. package/dist/adapters/models/openai-model-provider.d.ts +3 -0
  80. package/dist/adapters/models/openai-model-provider.js +13 -0
  81. package/dist/adapters/models/openai-model-provider.js.map +1 -0
  82. package/dist/adapters/models/openai-model-provider.types.d.ts +4 -0
  83. package/dist/adapters/models/openai-model-provider.types.js +2 -0
  84. package/dist/adapters/models/openai-model-provider.types.js.map +1 -0
  85. package/dist/adapters/models/openai-protocols.d.ts +2 -0
  86. package/dist/adapters/models/openai-protocols.js +22 -0
  87. package/dist/adapters/models/openai-protocols.js.map +1 -0
  88. package/dist/adapters/models/openai-responses-stream.d.ts +2 -0
  89. package/dist/adapters/models/openai-responses-stream.js +35 -0
  90. package/dist/adapters/models/openai-responses-stream.js.map +1 -0
  91. package/dist/adapters/models/openai-responses.d.ts +4 -0
  92. package/dist/adapters/models/openai-responses.js +107 -0
  93. package/dist/adapters/models/openai-responses.js.map +1 -0
  94. package/dist/adapters/models/openai-usage.d.ts +3 -0
  95. package/dist/adapters/models/openai-usage.js +20 -0
  96. package/dist/adapters/models/openai-usage.js.map +1 -0
  97. package/dist/adapters/models/stop-reasons.constants.d.ts +4 -0
  98. package/dist/adapters/models/stop-reasons.constants.js +19 -0
  99. package/dist/adapters/models/stop-reasons.constants.js.map +1 -0
  100. package/dist/adapters/models/stream-events.d.ts +3 -0
  101. package/dist/adapters/models/stream-events.js +22 -0
  102. package/dist/adapters/models/stream-events.js.map +1 -0
  103. package/dist/adapters/tools/edit-tools.d.ts +2 -0
  104. package/dist/adapters/tools/edit-tools.js +84 -0
  105. package/dist/adapters/tools/edit-tools.js.map +1 -0
  106. package/dist/adapters/tools/file-tools.d.ts +2 -0
  107. package/dist/adapters/tools/file-tools.js +97 -0
  108. package/dist/adapters/tools/file-tools.js.map +1 -0
  109. package/dist/adapters/tools/git-tools.d.ts +2 -0
  110. package/dist/adapters/tools/git-tools.js +54 -0
  111. package/dist/adapters/tools/git-tools.js.map +1 -0
  112. package/dist/adapters/tools/sandbox-files.d.ts +10 -0
  113. package/dist/adapters/tools/sandbox-files.js +60 -0
  114. package/dist/adapters/tools/sandbox-files.js.map +1 -0
  115. package/dist/adapters/tools/search-tools.d.ts +2 -0
  116. package/dist/adapters/tools/search-tools.js +65 -0
  117. package/dist/adapters/tools/search-tools.js.map +1 -0
  118. package/dist/adapters/tools/shell-tools.d.ts +3 -0
  119. package/dist/adapters/tools/shell-tools.js +38 -0
  120. package/dist/adapters/tools/shell-tools.js.map +1 -0
  121. package/dist/adapters/tools/tools.constants.d.ts +11 -0
  122. package/dist/adapters/tools/tools.constants.js +17 -0
  123. package/dist/adapters/tools/tools.constants.js.map +1 -0
  124. package/dist/adapters/tools/tools.types.d.ts +41 -0
  125. package/dist/adapters/tools/tools.types.js +2 -0
  126. package/dist/adapters/tools/tools.types.js.map +1 -0
  127. package/dist/application/activity-watchdog.js +15 -2
  128. package/dist/application/activity-watchdog.js.map +1 -1
  129. package/dist/application/agent-bootstrap.d.ts +2 -2
  130. package/dist/application/agent-bootstrap.js +2 -0
  131. package/dist/application/agent-bootstrap.js.map +1 -1
  132. package/dist/application/agent-storage.d.ts +3 -2
  133. package/dist/application/agent-storage.js +9 -2
  134. package/dist/application/agent-storage.js.map +1 -1
  135. package/dist/application/agent-turn.d.ts +3 -3
  136. package/dist/application/agent-turn.js +7 -1
  137. package/dist/application/agent-turn.js.map +1 -1
  138. package/dist/application/attach.js +1 -0
  139. package/dist/application/attach.js.map +1 -1
  140. package/dist/application/custom-turn.d.ts +5 -0
  141. package/dist/application/custom-turn.js +190 -0
  142. package/dist/application/custom-turn.js.map +1 -0
  143. package/dist/application/dispatch-observation.d.ts +3 -0
  144. package/dist/application/dispatch-observation.js +51 -0
  145. package/dist/application/dispatch-observation.js.map +1 -0
  146. package/dist/application/dispatch-observation.types.d.ts +5 -0
  147. package/dist/application/dispatch-observation.types.js +2 -0
  148. package/dist/application/dispatch-observation.types.js.map +1 -0
  149. package/dist/application/dispatch-validation.d.ts +2 -2
  150. package/dist/application/dispatch-validation.js.map +1 -1
  151. package/dist/application/dispatch.js +8 -3
  152. package/dist/application/dispatch.js.map +1 -1
  153. package/dist/application/doctor-image.js +3 -3
  154. package/dist/application/doctor-image.js.map +1 -1
  155. package/dist/application/doctor-protocol.js +9 -4
  156. package/dist/application/doctor-protocol.js.map +1 -1
  157. package/dist/application/doctor-sandbox.js +4 -4
  158. package/dist/application/doctor-sandbox.js.map +1 -1
  159. package/dist/application/doctor-sandbox.types.d.ts +2 -2
  160. package/dist/application/doctor-sandbox.types.js.map +1 -1
  161. package/dist/application/doctor.constants.d.ts +1 -1
  162. package/dist/application/doctor.constants.js +1 -1
  163. package/dist/application/doctor.constants.js.map +1 -1
  164. package/dist/application/doctor.js +10 -9
  165. package/dist/application/doctor.js.map +1 -1
  166. package/dist/application/doctor.types.d.ts +3 -3
  167. package/dist/application/doctor.types.js.map +1 -1
  168. package/dist/application/execution.d.ts +2 -2
  169. package/dist/application/execution.js +1 -1
  170. package/dist/application/execution.js.map +1 -1
  171. package/dist/application/execution.types.d.ts +9 -2
  172. package/dist/application/execution.types.js.map +1 -1
  173. package/dist/application/harness-context.d.ts +2 -0
  174. package/dist/application/harness-context.js +54 -0
  175. package/dist/application/harness-context.js.map +1 -0
  176. package/dist/application/harness-history.d.ts +3 -0
  177. package/dist/application/harness-history.js +17 -0
  178. package/dist/application/harness-history.js.map +1 -0
  179. package/dist/application/harness-hooks.d.ts +9 -0
  180. package/dist/application/harness-hooks.js +90 -0
  181. package/dist/application/harness-hooks.js.map +1 -0
  182. package/dist/application/harness-loop.d.ts +2 -0
  183. package/dist/application/harness-loop.js +132 -0
  184. package/dist/application/harness-loop.js.map +1 -0
  185. package/dist/application/harness.types.d.ts +55 -0
  186. package/dist/application/harness.types.js +2 -0
  187. package/dist/application/harness.types.js.map +1 -0
  188. package/dist/application/lifecycle.constants.d.ts +1 -1
  189. package/dist/application/lifecycle.constants.js +1 -1
  190. package/dist/application/lifecycle.constants.js.map +1 -1
  191. package/dist/application/outpost.types.d.ts +6 -6
  192. package/dist/application/outpost.types.js.map +1 -1
  193. package/dist/application/remote-download.js +1 -1
  194. package/dist/application/remote-download.js.map +1 -1
  195. package/dist/application/sandbox-agents.js +12 -4
  196. package/dist/application/sandbox-agents.js.map +1 -1
  197. package/dist/application/sandbox-attach.js +5 -2
  198. package/dist/application/sandbox-attach.js.map +1 -1
  199. package/dist/application/sandbox-dispatch.js +3 -3
  200. package/dist/application/sandbox-dispatch.js.map +1 -1
  201. package/dist/application/sandbox-provision.js +13 -10
  202. package/dist/application/sandbox-provision.js.map +1 -1
  203. package/dist/application/sandbox-session.types.d.ts +8 -8
  204. package/dist/application/sandbox-session.types.js.map +1 -1
  205. package/dist/application/sandbox.js +6 -3
  206. package/dist/application/sandbox.js.map +1 -1
  207. package/dist/application/speculation.js +1 -1
  208. package/dist/application/speculation.js.map +1 -1
  209. package/dist/application/speculation.types.d.ts +3 -3
  210. package/dist/application/speculation.types.js.map +1 -1
  211. package/dist/application/tasks.types.d.ts +2 -2
  212. package/dist/application/tasks.types.js.map +1 -1
  213. package/dist/application/tool-execution.d.ts +3 -0
  214. package/dist/application/tool-execution.js +211 -0
  215. package/dist/application/tool-execution.js.map +1 -0
  216. package/dist/cli/commands.js +4 -2
  217. package/dist/cli/commands.js.map +1 -1
  218. package/dist/cli/doctor-command.js +6 -6
  219. package/dist/cli/doctor-command.js.map +1 -1
  220. package/dist/cli/init-authentication.js +6 -7
  221. package/dist/cli/init-authentication.js.map +1 -1
  222. package/dist/cli/init-command.js +3 -3
  223. package/dist/cli/init-command.js.map +1 -1
  224. package/dist/cli/main.constants.d.ts +4 -4
  225. package/dist/cli/main.constants.js +4 -4
  226. package/dist/cli/main.constants.js.map +1 -1
  227. package/dist/cli/recovery-command.js +1 -1
  228. package/dist/cli/recovery-command.js.map +1 -1
  229. package/dist/cli/scaffold-files.js +5 -4
  230. package/dist/cli/scaffold-files.js.map +1 -1
  231. package/dist/cli/scaffold-validation.js +13 -10
  232. package/dist/cli/scaffold-validation.js.map +1 -1
  233. package/dist/cli/scaffold.js +8 -4
  234. package/dist/cli/scaffold.js.map +1 -1
  235. package/dist/cli/scaffold.types.d.ts +1 -1
  236. package/dist/cli/scaffold.types.js.map +1 -1
  237. package/dist/cli/starters.js +8 -8
  238. package/dist/cli/starters.js.map +1 -1
  239. package/dist/domain/agent-model.d.ts +3 -0
  240. package/dist/domain/agent-model.js +22 -0
  241. package/dist/domain/agent-model.js.map +1 -0
  242. package/dist/domain/agent.d.ts +4 -0
  243. package/dist/domain/agent.js +32 -0
  244. package/dist/domain/agent.js.map +1 -0
  245. package/dist/domain/agent.types.d.ts +69 -2
  246. package/dist/domain/agent.types.js.map +1 -1
  247. package/dist/domain/context.constants.d.ts +7 -0
  248. package/dist/domain/context.constants.js +8 -0
  249. package/dist/domain/context.constants.js.map +1 -0
  250. package/dist/domain/context.d.ts +4 -0
  251. package/dist/domain/context.js +81 -0
  252. package/dist/domain/context.js.map +1 -0
  253. package/dist/domain/context.types.d.ts +26 -0
  254. package/dist/domain/context.types.js +2 -0
  255. package/dist/domain/context.types.js.map +1 -0
  256. package/dist/domain/dispatch-telemetry.types.d.ts +12 -0
  257. package/dist/domain/dispatch-telemetry.types.js +2 -0
  258. package/dist/domain/dispatch-telemetry.types.js.map +1 -0
  259. package/dist/domain/errors.types.d.ts +1 -1
  260. package/dist/domain/errors.types.js.map +1 -1
  261. package/dist/domain/glob.d.ts +2 -0
  262. package/dist/domain/glob.js +25 -0
  263. package/dist/domain/glob.js.map +1 -0
  264. package/dist/domain/glob.types.d.ts +1 -0
  265. package/dist/domain/glob.types.js +2 -0
  266. package/dist/domain/glob.types.js.map +1 -0
  267. package/dist/domain/harness.constants.d.ts +11 -0
  268. package/dist/domain/harness.constants.js +24 -0
  269. package/dist/domain/harness.constants.js.map +1 -0
  270. package/dist/domain/harness.d.ts +2 -0
  271. package/dist/domain/harness.js +89 -0
  272. package/dist/domain/harness.js.map +1 -0
  273. package/dist/domain/harness.types.d.ts +60 -0
  274. package/dist/domain/harness.types.js +2 -0
  275. package/dist/domain/harness.types.js.map +1 -0
  276. package/dist/domain/hook.constants.d.ts +3 -0
  277. package/dist/domain/hook.constants.js +10 -0
  278. package/dist/domain/hook.constants.js.map +1 -0
  279. package/dist/domain/hook.d.ts +3 -0
  280. package/dist/domain/hook.js +25 -0
  281. package/dist/domain/hook.js.map +1 -0
  282. package/dist/domain/hook.types.d.ts +66 -0
  283. package/dist/domain/hook.types.js +2 -0
  284. package/dist/domain/hook.types.js.map +1 -0
  285. package/dist/domain/instructions.d.ts +3 -0
  286. package/dist/domain/instructions.js +25 -0
  287. package/dist/domain/instructions.js.map +1 -0
  288. package/dist/domain/model-messages.d.ts +5 -0
  289. package/dist/domain/model-messages.js +81 -0
  290. package/dist/domain/model-messages.js.map +1 -0
  291. package/dist/domain/model-messages.types.d.ts +6 -0
  292. package/dist/domain/model-messages.types.js +2 -0
  293. package/dist/domain/model-messages.types.js.map +1 -0
  294. package/dist/domain/model.constants.d.ts +4 -0
  295. package/dist/domain/model.constants.js +16 -0
  296. package/dist/domain/model.constants.js.map +1 -0
  297. package/dist/domain/model.types.d.ts +59 -2
  298. package/dist/domain/model.types.js.map +1 -1
  299. package/dist/domain/permissions.d.ts +3 -0
  300. package/dist/domain/permissions.js +92 -0
  301. package/dist/domain/permissions.js.map +1 -0
  302. package/dist/domain/permissions.types.d.ts +34 -0
  303. package/dist/domain/permissions.types.js +2 -0
  304. package/dist/domain/permissions.types.js.map +1 -0
  305. package/dist/domain/response.js +3 -2
  306. package/dist/domain/response.js.map +1 -1
  307. package/dist/domain/response.types.d.ts +12 -0
  308. package/dist/domain/response.types.js.map +1 -1
  309. package/dist/domain/skill.constants.d.ts +2 -0
  310. package/dist/domain/skill.constants.js +8 -0
  311. package/dist/domain/skill.constants.js.map +1 -0
  312. package/dist/domain/skill.d.ts +8 -0
  313. package/dist/domain/skill.js +79 -0
  314. package/dist/domain/skill.js.map +1 -0
  315. package/dist/domain/skill.types.d.ts +18 -0
  316. package/dist/domain/skill.types.js +2 -0
  317. package/dist/domain/skill.types.js.map +1 -0
  318. package/dist/domain/standard-schema.d.ts +6 -0
  319. package/dist/domain/standard-schema.js +45 -0
  320. package/dist/domain/standard-schema.js.map +1 -0
  321. package/dist/domain/tool-schema.d.ts +3 -0
  322. package/dist/domain/tool-schema.js +109 -0
  323. package/dist/domain/tool-schema.js.map +1 -0
  324. package/dist/domain/tool.constants.d.ts +4 -0
  325. package/dist/domain/tool.constants.js +36 -0
  326. package/dist/domain/tool.constants.js.map +1 -0
  327. package/dist/domain/tool.d.ts +4 -0
  328. package/dist/domain/tool.js +66 -0
  329. package/dist/domain/tool.js.map +1 -0
  330. package/dist/domain/tool.types.d.ts +62 -0
  331. package/dist/domain/tool.types.js +2 -0
  332. package/dist/domain/tool.types.js.map +1 -0
  333. package/dist/domain/transcript.d.ts +4 -0
  334. package/dist/domain/transcript.js +48 -0
  335. package/dist/domain/transcript.js.map +1 -0
  336. package/dist/domain/transcript.types.d.ts +15 -0
  337. package/dist/domain/transcript.types.js +2 -0
  338. package/dist/domain/transcript.types.js.map +1 -0
  339. package/dist/domain/workflow/workflow-state.js +13 -6
  340. package/dist/domain/workflow/workflow-state.js.map +1 -1
  341. package/dist/domain/workflow.d.ts +1 -1
  342. package/dist/domain/workflow.js.map +1 -1
  343. package/dist/domain/workflow.types.d.ts +4 -0
  344. package/dist/domain/workflow.types.js.map +1 -1
  345. package/dist/index.d.ts +34 -8
  346. package/dist/index.js +19 -4
  347. package/dist/index.js.map +1 -1
  348. package/dist/infrastructure/conversations/harness-store.d.ts +3 -0
  349. package/dist/infrastructure/conversations/harness-store.js +27 -0
  350. package/dist/infrastructure/conversations/harness-store.js.map +1 -0
  351. package/dist/infrastructure/conversations/harness-transcript.d.ts +2 -0
  352. package/dist/infrastructure/conversations/harness-transcript.js +50 -0
  353. package/dist/infrastructure/conversations/harness-transcript.js.map +1 -0
  354. package/dist/infrastructure/conversations/harness-transcript.types.d.ts +18 -0
  355. package/dist/infrastructure/conversations/harness-transcript.types.js +2 -0
  356. package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -0
  357. package/dist/infrastructure/conversations.d.ts +4 -1
  358. package/dist/infrastructure/conversations.js +3 -0
  359. package/dist/infrastructure/conversations.js.map +1 -1
  360. package/dist/infrastructure/conversations.types.d.ts +1 -0
  361. package/dist/infrastructure/conversations.types.js.map +1 -1
  362. package/dist/infrastructure/custom-reporter.d.ts +2 -0
  363. package/dist/infrastructure/custom-reporter.js +33 -0
  364. package/dist/infrastructure/custom-reporter.js.map +1 -0
  365. package/dist/infrastructure/custom-reporter.types.d.ts +13 -0
  366. package/dist/infrastructure/custom-reporter.types.js +2 -0
  367. package/dist/infrastructure/custom-reporter.types.js.map +1 -0
  368. package/dist/infrastructure/git/git.constants.d.ts +1 -1
  369. package/dist/infrastructure/git/git.constants.js +1 -0
  370. package/dist/infrastructure/git/git.constants.js.map +1 -1
  371. package/dist/infrastructure/journal.constants.d.ts +1 -0
  372. package/dist/infrastructure/journal.constants.js +2 -0
  373. package/dist/infrastructure/journal.constants.js.map +1 -0
  374. package/dist/infrastructure/journal.js +4 -1
  375. package/dist/infrastructure/journal.js.map +1 -1
  376. package/dist/infrastructure/opentelemetry-dispatch.d.ts +6 -0
  377. package/dist/infrastructure/opentelemetry-dispatch.js +70 -0
  378. package/dist/infrastructure/opentelemetry-dispatch.js.map +1 -0
  379. package/dist/infrastructure/opentelemetry.constants.d.ts +3 -0
  380. package/dist/infrastructure/opentelemetry.constants.js +3 -0
  381. package/dist/infrastructure/opentelemetry.constants.js.map +1 -1
  382. package/dist/infrastructure/opentelemetry.js +4 -0
  383. package/dist/infrastructure/opentelemetry.js.map +1 -1
  384. package/dist/infrastructure/opentelemetry.types.d.ts +3 -3
  385. package/dist/infrastructure/opentelemetry.types.js.map +1 -1
  386. package/dist/infrastructure/reporter.js +27 -2
  387. package/dist/infrastructure/reporter.js.map +1 -1
  388. package/dist/infrastructure/resource-activity-inspection.js +3 -2
  389. package/dist/infrastructure/resource-activity-inspection.js.map +1 -1
  390. package/dist/infrastructure/resource-activity.js +2 -2
  391. package/dist/infrastructure/resource-activity.js.map +1 -1
  392. package/dist/infrastructure/resource-activity.types.d.ts +2 -2
  393. package/dist/infrastructure/resource-activity.types.js.map +1 -1
  394. package/dist/infrastructure/settings.d.ts +1 -1
  395. package/dist/infrastructure/settings.js +3 -3
  396. package/dist/infrastructure/settings.js.map +1 -1
  397. package/dist/infrastructure/sse.d.ts +2 -0
  398. package/dist/infrastructure/sse.js +64 -0
  399. package/dist/infrastructure/sse.js.map +1 -0
  400. package/dist/infrastructure/sse.types.d.ts +4 -0
  401. package/dist/infrastructure/sse.types.js +2 -0
  402. package/dist/infrastructure/sse.types.js.map +1 -0
  403. package/dist/infrastructure/transport-conversations.d.ts +2 -2
  404. package/dist/infrastructure/transport-conversations.js +8 -1
  405. package/dist/infrastructure/transport-conversations.js.map +1 -1
  406. package/dist/infrastructure/transport-journal.js +2 -1
  407. package/dist/infrastructure/transport-journal.js.map +1 -1
  408. package/dist/providers/agents.d.ts +3 -3
  409. package/dist/providers/agents.js +3 -3
  410. package/dist/providers/agents.js.map +1 -1
  411. package/dist/providers/daytona.d.ts +1 -1
  412. package/dist/providers/daytona.js +1 -1
  413. package/dist/providers/daytona.js.map +1 -1
  414. package/dist/providers/docker.d.ts +1 -1
  415. package/dist/providers/docker.js +1 -1
  416. package/dist/providers/docker.js.map +1 -1
  417. package/dist/providers/factories.d.ts +2 -2
  418. package/dist/providers/factories.js +3 -3
  419. package/dist/providers/factories.js.map +1 -1
  420. package/dist/providers/firecracker.d.ts +1 -1
  421. package/dist/providers/firecracker.js +1 -1
  422. package/dist/providers/firecracker.js.map +1 -1
  423. package/dist/providers/local.d.ts +1 -1
  424. package/dist/providers/local.js +1 -1
  425. package/dist/providers/local.js.map +1 -1
  426. package/dist/providers/podman.d.ts +1 -1
  427. package/dist/providers/podman.js +1 -1
  428. package/dist/providers/podman.js.map +1 -1
  429. package/dist/providers/vercel.d.ts +1 -1
  430. package/dist/providers/vercel.js +1 -1
  431. package/dist/providers/vercel.js.map +1 -1
  432. package/package.json +1 -1
  433. package/dist/adapters/models/openai-compatible.constants.js.map +0 -1
  434. package/dist/adapters/models/openai-compatible.d.ts +0 -3
  435. package/dist/adapters/models/openai-compatible.js +0 -78
  436. package/dist/adapters/models/openai-compatible.js.map +0 -1
  437. package/dist/adapters/models/openai-compatible.types.d.ts +0 -14
  438. package/dist/adapters/models/openai-compatible.types.js +0 -2
  439. package/dist/adapters/models/openai-compatible.types.js.map +0 -1
  440. package/dist/adapters/models/openai-http.js.map +0 -1
  441. package/dist/adapters/models/openai-request.d.ts +0 -4
  442. package/dist/adapters/models/openai-request.js +0 -46
  443. package/dist/adapters/models/openai-request.js.map +0 -1
  444. package/dist/adapters/models/openai-response.d.ts +0 -3
  445. package/dist/adapters/models/openai-response.js +0 -65
  446. package/dist/adapters/models/openai-response.js.map +0 -1
  447. package/dist/cli/init-authentication.constants.js.map +0 -1
  448. /package/dist/{cli/init-authentication.constants.d.ts → adapters/agents/authentication.constants.d.ts} +0 -0
  449. /package/dist/adapters/models/{openai-http.d.ts → model-http.d.ts} +0 -0
  450. /package/dist/adapters/models/{openai-compatible.constants.d.ts → model.constants.d.ts} +0 -0
@@ -0,0 +1,4 @@
1
+ import type { ModelStopReason } from "../../domain/model.types.ts";
2
+ export declare const ANTHROPIC_STOP_REASONS: Readonly<Record<string, ModelStopReason>>;
3
+ export declare const CHAT_FINISH_REASONS: Readonly<Record<string, ModelStopReason>>;
4
+ export declare const RESPONSES_INCOMPLETE_REASONS: Readonly<Record<string, ModelStopReason>>;
@@ -0,0 +1,19 @@
1
+ export const ANTHROPIC_STOP_REASONS = {
2
+ end_turn: "end",
3
+ stop_sequence: "end",
4
+ tool_use: "tool-calls",
5
+ max_tokens: "max-tokens",
6
+ model_context_window_exceeded: "max-tokens",
7
+ refusal: "refusal",
8
+ };
9
+ export const CHAT_FINISH_REASONS = {
10
+ stop: "end",
11
+ tool_calls: "tool-calls",
12
+ length: "max-tokens",
13
+ content_filter: "refusal",
14
+ };
15
+ export const RESPONSES_INCOMPLETE_REASONS = {
16
+ max_output_tokens: "max-tokens",
17
+ content_filter: "refusal",
18
+ };
19
+ //# sourceMappingURL=stop-reasons.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop-reasons.constants.js","sourceRoot":"","sources":["../../../src/adapters/models/stop-reasons.constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GACjC;IACE,QAAQ,EAAE,KAAK;IACf,aAAa,EAAE,KAAK;IACpB,QAAQ,EAAE,YAAY;IACtB,UAAU,EAAE,YAAY;IACxB,6BAA6B,EAAE,YAAY;IAC3C,OAAO,EAAE,SAAS;CACnB,CAAC;AAEJ,MAAM,CAAC,MAAM,mBAAmB,GAA8C;IAC5E,IAAI,EAAE,KAAK;IACX,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,YAAY;IACpB,cAAc,EAAE,SAAS;CAC1B,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAErC;IACF,iBAAiB,EAAE,YAAY;IAC/B,cAAc,EAAE,SAAS;CAC1B,CAAC","sourcesContent":["import type { ModelStopReason } from \"../../domain/model.types.ts\";\n\nexport const ANTHROPIC_STOP_REASONS: Readonly<Record<string, ModelStopReason>> =\n {\n end_turn: \"end\",\n stop_sequence: \"end\",\n tool_use: \"tool-calls\",\n max_tokens: \"max-tokens\",\n model_context_window_exceeded: \"max-tokens\",\n refusal: \"refusal\",\n };\n\nexport const CHAT_FINISH_REASONS: Readonly<Record<string, ModelStopReason>> = {\n stop: \"end\",\n tool_calls: \"tool-calls\",\n length: \"max-tokens\",\n content_filter: \"refusal\",\n};\n\nexport const RESPONSES_INCOMPLETE_REASONS: Readonly<\n Record<string, ModelStopReason>\n> = {\n max_output_tokens: \"max-tokens\",\n content_filter: \"refusal\",\n};\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ServerSentEvent } from "../../infrastructure/sse.types.ts";
2
+ export declare function eventData(event: ServerSentEvent): Record<string, unknown>;
3
+ export declare function streamFailure(data: Record<string, unknown>): never;
@@ -0,0 +1,22 @@
1
+ import { OutpostError } from "../../domain/errors.js";
2
+ import { object } from "./model-response.js";
3
+ export function eventData(event) {
4
+ let value;
5
+ try {
6
+ value = JSON.parse(event.data);
7
+ }
8
+ catch {
9
+ throw new OutpostError("response", "Model stream event is not valid JSON");
10
+ }
11
+ return object(value);
12
+ }
13
+ export function streamFailure(data) {
14
+ const error = data.error;
15
+ const type = error && typeof error === "object" && "type" in error
16
+ ? String(error.type)
17
+ : undefined;
18
+ throw new OutpostError("provider", "Model stream reported an error", {
19
+ ...(type ? { type } : {}),
20
+ });
21
+ }
22
+ //# sourceMappingURL=stream-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-events.js","sourceRoot":"","sources":["../../../src/adapters/models/stream-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,sCAAsC,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAA6B;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,MAAM,IAAI,GACR,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK;QACnD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,gCAAgC,EAAE;QACnE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1B,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { OutpostError } from \"../../domain/errors.ts\";\nimport type { ServerSentEvent } from \"../../infrastructure/sse.types.ts\";\nimport { object } from \"./model-response.ts\";\n\nexport function eventData(event: ServerSentEvent): Record<string, unknown> {\n let value: unknown;\n try {\n value = JSON.parse(event.data);\n } catch {\n throw new OutpostError(\"response\", \"Model stream event is not valid JSON\");\n }\n return object(value);\n}\n\nexport function streamFailure(data: Record<string, unknown>): never {\n const error = data.error;\n const type =\n error && typeof error === \"object\" && \"type\" in error\n ? String(error.type)\n : undefined;\n throw new OutpostError(\"provider\", \"Model stream reported an error\", {\n ...(type ? { type } : {}),\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { HarnessToolset } from "../../domain/tool.types.ts";
2
+ export declare function harnessEditTools(): HarnessToolset;
@@ -0,0 +1,84 @@
1
+ import { writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
4
+ import { digest, downloadFile, repositoryPath, sandboxPath, withStaging, } from "./sandbox-files.js";
5
+ export function harnessEditTools() {
6
+ return defineHarnessToolset({
7
+ name: "edit",
8
+ tools: [writeFileTool(), editFileTool()],
9
+ });
10
+ }
11
+ function writeFileTool() {
12
+ return defineHarnessTool({
13
+ name: "write_file",
14
+ description: "Create or replace a UTF-8 file relative to the repository root with the given content. Prefer edit_file to change part of an existing file.",
15
+ input: {
16
+ type: "object",
17
+ properties: {
18
+ path: { type: "string", minLength: 1 },
19
+ content: { type: "string" },
20
+ },
21
+ required: ["path", "content"],
22
+ additionalProperties: false,
23
+ },
24
+ resources: (input) => ({ paths: [input.path] }),
25
+ execute: (input, context) => withStaging(async (directory) => {
26
+ repositoryPath(input.path);
27
+ const staged = join(directory, "file");
28
+ await writeFile(staged, input.content);
29
+ await upload(context, staged, input.path);
30
+ return `Wrote ${Buffer.byteLength(input.content)} bytes to ${input.path}`;
31
+ }),
32
+ });
33
+ }
34
+ function editFileTool() {
35
+ return defineHarnessTool({
36
+ name: "edit_file",
37
+ description: "Replace an exact text in a UTF-8 file. old_text must appear exactly once unless replace_all is true; include surrounding lines to make it unique.",
38
+ input: {
39
+ type: "object",
40
+ properties: {
41
+ path: { type: "string", minLength: 1 },
42
+ old_text: { type: "string", minLength: 1 },
43
+ new_text: { type: "string" },
44
+ replace_all: { type: "boolean" },
45
+ },
46
+ required: ["path", "old_text", "new_text"],
47
+ additionalProperties: false,
48
+ },
49
+ resources: (input) => ({ paths: [input.path] }),
50
+ execute: (input, context) => withStaging(async (directory) => {
51
+ const original = await downloadFile(context, input.path, join(directory, "file"));
52
+ const text = original.bytes.toString("utf8");
53
+ const occurrences = text.split(input.old_text).length - 1;
54
+ if (occurrences === 0)
55
+ return {
56
+ content: `old_text was not found in ${input.path}`,
57
+ isError: true,
58
+ };
59
+ if (occurrences > 1 && !input.replace_all)
60
+ return {
61
+ content: `old_text appears ${occurrences} times in ${input.path}; add surrounding lines or set replace_all`,
62
+ isError: true,
63
+ };
64
+ const updated = input.replace_all
65
+ ? text.split(input.old_text).join(input.new_text)
66
+ : text.replace(input.old_text, () => input.new_text);
67
+ const current = await downloadFile(context, input.path, join(directory, "current"));
68
+ if (digest(current.bytes) !== digest(original.bytes))
69
+ return {
70
+ content: `${input.path} changed during the edit; read it again and retry`,
71
+ isError: true,
72
+ };
73
+ await writeFile(original.staged, updated);
74
+ await upload(context, original.staged, input.path);
75
+ return `Replaced ${input.replace_all ? occurrences : 1} occurrence(s) in ${input.path}`;
76
+ }),
77
+ });
78
+ }
79
+ function upload(context, staged, path) {
80
+ return context.sandbox.upload(staged, sandboxPath(context, path), {
81
+ signal: context.signal,
82
+ });
83
+ }
84
+ //# sourceMappingURL=edit-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/edit-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type {\n HarnessToolContext,\n HarnessToolset,\n} from \"../../domain/tool.types.ts\";\nimport {\n digest,\n downloadFile,\n repositoryPath,\n sandboxPath,\n withStaging,\n} from \"./sandbox-files.ts\";\nimport type { EditFileInput, WriteFileInput } from \"./tools.types.ts\";\n\nexport function harnessEditTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"edit\",\n tools: [writeFileTool(), editFileTool()],\n });\n}\n\nfunction writeFileTool() {\n return defineHarnessTool({\n name: \"write_file\",\n description:\n \"Create or replace a UTF-8 file relative to the repository root with the given content. Prefer edit_file to change part of an existing file.\",\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n content: { type: \"string\" },\n },\n required: [\"path\", \"content\"],\n additionalProperties: false,\n },\n resources: (input: WriteFileInput) => ({ paths: [input.path] }),\n execute: (input: WriteFileInput, context) =>\n withStaging(async (directory) => {\n repositoryPath(input.path);\n const staged = join(directory, \"file\");\n await writeFile(staged, input.content);\n await upload(context, staged, input.path);\n return `Wrote ${Buffer.byteLength(input.content)} bytes to ${input.path}`;\n }),\n });\n}\n\nfunction editFileTool() {\n return defineHarnessTool({\n name: \"edit_file\",\n description:\n \"Replace an exact text in a UTF-8 file. old_text must appear exactly once unless replace_all is true; include surrounding lines to make it unique.\",\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n old_text: { type: \"string\", minLength: 1 },\n new_text: { type: \"string\" },\n replace_all: { type: \"boolean\" },\n },\n required: [\"path\", \"old_text\", \"new_text\"],\n additionalProperties: false,\n },\n resources: (input: EditFileInput) => ({ paths: [input.path] }),\n execute: (input: EditFileInput, context) =>\n withStaging(async (directory) => {\n const original = await downloadFile(\n context,\n input.path,\n join(directory, \"file\"),\n );\n const text = original.bytes.toString(\"utf8\");\n const occurrences = text.split(input.old_text).length - 1;\n if (occurrences === 0)\n return {\n content: `old_text was not found in ${input.path}`,\n isError: true,\n };\n if (occurrences > 1 && !input.replace_all)\n return {\n content: `old_text appears ${occurrences} times in ${input.path}; add surrounding lines or set replace_all`,\n isError: true,\n };\n const updated = input.replace_all\n ? text.split(input.old_text).join(input.new_text)\n : text.replace(input.old_text, () => input.new_text);\n const current = await downloadFile(\n context,\n input.path,\n join(directory, \"current\"),\n );\n if (digest(current.bytes) !== digest(original.bytes))\n return {\n content: `${input.path} changed during the edit; read it again and retry`,\n isError: true,\n };\n await writeFile(original.staged, updated);\n await upload(context, original.staged, input.path);\n return `Replaced ${input.replace_all ? occurrences : 1} occurrence(s) in ${input.path}`;\n }),\n });\n}\n\nfunction upload(context: HarnessToolContext, staged: string, path: string) {\n return context.sandbox.upload(staged, sandboxPath(context, path), {\n signal: context.signal,\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { HarnessToolset } from "../../domain/tool.types.ts";
2
+ export declare function harnessFileTools(): HarnessToolset;
@@ -0,0 +1,97 @@
1
+ import { join } from "node:path";
2
+ import { glob } from "../../domain/glob.js";
3
+ import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
4
+ import { anywhere, downloadFile, repositoryPath, withStaging, } from "./sandbox-files.js";
5
+ import { TOOL_LIMITS } from "./tools.constants.js";
6
+ export function harnessFileTools() {
7
+ return defineHarnessToolset({
8
+ name: "files",
9
+ tools: [readFileTool(), listFilesTool()],
10
+ });
11
+ }
12
+ function readFileTool() {
13
+ return defineHarnessTool({
14
+ name: "read_file",
15
+ description: "Read a UTF-8 text file relative to the repository root. Lines are numbered; use offset and limit for long files.",
16
+ readOnly: true,
17
+ input: {
18
+ type: "object",
19
+ properties: {
20
+ path: { type: "string", minLength: 1 },
21
+ offset: { type: "integer", minimum: 1 },
22
+ limit: { type: "integer", minimum: 1, maximum: TOOL_LIMITS.readLines },
23
+ },
24
+ required: ["path"],
25
+ additionalProperties: false,
26
+ },
27
+ resources: (input) => ({ paths: [input.path] }),
28
+ execute: (input, context) => withStaging(async (directory) => {
29
+ const file = await downloadFile(context, input.path, join(directory, "file"));
30
+ const lines = file.bytes.toString("utf8").split(/\r?\n/);
31
+ if (lines.at(-1) === "")
32
+ lines.pop();
33
+ const start = (input.offset ?? 1) - 1;
34
+ const selected = lines.slice(start, start + (input.limit ?? TOOL_LIMITS.readLines));
35
+ const width = String(start + selected.length).length;
36
+ const body = selected
37
+ .map((line, index) => `${String(start + index + 1).padStart(width)}\t${line}`)
38
+ .join("\n");
39
+ const end = start + selected.length;
40
+ const note = end < lines.length || start > 0
41
+ ? `\n[lines ${start + 1}-${end} of ${lines.length}]`
42
+ : "";
43
+ return lines.length ? `${body}${note}` : "(empty file)";
44
+ }),
45
+ });
46
+ }
47
+ function listFilesTool() {
48
+ return defineHarnessTool({
49
+ name: "list_files",
50
+ description: "List files in the repository that are tracked or not ignored by Git, optionally under a directory and filtered by a glob such as src/**/*.ts; a glob without a slash matches file names at any depth.",
51
+ readOnly: true,
52
+ input: {
53
+ type: "object",
54
+ properties: {
55
+ path: { type: "string" },
56
+ pattern: { type: "string", minLength: 1 },
57
+ },
58
+ additionalProperties: false,
59
+ },
60
+ resources: (input) => ({ paths: [input.path ?? "."] }),
61
+ async execute(input, context) {
62
+ const scope = repositoryPath(input.path ?? ".") || ".";
63
+ const result = await context.sandbox.invoke({
64
+ executable: "git",
65
+ arguments: [
66
+ "ls-files",
67
+ "-z",
68
+ "--cached",
69
+ "--others",
70
+ "--exclude-standard",
71
+ "--",
72
+ scope,
73
+ ],
74
+ retain: TOOL_LIMITS.commandCharacters * 10,
75
+ signal: context.signal,
76
+ });
77
+ if (result.status !== 0)
78
+ return {
79
+ content: result.stderr || "git ls-files failed",
80
+ isError: true,
81
+ };
82
+ const matcher = input.pattern
83
+ ? glob(anywhere(input.pattern), "path")
84
+ : undefined;
85
+ const files = [...new Set(result.stdout.split("\0").filter(Boolean))]
86
+ .filter((file) => !matcher || matcher.test(file))
87
+ .sort();
88
+ const shown = files.slice(0, TOOL_LIMITS.listEntries);
89
+ if (!shown.length)
90
+ return "No files found.";
91
+ return shown.length < files.length
92
+ ? `${shown.join("\n")}\n[${files.length - shown.length} more files; narrow the path or pattern]`
93
+ : shown.join("\n");
94
+ },
95
+ });
96
+ }
97
+ //# sourceMappingURL=file-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/file-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { glob } from \"../../domain/glob.ts\";\nimport { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport {\n anywhere,\n downloadFile,\n repositoryPath,\n withStaging,\n} from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { ListFilesInput, ReadFileInput } from \"./tools.types.ts\";\n\nexport function harnessFileTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"files\",\n tools: [readFileTool(), listFilesTool()],\n });\n}\n\nfunction readFileTool() {\n return defineHarnessTool({\n name: \"read_file\",\n description:\n \"Read a UTF-8 text file relative to the repository root. Lines are numbered; use offset and limit for long files.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n offset: { type: \"integer\", minimum: 1 },\n limit: { type: \"integer\", minimum: 1, maximum: TOOL_LIMITS.readLines },\n },\n required: [\"path\"],\n additionalProperties: false,\n },\n resources: (input: ReadFileInput) => ({ paths: [input.path] }),\n execute: (input: ReadFileInput, context) =>\n withStaging(async (directory) => {\n const file = await downloadFile(\n context,\n input.path,\n join(directory, \"file\"),\n );\n const lines = file.bytes.toString(\"utf8\").split(/\\r?\\n/);\n if (lines.at(-1) === \"\") lines.pop();\n const start = (input.offset ?? 1) - 1;\n const selected = lines.slice(\n start,\n start + (input.limit ?? TOOL_LIMITS.readLines),\n );\n const width = String(start + selected.length).length;\n const body = selected\n .map(\n (line, index) =>\n `${String(start + index + 1).padStart(width)}\\t${line}`,\n )\n .join(\"\\n\");\n const end = start + selected.length;\n const note =\n end < lines.length || start > 0\n ? `\\n[lines ${start + 1}-${end} of ${lines.length}]`\n : \"\";\n return lines.length ? `${body}${note}` : \"(empty file)\";\n }),\n });\n}\n\nfunction listFilesTool() {\n return defineHarnessTool({\n name: \"list_files\",\n description:\n \"List files in the repository that are tracked or not ignored by Git, optionally under a directory and filtered by a glob such as src/**/*.ts; a glob without a slash matches file names at any depth.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n pattern: { type: \"string\", minLength: 1 },\n },\n additionalProperties: false,\n },\n resources: (input: ListFilesInput) => ({ paths: [input.path ?? \".\"] }),\n async execute(input: ListFilesInput, context) {\n const scope = repositoryPath(input.path ?? \".\") || \".\";\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"ls-files\",\n \"-z\",\n \"--cached\",\n \"--others\",\n \"--exclude-standard\",\n \"--\",\n scope,\n ],\n retain: TOOL_LIMITS.commandCharacters * 10,\n signal: context.signal,\n });\n if (result.status !== 0)\n return {\n content: result.stderr || \"git ls-files failed\",\n isError: true,\n };\n const matcher = input.pattern\n ? glob(anywhere(input.pattern), \"path\")\n : undefined;\n const files = [...new Set(result.stdout.split(\"\\0\").filter(Boolean))]\n .filter((file) => !matcher || matcher.test(file))\n .sort();\n const shown = files.slice(0, TOOL_LIMITS.listEntries);\n if (!shown.length) return \"No files found.\";\n return shown.length < files.length\n ? `${shown.join(\"\\n\")}\\n[${files.length - shown.length} more files; narrow the path or pattern]`\n : shown.join(\"\\n\");\n },\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { HarnessToolset } from "../../domain/tool.types.ts";
2
+ export declare function harnessGitTools(): HarnessToolset;
@@ -0,0 +1,54 @@
1
+ import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
2
+ import { commandOutput } from "./sandbox-files.js";
3
+ import { GIT_BLOCKED_OPTIONS, GIT_READ_COMMANDS, TOOL_LIMITS, } from "./tools.constants.js";
4
+ export function harnessGitTools() {
5
+ return defineHarnessToolset({
6
+ name: "git",
7
+ tools: [
8
+ defineHarnessTool({
9
+ name: "git",
10
+ description: "Run a read-only Git command (status, diff, log or show) in the repository with extra arguments, for example log with -n 5 --oneline.",
11
+ readOnly: true,
12
+ input: {
13
+ type: "object",
14
+ properties: {
15
+ command: { enum: [...GIT_READ_COMMANDS] },
16
+ arguments: { type: "array", items: { type: "string" } },
17
+ },
18
+ required: ["command"],
19
+ additionalProperties: false,
20
+ },
21
+ resources: (input) => ({
22
+ command: ["git", input.command, ...(input.arguments ?? [])].join(" "),
23
+ }),
24
+ async execute(input, context) {
25
+ const blocked = (input.arguments ?? []).find((argument) => GIT_BLOCKED_OPTIONS.some((option) => argument.startsWith(option)));
26
+ if (blocked)
27
+ return {
28
+ content: `Unsupported Git option: ${blocked}`,
29
+ isError: true,
30
+ };
31
+ const result = await context.sandbox.invoke({
32
+ executable: "git",
33
+ arguments: [
34
+ "--no-pager",
35
+ input.command,
36
+ ...(input.command === "status"
37
+ ? []
38
+ : ["--no-ext-diff", "--no-textconv"]),
39
+ ...(input.arguments ?? []),
40
+ ],
41
+ stdin: "",
42
+ retain: TOOL_LIMITS.commandCharacters,
43
+ signal: context.signal,
44
+ });
45
+ return {
46
+ content: commandOutput(result),
47
+ isError: result.status !== 0,
48
+ };
49
+ },
50
+ }),
51
+ ],
52
+ });
53
+ }
54
+ //# sourceMappingURL=git-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/git-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAG9B,MAAM,UAAU,eAAe;IAC7B,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,KAAK;QACX,KAAK,EAAE;YACL,iBAAiB,CAAC;gBAChB,IAAI,EAAE,KAAK;gBACX,WAAW,EACT,sIAAsI;gBACxI,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,iBAAiB,CAAC,EAAE;wBACzC,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;qBACxD;oBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;oBACrB,oBAAoB,EAAE,KAAK;iBAC5B;gBACD,SAAS,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,CAAC;oBAC/B,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;iBACtE,CAAC;gBACF,KAAK,CAAC,OAAO,CAAC,KAAe,EAAE,OAAO;oBACpC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACxD,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAClE,CAAC;oBACF,IAAI,OAAO;wBACT,OAAO;4BACL,OAAO,EAAE,2BAA2B,OAAO,EAAE;4BAC7C,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;wBAC1C,UAAU,EAAE,KAAK;wBACjB,SAAS,EAAE;4BACT,YAAY;4BACZ,KAAK,CAAC,OAAO;4BACb,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ;gCAC5B,CAAC,CAAC,EAAE;gCACJ,CAAC,CAAC,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;4BACvC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;yBAC3B;wBACD,KAAK,EAAE,EAAE;wBACT,MAAM,EAAE,WAAW,CAAC,iBAAiB;wBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAC;oBACH,OAAO;wBACL,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC;wBAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;qBAC7B,CAAC;gBACJ,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { commandOutput } from \"./sandbox-files.ts\";\nimport {\n GIT_BLOCKED_OPTIONS,\n GIT_READ_COMMANDS,\n TOOL_LIMITS,\n} from \"./tools.constants.ts\";\nimport type { GitInput } from \"./tools.types.ts\";\n\nexport function harnessGitTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"git\",\n tools: [\n defineHarnessTool({\n name: \"git\",\n description:\n \"Run a read-only Git command (status, diff, log or show) in the repository with extra arguments, for example log with -n 5 --oneline.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n command: { enum: [...GIT_READ_COMMANDS] },\n arguments: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"command\"],\n additionalProperties: false,\n },\n resources: (input: GitInput) => ({\n command: [\"git\", input.command, ...(input.arguments ?? [])].join(\" \"),\n }),\n async execute(input: GitInput, context) {\n const blocked = (input.arguments ?? []).find((argument) =>\n GIT_BLOCKED_OPTIONS.some((option) => argument.startsWith(option)),\n );\n if (blocked)\n return {\n content: `Unsupported Git option: ${blocked}`,\n isError: true,\n };\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"--no-pager\",\n input.command,\n ...(input.command === \"status\"\n ? []\n : [\"--no-ext-diff\", \"--no-textconv\"]),\n ...(input.arguments ?? []),\n ],\n stdin: \"\",\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n return {\n content: commandOutput(result),\n isError: result.status !== 0,\n };\n },\n }),\n ],\n });\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { CommandResult } from "../../domain/command.types.ts";
2
+ import type { HarnessToolContext } from "../../domain/tool.types.ts";
3
+ import type { SandboxFile } from "./tools.types.ts";
4
+ export declare function repositoryPath(path: string): string;
5
+ export declare function sandboxPath(context: HarnessToolContext, path: string): string;
6
+ export declare function withStaging<T>(operation: (directory: string) => Promise<T>): Promise<T>;
7
+ export declare function downloadFile(context: HarnessToolContext, path: string, staged: string): Promise<SandboxFile>;
8
+ export declare function digest(bytes: Buffer): string;
9
+ export declare function commandOutput(result: CommandResult): string;
10
+ export declare function anywhere(pattern: string): string;
@@ -0,0 +1,60 @@
1
+ import { createHash } from "node:crypto";
2
+ import { lstat, mkdtemp, readFile, rm } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join, posix } from "node:path";
5
+ import { normalizeResourcePath } from "../../domain/permissions.js";
6
+ import { TOOL_LIMITS } from "./tools.constants.js";
7
+ export function repositoryPath(path) {
8
+ const normalized = normalizeResourcePath(path);
9
+ if (normalized === undefined)
10
+ throw new Error(`Path must stay inside the repository: ${path}`);
11
+ return normalized;
12
+ }
13
+ export function sandboxPath(context, path) {
14
+ const normalized = repositoryPath(path);
15
+ return normalized
16
+ ? posix.join(context.sandbox.root, normalized)
17
+ : context.sandbox.root;
18
+ }
19
+ export async function withStaging(operation) {
20
+ const directory = await mkdtemp(join(tmpdir(), "outpost-tool-"));
21
+ try {
22
+ return await operation(directory);
23
+ }
24
+ finally {
25
+ await rm(directory, { recursive: true, force: true });
26
+ }
27
+ }
28
+ export async function downloadFile(context, path, staged) {
29
+ await context.sandbox.download(sandboxPath(context, path), staged, {
30
+ signal: context.signal,
31
+ });
32
+ const info = await lstat(staged);
33
+ if (info.isSymbolicLink())
34
+ throw new Error(`${path} is a symbolic link; links are not followed`);
35
+ if (!info.isFile())
36
+ throw new Error(`${path} is not a regular file`);
37
+ if (info.size > TOOL_LIMITS.fileBytes)
38
+ throw new Error(`${path} has ${info.size} bytes; the limit is ${TOOL_LIMITS.fileBytes}`);
39
+ const bytes = await readFile(staged);
40
+ if (bytes.subarray(0, TOOL_LIMITS.binaryProbeBytes).includes(0))
41
+ throw new Error(`${path} looks binary and cannot be read as text`);
42
+ return { staged, bytes };
43
+ }
44
+ export function digest(bytes) {
45
+ return createHash("sha256").update(bytes).digest("hex");
46
+ }
47
+ export function commandOutput(result) {
48
+ const note = (text) => text.length >= TOOL_LIMITS.commandCharacters
49
+ ? `[output truncated to the last ${TOOL_LIMITS.commandCharacters} characters]\n${text}`
50
+ : text;
51
+ return [
52
+ `exit status: ${result.status}`,
53
+ ...(result.stdout ? ["--- stdout ---", note(result.stdout)] : []),
54
+ ...(result.stderr ? ["--- stderr ---", note(result.stderr)] : []),
55
+ ].join("\n");
56
+ }
57
+ export function anywhere(pattern) {
58
+ return pattern.includes("/") ? pattern : `**/${pattern}`;
59
+ }
60
+ //# sourceMappingURL=sandbox-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-files.js","sourceRoot":"","sources":["../../../src/adapters/tools/sandbox-files.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { lstat, mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join, posix } from \"node:path\";\nimport { normalizeResourcePath } from \"../../domain/permissions.ts\";\nimport type { CommandResult } from \"../../domain/command.types.ts\";\nimport type { HarnessToolContext } from \"../../domain/tool.types.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { SandboxFile } from \"./tools.types.ts\";\n\nexport function repositoryPath(path: string): string {\n const normalized = normalizeResourcePath(path);\n if (normalized === undefined)\n throw new Error(`Path must stay inside the repository: ${path}`);\n return normalized;\n}\n\nexport function sandboxPath(context: HarnessToolContext, path: string): string {\n const normalized = repositoryPath(path);\n return normalized\n ? posix.join(context.sandbox.root, normalized)\n : context.sandbox.root;\n}\n\nexport async function withStaging<T>(\n operation: (directory: string) => Promise<T>,\n): Promise<T> {\n const directory = await mkdtemp(join(tmpdir(), \"outpost-tool-\"));\n try {\n return await operation(directory);\n } finally {\n await rm(directory, { recursive: true, force: true });\n }\n}\n\nexport async function downloadFile(\n context: HarnessToolContext,\n path: string,\n staged: string,\n): Promise<SandboxFile> {\n await context.sandbox.download(sandboxPath(context, path), staged, {\n signal: context.signal,\n });\n const info = await lstat(staged);\n if (info.isSymbolicLink())\n throw new Error(`${path} is a symbolic link; links are not followed`);\n if (!info.isFile()) throw new Error(`${path} is not a regular file`);\n if (info.size > TOOL_LIMITS.fileBytes)\n throw new Error(\n `${path} has ${info.size} bytes; the limit is ${TOOL_LIMITS.fileBytes}`,\n );\n const bytes = await readFile(staged);\n if (bytes.subarray(0, TOOL_LIMITS.binaryProbeBytes).includes(0))\n throw new Error(`${path} looks binary and cannot be read as text`);\n return { staged, bytes };\n}\n\nexport function digest(bytes: Buffer): string {\n return createHash(\"sha256\").update(bytes).digest(\"hex\");\n}\n\nexport function commandOutput(result: CommandResult): string {\n const note = (text: string) =>\n text.length >= TOOL_LIMITS.commandCharacters\n ? `[output truncated to the last ${TOOL_LIMITS.commandCharacters} characters]\\n${text}`\n : text;\n return [\n `exit status: ${result.status}`,\n ...(result.stdout ? [\"--- stdout ---\", note(result.stdout)] : []),\n ...(result.stderr ? [\"--- stderr ---\", note(result.stderr)] : []),\n ].join(\"\\n\");\n}\n\nexport function anywhere(pattern: string): string {\n return pattern.includes(\"/\") ? pattern : `**/${pattern}`;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { HarnessToolset } from "../../domain/tool.types.ts";
2
+ export declare function harnessSearchTools(): HarnessToolset;
@@ -0,0 +1,65 @@
1
+ import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
2
+ import { anywhere, repositoryPath } from "./sandbox-files.js";
3
+ import { TOOL_LIMITS } from "./tools.constants.js";
4
+ export function harnessSearchTools() {
5
+ return defineHarnessToolset({ name: "search", tools: [searchTool()] });
6
+ }
7
+ function searchTool() {
8
+ return defineHarnessTool({
9
+ name: "search",
10
+ description: "Search repository files that are tracked or not ignored by Git for an extended regular expression. Returns path:line:text matches. A glob without a slash matches file names at any depth.",
11
+ readOnly: true,
12
+ input: {
13
+ type: "object",
14
+ properties: {
15
+ pattern: { type: "string", minLength: 1 },
16
+ path: { type: "string" },
17
+ glob: { type: "string", minLength: 1 },
18
+ ignore_case: { type: "boolean" },
19
+ max_results: {
20
+ type: "integer",
21
+ minimum: 1,
22
+ maximum: TOOL_LIMITS.searchMatches,
23
+ },
24
+ },
25
+ required: ["pattern"],
26
+ additionalProperties: false,
27
+ },
28
+ resources: (input) => ({ paths: [input.path ?? "."] }),
29
+ async execute(input, context) {
30
+ const scope = repositoryPath(input.path ?? ".") || ".";
31
+ const result = await context.sandbox.invoke({
32
+ executable: "git",
33
+ arguments: [
34
+ "grep",
35
+ "--untracked",
36
+ "-n",
37
+ "-I",
38
+ "--no-color",
39
+ "--full-name",
40
+ "-E",
41
+ ...(input.ignore_case ? ["-i"] : []),
42
+ "-e",
43
+ input.pattern,
44
+ "--",
45
+ input.glob
46
+ ? `:(glob)${scope === "." ? "" : `${scope}/`}${anywhere(input.glob)}`
47
+ : scope,
48
+ ],
49
+ retain: TOOL_LIMITS.commandCharacters,
50
+ signal: context.signal,
51
+ });
52
+ if (result.status === 1)
53
+ return "No matches.";
54
+ if (result.status !== 0)
55
+ return { content: result.stderr || "git grep failed", isError: true };
56
+ const limit = input.max_results ?? TOOL_LIMITS.searchMatches;
57
+ const matches = result.stdout.split("\n").filter(Boolean);
58
+ const shown = matches.slice(0, limit);
59
+ return shown.length < matches.length
60
+ ? `${shown.join("\n")}\n[${matches.length - shown.length} more matches; refine the search]`
61
+ : shown.join("\n");
62
+ },
63
+ });
64
+ }
65
+ //# sourceMappingURL=search-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/search-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { anywhere, repositoryPath } from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { SearchInput } from \"./tools.types.ts\";\n\nexport function harnessSearchTools(): HarnessToolset {\n return defineHarnessToolset({ name: \"search\", tools: [searchTool()] });\n}\n\nfunction searchTool() {\n return defineHarnessTool({\n name: \"search\",\n description:\n \"Search repository files that are tracked or not ignored by Git for an extended regular expression. Returns path:line:text matches. A glob without a slash matches file names at any depth.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\", minLength: 1 },\n path: { type: \"string\" },\n glob: { type: \"string\", minLength: 1 },\n ignore_case: { type: \"boolean\" },\n max_results: {\n type: \"integer\",\n minimum: 1,\n maximum: TOOL_LIMITS.searchMatches,\n },\n },\n required: [\"pattern\"],\n additionalProperties: false,\n },\n resources: (input: SearchInput) => ({ paths: [input.path ?? \".\"] }),\n async execute(input: SearchInput, context) {\n const scope = repositoryPath(input.path ?? \".\") || \".\";\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"grep\",\n \"--untracked\",\n \"-n\",\n \"-I\",\n \"--no-color\",\n \"--full-name\",\n \"-E\",\n ...(input.ignore_case ? [\"-i\"] : []),\n \"-e\",\n input.pattern,\n \"--\",\n input.glob\n ? `:(glob)${scope === \".\" ? \"\" : `${scope}/`}${anywhere(input.glob)}`\n : scope,\n ],\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n if (result.status === 1) return \"No matches.\";\n if (result.status !== 0)\n return { content: result.stderr || \"git grep failed\", isError: true };\n const limit = input.max_results ?? TOOL_LIMITS.searchMatches;\n const matches = result.stdout.split(\"\\n\").filter(Boolean);\n const shown = matches.slice(0, limit);\n return shown.length < matches.length\n ? `${shown.join(\"\\n\")}\\n[${matches.length - shown.length} more matches; refine the search]`\n : shown.join(\"\\n\");\n },\n });\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { HarnessToolset } from "../../domain/tool.types.ts";
2
+ import type { ShellToolsOptions } from "./tools.types.ts";
3
+ export declare function harnessShellTools(options?: ShellToolsOptions): HarnessToolset;
@@ -0,0 +1,38 @@
1
+ import { positive } from "../../domain/errors.js";
2
+ import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
3
+ import { commandOutput } from "./sandbox-files.js";
4
+ import { TOOL_LIMITS } from "./tools.constants.js";
5
+ export function harnessShellTools(options = {}) {
6
+ const deadlineMs = positive(options.deadlineMs ?? TOOL_LIMITS.shellDeadlineMs, "Shell deadlineMs");
7
+ return defineHarnessToolset({
8
+ name: "shell",
9
+ tools: [
10
+ defineHarnessTool({
11
+ name: "shell",
12
+ description: "Run a POSIX shell command in the repository root and return its exit status, stdout and stderr. Commands have a deadline and no interactive input.",
13
+ input: {
14
+ type: "object",
15
+ properties: { command: { type: "string", minLength: 1 } },
16
+ required: ["command"],
17
+ additionalProperties: false,
18
+ },
19
+ resources: (input) => ({ command: input.command }),
20
+ async execute(input, context) {
21
+ const result = await context.sandbox.invoke({
22
+ executable: "sh",
23
+ arguments: ["-c", input.command],
24
+ stdin: "",
25
+ deadlineMs,
26
+ retain: TOOL_LIMITS.commandCharacters,
27
+ signal: context.signal,
28
+ });
29
+ return {
30
+ content: commandOutput(result),
31
+ isError: result.status !== 0,
32
+ };
33
+ },
34
+ }),
35
+ ],
36
+ });
37
+ }
38
+ //# sourceMappingURL=shell-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/shell-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,MAAM,UAAU,iBAAiB,CAC/B,UAA6B,EAAE;IAE/B,MAAM,UAAU,GAAG,QAAQ,CACzB,OAAO,CAAC,UAAU,IAAI,WAAW,CAAC,eAAe,EACjD,kBAAkB,CACnB,CAAC;IACF,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,iBAAiB,CAAC;gBAChB,IAAI,EAAE,OAAO;gBACb,WAAW,EACT,oJAAoJ;gBACtJ,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE;oBACzD,QAAQ,EAAE,CAAC,SAAS,CAAC;oBACrB,oBAAoB,EAAE,KAAK;iBAC5B;gBACD,SAAS,EAAE,CAAC,KAAiB,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC9D,KAAK,CAAC,OAAO,CAAC,KAAiB,EAAE,OAAO;oBACtC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;wBAC1C,UAAU,EAAE,IAAI;wBAChB,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;wBAChC,KAAK,EAAE,EAAE;wBACT,UAAU;wBACV,MAAM,EAAE,WAAW,CAAC,iBAAiB;wBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAC;oBACH,OAAO;wBACL,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC;wBAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;qBAC7B,CAAC;gBACJ,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { positive } from \"../../domain/errors.ts\";\nimport { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { commandOutput } from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { ShellInput, ShellToolsOptions } from \"./tools.types.ts\";\n\nexport function harnessShellTools(\n options: ShellToolsOptions = {},\n): HarnessToolset {\n const deadlineMs = positive(\n options.deadlineMs ?? TOOL_LIMITS.shellDeadlineMs,\n \"Shell deadlineMs\",\n );\n return defineHarnessToolset({\n name: \"shell\",\n tools: [\n defineHarnessTool({\n name: \"shell\",\n description:\n \"Run a POSIX shell command in the repository root and return its exit status, stdout and stderr. Commands have a deadline and no interactive input.\",\n input: {\n type: \"object\",\n properties: { command: { type: \"string\", minLength: 1 } },\n required: [\"command\"],\n additionalProperties: false,\n },\n resources: (input: ShellInput) => ({ command: input.command }),\n async execute(input: ShellInput, context) {\n const result = await context.sandbox.invoke({\n executable: \"sh\",\n arguments: [\"-c\", input.command],\n stdin: \"\",\n deadlineMs,\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n return {\n content: commandOutput(result),\n isError: result.status !== 0,\n };\n },\n }),\n ],\n });\n}\n"]}
@@ -0,0 +1,11 @@
1
+ export declare const TOOL_LIMITS: {
2
+ readonly readLines: 2000;
3
+ readonly fileBytes: number;
4
+ readonly binaryProbeBytes: 8000;
5
+ readonly listEntries: 1000;
6
+ readonly searchMatches: 200;
7
+ readonly commandCharacters: 200000;
8
+ readonly shellDeadlineMs: 120000;
9
+ };
10
+ export declare const GIT_READ_COMMANDS: readonly ["status", "diff", "log", "show"];
11
+ export declare const GIT_BLOCKED_OPTIONS: string[];
@@ -0,0 +1,17 @@
1
+ export const TOOL_LIMITS = {
2
+ readLines: 2_000,
3
+ fileBytes: 4 * 1024 * 1024,
4
+ binaryProbeBytes: 8_000,
5
+ listEntries: 1_000,
6
+ searchMatches: 200,
7
+ commandCharacters: 200_000,
8
+ shellDeadlineMs: 120_000,
9
+ };
10
+ export const GIT_READ_COMMANDS = ["status", "diff", "log", "show"];
11
+ export const GIT_BLOCKED_OPTIONS = [
12
+ "--output",
13
+ "--ext-diff",
14
+ "--textconv",
15
+ "--open-files-in-pager",
16
+ ];
17
+ //# sourceMappingURL=tools.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.constants.js","sourceRoot":"","sources":["../../../src/adapters/tools/tools.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IAC1B,gBAAgB,EAAE,KAAK;IACvB,WAAW,EAAE,KAAK;IAClB,aAAa,EAAE,GAAG;IAClB,iBAAiB,EAAE,OAAO;IAC1B,eAAe,EAAE,OAAO;CAChB,CAAC;AAEX,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAU,CAAC;AAE5E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,UAAU;IACV,YAAY;IACZ,YAAY;IACZ,uBAAuB;CACxB,CAAC","sourcesContent":["export const TOOL_LIMITS = {\n readLines: 2_000,\n fileBytes: 4 * 1024 * 1024,\n binaryProbeBytes: 8_000,\n listEntries: 1_000,\n searchMatches: 200,\n commandCharacters: 200_000,\n shellDeadlineMs: 120_000,\n} as const;\n\nexport const GIT_READ_COMMANDS = [\"status\", \"diff\", \"log\", \"show\"] as const;\n\nexport const GIT_BLOCKED_OPTIONS = [\n \"--output\",\n \"--ext-diff\",\n \"--textconv\",\n \"--open-files-in-pager\",\n];\n"]}