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

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 +563 -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 +745 -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 +4 -0
  336. package/dist/sandbox/host.d.ts.map +1 -1
  337. package/dist/sandbox/host.js +52 -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 +65 -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
package/dist/agent.js CHANGED
@@ -1,24 +1,129 @@
1
- import { DEFAULT_EVENT_BUDGET, defaultExtensionDirs, formatSkillsForPrompt, loadExtensions, loadSkillsFromDir, MikanAgentSession, MikanModels, } from "./harness/index.js";
1
+ /**
2
+ * Agent runner: prompt construction, path translation, run lifecycle, and createRunner.
3
+ * Single module — do not split helpers that only this file uses.
4
+ */
5
+ import { DEFAULT_EVENT_BUDGET, formatSkillsForPrompt, loadExtensions, loadSkillsFromDir, MikanAgentSession, MikanModels, parseCommandInput, } from "./harness/index.js";
6
+ import { runSubagent } from "./harness/subagent-runner.js";
7
+ import { loadSubagentProfiles } from "./harness/subagent-profiles.js";
8
+ import { mergeSubagentProgress, parseSubagentProgressSnapshot, renderSubagentDashboard, settleSubagentProgress, } from "./subagent-progress.js";
2
9
  import { createHash } from "crypto";
3
- import { existsSync, readFileSync } from "fs";
4
- import { mkdir, readFile, writeFile } from "fs/promises";
5
- import { join, posix } from "path";
10
+ import { existsSync, lstatSync } from "fs";
11
+ import { chmod, mkdtemp, mkdir, readFile, rm, writeFile } from "fs/promises";
12
+ import { tmpdir } from "os";
13
+ import { basename, isAbsolute, join, posix, relative, resolve, sep } from "path";
6
14
  import { resolveConversationSettings } from "./config.js";
7
- import { readEnv } from "./utils/env.js";
15
+ import { effectiveStateDir } from "./cli/arg-grammar.js";
16
+ import { packageSkillRuntimeDir, resolveConversationPackages } from "./packages/index.js";
8
17
  import { ActorExecutionResolver } from "./execution-resolver.js";
9
18
  import * as log from "./log.js";
10
- import { reportUserFacingError } from "./observability/sentry.js";
11
- import { createExecutor, } from "./sandbox/index.js";
12
- import { createMountedRuntimePathContext } from "./sandbox/path-context.js";
13
- import { addLifecycleBreadcrumb, metricAttributes, updateActiveSpanAttribution, } from "./observability/sentry.js";
14
- import { AgentMemoryFileManager } from "./sessions/agent-memory-file-manager.js";
19
+ import { createExecutor, getUnresolvedSandboxPathContext, } from "./sandbox/index.js";
20
+ import { addLifecycleBreadcrumb, metricAttributes, reportUserFacingError, updateActiveSpanAttribution, } from "./observability/sentry.js";
21
+ import { ChatHistorySync } from "./sessions/chat-history-sync.js";
22
+ import { formatHistoryLine } from "./sessions/history-line.js";
23
+ import { conversationIdOf, isThreadSessionKey } from "./sessions/session-key.js";
15
24
  import { extractSessionUuid, openManagedSession, } from "./sessions/store.js";
16
25
  import { HostEventStore } from "./tools/event.js";
17
- import { createMikanTools } from "./tools/index.js";
26
+ import { createMikanTools, createSubagentTool, DEFAULT_GLOBAL_SUBAGENT_SLOTS, SubagentSlotPool, } from "./tools/index.js";
27
+ // One process-wide fan-out account: per-conversation queues serialize runs,
28
+ // but each run can fan out up to the per-run cap — without this shared
29
+ // ceiling, N busy conversations hold N × cap live subagent sessions.
30
+ const globalSubagentSlots = new SubagentSlotPool(DEFAULT_GLOBAL_SUBAGENT_SLOTS);
18
31
  import * as Sentry from "@sentry/node";
19
- import { formatLocalTimestamp } from "./utils/date.js";
20
- import { resolveConfiguredModel } from "./model-registry.js";
21
32
  import { emitAgentEvent } from "./agent-events.js";
33
+ export function translateRuntimePathToHost(runtimePath, pathContext) {
34
+ return pathContext.runtimeToHostPath?.(runtimePath) ?? runtimePath;
35
+ }
36
+ function isWithinPathRoot(path, root) {
37
+ const pathRelative = relative(root, path);
38
+ return (pathRelative === "" ||
39
+ (pathRelative !== ".." && !pathRelative.startsWith(`..${sep}`) && !isAbsolute(pathRelative)));
40
+ }
41
+ function hasParentTraversal(path) {
42
+ return path.split(/[\\/]/).some((segment) => segment === "..");
43
+ }
44
+ export function translateAttachPathToHost(filePath, pathContext) {
45
+ if (!pathContext.runtimeToHostPath) {
46
+ throw new Error("Cannot attach files: this sandbox has no host-backed runtime path mapping; attachments are unavailable for remote sandboxes such as Cloudflare or Firecracker");
47
+ }
48
+ if (hasParentTraversal(filePath)) {
49
+ throw new Error("Cannot attach files: parent-directory traversal is not allowed");
50
+ }
51
+ const runtimeRoot = resolve(pathContext.runtimeWorkspaceRoot);
52
+ const runtimePath = posix.isAbsolute(filePath)
53
+ ? filePath
54
+ : posix.join(pathContext.runtimeWorkspaceRoot, filePath);
55
+ const normalizedRuntimePath = resolve(runtimePath);
56
+ if (!isWithinPathRoot(normalizedRuntimePath, runtimeRoot)) {
57
+ throw new Error("Cannot attach files: path must be within the runtime workspace");
58
+ }
59
+ const hostRoot = resolve(pathContext.hostWorkspaceRoot);
60
+ const translatedPath = pathContext.runtimeToHostPath(runtimePath);
61
+ const hostPath = resolve(translatedPath);
62
+ if (!isWithinPathRoot(hostPath, hostRoot)) {
63
+ throw new Error("Cannot attach files: path must be within the host workspace");
64
+ }
65
+ // Reject symlinks in every existing component. Missing files are left for
66
+ // the uploader's normal error, but a present attachment must be a regular
67
+ // non-symlink path all the way from the workspace root.
68
+ if (existsSync(hostPath)) {
69
+ let current = hostRoot;
70
+ const pathParts = relative(hostRoot, hostPath).split(sep).filter(Boolean);
71
+ for (const [index, part] of pathParts.entries()) {
72
+ current = join(current, part);
73
+ let stat;
74
+ try {
75
+ stat = lstatSync(current);
76
+ }
77
+ catch {
78
+ break;
79
+ }
80
+ if (stat.isSymbolicLink()) {
81
+ throw new Error("Cannot attach files: symlink components are not allowed");
82
+ }
83
+ if (index === pathParts.length - 1 && !stat.isFile()) {
84
+ throw new Error("Cannot attach files: path must be a regular file");
85
+ }
86
+ }
87
+ }
88
+ return hostPath;
89
+ }
90
+ /**
91
+ * Normalize an attachment path using runtime lexical semantics only. The
92
+ * executor remains the authority for reading the resulting runtime path.
93
+ */
94
+ function normalizeAttachRuntimePath(filePath, runtimeWorkspaceRoot) {
95
+ if (hasParentTraversal(filePath)) {
96
+ throw new Error("Cannot attach files: parent-directory traversal is not allowed");
97
+ }
98
+ const runtimeRoot = posix.resolve(runtimeWorkspaceRoot);
99
+ const runtimePath = posix.resolve(runtimeRoot, filePath);
100
+ const runtimeRelativePath = posix.relative(runtimeRoot, runtimePath);
101
+ if (runtimeRelativePath === ".." ||
102
+ runtimeRelativePath.startsWith("../") ||
103
+ posix.isAbsolute(runtimeRelativePath)) {
104
+ throw new Error("Cannot attach files: path must be within the runtime workspace");
105
+ }
106
+ return runtimePath;
107
+ }
108
+ async function withStagedRuntimeFile(executor, runtimePath, upload) {
109
+ if (!executor.readFileBase64NoSymlinks) {
110
+ throw new Error("Attachments are unavailable: this sandbox cannot guarantee symlink-free path traversal");
111
+ }
112
+ const content = Buffer.from(await executor.readFileBase64NoSymlinks(runtimePath), "base64");
113
+ let stagingDir;
114
+ try {
115
+ stagingDir = await mkdtemp(join(tmpdir(), "mikan-upload-"));
116
+ await chmod(stagingDir, 0o700);
117
+ const stagedPath = join(stagingDir, basename(runtimePath));
118
+ await writeFile(stagedPath, content, { mode: 0o600, flag: "wx" });
119
+ await chmod(stagedPath, 0o600);
120
+ await upload(stagedPath);
121
+ }
122
+ finally {
123
+ if (stagingDir)
124
+ await rm(stagingDir, { recursive: true, force: true });
125
+ }
126
+ }
22
127
  const IMAGE_MIME_TYPES = {
23
128
  jpg: "image/jpeg",
24
129
  jpeg: "image/jpeg",
@@ -29,12 +134,46 @@ const IMAGE_MIME_TYPES = {
29
134
  function getImageMimeType(filename) {
30
135
  return IMAGE_MIME_TYPES[filename.toLowerCase().split(".").pop() || ""];
31
136
  }
32
- function buildThreadSessionName(message) {
33
- const text = message?.text?.trim();
34
- if (!text)
35
- return undefined;
36
- const userLabel = message?.userName || message?.user || "unknown";
37
- return `[${userLabel}]: ${text}`;
137
+ function formatTimestampedUserMessage(message) {
138
+ return formatHistoryLine({
139
+ date: new Date(),
140
+ userName: message.userName,
141
+ threadTs: message.threadTs,
142
+ text: message.text,
143
+ });
144
+ }
145
+ async function collectMessageAttachments(message, workspacePath, pathContext, readAttachment) {
146
+ const imageAttachments = [];
147
+ const nonImagePaths = [];
148
+ for (const attachment of message.attachments || []) {
149
+ const runtimePath = `${workspacePath}/${attachment.localPath}`;
150
+ const hostPath = pathContext?.runtimeToHostPath?.(runtimePath) ?? runtimePath;
151
+ const mimeType = getImageMimeType(attachment.localPath);
152
+ if (mimeType && existsSync(hostPath) && readAttachment) {
153
+ try {
154
+ imageAttachments.push({
155
+ type: "image",
156
+ mimeType,
157
+ data: await readAttachment(runtimePath),
158
+ });
159
+ }
160
+ catch {
161
+ nonImagePaths.push(runtimePath);
162
+ }
163
+ }
164
+ else {
165
+ nonImagePaths.push(runtimePath);
166
+ }
167
+ }
168
+ return { imageAttachments, nonImagePaths };
169
+ }
170
+ export async function buildPromptPayload(message, workspacePath, pathContext, readAttachment) {
171
+ let userMessage = formatTimestampedUserMessage(message);
172
+ const { imageAttachments, nonImagePaths } = await collectMessageAttachments(message, workspacePath, pathContext, readAttachment);
173
+ if (nonImagePaths.length > 0) {
174
+ userMessage += `\n\n<slack_attachments>\n${nonImagePaths.join("\n")}\n</slack_attachments>`;
175
+ }
176
+ return { userMessage, imageAttachments };
38
177
  }
39
178
  async function getMemory(conversationDir) {
40
179
  const parts = [];
@@ -82,6 +221,32 @@ function loadMikanSkills(conversationDir, workspacePath) {
82
221
  }
83
222
  return hostPath;
84
223
  };
224
+ // Package skills first: they are the lowest precedence, so a workspace or
225
+ // conversation skill of the same name below overwrites them. A package can
226
+ // offer a capability without taking the name away from whoever wants to
227
+ // replace it locally.
228
+ //
229
+ // Unlike extension-shipped skills, these are NOT inlined into the prompt:
230
+ // conversationPackageSkillMounts exposes them read-only at a runtime path,
231
+ // so the agent can read the files — including any scripts or templates the
232
+ // skill ships alongside its SKILL.md, which inlining could never carry.
233
+ const mounted = workspacePath !== hostWorkspacePath;
234
+ for (const { slug, dir } of resolveConversationPackages({
235
+ conversationId: basename(conversationDir),
236
+ stateDir: effectiveStateDir(),
237
+ conversationDir,
238
+ }).skillDirs) {
239
+ const runtimeDir = packageSkillRuntimeDir(slug);
240
+ for (const skill of loadSkillsFromDir({ dir, source: `package:${slug}` }).skills) {
241
+ // In host mode there is no mount, so the host path is already the path
242
+ // the agent will use.
243
+ if (mounted) {
244
+ skill.filePath = runtimeDir + skill.filePath.slice(dir.length);
245
+ skill.baseDir = runtimeDir + skill.baseDir.slice(dir.length);
246
+ }
247
+ skillMap.set(skill.name, skill);
248
+ }
249
+ }
85
250
  // Load workspace-level skills (global)
86
251
  const workspaceSkillsDir = join(hostWorkspacePath, "skills");
87
252
  for (const skill of loadSkillsFromDir({ dir: workspaceSkillsDir, source: "workspace" }).skills) {
@@ -174,8 +339,9 @@ function buildSystemPrompt(workspacePath, conversationId, conversationKind, curr
174
339
  const slackBlockKitInstructions = platform.name === "slack"
175
340
  ? `
176
341
  ## Slack Rendering
177
- - The Slack adapter renders responses with Block Kit automatically. Answer normally using Slack mrkdwn.
178
- - Do not emit markdown pipe tables; Slack does not render them as tables. Prefer short sections or bullet lists.
342
+ - The Slack adapter renders responses natively from standard Markdown. Answer in normal Markdown/GFM.
343
+ - Markdown pipe tables are rendered as native Slack tables.
344
+ - For interactive elements (buttons, select menus), use the slack_blockkit tool; user interactions arrive as "[Slack action] <action_id>: <value>" messages.
179
345
  `
180
346
  : "";
181
347
  return `You are mikan, a ${platform.name} bot assistant. Be concise. No emojis.
@@ -329,81 +495,21 @@ Do not add this to \`[SILENT]\` responses.`);
329
495
  }
330
496
  return parts.join("\n\n");
331
497
  }
332
- export function getUnresolvedSandboxPathContext(sandboxConfig, hostWorkspaceRoot) {
333
- if (sandboxConfig.type === "image") {
334
- return createMountedRuntimePathContext(hostWorkspaceRoot, "/workspace");
335
- }
336
- return createExecutor(sandboxConfig).getPathContext(hostWorkspaceRoot);
337
- }
338
- function createRunnerExecutionContext(sandboxConfig, vaultManager, provisioner, workspaceDir, hostWorkspacePath) {
339
- const executionResolver = vaultManager && sandboxConfig.type !== "host"
340
- ? new ActorExecutionResolver(sandboxConfig, vaultManager, provisioner, workspaceDir)
341
- : undefined;
342
- // activeExecutor is replaced at the start of each run() call when executionResolver
343
- // is present, so the stable `executor` wrapper always delegates to the latest resolved value.
344
- let activeExecutor = executionResolver !== undefined
345
- ? createExecutor({ type: "host" })
346
- : createExecutor(sandboxConfig);
347
- const executor = {
348
- exec(command, options) {
349
- return activeExecutor.exec(command, options);
350
- },
351
- getWorkspacePath(hostPath) {
352
- return activeExecutor.getWorkspacePath(hostPath);
353
- },
354
- getSandboxConfig() {
355
- return activeExecutor.getSandboxConfig();
356
- },
357
- getPathContext(hostWorkspaceRoot) {
358
- return activeExecutor.getPathContext(hostWorkspaceRoot);
359
- },
360
- };
361
- return {
362
- executionResolver,
363
- executor,
364
- getPathContext: () => executor.getPathContext(hostWorkspacePath),
365
- async resolveExecutorForRun(context) {
366
- if (!executionResolver)
367
- return;
368
- activeExecutor = await executionResolver.resolve(context);
369
- },
370
- };
371
- }
372
- /**
373
- * Extension host services over mikan's runtime infrastructure: schedules
374
- * become event files under `<workspaceDir>/events` (picked up live by
375
- * EventsWatcher), secrets come from `vaults/extensions/<slug>/env`, and
376
- * notify posts through the platform bots when main.ts provides a notifier.
377
- */
378
- function buildExtensionHostServices(params) {
379
- const { workspaceDir, vaultManager, platformNotifier } = params;
380
- const eventStore = HostEventStore.fromWorkspaceDir(workspaceDir);
381
- return {
382
- stateDir: readEnv("STATE_DIR"),
383
- scheduleStore: {
384
- write: async (filename, payload) => {
385
- // Event files tolerate a missing platform (single-platform default),
386
- // so the harness payload is a valid event payload as written.
387
- await eventStore.write(filename, payload);
388
- },
389
- delete: async (filename) => (await eventStore.delete(filename)).deleted,
390
- list: async () => (await eventStore.list()).map((entry) => ({
391
- filename: entry.filename,
392
- payload: entry.payload,
393
- })),
394
- },
395
- ...(platformNotifier ? { postMessage: platformNotifier } : {}),
396
- ...(vaultManager
397
- ? {
398
- resolveSecrets: (slug) => vaultManager.resolve(`extensions/${slug}`)?.env ?? {},
399
- }
400
- : {}),
401
- };
498
+ export function appendTriggerAttribution(text, triggerAttribution, sessionLink) {
499
+ if (!triggerAttribution)
500
+ return text;
501
+ const trimmed = text.trimEnd();
502
+ const legacySuffix = `_Triggered by ${triggerAttribution}_`;
503
+ // Slack mrkdwn italics cannot span a URL — a `_..._` wrapping a link renders
504
+ // the underscores literally. Keep the session link outside the italic span.
505
+ const suffix = sessionLink ? `${legacySuffix} · session: ${sessionLink}` : legacySuffix;
506
+ if (trimmed.endsWith(suffix))
507
+ return text;
508
+ const body = trimmed.endsWith(legacySuffix)
509
+ ? trimmed.slice(0, -legacySuffix.length).trimEnd()
510
+ : trimmed;
511
+ return `${body}\n\n${suffix}`;
402
512
  }
403
- /**
404
- * Local (workspace/conversation) skills override extension skills on name
405
- * collision: an admin's on-disk skill always beats an extension's.
406
- */
407
513
  function mergeExtensionSkills(local, extension) {
408
514
  if (extension.length === 0)
409
515
  return local;
@@ -414,37 +520,6 @@ function mergeExtensionSkills(local, extension) {
414
520
  byName.set(skill.name, skill);
415
521
  return [...byName.values()];
416
522
  }
417
- async function createConfiguredAgentSession(params) {
418
- const { conversationId, workspaceDir, systemPrompt, model, thinkingLevel, tools, sessionStore, models, vaultManager, platformNotifier, } = params;
419
- // Host-only dirs under the state dir: extension code runs in the mikan
420
- // process, so it must never load from workspace paths — those are mounted
421
- // into sandbox containers and agent-writable (sandbox escape otherwise).
422
- const extensionsResult = await loadExtensions({
423
- dirs: defaultExtensionDirs(conversationId, readEnv("STATE_DIR")),
424
- context: { conversationId, workspaceDir, model, thinkingLevel },
425
- services: buildExtensionHostServices({ workspaceDir, vaultManager, platformNotifier }),
426
- });
427
- for (const err of extensionsResult.errors) {
428
- log.logWarning(`[${conversationId}] Extension load error: ${err.path}`, err.error);
429
- }
430
- if (extensionsResult.extensions.length > 0) {
431
- log.logInfo(`[${conversationId}] Loaded ${extensionsResult.extensions.length} extension(s): ${extensionsResult.extensions.map((extension) => extension.name).join(", ")}`);
432
- }
433
- const session = new MikanAgentSession({
434
- systemPrompt,
435
- model,
436
- thinkingLevel,
437
- tools,
438
- models,
439
- sessionStore,
440
- extensions: extensionsResult.registry,
441
- });
442
- const reloaded = session.reloadFromSession();
443
- if (reloaded > 0) {
444
- log.logInfo(`[${conversationId}] Reloaded ${reloaded} messages from session context`);
445
- }
446
- return { session, extensionSkills: extensionsResult.skills };
447
- }
448
523
  function createEmptyUsageTotals() {
449
524
  return {
450
525
  input: 0,
@@ -461,6 +536,13 @@ function createRunState() {
461
536
  queue: null,
462
537
  pendingTools: new Map(),
463
538
  toolProgress: new Map(),
539
+ subagentProgress: new Map(),
540
+ completedSubagentProgress: [],
541
+ subagentToolCalls: new Set(),
542
+ subagentProgressShown: false,
543
+ suppressResponseDeltas: false,
544
+ lastSubagentProgressAt: 0,
545
+ toolProgressTimer: undefined,
464
546
  totalUsage: createEmptyUsageTotals(),
465
547
  llmCallCount: 0,
466
548
  stopReason: "stop",
@@ -480,6 +562,15 @@ function resetRunState(runState, responder, sessionConversation, userName, sessi
480
562
  };
481
563
  runState.pendingTools.clear();
482
564
  runState.toolProgress.clear();
565
+ runState.subagentProgress.clear();
566
+ runState.completedSubagentProgress = [];
567
+ runState.subagentToolCalls.clear();
568
+ runState.subagentProgressShown = false;
569
+ runState.suppressResponseDeltas = false;
570
+ runState.lastSubagentProgressAt = 0;
571
+ if (runState.toolProgressTimer)
572
+ clearTimeout(runState.toolProgressTimer);
573
+ runState.toolProgressTimer = undefined;
483
574
  runState.totalUsage = createEmptyUsageTotals();
484
575
  runState.llmCallCount = 0;
485
576
  runState.stopReason = "stop";
@@ -515,53 +606,6 @@ function createRunQueue(responder, runState) {
515
606
  wait: () => queueChain,
516
607
  };
517
608
  }
518
- function formatTimestampedUserMessage(message) {
519
- const timestamp = formatLocalTimestamp(new Date());
520
- const threadContext = message.threadTs ? ` [in-thread:${message.threadTs}]` : "";
521
- return `[${timestamp}] [${message.userName || "unknown"}]${threadContext}: ${message.text}`;
522
- }
523
- function collectMessageAttachments(message, workspacePath, pathContext) {
524
- const imageAttachments = [];
525
- const nonImagePaths = [];
526
- for (const attachment of message.attachments || []) {
527
- const runtimePath = `${workspacePath}/${attachment.localPath}`;
528
- const hostPath = pathContext?.runtimeToHostPath?.(runtimePath) ?? runtimePath;
529
- const mimeType = getImageMimeType(attachment.localPath);
530
- if (mimeType && existsSync(hostPath)) {
531
- try {
532
- imageAttachments.push({
533
- type: "image",
534
- mimeType,
535
- data: readFileSync(hostPath).toString("base64"),
536
- });
537
- }
538
- catch {
539
- nonImagePaths.push(runtimePath);
540
- }
541
- }
542
- else {
543
- nonImagePaths.push(runtimePath);
544
- }
545
- }
546
- return { imageAttachments, nonImagePaths };
547
- }
548
- export function buildPromptPayload(message, workspacePath, pathContext) {
549
- let userMessage = formatTimestampedUserMessage(message);
550
- const { imageAttachments, nonImagePaths } = collectMessageAttachments(message, workspacePath, pathContext);
551
- if (nonImagePaths.length > 0) {
552
- userMessage += `\n\n<slack_attachments>\n${nonImagePaths.join("\n")}\n</slack_attachments>`;
553
- }
554
- return { userMessage, imageAttachments };
555
- }
556
- async function writePromptDebugContext(conversationDir, systemPrompt, session, userMessage, imageAttachmentCount) {
557
- const debugContext = {
558
- systemPrompt,
559
- messages: session.messages,
560
- newUserMessage: userMessage,
561
- imageAttachmentCount,
562
- };
563
- await writeFile(join(conversationDir, "last_prompt.jsonl"), JSON.stringify(debugContext, null, 2));
564
- }
565
609
  function getFinalAssistantText(session) {
566
610
  const lastAssistant = session.messages.findLast((message) => message.role === "assistant");
567
611
  return (lastAssistant?.content
@@ -569,21 +613,6 @@ function getFinalAssistantText(session) {
569
613
  .map((content) => content.text)
570
614
  .join("\n") || "");
571
615
  }
572
- export function appendTriggerAttribution(text, triggerAttribution, sessionLink) {
573
- if (!triggerAttribution)
574
- return text;
575
- const trimmed = text.trimEnd();
576
- const legacySuffix = `_Triggered by ${triggerAttribution}_`;
577
- const suffix = sessionLink
578
- ? `_Triggered by ${triggerAttribution} · session: ${sessionLink}_`
579
- : legacySuffix;
580
- if (trimmed.endsWith(suffix))
581
- return text;
582
- const body = trimmed.endsWith(legacySuffix)
583
- ? trimmed.slice(0, -legacySuffix.length).trimEnd()
584
- : trimmed;
585
- return `${body}\n\n${suffix}`;
586
- }
587
616
  function isEventTriggerAttribution(triggerAttribution) {
588
617
  return triggerAttribution?.startsWith("[event:") === true;
589
618
  }
@@ -593,22 +622,86 @@ function extractToolLabel(toolName, args) {
593
622
  return toolName;
594
623
  return label.trim() || toolName;
595
624
  }
625
+ /** Non-subagent tool activity lines; subagent calls render as the dashboard. */
596
626
  function formatToolProgress(runState) {
597
- const lines = Array.from(runState.toolProgress.values()).map((item) => {
627
+ const lines = Array.from(runState.toolProgress.entries()).flatMap(([toolCallId, item]) => {
628
+ if (runState.subagentToolCalls.has(toolCallId))
629
+ return [];
598
630
  const marker = item.status === "running" ? "•" : item.status === "error" ? "✗" : "✓";
599
- return `${marker} ${item.label}`;
631
+ return [`${marker} ${item.label}`];
600
632
  });
601
633
  return lines.join("\n");
602
634
  }
603
635
  function formatResponseWithToolProgress(text, runState) {
604
636
  const progress = formatToolProgress(runState);
605
- return progress ? `${progress}\n\n${text}` : text;
637
+ return [progress, text].filter(Boolean).join("\n\n");
638
+ }
639
+ /**
640
+ * The one dashboard render path. A responder that overrides
641
+ * `replaceSubagentProgress` converts the snapshot for a pipeline that is not
642
+ * response-source Markdown (Telegram HTML); every other platform receives the
643
+ * Markdown dashboard — "dashboard, blank line, answer" — through
644
+ * `replaceResponse`, the same conversion as any response.
645
+ */
646
+ async function replaceWithSubagentDashboard(responder, snapshot, finalText, options) {
647
+ if (responder.replaceSubagentProgress) {
648
+ await responder.replaceSubagentProgress(snapshot, finalText);
649
+ return;
650
+ }
651
+ const dashboard = renderSubagentDashboard(snapshot);
652
+ await responder.replaceResponse(finalText ? `${dashboard}\n\n${finalText}` : dashboard, options);
606
653
  }
607
- async function replaceResponseWithToolProgress(responder, runState) {
654
+ async function replaceResponseWithToolProgress(responder, runState, subagentProgress = mergeSubagentProgress([...runState.subagentProgress.values()])) {
655
+ if (subagentProgress) {
656
+ await replaceWithSubagentDashboard(responder, subagentProgress);
657
+ return;
658
+ }
608
659
  const progress = formatToolProgress(runState);
609
660
  if (progress)
610
661
  await responder.replaceResponse(progress);
611
662
  }
663
+ const TOOL_PROGRESS_DEBOUNCE_MS = 500;
664
+ const SUBAGENT_PROGRESS_THROTTLE_MS = 2000;
665
+ function subagentProgressDelay(runState) {
666
+ if (!runState.subagentProgressShown)
667
+ return 0;
668
+ return Math.max(0, runState.lastSubagentProgressAt + SUBAGENT_PROGRESS_THROTTLE_MS - Date.now());
669
+ }
670
+ function scheduleToolProgressUpdate(responder, runState) {
671
+ if (runState.toolProgressTimer)
672
+ return;
673
+ const subagentProgress = mergeSubagentProgress([...runState.subagentProgress.values()]);
674
+ const delay = subagentProgress ? subagentProgressDelay(runState) : TOOL_PROGRESS_DEBOUNCE_MS;
675
+ runState.toolProgressTimer = setTimeout(() => {
676
+ runState.toolProgressTimer = undefined;
677
+ const snapshot = mergeSubagentProgress([...runState.subagentProgress.values()]);
678
+ if (snapshot) {
679
+ runState.subagentProgressShown = true;
680
+ runState.lastSubagentProgressAt = Date.now();
681
+ }
682
+ runState.queue?.enqueue(() => replaceResponseWithToolProgress(responder, runState, snapshot), "tool progress update");
683
+ }, delay);
684
+ runState.toolProgressTimer.unref();
685
+ }
686
+ function flushToolProgressUpdate(responder, runState) {
687
+ if (runState.toolProgressTimer)
688
+ clearTimeout(runState.toolProgressTimer);
689
+ runState.toolProgressTimer = undefined;
690
+ const subagentProgress = mergeSubagentProgress([...runState.subagentProgress.values()]);
691
+ if (subagentProgress) {
692
+ runState.subagentProgressShown = true;
693
+ runState.lastSubagentProgressAt = Date.now();
694
+ }
695
+ runState.queue?.enqueue(() => replaceResponseWithToolProgress(responder, runState, subagentProgress), "tool progress update");
696
+ }
697
+ function extractSubagentProgress(partialResult) {
698
+ if (!partialResult || typeof partialResult !== "object")
699
+ return undefined;
700
+ const details = partialResult.details;
701
+ if (!details || typeof details !== "object")
702
+ return undefined;
703
+ return parseSubagentProgressSnapshot(details.progress);
704
+ }
612
705
  async function finalizeRunResponse(responder, session, runState, options) {
613
706
  if (runState.stopReason === "error" && runState.errorMessage) {
614
707
  if (!runState.reportedLlmError) {
@@ -673,7 +766,17 @@ async function finalizeRunResponse(responder, session, runState, options) {
673
766
  if (!finalText.trim())
674
767
  return;
675
768
  try {
676
- await responder.replaceResponse(appendTriggerAttribution(formatResponseWithToolProgress(finalText, runState), options?.triggerAttribution, options?.triggerSessionLink), { createOverflowLink: options?.createOverflowLink });
769
+ const finalResponse = appendTriggerAttribution(finalText, options?.triggerAttribution, options?.triggerSessionLink);
770
+ const finalDashboard = mergeSubagentProgress(runState.completedSubagentProgress);
771
+ if (finalDashboard) {
772
+ await replaceWithSubagentDashboard(responder, finalDashboard, finalResponse, {
773
+ createOverflowLink: options?.createOverflowLink,
774
+ });
775
+ return;
776
+ }
777
+ await responder.replaceResponse(formatResponseWithToolProgress(finalResponse, runState), {
778
+ createOverflowLink: options?.createOverflowLink,
779
+ });
677
780
  }
678
781
  catch (err) {
679
782
  const errMsg = err instanceof Error ? err.message : String(err);
@@ -739,6 +842,215 @@ async function reportUsageSummary(ctx) {
739
842
  await waitForQueue();
740
843
  }
741
844
  }
845
+ function extractToolResultText(result) {
846
+ if (typeof result === "string") {
847
+ return result;
848
+ }
849
+ if (result &&
850
+ typeof result === "object" &&
851
+ "content" in result &&
852
+ Array.isArray(result.content)) {
853
+ const content = result.content;
854
+ const textParts = [];
855
+ for (const part of content) {
856
+ if (part.type === "text" && part.text) {
857
+ textParts.push(part.text);
858
+ }
859
+ }
860
+ if (textParts.length > 0) {
861
+ return textParts.join("\n");
862
+ }
863
+ }
864
+ return JSON.stringify(result);
865
+ }
866
+ function buildThreadSessionName(message) {
867
+ const text = message?.text?.trim();
868
+ if (!text)
869
+ return undefined;
870
+ const userLabel = message?.userName || message?.user || "unknown";
871
+ return `[${userLabel}]: ${text}`;
872
+ }
873
+ function createRunnerExecutionContext(sandboxConfig, vaultManager, provisioner, workspaceDir, hostWorkspacePath) {
874
+ const executionResolver = vaultManager && sandboxConfig.type !== "host"
875
+ ? new ActorExecutionResolver(sandboxConfig, vaultManager, provisioner, workspaceDir, hostWorkspacePath)
876
+ : undefined;
877
+ // activeExecutor is replaced at the start of each run() call when executionResolver
878
+ // is present, so the stable `executor` wrapper always delegates to the latest resolved value.
879
+ let activeExecutor = executionResolver !== undefined
880
+ ? createExecutor({ type: "host" })
881
+ : createExecutor(sandboxConfig);
882
+ const executor = {
883
+ exec(command, options) {
884
+ return activeExecutor.exec(command, options);
885
+ },
886
+ readFile(path, options) {
887
+ return activeExecutor.readFile(path, options);
888
+ },
889
+ readFileBase64(path, options) {
890
+ return activeExecutor.readFileBase64(path, options);
891
+ },
892
+ readFileBase64NoSymlinks(path, options) {
893
+ if (!activeExecutor.readFileBase64NoSymlinks) {
894
+ throw new Error("Attachments are unavailable: this sandbox cannot guarantee symlink-free path traversal");
895
+ }
896
+ return activeExecutor.readFileBase64NoSymlinks(path, options);
897
+ },
898
+ writeFile(path, content, options) {
899
+ return activeExecutor.writeFile(path, content, options);
900
+ },
901
+ getWorkspacePath(hostPath) {
902
+ return activeExecutor.getWorkspacePath(hostPath);
903
+ },
904
+ getSandboxConfig() {
905
+ return activeExecutor.getSandboxConfig();
906
+ },
907
+ getPathContext(hostWorkspaceRoot) {
908
+ return activeExecutor.getPathContext(hostWorkspaceRoot);
909
+ },
910
+ };
911
+ return {
912
+ executionResolver,
913
+ executor,
914
+ getPathContext: () => executor.getPathContext(hostWorkspacePath),
915
+ async resolveExecutorForRun(context) {
916
+ if (!executionResolver)
917
+ return;
918
+ activeExecutor = await executionResolver.resolve(context);
919
+ },
920
+ };
921
+ }
922
+ /**
923
+ * Extension host services over mikan's runtime infrastructure: schedules
924
+ * become event files under `<workspaceDir>/events` (picked up live by
925
+ * EventsWatcher), secrets come from `vaults/extensions/<slug>/env`, and
926
+ * notify posts through the platform bots when main.ts provides a notifier.
927
+ */
928
+ function buildExtensionHostServices(params) {
929
+ const { workspaceDir, vaultManager, platformNotifier, platformReactor, platformUploader, platformBlockKit, runSubagentService, } = params;
930
+ const eventStore = HostEventStore.fromWorkspaceDir(workspaceDir);
931
+ return {
932
+ stateDir: effectiveStateDir(),
933
+ scheduleStore: {
934
+ write: async (filename, payload) => {
935
+ await eventStore.write(filename, payload);
936
+ },
937
+ delete: async (filename) => (await eventStore.delete(filename)).deleted,
938
+ list: async () => (await eventStore.list()).flatMap((entry) => entry.payload ? [{ filename: entry.filename, payload: entry.payload }] : []),
939
+ },
940
+ ...(platformNotifier ? { postMessage: platformNotifier } : {}),
941
+ ...(platformReactor ? { addReaction: platformReactor } : {}),
942
+ ...(platformUploader ? { uploadFile: platformUploader } : {}),
943
+ ...(platformBlockKit
944
+ ? { postBlocks: platformBlockKit.postBlocks, updateBlocks: platformBlockKit.updateBlocks }
945
+ : {}),
946
+ ...(runSubagentService ? { runSubagent: runSubagentService } : {}),
947
+ ...(vaultManager
948
+ ? {
949
+ resolveSecrets: (slug) => vaultManager.resolve(`extensions/${slug}`)?.env ?? {},
950
+ }
951
+ : {}),
952
+ };
953
+ }
954
+ async function createConfiguredAgentSession(params) {
955
+ const { conversationId, workspaceDir, systemPrompt, model, thinkingLevel, tools, sessionStore, models, vaultManager, platformNotifier, platformReactor, platformUploader, platformBlockKit, } = params;
956
+ // Host-only dirs under the state dir: extension code runs in the mikan
957
+ // process, so it must never load from workspace paths — those are mounted
958
+ // into sandbox containers and agent-writable (sandbox escape otherwise).
959
+ // resolveConversationPackages only ever returns state-dir paths (and host
960
+ // paths an administrator named explicitly in settings); it never reaches
961
+ // the network on this path, so a slow remote cannot delay a reply.
962
+ let session;
963
+ const loadedProfiles = loadSubagentProfiles(workspaceDir);
964
+ for (const diagnostic of loadedProfiles.diagnostics) {
965
+ log.logWarning(`[${conversationId}] Subagent profile ignored: ${diagnostic.path}`, diagnostic.message);
966
+ }
967
+ // Narrowed to the profiles whose tools actually exist once extensions have
968
+ // contributed theirs. Both subagent entry points read this at call time, so
969
+ // they always agree on which profiles are launchable.
970
+ let runnableSubagentProfiles = loadedProfiles.profiles;
971
+ const resolvedPackages = resolveConversationPackages({
972
+ conversationId,
973
+ stateDir: effectiveStateDir(),
974
+ conversationDir: join(workspaceDir, conversationId),
975
+ });
976
+ for (const error of resolvedPackages.errors) {
977
+ log.logWarning(`Package unavailable: ${error.source}`, error.message);
978
+ }
979
+ const extensionsResult = await loadExtensions({
980
+ dirs: resolvedPackages.extensionDirs,
981
+ roots: resolvedPackages.extensionRoots,
982
+ context: { conversationId, workspaceDir, model, thinkingLevel },
983
+ services: buildExtensionHostServices({
984
+ workspaceDir,
985
+ vaultManager,
986
+ platformNotifier,
987
+ platformReactor,
988
+ platformUploader,
989
+ platformBlockKit,
990
+ runSubagentService: (request, extensionTools) => {
991
+ const activeParent = session?.isActiveRun ? session : undefined;
992
+ return runSubagent({
993
+ request,
994
+ defaultModel: model,
995
+ thinkingLevel,
996
+ models,
997
+ workspaceDir,
998
+ availableTools: [...tools, ...extensionTools],
999
+ profiles: runnableSubagentProfiles,
1000
+ slots: globalSubagentSlots,
1001
+ ...(activeParent
1002
+ ? {
1003
+ parentMessages: [...activeParent.messages],
1004
+ onUsage: activeParent.captureExternalUsageSink(),
1005
+ }
1006
+ : {}),
1007
+ });
1008
+ },
1009
+ }),
1010
+ });
1011
+ const contributedTools = extensionsResult.registry.getContributedTools();
1012
+ const subagentAvailableTools = [...tools, ...contributedTools];
1013
+ const availableToolNames = new Set(subagentAvailableTools.map((tool) => tool.name));
1014
+ runnableSubagentProfiles = new Map([...loadedProfiles.profiles].filter(([, profile]) => profile.tools.every((tool) => availableToolNames.has(tool))));
1015
+ for (const err of extensionsResult.errors) {
1016
+ log.logWarning(`[${conversationId}] Extension load error: ${err.path}`, err.error);
1017
+ }
1018
+ if (extensionsResult.extensions.length > 0) {
1019
+ log.logInfo(`[${conversationId}] Loaded ${extensionsResult.extensions.length} extension(s): ${extensionsResult.extensions.map((extension) => extension.name).join(", ")}`);
1020
+ }
1021
+ const subagentTool = createSubagentTool((request) => runSubagent({
1022
+ request,
1023
+ defaultModel: model,
1024
+ thinkingLevel,
1025
+ models,
1026
+ workspaceDir,
1027
+ availableTools: subagentAvailableTools,
1028
+ profiles: runnableSubagentProfiles,
1029
+ slots: globalSubagentSlots,
1030
+ parentMessages: [...session.messages],
1031
+ onUsage: session.captureExternalUsageSink(),
1032
+ }), runnableSubagentProfiles);
1033
+ session = new MikanAgentSession({
1034
+ systemPrompt,
1035
+ model,
1036
+ thinkingLevel,
1037
+ tools: [...tools, subagentTool],
1038
+ models,
1039
+ sessionStore,
1040
+ extensions: extensionsResult.registry,
1041
+ });
1042
+ const activeSession = session;
1043
+ const reloaded = activeSession.reloadFromSession();
1044
+ if (reloaded > 0) {
1045
+ log.logInfo(`[${conversationId}] Reloaded ${reloaded} messages from session context`);
1046
+ }
1047
+ return {
1048
+ session: activeSession,
1049
+ extensionSkills: extensionsResult.skills,
1050
+ extensionRegistry: extensionsResult.registry,
1051
+ disposeExtensions: extensionsResult.dispose,
1052
+ };
1053
+ }
742
1054
  function reloadSessionMessages(session, conversationId) {
743
1055
  const reloaded = session.reloadFromSession();
744
1056
  if (reloaded > 0) {
@@ -746,15 +1058,16 @@ function reloadSessionMessages(session, conversationId) {
746
1058
  }
747
1059
  }
748
1060
  async function prepareRunContext(params) {
749
- const { message, responder, platform, conversationId, conversationDir, sessionUuid, runState, executor, executionResolver, resolveExecutorForRun, getPathContext, session, setEventContext, setSandboxContext, setUploadFunction, } = params;
1061
+ const { message, responder, platform, conversationId, conversationDir, sessionUuid, runState, executor, executionResolver, resolveExecutorForRun, getPathContext, session, setEventContext, setSandboxContext, setUploadFunction, setReactFunction, bindPlatformToolPacks, } = params;
750
1062
  let pathContext = params.pathContext;
751
- const sessionConversation = message.sessionKey.split(":")[0];
1063
+ const sessionConversation = conversationIdOf(message.sessionKey);
752
1064
  await mkdir(join(conversationDir, "scratch"), { recursive: true });
753
1065
  if (executionResolver) {
754
1066
  await resolveExecutorForRun({
755
1067
  platform: platform.name,
756
1068
  userId: message.userId,
757
1069
  conversationId,
1070
+ trustModel: platform.trustModel,
758
1071
  });
759
1072
  pathContext = getPathContext();
760
1073
  }
@@ -768,9 +1081,11 @@ async function prepareRunContext(params) {
768
1081
  // provider prompt caching. If this hash changes between turns of one
769
1082
  // conversation, something turn-varying leaked into the prompt; if it is
770
1083
  // stable and cacheRead stays 0, the miss is provider-side (e.g. OpenRouter
771
- // routing the model across upstream hosts).
1084
+ // routing the model across upstream hosts). This is the base prompt mikan
1085
+ // builds; a `before_agent_start` extension may still rewrite it per turn
1086
+ // (logged separately by the runner).
772
1087
  const promptHash = createHash("sha256").update(systemPrompt).digest("hex").slice(0, 8);
773
- log.logInfo(`[${conversationId}] System prompt: ${systemPrompt.length} chars, sha ${promptHash}`);
1088
+ log.logInfo(`[${conversationId}] System prompt (base): ${systemPrompt.length} chars, sha ${promptHash}`);
774
1089
  setEventContext({
775
1090
  platform: platform.name,
776
1091
  conversationId,
@@ -779,18 +1094,30 @@ async function prepareRunContext(params) {
779
1094
  });
780
1095
  setSandboxContext({ conversationId, userId: message.userId });
781
1096
  setUploadFunction(async (filePath, title) => {
782
- const hostPath = translateAttachPathToHost(filePath, pathContext);
783
- await responder.uploadFile(hostPath, title);
1097
+ const runtimePath = normalizeAttachRuntimePath(filePath, pathContext.runtimeWorkspaceRoot);
1098
+ await withStagedRuntimeFile(executor, runtimePath, (stagedPath) => responder.uploadFile(stagedPath, title));
1099
+ });
1100
+ // The react tool is available only when the responder supports reactions
1101
+ // (interactive turns on platforms with reaction support); otherwise unset
1102
+ // so the tool reports it is unavailable rather than silently no-op'ing.
1103
+ setReactFunction(responder.react ? async (emoji) => responder.react(emoji) : null);
1104
+ // Platform capability packs (e.g. GitHub PR/CI) enable themselves per run;
1105
+ // core does not branch on platform name here.
1106
+ bindPlatformToolPacks({
1107
+ conversationId,
1108
+ platformName: platform.name,
1109
+ threadTs: message.threadTs,
784
1110
  });
785
1111
  resetRunState(runState, responder, sessionConversation, message.userName, sessionUuid, triggerAttribution);
786
1112
  const runQueue = createRunQueue(responder, runState);
787
1113
  runState.queue = runQueue.queue;
788
1114
  log.logInfo(`Context sizes - system: ${systemPrompt.length} chars, memory: ${memory.length} chars`);
789
1115
  log.logInfo(`Channels: ${platform.channels.length}, Users: ${platform.users.length}`);
790
- const { userMessage, imageAttachments } = buildPromptPayload(message, pathContext.runtimeWorkspaceRoot, pathContext);
1116
+ const { userMessage, imageAttachments } = await buildPromptPayload(message, pathContext.runtimeWorkspaceRoot, pathContext, executor.readFileBase64NoSymlinks
1117
+ ? (runtimePath) => executor.readFileBase64NoSymlinks(runtimePath)
1118
+ : undefined);
791
1119
  const turnInstructions = buildTurnInstructions(message.id.startsWith("event:"), triggerAttribution, platform.name);
792
1120
  const finalUserMessage = turnInstructions ? `${turnInstructions}\n\n${userMessage}` : userMessage;
793
- await writePromptDebugContext(conversationDir, systemPrompt, session, finalUserMessage, imageAttachments.length);
794
1121
  return {
795
1122
  sessionConversation,
796
1123
  runQueue,
@@ -800,6 +1127,63 @@ async function prepareRunContext(params) {
800
1127
  pathContext,
801
1128
  };
802
1129
  }
1130
+ /**
1131
+ * The dream run reads a transcript in which the agent held its full tool set,
1132
+ * but `sessionDreamTools` has since narrowed it. Left to infer its grant from
1133
+ * the transcript, the model calls a tool it no longer holds and burns one of
1134
+ * its five turns on the failure — so the grant is stated, and derived from the
1135
+ * tools actually handed to the run rather than restated by hand.
1136
+ */
1137
+ function sessionDreamPrompt(conversationMemoryPath, toolNames) {
1138
+ // read/edit/write are core tools, so an empty grant does not arise today;
1139
+ // the fallback only keeps this sentence coherent if that ever changes.
1140
+ const grant = toolNames.length === 0
1141
+ ? "You have no tools in this run and cannot change memory. Say so and stop."
1142
+ : `Your tools this run: ${toolNames.join(", ")}. Nothing else will execute, including tools used earlier in this transcript. ${conversationMemoryPath} is the only path you may write.`;
1143
+ return [
1144
+ "Before this conversation is reset or rotated, preserve only durable information worth carrying into future sessions of this same conversation.",
1145
+ `Review the existing transcript and update only the conversation-specific MEMORY.md at ${conversationMemoryPath}.`,
1146
+ grant,
1147
+ "Do not modify the workspace-level global MEMORY.md. Information from one DM or channel must not be promoted into memory shared with other conversations by this maintenance run.",
1148
+ "Preserve durable decisions, preferences, facts, and ongoing work specific to this conversation. Preserve the concrete values and details needed to resume the work; do not replace them with abstract categories, summaries of retention rules, or statements that merely say a kind of information is durable. An explicit user statement that a fact, preference, or decision should persist is strong evidence that its exact content is worth preserving.",
1149
+ "Deduplicate against existing conversation memory. Do not preserve transient discussion, tool noise, secrets, speculative details, or test scaffolding. If there is nothing new worth preserving, make no changes. Do no unrelated work.",
1150
+ ].join("\n");
1151
+ }
1152
+ const SESSION_DREAM_BUDGET = {
1153
+ maxDurationMs: 2 * 60 * 1000,
1154
+ maxLlmCalls: 5,
1155
+ maxCostUsd: 0.25,
1156
+ };
1157
+ function sessionDreamTools(tools, conversationMemoryPath) {
1158
+ return tools
1159
+ .filter((tool) => tool.name === "read" || tool.name === "edit" || tool.name === "write")
1160
+ .map((tool) => {
1161
+ if (tool.name === "read")
1162
+ return tool;
1163
+ return Object.assign({}, tool, {
1164
+ execute: async (...args) => {
1165
+ const params = args[1];
1166
+ if (params.path !== conversationMemoryPath) {
1167
+ throw new Error(`Session Dream may only modify ${conversationMemoryPath}`);
1168
+ }
1169
+ return tool.execute(...args);
1170
+ },
1171
+ });
1172
+ });
1173
+ }
1174
+ async function noopResponderMethod() { }
1175
+ function createNoopResponder() {
1176
+ return {
1177
+ respond: noopResponderMethod,
1178
+ replaceResponse: noopResponderMethod,
1179
+ respondDiagnostic: noopResponderMethod,
1180
+ respondToolResult: noopResponderMethod,
1181
+ setTyping: noopResponderMethod,
1182
+ setWorking: noopResponderMethod,
1183
+ uploadFile: noopResponderMethod,
1184
+ deleteResponse: noopResponderMethod,
1185
+ };
1186
+ }
803
1187
  function formatAgentActorName(userName, fallback) {
804
1188
  return userName ? `DM:${userName}` : fallback;
805
1189
  }
@@ -837,7 +1221,12 @@ function attachSessionEventHandlers(params) {
837
1221
  label: extractToolLabel(event.toolName, event.args),
838
1222
  status: "running",
839
1223
  });
840
- queue.enqueue(() => replaceResponseWithToolProgress(responder, runState), "tool progress update");
1224
+ if (event.toolName === "subagent") {
1225
+ runState.subagentToolCalls.add(event.toolCallId);
1226
+ }
1227
+ else {
1228
+ queue.enqueue(() => replaceResponseWithToolProgress(responder, runState), "tool progress update");
1229
+ }
841
1230
  addLifecycleBreadcrumb("agent.tool.started", {
842
1231
  tool: event.toolName,
843
1232
  ...baseAttrs,
@@ -845,6 +1234,16 @@ function attachSessionEventHandlers(params) {
845
1234
  log.logToolStart(logCtx, event.toolName, label, event.args);
846
1235
  return;
847
1236
  }
1237
+ if (event.type === "tool_execution_update") {
1238
+ const subagentProgress = extractSubagentProgress(event.partialResult);
1239
+ if (subagentProgress) {
1240
+ runState.subagentProgress.set(event.toolCallId, subagentProgress);
1241
+ runState.subagentToolCalls.add(event.toolCallId);
1242
+ runState.suppressResponseDeltas = true;
1243
+ scheduleToolProgressUpdate(responder, runState);
1244
+ }
1245
+ return;
1246
+ }
848
1247
  if (event.type === "tool_execution_end") {
849
1248
  const resultStr = extractToolResultText(event.result);
850
1249
  const pending = pendingTools.get(event.toolCallId);
@@ -856,7 +1255,15 @@ function attachSessionEventHandlers(params) {
856
1255
  const progress = runState.toolProgress.get(event.toolCallId);
857
1256
  if (progress)
858
1257
  progress.status = event.isError ? "error" : "done";
859
- queue.enqueue(() => replaceResponseWithToolProgress(responder, runState), "tool progress update");
1258
+ const subagentProgress = runState.subagentProgress.get(event.toolCallId);
1259
+ if (subagentProgress) {
1260
+ runState.subagentProgress.set(event.toolCallId, settleSubagentProgress(subagentProgress, event.isError));
1261
+ }
1262
+ flushToolProgressUpdate(responder, runState);
1263
+ const completedProgress = runState.subagentProgress.get(event.toolCallId);
1264
+ if (completedProgress)
1265
+ runState.completedSubagentProgress.push(completedProgress);
1266
+ runState.subagentProgress.delete(event.toolCallId);
860
1267
  pendingTools.delete(event.toolCallId);
861
1268
  const durationMs = pending ? Date.now() - pending.startTime : 0;
862
1269
  Sentry.metrics.count("agent.tool.calls", 1, {
@@ -884,6 +1291,9 @@ function attachSessionEventHandlers(params) {
884
1291
  }
885
1292
  else {
886
1293
  log.logToolSuccess(logCtx, event.toolName, durationMs, resultStr);
1294
+ if (event.toolName === "slack_blockkit") {
1295
+ runState.finalResponseHandledByTool = true;
1296
+ }
887
1297
  }
888
1298
  return;
889
1299
  }
@@ -913,7 +1323,7 @@ function attachSessionEventHandlers(params) {
913
1323
  actorName: formatAgentActorName(logCtx.userName, logCtx.conversationId),
914
1324
  event: { kind: "responseDelta", delta: assistantMessageEvent.delta },
915
1325
  });
916
- if (responder.appendResponseDelta) {
1326
+ if (responder.appendResponseDelta && !runState.suppressResponseDeltas) {
917
1327
  queue.enqueue(async () => {
918
1328
  await responder.appendResponseDelta?.(assistantMessageEvent.delta ?? "");
919
1329
  }, "response delta");
@@ -1010,6 +1420,12 @@ function attachSessionEventHandlers(params) {
1010
1420
  actorName: formatAgentActorName(logCtx.userName, logCtx.conversationId),
1011
1421
  event: { kind: "turnEnd" },
1012
1422
  });
1423
+ // A run that produced a subagent dashboard finalizes through it:
1424
+ // finalizeRunResponse renders "dashboard, blank line, answer", and a
1425
+ // finish here would first overwrite the dashboard with the bare
1426
+ // answer on every platform.
1427
+ if (runState.completedSubagentProgress.length > 0)
1428
+ return;
1013
1429
  if (responder.finishResponse) {
1014
1430
  queue.enqueue(async () => {
1015
1431
  await responder.finishResponse?.(finalText);
@@ -1069,27 +1485,6 @@ function attachSessionEventHandlers(params) {
1069
1485
  }
1070
1486
  });
1071
1487
  }
1072
- function extractToolResultText(result) {
1073
- if (typeof result === "string") {
1074
- return result;
1075
- }
1076
- if (result &&
1077
- typeof result === "object" &&
1078
- "content" in result &&
1079
- Array.isArray(result.content)) {
1080
- const content = result.content;
1081
- const textParts = [];
1082
- for (const part of content) {
1083
- if (part.type === "text" && part.text) {
1084
- textParts.push(part.text);
1085
- }
1086
- }
1087
- if (textParts.length > 0) {
1088
- return textParts.join("\n");
1089
- }
1090
- }
1091
- return JSON.stringify(result);
1092
- }
1093
1488
  /**
1094
1489
  * Create a new PiAgentWrapper for a channel.
1095
1490
  * Sets up the session and subscribes to events once.
@@ -1097,18 +1492,22 @@ function extractToolResultText(result) {
1097
1492
  * Runner caching is handled by the caller (channelStates in main.ts).
1098
1493
  * This is a stateless factory function.
1099
1494
  */
1100
- export async function createRunner(sandboxConfig, sessionKey, conversationId, conversationDir, workspaceDir, sessionScope, vaultManager, provisioner, sessionView, platformNotifier) {
1495
+ export async function createRunner(options) {
1496
+ const { sandboxConfig, sessionKey, conversationId, conversationDir, workspaceDir, sessionScope, vaultManager, provisioner, resourceController, sessionView, platformNotifier, platformReactor, platformUploader, platformBlockKit, platformToolPackFactories, } = options;
1101
1497
  const agentConfig = resolveConversationSettings(conversationDir);
1102
1498
  const workspaceBase = join(conversationDir, "..");
1103
1499
  const { executionResolver, executor, getPathContext, resolveExecutorForRun } = createRunnerExecutionContext(sandboxConfig, vaultManager, provisioner, workspaceDir, workspaceBase);
1104
1500
  let pathContext = getUnresolvedSandboxPathContext(sandboxConfig, workspaceBase);
1105
- // Create tools (per-runner, with per-runner upload function setter)
1106
- const { tools, setUploadFunction, setEventContext, setSandboxContext } = createMikanTools(executor, workspaceDir, { sandbox: sandboxConfig, provisioner });
1107
- const modelRegistry = MikanModels.create();
1501
+ const modelRegistry = options.models ?? MikanModels.create();
1108
1502
  if (modelRegistry.getError()) {
1109
1503
  log.logWarning("models.json load error", modelRegistry.getError());
1110
1504
  }
1111
- const model = resolveConfiguredModel(modelRegistry, agentConfig.provider, agentConfig.model);
1505
+ const model = modelRegistry.resolve(agentConfig.provider, agentConfig.model);
1506
+ // Create tools (per-runner, with per-runner upload function setter)
1507
+ const { tools, setUploadFunction, setReactFunction, bindPlatformToolPacks, setEventContext, setSandboxContext, } = createMikanTools(executor, workspaceDir, { sandbox: sandboxConfig, resourceController: resourceController ?? provisioner }, platformToolPackFactories ?? [], {
1508
+ model,
1509
+ getApiKey: () => modelRegistry.getApiKeyForProvider(model.provider),
1510
+ });
1112
1511
  // Initial system prompt (will be updated each run with fresh memory/channels/users/skills)
1113
1512
  const memory = await getMemory(conversationDir);
1114
1513
  const skills = loadMikanSkills(conversationDir, pathContext.runtimeWorkspaceRoot);
@@ -1117,12 +1516,13 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
1117
1516
  formattingGuide: "",
1118
1517
  channels: [],
1119
1518
  users: [],
1519
+ trustModel: "membership",
1120
1520
  };
1121
1521
  const systemPrompt = buildSystemPrompt(pathContext.runtimeWorkspaceRoot, conversationId, "shared", undefined, memory, sandboxConfig, emptyPlatform, skills);
1122
1522
  // Create session manager and settings manager. Top-level/private sessions
1123
1523
  // use the conversation's current pointer; scoped sessions use fixed files.
1124
1524
  // Platform-specific scope behavior is resolved before runner creation.
1125
- const isThread = sessionKey.includes(":");
1525
+ const isThread = isThreadSessionKey(sessionKey);
1126
1526
  const { contextFile, threadRootMessage } = sessionScope;
1127
1527
  const sessionManager = openManagedSession(contextFile, pathContext.runtimeWorkspaceRoot);
1128
1528
  const threadSessionName = buildThreadSessionName(threadRootMessage);
@@ -1130,8 +1530,8 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
1130
1530
  sessionManager.appendSessionInfo(threadSessionName);
1131
1531
  }
1132
1532
  const sessionUuid = extractSessionUuid(contextFile);
1133
- const chatSessionManager = new AgentMemoryFileManager();
1134
- const { session, extensionSkills } = await createConfiguredAgentSession({
1533
+ const chatSessionManager = new ChatHistorySync();
1534
+ const { session, extensionSkills, extensionRegistry, disposeExtensions } = await createConfiguredAgentSession({
1135
1535
  conversationId,
1136
1536
  workspaceDir,
1137
1537
  systemPrompt,
@@ -1142,6 +1542,9 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
1142
1542
  models: modelRegistry,
1143
1543
  vaultManager,
1144
1544
  platformNotifier,
1545
+ platformReactor,
1546
+ platformUploader,
1547
+ platformBlockKit,
1145
1548
  });
1146
1549
  // Mutable per-run state - event handler references this
1147
1550
  const runState = createRunState();
@@ -1173,6 +1576,8 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
1173
1576
  setEventContext,
1174
1577
  setSandboxContext,
1175
1578
  setUploadFunction,
1579
+ setReactFunction,
1580
+ bindPlatformToolPacks,
1176
1581
  pathContext,
1177
1582
  });
1178
1583
  pathContext = prepared.pathContext;
@@ -1201,10 +1606,39 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
1201
1606
  // Autonomous (event/trigger) runs get an explicit resource ceiling since
1202
1607
  // no human is watching the loop; interactive turns stay human-gated.
1203
1608
  const isEventRun = message.id.startsWith("event:");
1204
- await session.prompt(prepared.userMessage, {
1609
+ // Event runs have no triggering platform message, so identity fields
1610
+ // stay unset and extensions must null-check them.
1611
+ const origin = isEventRun
1612
+ ? { kind: "event", platform: platform.name }
1613
+ : {
1614
+ kind: "interactive",
1615
+ platform: platform.name,
1616
+ messageTs: message.id,
1617
+ userId: message.userId,
1618
+ userName: message.userName,
1619
+ threadTs: message.threadTs,
1620
+ attachments: message.attachments,
1621
+ };
1622
+ const outcome = await session.prompt(prepared.userMessage, {
1623
+ origin,
1205
1624
  ...(prepared.imageAttachments.length > 0 ? { images: prepared.imageAttachments } : {}),
1206
1625
  ...(isEventRun ? { budget: DEFAULT_EVENT_BUDGET } : {}),
1207
1626
  });
1627
+ if (outcome?.blocked) {
1628
+ const text = outcome.reason
1629
+ ? `_Turn blocked by an extension: ${outcome.reason}_`
1630
+ : "_Turn blocked by an extension._";
1631
+ sendAgentEvent({
1632
+ sessionId: sessionUuid,
1633
+ actorName: formatAgentActorName(message.userName, prepared.sessionConversation),
1634
+ event: { kind: "diagnostic", text },
1635
+ });
1636
+ await responder.respondDiagnostic(text, { style: "muted" });
1637
+ runState.responder = null;
1638
+ runState.logCtx = null;
1639
+ runState.queue = null;
1640
+ return { stopReason: "blocked" };
1641
+ }
1208
1642
  // Wait for queued messages
1209
1643
  await prepared.runQueue.wait();
1210
1644
  const sessionViewTokenStore = sessionView?.tokenStore;
@@ -1247,9 +1681,86 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
1247
1681
  runState.queue = null;
1248
1682
  return { stopReason: runState.stopReason, errorMessage: runState.errorMessage };
1249
1683
  },
1684
+ async dreamSessionMemory(message, platform) {
1685
+ const responder = createNoopResponder();
1686
+ const prepared = await prepareRunContext({
1687
+ message,
1688
+ responder,
1689
+ platform,
1690
+ conversationId,
1691
+ conversationDir,
1692
+ sessionUuid,
1693
+ runState,
1694
+ executor,
1695
+ executionResolver,
1696
+ resolveExecutorForRun,
1697
+ getPathContext,
1698
+ session,
1699
+ extensionSkills,
1700
+ setEventContext,
1701
+ setSandboxContext,
1702
+ setUploadFunction,
1703
+ setReactFunction,
1704
+ bindPlatformToolPacks,
1705
+ pathContext,
1706
+ });
1707
+ pathContext = prepared.pathContext;
1708
+ try {
1709
+ const conversationMemoryPath = posix.join(prepared.pathContext.runtimeWorkspaceRoot, conversationId, "MEMORY.md");
1710
+ const dreamTools = sessionDreamTools(session.agent.state.tools, conversationMemoryPath);
1711
+ const outcome = await session.prompt(sessionDreamPrompt(conversationMemoryPath, dreamTools.map((tool) => tool.name)), {
1712
+ origin: {
1713
+ kind: "interactive",
1714
+ platform: platform.name,
1715
+ messageTs: message.id,
1716
+ userId: message.userId,
1717
+ userName: message.userName,
1718
+ threadTs: message.threadTs,
1719
+ attachments: message.attachments,
1720
+ },
1721
+ budget: SESSION_DREAM_BUDGET,
1722
+ tools: dreamTools,
1723
+ });
1724
+ if (outcome?.blocked) {
1725
+ return { stopReason: "blocked", errorMessage: outcome.reason };
1726
+ }
1727
+ await prepared.runQueue.wait();
1728
+ // A budget abort carries its reason in the tally, not in errorMessage,
1729
+ // and that reason is the only thing that tells the user why memory was
1730
+ // not preserved.
1731
+ return {
1732
+ stopReason: runState.stopReason,
1733
+ errorMessage: runState.errorMessage ?? session.getLastRunStats().budgetExceededReason,
1734
+ };
1735
+ }
1736
+ finally {
1737
+ runState.responder = null;
1738
+ runState.logCtx = null;
1739
+ runState.queue = null;
1740
+ }
1741
+ },
1250
1742
  abort() {
1251
1743
  session.abort();
1252
1744
  },
1745
+ async tryExtensionCommand(message, responder) {
1746
+ const parsed = parseCommandInput(message.text);
1747
+ if (!parsed)
1748
+ return false;
1749
+ return extensionRegistry.dispatchCommand(parsed.name, {
1750
+ args: parsed.args,
1751
+ conversationId,
1752
+ userId: message.userId,
1753
+ userName: message.userName,
1754
+ threadTs: message.threadTs,
1755
+ respond: (text) => responder.respond(text),
1756
+ });
1757
+ },
1758
+ async tryExtensionAction(slug, action) {
1759
+ return extensionRegistry.dispatchAction(slug, action);
1760
+ },
1761
+ async dispose() {
1762
+ await disposeExtensions();
1763
+ },
1253
1764
  getCurrentStep() {
1254
1765
  const pending = runState.pendingTools;
1255
1766
  if (pending.size === 0)
@@ -1265,13 +1776,4 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
1265
1776
  },
1266
1777
  };
1267
1778
  }
1268
- export function translateRuntimePathToHost(runtimePath, pathContext) {
1269
- return pathContext.runtimeToHostPath?.(runtimePath) ?? runtimePath;
1270
- }
1271
- export function translateAttachPathToHost(filePath, pathContext) {
1272
- const runtimePath = posix.isAbsolute(filePath)
1273
- ? filePath
1274
- : posix.join(pathContext.runtimeWorkspaceRoot, filePath);
1275
- return translateRuntimePathToHost(runtimePath, pathContext);
1276
- }
1277
1779
  //# sourceMappingURL=agent.js.map