@geminixiang/mikan 1.0.0-beta.78 → 1.0.0-beta.79

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 (471) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/adapters/commands/admin.js +1 -1
  3. package/dist/adapters/commands/admin.js.map +1 -1
  4. package/dist/adapters/commands/login.d.ts.map +1 -1
  5. package/dist/adapters/commands/login.js +3 -2
  6. package/dist/adapters/commands/login.js.map +1 -1
  7. package/dist/adapters/commands/manifest.d.ts +0 -1
  8. package/dist/adapters/commands/manifest.d.ts.map +1 -1
  9. package/dist/adapters/commands/manifest.js.map +1 -1
  10. package/dist/adapters/commands/model.d.ts +0 -1
  11. package/dist/adapters/commands/model.d.ts.map +1 -1
  12. package/dist/adapters/commands/model.js +8 -20
  13. package/dist/adapters/commands/model.js.map +1 -1
  14. package/dist/adapters/commands/new.js +1 -1
  15. package/dist/adapters/commands/new.js.map +1 -1
  16. package/dist/adapters/commands/registry.js +1 -1
  17. package/dist/adapters/commands/registry.js.map +1 -1
  18. package/dist/adapters/commands/sandbox.d.ts +0 -1
  19. package/dist/adapters/commands/sandbox.d.ts.map +1 -1
  20. package/dist/adapters/commands/sandbox.js +1 -1
  21. package/dist/adapters/commands/sandbox.js.map +1 -1
  22. package/dist/adapters/commands/types.d.ts +6 -17
  23. package/dist/adapters/commands/types.d.ts.map +1 -1
  24. package/dist/adapters/commands/types.js.map +1 -1
  25. package/dist/adapters/commands/utils.d.ts +1 -1
  26. package/dist/adapters/commands/utils.d.ts.map +1 -1
  27. package/dist/adapters/commands/utils.js.map +1 -1
  28. package/dist/adapters/discord/bot.d.ts +4 -10
  29. package/dist/adapters/discord/bot.d.ts.map +1 -1
  30. package/dist/adapters/discord/bot.js +26 -22
  31. package/dist/adapters/discord/bot.js.map +1 -1
  32. package/dist/adapters/discord/components.d.ts +0 -1
  33. package/dist/adapters/discord/components.d.ts.map +1 -1
  34. package/dist/adapters/discord/components.js.map +1 -1
  35. package/dist/adapters/discord/context.d.ts +3 -3
  36. package/dist/adapters/discord/context.d.ts.map +1 -1
  37. package/dist/adapters/discord/context.js +1 -1
  38. package/dist/adapters/discord/context.js.map +1 -1
  39. package/dist/adapters/discord/types.d.ts +83 -1
  40. package/dist/adapters/discord/types.d.ts.map +1 -1
  41. package/dist/adapters/discord/types.js.map +1 -1
  42. package/dist/adapters/github/bot.d.ts +4 -5
  43. package/dist/adapters/github/bot.d.ts.map +1 -1
  44. package/dist/adapters/github/bot.js +10 -10
  45. package/dist/adapters/github/bot.js.map +1 -1
  46. package/dist/adapters/github/client.js +1 -1
  47. package/dist/adapters/github/client.js.map +1 -1
  48. package/dist/adapters/github/context.d.ts +3 -4
  49. package/dist/adapters/github/context.d.ts.map +1 -1
  50. package/dist/adapters/github/context.js +1 -2
  51. package/dist/adapters/github/context.js.map +1 -1
  52. package/dist/adapters/github/github-ops.d.ts +5 -6
  53. package/dist/adapters/github/github-ops.d.ts.map +1 -1
  54. package/dist/adapters/github/github-ops.js +1 -2
  55. package/dist/adapters/github/github-ops.js.map +1 -1
  56. package/dist/adapters/github/ids.d.ts +0 -3
  57. package/dist/adapters/github/ids.d.ts.map +1 -1
  58. package/dist/adapters/github/ids.js +0 -19
  59. package/dist/adapters/github/ids.js.map +1 -1
  60. package/dist/adapters/github/repo.d.ts +1 -1
  61. package/dist/adapters/github/repo.js.map +1 -1
  62. package/dist/adapters/github/tools/checks.d.ts +6 -4
  63. package/dist/adapters/github/tools/checks.d.ts.map +1 -1
  64. package/dist/adapters/github/tools/checks.js +4 -3
  65. package/dist/adapters/github/tools/checks.js.map +1 -1
  66. package/dist/adapters/github/tools/issue.d.ts +10 -8
  67. package/dist/adapters/github/tools/issue.d.ts.map +1 -1
  68. package/dist/adapters/github/tools/issue.js +4 -3
  69. package/dist/adapters/github/tools/issue.js.map +1 -1
  70. package/dist/adapters/github/tools/pr.d.ts +8 -6
  71. package/dist/adapters/github/tools/pr.d.ts.map +1 -1
  72. package/dist/adapters/github/tools/pr.js +4 -3
  73. package/dist/adapters/github/tools/pr.js.map +1 -1
  74. package/dist/adapters/github/tools/read.d.ts +9 -7
  75. package/dist/adapters/github/tools/read.d.ts.map +1 -1
  76. package/dist/adapters/github/tools/read.js +4 -3
  77. package/dist/adapters/github/tools/read.js.map +1 -1
  78. package/dist/adapters/github/tools/review-reply.d.ts +6 -4
  79. package/dist/adapters/github/tools/review-reply.d.ts.map +1 -1
  80. package/dist/adapters/github/tools/review-reply.js +4 -3
  81. package/dist/adapters/github/tools/review-reply.js.map +1 -1
  82. package/dist/adapters/github/tools/sync.d.ts +5 -3
  83. package/dist/adapters/github/tools/sync.d.ts.map +1 -1
  84. package/dist/adapters/github/tools/sync.js +4 -3
  85. package/dist/adapters/github/tools/sync.js.map +1 -1
  86. package/dist/adapters/github/types.d.ts +5 -4
  87. package/dist/adapters/github/types.d.ts.map +1 -1
  88. package/dist/adapters/github/types.js.map +1 -1
  89. package/dist/adapters/github/webhook.d.ts +0 -1
  90. package/dist/adapters/github/webhook.d.ts.map +1 -1
  91. package/dist/adapters/github/webhook.js.map +1 -1
  92. package/dist/adapters/intake.d.ts +1 -1
  93. package/dist/adapters/intake.d.ts.map +1 -1
  94. package/dist/adapters/intake.js.map +1 -1
  95. package/dist/adapters/markdown-tables.d.ts +0 -1
  96. package/dist/adapters/markdown-tables.d.ts.map +1 -1
  97. package/dist/adapters/markdown-tables.js.map +1 -1
  98. package/dist/adapters/messages.d.ts +1 -1
  99. package/dist/adapters/messages.d.ts.map +1 -1
  100. package/dist/adapters/messages.js.map +1 -1
  101. package/dist/adapters/progressive-renderer.d.ts +1 -1
  102. package/dist/adapters/progressive-renderer.d.ts.map +1 -1
  103. package/dist/adapters/progressive-renderer.js +8 -6
  104. package/dist/adapters/progressive-renderer.js.map +1 -1
  105. package/dist/adapters/shared.d.ts +6 -4
  106. package/dist/adapters/shared.d.ts.map +1 -1
  107. package/dist/adapters/shared.js +39 -25
  108. package/dist/adapters/shared.js.map +1 -1
  109. package/dist/adapters/slack/assistant.d.ts +0 -1
  110. package/dist/adapters/slack/assistant.d.ts.map +1 -1
  111. package/dist/adapters/slack/assistant.js +2 -1
  112. package/dist/adapters/slack/assistant.js.map +1 -1
  113. package/dist/adapters/slack/bot.d.ts +5 -10
  114. package/dist/adapters/slack/bot.d.ts.map +1 -1
  115. package/dist/adapters/slack/bot.js +84 -86
  116. package/dist/adapters/slack/bot.js.map +1 -1
  117. package/dist/adapters/slack/context.d.ts +3 -5
  118. package/dist/adapters/slack/context.d.ts.map +1 -1
  119. package/dist/adapters/slack/context.js +1 -2
  120. package/dist/adapters/slack/context.js.map +1 -1
  121. package/dist/adapters/slack/jev-context.d.ts.map +1 -1
  122. package/dist/adapters/slack/jev-context.js +4 -2
  123. package/dist/adapters/slack/jev-context.js.map +1 -1
  124. package/dist/adapters/slack/response-lifecycle.d.ts +3 -4
  125. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  126. package/dist/adapters/slack/response-lifecycle.js +5 -3
  127. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  128. package/dist/adapters/slack/session.d.ts +1 -1
  129. package/dist/adapters/slack/session.d.ts.map +1 -1
  130. package/dist/adapters/slack/session.js.map +1 -1
  131. package/dist/adapters/slack/task-intent.js +1 -1
  132. package/dist/adapters/slack/task-intent.js.map +1 -1
  133. package/dist/adapters/slack/task-status.d.ts.map +1 -1
  134. package/dist/adapters/slack/task-status.js +2 -1
  135. package/dist/adapters/slack/task-status.js.map +1 -1
  136. package/dist/adapters/slack/tool-pack.d.ts +0 -1
  137. package/dist/adapters/slack/tool-pack.d.ts.map +1 -1
  138. package/dist/adapters/slack/tool-pack.js +2 -1
  139. package/dist/adapters/slack/tool-pack.js.map +1 -1
  140. package/dist/adapters/slack/tools/blockkit.d.ts +9 -7
  141. package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -1
  142. package/dist/adapters/slack/tools/blockkit.js +6 -4
  143. package/dist/adapters/slack/tools/blockkit.js.map +1 -1
  144. package/dist/adapters/slack/types.d.ts +36 -2
  145. package/dist/adapters/slack/types.d.ts.map +1 -1
  146. package/dist/adapters/slack/types.js.map +1 -1
  147. package/dist/adapters/telegram/bot.d.ts +3 -8
  148. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  149. package/dist/adapters/telegram/bot.js +11 -11
  150. package/dist/adapters/telegram/bot.js.map +1 -1
  151. package/dist/adapters/telegram/context.d.ts +3 -3
  152. package/dist/adapters/telegram/context.d.ts.map +1 -1
  153. package/dist/adapters/telegram/context.js +2 -2
  154. package/dist/adapters/telegram/context.js.map +1 -1
  155. package/dist/adapters/telegram/types.d.ts +24 -1
  156. package/dist/adapters/telegram/types.d.ts.map +1 -1
  157. package/dist/adapters/telegram/types.js.map +1 -1
  158. package/dist/adapters/types.d.ts +1 -2
  159. package/dist/adapters/types.d.ts.map +1 -1
  160. package/dist/adapters/types.js.map +1 -1
  161. package/dist/adapters/web/admin/client-assets.d.ts +1 -1
  162. package/dist/adapters/web/admin/client-assets.d.ts.map +1 -1
  163. package/dist/adapters/web/admin/client-assets.js +3 -2
  164. package/dist/adapters/web/admin/client-assets.js.map +1 -1
  165. package/dist/adapters/web/admin/portal.d.ts +4 -11
  166. package/dist/adapters/web/admin/portal.d.ts.map +1 -1
  167. package/dist/adapters/web/admin/portal.js +27 -30
  168. package/dist/adapters/web/admin/portal.js.map +1 -1
  169. package/dist/adapters/web/admin/provider-models.d.ts +1 -1
  170. package/dist/adapters/web/admin/provider-models.d.ts.map +1 -1
  171. package/dist/adapters/web/admin/provider-models.js.map +1 -1
  172. package/dist/adapters/web/admin/types.d.ts +10 -4
  173. package/dist/adapters/web/admin/types.d.ts.map +1 -1
  174. package/dist/adapters/web/admin/types.js.map +1 -1
  175. package/dist/adapters/web/login/oauth.d.ts +0 -1
  176. package/dist/adapters/web/login/oauth.d.ts.map +1 -1
  177. package/dist/adapters/web/login/oauth.js +12 -12
  178. package/dist/adapters/web/login/oauth.js.map +1 -1
  179. package/dist/adapters/web/login/portal.d.ts +3 -6
  180. package/dist/adapters/web/login/portal.d.ts.map +1 -1
  181. package/dist/adapters/web/login/portal.js +5 -4
  182. package/dist/adapters/web/login/portal.js.map +1 -1
  183. package/dist/adapters/web/login/types.d.ts +1 -1
  184. package/dist/adapters/web/login/types.d.ts.map +1 -1
  185. package/dist/adapters/web/login/types.js.map +1 -1
  186. package/dist/adapters/web/portal-shell.d.ts +0 -1
  187. package/dist/adapters/web/portal-shell.d.ts.map +1 -1
  188. package/dist/adapters/web/portal-shell.js.map +1 -1
  189. package/dist/adapters/web/server.d.ts +6 -6
  190. package/dist/adapters/web/server.d.ts.map +1 -1
  191. package/dist/adapters/web/server.js +3 -2
  192. package/dist/adapters/web/server.js.map +1 -1
  193. package/dist/adapters/web/session-view/portal.d.ts +2 -3
  194. package/dist/adapters/web/session-view/portal.d.ts.map +1 -1
  195. package/dist/adapters/web/session-view/portal.js +12 -12
  196. package/dist/adapters/web/session-view/portal.js.map +1 -1
  197. package/dist/adapters/web/session-view/types.d.ts +1 -11
  198. package/dist/adapters/web/session-view/types.d.ts.map +1 -1
  199. package/dist/adapters/web/session-view/types.js.map +1 -1
  200. package/dist/adapters/web/token-store.d.ts +0 -1
  201. package/dist/adapters/web/token-store.d.ts.map +1 -1
  202. package/dist/adapters/web/token-store.js.map +1 -1
  203. package/dist/cli/boot.d.ts +0 -1
  204. package/dist/cli/boot.d.ts.map +1 -1
  205. package/dist/cli/boot.js +4 -4
  206. package/dist/cli/boot.js.map +1 -1
  207. package/dist/cli/office.d.ts.map +1 -1
  208. package/dist/cli/office.js +4 -3
  209. package/dist/cli/office.js.map +1 -1
  210. package/dist/cli/onboard.js +1 -1
  211. package/dist/cli/onboard.js.map +1 -1
  212. package/dist/cli/sandbox.d.ts.map +1 -1
  213. package/dist/cli/sandbox.js +2 -1
  214. package/dist/cli/sandbox.js.map +1 -1
  215. package/dist/cli/sessions.d.ts.map +1 -1
  216. package/dist/cli/sessions.js +2 -1
  217. package/dist/cli/sessions.js.map +1 -1
  218. package/dist/env-manifest.d.ts +1 -1
  219. package/dist/env-manifest.d.ts.map +1 -1
  220. package/dist/env-manifest.js.map +1 -1
  221. package/dist/events/index.d.ts +3 -2
  222. package/dist/events/index.d.ts.map +1 -1
  223. package/dist/events/index.js +11 -10
  224. package/dist/events/index.js.map +1 -1
  225. package/dist/events/scheduler.d.ts +1 -2
  226. package/dist/events/scheduler.d.ts.map +1 -1
  227. package/dist/events/scheduler.js +4 -4
  228. package/dist/events/scheduler.js.map +1 -1
  229. package/dist/file-guards.d.ts +8 -6
  230. package/dist/file-guards.d.ts.map +1 -1
  231. package/dist/file-guards.js +10 -15
  232. package/dist/file-guards.js.map +1 -1
  233. package/dist/harness/execution-env.d.ts +1 -1
  234. package/dist/harness/execution-env.d.ts.map +1 -1
  235. package/dist/harness/execution-env.js +7 -6
  236. package/dist/harness/execution-env.js.map +1 -1
  237. package/dist/harness/execution-resolver.d.ts +4 -6
  238. package/dist/harness/execution-resolver.d.ts.map +1 -1
  239. package/dist/harness/execution-resolver.js +1 -1
  240. package/dist/harness/execution-resolver.js.map +1 -1
  241. package/dist/harness/jev.d.ts +1 -1
  242. package/dist/harness/jev.d.ts.map +1 -1
  243. package/dist/harness/jev.js +1 -4
  244. package/dist/harness/jev.js.map +1 -1
  245. package/dist/harness/mcp-result.d.ts.map +1 -1
  246. package/dist/harness/mcp-result.js +15 -7
  247. package/dist/harness/mcp-result.js.map +1 -1
  248. package/dist/harness/mcp.d.ts +0 -2
  249. package/dist/harness/mcp.d.ts.map +1 -1
  250. package/dist/harness/mcp.js +13 -15
  251. package/dist/harness/mcp.js.map +1 -1
  252. package/dist/harness/models.d.ts +0 -1
  253. package/dist/harness/models.d.ts.map +1 -1
  254. package/dist/harness/models.js +2 -1
  255. package/dist/harness/models.js.map +1 -1
  256. package/dist/harness/open-connector.d.ts +2 -3
  257. package/dist/harness/open-connector.d.ts.map +1 -1
  258. package/dist/harness/open-connector.js +13 -9
  259. package/dist/harness/open-connector.js.map +1 -1
  260. package/dist/harness/presenter.d.ts +4 -25
  261. package/dist/harness/presenter.d.ts.map +1 -1
  262. package/dist/harness/presenter.js +26 -20
  263. package/dist/harness/presenter.js.map +1 -1
  264. package/dist/harness/prompt.d.ts +1 -2
  265. package/dist/harness/prompt.d.ts.map +1 -1
  266. package/dist/harness/prompt.js.map +1 -1
  267. package/dist/harness/runner.d.ts.map +1 -1
  268. package/dist/harness/runner.js +34 -17
  269. package/dist/harness/runner.js.map +1 -1
  270. package/dist/harness/session.d.ts +0 -7
  271. package/dist/harness/session.d.ts.map +1 -1
  272. package/dist/harness/session.js +16 -14
  273. package/dist/harness/session.js.map +1 -1
  274. package/dist/harness/skills.d.ts +2 -5
  275. package/dist/harness/skills.d.ts.map +1 -1
  276. package/dist/harness/skills.js.map +1 -1
  277. package/dist/harness/subagent-profiles.d.ts +0 -1
  278. package/dist/harness/subagent-profiles.d.ts.map +1 -1
  279. package/dist/harness/subagent-profiles.js +12 -16
  280. package/dist/harness/subagent-profiles.js.map +1 -1
  281. package/dist/harness/subagent.d.ts +1 -1
  282. package/dist/harness/subagent.d.ts.map +1 -1
  283. package/dist/harness/subagent.js +17 -17
  284. package/dist/harness/subagent.js.map +1 -1
  285. package/dist/harness/tool-args.d.ts +2 -0
  286. package/dist/harness/tool-args.d.ts.map +1 -0
  287. package/dist/harness/tool-args.js +20 -0
  288. package/dist/harness/tool-args.js.map +1 -0
  289. package/dist/harness/tools/attach.d.ts +5 -4
  290. package/dist/harness/tools/attach.d.ts.map +1 -1
  291. package/dist/harness/tools/attach.js +1 -1
  292. package/dist/harness/tools/attach.js.map +1 -1
  293. package/dist/harness/tools/event.d.ts +12 -11
  294. package/dist/harness/tools/event.d.ts.map +1 -1
  295. package/dist/harness/tools/event.js +1 -1
  296. package/dist/harness/tools/event.js.map +1 -1
  297. package/dist/harness/tools/generate-image.d.ts +7 -5
  298. package/dist/harness/tools/generate-image.d.ts.map +1 -1
  299. package/dist/harness/tools/generate-image.js +7 -5
  300. package/dist/harness/tools/generate-image.js.map +1 -1
  301. package/dist/harness/tools/host-fn-tool.d.ts +3 -2
  302. package/dist/harness/tools/host-fn-tool.d.ts.map +1 -1
  303. package/dist/harness/tools/host-fn-tool.js +5 -2
  304. package/dist/harness/tools/host-fn-tool.js.map +1 -1
  305. package/dist/harness/tools/index.d.ts +3 -4
  306. package/dist/harness/tools/index.d.ts.map +1 -1
  307. package/dist/harness/tools/index.js +1 -3
  308. package/dist/harness/tools/index.js.map +1 -1
  309. package/dist/harness/tools/jev-browser.d.ts +12 -10
  310. package/dist/harness/tools/jev-browser.d.ts.map +1 -1
  311. package/dist/harness/tools/jev-browser.js +6 -4
  312. package/dist/harness/tools/jev-browser.js.map +1 -1
  313. package/dist/harness/tools/jev.d.ts +9 -7
  314. package/dist/harness/tools/jev.d.ts.map +1 -1
  315. package/dist/harness/tools/jev.js +5 -6
  316. package/dist/harness/tools/jev.js.map +1 -1
  317. package/dist/harness/tools/pi-tools.d.ts.map +1 -1
  318. package/dist/harness/tools/pi-tools.js +2 -2
  319. package/dist/harness/tools/pi-tools.js.map +1 -1
  320. package/dist/harness/tools/react.d.ts +3 -2
  321. package/dist/harness/tools/react.d.ts.map +1 -1
  322. package/dist/harness/tools/react.js +1 -1
  323. package/dist/harness/tools/react.js.map +1 -1
  324. package/dist/harness/tools/sandbox.d.ts +7 -6
  325. package/dist/harness/tools/sandbox.d.ts.map +1 -1
  326. package/dist/harness/tools/sandbox.js +3 -2
  327. package/dist/harness/tools/sandbox.js.map +1 -1
  328. package/dist/harness/tools/subagent.d.ts +26 -26
  329. package/dist/harness/tools/subagent.d.ts.map +1 -1
  330. package/dist/harness/tools/subagent.js +25 -29
  331. package/dist/harness/tools/subagent.js.map +1 -1
  332. package/dist/harness/tools/task.d.ts +11 -8
  333. package/dist/harness/tools/task.d.ts.map +1 -1
  334. package/dist/harness/tools/task.js +8 -6
  335. package/dist/harness/tools/task.js.map +1 -1
  336. package/dist/harness/tools/types.d.ts +2 -1
  337. package/dist/harness/tools/types.d.ts.map +1 -1
  338. package/dist/harness/tools/types.js.map +1 -1
  339. package/dist/harness/types.d.ts +37 -4
  340. package/dist/harness/types.d.ts.map +1 -1
  341. package/dist/harness/types.js.map +1 -1
  342. package/dist/index.d.ts +16 -13
  343. package/dist/index.d.ts.map +1 -1
  344. package/dist/index.js +3 -2
  345. package/dist/index.js.map +1 -1
  346. package/dist/log.d.ts +0 -1
  347. package/dist/log.d.ts.map +1 -1
  348. package/dist/log.js +1 -1
  349. package/dist/log.js.map +1 -1
  350. package/dist/main.js +27 -17
  351. package/dist/main.js.map +1 -1
  352. package/dist/memory-capture/index.d.ts +1 -2
  353. package/dist/memory-capture/index.d.ts.map +1 -1
  354. package/dist/memory-capture/index.js +8 -3
  355. package/dist/memory-capture/index.js.map +1 -1
  356. package/dist/memory-capture/types.d.ts +1 -1
  357. package/dist/memory-capture/types.js.map +1 -1
  358. package/dist/observability/index.d.ts +0 -3
  359. package/dist/observability/index.d.ts.map +1 -1
  360. package/dist/observability/index.js +11 -16
  361. package/dist/observability/index.js.map +1 -1
  362. package/dist/observability/sentry.d.ts +9 -12
  363. package/dist/observability/sentry.d.ts.map +1 -1
  364. package/dist/observability/sentry.js +9 -118
  365. package/dist/observability/sentry.js.map +1 -1
  366. package/dist/office/index.d.ts +14 -3
  367. package/dist/office/index.d.ts.map +1 -1
  368. package/dist/office/index.js +51 -14
  369. package/dist/office/index.js.map +1 -1
  370. package/dist/office/projection.d.ts +1 -3
  371. package/dist/office/projection.d.ts.map +1 -1
  372. package/dist/office/projection.js +5 -5
  373. package/dist/office/projection.js.map +1 -1
  374. package/dist/office/types.d.ts +5 -0
  375. package/dist/office/types.d.ts.map +1 -1
  376. package/dist/office/types.js.map +1 -1
  377. package/dist/runtime/conversation-runtime.d.ts +0 -1
  378. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  379. package/dist/runtime/conversation-runtime.js +10 -6
  380. package/dist/runtime/conversation-runtime.js.map +1 -1
  381. package/dist/runtime/session-lifecycle.d.ts.map +1 -1
  382. package/dist/runtime/session-lifecycle.js +2 -1
  383. package/dist/runtime/session-lifecycle.js.map +1 -1
  384. package/dist/runtime/types.d.ts +8 -5
  385. package/dist/runtime/types.d.ts.map +1 -1
  386. package/dist/runtime/types.js.map +1 -1
  387. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  388. package/dist/sandbox/cloudflare.js +3 -2
  389. package/dist/sandbox/cloudflare.js.map +1 -1
  390. package/dist/sandbox/container.d.ts.map +1 -1
  391. package/dist/sandbox/container.js +2 -1
  392. package/dist/sandbox/container.js.map +1 -1
  393. package/dist/sandbox/host.js +1 -1
  394. package/dist/sandbox/host.js.map +1 -1
  395. package/dist/sandbox/identity.d.ts +0 -1
  396. package/dist/sandbox/identity.d.ts.map +1 -1
  397. package/dist/sandbox/identity.js.map +1 -1
  398. package/dist/sandbox/index.d.ts +4 -14
  399. package/dist/sandbox/index.d.ts.map +1 -1
  400. package/dist/sandbox/index.js +4 -93
  401. package/dist/sandbox/index.js.map +1 -1
  402. package/dist/sandbox/provisioner.d.ts +0 -1
  403. package/dist/sandbox/provisioner.d.ts.map +1 -1
  404. package/dist/sandbox/provisioner.js +12 -11
  405. package/dist/sandbox/provisioner.js.map +1 -1
  406. package/dist/sandbox/registry.d.ts +12 -0
  407. package/dist/sandbox/registry.d.ts.map +1 -0
  408. package/dist/sandbox/registry.js +93 -0
  409. package/dist/sandbox/registry.js.map +1 -0
  410. package/dist/sandbox/types.d.ts +3 -0
  411. package/dist/sandbox/types.d.ts.map +1 -1
  412. package/dist/sandbox/types.js.map +1 -1
  413. package/dist/sandbox/utils.d.ts.map +1 -1
  414. package/dist/sandbox/utils.js +1 -0
  415. package/dist/sandbox/utils.js.map +1 -1
  416. package/dist/sessions/chat-history-sync.d.ts +2 -2
  417. package/dist/sessions/chat-history-sync.d.ts.map +1 -1
  418. package/dist/sessions/chat-history-sync.js +32 -23
  419. package/dist/sessions/chat-history-sync.js.map +1 -1
  420. package/dist/sessions/migrate-common.js +2 -2
  421. package/dist/sessions/migrate-common.js.map +1 -1
  422. package/dist/sessions/migrate-pi-084.d.ts +0 -1
  423. package/dist/sessions/migrate-pi-084.d.ts.map +1 -1
  424. package/dist/sessions/migrate-pi-084.js +4 -6
  425. package/dist/sessions/migrate-pi-084.js.map +1 -1
  426. package/dist/sessions/migrate-v3.d.ts +0 -1
  427. package/dist/sessions/migrate-v3.d.ts.map +1 -1
  428. package/dist/sessions/migrate-v3.js +3 -5
  429. package/dist/sessions/migrate-v3.js.map +1 -1
  430. package/dist/sessions/session-key.d.ts +0 -1
  431. package/dist/sessions/session-key.d.ts.map +1 -1
  432. package/dist/sessions/session-key.js.map +1 -1
  433. package/dist/sessions/session-store.d.ts.map +1 -1
  434. package/dist/sessions/session-store.js +12 -19
  435. package/dist/sessions/session-store.js.map +1 -1
  436. package/dist/sessions/store.d.ts +0 -1
  437. package/dist/sessions/store.d.ts.map +1 -1
  438. package/dist/sessions/store.js +5 -3
  439. package/dist/sessions/store.js.map +1 -1
  440. package/dist/sessions/types.d.ts +2 -0
  441. package/dist/sessions/types.d.ts.map +1 -1
  442. package/dist/sessions/types.js +1 -0
  443. package/dist/sessions/types.js.map +1 -1
  444. package/dist/settings/apply.d.ts +1 -2
  445. package/dist/settings/apply.d.ts.map +1 -1
  446. package/dist/settings/apply.js.map +1 -1
  447. package/dist/settings/index.d.ts +37 -34
  448. package/dist/settings/index.d.ts.map +1 -1
  449. package/dist/settings/index.js +28 -22
  450. package/dist/settings/index.js.map +1 -1
  451. package/dist/settings/migrate.d.ts +1 -1
  452. package/dist/settings/migrate.d.ts.map +1 -1
  453. package/dist/settings/migrate.js +5 -4
  454. package/dist/settings/migrate.js.map +1 -1
  455. package/dist/types.d.ts +17 -6
  456. package/dist/types.d.ts.map +1 -1
  457. package/dist/types.js +1 -3
  458. package/dist/types.js.map +1 -1
  459. package/dist/unknown-values.d.ts +3 -0
  460. package/dist/unknown-values.d.ts.map +1 -0
  461. package/dist/unknown-values.js +7 -0
  462. package/dist/unknown-values.js.map +1 -0
  463. package/dist/vault/index.d.ts +10 -2
  464. package/dist/vault/index.d.ts.map +1 -1
  465. package/dist/vault/index.js +16 -7
  466. package/dist/vault/index.js.map +1 -1
  467. package/package.json +3 -2
  468. package/dist/adapters/index.d.ts +0 -11
  469. package/dist/adapters/index.d.ts.map +0 -1
  470. package/dist/adapters/index.js +0 -19
  471. package/dist/adapters/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"file-guards.js","sourceRoot":"","sources":["../src/file-guards.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,EACL,SAAS,EACT,SAAS,IAAI,WAAW,EACxB,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,UAAU,EACV,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnE,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,QAAwC,EACxC,gBAA4C;IAE5C,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,IAAY,EACZ,MAAS,EACT,gBAA4C;IAE5C,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,gBAA4C;IAC1E,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,QAAwC,EACxC,gBAA4C;IAE5C,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAChD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,GAAW,EACX,MAAS,EACT,gBAA4C;IAE5C,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QACjC,IAAI,UAAyD,CAAC;QAC9D,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;YAC/C,UAAU,GAAG,GAAG,CAAC;YACjB,MAAM;QACR,CAAC;QACD,MAAM,MAAM,GACV,CAAC,UAAU,IAAI,UAAU,CAAC,IAAI,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,KAAK,GAAG;YAC9D,CAAC,CAAC,uBAAuB;YACzB,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,OAAe;IACxE,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAClB,GAAG,EACH,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAChF,CAAC;IACF,MAAM,EAAE,GAAG,QAAQ,CACjB,OAAO,EACP,WAAW,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,MAAM,EAC/D,iBAAiB,CAClB,CAAC;IACF,IAAI,CAAC;QACH,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACH,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,MAAc;IACjD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,SAAS,KAAK,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,QAAgB,EAChB,UAAkB,EAClB,WAAmB;IAEnB,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC;QAAE,OAAO;IAChD,MAAM,OAAO,GACX,gBAAgB,QAAQ,+CAA+C,UAAU,KAAK;QACtF,0EAA0E;QAC1E,mFAAmF,CAAC;IACtF,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAC3B,GAAG,CAAC,UAAU,CAAC,6BAA6B,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["import type { Static, TSchema } from \"@sinclair/typebox\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport {\n closeSync,\n constants as fsConstants,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport * as log from \"./log.js\";\nimport { randomBytes } from \"node:crypto\";\nimport { basename, dirname, join } from \"node:path\";\n\nexport function ensureDirExists(dir: string): void {\n mkdirSync(dir, { recursive: true });\n}\n\nexport function readTextFileIfExists(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf-8\");\n } catch (err) {\n if (err instanceof Error && \"code\" in err && err.code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n}\n\nexport function readJsonFileIfExists<T>(\n path: string,\n validate: (value: unknown) => value is T,\n malformedMessage: (detail: string) => string,\n): T | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonValue(raw, validate, malformedMessage);\n}\n\nexport function readJsonSchemaFileIfExists<T extends TSchema>(\n path: string,\n schema: T,\n malformedMessage: (detail: string) => string,\n): Static<T> | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonSchemaValue(raw, schema, malformedMessage);\n}\n\nfunction parseJson(raw: string, malformedMessage: (detail: string) => string): unknown {\n try {\n return JSON.parse(raw);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(malformedMessage(detail), { cause: err });\n }\n}\n\nexport function parseJsonValue<T>(\n raw: string,\n validate: (value: unknown) => value is T,\n malformedMessage: (detail: string) => string,\n): T {\n const parsed = parseJson(raw, malformedMessage);\n if (!validate(parsed)) {\n throw new Error(malformedMessage(\"unexpected JSON shape\"));\n }\n return parsed;\n}\n\nexport function parseJsonSchemaValue<T extends TSchema>(\n raw: string,\n schema: T,\n malformedMessage: (detail: string) => string,\n): Static<T> {\n const parsed = parseJson(raw, malformedMessage);\n if (!Value.Check(schema, parsed)) {\n let firstError: { path: string; message: string } | undefined;\n for (const err of Value.Errors(schema, parsed)) {\n firstError = err;\n break;\n }\n const detail =\n !firstError || firstError.path === \"\" || firstError.path === \"/\"\n ? \"unexpected JSON shape\"\n : `${firstError.path}: ${firstError.message}`;\n throw new Error(malformedMessage(detail));\n }\n return parsed;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nconst PRIVATE_FILE_MODE = 0o600;\n\nexport function atomicWritePrivateFile(targetPath: string, content: string): void {\n const dir = dirname(targetPath);\n const tmpPath = join(\n dir,\n `.${basename(targetPath)}.${process.pid}.${randomBytes(8).toString(\"hex\")}.tmp`,\n );\n const fd = openSync(\n tmpPath,\n fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL,\n PRIVATE_FILE_MODE,\n );\n try {\n writeSync(fd, content);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {}\n throw err;\n } finally {\n closeSync(fd);\n }\n try {\n renameSync(tmpPath, targetPath);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {}\n throw err;\n }\n}\n\nfunction isPathInside(child: string, parent: string): boolean {\n const parentPath = resolve(parent);\n const childPath = resolve(child);\n return childPath === parentPath || childPath.startsWith(parentPath + \"/\");\n}\n\nexport function assertStateDirOutsideWorkspace(\n stateDir: string,\n workingDir: string,\n sandboxType: string,\n): void {\n if (!isPathInside(stateDir, workingDir)) return;\n const message =\n `--state-dir (${stateDir}) must not be inside the working directory (${workingDir}): ` +\n `sandbox containers mount the working directory, and a mounted state dir ` +\n `would expose settings, office records, vaults, and credentials to sandboxed code.`;\n if (sandboxType === \"host\") {\n log.logWarning(\"Insecure state dir location\", message);\n return;\n }\n throw new Error(message);\n}\n"]}
1
+ {"version":3,"file":"file-guards.js","sourceRoot":"","sources":["../src/file-guards.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Static, TSchema } from \"typebox\";\nimport { Value } from \"typebox/value\";\nimport {\n closeSync,\n constants as fsConstants,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport * as log from \"./log.js\";\nimport { randomBytes } from \"node:crypto\";\nimport { basename, dirname, join } from \"node:path\";\nimport { errorMessage } from \"./unknown-values.js\";\n\ntype JsonFailureKind = \"syntax\" | \"shape\" | \"field\";\n\ntype MalformedJsonMessage = (detail: string, kind: JsonFailureKind) => string;\n\nconst UNEXPECTED_JSON_SHAPE = \"unexpected JSON shape\";\n\nexport function ensureDirExists(dir: string): void {\n mkdirSync(dir, { recursive: true });\n}\n\nexport function readTextFileIfExists(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf-8\");\n } catch (err) {\n if (err instanceof Error && \"code\" in err && err.code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n}\n\nexport function readJsonFileIfExists<T>(\n path: string,\n validate: (value: unknown) => value is T,\n malformedMessage: MalformedJsonMessage,\n): T | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonValue(raw, validate, malformedMessage);\n}\n\nexport function readJsonSchemaFileIfExists<T extends TSchema>(\n path: string,\n schema: T,\n malformedMessage: MalformedJsonMessage,\n): Static<T> | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonSchemaValue(raw, schema, malformedMessage);\n}\n\nfunction parseJson(raw: string, malformedMessage: MalformedJsonMessage): unknown {\n try {\n return JSON.parse(raw);\n } catch (err) {\n const detail = errorMessage(err);\n throw new Error(malformedMessage(detail, \"syntax\"), { cause: err });\n }\n}\n\nexport function parseJsonValue<T>(\n raw: string,\n validate: (value: unknown) => value is T,\n malformedMessage: MalformedJsonMessage,\n): T {\n const parsed = parseJson(raw, malformedMessage);\n if (!validate(parsed)) {\n throw new Error(malformedMessage(UNEXPECTED_JSON_SHAPE, \"shape\"));\n }\n return parsed;\n}\n\nexport function parseJsonSchemaValue<T extends TSchema>(\n raw: string,\n schema: T,\n malformedMessage: MalformedJsonMessage,\n): Static<T> {\n const parsed = parseJson(raw, malformedMessage);\n if (!Value.Check(schema, parsed)) {\n const firstError = Value.Errors(schema, parsed)[0];\n if (!firstError || firstError.instancePath === \"\" || firstError.instancePath === \"/\") {\n throw new Error(malformedMessage(UNEXPECTED_JSON_SHAPE, \"shape\"));\n }\n throw new Error(malformedMessage(`${firstError.instancePath}: ${firstError.message}`, \"field\"));\n }\n return parsed;\n}\n\nconst PRIVATE_FILE_MODE = 0o600;\n\nexport function atomicWritePrivateFile(targetPath: string, content: string): void {\n const dir = dirname(targetPath);\n const tmpPath = join(\n dir,\n `.${basename(targetPath)}.${process.pid}.${randomBytes(8).toString(\"hex\")}.tmp`,\n );\n const fd = openSync(\n tmpPath,\n fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL,\n PRIVATE_FILE_MODE,\n );\n try {\n writeSync(fd, content);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {}\n throw err;\n } finally {\n closeSync(fd);\n }\n try {\n renameSync(tmpPath, targetPath);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {}\n throw err;\n }\n}\n\nfunction isPathInside(child: string, parent: string): boolean {\n const parentPath = resolve(parent);\n const childPath = resolve(child);\n return childPath === parentPath || childPath.startsWith(parentPath + \"/\");\n}\n\nexport function assertStateDirOutsideWorkspace(\n stateDir: string,\n workingDir: string,\n sandboxType: string,\n): void {\n if (!isPathInside(stateDir, workingDir)) return;\n const message =\n `--state-dir (${stateDir}) must not be inside the working directory (${workingDir}): ` +\n `sandbox containers mount the working directory, and a mounted state dir ` +\n `would expose settings, office records, vaults, and credentials to sandboxed code.`;\n if (sandboxType === \"host\") {\n log.logWarning(\"Insecure state dir location\", message);\n return;\n }\n throw new Error(message);\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  import { type ExecutionEnv } from "@earendil-works/pi-agent-core";
2
- import type { Executor, SandboxConfig } from "../sandbox/index.js";
2
+ import type { Executor, SandboxConfig } from "../sandbox/types.js";
3
3
  export declare function createSandboxExecutionEnv(executor: Executor, sandboxType: SandboxConfig["type"], runtimeWorkspaceRoot: string): ExecutionEnv;
4
4
  //# sourceMappingURL=execution-env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"execution-env.d.ts","sourceRoot":"","sources":["../../src/harness/execution-env.ts"],"names":[],"mappings":"AAEA,OAAO,EAUL,KAAK,YAAY,EAQlB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKnE,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,EAClC,oBAAoB,EAAE,MAAM,GAC3B,YAAY,CAKd"}
1
+ {"version":3,"file":"execution-env.d.ts","sourceRoot":"","sources":["../../src/harness/execution-env.ts"],"names":[],"mappings":"AAEA,OAAO,EAUL,KAAK,YAAY,EAQlB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMnE,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,EAClC,oBAAoB,EAAE,MAAM,GAC3B,YAAY,CAKd"}
@@ -3,6 +3,7 @@ import { posix } from "node:path";
3
3
  import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, ExecutionError, FileError, err, ok, truncateHead, truncateTail, } from "@earendil-works/pi-agent-core";
4
4
  import { NodeExecutionEnv } from "@earendil-works/pi-agent-core/node";
5
5
  import { execAppendFile, execWriteFile, shellEscape } from "../sandbox/utils.js";
6
+ import { errorMessage } from "../unknown-values.js";
6
7
  const SPILL_DIR = ".mikan/bash-output";
7
8
  export function createSandboxExecutionEnv(executor, sandboxType, runtimeWorkspaceRoot) {
8
9
  if (sandboxType === "host") {
@@ -137,8 +138,8 @@ class ShellExecutionEnv {
137
138
  async exec(command, options, context) {
138
139
  try {
139
140
  const result = await this.executor.exec(command, {
140
- ...(options?.cwd ? { cwd: options.cwd } : {}),
141
- ...(options?.timeout ? { timeout: options.timeout } : {}),
141
+ cwd: options?.cwd || undefined,
142
+ timeout: options?.timeout || undefined,
142
143
  signal: context.abortSignal,
143
144
  });
144
145
  const combined = [result.stdout, result.stderr].filter((part) => part.length > 0).join("\n");
@@ -214,12 +215,12 @@ function shellOutputMetadata(truncation, spillPath) {
214
215
  const lastLine = truncation.content.split("\n").at(-1) ?? "";
215
216
  return {
216
217
  truncation: metadata,
217
- ...(spillPath ? { spillPath } : {}),
218
- ...(truncation.lastLinePartial ? { lastLineBytes: Buffer.byteLength(lastLine, "utf8") } : {}),
218
+ spillPath: spillPath || undefined,
219
+ lastLineBytes: truncation.lastLinePartial ? Buffer.byteLength(lastLine, "utf8") : undefined,
219
220
  };
220
221
  }
221
222
  function toFileError(error) {
222
- const message = error instanceof Error ? error.message : String(error);
223
+ const message = errorMessage(error);
223
224
  if (/aborted/i.test(message))
224
225
  return new FileError("aborted", message);
225
226
  if (/no such file|not found/i.test(message))
@@ -233,7 +234,7 @@ function toFileError(error) {
233
234
  return new FileError("unknown", message, undefined, error instanceof Error ? error : undefined);
234
235
  }
235
236
  function toExecutionError(error, context) {
236
- const message = error instanceof Error ? error.message : String(error);
237
+ const message = errorMessage(error);
237
238
  if (context.abortSignal?.aborted || /aborted/i.test(message)) {
238
239
  return new ExecutionError("aborted", message);
239
240
  }
@@ -1 +1 @@
1
- {"version":3,"file":"execution-env.js","sourceRoot":"","sources":["../../src/harness/execution-env.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { posix } from \"node:path\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n ExecutionError,\n FileError,\n err,\n ok,\n truncateHead,\n truncateTail,\n type Context,\n type ExecutionEnv,\n type FileInfo,\n type FileKind,\n type Result,\n type ShellExecOptions,\n type ShellExecResult,\n type ShellOutputMetadata,\n type TruncationResult,\n} from \"@earendil-works/pi-agent-core\";\nimport { NodeExecutionEnv } from \"@earendil-works/pi-agent-core/node\";\nimport type { Executor, SandboxConfig } from \"../sandbox/index.js\";\nimport { execAppendFile, execWriteFile, shellEscape } from \"../sandbox/utils.js\";\n\nconst SPILL_DIR = \".mikan/bash-output\";\n\nexport function createSandboxExecutionEnv(\n executor: Executor,\n sandboxType: SandboxConfig[\"type\"],\n runtimeWorkspaceRoot: string,\n): ExecutionEnv {\n if (sandboxType === \"host\") {\n return new NodeExecutionEnv({ cwd: runtimeWorkspaceRoot });\n }\n return new ShellExecutionEnv(executor, runtimeWorkspaceRoot);\n}\n\ntype TextLineReader =\n Awaited<ReturnType<ExecutionEnv[\"openTextLineReader\"]>> extends Result<infer T, FileError>\n ? T\n : never;\ntype TextLine =\n Awaited<ReturnType<TextLineReader[\"readLine\"]>> extends Result<infer T, FileError>\n ? Exclude<T, undefined>\n : never;\n\nclass ShellExecutionEnv implements ExecutionEnv {\n readonly cwd: string;\n\n constructor(\n private readonly executor: Executor,\n runtimeWorkspaceRoot: string,\n ) {\n this.cwd = runtimeWorkspaceRoot;\n }\n\n async absolutePath(path: string, _context: Context): Promise<Result<string, FileError>> {\n return ok(posix.isAbsolute(path) ? posix.normalize(path) : posix.resolve(this.cwd, path));\n }\n\n async joinPath(parts: string[], _context: Context): Promise<Result<string, FileError>> {\n return ok(posix.join(...parts));\n }\n\n readTextFile(path: string, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(() => this.executor.readFile(path, this.execOptions(context)));\n }\n\n openTextLineReader(path: string, context: Context): Promise<Result<TextLineReader, FileError>> {\n return this.fileOp(async () => {\n const content = await this.executor.readFile(path, this.execOptions(context));\n return new ShellTextLineReader(content);\n });\n }\n\n async readBinaryFile(path: string, context: Context): Promise<Result<Uint8Array, FileError>> {\n return this.fileOp(async () =>\n Buffer.from(await this.executor.readFileBase64(path, this.execOptions(context)), \"base64\"),\n );\n }\n\n readTextLines(\n path: string,\n options: { maxLines?: number } | undefined,\n context: Context,\n ): Promise<Result<string[], FileError>> {\n return this.fileOp(async () => {\n const max = options?.maxLines;\n const command =\n max === undefined\n ? `cat ${shellEscape(path)}`\n : `head -n ${Math.max(0, Math.floor(max))} ${shellEscape(path)}`;\n const { stdout } = await this.run(command, context);\n const lines = stdout.split(\"\\n\");\n if (lines.at(-1) === \"\") lines.pop();\n return lines;\n });\n }\n\n writeFile(\n path: string,\n content: string | Uint8Array,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(() =>\n execWriteFile(this.executor, path, content, this.execOptions(context)),\n );\n }\n\n appendFile(\n path: string,\n content: string | Uint8Array,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(() =>\n execAppendFile(this.executor, path, content, this.execOptions(context)),\n );\n }\n\n renameFile(\n sourcePath: string,\n destinationPath: string,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n await this.run(`mv -f ${shellEscape(sourcePath)} ${shellEscape(destinationPath)}`, context);\n });\n }\n\n fileInfo(path: string, context: Context): Promise<Result<FileInfo, FileError>> {\n return this.fileOp(async () => {\n const escaped = shellEscape(path);\n const probe = await this.executor.exec(\n `if [ -L ${escaped} ]; then printf 'symlink'; elif [ -d ${escaped} ]; then printf 'directory'; ` +\n `elif [ -f ${escaped} ]; then printf 'file'; else exit 1; fi`,\n this.execOptions(context),\n );\n if (probe.code !== 0) throw new Error(`No such file or directory: ${path}`);\n const kind = probe.stdout.trim() as FileKind;\n let size = 0;\n if (kind === \"file\") {\n const stat = await this.executor.exec(`wc -c < ${escaped}`, this.execOptions(context));\n if (stat.code === 0) size = Number.parseInt(stat.stdout.trim(), 10) || 0;\n }\n let mtimeMs = 0;\n const mtime = await this.executor.exec(`date -r ${escaped} +%s`, this.execOptions(context));\n if (mtime.code === 0) mtimeMs = (Number.parseInt(mtime.stdout.trim(), 10) || 0) * 1000;\n return { name: posix.basename(path), path, kind, size, mtimeMs };\n });\n }\n\n async listDir(path: string, context: Context): Promise<Result<FileInfo[], FileError>> {\n return this.fileOp(async () => {\n const { stdout } = await this.run(`ls -A ${shellEscape(path)}`, context);\n const names = stdout.split(\"\\n\").filter(Boolean).toSorted();\n const entries: FileInfo[] = [];\n for (const name of names) {\n const child = posix.join(path, name);\n const info = await this.fileInfo(child, context);\n if (info.ok) entries.push(info.value);\n }\n return entries;\n });\n }\n\n canonicalPath(path: string, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(async () =>\n (await this.run(`realpath ${shellEscape(path)}`, context)).stdout.trim(),\n );\n }\n\n async exists(path: string, context: Context): Promise<Result<boolean, FileError>> {\n try {\n const result = await this.executor.exec(\n `test -e ${shellEscape(path)}`,\n this.execOptions(context),\n );\n return ok(result.code === 0);\n } catch (error) {\n return err(toFileError(error));\n }\n }\n\n createDir(\n path: string,\n options: { recursive?: boolean } | undefined,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n const flag = options?.recursive === false ? \"\" : \"-p \";\n await this.run(`mkdir ${flag}${shellEscape(path)}`, context);\n });\n }\n\n remove(\n path: string,\n options: { recursive?: boolean; force?: boolean } | undefined,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n const recursive = options?.recursive ? \"-r\" : \"\";\n const force = options?.force ? \"-f\" : \"\";\n await this.run(`rm ${recursive} ${force} ${shellEscape(path)}`, context);\n });\n }\n\n createTempDir(prefix: string | undefined, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(async () => {\n const template = prefix === undefined ? \"\" : shellEscape(`${prefix}XXXXXX`);\n const { stdout } = await this.run(`mktemp -d ${template}`.trim(), context);\n return stdout.trim();\n });\n }\n\n createTempFile(\n options: { prefix?: string; suffix?: string } | undefined,\n context: Context,\n ): Promise<Result<string, FileError>> {\n return this.fileOp(async () => {\n const template =\n options?.prefix === undefined && options?.suffix === undefined\n ? \"\"\n : shellEscape(`${options?.prefix ?? \"\"}XXXXXX${options?.suffix ?? \"\"}`);\n const { stdout } = await this.run(`mktemp ${template}`.trim(), context);\n return stdout.trim();\n });\n }\n\n async cleanup(_context: Context): Promise<void> {}\n\n async exec(\n command: string,\n options: ShellExecOptions | undefined,\n context: Context,\n ): Promise<Result<ShellExecResult, ExecutionError>> {\n try {\n const result = await this.executor.exec(command, {\n ...(options?.cwd ? { cwd: options.cwd } : {}),\n ...(options?.timeout ? { timeout: options.timeout } : {}),\n signal: context.abortSignal,\n });\n const combined = [result.stdout, result.stderr].filter((part) => part.length > 0).join(\"\\n\");\n const limits = options?.capture?.limits ?? {\n maxBytes: DEFAULT_MAX_BYTES,\n maxLines: DEFAULT_MAX_LINES,\n retain: \"tail\" as const,\n };\n const truncation =\n limits.retain === \"head\"\n ? truncateHead(combined, { maxLines: limits.maxLines, maxBytes: limits.maxBytes })\n : truncateTail(combined, { maxLines: limits.maxLines, maxBytes: limits.maxBytes });\n\n let spillPath: string | undefined;\n if (options?.capture?.spill && truncation.truncated) {\n try {\n spillPath = posix.join(this.cwd, SPILL_DIR, `${randomBytes(8).toString(\"hex\")}.log`);\n await this.executor.writeFile(spillPath, combined, this.execOptions(context));\n } catch {\n spillPath = undefined;\n }\n }\n\n const metadata = shellOutputMetadata(truncation, spillPath);\n options?.onUpdate?.(\n { kind: \"replace\", output: { text: truncation.content, ...metadata } },\n context,\n );\n return ok({ exitCode: result.code, ...metadata });\n } catch (error) {\n return err(toExecutionError(error, context));\n }\n }\n\n private execOptions(context: Context): { signal: AbortSignal | undefined } {\n return { signal: context.abortSignal };\n }\n\n private async run(\n command: string,\n context: Context,\n ): Promise<{ stdout: string; stderr: string }> {\n const result = await this.executor.exec(command, this.execOptions(context));\n if (result.code !== 0) {\n throw new Error(result.stderr.trim() || `Command failed (${result.code}): ${command}`);\n }\n return result;\n }\n\n private async fileOp<T>(op: () => Promise<T>): Promise<Result<T, FileError>> {\n try {\n return ok(await op());\n } catch (error) {\n return err(toFileError(error));\n }\n }\n}\n\nclass ShellTextLineReader implements TextLineReader {\n private offset = 0;\n\n constructor(private readonly content: string) {}\n\n async readLine(_context: Context): Promise<Result<TextLine | undefined, FileError>> {\n if (this.offset >= this.content.length) return ok(undefined);\n const newline = this.content.indexOf(\"\\n\", this.offset);\n if (newline === -1) {\n const text = this.content.slice(this.offset);\n this.offset = this.content.length;\n return ok({ text, terminated: false });\n }\n const text = this.content.slice(this.offset, newline);\n this.offset = newline + 1;\n return ok({ text, terminated: true });\n }\n\n async close(_context: Context): Promise<void> {\n this.offset = this.content.length;\n }\n}\n\nfunction shellOutputMetadata(\n truncation: TruncationResult,\n spillPath: string | undefined,\n): ShellOutputMetadata {\n const { content: _content, ...metadata } = truncation;\n const lastLine = truncation.content.split(\"\\n\").at(-1) ?? \"\";\n return {\n truncation: metadata,\n ...(spillPath ? { spillPath } : {}),\n ...(truncation.lastLinePartial ? { lastLineBytes: Buffer.byteLength(lastLine, \"utf8\") } : {}),\n };\n}\n\nfunction toFileError(error: unknown): FileError {\n const message = error instanceof Error ? error.message : String(error);\n if (/aborted/i.test(message)) return new FileError(\"aborted\", message);\n if (/no such file|not found/i.test(message)) return new FileError(\"not_found\", message);\n if (/permission denied/i.test(message)) return new FileError(\"permission_denied\", message);\n if (/not a directory/i.test(message)) return new FileError(\"not_directory\", message);\n if (/is a directory/i.test(message)) return new FileError(\"is_directory\", message);\n return new FileError(\"unknown\", message, undefined, error instanceof Error ? error : undefined);\n}\n\nfunction toExecutionError(error: unknown, context: Context): ExecutionError {\n const message = error instanceof Error ? error.message : String(error);\n if (context.abortSignal?.aborted || /aborted/i.test(message)) {\n return new ExecutionError(\"aborted\", message);\n }\n if (/timed out/i.test(message)) return new ExecutionError(\"timeout\", message);\n return new ExecutionError(\"unknown\", message, error instanceof Error ? error : undefined);\n}\n"]}
1
+ {"version":3,"file":"execution-env.js","sourceRoot":"","sources":["../../src/harness/execution-env.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { posix } from \"node:path\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n ExecutionError,\n FileError,\n err,\n ok,\n truncateHead,\n truncateTail,\n type Context,\n type ExecutionEnv,\n type FileInfo,\n type FileKind,\n type Result,\n type ShellExecOptions,\n type ShellExecResult,\n type ShellOutputMetadata,\n type TruncationResult,\n} from \"@earendil-works/pi-agent-core\";\nimport { NodeExecutionEnv } from \"@earendil-works/pi-agent-core/node\";\nimport type { Executor, SandboxConfig } from \"../sandbox/types.js\";\nimport { execAppendFile, execWriteFile, shellEscape } from \"../sandbox/utils.js\";\nimport { errorMessage } from \"../unknown-values.js\";\n\nconst SPILL_DIR = \".mikan/bash-output\";\n\nexport function createSandboxExecutionEnv(\n executor: Executor,\n sandboxType: SandboxConfig[\"type\"],\n runtimeWorkspaceRoot: string,\n): ExecutionEnv {\n if (sandboxType === \"host\") {\n return new NodeExecutionEnv({ cwd: runtimeWorkspaceRoot });\n }\n return new ShellExecutionEnv(executor, runtimeWorkspaceRoot);\n}\n\ntype TextLineReader =\n Awaited<ReturnType<ExecutionEnv[\"openTextLineReader\"]>> extends Result<infer T, FileError>\n ? T\n : never;\ntype TextLine =\n Awaited<ReturnType<TextLineReader[\"readLine\"]>> extends Result<infer T, FileError>\n ? Exclude<T, undefined>\n : never;\n\nclass ShellExecutionEnv implements ExecutionEnv {\n readonly cwd: string;\n\n constructor(\n private readonly executor: Executor,\n runtimeWorkspaceRoot: string,\n ) {\n this.cwd = runtimeWorkspaceRoot;\n }\n\n async absolutePath(path: string, _context: Context): Promise<Result<string, FileError>> {\n return ok(posix.isAbsolute(path) ? posix.normalize(path) : posix.resolve(this.cwd, path));\n }\n\n async joinPath(parts: string[], _context: Context): Promise<Result<string, FileError>> {\n return ok(posix.join(...parts));\n }\n\n readTextFile(path: string, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(() => this.executor.readFile(path, this.execOptions(context)));\n }\n\n openTextLineReader(path: string, context: Context): Promise<Result<TextLineReader, FileError>> {\n return this.fileOp(async () => {\n const content = await this.executor.readFile(path, this.execOptions(context));\n return new ShellTextLineReader(content);\n });\n }\n\n async readBinaryFile(path: string, context: Context): Promise<Result<Uint8Array, FileError>> {\n return this.fileOp(async () =>\n Buffer.from(await this.executor.readFileBase64(path, this.execOptions(context)), \"base64\"),\n );\n }\n\n readTextLines(\n path: string,\n options: { maxLines?: number } | undefined,\n context: Context,\n ): Promise<Result<string[], FileError>> {\n return this.fileOp(async () => {\n const max = options?.maxLines;\n const command =\n max === undefined\n ? `cat ${shellEscape(path)}`\n : `head -n ${Math.max(0, Math.floor(max))} ${shellEscape(path)}`;\n const { stdout } = await this.run(command, context);\n const lines = stdout.split(\"\\n\");\n if (lines.at(-1) === \"\") lines.pop();\n return lines;\n });\n }\n\n writeFile(\n path: string,\n content: string | Uint8Array,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(() =>\n execWriteFile(this.executor, path, content, this.execOptions(context)),\n );\n }\n\n appendFile(\n path: string,\n content: string | Uint8Array,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(() =>\n execAppendFile(this.executor, path, content, this.execOptions(context)),\n );\n }\n\n renameFile(\n sourcePath: string,\n destinationPath: string,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n await this.run(`mv -f ${shellEscape(sourcePath)} ${shellEscape(destinationPath)}`, context);\n });\n }\n\n fileInfo(path: string, context: Context): Promise<Result<FileInfo, FileError>> {\n return this.fileOp(async () => {\n const escaped = shellEscape(path);\n const probe = await this.executor.exec(\n `if [ -L ${escaped} ]; then printf 'symlink'; elif [ -d ${escaped} ]; then printf 'directory'; ` +\n `elif [ -f ${escaped} ]; then printf 'file'; else exit 1; fi`,\n this.execOptions(context),\n );\n if (probe.code !== 0) throw new Error(`No such file or directory: ${path}`);\n const kind = probe.stdout.trim() as FileKind;\n let size = 0;\n if (kind === \"file\") {\n const stat = await this.executor.exec(`wc -c < ${escaped}`, this.execOptions(context));\n if (stat.code === 0) size = Number.parseInt(stat.stdout.trim(), 10) || 0;\n }\n let mtimeMs = 0;\n const mtime = await this.executor.exec(`date -r ${escaped} +%s`, this.execOptions(context));\n if (mtime.code === 0) mtimeMs = (Number.parseInt(mtime.stdout.trim(), 10) || 0) * 1000;\n return { name: posix.basename(path), path, kind, size, mtimeMs };\n });\n }\n\n async listDir(path: string, context: Context): Promise<Result<FileInfo[], FileError>> {\n return this.fileOp(async () => {\n const { stdout } = await this.run(`ls -A ${shellEscape(path)}`, context);\n const names = stdout.split(\"\\n\").filter(Boolean).toSorted();\n const entries: FileInfo[] = [];\n for (const name of names) {\n const child = posix.join(path, name);\n const info = await this.fileInfo(child, context);\n if (info.ok) entries.push(info.value);\n }\n return entries;\n });\n }\n\n canonicalPath(path: string, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(async () =>\n (await this.run(`realpath ${shellEscape(path)}`, context)).stdout.trim(),\n );\n }\n\n async exists(path: string, context: Context): Promise<Result<boolean, FileError>> {\n try {\n const result = await this.executor.exec(\n `test -e ${shellEscape(path)}`,\n this.execOptions(context),\n );\n return ok(result.code === 0);\n } catch (error) {\n return err(toFileError(error));\n }\n }\n\n createDir(\n path: string,\n options: { recursive?: boolean } | undefined,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n const flag = options?.recursive === false ? \"\" : \"-p \";\n await this.run(`mkdir ${flag}${shellEscape(path)}`, context);\n });\n }\n\n remove(\n path: string,\n options: { recursive?: boolean; force?: boolean } | undefined,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n const recursive = options?.recursive ? \"-r\" : \"\";\n const force = options?.force ? \"-f\" : \"\";\n await this.run(`rm ${recursive} ${force} ${shellEscape(path)}`, context);\n });\n }\n\n createTempDir(prefix: string | undefined, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(async () => {\n const template = prefix === undefined ? \"\" : shellEscape(`${prefix}XXXXXX`);\n const { stdout } = await this.run(`mktemp -d ${template}`.trim(), context);\n return stdout.trim();\n });\n }\n\n createTempFile(\n options: { prefix?: string; suffix?: string } | undefined,\n context: Context,\n ): Promise<Result<string, FileError>> {\n return this.fileOp(async () => {\n const template =\n options?.prefix === undefined && options?.suffix === undefined\n ? \"\"\n : shellEscape(`${options?.prefix ?? \"\"}XXXXXX${options?.suffix ?? \"\"}`);\n const { stdout } = await this.run(`mktemp ${template}`.trim(), context);\n return stdout.trim();\n });\n }\n\n async cleanup(_context: Context): Promise<void> {}\n\n async exec(\n command: string,\n options: ShellExecOptions | undefined,\n context: Context,\n ): Promise<Result<ShellExecResult, ExecutionError>> {\n try {\n const result = await this.executor.exec(command, {\n cwd: options?.cwd || undefined,\n timeout: options?.timeout || undefined,\n signal: context.abortSignal,\n });\n const combined = [result.stdout, result.stderr].filter((part) => part.length > 0).join(\"\\n\");\n const limits = options?.capture?.limits ?? {\n maxBytes: DEFAULT_MAX_BYTES,\n maxLines: DEFAULT_MAX_LINES,\n retain: \"tail\" as const,\n };\n const truncation =\n limits.retain === \"head\"\n ? truncateHead(combined, { maxLines: limits.maxLines, maxBytes: limits.maxBytes })\n : truncateTail(combined, { maxLines: limits.maxLines, maxBytes: limits.maxBytes });\n\n let spillPath: string | undefined;\n if (options?.capture?.spill && truncation.truncated) {\n try {\n spillPath = posix.join(this.cwd, SPILL_DIR, `${randomBytes(8).toString(\"hex\")}.log`);\n await this.executor.writeFile(spillPath, combined, this.execOptions(context));\n } catch {\n spillPath = undefined;\n }\n }\n\n const metadata = shellOutputMetadata(truncation, spillPath);\n options?.onUpdate?.(\n { kind: \"replace\", output: { text: truncation.content, ...metadata } },\n context,\n );\n return ok({ exitCode: result.code, ...metadata });\n } catch (error) {\n return err(toExecutionError(error, context));\n }\n }\n\n private execOptions(context: Context): { signal: AbortSignal | undefined } {\n return { signal: context.abortSignal };\n }\n\n private async run(\n command: string,\n context: Context,\n ): Promise<{ stdout: string; stderr: string }> {\n const result = await this.executor.exec(command, this.execOptions(context));\n if (result.code !== 0) {\n throw new Error(result.stderr.trim() || `Command failed (${result.code}): ${command}`);\n }\n return result;\n }\n\n private async fileOp<T>(op: () => Promise<T>): Promise<Result<T, FileError>> {\n try {\n return ok(await op());\n } catch (error) {\n return err(toFileError(error));\n }\n }\n}\n\nclass ShellTextLineReader implements TextLineReader {\n private offset = 0;\n\n constructor(private readonly content: string) {}\n\n async readLine(_context: Context): Promise<Result<TextLine | undefined, FileError>> {\n if (this.offset >= this.content.length) return ok(undefined);\n const newline = this.content.indexOf(\"\\n\", this.offset);\n if (newline === -1) {\n const text = this.content.slice(this.offset);\n this.offset = this.content.length;\n return ok({ text, terminated: false });\n }\n const text = this.content.slice(this.offset, newline);\n this.offset = newline + 1;\n return ok({ text, terminated: true });\n }\n\n async close(_context: Context): Promise<void> {\n this.offset = this.content.length;\n }\n}\n\nfunction shellOutputMetadata(\n truncation: TruncationResult,\n spillPath: string | undefined,\n): ShellOutputMetadata {\n const { content: _content, ...metadata } = truncation;\n const lastLine = truncation.content.split(\"\\n\").at(-1) ?? \"\";\n return {\n truncation: metadata,\n spillPath: spillPath || undefined,\n lastLineBytes: truncation.lastLinePartial ? Buffer.byteLength(lastLine, \"utf8\") : undefined,\n };\n}\n\nfunction toFileError(error: unknown): FileError {\n const message = errorMessage(error);\n if (/aborted/i.test(message)) return new FileError(\"aborted\", message);\n if (/no such file|not found/i.test(message)) return new FileError(\"not_found\", message);\n if (/permission denied/i.test(message)) return new FileError(\"permission_denied\", message);\n if (/not a directory/i.test(message)) return new FileError(\"not_directory\", message);\n if (/is a directory/i.test(message)) return new FileError(\"is_directory\", message);\n return new FileError(\"unknown\", message, undefined, error instanceof Error ? error : undefined);\n}\n\nfunction toExecutionError(error: unknown, context: Context): ExecutionError {\n const message = errorMessage(error);\n if (context.abortSignal?.aborted || /aborted/i.test(message)) {\n return new ExecutionError(\"aborted\", message);\n }\n if (/timed out/i.test(message)) return new ExecutionError(\"timeout\", message);\n return new ExecutionError(\"unknown\", message, error instanceof Error ? error : undefined);\n}\n"]}
@@ -1,16 +1,14 @@
1
- import type { Workspace } from "../office/index.js";
2
1
  import { DockerContainerManager } from "../sandbox/provisioner.js";
3
- import { type SandboxConfig } from "../sandbox/index.js";
4
- import { type VaultManager } from "../vault/index.js";
5
- import type { WorkspaceProjection } from "../office/types.js";
6
- export type { ActorContext } from "../types.js";
7
2
  import type { ActorContext } from "../types.js";
3
+ import type { SandboxConfig } from "../sandbox/types.js";
4
+ import type { VaultManager } from "../vault/types.js";
5
+ import type { WorkspaceProjection, Workspace } from "../office/types.js";
8
6
  export declare class ActorExecutionResolver {
9
7
  private baseConfig;
10
8
  private vaultManager;
11
9
  private provisioner;
12
10
  private workspace;
13
- constructor(baseConfig: SandboxConfig, vaultManager: VaultManager, provisioner: DockerContainerManager | undefined, workspace: Workspace);
11
+ constructor(baseConfig: SandboxConfig, vaultManager: Pick<VaultManager, "hasEntry" | "resolve" | "copySharedVaultTo">, provisioner: Pick<DockerContainerManager, "provision"> | undefined, workspace: Workspace);
14
12
  resolve(context: ActorContext): Promise<{
15
13
  executor: import("../sandbox/types.js").Executor;
16
14
  pathContext: import("../sandbox/types.js").RuntimePathContext;
@@ -1 +1 @@
1
- {"version":3,"file":"execution-resolver.d.ts","sourceRoot":"","sources":["../../src/harness/execution-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,sBAAsB,EAAuB,MAAM,2BAA2B,CAAC;AACxF,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAShF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,aAAa,CAAC;AAE/D,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,SAAS;IAJnB,YACU,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,sBAAsB,GAAG,SAAS,EAC/C,SAAS,EAAE,SAAS,EAC1B;IAEE,OAAO,CAAC,OAAO,EAAE,YAAY;;;;OAYlC;IAED,OAAO,CAAC,WAAW;IAuCnB,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,aAAa;CA4BtB"}
1
+ {"version":3,"file":"execution-resolver.d.ts","sourceRoot":"","sources":["../../src/harness/execution-resolver.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAkB,YAAY,EAAiB,MAAM,aAAa,CAAC;AAM/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAStD,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEzE,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,SAAS;IAJnB,YACU,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,SAAS,GAAG,mBAAmB,CAAC,EAC9E,WAAW,EAAE,IAAI,CAAC,sBAAsB,EAAE,WAAW,CAAC,GAAG,SAAS,EAClE,SAAS,EAAE,SAAS,EAC1B;IAEE,OAAO,CAAC,OAAO,EAAE,YAAY;;;;OAYlC;IAED,OAAO,CAAC,WAAW;IAuCnB,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,aAAa;CA4BtB"}
@@ -1,7 +1,7 @@
1
1
  import { posix } from "node:path";
2
2
  import { loadGlobalSettings } from "../settings/index.js";
3
3
  import { DockerContainerManager } from "../sandbox/provisioner.js";
4
- import { assertSandboxSupportsWorkspacePolicy, createExecutor, getSandboxCredentialCapabilities, } from "../sandbox/index.js";
4
+ import { assertSandboxSupportsWorkspacePolicy, createExecutor, getSandboxCredentialCapabilities, } from "../sandbox/registry.js";
5
5
  import { reportUserFacingError } from "../observability/index.js";
6
6
  import { normalizeSharedVaultName } from "../vault/index.js";
7
7
  import { allowsAmbientDefaultSharedVault, resolveVaultInjection } from "../vault/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../../src/harness/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { posix } from \"node:path\";\nimport type { Workspace } from \"../office/index.js\";\nimport { loadGlobalSettings } from \"../settings/index.js\";\nimport { DockerContainerManager, type ContainerMount } from \"../sandbox/provisioner.js\";\nimport {\n assertSandboxSupportsWorkspacePolicy,\n createExecutor,\n getSandboxCredentialCapabilities,\n type SandboxConfig,\n} from \"../sandbox/index.js\";\nimport { reportUserFacingError } from \"../observability/index.js\";\nimport { normalizeSharedVaultName, type VaultManager } from \"../vault/index.js\";\nimport { allowsAmbientDefaultSharedVault, resolveVaultInjection } from \"../vault/index.js\";\nimport {\n credentialAuthorizationKey,\n legacyExactCredentialAuthorizationKey,\n runtimeResourceKey,\n scopeCloudflareSandboxId,\n} from \"../sandbox/identity.js\";\nimport { resolveWorkspaceProjection } from \"../office/projection.js\";\nimport type { WorkspaceProjection } from \"../office/types.js\";\n\nexport type { ActorContext } from \"../types.js\";\nimport type { ActorContext, ExecutionPlan } from \"../types.js\";\n\nexport class ActorExecutionResolver {\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner: DockerContainerManager | undefined,\n private workspace: Workspace,\n ) {}\n\n async resolve(context: ActorContext) {\n const { plan, projection } = this.resolvePlan(context);\n const executor = createExecutor(\n plan.sandboxConfig,\n plan.env,\n this.buildEnsureReadyCallback(plan, context.address.conversationId),\n );\n return {\n executor,\n pathContext: executor.getPathContext(this.workspace.root),\n projection,\n };\n }\n\n private resolvePlan(context: ActorContext): {\n plan: ExecutionPlan;\n projection: WorkspaceProjection;\n } {\n const scope = { userId: context.userId, address: context.address };\n const credentialKey = credentialAuthorizationKey(this.baseConfig, scope);\n const legacyCredentialKey = legacyExactCredentialAuthorizationKey(this.baseConfig, scope);\n const resourceKey = runtimeResourceKey(this.baseConfig, {\n userId: context.userId,\n address: context.address,\n });\n this.ensureDefaultSharedVault(credentialKey, legacyCredentialKey, context.trustModel);\n\n const vault =\n this.vaultManager.resolve(credentialKey) ??\n (legacyCredentialKey ? this.vaultManager.resolve(legacyCredentialKey) : undefined);\n const capabilities = getSandboxCredentialCapabilities(this.baseConfig.type);\n const office = this.workspace.office(context.address);\n const projection = resolveWorkspaceProjection(office);\n const injection = resolveVaultInjection({\n vault,\n capabilities,\n sandboxType: this.baseConfig.type,\n address: office.address,\n });\n const mounts = this.resolveMounts(injection.mounts, projection);\n assertSandboxSupportsWorkspacePolicy(this.baseConfig, projection.visibility, office.key);\n return {\n plan: {\n credentialKey,\n resourceKey,\n sandboxConfig: this.resolveSandboxConfig(resourceKey),\n env: injection.env,\n mounts,\n },\n projection,\n };\n }\n\n private ensureDefaultSharedVault(\n credentialKey: string,\n legacyCredentialKey: string | undefined,\n trustModel: ActorContext[\"trustModel\"],\n ): void {\n if (!allowsAmbientDefaultSharedVault({ trustModel, sandboxType: this.baseConfig.type })) return;\n if (\n this.vaultManager.hasEntry(credentialKey) ||\n (legacyCredentialKey && this.vaultManager.hasEntry(legacyCredentialKey))\n ) {\n return;\n }\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().sandbox?.defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n this.vaultManager.copySharedVaultTo(profile, credentialKey);\n }\n\n private resolveSandboxConfig(resourceKey: string): SandboxConfig {\n if (this.baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, resourceKey),\n };\n }\n if (this.baseConfig.type !== \"image\") return this.baseConfig;\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(resourceKey),\n };\n }\n\n private buildEnsureReadyCallback(\n plan: ExecutionPlan,\n conversationId: string,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || plan.sandboxConfig.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = plan.sandboxConfig.type === \"container\" ? plan.sandboxConfig.container : \"\";\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(plan.resourceKey, {\n containerName: expected,\n mounts: plan.mounts,\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n conversationId,\n credentialKey: plan.credentialKey,\n resourceKey: plan.resourceKey,\n expectedContainer: expected,\n hasVault: Boolean(plan.env || plan.mounts.length > 0),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for resource key \"${plan.resourceKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(\n vaultMounts: ContainerMount[],\n projection: WorkspaceProjection,\n ): ContainerMount[] {\n const protectedMounts = projection.mounts;\n for (let index = 0; index < vaultMounts.length; index += 1) {\n const vaultMount = vaultMounts[index];\n if (vaultMount === undefined) continue;\n const workspaceCollision = protectedMounts.find((protectedMount) =>\n targetsOverlap(protectedMount.target, vaultMount.target),\n );\n if (workspaceCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps protected workspace target \"${workspaceCollision.target}\"`,\n );\n }\n\n const vaultCollision = vaultMounts\n .slice(0, index)\n .find((other) => targetsOverlap(other.target, vaultMount.target));\n if (vaultCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps vault target \"${vaultCollision.target}\"`,\n );\n }\n }\n return [...protectedMounts, ...vaultMounts];\n }\n}\n\nfunction targetsOverlap(left: string, right: string): boolean {\n const a = normalizeMountTarget(left);\n const b = normalizeMountTarget(right);\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\nfunction normalizeMountTarget(value: string): string {\n const normalized = posix.normalize(value);\n return normalized.replace(/\\/+$/, \"\") || \"/\";\n}\n"]}
1
+ {"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../../src/harness/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { posix } from \"node:path\";\n\nimport { loadGlobalSettings } from \"../settings/index.js\";\nimport { DockerContainerManager } from \"../sandbox/provisioner.js\";\nimport type { ContainerMount, ActorContext, ExecutionPlan } from \"../types.js\";\nimport {\n assertSandboxSupportsWorkspacePolicy,\n createExecutor,\n getSandboxCredentialCapabilities,\n} from \"../sandbox/registry.js\";\nimport type { SandboxConfig } from \"../sandbox/types.js\";\nimport { reportUserFacingError } from \"../observability/index.js\";\nimport { normalizeSharedVaultName } from \"../vault/index.js\";\nimport type { VaultManager } from \"../vault/types.js\";\nimport { allowsAmbientDefaultSharedVault, resolveVaultInjection } from \"../vault/index.js\";\nimport {\n credentialAuthorizationKey,\n legacyExactCredentialAuthorizationKey,\n runtimeResourceKey,\n scopeCloudflareSandboxId,\n} from \"../sandbox/identity.js\";\nimport { resolveWorkspaceProjection } from \"../office/projection.js\";\nimport type { WorkspaceProjection, Workspace } from \"../office/types.js\";\n\nexport class ActorExecutionResolver {\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: Pick<VaultManager, \"hasEntry\" | \"resolve\" | \"copySharedVaultTo\">,\n private provisioner: Pick<DockerContainerManager, \"provision\"> | undefined,\n private workspace: Workspace,\n ) {}\n\n async resolve(context: ActorContext) {\n const { plan, projection } = this.resolvePlan(context);\n const executor = createExecutor(\n plan.sandboxConfig,\n plan.env,\n this.buildEnsureReadyCallback(plan, context.address.conversationId),\n );\n return {\n executor,\n pathContext: executor.getPathContext(this.workspace.root),\n projection,\n };\n }\n\n private resolvePlan(context: ActorContext): {\n plan: ExecutionPlan;\n projection: WorkspaceProjection;\n } {\n const scope = { userId: context.userId, address: context.address };\n const credentialKey = credentialAuthorizationKey(this.baseConfig, scope);\n const legacyCredentialKey = legacyExactCredentialAuthorizationKey(this.baseConfig, scope);\n const resourceKey = runtimeResourceKey(this.baseConfig, {\n userId: context.userId,\n address: context.address,\n });\n this.ensureDefaultSharedVault(credentialKey, legacyCredentialKey, context.trustModel);\n\n const vault =\n this.vaultManager.resolve(credentialKey) ??\n (legacyCredentialKey ? this.vaultManager.resolve(legacyCredentialKey) : undefined);\n const capabilities = getSandboxCredentialCapabilities(this.baseConfig.type);\n const office = this.workspace.office(context.address);\n const projection = resolveWorkspaceProjection(office);\n const injection = resolveVaultInjection({\n vault,\n capabilities,\n sandboxType: this.baseConfig.type,\n address: office.address,\n });\n const mounts = this.resolveMounts(injection.mounts, projection);\n assertSandboxSupportsWorkspacePolicy(this.baseConfig, projection.visibility, office.key);\n return {\n plan: {\n credentialKey,\n resourceKey,\n sandboxConfig: this.resolveSandboxConfig(resourceKey),\n env: injection.env,\n mounts,\n },\n projection,\n };\n }\n\n private ensureDefaultSharedVault(\n credentialKey: string,\n legacyCredentialKey: string | undefined,\n trustModel: ActorContext[\"trustModel\"],\n ): void {\n if (!allowsAmbientDefaultSharedVault({ trustModel, sandboxType: this.baseConfig.type })) return;\n if (\n this.vaultManager.hasEntry(credentialKey) ||\n (legacyCredentialKey && this.vaultManager.hasEntry(legacyCredentialKey))\n ) {\n return;\n }\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().sandbox?.defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n this.vaultManager.copySharedVaultTo(profile, credentialKey);\n }\n\n private resolveSandboxConfig(resourceKey: string): SandboxConfig {\n if (this.baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, resourceKey),\n };\n }\n if (this.baseConfig.type !== \"image\") return this.baseConfig;\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(resourceKey),\n };\n }\n\n private buildEnsureReadyCallback(\n plan: ExecutionPlan,\n conversationId: string,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || plan.sandboxConfig.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = plan.sandboxConfig.type === \"container\" ? plan.sandboxConfig.container : \"\";\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(plan.resourceKey, {\n containerName: expected,\n mounts: plan.mounts,\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n conversationId,\n credentialKey: plan.credentialKey,\n resourceKey: plan.resourceKey,\n expectedContainer: expected,\n hasVault: Boolean(plan.env || plan.mounts.length > 0),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for resource key \"${plan.resourceKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(\n vaultMounts: ContainerMount[],\n projection: WorkspaceProjection,\n ): ContainerMount[] {\n const protectedMounts = projection.mounts;\n for (let index = 0; index < vaultMounts.length; index += 1) {\n const vaultMount = vaultMounts[index];\n if (vaultMount === undefined) continue;\n const workspaceCollision = protectedMounts.find((protectedMount) =>\n targetsOverlap(protectedMount.target, vaultMount.target),\n );\n if (workspaceCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps protected workspace target \"${workspaceCollision.target}\"`,\n );\n }\n\n const vaultCollision = vaultMounts\n .slice(0, index)\n .find((other) => targetsOverlap(other.target, vaultMount.target));\n if (vaultCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps vault target \"${vaultCollision.target}\"`,\n );\n }\n }\n return [...protectedMounts, ...vaultMounts];\n }\n}\n\nfunction targetsOverlap(left: string, right: string): boolean {\n const a = normalizeMountTarget(left);\n const b = normalizeMountTarget(right);\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\nfunction normalizeMountTarget(value: string): string {\n const normalized = posix.normalize(value);\n return normalized.replace(/\\/+$/, \"\") || \"/\";\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type JevCaller } from "../observability/index.js";
1
+ import type { JevCaller } from "../observability/types.js";
2
2
  export declare const JEV_MODEL_ID = "~typesafe/jev-latest";
3
3
  export type JevEntry = string | number | boolean | null | JevEntry[] | {
4
4
  [key: string]: JevEntry;
@@ -1 +1 @@
1
- {"version":3,"file":"jev.d.ts","sourceRoot":"","sources":["../../src/harness/jev.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jev.d.ts","sourceRoot":"","sources":["../../src/harness/jev.ts"],"names":[],"mappings":"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"}
@@ -85,10 +85,7 @@ export async function evaluateWithJev(state, questions, options) {
85
85
  const startedAt = Date.now();
86
86
  let result;
87
87
  try {
88
- result = await models().evaluate(model, { state: state, questions: wireQuestions }, {
89
- ...(options.headers ? { headers: options.headers } : {}),
90
- ...(options.abortSignal ? { signal: options.abortSignal } : {}),
91
- });
88
+ result = await models().evaluate(model, { state: state, questions: wireQuestions }, { headers: options.headers, signal: options.abortSignal });
92
89
  }
93
90
  catch (error) {
94
91
  recordJevOutcome({
@@ -1 +1 @@
1
- {"version":3,"file":"jev.js","sourceRoot":"","sources":["../../src/harness/jev.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createBuiltinJevModels,\n JevAPIError,\n JevAuthError,\n JevConfigError,\n JevConnectionError,\n JevResponseError,\n JevTimeoutError,\n type AnswerFor as GeminixiangAnswerFor,\n type Entry as GeminixiangEntry,\n type Question as GeminixiangQuestion,\n} from \"@geminixiang/jev\";\nimport type { AuthContext } from \"@earendil-works/pi-ai\";\nimport { readEnv } from \"../env-manifest.js\";\nimport { recordJevOutcome, type JevCaller } from \"../observability/index.js\";\n\nexport const JEV_MODEL_ID = \"~typesafe/jev-latest\";\n\nexport type JevEntry = string | number | boolean | null | JevEntry[] | { [key: string]: JevEntry };\n\nexport type JevQuestion =\n | {\n type: \"boolean\";\n instructions: JevEntry;\n criteria?: { true?: JevEntry; false?: JevEntry };\n }\n | { type: \"choice\"; instructions: JevEntry; criteria: Record<string, JevEntry> }\n | { type: \"score\"; instructions: JevEntry; criteria: readonly JevEntry[] };\n\nexport type JevQuestions = Record<string, JevQuestion>;\n\nexport type JevAnswer<QUESTION extends JevQuestion> = QUESTION extends { type: \"choice\" }\n ? {\n type: \"choice\";\n choice: string;\n probabilities?: Record<string, number>;\n confidence?: number;\n }\n : QUESTION extends { type: \"score\" }\n ? {\n type: \"score\";\n score: number;\n probabilities?: Record<string, number>;\n legend?: Record<string, string>;\n confidence?: number;\n }\n : { type: \"boolean\"; probability: number };\n\nexport interface JevResult<QUESTIONS extends JevQuestions> {\n readonly answers: { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n readonly usage: {\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n cost: number | undefined;\n };\n readonly model: string;\n}\n\nexport class JevNotConfiguredError extends Error {\n constructor() {\n super(\n \"Jev requires OPENROUTER_API_KEY (an OpenRouter API key). Set it in the environment before calling evaluateWithJev().\",\n );\n this.name = \"JevNotConfiguredError\";\n }\n}\n\nexport class JevRequestError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n ) {\n super(message);\n this.name = \"JevRequestError\";\n }\n}\n\nexport interface EvaluateWithJevOptions {\n model?: string;\n abortSignal?: AbortSignal;\n headers?: Record<string, string>;\n caller: JevCaller;\n}\n\nconst mikanAuthContext: AuthContext = {\n async env(name) {\n return readEnv(name);\n },\n async fileExists() {\n return false;\n },\n};\n\nlet cachedModels: ReturnType<typeof createBuiltinJevModels> | undefined;\n\nfunction models() {\n cachedModels ??= createBuiltinJevModels({ authContext: mikanAuthContext });\n return cachedModels;\n}\n\nfunction toGeminixiangQuestion(question: JevQuestion): GeminixiangQuestion {\n const instructions = question.instructions as GeminixiangEntry;\n if (question.type === \"boolean\") {\n return {\n type: \"noul\",\n instructions,\n criteria: {\n true: (question.criteria?.true as GeminixiangEntry) ?? \"Yes\",\n false: (question.criteria?.false as GeminixiangEntry) ?? \"No\",\n },\n };\n }\n if (question.type === \"choice\") {\n return {\n type: \"choice\",\n instructions,\n criteria: question.criteria as Record<string, GeminixiangEntry>,\n };\n }\n const [first, second, ...rest] = question.criteria as GeminixiangEntry[];\n if (first === undefined || second === undefined) {\n throw new Error(\"score questions need at least two levels\");\n }\n return { type: \"score\", instructions, criteria: [first, second, ...rest] };\n}\n\nfunction fromGeminixiangAnswer(\n answer: GeminixiangAnswerFor<GeminixiangQuestion>,\n): JevAnswer<JevQuestion> {\n if (answer.type === \"noul\") {\n return { type: \"boolean\", probability: answer.noul };\n }\n if (answer.type === \"choice\") {\n return {\n type: \"choice\",\n choice: answer.choice,\n probabilities: answer.probabilities as Record<string, number>,\n confidence: answer.confidence,\n };\n }\n return {\n type: \"score\",\n score: answer.score,\n probabilities: answer.probabilities,\n legend: answer.legend as Record<string, string> | undefined,\n confidence: answer.confidence,\n };\n}\n\nexport async function evaluateWithJev<const QUESTIONS extends JevQuestions>(\n state: JevEntry,\n questions: QUESTIONS,\n options: EvaluateWithJevOptions,\n): Promise<JevResult<QUESTIONS>> {\n const catalogModel = models().getModel(\"openrouter\", \"jev-latest\");\n if (!catalogModel) throw new JevNotConfiguredError();\n const model = options.model ? { ...catalogModel, slug: options.model } : catalogModel;\n\n const wireQuestions: Record<string, GeminixiangQuestion> = {};\n for (const [id, question] of Object.entries(questions)) {\n wireQuestions[id] = toGeminixiangQuestion(question);\n }\n\n const startedAt = Date.now();\n let result;\n try {\n result = await models().evaluate(\n model,\n { state: state as GeminixiangEntry, questions: wireQuestions },\n {\n ...(options.headers ? { headers: options.headers } : {}),\n ...(options.abortSignal ? { signal: options.abortSignal } : {}),\n },\n );\n } catch (error) {\n recordJevOutcome({\n caller: options.caller,\n status: \"error\",\n errorType: error instanceof Error ? error.name : \"Error\",\n durationMs: Date.now() - startedAt,\n });\n if (error instanceof JevAuthError || error instanceof JevConfigError) {\n throw new JevNotConfiguredError();\n }\n if (error instanceof JevAPIError) {\n throw new JevRequestError(error.message, error.status);\n }\n if (\n error instanceof JevResponseError ||\n error instanceof JevConnectionError ||\n error instanceof JevTimeoutError\n ) {\n throw new JevRequestError(error.message, 502);\n }\n throw error;\n }\n recordJevOutcome({\n caller: options.caller,\n status: \"ok\",\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n costUsd: result.usage.cost.total,\n durationMs: Date.now() - startedAt,\n });\n\n const answers = {} as { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n for (const id of Object.keys(questions)) {\n const answer = result.answers[id];\n if (!answer) throw new JevRequestError(`Jev response missing answer for \"${id}\"`, 502);\n (answers as Record<string, JevAnswer<JevQuestion>>)[id] = fromGeminixiangAnswer(answer);\n }\n\n return {\n answers,\n usage: {\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n cost: result.usage.cost.total,\n },\n model: result.model,\n };\n}\n"]}
1
+ {"version":3,"file":"jev.js","sourceRoot":"","sources":["../../src/harness/jev.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createBuiltinJevModels,\n JevAPIError,\n JevAuthError,\n JevConfigError,\n JevConnectionError,\n JevResponseError,\n JevTimeoutError,\n type AnswerFor as GeminixiangAnswerFor,\n type Entry as GeminixiangEntry,\n type Question as GeminixiangQuestion,\n} from \"@geminixiang/jev\";\nimport type { AuthContext } from \"@earendil-works/pi-ai\";\nimport { readEnv } from \"../env-manifest.js\";\nimport { recordJevOutcome } from \"../observability/index.js\";\nimport type { JevCaller } from \"../observability/types.js\";\n\nexport const JEV_MODEL_ID = \"~typesafe/jev-latest\";\n\nexport type JevEntry = string | number | boolean | null | JevEntry[] | { [key: string]: JevEntry };\n\nexport type JevQuestion =\n | {\n type: \"boolean\";\n instructions: JevEntry;\n criteria?: { true?: JevEntry; false?: JevEntry };\n }\n | { type: \"choice\"; instructions: JevEntry; criteria: Record<string, JevEntry> }\n | { type: \"score\"; instructions: JevEntry; criteria: readonly JevEntry[] };\n\nexport type JevQuestions = Record<string, JevQuestion>;\n\nexport type JevAnswer<QUESTION extends JevQuestion> = QUESTION extends { type: \"choice\" }\n ? {\n type: \"choice\";\n choice: string;\n probabilities?: Record<string, number>;\n confidence?: number;\n }\n : QUESTION extends { type: \"score\" }\n ? {\n type: \"score\";\n score: number;\n probabilities?: Record<string, number>;\n legend?: Record<string, string>;\n confidence?: number;\n }\n : { type: \"boolean\"; probability: number };\n\nexport interface JevResult<QUESTIONS extends JevQuestions> {\n readonly answers: { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n readonly usage: {\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n cost: number | undefined;\n };\n readonly model: string;\n}\n\nexport class JevNotConfiguredError extends Error {\n constructor() {\n super(\n \"Jev requires OPENROUTER_API_KEY (an OpenRouter API key). Set it in the environment before calling evaluateWithJev().\",\n );\n this.name = \"JevNotConfiguredError\";\n }\n}\n\nexport class JevRequestError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n ) {\n super(message);\n this.name = \"JevRequestError\";\n }\n}\n\nexport interface EvaluateWithJevOptions {\n model?: string;\n abortSignal?: AbortSignal;\n headers?: Record<string, string>;\n caller: JevCaller;\n}\n\nconst mikanAuthContext: AuthContext = {\n async env(name) {\n return readEnv(name);\n },\n async fileExists() {\n return false;\n },\n};\n\nlet cachedModels: ReturnType<typeof createBuiltinJevModels> | undefined;\n\nfunction models() {\n cachedModels ??= createBuiltinJevModels({ authContext: mikanAuthContext });\n return cachedModels;\n}\n\nfunction toGeminixiangQuestion(question: JevQuestion): GeminixiangQuestion {\n const instructions = question.instructions as GeminixiangEntry;\n if (question.type === \"boolean\") {\n return {\n type: \"noul\",\n instructions,\n criteria: {\n true: (question.criteria?.true as GeminixiangEntry) ?? \"Yes\",\n false: (question.criteria?.false as GeminixiangEntry) ?? \"No\",\n },\n };\n }\n if (question.type === \"choice\") {\n return {\n type: \"choice\",\n instructions,\n criteria: question.criteria as Record<string, GeminixiangEntry>,\n };\n }\n const [first, second, ...rest] = question.criteria as GeminixiangEntry[];\n if (first === undefined || second === undefined) {\n throw new Error(\"score questions need at least two levels\");\n }\n return { type: \"score\", instructions, criteria: [first, second, ...rest] };\n}\n\nfunction fromGeminixiangAnswer(\n answer: GeminixiangAnswerFor<GeminixiangQuestion>,\n): JevAnswer<JevQuestion> {\n if (answer.type === \"noul\") {\n return { type: \"boolean\", probability: answer.noul };\n }\n if (answer.type === \"choice\") {\n return {\n type: \"choice\",\n choice: answer.choice,\n probabilities: answer.probabilities as Record<string, number>,\n confidence: answer.confidence,\n };\n }\n return {\n type: \"score\",\n score: answer.score,\n probabilities: answer.probabilities,\n legend: answer.legend as Record<string, string> | undefined,\n confidence: answer.confidence,\n };\n}\n\nexport async function evaluateWithJev<const QUESTIONS extends JevQuestions>(\n state: JevEntry,\n questions: QUESTIONS,\n options: EvaluateWithJevOptions,\n): Promise<JevResult<QUESTIONS>> {\n const catalogModel = models().getModel(\"openrouter\", \"jev-latest\");\n if (!catalogModel) throw new JevNotConfiguredError();\n const model = options.model ? { ...catalogModel, slug: options.model } : catalogModel;\n\n const wireQuestions: Record<string, GeminixiangQuestion> = {};\n for (const [id, question] of Object.entries(questions)) {\n wireQuestions[id] = toGeminixiangQuestion(question);\n }\n\n const startedAt = Date.now();\n let result;\n try {\n result = await models().evaluate(\n model,\n { state: state as GeminixiangEntry, questions: wireQuestions },\n { headers: options.headers, signal: options.abortSignal },\n );\n } catch (error) {\n recordJevOutcome({\n caller: options.caller,\n status: \"error\",\n errorType: error instanceof Error ? error.name : \"Error\",\n durationMs: Date.now() - startedAt,\n });\n if (error instanceof JevAuthError || error instanceof JevConfigError) {\n throw new JevNotConfiguredError();\n }\n if (error instanceof JevAPIError) {\n throw new JevRequestError(error.message, error.status);\n }\n if (\n error instanceof JevResponseError ||\n error instanceof JevConnectionError ||\n error instanceof JevTimeoutError\n ) {\n throw new JevRequestError(error.message, 502);\n }\n throw error;\n }\n recordJevOutcome({\n caller: options.caller,\n status: \"ok\",\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n costUsd: result.usage.cost.total,\n durationMs: Date.now() - startedAt,\n });\n\n const answers = {} as { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n for (const id of Object.keys(questions)) {\n const answer = result.answers[id];\n if (!answer) throw new JevRequestError(`Jev response missing answer for \"${id}\"`, 502);\n (answers as Record<string, JevAnswer<JevQuestion>>)[id] = fromGeminixiangAnswer(answer);\n }\n\n return {\n answers,\n usage: {\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n cost: result.usage.cost.total,\n },\n model: result.model,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-result.d.ts","sourceRoot":"","sources":["../../src/harness/mcp-result.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,YAAY,EAClB,MAAM,+BAA+B,CAAC;AAGvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAiED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAStF;AAsDD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,cAAc,CAehF;AAoCD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAkBrC"}
1
+ {"version":3,"file":"mcp-result.d.ts","sourceRoot":"","sources":["../../src/harness/mcp-result.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,YAAY,EAClB,MAAM,+BAA+B,CAAC;AAIvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAiED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAStF;AAsDD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,cAAc,CAehF;AA2CD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAkBrC"}
@@ -1,6 +1,7 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead, } from "@earendil-works/pi-agent-core";
3
3
  import { redactSecrets } from "./tools/secret-redaction.js";
4
+ import { isRecord } from "../unknown-values.js";
4
5
  const SPILL_DIR = [".mikan", "mcp-output"];
5
6
  const NOTICE_RESERVE_BYTES = 640;
6
7
  const NOTICE_RESERVE_LINES = 4;
@@ -14,8 +15,8 @@ const DIGEST_LEVELS = [
14
15
  { stringChars: 40, arrayItems: 1, depth: 3 },
15
16
  { stringChars: 16, arrayItems: 1, depth: 2 },
16
17
  ];
17
- function isRecord(value) {
18
- return typeof value === "object" && value !== null && !Array.isArray(value);
18
+ function isRawBlock(value) {
19
+ return isRecord(value);
19
20
  }
20
21
  function stringField(block, key) {
21
22
  const value = block[key];
@@ -40,7 +41,7 @@ function blockContent(block) {
40
41
  if (block.type === "image" && data !== undefined && mimeType !== undefined) {
41
42
  return { type: "image", data, mimeType };
42
43
  }
43
- if (block.type === "resource" && isRecord(block.resource)) {
44
+ if (block.type === "resource" && isRawBlock(block.resource)) {
44
45
  return { type: "text", text: describeResource(block.resource) };
45
46
  }
46
47
  if (block.type === "resource_link") {
@@ -54,7 +55,7 @@ function blockContent(block) {
54
55
  }
55
56
  export function mcpResultContent(result) {
56
57
  const blocks = (Array.isArray(result.content) ? result.content : [])
57
- .filter(isRecord)
58
+ .filter(isRawBlock)
58
59
  .map(blockContent);
59
60
  if (blocks.length > 0)
60
61
  return blocks;
@@ -87,7 +88,7 @@ function digest(value, level, depth = 0) {
87
88
  const hidden = value.length - kept.length;
88
89
  return hidden > 0 ? [...kept, `…[+${hidden} more items]`] : kept;
89
90
  }
90
- if (isRecord(value)) {
91
+ if (isRawBlock(value)) {
91
92
  if (depth >= level.depth)
92
93
  return `{…${Object.keys(value).length} keys}`;
93
94
  return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, digest(item, level, depth + 1)]));
@@ -134,7 +135,14 @@ function compactMcpText(text) {
134
135
  const parsed = parseJson(text);
135
136
  return parsed ? JSON.stringify(parsed.value) : text;
136
137
  }
137
- async function spillFullResult(env, text, extension, context) {
138
+ function readableSpill(text) {
139
+ const parsed = parseJson(text);
140
+ return parsed
141
+ ? { text: JSON.stringify(parsed.value, null, 2), extension: "json" }
142
+ : { text, extension: "txt" };
143
+ }
144
+ async function spillFullResult(env, result, context) {
145
+ const { text, extension } = readableSpill(result);
138
146
  const path = await env.joinPath([env.cwd, ...SPILL_DIR, `${randomBytes(8).toString("hex")}.${extension}`], context);
139
147
  if (!path.ok)
140
148
  return undefined;
@@ -161,7 +169,7 @@ export async function guardMcpToolResult(result, env, context) {
161
169
  if (fits(combined, RESULT_LIMITS))
162
170
  return { content: blocks, details: undefined };
163
171
  const bounded = boundMcpText(combined, RESULT_LIMITS);
164
- const spillPath = await spillFullResult(env, combined, bounded.digest ? "json" : "txt", context);
172
+ const spillPath = await spillFullResult(env, combined, context);
165
173
  const notice = truncationNotice(bounded, Buffer.byteLength(combined, "utf8"), spillPath);
166
174
  return {
167
175
  content: [{ type: "text", text: `${bounded.text}\n\n${notice}` }, ...images],
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-result.js","sourceRoot":"","sources":["../../src/harness/mcp-result.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n truncateHead,\n type AgentToolResult,\n type Context,\n type ExecutionEnv,\n} from \"@earendil-works/pi-agent-core\";\nimport { redactSecrets } from \"./tools/secret-redaction.js\";\n\nexport interface McpTextLimits {\n maxBytes: number;\n maxLines: number;\n}\n\nexport interface BoundedMcpText {\n text: string;\n truncated: boolean;\n digest?: true;\n}\n\nexport interface McpCallResult {\n content?: unknown;\n structuredContent?: unknown;\n isError?: boolean;\n}\n\nconst SPILL_DIR = [\".mikan\", \"mcp-output\"];\nconst NOTICE_RESERVE_BYTES = 640;\nconst NOTICE_RESERVE_LINES = 4;\nconst RESULT_LIMITS: McpTextLimits = {\n maxBytes: DEFAULT_MAX_BYTES - NOTICE_RESERVE_BYTES,\n maxLines: DEFAULT_MAX_LINES - NOTICE_RESERVE_LINES,\n};\n\ninterface DigestLevel {\n stringChars: number;\n arrayItems: number;\n depth: number;\n}\n\nconst DIGEST_LEVELS: readonly DigestLevel[] = [\n { stringChars: 200, arrayItems: 3, depth: 6 },\n { stringChars: 80, arrayItems: 2, depth: 4 },\n { stringChars: 40, arrayItems: 1, depth: 3 },\n { stringChars: 16, arrayItems: 1, depth: 2 },\n];\n\ntype RawBlock = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is RawBlock {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stringField(block: RawBlock, key: string): string | undefined {\n const value = block[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction describeResource(resource: RawBlock): string {\n const uri = stringField(resource, \"uri\") ?? \"(no URI)\";\n const text = stringField(resource, \"text\");\n if (text !== undefined) return `[Resource: ${uri}]\\n${text}`;\n const blob = stringField(resource, \"blob\");\n const mimeType = stringField(resource, \"mimeType\") ?? \"unknown type\";\n const size = blob === undefined ? \"no content\" : `${Buffer.byteLength(blob, \"base64\")} bytes`;\n return `[Resource: ${uri} (${mimeType}, ${size}, binary content omitted)]`;\n}\n\nfunction blockContent(block: RawBlock): TextContent | ImageContent {\n const text = stringField(block, \"text\");\n if (block.type === \"text\" && text !== undefined) return { type: \"text\", text };\n const data = stringField(block, \"data\");\n const mimeType = stringField(block, \"mimeType\");\n if (block.type === \"image\" && data !== undefined && mimeType !== undefined) {\n return { type: \"image\", data, mimeType };\n }\n if (block.type === \"resource\" && isRecord(block.resource)) {\n return { type: \"text\", text: describeResource(block.resource) };\n }\n if (block.type === \"resource_link\") {\n const uri = stringField(block, \"uri\") ?? \"(no URI)\";\n return { type: \"text\", text: `[Resource link: ${stringField(block, \"name\") ?? uri}] ${uri}` };\n }\n if (block.type === \"audio\") {\n return { type: \"text\", text: `[Audio content omitted: ${mimeType ?? \"audio/*\"}]` };\n }\n return { type: \"text\", text: JSON.stringify(block) };\n}\n\nexport function mcpResultContent(result: McpCallResult): (TextContent | ImageContent)[] {\n const blocks = (Array.isArray(result.content) ? result.content : [])\n .filter(isRecord)\n .map(blockContent);\n if (blocks.length > 0) return blocks;\n if (result.structuredContent !== undefined && result.structuredContent !== null) {\n return [{ type: \"text\", text: JSON.stringify(result.structuredContent) }];\n }\n return [{ type: \"text\", text: \"(empty result)\" }];\n}\n\nfunction parseJson(text: string): { value: unknown } | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) return undefined;\n try {\n return { value: JSON.parse(text) };\n } catch {\n return undefined;\n }\n}\n\nfunction digest(value: unknown, level: DigestLevel, depth = 0): unknown {\n if (typeof value === \"string\") {\n return value.length <= level.stringChars\n ? value\n : `${value.slice(0, level.stringChars)}…[+${value.length - level.stringChars} chars]`;\n }\n if (Array.isArray(value)) {\n if (depth >= level.depth) return `[…${value.length} items]`;\n const kept = value.slice(0, level.arrayItems).map((item) => digest(item, level, depth + 1));\n const hidden = value.length - kept.length;\n return hidden > 0 ? [...kept, `…[+${hidden} more items]`] : kept;\n }\n if (isRecord(value)) {\n if (depth >= level.depth) return `{…${Object.keys(value).length} keys}`;\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, digest(item, level, depth + 1)]),\n );\n }\n return value;\n}\n\nfunction fits(text: string, limits: McpTextLimits): boolean {\n return (\n Buffer.byteLength(text, \"utf8\") <= limits.maxBytes && text.split(\"\\n\").length <= limits.maxLines\n );\n}\n\nfunction sliceToBytes(text: string, maxBytes: number): string {\n const buffer = Buffer.from(text, \"utf8\");\n if (buffer.length <= maxBytes) return text;\n let end = Math.max(0, maxBytes);\n while (end > 0 && (buffer[end]! & 0xc0) === 0x80) end--;\n return buffer.subarray(0, end).toString(\"utf8\");\n}\n\nfunction headTruncate(text: string, limits: McpTextLimits): string {\n const truncation = truncateHead(text, limits);\n return truncation.firstLineExceedsLimit\n ? sliceToBytes(text, limits.maxBytes)\n : truncation.content;\n}\n\nexport function boundMcpText(text: string, limits: McpTextLimits): BoundedMcpText {\n const parsed = parseJson(text);\n if (!parsed) {\n return fits(text, limits)\n ? { text, truncated: false }\n : { text: headTruncate(text, limits), truncated: true };\n }\n const compact = JSON.stringify(parsed.value);\n if (fits(compact, limits)) return { text: compact, truncated: false };\n for (const level of DIGEST_LEVELS) {\n const digested = JSON.stringify(digest(parsed.value, level));\n if (fits(digested, limits)) return { text: digested, truncated: true, digest: true };\n }\n const smallest = JSON.stringify(digest(parsed.value, DIGEST_LEVELS.at(-1)!));\n return { text: sliceToBytes(smallest, limits.maxBytes), truncated: true, digest: true };\n}\n\nfunction compactMcpText(text: string): string {\n const parsed = parseJson(text);\n return parsed ? JSON.stringify(parsed.value) : text;\n}\n\nasync function spillFullResult(\n env: ExecutionEnv,\n text: string,\n extension: \"json\" | \"txt\",\n context: Context,\n): Promise<string | undefined> {\n const path = await env.joinPath(\n [env.cwd, ...SPILL_DIR, `${randomBytes(8).toString(\"hex\")}.${extension}`],\n context,\n );\n if (!path.ok) return undefined;\n const written = await env.writeFile(path.value, redactSecrets(text), context);\n return written.ok ? path.value : undefined;\n}\n\nfunction truncationNotice(\n bounded: BoundedMcpText,\n totalBytes: number,\n spillPath: string | undefined,\n): string {\n const view = bounded.digest\n ? `an abbreviated view of ${formatSize(totalBytes)}: long strings, arrays, and deep nesting are shortened; keys, counts, and pagination fields are kept`\n : `the beginning of ${formatSize(totalBytes)}`;\n const full = spillPath\n ? `Full result: ${spillPath} — use read with offset/limit or grep to inspect it`\n : \"The full result could not be saved\";\n return `[MCP result truncated: showing ${view}. ${full}, or re-query with filters or smaller pages.]`;\n}\n\nexport async function guardMcpToolResult(\n result: McpCallResult,\n env: ExecutionEnv,\n context: Context,\n): Promise<AgentToolResult<undefined>> {\n const blocks = mcpResultContent(result).map((block) =>\n block.type === \"text\" ? Object.assign(block, { text: compactMcpText(block.text) }) : block,\n );\n const texts = blocks.filter((block): block is TextContent => block.type === \"text\");\n const images = blocks.filter((block): block is ImageContent => block.type === \"image\");\n const combined = texts.map((block) => block.text).join(\"\\n\");\n if (result.isError) {\n throw new Error(boundMcpText(combined, RESULT_LIMITS).text || \"MCP tool call failed\");\n }\n if (fits(combined, RESULT_LIMITS)) return { content: blocks, details: undefined };\n const bounded = boundMcpText(combined, RESULT_LIMITS);\n const spillPath = await spillFullResult(env, combined, bounded.digest ? \"json\" : \"txt\", context);\n const notice = truncationNotice(bounded, Buffer.byteLength(combined, \"utf8\"), spillPath);\n return {\n content: [{ type: \"text\", text: `${bounded.text}\\n\\n${notice}` }, ...images],\n details: undefined,\n };\n}\n"]}
1
+ {"version":3,"file":"mcp-result.js","sourceRoot":"","sources":["../../src/harness/mcp-result.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n truncateHead,\n type AgentToolResult,\n type Context,\n type ExecutionEnv,\n} from \"@earendil-works/pi-agent-core\";\nimport { redactSecrets } from \"./tools/secret-redaction.js\";\nimport { isRecord } from \"../unknown-values.js\";\n\nexport interface McpTextLimits {\n maxBytes: number;\n maxLines: number;\n}\n\nexport interface BoundedMcpText {\n text: string;\n truncated: boolean;\n digest?: true;\n}\n\nexport interface McpCallResult {\n content?: unknown;\n structuredContent?: unknown;\n isError?: boolean;\n}\n\nconst SPILL_DIR = [\".mikan\", \"mcp-output\"];\nconst NOTICE_RESERVE_BYTES = 640;\nconst NOTICE_RESERVE_LINES = 4;\nconst RESULT_LIMITS: McpTextLimits = {\n maxBytes: DEFAULT_MAX_BYTES - NOTICE_RESERVE_BYTES,\n maxLines: DEFAULT_MAX_LINES - NOTICE_RESERVE_LINES,\n};\n\ninterface DigestLevel {\n stringChars: number;\n arrayItems: number;\n depth: number;\n}\n\nconst DIGEST_LEVELS: readonly DigestLevel[] = [\n { stringChars: 200, arrayItems: 3, depth: 6 },\n { stringChars: 80, arrayItems: 2, depth: 4 },\n { stringChars: 40, arrayItems: 1, depth: 3 },\n { stringChars: 16, arrayItems: 1, depth: 2 },\n];\n\ntype RawBlock = Record<string, unknown>;\n\nfunction isRawBlock(value: unknown): value is RawBlock {\n return isRecord(value);\n}\n\nfunction stringField(block: RawBlock, key: string): string | undefined {\n const value = block[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction describeResource(resource: RawBlock): string {\n const uri = stringField(resource, \"uri\") ?? \"(no URI)\";\n const text = stringField(resource, \"text\");\n if (text !== undefined) return `[Resource: ${uri}]\\n${text}`;\n const blob = stringField(resource, \"blob\");\n const mimeType = stringField(resource, \"mimeType\") ?? \"unknown type\";\n const size = blob === undefined ? \"no content\" : `${Buffer.byteLength(blob, \"base64\")} bytes`;\n return `[Resource: ${uri} (${mimeType}, ${size}, binary content omitted)]`;\n}\n\nfunction blockContent(block: RawBlock): TextContent | ImageContent {\n const text = stringField(block, \"text\");\n if (block.type === \"text\" && text !== undefined) return { type: \"text\", text };\n const data = stringField(block, \"data\");\n const mimeType = stringField(block, \"mimeType\");\n if (block.type === \"image\" && data !== undefined && mimeType !== undefined) {\n return { type: \"image\", data, mimeType };\n }\n if (block.type === \"resource\" && isRawBlock(block.resource)) {\n return { type: \"text\", text: describeResource(block.resource) };\n }\n if (block.type === \"resource_link\") {\n const uri = stringField(block, \"uri\") ?? \"(no URI)\";\n return { type: \"text\", text: `[Resource link: ${stringField(block, \"name\") ?? uri}] ${uri}` };\n }\n if (block.type === \"audio\") {\n return { type: \"text\", text: `[Audio content omitted: ${mimeType ?? \"audio/*\"}]` };\n }\n return { type: \"text\", text: JSON.stringify(block) };\n}\n\nexport function mcpResultContent(result: McpCallResult): (TextContent | ImageContent)[] {\n const blocks = (Array.isArray(result.content) ? result.content : [])\n .filter(isRawBlock)\n .map(blockContent);\n if (blocks.length > 0) return blocks;\n if (result.structuredContent !== undefined && result.structuredContent !== null) {\n return [{ type: \"text\", text: JSON.stringify(result.structuredContent) }];\n }\n return [{ type: \"text\", text: \"(empty result)\" }];\n}\n\nfunction parseJson(text: string): { value: unknown } | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) return undefined;\n try {\n return { value: JSON.parse(text) };\n } catch {\n return undefined;\n }\n}\n\nfunction digest(value: unknown, level: DigestLevel, depth = 0): unknown {\n if (typeof value === \"string\") {\n return value.length <= level.stringChars\n ? value\n : `${value.slice(0, level.stringChars)}…[+${value.length - level.stringChars} chars]`;\n }\n if (Array.isArray(value)) {\n if (depth >= level.depth) return `[…${value.length} items]`;\n const kept = value.slice(0, level.arrayItems).map((item) => digest(item, level, depth + 1));\n const hidden = value.length - kept.length;\n return hidden > 0 ? [...kept, `…[+${hidden} more items]`] : kept;\n }\n if (isRawBlock(value)) {\n if (depth >= level.depth) return `{…${Object.keys(value).length} keys}`;\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, digest(item, level, depth + 1)]),\n );\n }\n return value;\n}\n\nfunction fits(text: string, limits: McpTextLimits): boolean {\n return (\n Buffer.byteLength(text, \"utf8\") <= limits.maxBytes && text.split(\"\\n\").length <= limits.maxLines\n );\n}\n\nfunction sliceToBytes(text: string, maxBytes: number): string {\n const buffer = Buffer.from(text, \"utf8\");\n if (buffer.length <= maxBytes) return text;\n let end = Math.max(0, maxBytes);\n while (end > 0 && (buffer[end]! & 0xc0) === 0x80) end--;\n return buffer.subarray(0, end).toString(\"utf8\");\n}\n\nfunction headTruncate(text: string, limits: McpTextLimits): string {\n const truncation = truncateHead(text, limits);\n return truncation.firstLineExceedsLimit\n ? sliceToBytes(text, limits.maxBytes)\n : truncation.content;\n}\n\nexport function boundMcpText(text: string, limits: McpTextLimits): BoundedMcpText {\n const parsed = parseJson(text);\n if (!parsed) {\n return fits(text, limits)\n ? { text, truncated: false }\n : { text: headTruncate(text, limits), truncated: true };\n }\n const compact = JSON.stringify(parsed.value);\n if (fits(compact, limits)) return { text: compact, truncated: false };\n for (const level of DIGEST_LEVELS) {\n const digested = JSON.stringify(digest(parsed.value, level));\n if (fits(digested, limits)) return { text: digested, truncated: true, digest: true };\n }\n const smallest = JSON.stringify(digest(parsed.value, DIGEST_LEVELS.at(-1)!));\n return { text: sliceToBytes(smallest, limits.maxBytes), truncated: true, digest: true };\n}\n\nfunction compactMcpText(text: string): string {\n const parsed = parseJson(text);\n return parsed ? JSON.stringify(parsed.value) : text;\n}\n\nfunction readableSpill(text: string): { text: string; extension: \"json\" | \"txt\" } {\n const parsed = parseJson(text);\n return parsed\n ? { text: JSON.stringify(parsed.value, null, 2), extension: \"json\" }\n : { text, extension: \"txt\" };\n}\n\nasync function spillFullResult(\n env: ExecutionEnv,\n result: string,\n context: Context,\n): Promise<string | undefined> {\n const { text, extension } = readableSpill(result);\n const path = await env.joinPath(\n [env.cwd, ...SPILL_DIR, `${randomBytes(8).toString(\"hex\")}.${extension}`],\n context,\n );\n if (!path.ok) return undefined;\n const written = await env.writeFile(path.value, redactSecrets(text), context);\n return written.ok ? path.value : undefined;\n}\n\nfunction truncationNotice(\n bounded: BoundedMcpText,\n totalBytes: number,\n spillPath: string | undefined,\n): string {\n const view = bounded.digest\n ? `an abbreviated view of ${formatSize(totalBytes)}: long strings, arrays, and deep nesting are shortened; keys, counts, and pagination fields are kept`\n : `the beginning of ${formatSize(totalBytes)}`;\n const full = spillPath\n ? `Full result: ${spillPath} — use read with offset/limit or grep to inspect it`\n : \"The full result could not be saved\";\n return `[MCP result truncated: showing ${view}. ${full}, or re-query with filters or smaller pages.]`;\n}\n\nexport async function guardMcpToolResult(\n result: McpCallResult,\n env: ExecutionEnv,\n context: Context,\n): Promise<AgentToolResult<undefined>> {\n const blocks = mcpResultContent(result).map((block) =>\n block.type === \"text\" ? Object.assign(block, { text: compactMcpText(block.text) }) : block,\n );\n const texts = blocks.filter((block): block is TextContent => block.type === \"text\");\n const images = blocks.filter((block): block is ImageContent => block.type === \"image\");\n const combined = texts.map((block) => block.text).join(\"\\n\");\n if (result.isError) {\n throw new Error(boundMcpText(combined, RESULT_LIMITS).text || \"MCP tool call failed\");\n }\n if (fits(combined, RESULT_LIMITS)) return { content: blocks, details: undefined };\n const bounded = boundMcpText(combined, RESULT_LIMITS);\n const spillPath = await spillFullResult(env, combined, context);\n const notice = truncationNotice(bounded, Buffer.byteLength(combined, \"utf8\"), spillPath);\n return {\n content: [{ type: \"text\", text: `${bounded.text}\\n\\n${notice}` }, ...images],\n details: undefined,\n };\n}\n"]}