@geminixiang/mikan 1.0.0-beta.3 → 1.0.0-beta.31

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 (545) hide show
  1. package/CHANGELOG.md +577 -0
  2. package/README.md +60 -24
  3. package/dist/adapter.d.ts +1 -1
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/adapters/discord/bot.d.ts +1 -0
  7. package/dist/adapters/discord/bot.d.ts.map +1 -1
  8. package/dist/adapters/discord/bot.js +47 -65
  9. package/dist/adapters/discord/bot.js.map +1 -1
  10. package/dist/adapters/discord/context.d.ts.map +1 -1
  11. package/dist/adapters/discord/context.js +46 -211
  12. package/dist/adapters/discord/context.js.map +1 -1
  13. package/dist/adapters/github/bot.d.ts +86 -0
  14. package/dist/adapters/github/bot.d.ts.map +1 -0
  15. package/dist/adapters/github/bot.js +640 -0
  16. package/dist/adapters/github/bot.js.map +1 -0
  17. package/dist/adapters/github/client.d.ts +122 -0
  18. package/dist/adapters/github/client.d.ts.map +1 -0
  19. package/dist/adapters/github/client.js +314 -0
  20. package/dist/adapters/github/client.js.map +1 -0
  21. package/dist/adapters/github/cloudbuild.d.ts +19 -0
  22. package/dist/adapters/github/cloudbuild.d.ts.map +1 -0
  23. package/dist/adapters/github/cloudbuild.js +71 -0
  24. package/dist/adapters/github/cloudbuild.js.map +1 -0
  25. package/dist/adapters/github/context.d.ts +9 -0
  26. package/dist/adapters/github/context.d.ts.map +1 -0
  27. package/dist/adapters/github/context.js +98 -0
  28. package/dist/adapters/github/context.js.map +1 -0
  29. package/dist/adapters/github/gcp-auth.d.ts +28 -0
  30. package/dist/adapters/github/gcp-auth.d.ts.map +1 -0
  31. package/dist/adapters/github/gcp-auth.js +196 -0
  32. package/dist/adapters/github/gcp-auth.js.map +1 -0
  33. package/dist/adapters/github/github-ops.d.ts +90 -0
  34. package/dist/adapters/github/github-ops.d.ts.map +1 -0
  35. package/dist/adapters/github/github-ops.js +405 -0
  36. package/dist/adapters/github/github-ops.js.map +1 -0
  37. package/dist/adapters/github/ids.d.ts +34 -0
  38. package/dist/adapters/github/ids.d.ts.map +1 -0
  39. package/dist/adapters/github/ids.js +53 -0
  40. package/dist/adapters/github/ids.js.map +1 -0
  41. package/dist/adapters/github/repo.d.ts +32 -0
  42. package/dist/adapters/github/repo.d.ts.map +1 -0
  43. package/dist/adapters/github/repo.js +141 -0
  44. package/dist/adapters/github/repo.js.map +1 -0
  45. package/dist/adapters/github/tool-pack.d.ts +14 -0
  46. package/dist/adapters/github/tool-pack.d.ts.map +1 -0
  47. package/dist/adapters/github/tool-pack.js +56 -0
  48. package/dist/adapters/github/tool-pack.js.map +1 -0
  49. package/dist/adapters/github/tools/checks.d.ts +19 -0
  50. package/dist/adapters/github/tools/checks.d.ts.map +1 -0
  51. package/dist/adapters/github/tools/checks.js +105 -0
  52. package/dist/adapters/github/tools/checks.js.map +1 -0
  53. package/dist/adapters/github/tools/issue.d.ts +21 -0
  54. package/dist/adapters/github/tools/issue.d.ts.map +1 -0
  55. package/dist/adapters/github/tools/issue.js +48 -0
  56. package/dist/adapters/github/tools/issue.js.map +1 -0
  57. package/dist/adapters/github/tools/pr.d.ts +22 -0
  58. package/dist/adapters/github/tools/pr.d.ts.map +1 -0
  59. package/dist/adapters/github/tools/pr.js +48 -0
  60. package/dist/adapters/github/tools/pr.js.map +1 -0
  61. package/dist/adapters/github/tools/read.d.ts +21 -0
  62. package/dist/adapters/github/tools/read.d.ts.map +1 -0
  63. package/dist/adapters/github/tools/read.js +141 -0
  64. package/dist/adapters/github/tools/read.js.map +1 -0
  65. package/dist/adapters/github/tools/review-reply.d.ts +17 -0
  66. package/dist/adapters/github/tools/review-reply.d.ts.map +1 -0
  67. package/dist/adapters/github/tools/review-reply.js +38 -0
  68. package/dist/adapters/github/tools/review-reply.js.map +1 -0
  69. package/dist/adapters/github/tools/sync.d.ts +17 -0
  70. package/dist/adapters/github/tools/sync.d.ts.map +1 -0
  71. package/dist/adapters/github/tools/sync.js +34 -0
  72. package/dist/adapters/github/tools/sync.js.map +1 -0
  73. package/dist/adapters/github/types.d.ts +372 -0
  74. package/dist/adapters/github/types.d.ts.map +1 -0
  75. package/dist/adapters/github/types.js +2 -0
  76. package/dist/adapters/github/types.js.map +1 -0
  77. package/dist/adapters/intake.d.ts +16 -5
  78. package/dist/adapters/intake.d.ts.map +1 -1
  79. package/dist/adapters/intake.js +84 -22
  80. package/dist/adapters/intake.js.map +1 -1
  81. package/dist/adapters/progressive-renderer.d.ts +7 -0
  82. package/dist/adapters/progressive-renderer.d.ts.map +1 -0
  83. package/dist/adapters/progressive-renderer.js +383 -0
  84. package/dist/adapters/progressive-renderer.js.map +1 -0
  85. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  86. package/dist/adapters/slack/blocks.js +111 -111
  87. package/dist/adapters/slack/blocks.js.map +1 -1
  88. package/dist/adapters/slack/bot.d.ts +10 -6
  89. package/dist/adapters/slack/bot.d.ts.map +1 -1
  90. package/dist/adapters/slack/bot.js +173 -145
  91. package/dist/adapters/slack/bot.js.map +1 -1
  92. package/dist/adapters/slack/context.d.ts.map +1 -1
  93. package/dist/adapters/slack/context.js +3 -14
  94. package/dist/adapters/slack/context.js.map +1 -1
  95. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  96. package/dist/adapters/slack/response-lifecycle.js +126 -323
  97. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  98. package/dist/adapters/slack/session.d.ts.map +1 -1
  99. package/dist/adapters/slack/session.js +5 -8
  100. package/dist/adapters/slack/session.js.map +1 -1
  101. package/dist/adapters/slack/tool-pack.d.ts +11 -0
  102. package/dist/adapters/slack/tool-pack.d.ts.map +1 -0
  103. package/dist/adapters/slack/tool-pack.js +45 -0
  104. package/dist/adapters/slack/tool-pack.js.map +1 -0
  105. package/dist/adapters/slack/tools/blockkit.d.ts +14 -0
  106. package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -0
  107. package/dist/adapters/slack/tools/blockkit.js +106 -0
  108. package/dist/adapters/slack/tools/blockkit.js.map +1 -0
  109. package/dist/adapters/slack/types.d.ts +37 -0
  110. package/dist/adapters/slack/types.d.ts.map +1 -1
  111. package/dist/adapters/slack/types.js.map +1 -1
  112. package/dist/adapters/telegram/bot.d.ts +1 -2
  113. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  114. package/dist/adapters/telegram/bot.js +51 -63
  115. package/dist/adapters/telegram/bot.js.map +1 -1
  116. package/dist/adapters/telegram/context.d.ts.map +1 -1
  117. package/dist/adapters/telegram/context.js +55 -182
  118. package/dist/adapters/telegram/context.js.map +1 -1
  119. package/dist/adapters/types.d.ts +86 -10
  120. package/dist/adapters/types.d.ts.map +1 -1
  121. package/dist/adapters/types.js.map +1 -1
  122. package/dist/agent.d.ts +14 -19
  123. package/dist/agent.d.ts.map +1 -1
  124. package/dist/agent.js +711 -243
  125. package/dist/agent.js.map +1 -1
  126. package/dist/cli/arg-grammar.d.ts +25 -0
  127. package/dist/cli/arg-grammar.d.ts.map +1 -0
  128. package/dist/cli/arg-grammar.js +59 -0
  129. package/dist/cli/arg-grammar.js.map +1 -0
  130. package/dist/cli/boot.d.ts +5 -0
  131. package/dist/cli/boot.d.ts.map +1 -0
  132. package/dist/cli/boot.js +112 -0
  133. package/dist/cli/boot.js.map +1 -0
  134. package/dist/cli/download.d.ts.map +1 -0
  135. package/dist/cli/download.js.map +1 -0
  136. package/dist/cli/ext-dev.d.ts +2 -0
  137. package/dist/cli/ext-dev.d.ts.map +1 -0
  138. package/dist/cli/ext-dev.js +177 -0
  139. package/dist/cli/ext-dev.js.map +1 -0
  140. package/dist/cli/ext-git.d.ts +17 -0
  141. package/dist/cli/ext-git.d.ts.map +1 -0
  142. package/dist/cli/ext-git.js +107 -0
  143. package/dist/cli/ext-git.js.map +1 -0
  144. package/dist/cli/ext.d.ts +2 -0
  145. package/dist/cli/ext.d.ts.map +1 -0
  146. package/dist/cli/ext.js +222 -0
  147. package/dist/cli/ext.js.map +1 -0
  148. package/dist/cli/types.d.ts +20 -0
  149. package/dist/cli/types.d.ts.map +1 -0
  150. package/dist/cli/types.js +2 -0
  151. package/dist/cli/types.js.map +1 -0
  152. package/dist/commands/admin.d.ts.map +1 -1
  153. package/dist/commands/admin.js +2 -1
  154. package/dist/commands/admin.js.map +1 -1
  155. package/dist/commands/auto-reply.d.ts.map +1 -1
  156. package/dist/commands/auto-reply.js +2 -6
  157. package/dist/commands/auto-reply.js.map +1 -1
  158. package/dist/commands/extensions.d.ts.map +1 -1
  159. package/dist/commands/extensions.js +18 -8
  160. package/dist/commands/extensions.js.map +1 -1
  161. package/dist/commands/login.d.ts +2 -1
  162. package/dist/commands/login.d.ts.map +1 -1
  163. package/dist/commands/login.js +35 -3
  164. package/dist/commands/login.js.map +1 -1
  165. package/dist/commands/manifest.d.ts +30 -0
  166. package/dist/commands/manifest.d.ts.map +1 -0
  167. package/dist/commands/manifest.js +121 -0
  168. package/dist/commands/manifest.js.map +1 -0
  169. package/dist/commands/model.d.ts +2 -3
  170. package/dist/commands/model.d.ts.map +1 -1
  171. package/dist/commands/model.js +57 -20
  172. package/dist/commands/model.js.map +1 -1
  173. package/dist/commands/new.d.ts.map +1 -1
  174. package/dist/commands/new.js +10 -2
  175. package/dist/commands/new.js.map +1 -1
  176. package/dist/commands/registry.d.ts +2 -2
  177. package/dist/commands/registry.d.ts.map +1 -1
  178. package/dist/commands/registry.js +1 -2
  179. package/dist/commands/registry.js.map +1 -1
  180. package/dist/commands/sandbox.d.ts.map +1 -1
  181. package/dist/commands/sandbox.js +23 -17
  182. package/dist/commands/sandbox.js.map +1 -1
  183. package/dist/commands/text.d.ts +2 -0
  184. package/dist/commands/text.d.ts.map +1 -0
  185. package/dist/commands/text.js +16 -0
  186. package/dist/commands/text.js.map +1 -0
  187. package/dist/commands/types.d.ts +70 -2
  188. package/dist/commands/types.d.ts.map +1 -1
  189. package/dist/commands/types.js.map +1 -1
  190. package/dist/config.d.ts +1 -3
  191. package/dist/config.d.ts.map +1 -1
  192. package/dist/config.js +102 -95
  193. package/dist/config.js.map +1 -1
  194. package/dist/env-manifest.d.ts +28 -0
  195. package/dist/env-manifest.d.ts.map +1 -0
  196. package/dist/env-manifest.js +214 -0
  197. package/dist/env-manifest.js.map +1 -0
  198. package/dist/events.d.ts.map +1 -1
  199. package/dist/events.js +9 -73
  200. package/dist/events.js.map +1 -1
  201. package/dist/execution-resolver.d.ts +7 -6
  202. package/dist/execution-resolver.d.ts.map +1 -1
  203. package/dist/execution-resolver.js +105 -110
  204. package/dist/execution-resolver.js.map +1 -1
  205. package/dist/harness/auth.d.ts +2 -1
  206. package/dist/harness/auth.d.ts.map +1 -1
  207. package/dist/harness/auth.js +6 -0
  208. package/dist/harness/auth.js.map +1 -1
  209. package/dist/harness/event-format.d.ts +25 -0
  210. package/dist/harness/event-format.d.ts.map +1 -0
  211. package/dist/harness/event-format.js +159 -0
  212. package/dist/harness/event-format.js.map +1 -0
  213. package/dist/harness/extensions/blockkit.d.ts +19 -0
  214. package/dist/harness/extensions/blockkit.d.ts.map +1 -0
  215. package/dist/harness/extensions/blockkit.js +42 -0
  216. package/dist/harness/extensions/blockkit.js.map +1 -0
  217. package/dist/harness/extensions/loader.d.ts +25 -48
  218. package/dist/harness/extensions/loader.d.ts.map +1 -1
  219. package/dist/harness/extensions/loader.js +373 -113
  220. package/dist/harness/extensions/loader.js.map +1 -1
  221. package/dist/harness/extensions/registry.d.ts +75 -2
  222. package/dist/harness/extensions/registry.d.ts.map +1 -1
  223. package/dist/harness/extensions/registry.js +239 -0
  224. package/dist/harness/extensions/registry.js.map +1 -1
  225. package/dist/harness/extensions/types.d.ts +318 -25
  226. package/dist/harness/extensions/types.d.ts.map +1 -1
  227. package/dist/harness/extensions/types.js.map +1 -1
  228. package/dist/harness/index.d.ts +18 -8
  229. package/dist/harness/index.d.ts.map +1 -1
  230. package/dist/harness/index.js +7 -4
  231. package/dist/harness/index.js.map +1 -1
  232. package/dist/harness/models.d.ts +7 -4
  233. package/dist/harness/models.d.ts.map +1 -1
  234. package/dist/harness/models.js +10 -0
  235. package/dist/harness/models.js.map +1 -1
  236. package/dist/harness/runner.d.ts +50 -54
  237. package/dist/harness/runner.d.ts.map +1 -1
  238. package/dist/harness/runner.js +230 -44
  239. package/dist/harness/runner.js.map +1 -1
  240. package/dist/harness/session-store.d.ts +9 -5
  241. package/dist/harness/session-store.d.ts.map +1 -1
  242. package/dist/harness/session-store.js +131 -30
  243. package/dist/harness/session-store.js.map +1 -1
  244. package/dist/harness/settings.d.ts +2 -20
  245. package/dist/harness/settings.d.ts.map +1 -1
  246. package/dist/harness/settings.js +11 -0
  247. package/dist/harness/settings.js.map +1 -1
  248. package/dist/harness/skills.d.ts +2 -29
  249. package/dist/harness/skills.d.ts.map +1 -1
  250. package/dist/harness/skills.js.map +1 -1
  251. package/dist/harness/subagent-profiles.d.ts +8 -0
  252. package/dist/harness/subagent-profiles.d.ts.map +1 -0
  253. package/dist/harness/subagent-profiles.js +290 -0
  254. package/dist/harness/subagent-profiles.js.map +1 -0
  255. package/dist/harness/subagent-runner.d.ts +39 -0
  256. package/dist/harness/subagent-runner.d.ts.map +1 -0
  257. package/dist/harness/subagent-runner.js +615 -0
  258. package/dist/harness/subagent-runner.js.map +1 -0
  259. package/dist/harness/types.d.ts +263 -1
  260. package/dist/harness/types.d.ts.map +1 -1
  261. package/dist/harness/types.js.map +1 -1
  262. package/dist/harness/usage.d.ts +6 -0
  263. package/dist/harness/usage.d.ts.map +1 -0
  264. package/dist/harness/usage.js +32 -0
  265. package/dist/harness/usage.js.map +1 -0
  266. package/dist/index.d.ts +33 -8
  267. package/dist/index.d.ts.map +1 -1
  268. package/dist/index.js +20 -6
  269. package/dist/index.js.map +1 -1
  270. package/dist/main.js +253 -109
  271. package/dist/main.js.map +1 -1
  272. package/dist/observability/instrument.js +6 -4
  273. package/dist/observability/instrument.js.map +1 -1
  274. package/dist/observability/sentry.d.ts.map +1 -1
  275. package/dist/observability/sentry.js +3 -2
  276. package/dist/observability/sentry.js.map +1 -1
  277. package/dist/packages/admin.d.ts +17 -0
  278. package/dist/packages/admin.d.ts.map +1 -0
  279. package/dist/packages/admin.js +96 -0
  280. package/dist/packages/admin.js.map +1 -0
  281. package/dist/packages/index.d.ts +6 -0
  282. package/dist/packages/index.d.ts.map +1 -0
  283. package/dist/packages/index.js +6 -0
  284. package/dist/packages/index.js.map +1 -0
  285. package/dist/packages/inspect.d.ts +11 -0
  286. package/dist/packages/inspect.d.ts.map +1 -0
  287. package/dist/packages/inspect.js +100 -0
  288. package/dist/packages/inspect.js.map +1 -0
  289. package/dist/packages/materialize.d.ts +39 -0
  290. package/dist/packages/materialize.d.ts.map +1 -0
  291. package/dist/packages/materialize.js +300 -0
  292. package/dist/packages/materialize.js.map +1 -0
  293. package/dist/packages/resolve.d.ts +25 -0
  294. package/dist/packages/resolve.d.ts.map +1 -0
  295. package/dist/packages/resolve.js +212 -0
  296. package/dist/packages/resolve.js.map +1 -0
  297. package/dist/packages/source.d.ts +33 -0
  298. package/dist/packages/source.d.ts.map +1 -0
  299. package/dist/packages/source.js +177 -0
  300. package/dist/packages/source.js.map +1 -0
  301. package/dist/packages/types.d.ts +104 -0
  302. package/dist/packages/types.d.ts.map +1 -0
  303. package/dist/packages/types.js +2 -0
  304. package/dist/packages/types.js.map +1 -0
  305. package/dist/provisioner.d.ts.map +1 -1
  306. package/dist/provisioner.js +6 -6
  307. package/dist/provisioner.js.map +1 -1
  308. package/dist/runtime/conversation-runtime.d.ts +1 -1
  309. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  310. package/dist/runtime/conversation-runtime.js +481 -98
  311. package/dist/runtime/conversation-runtime.js.map +1 -1
  312. package/dist/runtime/session-lifecycle.d.ts +28 -0
  313. package/dist/runtime/session-lifecycle.d.ts.map +1 -0
  314. package/dist/runtime/session-lifecycle.js +161 -0
  315. package/dist/runtime/session-lifecycle.js.map +1 -0
  316. package/dist/runtime/types.d.ts +45 -5
  317. package/dist/runtime/types.d.ts.map +1 -1
  318. package/dist/runtime/types.js.map +1 -1
  319. package/dist/sandbox/cloudflare.d.ts +3 -0
  320. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  321. package/dist/sandbox/cloudflare.js +11 -0
  322. package/dist/sandbox/cloudflare.js.map +1 -1
  323. package/dist/sandbox/container.d.ts +4 -0
  324. package/dist/sandbox/container.d.ts.map +1 -1
  325. package/dist/sandbox/container.js +12 -2
  326. package/dist/sandbox/container.js.map +1 -1
  327. package/dist/sandbox/firecracker.d.ts +3 -0
  328. package/dist/sandbox/firecracker.d.ts.map +1 -1
  329. package/dist/sandbox/firecracker.js +11 -1
  330. package/dist/sandbox/firecracker.js.map +1 -1
  331. package/dist/sandbox/gondolin.d.ts +57 -0
  332. package/dist/sandbox/gondolin.d.ts.map +1 -0
  333. package/dist/sandbox/gondolin.js +764 -0
  334. package/dist/sandbox/gondolin.js.map +1 -0
  335. package/dist/sandbox/host.d.ts +3 -0
  336. package/dist/sandbox/host.d.ts.map +1 -1
  337. package/dist/sandbox/host.js +15 -0
  338. package/dist/sandbox/host.js.map +1 -1
  339. package/dist/sandbox/identity.d.ts +16 -0
  340. package/dist/sandbox/identity.d.ts.map +1 -0
  341. package/dist/sandbox/identity.js +42 -0
  342. package/dist/sandbox/identity.js.map +1 -0
  343. package/dist/sandbox/image.d.ts.map +1 -1
  344. package/dist/sandbox/image.js +1 -0
  345. package/dist/sandbox/image.js.map +1 -1
  346. package/dist/sandbox/index.d.ts +15 -4
  347. package/dist/sandbox/index.d.ts.map +1 -1
  348. package/dist/sandbox/index.js +25 -3
  349. package/dist/sandbox/index.js.map +1 -1
  350. package/dist/sandbox/path-context.js +18 -8
  351. package/dist/sandbox/path-context.js.map +1 -1
  352. package/dist/sandbox/types.d.ts +59 -1
  353. package/dist/sandbox/types.d.ts.map +1 -1
  354. package/dist/sandbox/types.js.map +1 -1
  355. package/dist/sandbox/utils.d.ts +12 -0
  356. package/dist/sandbox/utils.d.ts.map +1 -1
  357. package/dist/sandbox/utils.js +38 -0
  358. package/dist/sandbox/utils.js.map +1 -1
  359. package/dist/sessions/chat-history-sync.d.ts +25 -0
  360. package/dist/sessions/chat-history-sync.d.ts.map +1 -0
  361. package/dist/sessions/{agent-memory-file-manager.js → chat-history-sync.js} +98 -124
  362. package/dist/sessions/chat-history-sync.js.map +1 -0
  363. package/dist/sessions/conversation-log.d.ts +9 -0
  364. package/dist/sessions/conversation-log.d.ts.map +1 -0
  365. package/dist/sessions/conversation-log.js +47 -0
  366. package/dist/sessions/conversation-log.js.map +1 -0
  367. package/dist/sessions/history-line.d.ts +20 -0
  368. package/dist/sessions/history-line.d.ts.map +1 -0
  369. package/dist/sessions/history-line.js +24 -0
  370. package/dist/sessions/history-line.js.map +1 -0
  371. package/dist/sessions/policy.d.ts.map +1 -1
  372. package/dist/sessions/policy.js +5 -3
  373. package/dist/sessions/policy.js.map +1 -1
  374. package/dist/sessions/rotation.d.ts +2 -0
  375. package/dist/sessions/rotation.d.ts.map +1 -0
  376. package/dist/sessions/rotation.js +39 -0
  377. package/dist/sessions/rotation.js.map +1 -0
  378. package/dist/sessions/session-key.d.ts +40 -0
  379. package/dist/sessions/session-key.d.ts.map +1 -0
  380. package/dist/sessions/session-key.js +92 -0
  381. package/dist/sessions/session-key.js.map +1 -0
  382. package/dist/sessions/store.d.ts.map +1 -1
  383. package/dist/sessions/store.js +40 -18
  384. package/dist/sessions/store.js.map +1 -1
  385. package/dist/sessions/types.d.ts +17 -4
  386. package/dist/sessions/types.d.ts.map +1 -1
  387. package/dist/sessions/types.js.map +1 -1
  388. package/dist/settings-mutation.d.ts +8 -0
  389. package/dist/settings-mutation.d.ts.map +1 -0
  390. package/dist/settings-mutation.js +43 -0
  391. package/dist/settings-mutation.js.map +1 -0
  392. package/dist/subagent-progress.d.ts +43 -0
  393. package/dist/subagent-progress.d.ts.map +1 -0
  394. package/dist/subagent-progress.js +220 -0
  395. package/dist/subagent-progress.js.map +1 -0
  396. package/dist/tools/bash.d.ts +3 -1
  397. package/dist/tools/bash.d.ts.map +1 -1
  398. package/dist/tools/bash.js +25 -17
  399. package/dist/tools/bash.js.map +1 -1
  400. package/dist/tools/edit.d.ts.map +1 -1
  401. package/dist/tools/edit.js +10 -12
  402. package/dist/tools/edit.js.map +1 -1
  403. package/dist/tools/event.d.ts +1 -1
  404. package/dist/tools/event.d.ts.map +1 -1
  405. package/dist/tools/event.js +53 -43
  406. package/dist/tools/event.js.map +1 -1
  407. package/dist/tools/generate-image.d.ts +17 -0
  408. package/dist/tools/generate-image.d.ts.map +1 -0
  409. package/dist/tools/generate-image.js +63 -0
  410. package/dist/tools/generate-image.js.map +1 -0
  411. package/dist/tools/host-fn-tool.d.ts +21 -0
  412. package/dist/tools/host-fn-tool.d.ts.map +1 -0
  413. package/dist/tools/host-fn-tool.js +32 -0
  414. package/dist/tools/host-fn-tool.js.map +1 -0
  415. package/dist/tools/index.d.ts +14 -2
  416. package/dist/tools/index.d.ts.map +1 -1
  417. package/dist/tools/index.js +28 -3
  418. package/dist/tools/index.js.map +1 -1
  419. package/dist/tools/react.d.ts +15 -0
  420. package/dist/tools/react.d.ts.map +1 -0
  421. package/dist/tools/react.js +29 -0
  422. package/dist/tools/react.js.map +1 -0
  423. package/dist/tools/read.d.ts +1 -0
  424. package/dist/tools/read.d.ts.map +1 -1
  425. package/dist/tools/read.js +37 -31
  426. package/dist/tools/read.js.map +1 -1
  427. package/dist/tools/sandbox.d.ts +2 -2
  428. package/dist/tools/sandbox.d.ts.map +1 -1
  429. package/dist/tools/sandbox.js +14 -9
  430. package/dist/tools/sandbox.js.map +1 -1
  431. package/dist/tools/subagent-slots.d.ts +28 -0
  432. package/dist/tools/subagent-slots.d.ts.map +1 -0
  433. package/dist/tools/subagent-slots.js +72 -0
  434. package/dist/tools/subagent-slots.js.map +1 -0
  435. package/dist/tools/subagent.d.ts +54 -0
  436. package/dist/tools/subagent.d.ts.map +1 -0
  437. package/dist/tools/subagent.js +401 -0
  438. package/dist/tools/subagent.js.map +1 -0
  439. package/dist/tools/types.d.ts +40 -6
  440. package/dist/tools/types.d.ts.map +1 -1
  441. package/dist/tools/types.js.map +1 -1
  442. package/dist/tools/write.d.ts.map +1 -1
  443. package/dist/tools/write.js +2 -8
  444. package/dist/tools/write.js.map +1 -1
  445. package/dist/trigger.d.ts.map +1 -1
  446. package/dist/trigger.js +1 -2
  447. package/dist/trigger.js.map +1 -1
  448. package/dist/types.d.ts +232 -32
  449. package/dist/types.d.ts.map +1 -1
  450. package/dist/types.js.map +1 -1
  451. package/dist/utils/date.d.ts +1 -1
  452. package/dist/utils/date.js +1 -1
  453. package/dist/utils/date.js.map +1 -1
  454. package/dist/vault/disabled.d.ts +9 -0
  455. package/dist/vault/disabled.d.ts.map +1 -0
  456. package/dist/vault/disabled.js +22 -0
  457. package/dist/vault/disabled.js.map +1 -0
  458. package/dist/vault/index.d.ts +0 -2
  459. package/dist/vault/index.d.ts.map +1 -1
  460. package/dist/vault/index.js +30 -33
  461. package/dist/vault/index.js.map +1 -1
  462. package/dist/vault/injection.d.ts +10 -0
  463. package/dist/vault/injection.d.ts.map +1 -0
  464. package/dist/vault/injection.js +30 -0
  465. package/dist/vault/injection.js.map +1 -0
  466. package/dist/vault/policy.d.ts +20 -0
  467. package/dist/vault/policy.d.ts.map +1 -0
  468. package/dist/vault/policy.js +20 -0
  469. package/dist/vault/policy.js.map +1 -0
  470. package/dist/vault/types.d.ts +4 -2
  471. package/dist/vault/types.d.ts.map +1 -1
  472. package/dist/vault/types.js.map +1 -1
  473. package/dist/web/admin/portal.d.ts +17 -2
  474. package/dist/web/admin/portal.d.ts.map +1 -1
  475. package/dist/web/admin/portal.js +385 -155
  476. package/dist/web/admin/portal.js.map +1 -1
  477. package/dist/web/admin/types.d.ts +18 -0
  478. package/dist/web/admin/types.d.ts.map +1 -1
  479. package/dist/web/admin/types.js.map +1 -1
  480. package/dist/web/agent-events/portal.d.ts.map +1 -1
  481. package/dist/web/agent-events/portal.js +2 -1
  482. package/dist/web/agent-events/portal.js.map +1 -1
  483. package/dist/web/login/oauth.d.ts +2 -3
  484. package/dist/web/login/oauth.d.ts.map +1 -1
  485. package/dist/web/login/oauth.js +0 -31
  486. package/dist/web/login/oauth.js.map +1 -1
  487. package/dist/web/login/portal.js +1 -1
  488. package/dist/web/login/portal.js.map +1 -1
  489. package/dist/web/login/types.d.ts +0 -11
  490. package/dist/web/login/types.d.ts.map +1 -1
  491. package/dist/web/login/types.js.map +1 -1
  492. package/dist/web/portal-shell.d.ts +4 -0
  493. package/dist/web/portal-shell.d.ts.map +1 -0
  494. package/dist/{portal-shell.js → web/portal-shell.js} +2 -2
  495. package/dist/web/portal-shell.js.map +1 -0
  496. package/dist/web/server.d.ts.map +1 -1
  497. package/dist/web/server.js +7 -0
  498. package/dist/web/server.js.map +1 -1
  499. package/dist/web/session-view/command.d.ts.map +1 -1
  500. package/dist/web/session-view/command.js +4 -1
  501. package/dist/web/session-view/command.js.map +1 -1
  502. package/dist/web/session-view/portal.d.ts.map +1 -1
  503. package/dist/web/session-view/portal.js +4 -3
  504. package/dist/web/session-view/portal.js.map +1 -1
  505. package/dist/web/session-view/service.d.ts.map +1 -1
  506. package/dist/web/session-view/service.js +2 -1
  507. package/dist/web/session-view/service.js.map +1 -1
  508. package/dist/web/session-view/types.d.ts +2 -1
  509. package/dist/web/session-view/types.d.ts.map +1 -1
  510. package/dist/web/session-view/types.js.map +1 -1
  511. package/dist/workspace-projection/index.d.ts +5 -0
  512. package/dist/workspace-projection/index.d.ts.map +1 -0
  513. package/dist/workspace-projection/index.js +71 -0
  514. package/dist/workspace-projection/index.js.map +1 -0
  515. package/dist/workspace-projection/types.d.ts +7 -0
  516. package/dist/workspace-projection/types.d.ts.map +1 -0
  517. package/dist/workspace-projection/types.js +2 -0
  518. package/dist/workspace-projection/types.js.map +1 -0
  519. package/package.json +28 -15
  520. package/dist/adapters/streaming.d.ts +0 -18
  521. package/dist/adapters/streaming.d.ts.map +0 -1
  522. package/dist/adapters/streaming.js +0 -44
  523. package/dist/adapters/streaming.js.map +0 -1
  524. package/dist/download.d.ts.map +0 -1
  525. package/dist/download.js.map +0 -1
  526. package/dist/model-registry.d.ts +0 -4
  527. package/dist/model-registry.d.ts.map +0 -1
  528. package/dist/model-registry.js +0 -7
  529. package/dist/model-registry.js.map +0 -1
  530. package/dist/portal-shell.d.ts +0 -4
  531. package/dist/portal-shell.d.ts.map +0 -1
  532. package/dist/portal-shell.js.map +0 -1
  533. package/dist/runtime/agent-run-controller.d.ts +0 -31
  534. package/dist/runtime/agent-run-controller.d.ts.map +0 -1
  535. package/dist/runtime/agent-run-controller.js +0 -195
  536. package/dist/runtime/agent-run-controller.js.map +0 -1
  537. package/dist/sessions/agent-memory-file-manager.d.ts +0 -19
  538. package/dist/sessions/agent-memory-file-manager.d.ts.map +0 -1
  539. package/dist/sessions/agent-memory-file-manager.js.map +0 -1
  540. package/dist/vault/routing.d.ts +0 -3
  541. package/dist/vault/routing.d.ts.map +0 -1
  542. package/dist/vault/routing.js +0 -13
  543. package/dist/vault/routing.js.map +0 -1
  544. /package/dist/{download.d.ts → cli/download.d.ts} +0 -0
  545. /package/dist/{download.js → cli/download.js} +0 -0
@@ -0,0 +1,401 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { boundSubagentProgressNode, clampSubagentLabel } from "../subagent-progress.js";
3
+ const MAX_DAG_NODES = 8;
4
+ const MAX_DAG_EDGES = 16;
5
+ const MAX_DAG_DEPTH = 4;
6
+ const MAX_CONCURRENT_SUBAGENTS = 4;
7
+ const MAX_DEPENDENCY_OUTPUT_CHARS = 4000;
8
+ /**
9
+ * Every subagent runs under a named profile: the profile owns the prompt,
10
+ * tool grant, model and budget defaults. Letting the model assemble those
11
+ * per call proved unstable, so the schema deliberately exposes no
12
+ * `systemPrompt`, `tools` or `model` escape hatch — narrowing what the model
13
+ * can get wrong is the point. `budget` survives because it can only tighten
14
+ * the profile's defaults, never widen them.
15
+ *
16
+ * `profileNames` is baked into the schema as an enum to steer the model's
17
+ * choice. TypeBox does not check `enum` on a string, so an unknown name still
18
+ * reaches `validatePlanProfiles`, which names the available profiles.
19
+ */
20
+ function buildTaskProperties(profileNames) {
21
+ return {
22
+ task: Type.String({ minLength: 1, description: "Self-contained task for a fresh subagent." }),
23
+ profile: Type.Optional(Type.String({
24
+ enum: profileNames,
25
+ description: "Profile this subagent runs under. Required, but a top-level profile covers every task and DAG node that does not set its own.",
26
+ })),
27
+ // No length bound: a label is a display string, and `taskLabel` clamps it.
28
+ // Bounding it in the schema only lets a cosmetic field reject a whole DAG,
29
+ // and validation reports that failure by echoing every node back.
30
+ label: Type.Optional(Type.String({ description: "Short progress label for this subagent." })),
31
+ input: Type.Optional(Type.Unknown({ description: "Optional JSON-serializable structured input for the task." })),
32
+ };
33
+ }
34
+ const sharedProperties = {
35
+ parentContext: Type.Optional(Type.Object({
36
+ mode: Type.Literal("normalized"),
37
+ recentTurns: Type.Optional(Type.Integer({ minimum: 1, maximum: 8, default: 3 })),
38
+ })),
39
+ outputSchema: Type.Optional(Type.Record(Type.String(), Type.Unknown(), {
40
+ description: "Optional TypeBox/JSON Schema applied to every subagent result.",
41
+ })),
42
+ budget: Type.Optional(Type.Object({
43
+ maxTurns: Type.Optional(Type.Integer({ minimum: 1 })),
44
+ maxTokens: Type.Optional(Type.Integer({ minimum: 1 })),
45
+ maxCostUsd: Type.Optional(Type.Number({ minimum: 0 })),
46
+ maxDurationMs: Type.Optional(Type.Integer({ minimum: 1 })),
47
+ }, { description: "Tightens the profile's budget defaults; cannot raise them." })),
48
+ };
49
+ /**
50
+ * The runtime schema varies only in the `profile` enum, so every instance
51
+ * shares one static type and `subagentSchema` below can stand in for it.
52
+ */
53
+ function buildSubagentSchema(profileNames) {
54
+ const taskProperties = buildTaskProperties(profileNames);
55
+ return Type.Object({
56
+ task: Type.Optional(taskProperties.task),
57
+ profile: taskProperties.profile,
58
+ label: taskProperties.label,
59
+ input: taskProperties.input,
60
+ tasks: Type.Optional(Type.Array(Type.Object(taskProperties), {
61
+ minItems: 1,
62
+ maxItems: MAX_DAG_NODES,
63
+ description: "Independent subagent tasks executed concurrently; results preserve input order.",
64
+ })),
65
+ dag: Type.Optional(Type.Object({
66
+ nodes: Type.Array(Type.Object({
67
+ id: Type.String({
68
+ pattern: "^[A-Za-z0-9_-]+$",
69
+ maxLength: 64,
70
+ description: "Unique stable node id used by dependsOn.",
71
+ }),
72
+ ...taskProperties,
73
+ dependsOn: Type.Optional(Type.Array(Type.String(), { maxItems: MAX_DAG_NODES })),
74
+ }), { minItems: 1, maxItems: MAX_DAG_NODES }),
75
+ maxConcurrency: Type.Optional(Type.Integer({
76
+ minimum: 1,
77
+ maximum: MAX_CONCURRENT_SUBAGENTS,
78
+ default: MAX_CONCURRENT_SUBAGENTS,
79
+ })),
80
+ })),
81
+ ...sharedProperties,
82
+ }, { description: "Provide task, tasks, or dag." });
83
+ }
84
+ const subagentSchema = buildSubagentSchema([]);
85
+ class SubagentProgressTracker {
86
+ constructor(mode, items, onUpdate) {
87
+ this.mode = mode;
88
+ this.items = items;
89
+ this.onUpdate = onUpdate;
90
+ this.states = new Map();
91
+ this.metrics = new Map();
92
+ for (const item of items)
93
+ this.states.set(item.id, "pending");
94
+ }
95
+ update(id, status, metrics) {
96
+ this.states.set(id, status);
97
+ if (metrics)
98
+ this.metrics.set(id, metrics);
99
+ this.emit();
100
+ }
101
+ emit() {
102
+ if (!this.onUpdate)
103
+ return;
104
+ const nodes = this.items.map((item) => boundSubagentProgressNode({
105
+ ...item,
106
+ status: this.states.get(item.id) ?? "pending",
107
+ ...this.metrics.get(item.id),
108
+ }));
109
+ this.onUpdate({
110
+ content: [],
111
+ details: { progress: { mode: this.mode, nodes } },
112
+ });
113
+ }
114
+ }
115
+ function taskLabel(task, fallback) {
116
+ return clampSubagentLabel(task.label?.trim() || task.task.trim().slice(0, 48) || fallback);
117
+ }
118
+ function formatOutcome(outcome) {
119
+ if (outcome.status === "budget_exceeded") {
120
+ return `Subagent stopped: budget limit exceeded${outcome.error ? ` (${outcome.error})` : ""}`;
121
+ }
122
+ if (outcome.status !== "completed") {
123
+ return `Subagent ${outcome.status}${outcome.error ? `: ${outcome.error}` : ""}`;
124
+ }
125
+ return typeof outcome.output === "string"
126
+ ? outcome.output
127
+ : JSON.stringify(outcome.output, null, 2);
128
+ }
129
+ function buildRequest(task, shared, signal) {
130
+ const outputSchema = shared.outputSchema;
131
+ return {
132
+ task: task.task,
133
+ ...(task.profile ? { profile: task.profile } : {}),
134
+ ...(task.input !== undefined ? { input: task.input } : {}),
135
+ ...(shared.parentContext ? { parentContext: shared.parentContext } : {}),
136
+ ...(outputSchema ? { outputSchema } : {}),
137
+ ...(shared.budget ? { budget: shared.budget } : {}),
138
+ ...(signal ? { signal } : {}),
139
+ };
140
+ }
141
+ function buildDagWaves(nodes) {
142
+ if (nodes.length === 0 || nodes.length > MAX_DAG_NODES) {
143
+ throw new Error(`Subagent DAG must contain 1-${MAX_DAG_NODES} nodes`);
144
+ }
145
+ const byId = new Map();
146
+ let edgeCount = 0;
147
+ for (const node of nodes) {
148
+ if (!/^[A-Za-z0-9_-]{1,64}$/.test(node.id)) {
149
+ throw new Error(`Invalid subagent DAG node id: ${node.id}`);
150
+ }
151
+ if (byId.has(node.id))
152
+ throw new Error(`Duplicate subagent DAG node id: ${node.id}`);
153
+ byId.set(node.id, node);
154
+ const dependencies = new Set(node.dependsOn ?? []);
155
+ if (dependencies.size !== (node.dependsOn?.length ?? 0)) {
156
+ throw new Error(`Duplicate dependency on subagent DAG node: ${node.id}`);
157
+ }
158
+ edgeCount += dependencies.size;
159
+ }
160
+ if (edgeCount > MAX_DAG_EDGES) {
161
+ throw new Error(`Subagent DAG exceeds ${MAX_DAG_EDGES} dependency edges`);
162
+ }
163
+ for (const node of nodes) {
164
+ for (const dependency of node.dependsOn ?? []) {
165
+ if (!byId.has(dependency)) {
166
+ throw new Error(`Unknown subagent DAG dependency ${dependency} for node ${node.id}`);
167
+ }
168
+ if (dependency === node.id)
169
+ throw new Error(`Subagent DAG node ${node.id} depends on itself`);
170
+ }
171
+ }
172
+ const remaining = new Set(nodes.map((node) => node.id));
173
+ const completed = new Set();
174
+ const waves = [];
175
+ while (remaining.size > 0) {
176
+ const wave = nodes.filter((node) => remaining.has(node.id) && (node.dependsOn ?? []).every((id) => completed.has(id)));
177
+ if (wave.length === 0)
178
+ throw new Error("Subagent DAG contains a cycle");
179
+ waves.push(wave);
180
+ if (waves.length > MAX_DAG_DEPTH) {
181
+ throw new Error(`Subagent DAG exceeds maximum depth ${MAX_DAG_DEPTH}`);
182
+ }
183
+ for (const node of wave) {
184
+ remaining.delete(node.id);
185
+ completed.add(node.id);
186
+ }
187
+ }
188
+ return waves;
189
+ }
190
+ /**
191
+ * A top-level `profile` is the default for every task and DAG node, like the
192
+ * other shared params. A fan-out that runs entirely under one profile then
193
+ * names it once instead of repeating it per node.
194
+ */
195
+ function withDefaultProfile(task, fallback) {
196
+ return task.profile || !fallback ? task : { ...task, profile: fallback };
197
+ }
198
+ function itemForNode(node, defaultProfile) {
199
+ return {
200
+ id: node.id,
201
+ label: clampSubagentLabel(node.label?.trim() || node.id),
202
+ task: withDefaultProfile(node, defaultProfile),
203
+ dependsOn: node.dependsOn ?? [],
204
+ };
205
+ }
206
+ /** Normalize every tool mode into one plan: nodes, waves, concurrency. */
207
+ function buildPlan(params) {
208
+ const modeCount = [params.task, params.tasks, params.dag].filter((mode) => mode !== undefined).length;
209
+ if (modeCount !== 1) {
210
+ throw new Error("Subagent requires exactly one of task, tasks, or dag");
211
+ }
212
+ if (params.dag !== undefined) {
213
+ const toItem = (node) => itemForNode(node, params.profile);
214
+ const waves = buildDagWaves(params.dag.nodes).map((wave) => wave.map(toItem));
215
+ const requested = params.dag.maxConcurrency ?? MAX_CONCURRENT_SUBAGENTS;
216
+ return {
217
+ mode: "dag",
218
+ items: params.dag.nodes.map(toItem),
219
+ waves,
220
+ concurrency: Math.max(1, Math.min(MAX_CONCURRENT_SUBAGENTS, Math.floor(requested))),
221
+ };
222
+ }
223
+ if (params.tasks !== undefined) {
224
+ const items = params.tasks.map((task, index) => ({
225
+ id: String(index),
226
+ label: taskLabel(task, String(index + 1)),
227
+ task: withDefaultProfile(task, params.profile),
228
+ dependsOn: [],
229
+ }));
230
+ return { mode: "parallel", items, waves: [items], concurrency: MAX_CONCURRENT_SUBAGENTS };
231
+ }
232
+ if (!params.task)
233
+ throw new Error("Subagent requires task, tasks, or dag");
234
+ const task = { ...params, task: params.task };
235
+ const item = { id: "0", label: taskLabel(task, "subagent"), task, dependsOn: [] };
236
+ return { mode: "single", items: [item], waves: [[item]], concurrency: 1 };
237
+ }
238
+ /** Run `worker` over every item with at most `limit` in flight. */
239
+ async function forEachConcurrent(items, limit, worker) {
240
+ let cursor = 0;
241
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, async () => {
242
+ while (cursor < items.length) {
243
+ const index = cursor++;
244
+ await worker(items[index], index);
245
+ }
246
+ }));
247
+ }
248
+ function dependencyOutput(outcome) {
249
+ if (outcome.status !== "completed")
250
+ return undefined;
251
+ const value = outcome.output;
252
+ const serialized = typeof value === "string" ? value : JSON.stringify(value);
253
+ if (serialized === undefined)
254
+ return null;
255
+ if (serialized.length <= MAX_DEPENDENCY_OUTPUT_CHARS)
256
+ return value;
257
+ // Oversized structured output becomes a marked string — the shape is lost,
258
+ // which the tool description warns downstream consumers about.
259
+ return `${serialized.slice(0, MAX_DEPENDENCY_OUTPUT_CHARS)}\n[truncated]`;
260
+ }
261
+ function planRequest(item, shared, outcomes, signal) {
262
+ if (item.dependsOn.length === 0)
263
+ return buildRequest(item.task, shared, signal);
264
+ const dependencies = Object.fromEntries(item.dependsOn.map((id) => [id, dependencyOutput(outcomes.get(id))]));
265
+ const input = {
266
+ ...(item.task.input !== undefined ? { input: item.task.input } : {}),
267
+ dependencies,
268
+ };
269
+ return buildRequest({ ...item.task, input }, shared, signal);
270
+ }
271
+ /**
272
+ * One executor for every mode: wave barriers and a per-invocation concurrency
273
+ * bound. Process-wide slots are acquired by the shared runner seam.
274
+ */
275
+ async function runWaves(plan, shared, runSubagent, progress, signal) {
276
+ const outcomes = new Map();
277
+ for (const wave of plan.waves) {
278
+ await forEachConcurrent(wave, plan.concurrency, async (item) => {
279
+ const failedDependency = item.dependsOn.find((id) => outcomes.get(id)?.status !== "completed");
280
+ if (failedDependency) {
281
+ outcomes.set(item.id, {
282
+ id: item.id,
283
+ status: "skipped",
284
+ error: `Dependency ${failedDependency} did not complete`,
285
+ });
286
+ progress.update(item.id, "skipped", {
287
+ reason: `Dependency ${failedDependency} did not complete`,
288
+ });
289
+ return;
290
+ }
291
+ let result;
292
+ progress.update(item.id, "running");
293
+ result = await runSubagent(planRequest(item, shared, outcomes, signal));
294
+ outcomes.set(item.id, { id: item.id, ...result });
295
+ progress.update(item.id, result.status, {
296
+ turns: result.turns,
297
+ toolCalls: result.toolCalls,
298
+ toolCallCounts: result.toolCallCounts,
299
+ tokens: result.tokens,
300
+ costUsd: result.costUsd,
301
+ durationMs: result.durationMs,
302
+ ...(result.error ? { reason: result.error } : {}),
303
+ ...(result.cleanupPending ? { cleanupPending: true } : {}),
304
+ });
305
+ });
306
+ }
307
+ return plan.items.map((item) => outcomes.get(item.id));
308
+ }
309
+ /**
310
+ * The tool grant belongs in the menu. A description alone reads as a stylistic
311
+ * constraint, so a model will pick a no-tool profile for work that needs tools
312
+ * and then narrate the tool call it could not make.
313
+ */
314
+ function formatToolGrant(tools) {
315
+ if (!tools)
316
+ return "tools unknown";
317
+ return tools.length === 0 ? "no tools" : `tools: ${tools.join(", ")}`;
318
+ }
319
+ function validatePlanProfiles(plan, availableProfiles) {
320
+ const known = [...availableProfiles].join(", ");
321
+ for (const item of plan.items) {
322
+ const profile = item.task.profile;
323
+ if (!profile) {
324
+ throw new Error(`Subagent ${item.label} must specify a profile (available: ${known})`);
325
+ }
326
+ if (!availableProfiles.has(profile)) {
327
+ throw new Error(`Unknown subagent profile: ${profile} (available: ${known})`);
328
+ }
329
+ }
330
+ }
331
+ /**
332
+ * Create the normal agent's bounded subagent delegation and DAG tool.
333
+ * `globalSlots` is the process-wide fan-out account shared across every
334
+ * conversation's tool instance; omitted, fan-out is bounded per run only.
335
+ *
336
+ * `profiles` must be non-empty: it is both the model-facing menu and the only
337
+ * way to grant a subagent any capability at all.
338
+ */
339
+ export function createSubagentTool(runSubagent, profiles) {
340
+ if (profiles.size === 0) {
341
+ throw new Error("createSubagentTool requires at least one subagent profile");
342
+ }
343
+ const profileDescription = [...profiles.entries()]
344
+ .map(([name, profile]) => `${name} [${formatToolGrant(profile.tools)}] — ${profile.description}`)
345
+ .join("; ");
346
+ return {
347
+ name: "subagent",
348
+ label: "Subagent",
349
+ description: `Run fresh isolated subagents. Use task for one subagent, tasks for independent concurrent work, or dag.nodes for a bounded dependency graph. At most ${MAX_CONCURRENT_SUBAGENTS} subagents run concurrently. DAG limits: ${MAX_DAG_NODES} nodes, ${MAX_DAG_EDGES} edges, depth ${MAX_DAG_DEPTH}; failed dependencies skip descendants, and dependency outputs larger than ${MAX_DEPENDENCY_OUTPUT_CHARS} characters reach downstream nodes as a truncated string. ` +
350
+ "Subagents are fresh by default; parentContext.mode=normalized can include a sanitized reference snapshot of the active parent run. Nested subagents are not allowed. " +
351
+ `Every task and DAG node must set profile; the profile supplies the prompt, tools, model and budget. Available profiles: ${profileDescription}.`,
352
+ parameters: buildSubagentSchema([...profiles.keys()]),
353
+ execute: async (_toolCallId, params, signal, onUpdate) => {
354
+ const plan = buildPlan(params);
355
+ validatePlanProfiles(plan, new Set(profiles.keys()));
356
+ const progress = new SubagentProgressTracker(plan.mode, plan.items.map(({ id, label, task }) => ({ id, label, profile: task.profile })), onUpdate);
357
+ progress.emit();
358
+ const ordered = await runWaves(plan, params, runSubagent, progress, signal);
359
+ switch (plan.mode) {
360
+ case "dag":
361
+ return {
362
+ content: [
363
+ {
364
+ type: "text",
365
+ text: ordered
366
+ .map((outcome) => `[${outcome.id}] ${formatOutcome(outcome)}`)
367
+ .join("\n\n"),
368
+ },
369
+ ],
370
+ details: {
371
+ mode: "dag",
372
+ waves: plan.waves.map((wave) => wave.map((item) => item.id)),
373
+ results: ordered,
374
+ },
375
+ };
376
+ case "parallel": {
377
+ const results = ordered.map(({ id: _id, ...result }) => result);
378
+ return {
379
+ content: [
380
+ {
381
+ type: "text",
382
+ text: results
383
+ .map((result, index) => `[${index + 1}] ${formatOutcome(result)}`)
384
+ .join("\n\n"),
385
+ },
386
+ ],
387
+ details: { mode: "parallel", results },
388
+ };
389
+ }
390
+ case "single": {
391
+ const { id: _id, ...result } = ordered[0];
392
+ return {
393
+ content: [{ type: "text", text: formatOutcome(result) }],
394
+ details: result,
395
+ };
396
+ }
397
+ }
398
+ },
399
+ };
400
+ }
401
+ //# sourceMappingURL=subagent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent.js","sourceRoot":"","sources":["../../src/tools/subagent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool, AgentToolUpdateCallback } from \"@earendil-works/pi-agent-core\";\nimport { Type, type Static, type TSchema } from \"@sinclair/typebox\";\nimport type { SubagentRunOutput, SubagentRunRequest, SubagentRunResult } from \"../harness/types.js\";\n// Progress statuses extend run statuses with the pre- and non-run states. The\n// dashboard renders the same union, so it is defined once alongside the\n// snapshot the tool emits rather than restated here.\nimport type { SubagentProgressNode, SubagentProgressStatus } from \"../types.js\";\nimport { boundSubagentProgressNode, clampSubagentLabel } from \"../subagent-progress.js\";\n\nconst MAX_DAG_NODES = 8;\nconst MAX_DAG_EDGES = 16;\nconst MAX_DAG_DEPTH = 4;\nconst MAX_CONCURRENT_SUBAGENTS = 4;\nconst MAX_DEPENDENCY_OUTPUT_CHARS = 4000;\n\n/**\n * Every subagent runs under a named profile: the profile owns the prompt,\n * tool grant, model and budget defaults. Letting the model assemble those\n * per call proved unstable, so the schema deliberately exposes no\n * `systemPrompt`, `tools` or `model` escape hatch — narrowing what the model\n * can get wrong is the point. `budget` survives because it can only tighten\n * the profile's defaults, never widen them.\n *\n * `profileNames` is baked into the schema as an enum to steer the model's\n * choice. TypeBox does not check `enum` on a string, so an unknown name still\n * reaches `validatePlanProfiles`, which names the available profiles.\n */\nfunction buildTaskProperties(profileNames: string[]) {\n return {\n task: Type.String({ minLength: 1, description: \"Self-contained task for a fresh subagent.\" }),\n profile: Type.Optional(\n Type.String({\n enum: profileNames,\n description:\n \"Profile this subagent runs under. Required, but a top-level profile covers every task and DAG node that does not set its own.\",\n }),\n ),\n // No length bound: a label is a display string, and `taskLabel` clamps it.\n // Bounding it in the schema only lets a cosmetic field reject a whole DAG,\n // and validation reports that failure by echoing every node back.\n label: Type.Optional(Type.String({ description: \"Short progress label for this subagent.\" })),\n input: Type.Optional(\n Type.Unknown({ description: \"Optional JSON-serializable structured input for the task.\" }),\n ),\n };\n}\n\nconst sharedProperties = {\n parentContext: Type.Optional(\n Type.Object({\n mode: Type.Literal(\"normalized\"),\n recentTurns: Type.Optional(Type.Integer({ minimum: 1, maximum: 8, default: 3 })),\n }),\n ),\n outputSchema: Type.Optional(\n Type.Record(Type.String(), Type.Unknown(), {\n description: \"Optional TypeBox/JSON Schema applied to every subagent result.\",\n }),\n ),\n budget: Type.Optional(\n Type.Object(\n {\n maxTurns: Type.Optional(Type.Integer({ minimum: 1 })),\n maxTokens: Type.Optional(Type.Integer({ minimum: 1 })),\n maxCostUsd: Type.Optional(Type.Number({ minimum: 0 })),\n maxDurationMs: Type.Optional(Type.Integer({ minimum: 1 })),\n },\n { description: \"Tightens the profile's budget defaults; cannot raise them.\" },\n ),\n ),\n};\n\n/**\n * The runtime schema varies only in the `profile` enum, so every instance\n * shares one static type and `subagentSchema` below can stand in for it.\n */\nfunction buildSubagentSchema(profileNames: string[]) {\n const taskProperties = buildTaskProperties(profileNames);\n return Type.Object(\n {\n task: Type.Optional(taskProperties.task),\n profile: taskProperties.profile,\n label: taskProperties.label,\n input: taskProperties.input,\n tasks: Type.Optional(\n Type.Array(Type.Object(taskProperties), {\n minItems: 1,\n maxItems: MAX_DAG_NODES,\n description:\n \"Independent subagent tasks executed concurrently; results preserve input order.\",\n }),\n ),\n dag: Type.Optional(\n Type.Object({\n nodes: Type.Array(\n Type.Object({\n id: Type.String({\n pattern: \"^[A-Za-z0-9_-]+$\",\n maxLength: 64,\n description: \"Unique stable node id used by dependsOn.\",\n }),\n ...taskProperties,\n dependsOn: Type.Optional(Type.Array(Type.String(), { maxItems: MAX_DAG_NODES })),\n }),\n { minItems: 1, maxItems: MAX_DAG_NODES },\n ),\n maxConcurrency: Type.Optional(\n Type.Integer({\n minimum: 1,\n maximum: MAX_CONCURRENT_SUBAGENTS,\n default: MAX_CONCURRENT_SUBAGENTS,\n }),\n ),\n }),\n ),\n ...sharedProperties,\n },\n { description: \"Provide task, tasks, or dag.\" },\n );\n}\n\nconst subagentSchema = buildSubagentSchema([]);\n\ntype SubagentParams = Static<typeof subagentSchema>;\ntype SubagentTask = NonNullable<SubagentParams[\"tasks\"]>[number];\ntype DagNode = NonNullable<SubagentParams[\"dag\"]>[\"nodes\"][number];\ntype SharedParams = Pick<SubagentParams, \"parentContext\" | \"outputSchema\" | \"budget\">;\ntype RunSubagent = <TOutputSchema extends TSchema | undefined = undefined>(\n request: SubagentRunRequest<TOutputSchema>,\n) => Promise<SubagentRunResult<SubagentRunOutput<TOutputSchema>>>;\n\ntype PlanMode = \"single\" | \"parallel\" | \"dag\";\n\n/** One planned subagent run; single and tasks modes are plans with no edges. */\ninterface PlanItem {\n id: string;\n label: string;\n task: SubagentTask;\n dependsOn: string[];\n}\n\ninterface Plan {\n mode: PlanMode;\n items: PlanItem[];\n waves: PlanItem[][];\n concurrency: number;\n}\n\ntype PlanOutcome =\n | ({ id: string } & SubagentRunResult<unknown>)\n | { id: string; status: \"skipped\"; error: string };\n\n/** The metrics half of a progress node — derived, not restated. */\ntype SubagentProgressMetrics = Omit<SubagentProgressNode, \"id\" | \"label\" | \"status\" | \"profile\">;\n\nclass SubagentProgressTracker {\n private readonly states = new Map<string, SubagentProgressStatus>();\n private readonly metrics = new Map<string, SubagentProgressMetrics>();\n\n constructor(\n private readonly mode: PlanMode,\n private readonly items: Array<{ id: string; label: string; profile?: string }>,\n private readonly onUpdate?: AgentToolUpdateCallback,\n ) {\n for (const item of items) this.states.set(item.id, \"pending\");\n }\n\n update(id: string, status: SubagentProgressStatus, metrics?: SubagentProgressMetrics): void {\n this.states.set(id, status);\n if (metrics) this.metrics.set(id, metrics);\n this.emit();\n }\n\n emit(): void {\n if (!this.onUpdate) return;\n const nodes = this.items.map((item) =>\n boundSubagentProgressNode({\n ...item,\n status: this.states.get(item.id) ?? (\"pending\" as SubagentProgressStatus),\n ...this.metrics.get(item.id),\n }),\n );\n this.onUpdate({\n content: [],\n details: { progress: { mode: this.mode, nodes } },\n });\n }\n}\n\nfunction taskLabel(task: SubagentTask, fallback: string): string {\n return clampSubagentLabel(task.label?.trim() || task.task.trim().slice(0, 48) || fallback);\n}\n\nfunction formatOutcome(outcome: {\n status: SubagentProgressStatus;\n output?: unknown;\n error?: string;\n}): string {\n if (outcome.status === \"budget_exceeded\") {\n return `Subagent stopped: budget limit exceeded${outcome.error ? ` (${outcome.error})` : \"\"}`;\n }\n if (outcome.status !== \"completed\") {\n return `Subagent ${outcome.status}${outcome.error ? `: ${outcome.error}` : \"\"}`;\n }\n return typeof outcome.output === \"string\"\n ? outcome.output\n : JSON.stringify(outcome.output, null, 2);\n}\n\nfunction buildRequest(\n task: SubagentTask,\n shared: SharedParams,\n signal?: AbortSignal,\n): SubagentRunRequest<TSchema | undefined> {\n const outputSchema = shared.outputSchema as TSchema | undefined;\n return {\n task: task.task,\n ...(task.profile ? { profile: task.profile } : {}),\n ...(task.input !== undefined ? { input: task.input } : {}),\n ...(shared.parentContext ? { parentContext: shared.parentContext } : {}),\n ...(outputSchema ? { outputSchema } : {}),\n ...(shared.budget ? { budget: shared.budget } : {}),\n ...(signal ? { signal } : {}),\n };\n}\n\nfunction buildDagWaves(nodes: DagNode[]): DagNode[][] {\n if (nodes.length === 0 || nodes.length > MAX_DAG_NODES) {\n throw new Error(`Subagent DAG must contain 1-${MAX_DAG_NODES} nodes`);\n }\n const byId = new Map<string, DagNode>();\n let edgeCount = 0;\n for (const node of nodes) {\n if (!/^[A-Za-z0-9_-]{1,64}$/.test(node.id)) {\n throw new Error(`Invalid subagent DAG node id: ${node.id}`);\n }\n if (byId.has(node.id)) throw new Error(`Duplicate subagent DAG node id: ${node.id}`);\n byId.set(node.id, node);\n const dependencies = new Set(node.dependsOn ?? []);\n if (dependencies.size !== (node.dependsOn?.length ?? 0)) {\n throw new Error(`Duplicate dependency on subagent DAG node: ${node.id}`);\n }\n edgeCount += dependencies.size;\n }\n if (edgeCount > MAX_DAG_EDGES) {\n throw new Error(`Subagent DAG exceeds ${MAX_DAG_EDGES} dependency edges`);\n }\n for (const node of nodes) {\n for (const dependency of node.dependsOn ?? []) {\n if (!byId.has(dependency)) {\n throw new Error(`Unknown subagent DAG dependency ${dependency} for node ${node.id}`);\n }\n if (dependency === node.id) throw new Error(`Subagent DAG node ${node.id} depends on itself`);\n }\n }\n\n const remaining = new Set(nodes.map((node) => node.id));\n const completed = new Set<string>();\n const waves: DagNode[][] = [];\n while (remaining.size > 0) {\n const wave = nodes.filter(\n (node) => remaining.has(node.id) && (node.dependsOn ?? []).every((id) => completed.has(id)),\n );\n if (wave.length === 0) throw new Error(\"Subagent DAG contains a cycle\");\n waves.push(wave);\n if (waves.length > MAX_DAG_DEPTH) {\n throw new Error(`Subagent DAG exceeds maximum depth ${MAX_DAG_DEPTH}`);\n }\n for (const node of wave) {\n remaining.delete(node.id);\n completed.add(node.id);\n }\n }\n return waves;\n}\n\n/**\n * A top-level `profile` is the default for every task and DAG node, like the\n * other shared params. A fan-out that runs entirely under one profile then\n * names it once instead of repeating it per node.\n */\nfunction withDefaultProfile<T extends { profile?: string }>(task: T, fallback?: string): T {\n return task.profile || !fallback ? task : { ...task, profile: fallback };\n}\n\nfunction itemForNode(node: DagNode, defaultProfile?: string): PlanItem {\n return {\n id: node.id,\n label: clampSubagentLabel(node.label?.trim() || node.id),\n task: withDefaultProfile(node, defaultProfile),\n dependsOn: node.dependsOn ?? [],\n };\n}\n\n/** Normalize every tool mode into one plan: nodes, waves, concurrency. */\nfunction buildPlan(params: SubagentParams): Plan {\n const modeCount = [params.task, params.tasks, params.dag].filter(\n (mode) => mode !== undefined,\n ).length;\n if (modeCount !== 1) {\n throw new Error(\"Subagent requires exactly one of task, tasks, or dag\");\n }\n\n if (params.dag !== undefined) {\n const toItem = (node: DagNode) => itemForNode(node, params.profile);\n const waves = buildDagWaves(params.dag.nodes).map((wave) => wave.map(toItem));\n const requested = params.dag.maxConcurrency ?? MAX_CONCURRENT_SUBAGENTS;\n return {\n mode: \"dag\",\n items: params.dag.nodes.map(toItem),\n waves,\n concurrency: Math.max(1, Math.min(MAX_CONCURRENT_SUBAGENTS, Math.floor(requested))),\n };\n }\n if (params.tasks !== undefined) {\n const items = params.tasks.map((task, index) => ({\n id: String(index),\n label: taskLabel(task, String(index + 1)),\n task: withDefaultProfile(task, params.profile),\n dependsOn: [],\n }));\n return { mode: \"parallel\", items, waves: [items], concurrency: MAX_CONCURRENT_SUBAGENTS };\n }\n if (!params.task) throw new Error(\"Subagent requires task, tasks, or dag\");\n const task = { ...params, task: params.task };\n const item = { id: \"0\", label: taskLabel(task, \"subagent\"), task, dependsOn: [] };\n return { mode: \"single\", items: [item], waves: [[item]], concurrency: 1 };\n}\n\n/** Run `worker` over every item with at most `limit` in flight. */\nasync function forEachConcurrent<T>(\n items: readonly T[],\n limit: number,\n worker: (item: T, index: number) => Promise<void>,\n): Promise<void> {\n let cursor = 0;\n await Promise.all(\n Array.from({ length: Math.min(limit, items.length) }, async () => {\n while (cursor < items.length) {\n const index = cursor++;\n await worker(items[index], index);\n }\n }),\n );\n}\n\nfunction dependencyOutput(outcome: PlanOutcome): unknown {\n if (outcome.status !== \"completed\") return undefined;\n const value = outcome.output;\n const serialized = typeof value === \"string\" ? value : JSON.stringify(value);\n if (serialized === undefined) return null;\n if (serialized.length <= MAX_DEPENDENCY_OUTPUT_CHARS) return value;\n // Oversized structured output becomes a marked string — the shape is lost,\n // which the tool description warns downstream consumers about.\n return `${serialized.slice(0, MAX_DEPENDENCY_OUTPUT_CHARS)}\\n[truncated]`;\n}\n\nfunction planRequest(\n item: PlanItem,\n shared: SharedParams,\n outcomes: Map<string, PlanOutcome>,\n signal?: AbortSignal,\n): SubagentRunRequest<TSchema | undefined> {\n if (item.dependsOn.length === 0) return buildRequest(item.task, shared, signal);\n const dependencies = Object.fromEntries(\n item.dependsOn.map((id) => [id, dependencyOutput(outcomes.get(id)!)]),\n );\n const input = {\n ...(item.task.input !== undefined ? { input: item.task.input } : {}),\n dependencies,\n };\n return buildRequest({ ...item.task, input }, shared, signal);\n}\n\n/**\n * One executor for every mode: wave barriers and a per-invocation concurrency\n * bound. Process-wide slots are acquired by the shared runner seam.\n */\nasync function runWaves(\n plan: Plan,\n shared: SharedParams,\n runSubagent: RunSubagent,\n progress: SubagentProgressTracker,\n signal?: AbortSignal,\n): Promise<PlanOutcome[]> {\n const outcomes = new Map<string, PlanOutcome>();\n for (const wave of plan.waves) {\n await forEachConcurrent(wave, plan.concurrency, async (item) => {\n const failedDependency = item.dependsOn.find(\n (id) => outcomes.get(id)?.status !== \"completed\",\n );\n if (failedDependency) {\n outcomes.set(item.id, {\n id: item.id,\n status: \"skipped\",\n error: `Dependency ${failedDependency} did not complete`,\n });\n progress.update(item.id, \"skipped\", {\n reason: `Dependency ${failedDependency} did not complete`,\n });\n return;\n }\n let result: SubagentRunResult<unknown>;\n progress.update(item.id, \"running\");\n result = await runSubagent(planRequest(item, shared, outcomes, signal));\n outcomes.set(item.id, { id: item.id, ...result });\n progress.update(item.id, result.status, {\n turns: result.turns,\n toolCalls: result.toolCalls,\n toolCallCounts: result.toolCallCounts,\n tokens: result.tokens,\n costUsd: result.costUsd,\n durationMs: result.durationMs,\n ...(result.error ? { reason: result.error } : {}),\n ...(result.cleanupPending ? { cleanupPending: true } : {}),\n });\n });\n }\n return plan.items.map((item) => outcomes.get(item.id)!);\n}\n\n/** What the model needs to choose a profile: what it is, and what it can do. */\ninterface SubagentProfileMenuEntry {\n description: string;\n tools?: string[];\n}\n\n/**\n * The tool grant belongs in the menu. A description alone reads as a stylistic\n * constraint, so a model will pick a no-tool profile for work that needs tools\n * and then narrate the tool call it could not make.\n */\nfunction formatToolGrant(tools: string[] | undefined): string {\n if (!tools) return \"tools unknown\";\n return tools.length === 0 ? \"no tools\" : `tools: ${tools.join(\", \")}`;\n}\n\nfunction validatePlanProfiles(plan: Plan, availableProfiles: ReadonlySet<string>): void {\n const known = [...availableProfiles].join(\", \");\n for (const item of plan.items) {\n const profile = item.task.profile;\n if (!profile) {\n throw new Error(`Subagent ${item.label} must specify a profile (available: ${known})`);\n }\n if (!availableProfiles.has(profile)) {\n throw new Error(`Unknown subagent profile: ${profile} (available: ${known})`);\n }\n }\n}\n\n/**\n * Create the normal agent's bounded subagent delegation and DAG tool.\n * `globalSlots` is the process-wide fan-out account shared across every\n * conversation's tool instance; omitted, fan-out is bounded per run only.\n *\n * `profiles` must be non-empty: it is both the model-facing menu and the only\n * way to grant a subagent any capability at all.\n */\nexport function createSubagentTool(\n runSubagent: RunSubagent,\n profiles: ReadonlyMap<string, SubagentProfileMenuEntry>,\n): AgentTool<typeof subagentSchema> {\n if (profiles.size === 0) {\n throw new Error(\"createSubagentTool requires at least one subagent profile\");\n }\n const profileDescription = [...profiles.entries()]\n .map(\n ([name, profile]) => `${name} [${formatToolGrant(profile.tools)}] — ${profile.description}`,\n )\n .join(\"; \");\n return {\n name: \"subagent\",\n label: \"Subagent\",\n description:\n `Run fresh isolated subagents. Use task for one subagent, tasks for independent concurrent work, or dag.nodes for a bounded dependency graph. At most ${MAX_CONCURRENT_SUBAGENTS} subagents run concurrently. DAG limits: ${MAX_DAG_NODES} nodes, ${MAX_DAG_EDGES} edges, depth ${MAX_DAG_DEPTH}; failed dependencies skip descendants, and dependency outputs larger than ${MAX_DEPENDENCY_OUTPUT_CHARS} characters reach downstream nodes as a truncated string. ` +\n \"Subagents are fresh by default; parentContext.mode=normalized can include a sanitized reference snapshot of the active parent run. Nested subagents are not allowed. \" +\n `Every task and DAG node must set profile; the profile supplies the prompt, tools, model and budget. Available profiles: ${profileDescription}.`,\n parameters: buildSubagentSchema([...profiles.keys()]),\n execute: async (\n _toolCallId: string,\n params: SubagentParams,\n signal?: AbortSignal,\n onUpdate?: AgentToolUpdateCallback,\n ) => {\n const plan = buildPlan(params);\n validatePlanProfiles(plan, new Set(profiles.keys()));\n const progress = new SubagentProgressTracker(\n plan.mode,\n plan.items.map(({ id, label, task }) => ({ id, label, profile: task.profile })),\n onUpdate,\n );\n progress.emit();\n const ordered = await runWaves(plan, params, runSubagent, progress, signal);\n\n switch (plan.mode) {\n case \"dag\":\n return {\n content: [\n {\n type: \"text\",\n text: ordered\n .map((outcome) => `[${outcome.id}] ${formatOutcome(outcome)}`)\n .join(\"\\n\\n\"),\n },\n ],\n details: {\n mode: \"dag\",\n waves: plan.waves.map((wave) => wave.map((item) => item.id)),\n results: ordered,\n },\n };\n case \"parallel\": {\n const results = ordered.map(({ id: _id, ...result }) => result);\n return {\n content: [\n {\n type: \"text\",\n text: results\n .map((result, index) => `[${index + 1}] ${formatOutcome(result)}`)\n .join(\"\\n\\n\"),\n },\n ],\n details: { mode: \"parallel\", results },\n };\n }\n case \"single\": {\n const { id: _id, ...result } = ordered[0];\n return {\n content: [{ type: \"text\", text: formatOutcome(result) }],\n details: result,\n };\n }\n }\n },\n };\n}\n"]}
@@ -1,23 +1,57 @@
1
- import type { MikanEvent } from "../types.js";
2
- export type EventPayload = MikanEvent;
1
+ import type { AgentTool } from "@earendil-works/pi-agent-core";
2
+ import type { TSchema } from "@sinclair/typebox";
3
+ import type { EventFilePayload } from "../harness/event-format.js";
4
+ /**
5
+ * Per-run context for optional platform-contributed tools (e.g. GitHub PR/CI).
6
+ * Core agent code binds packs without knowing which platform owns them.
7
+ */
8
+ export interface PlatformToolRunContext {
9
+ conversationId: string;
10
+ platformName: string;
11
+ threadTs?: string;
12
+ }
13
+ /**
14
+ * A platform capability pack: extra tools plus a bind hook that enables or
15
+ * disables them for the current run. Packs are assembled at process start
16
+ * (main.ts) and injected into runners; they must not be hardcoded in the
17
+ * core tool list.
18
+ */
19
+ export interface PlatformToolPack {
20
+ tools: AgentTool<TSchema>[];
21
+ bindRun(ctx: PlatformToolRunContext): void;
22
+ }
23
+ /**
24
+ * Injected as factories, not instances: bindRun mutates closure state inside
25
+ * the pack's tools, so a pack must be private to one runner (whose runs are
26
+ * serialized). A single shared instance would let concurrent conversations
27
+ * rebind each other mid-run — routing github_pr to the wrong conversation.
28
+ */
29
+ export type PlatformToolPackFactory = () => PlatformToolPack;
30
+ export type EventPayload = EventFilePayload;
3
31
  export interface EventStore {
4
- write(filename: string, payload: MikanEvent): Promise<{
32
+ write(filename: string, payload: EventFilePayload): Promise<{
5
33
  path: string;
6
34
  size: number;
7
35
  }>;
36
+ /**
37
+ * List all event files. Entries whose JSON cannot be parsed or fail format
38
+ * validation are kept with a `null` payload so consumers (e.g. the admin
39
+ * portal) can still surface and delete them; files that disappear
40
+ * mid-listing are skipped.
41
+ */
8
42
  list(): Promise<Array<{
9
43
  filename: string;
10
- payload: MikanEvent;
44
+ payload: EventFilePayload | null;
11
45
  size: number;
12
46
  mtimeMs: number;
13
47
  }>>;
14
48
  read(filename: string): Promise<{
15
49
  filename: string;
16
- payload: MikanEvent;
50
+ payload: EventFilePayload;
17
51
  size: number;
18
52
  mtimeMs: number;
19
53
  }>;
20
- update(filename: string, payload: MikanEvent): Promise<{
54
+ update(filename: string, payload: EventFilePayload): Promise<{
21
55
  path: string;
22
56
  size: number;
23
57
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtF,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACjG,IAAI,CACF,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrF,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvF,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACzD;AAID,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC;IACtC,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,eAAe,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAInE;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5B,OAAO,CAAC,GAAG,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC5C;AAED;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,gBAAgB,CAAC;AAI7D,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5F;;;;;OAKG;IACH,IAAI,IAAI,OAAO,CACb,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAC7F,CAAC;IACF,IAAI,CACF,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3F,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7F,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACzD;AAID,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC;IACtC,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,eAAe,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { MikanEvent } from \"../types.js\";\n\n// ── event tool ───────────────────────────────────────────────────────────────\n\nexport type EventPayload = MikanEvent;\n\nexport interface EventStore {\n write(filename: string, payload: MikanEvent): Promise<{ path: string; size: number }>;\n list(): Promise<Array<{ filename: string; payload: MikanEvent; size: number; mtimeMs: number }>>;\n read(\n filename: string,\n ): Promise<{ filename: string; payload: MikanEvent; size: number; mtimeMs: number }>;\n update(filename: string, payload: MikanEvent): Promise<{ path: string; size: number }>;\n delete(filename: string): Promise<{ deleted: boolean }>;\n}\n\n// ── truncation ───────────────────────────────────────────────────────────────\n\nexport interface TruncationResult {\n /** The truncated content */\n content: string;\n /** Whether truncation occurred */\n truncated: boolean;\n /** Which limit was hit: \"lines\", \"bytes\", or null if not truncated */\n truncatedBy: \"lines\" | \"bytes\" | null;\n /** Total number of lines in the original content */\n totalLines: number;\n /** Total number of bytes in the original content */\n totalBytes: number;\n /** Number of complete lines in the truncated output */\n outputLines: number;\n /** Number of bytes in the truncated output */\n outputBytes: number;\n /** Whether the last line was partially truncated (only for tail truncation edge case) */\n lastLinePartial: boolean;\n /** Whether the first line exceeded the byte limit (for head truncation) */\n firstLineExceedsLimit: boolean;\n}\n\nexport interface TruncationOptions {\n /** Maximum number of lines (default: 2000) */\n maxLines?: number;\n /** Maximum number of bytes (default: 50KB) */\n maxBytes?: number;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { TSchema } from \"@sinclair/typebox\";\nimport type { EventFilePayload } from \"../harness/event-format.js\";\n\n// ── platform tool packs ───────────────────────────────────────────────────────\n\n/**\n * Per-run context for optional platform-contributed tools (e.g. GitHub PR/CI).\n * Core agent code binds packs without knowing which platform owns them.\n */\nexport interface PlatformToolRunContext {\n conversationId: string;\n platformName: string;\n threadTs?: string;\n}\n\n/**\n * A platform capability pack: extra tools plus a bind hook that enables or\n * disables them for the current run. Packs are assembled at process start\n * (main.ts) and injected into runners; they must not be hardcoded in the\n * core tool list.\n */\nexport interface PlatformToolPack {\n tools: AgentTool<TSchema>[];\n bindRun(ctx: PlatformToolRunContext): void;\n}\n\n/**\n * Injected as factories, not instances: bindRun mutates closure state inside\n * the pack's tools, so a pack must be private to one runner (whose runs are\n * serialized). A single shared instance would let concurrent conversations\n * rebind each other mid-run — routing github_pr to the wrong conversation.\n */\nexport type PlatformToolPackFactory = () => PlatformToolPack;\n\n// ── event tool ───────────────────────────────────────────────────────────────\n\nexport type EventPayload = EventFilePayload;\n\nexport interface EventStore {\n write(filename: string, payload: EventFilePayload): Promise<{ path: string; size: number }>;\n /**\n * List all event files. Entries whose JSON cannot be parsed or fail format\n * validation are kept with a `null` payload so consumers (e.g. the admin\n * portal) can still surface and delete them; files that disappear\n * mid-listing are skipped.\n */\n list(): Promise<\n Array<{ filename: string; payload: EventFilePayload | null; size: number; mtimeMs: number }>\n >;\n read(\n filename: string,\n ): Promise<{ filename: string; payload: EventFilePayload; size: number; mtimeMs: number }>;\n update(filename: string, payload: EventFilePayload): Promise<{ path: string; size: number }>;\n delete(filename: string): Promise<{ deleted: boolean }>;\n}\n\n// ── truncation ───────────────────────────────────────────────────────────────\n\nexport interface TruncationResult {\n /** The truncated content */\n content: string;\n /** Whether truncation occurred */\n truncated: boolean;\n /** Which limit was hit: \"lines\", \"bytes\", or null if not truncated */\n truncatedBy: \"lines\" | \"bytes\" | null;\n /** Total number of lines in the original content */\n totalLines: number;\n /** Total number of bytes in the original content */\n totalBytes: number;\n /** Number of complete lines in the truncated output */\n outputLines: number;\n /** Number of bytes in the truncated output */\n outputBytes: number;\n /** Whether the last line was partially truncated (only for tail truncation edge case) */\n lastLinePartial: boolean;\n /** Whether the first line exceeded the byte limit (for head truncation) */\n firstLineExceedsLimit: boolean;\n}\n\nexport interface TruncationOptions {\n /** Maximum number of lines (default: 2000) */\n maxLines?: number;\n /** Maximum number of bytes (default: 50KB) */\n maxBytes?: number;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,QAAA,MAAM,WAAW;;;;EAIf,CAAC;AAEH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CA0BjF"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,QAAA,MAAM,WAAW;;;;EAIf,CAAC;AAEH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAqBjF"}
@@ -1,6 +1,4 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import { dirname } from "path";
3
- import { shellEscape } from "../sandbox/utils.js";
4
2
  const writeSchema = Type.Object({
5
3
  label: Type.String({ description: "Brief description of what you're writing (shown to user)" }),
6
4
  path: Type.String({ description: "Path to the file to write (relative or absolute)" }),
@@ -10,15 +8,11 @@ export function createWriteTool(executor) {
10
8
  return {
11
9
  name: "write",
12
10
  label: "write",
11
+ executionMode: "sequential",
13
12
  description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
14
13
  parameters: writeSchema,
15
14
  execute: async (_toolCallId, { path, content }, signal) => {
16
- const dir = dirname(path);
17
- const cmd = `mkdir -p ${shellEscape(dir)} && printf '%s' ${shellEscape(content)} > ${shellEscape(path)}`;
18
- const result = await executor.exec(cmd, { signal });
19
- if (result.code !== 0) {
20
- throw new Error(result.stderr || `Failed to write file: ${path}`);
21
- }
15
+ await executor.writeFile(path, content, { signal });
22
16
  return {
23
17
  content: [{ type: "text", text: `Successfully wrote ${content.length} bytes to ${path}` }],
24
18
  details: undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;IAC/F,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;IACtF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;CACtE,CAAC,CAAC;AAEH,MAAM,UAAU,eAAe,CAAC,QAAkB;IAChD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,WAAW,EACT,iIAAiI;QACnI,UAAU,EAAE,WAAW;QACvB,OAAO,EAAE,KAAK,EACZ,WAAmB,EACnB,EAAE,IAAI,EAAE,OAAO,EAAoD,EACnE,MAAoB,EACpB,EAAE;YACF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,GAAG,GAAG,YAAY,WAAW,CAAC,GAAG,CAAC,mBAAmB,WAAW,CAAC,OAAO,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAEzG,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACpD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,yBAAyB,IAAI,EAAE,CAAC,CAAC;YACpE,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,EAAE,CAAC;gBAC1F,OAAO,EAAE,SAAS;aACnB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport { dirname } from \"path\";\nimport type { Executor } from \"../sandbox/index.js\";\nimport { shellEscape } from \"../sandbox/utils.js\";\n\nconst writeSchema = Type.Object({\n label: Type.String({ description: \"Brief description of what you're writing (shown to user)\" }),\n path: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n content: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport function createWriteTool(executor: Executor): AgentTool<typeof writeSchema> {\n return {\n name: \"write\",\n label: \"write\",\n description:\n \"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n parameters: writeSchema,\n execute: async (\n _toolCallId: string,\n { path, content }: { label: string; path: string; content: string },\n signal?: AbortSignal,\n ) => {\n const dir = dirname(path);\n const cmd = `mkdir -p ${shellEscape(dir)} && printf '%s' ${shellEscape(content)} > ${shellEscape(path)}`;\n\n const result = await executor.exec(cmd, { signal });\n if (result.code !== 0) {\n throw new Error(result.stderr || `Failed to write file: ${path}`);\n }\n\n return {\n content: [{ type: \"text\", text: `Successfully wrote ${content.length} bytes to ${path}` }],\n details: undefined,\n };\n },\n };\n}\n"]}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;IAC/F,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;IACtF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;CACtE,CAAC,CAAC;AAEH,MAAM,UAAU,eAAe,CAAC,QAAkB;IAChD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,aAAa,EAAE,YAAY;QAC3B,WAAW,EACT,iIAAiI;QACnI,UAAU,EAAE,WAAW;QACvB,OAAO,EAAE,KAAK,EACZ,WAAmB,EACnB,EAAE,IAAI,EAAE,OAAO,EAAoD,EACnE,MAAoB,EACpB,EAAE;YACF,MAAM,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAEpD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,EAAE,CAAC;gBAC1F,OAAO,EAAE,SAAS;aACnB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { Executor } from \"../sandbox/index.js\";\n\nconst writeSchema = Type.Object({\n label: Type.String({ description: \"Brief description of what you're writing (shown to user)\" }),\n path: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n content: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport function createWriteTool(executor: Executor): AgentTool<typeof writeSchema> {\n return {\n name: \"write\",\n label: \"write\",\n executionMode: \"sequential\",\n description:\n \"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n parameters: writeSchema,\n execute: async (\n _toolCallId: string,\n { path, content }: { label: string; path: string; content: string },\n signal?: AbortSignal,\n ) => {\n await executor.writeFile(path, content, { signal });\n\n return {\n content: [{ type: \"text\", text: `Successfully wrote ${content.length} bytes to ${path}` }],\n details: undefined,\n };\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../src/trigger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAOtD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/E;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE,sBAAsB,CAAC,GACrD,aAAa,CAEf;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,aAAa,CAAC,CA4BzB"}
1
+ {"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../src/trigger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAMtD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/E;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE,sBAAsB,CAAC,GACrD,aAAa,CAEf;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,aAAa,CAAC,CA4BzB"}
package/dist/trigger.js CHANGED
@@ -2,7 +2,6 @@ import { join } from "path";
2
2
  import { MikanModels } from "./harness/index.js";
3
3
  import { loadAutoReplyJudgeModel, loadConversationAutoReplyConfig } from "./config.js";
4
4
  import * as log from "./log.js";
5
- import { resolveConfiguredModel } from "./model-registry.js";
6
5
  const JUDGE_TIMEOUT_MS = 10_000;
7
6
  /**
8
7
  * Trivially decide non-auto-reply intents synchronously. For "auto-reply-candidate"
@@ -65,7 +64,7 @@ function withTimeout(promise, ms) {
65
64
  async function judgeAutoReplyWithLlm(input) {
66
65
  const judgeConfig = loadAutoReplyJudgeModel(input.conversationDir);
67
66
  const models = MikanModels.create();
68
- const model = resolveConfiguredModel(models, judgeConfig.provider, judgeConfig.model);
67
+ const model = models.resolve(judgeConfig.provider, judgeConfig.model);
69
68
  const answer = await models.models.completeSimple(model, {
70
69
  systemPrompt: "You decide whether a bot should reply to a group/channel message. " +
71
70
  "Use only the rules provided by the user. Answer exactly YES or NO.",