@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
@@ -0,0 +1,100 @@
1
+ /**
2
+ * The administrator's view of a conversation's packages: what each scope
3
+ * declares, whether it is actually on disk, and what it contributes.
4
+ *
5
+ * Resolution answers "what loads"; inspection answers "why is this not
6
+ * loading", which is the question someone staring at the portal has. A source
7
+ * that failed to fetch, or one shadowed by the conversation's own copy, is
8
+ * absent from the resolved set — reporting only the survivors would leave the
9
+ * admin with a silently short list and nothing to act on.
10
+ */
11
+ import { join } from "node:path";
12
+ import { listInstalledExtensions, loadSkillsFromDir, validateExtension } from "../harness/index.js";
13
+ import { loadGlobalSettings, resolveConversationSettings } from "../config.js";
14
+ import { parseSource, sourceIdentity } from "./source.js";
15
+ import { materializeSource } from "./materialize.js";
16
+ /**
17
+ * Inventory both scopes for one conversation. Never throws and never fetches:
18
+ * the portal renders this on page load, so it reports the current on-disk
19
+ * truth rather than going to the network behind the admin's back.
20
+ */
21
+ export async function inspectConversationPackages(options) {
22
+ const conversationIdentities = new Set(declaredSources("conversation", options).map(safeIdentity).filter(Boolean));
23
+ return {
24
+ global: await Promise.all(declaredSources("global", options).map((source) => describe(source, "global", options, conversationIdentities))),
25
+ conversation: await Promise.all(declaredSources("conversation", options).map((source) => describe(source, "conversation", options, new Set()))),
26
+ };
27
+ }
28
+ /** Sources one scope declares, or an empty list when its settings are unreadable. */
29
+ export function declaredSources(scope, options) {
30
+ try {
31
+ const settings = scope === "global"
32
+ ? loadGlobalSettings()
33
+ : resolveConversationSettings(options.conversationDir);
34
+ return settings.packages ?? [];
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ function safeIdentity(source) {
41
+ try {
42
+ return sourceIdentity(parseSource(source));
43
+ }
44
+ catch {
45
+ return "";
46
+ }
47
+ }
48
+ async function describe(source, scope, options, shadowedBy) {
49
+ const base = { source, scope, ready: false, extensions: [], skills: [] };
50
+ let identity;
51
+ try {
52
+ identity = sourceIdentity(parseSource(source));
53
+ }
54
+ catch (err) {
55
+ return { ...base, error: messageOf(err) };
56
+ }
57
+ let dir;
58
+ try {
59
+ dir = materializeSource(source, {
60
+ scope,
61
+ conversationId: options.conversationId,
62
+ stateDir: options.stateDir,
63
+ mode: "offline",
64
+ }).dir;
65
+ }
66
+ catch (err) {
67
+ return { ...base, error: messageOf(err) };
68
+ }
69
+ return {
70
+ ...base,
71
+ ready: true,
72
+ dir,
73
+ ...(shadowedBy.has(identity) ? { shadowed: true } : {}),
74
+ extensions: await contributedExtensions(dir),
75
+ skills: contributedSkills(dir),
76
+ };
77
+ }
78
+ /**
79
+ * Mirrors the loader's two accepted layouts (an `extensions/` collection, or a
80
+ * package that is itself one extension) so the portal reports exactly what
81
+ * would activate — including the slug, which is the name the extension's data
82
+ * dir, secrets, and schedules are keyed by.
83
+ */
84
+ async function contributedExtensions(dir) {
85
+ const collection = listInstalledExtensions([join(dir, "extensions")]);
86
+ if (collection.length > 0)
87
+ return collection.map((info) => info.slug);
88
+ // Single-extension layout: validate the root itself rather than scanning its
89
+ // parent, which would report unrelated siblings.
90
+ const validated = await validateExtension(dir);
91
+ return validated.ok ? [validated.slug] : [];
92
+ }
93
+ function contributedSkills(dir) {
94
+ const skillsDir = join(dir, "skills");
95
+ return loadSkillsFromDir({ dir: skillsDir, source: "package" }).skills.map((skill) => skill.name);
96
+ }
97
+ function messageOf(err) {
98
+ return err instanceof Error ? err.message : String(err);
99
+ }
100
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/packages/inspect.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The administrator's view of a conversation's packages: what each scope\n * declares, whether it is actually on disk, and what it contributes.\n *\n * Resolution answers \"what loads\"; inspection answers \"why is this not\n * loading\", which is the question someone staring at the portal has. A source\n * that failed to fetch, or one shadowed by the conversation's own copy, is\n * absent from the resolved set — reporting only the survivors would leave the\n * admin with a silently short list and nothing to act on.\n */\nimport { join } from \"node:path\";\nimport { listInstalledExtensions, loadSkillsFromDir, validateExtension } from \"../harness/index.js\";\nimport { loadGlobalSettings, resolveConversationSettings } from \"../config.js\";\nimport { parseSource, sourceIdentity } from \"./source.js\";\nimport { materializeSource } from \"./materialize.js\";\nimport type {\n PackageInventory,\n PackageScope,\n PackageStatus,\n ResolvePackagesOptions,\n} from \"./types.js\";\n\nexport type { PackageInventory } from \"./types.js\";\n\n/**\n * Inventory both scopes for one conversation. Never throws and never fetches:\n * the portal renders this on page load, so it reports the current on-disk\n * truth rather than going to the network behind the admin's back.\n */\nexport async function inspectConversationPackages(\n options: ResolvePackagesOptions,\n): Promise<PackageInventory> {\n const conversationIdentities = new Set(\n declaredSources(\"conversation\", options).map(safeIdentity).filter(Boolean),\n );\n\n return {\n global: await Promise.all(\n declaredSources(\"global\", options).map((source) =>\n describe(source, \"global\", options, conversationIdentities),\n ),\n ),\n conversation: await Promise.all(\n declaredSources(\"conversation\", options).map((source) =>\n describe(source, \"conversation\", options, new Set()),\n ),\n ),\n };\n}\n\n/** Sources one scope declares, or an empty list when its settings are unreadable. */\nexport function declaredSources(scope: PackageScope, options: ResolvePackagesOptions): string[] {\n try {\n const settings =\n scope === \"global\"\n ? loadGlobalSettings()\n : resolveConversationSettings(options.conversationDir);\n return settings.packages ?? [];\n } catch {\n return [];\n }\n}\n\nfunction safeIdentity(source: string): string {\n try {\n return sourceIdentity(parseSource(source));\n } catch {\n return \"\";\n }\n}\n\nasync function describe(\n source: string,\n scope: PackageScope,\n options: ResolvePackagesOptions,\n shadowedBy: Set<string>,\n): Promise<PackageStatus> {\n const base: PackageStatus = { source, scope, ready: false, extensions: [], skills: [] };\n\n let identity: string;\n try {\n identity = sourceIdentity(parseSource(source));\n } catch (err) {\n return { ...base, error: messageOf(err) };\n }\n\n let dir: string;\n try {\n dir = materializeSource(source, {\n scope,\n conversationId: options.conversationId,\n stateDir: options.stateDir,\n mode: \"offline\",\n }).dir;\n } catch (err) {\n return { ...base, error: messageOf(err) };\n }\n\n return {\n ...base,\n ready: true,\n dir,\n ...(shadowedBy.has(identity) ? { shadowed: true } : {}),\n extensions: await contributedExtensions(dir),\n skills: contributedSkills(dir),\n };\n}\n\n/**\n * Mirrors the loader's two accepted layouts (an `extensions/` collection, or a\n * package that is itself one extension) so the portal reports exactly what\n * would activate — including the slug, which is the name the extension's data\n * dir, secrets, and schedules are keyed by.\n */\nasync function contributedExtensions(dir: string): Promise<string[]> {\n const collection = listInstalledExtensions([join(dir, \"extensions\")]);\n if (collection.length > 0) return collection.map((info) => info.slug);\n // Single-extension layout: validate the root itself rather than scanning its\n // parent, which would report unrelated siblings.\n const validated = await validateExtension(dir);\n return validated.ok ? [validated.slug] : [];\n}\n\nfunction contributedSkills(dir: string): string[] {\n const skillsDir = join(dir, \"skills\");\n return loadSkillsFromDir({ dir: skillsDir, source: \"package\" }).skills.map((skill) => skill.name);\n}\n\nfunction messageOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n"]}
@@ -0,0 +1,39 @@
1
+ import type { MaterializeOptions, MaterializedPackage, PackageScope, PackageSourceString } from "./types.js";
2
+ export type { MaterializeOptions } from "./types.js";
3
+ /**
4
+ * How far materialization may go to produce the package's files.
5
+ *
6
+ * - `offline`: use what is already on disk; never touch the network. This is
7
+ * what a conversation load uses, so no chat reply can ever wait on a remote.
8
+ * - `fetch`: clone a package that is not on disk yet, reuse an existing clone
9
+ * when it already has the requested ref, or switch it to a new ref. What the
10
+ * portal uses when a source is added.
11
+ * - `refresh`: additionally re-fetch an existing clone, resetting and cleaning
12
+ * it first. What the portal's Update action uses.
13
+ *
14
+ * One mode rather than two booleans: "re-fetch an existing clone but refuse to
15
+ * create a missing one" is not a state any caller wants, and expressing it
16
+ * should not be possible.
17
+ */
18
+ /**
19
+ * Root of a scope's host-only assets: `<stateDir>/global` or
20
+ * `<stateDir>/conversations/<id>`. The two are isomorphic by design — both
21
+ * hold `extensions/`, `extension-data/`, and now `git/`. See
22
+ * `src/harness/extensions/LAYOUT.md`.
23
+ */
24
+ export declare function packageScopeDir(scope: PackageScope, conversationId: string | undefined, stateDir: string): string;
25
+ /**
26
+ * Where a git checkout lives.
27
+ *
28
+ * The unpinned checkout keeps the original path for compatibility. Explicit
29
+ * refs get a sibling keyed by the ref, so two refs can never reset each
30
+ * other's working tree; subpaths of one ref therefore still share a checkout.
31
+ */
32
+ export declare function gitCloneDir(url: string, scopeDir: string, ref?: string): string;
33
+ /**
34
+ * Materialize one source and return where its files ended up. Throws with a
35
+ * message meant to be shown to a human — callers render it next to the input
36
+ * that produced it.
37
+ */
38
+ export declare function materializeSource(source: PackageSourceString, options: MaterializeOptions): MaterializedPackage;
39
+ //# sourceMappingURL=materialize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize.d.ts","sourceRoot":"","sources":["../../src/packages/materialize.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAEV,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EAEpB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAOrD;;;;;;;;;;;;;;GAcG;AACH;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,YAAY,EACnB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,QAAQ,EAAE,MAAM,GACf,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAS/E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,kBAAkB,GAC1B,mBAAmB,CAerB"}
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Turning a parsed source into a directory on the host.
3
+ *
4
+ * Materialization is an explicit, reported step — it happens when a human adds
5
+ * or updates a package, not lazily while a conversation is waiting for a
6
+ * reply. Failures (bad URL, missing ref, no such subpath) therefore surface in
7
+ * front of the person who typed the source instead of as a silently absent
8
+ * feature in a chat.
9
+ *
10
+ * Everything lands under the host-only state dir, never the workspace: this
11
+ * code is imported into the mikan process, so a mounted location would let
12
+ * sandboxed code write what the host executes.
13
+ */
14
+ import { execFileSync } from "node:child_process";
15
+ import { createHash } from "node:crypto";
16
+ import { cpSync, existsSync, rmSync, statSync, writeFileSync } from "node:fs";
17
+ import { dirname, join } from "node:path";
18
+ import { ensureDirExists, readTextFileIfExists } from "../utils/file-guards.js";
19
+ import * as log from "../log.js";
20
+ import { gitRepoPath, parseSource, sourceIdentity } from "./source.js";
21
+ /** Git operations get a bounded wall clock so a hung remote cannot wedge a save. */
22
+ const GIT_TIMEOUT_MS = 120_000;
23
+ const NPM_TIMEOUT_MS = 300_000;
24
+ const MATERIALIZED_REF_FILE = "mikan-ref";
25
+ /**
26
+ * How far materialization may go to produce the package's files.
27
+ *
28
+ * - `offline`: use what is already on disk; never touch the network. This is
29
+ * what a conversation load uses, so no chat reply can ever wait on a remote.
30
+ * - `fetch`: clone a package that is not on disk yet, reuse an existing clone
31
+ * when it already has the requested ref, or switch it to a new ref. What the
32
+ * portal uses when a source is added.
33
+ * - `refresh`: additionally re-fetch an existing clone, resetting and cleaning
34
+ * it first. What the portal's Update action uses.
35
+ *
36
+ * One mode rather than two booleans: "re-fetch an existing clone but refuse to
37
+ * create a missing one" is not a state any caller wants, and expressing it
38
+ * should not be possible.
39
+ */
40
+ /**
41
+ * Root of a scope's host-only assets: `<stateDir>/global` or
42
+ * `<stateDir>/conversations/<id>`. The two are isomorphic by design — both
43
+ * hold `extensions/`, `extension-data/`, and now `git/`. See
44
+ * `src/harness/extensions/LAYOUT.md`.
45
+ */
46
+ export function packageScopeDir(scope, conversationId, stateDir) {
47
+ if (scope === "global")
48
+ return join(stateDir, "global");
49
+ if (!conversationId)
50
+ throw new Error("A conversation-scoped package needs a conversation id");
51
+ assertSafePathSegment(conversationId);
52
+ return join(stateDir, "conversations", conversationId);
53
+ }
54
+ /**
55
+ * Where a git checkout lives.
56
+ *
57
+ * The unpinned checkout keeps the original path for compatibility. Explicit
58
+ * refs get a sibling keyed by the ref, so two refs can never reset each
59
+ * other's working tree; subpaths of one ref therefore still share a checkout.
60
+ */
61
+ export function gitCloneDir(url, scopeDir, ref) {
62
+ const repoPath = gitRepoPath(url).split("/");
63
+ const repoName = repoPath[repoPath.length - 1];
64
+ const parent = repoPath.slice(0, -1);
65
+ const checkoutName = ref === undefined || ref === "HEAD"
66
+ ? repoName
67
+ : `${repoName}.mikan-${createHash("sha256").update(ref).digest("hex")}`;
68
+ return join(scopeDir, "git", ...parent, checkoutName);
69
+ }
70
+ /**
71
+ * Materialize one source and return where its files ended up. Throws with a
72
+ * message meant to be shown to a human — callers render it next to the input
73
+ * that produced it.
74
+ */
75
+ export function materializeSource(source, options) {
76
+ const parsed = parseSource(source);
77
+ const scopeDir = packageScopeDir(options.scope, options.conversationId, options.stateDir);
78
+ const dir = parsed.type === "local"
79
+ ? materializeLocal(parsed)
80
+ : materializeGit(parsed, scopeDir, options.mode ?? "fetch");
81
+ return {
82
+ source,
83
+ parsed,
84
+ identity: sourceIdentity(parsed),
85
+ dir,
86
+ scope: options.scope,
87
+ };
88
+ }
89
+ function materializeLocal(parsed) {
90
+ if (!existsSync(parsed.path)) {
91
+ throw new Error(`Path does not exist on the mikan host: ${parsed.path}`);
92
+ }
93
+ if (!statSync(parsed.path).isDirectory()) {
94
+ throw new Error(`Package path must be a directory: ${parsed.path}`);
95
+ }
96
+ return parsed.path;
97
+ }
98
+ function materializeGit(parsed, scopeDir, mode) {
99
+ const requestedRef = parsed.ref ?? "HEAD";
100
+ const cloneDir = gitCloneDir(parsed.url, scopeDir, requestedRef);
101
+ migrateLegacyCheckout(parsed.url, scopeDir, cloneDir, requestedRef);
102
+ const alreadyCloned = existsSync(join(cloneDir, ".git"));
103
+ const markerPath = join(cloneDir, ".git", MATERIALIZED_REF_FILE);
104
+ const recordedRef = alreadyCloned ? readTextFileIfExists(markerPath)?.trim() : undefined;
105
+ const canReuse = alreadyCloned &&
106
+ mode !== "refresh" &&
107
+ (recordedRef === requestedRef ||
108
+ (mode === "offline" &&
109
+ recordedRef === undefined &&
110
+ markerlessCheckoutMatchesRef(cloneDir, requestedRef)));
111
+ if (canReuse) {
112
+ return resolveSubpath(cloneDir, parsed);
113
+ }
114
+ if (mode === "offline") {
115
+ throw new Error(`Not fetched on this host yet: ${describeRef(parsed)}`);
116
+ }
117
+ // An incomplete checkout must not retain a marker from an earlier attempt:
118
+ // otherwise a retry could mistake a failed dependency install for success.
119
+ if (alreadyCloned)
120
+ rmSync(markerPath, { force: true });
121
+ if (!alreadyCloned) {
122
+ // A leftover directory without .git means a previous attempt died partway.
123
+ if (existsSync(cloneDir))
124
+ rmSync(cloneDir, { recursive: true, force: true });
125
+ ensureDirExists(cloneDir);
126
+ git(cloneDir, ["init", "-q"]);
127
+ git(cloneDir, ["remote", "add", "origin", parsed.url]);
128
+ }
129
+ else {
130
+ // Reconcile: drop anything a previous checkout left behind so the new ref
131
+ // lands on a clean tree.
132
+ git(cloneDir, ["remote", "set-url", "origin", parsed.url]);
133
+ git(cloneDir, ["reset", "--hard", "-q"]);
134
+ git(cloneDir, ["clean", "-qfd"]);
135
+ }
136
+ // One fetch shape for every kind of ref — tag, branch, or commit sha — and
137
+ // `HEAD` for "whatever the remote's default branch is now".
138
+ try {
139
+ git(cloneDir, ["fetch", "--depth", "1", "origin", requestedRef]);
140
+ }
141
+ catch (err) {
142
+ if (!alreadyCloned)
143
+ rmSync(cloneDir, { recursive: true, force: true });
144
+ throw new Error(`Could not fetch ${describeRef(parsed)}: ${gitErrorText(err)}`, { cause: err });
145
+ }
146
+ git(cloneDir, ["checkout", "-q", "--detach", "FETCH_HEAD"]);
147
+ const dir = resolveSubpath(cloneDir, parsed);
148
+ installDependencies(dir);
149
+ // This is the completion marker, not merely a fetched-ref marker. Write it
150
+ // last so a failed npm install is retried by the next materialization.
151
+ writeFileSync(markerPath, `${requestedRef}\n`);
152
+ return dir;
153
+ }
154
+ /**
155
+ * Before keyed checkout paths existed, every ref used the legacy repo path.
156
+ * Copy a matching complete checkout on first use of its keyed path so offline
157
+ * loads keep working. Markerless legacy checkouts are accepted only when git
158
+ * can prove the requested ref is the checked-out commit; a different or
159
+ * unprovable pinned ref is rebuilt by fetch/refresh instead.
160
+ */
161
+ function migrateLegacyCheckout(url, scopeDir, cloneDir, requestedRef) {
162
+ const legacyDir = gitCloneDir(url, scopeDir);
163
+ if (cloneDir === legacyDir || existsSync(cloneDir))
164
+ return;
165
+ const legacyMarker = join(legacyDir, ".git", MATERIALIZED_REF_FILE);
166
+ if (!existsSync(join(legacyDir, ".git")))
167
+ return;
168
+ const recordedRef = readTextFileIfExists(legacyMarker)?.trim();
169
+ if (recordedRef !== requestedRef) {
170
+ if (recordedRef !== undefined || !markerlessCheckoutMatchesRef(legacyDir, requestedRef)) {
171
+ return;
172
+ }
173
+ }
174
+ ensureDirExists(dirname(cloneDir));
175
+ cpSync(legacyDir, cloneDir, { recursive: true });
176
+ }
177
+ /**
178
+ * Legacy checkouts have no completion marker. Accept them offline only when
179
+ * the checkout is clean and the local git metadata identifies the requested
180
+ * commit/ref; never infer a pinned ref from HEAD alone.
181
+ */
182
+ function markerlessCheckoutMatchesRef(cloneDir, requestedRef) {
183
+ let head;
184
+ try {
185
+ head = git(cloneDir, ["rev-parse", "--verify", "HEAD"]).trim();
186
+ if (!head || git(cloneDir, ["status", "--porcelain", "--untracked-files=no"]).trim()) {
187
+ return false;
188
+ }
189
+ }
190
+ catch {
191
+ return false;
192
+ }
193
+ if (requestedRef === "HEAD")
194
+ return true;
195
+ try {
196
+ if (git(cloneDir, ["rev-parse", "--verify", `${requestedRef}^{commit}`]).trim() === head) {
197
+ return true;
198
+ }
199
+ }
200
+ catch {
201
+ // A shallow legacy fetch may retain only FETCH_HEAD, not a local ref.
202
+ }
203
+ try {
204
+ if (git(cloneDir, ["symbolic-ref", "--quiet", "--short", "HEAD"]).trim() === requestedRef) {
205
+ return true;
206
+ }
207
+ }
208
+ catch {
209
+ // Detached checkouts do not have a symbolic branch.
210
+ }
211
+ const fetchHead = readTextFileIfExists(join(cloneDir, ".git", "FETCH_HEAD"));
212
+ if (!fetchHead)
213
+ return false;
214
+ return fetchHead.split("\n").some((line) => {
215
+ const match = /^(\w+)\s+.*(?:branch|tag) '([^']+)'/.exec(line);
216
+ return match?.[1] === head && match[2] === requestedRef;
217
+ });
218
+ }
219
+ function resolveSubpath(cloneDir, parsed) {
220
+ if (!parsed.subpath)
221
+ return cloneDir;
222
+ const dir = join(cloneDir, parsed.subpath);
223
+ if (!existsSync(dir)) {
224
+ throw new Error(`Subpath not found in repository: ${parsed.subpath}`);
225
+ }
226
+ return dir;
227
+ }
228
+ /**
229
+ * Install runtime dependencies when the package declares any. This runs npm
230
+ * on the host against code that was just fetched from a remote, which is the
231
+ * same trust level as importing the package itself — but it is worth being
232
+ * explicit that it happens, because it also runs the dependencies' install
233
+ * scripts.
234
+ */
235
+ function installDependencies(dir) {
236
+ if (!hasDependencies(dir))
237
+ return;
238
+ log.logInfo(`Installing package dependencies in ${dir}`);
239
+ try {
240
+ execFileSync("npm", ["install", "--omit=dev", "--no-audit", "--no-fund"], {
241
+ cwd: dir,
242
+ timeout: NPM_TIMEOUT_MS,
243
+ encoding: "utf-8",
244
+ stdio: ["ignore", "pipe", "pipe"],
245
+ });
246
+ }
247
+ catch (err) {
248
+ throw new Error(`npm install failed for the package: ${gitErrorText(err)}`, { cause: err });
249
+ }
250
+ }
251
+ function hasDependencies(dir) {
252
+ const raw = readTextFileIfExists(join(dir, "package.json"));
253
+ if (raw === undefined)
254
+ return false;
255
+ try {
256
+ const pkg = JSON.parse(raw);
257
+ return Boolean(pkg.dependencies && Object.keys(pkg.dependencies).length > 0);
258
+ }
259
+ catch {
260
+ return false;
261
+ }
262
+ }
263
+ function git(cwd, args) {
264
+ return execFileSync("git", args, {
265
+ cwd,
266
+ timeout: GIT_TIMEOUT_MS,
267
+ encoding: "utf-8",
268
+ stdio: ["ignore", "pipe", "pipe"],
269
+ env: {
270
+ ...process.env,
271
+ // Never block a portal save on an interactive credential prompt.
272
+ GIT_TERMINAL_PROMPT: "0",
273
+ GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND ?? "ssh -o BatchMode=yes -o ConnectTimeout=10",
274
+ },
275
+ });
276
+ }
277
+ function describeRef(parsed) {
278
+ return parsed.ref ? `${parsed.url} at ${parsed.ref}` : parsed.url;
279
+ }
280
+ /** Prefer git's stderr over the generic "Command failed" wrapper. */
281
+ function gitErrorText(err) {
282
+ if (err && typeof err === "object" && "stderr" in err) {
283
+ const stderr = err.stderr;
284
+ const text = typeof stderr === "string" ? stderr.trim() : "";
285
+ if (text)
286
+ return text.split("\n").slice(-3).join(" ");
287
+ }
288
+ return err instanceof Error ? err.message : String(err);
289
+ }
290
+ function assertSafePathSegment(value) {
291
+ if (value.length === 0 ||
292
+ value === "." ||
293
+ value === ".." ||
294
+ value.includes("/") ||
295
+ value.includes("\\") ||
296
+ value.includes("\0")) {
297
+ throw new Error("Conversation id must be a safe path segment");
298
+ }
299
+ }
300
+ //# sourceMappingURL=materialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize.js","sourceRoot":"","sources":["../../src/packages/materialize.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Turning a parsed source into a directory on the host.\n *\n * Materialization is an explicit, reported step — it happens when a human adds\n * or updates a package, not lazily while a conversation is waiting for a\n * reply. Failures (bad URL, missing ref, no such subpath) therefore surface in\n * front of the person who typed the source instead of as a silently absent\n * feature in a chat.\n *\n * Everything lands under the host-only state dir, never the workspace: this\n * code is imported into the mikan process, so a mounted location would let\n * sandboxed code write what the host executes.\n */\nimport { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { cpSync, existsSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { ensureDirExists, readTextFileIfExists } from \"../utils/file-guards.js\";\nimport * as log from \"../log.js\";\nimport { gitRepoPath, parseSource, sourceIdentity } from \"./source.js\";\nimport type {\n MaterializeMode,\n MaterializeOptions,\n MaterializedPackage,\n PackageScope,\n PackageSourceString,\n ParsedSource,\n} from \"./types.js\";\n\nexport type { MaterializeOptions } from \"./types.js\";\n\n/** Git operations get a bounded wall clock so a hung remote cannot wedge a save. */\nconst GIT_TIMEOUT_MS = 120_000;\nconst NPM_TIMEOUT_MS = 300_000;\nconst MATERIALIZED_REF_FILE = \"mikan-ref\";\n\n/**\n * How far materialization may go to produce the package's files.\n *\n * - `offline`: use what is already on disk; never touch the network. This is\n * what a conversation load uses, so no chat reply can ever wait on a remote.\n * - `fetch`: clone a package that is not on disk yet, reuse an existing clone\n * when it already has the requested ref, or switch it to a new ref. What the\n * portal uses when a source is added.\n * - `refresh`: additionally re-fetch an existing clone, resetting and cleaning\n * it first. What the portal's Update action uses.\n *\n * One mode rather than two booleans: \"re-fetch an existing clone but refuse to\n * create a missing one\" is not a state any caller wants, and expressing it\n * should not be possible.\n */\n/**\n * Root of a scope's host-only assets: `<stateDir>/global` or\n * `<stateDir>/conversations/<id>`. The two are isomorphic by design — both\n * hold `extensions/`, `extension-data/`, and now `git/`. See\n * `src/harness/extensions/LAYOUT.md`.\n */\nexport function packageScopeDir(\n scope: PackageScope,\n conversationId: string | undefined,\n stateDir: string,\n): string {\n if (scope === \"global\") return join(stateDir, \"global\");\n if (!conversationId) throw new Error(\"A conversation-scoped package needs a conversation id\");\n assertSafePathSegment(conversationId);\n return join(stateDir, \"conversations\", conversationId);\n}\n\n/**\n * Where a git checkout lives.\n *\n * The unpinned checkout keeps the original path for compatibility. Explicit\n * refs get a sibling keyed by the ref, so two refs can never reset each\n * other's working tree; subpaths of one ref therefore still share a checkout.\n */\nexport function gitCloneDir(url: string, scopeDir: string, ref?: string): string {\n const repoPath = gitRepoPath(url).split(\"/\");\n const repoName = repoPath[repoPath.length - 1];\n const parent = repoPath.slice(0, -1);\n const checkoutName =\n ref === undefined || ref === \"HEAD\"\n ? repoName\n : `${repoName}.mikan-${createHash(\"sha256\").update(ref).digest(\"hex\")}`;\n return join(scopeDir, \"git\", ...parent, checkoutName);\n}\n\n/**\n * Materialize one source and return where its files ended up. Throws with a\n * message meant to be shown to a human — callers render it next to the input\n * that produced it.\n */\nexport function materializeSource(\n source: PackageSourceString,\n options: MaterializeOptions,\n): MaterializedPackage {\n const parsed = parseSource(source);\n const scopeDir = packageScopeDir(options.scope, options.conversationId, options.stateDir);\n const dir =\n parsed.type === \"local\"\n ? materializeLocal(parsed)\n : materializeGit(parsed, scopeDir, options.mode ?? \"fetch\");\n\n return {\n source,\n parsed,\n identity: sourceIdentity(parsed),\n dir,\n scope: options.scope,\n };\n}\n\nfunction materializeLocal(parsed: Extract<ParsedSource, { type: \"local\" }>): string {\n if (!existsSync(parsed.path)) {\n throw new Error(`Path does not exist on the mikan host: ${parsed.path}`);\n }\n if (!statSync(parsed.path).isDirectory()) {\n throw new Error(`Package path must be a directory: ${parsed.path}`);\n }\n return parsed.path;\n}\n\nfunction materializeGit(\n parsed: Extract<ParsedSource, { type: \"git\" }>,\n scopeDir: string,\n mode: MaterializeMode,\n): string {\n const requestedRef = parsed.ref ?? \"HEAD\";\n const cloneDir = gitCloneDir(parsed.url, scopeDir, requestedRef);\n migrateLegacyCheckout(parsed.url, scopeDir, cloneDir, requestedRef);\n const alreadyCloned = existsSync(join(cloneDir, \".git\"));\n const markerPath = join(cloneDir, \".git\", MATERIALIZED_REF_FILE);\n const recordedRef = alreadyCloned ? readTextFileIfExists(markerPath)?.trim() : undefined;\n const canReuse =\n alreadyCloned &&\n mode !== \"refresh\" &&\n (recordedRef === requestedRef ||\n (mode === \"offline\" &&\n recordedRef === undefined &&\n markerlessCheckoutMatchesRef(cloneDir, requestedRef)));\n\n if (canReuse) {\n return resolveSubpath(cloneDir, parsed);\n }\n if (mode === \"offline\") {\n throw new Error(`Not fetched on this host yet: ${describeRef(parsed)}`);\n }\n\n // An incomplete checkout must not retain a marker from an earlier attempt:\n // otherwise a retry could mistake a failed dependency install for success.\n if (alreadyCloned) rmSync(markerPath, { force: true });\n\n if (!alreadyCloned) {\n // A leftover directory without .git means a previous attempt died partway.\n if (existsSync(cloneDir)) rmSync(cloneDir, { recursive: true, force: true });\n ensureDirExists(cloneDir);\n git(cloneDir, [\"init\", \"-q\"]);\n git(cloneDir, [\"remote\", \"add\", \"origin\", parsed.url]);\n } else {\n // Reconcile: drop anything a previous checkout left behind so the new ref\n // lands on a clean tree.\n git(cloneDir, [\"remote\", \"set-url\", \"origin\", parsed.url]);\n git(cloneDir, [\"reset\", \"--hard\", \"-q\"]);\n git(cloneDir, [\"clean\", \"-qfd\"]);\n }\n\n // One fetch shape for every kind of ref — tag, branch, or commit sha — and\n // `HEAD` for \"whatever the remote's default branch is now\".\n try {\n git(cloneDir, [\"fetch\", \"--depth\", \"1\", \"origin\", requestedRef]);\n } catch (err) {\n if (!alreadyCloned) rmSync(cloneDir, { recursive: true, force: true });\n throw new Error(`Could not fetch ${describeRef(parsed)}: ${gitErrorText(err)}`, { cause: err });\n }\n git(cloneDir, [\"checkout\", \"-q\", \"--detach\", \"FETCH_HEAD\"]);\n\n const dir = resolveSubpath(cloneDir, parsed);\n installDependencies(dir);\n // This is the completion marker, not merely a fetched-ref marker. Write it\n // last so a failed npm install is retried by the next materialization.\n writeFileSync(markerPath, `${requestedRef}\\n`);\n return dir;\n}\n\n/**\n * Before keyed checkout paths existed, every ref used the legacy repo path.\n * Copy a matching complete checkout on first use of its keyed path so offline\n * loads keep working. Markerless legacy checkouts are accepted only when git\n * can prove the requested ref is the checked-out commit; a different or\n * unprovable pinned ref is rebuilt by fetch/refresh instead.\n */\nfunction migrateLegacyCheckout(\n url: string,\n scopeDir: string,\n cloneDir: string,\n requestedRef: string,\n): void {\n const legacyDir = gitCloneDir(url, scopeDir);\n if (cloneDir === legacyDir || existsSync(cloneDir)) return;\n const legacyMarker = join(legacyDir, \".git\", MATERIALIZED_REF_FILE);\n if (!existsSync(join(legacyDir, \".git\"))) return;\n const recordedRef = readTextFileIfExists(legacyMarker)?.trim();\n if (recordedRef !== requestedRef) {\n if (recordedRef !== undefined || !markerlessCheckoutMatchesRef(legacyDir, requestedRef)) {\n return;\n }\n }\n\n ensureDirExists(dirname(cloneDir));\n cpSync(legacyDir, cloneDir, { recursive: true });\n}\n\n/**\n * Legacy checkouts have no completion marker. Accept them offline only when\n * the checkout is clean and the local git metadata identifies the requested\n * commit/ref; never infer a pinned ref from HEAD alone.\n */\nfunction markerlessCheckoutMatchesRef(cloneDir: string, requestedRef: string): boolean {\n let head: string;\n try {\n head = git(cloneDir, [\"rev-parse\", \"--verify\", \"HEAD\"]).trim();\n if (!head || git(cloneDir, [\"status\", \"--porcelain\", \"--untracked-files=no\"]).trim()) {\n return false;\n }\n } catch {\n return false;\n }\n\n if (requestedRef === \"HEAD\") return true;\n\n try {\n if (git(cloneDir, [\"rev-parse\", \"--verify\", `${requestedRef}^{commit}`]).trim() === head) {\n return true;\n }\n } catch {\n // A shallow legacy fetch may retain only FETCH_HEAD, not a local ref.\n }\n\n try {\n if (git(cloneDir, [\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"]).trim() === requestedRef) {\n return true;\n }\n } catch {\n // Detached checkouts do not have a symbolic branch.\n }\n\n const fetchHead = readTextFileIfExists(join(cloneDir, \".git\", \"FETCH_HEAD\"));\n if (!fetchHead) return false;\n return fetchHead.split(\"\\n\").some((line) => {\n const match = /^(\\w+)\\s+.*(?:branch|tag) '([^']+)'/.exec(line);\n return match?.[1] === head && match[2] === requestedRef;\n });\n}\n\nfunction resolveSubpath(cloneDir: string, parsed: Extract<ParsedSource, { type: \"git\" }>): string {\n if (!parsed.subpath) return cloneDir;\n const dir = join(cloneDir, parsed.subpath);\n if (!existsSync(dir)) {\n throw new Error(`Subpath not found in repository: ${parsed.subpath}`);\n }\n return dir;\n}\n\n/**\n * Install runtime dependencies when the package declares any. This runs npm\n * on the host against code that was just fetched from a remote, which is the\n * same trust level as importing the package itself — but it is worth being\n * explicit that it happens, because it also runs the dependencies' install\n * scripts.\n */\nfunction installDependencies(dir: string): void {\n if (!hasDependencies(dir)) return;\n log.logInfo(`Installing package dependencies in ${dir}`);\n try {\n execFileSync(\"npm\", [\"install\", \"--omit=dev\", \"--no-audit\", \"--no-fund\"], {\n cwd: dir,\n timeout: NPM_TIMEOUT_MS,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (err) {\n throw new Error(`npm install failed for the package: ${gitErrorText(err)}`, { cause: err });\n }\n}\n\nfunction hasDependencies(dir: string): boolean {\n const raw = readTextFileIfExists(join(dir, \"package.json\"));\n if (raw === undefined) return false;\n try {\n const pkg = JSON.parse(raw) as { dependencies?: Record<string, string> };\n return Boolean(pkg.dependencies && Object.keys(pkg.dependencies).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction git(cwd: string, args: string[]): string {\n return execFileSync(\"git\", args, {\n cwd,\n timeout: GIT_TIMEOUT_MS,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: {\n ...process.env,\n // Never block a portal save on an interactive credential prompt.\n GIT_TERMINAL_PROMPT: \"0\",\n GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND ?? \"ssh -o BatchMode=yes -o ConnectTimeout=10\",\n },\n });\n}\n\nfunction describeRef(parsed: Extract<ParsedSource, { type: \"git\" }>): string {\n return parsed.ref ? `${parsed.url} at ${parsed.ref}` : parsed.url;\n}\n\n/** Prefer git's stderr over the generic \"Command failed\" wrapper. */\nfunction gitErrorText(err: unknown): string {\n if (err && typeof err === \"object\" && \"stderr\" in err) {\n const stderr = (err as { stderr?: unknown }).stderr;\n const text = typeof stderr === \"string\" ? stderr.trim() : \"\";\n if (text) return text.split(\"\\n\").slice(-3).join(\" \");\n }\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction assertSafePathSegment(value: string): void {\n if (\n value.length === 0 ||\n value === \".\" ||\n value === \"..\" ||\n value.includes(\"/\") ||\n value.includes(\"\\\\\") ||\n value.includes(\"\\0\")\n ) {\n throw new Error(\"Conversation id must be a safe path segment\");\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import type { ResolvePackagesOptions, ResolvedPackages } from "./types.js";
2
+ export type { ResolvePackagesOptions, ResolvedPackages } from "./types.js";
3
+ /** Runtime path a package's skills directory is mounted at. */
4
+ export declare function packageSkillRuntimeDir(slug: string): string;
5
+ /**
6
+ * Read-only mounts exposing every resolved package's skills to the sandbox.
7
+ *
8
+ * Read-only rather than read-write because the host owns these files: the
9
+ * directory is a git checkout that an update replaces wholesale, so an agent
10
+ * edit would be silently discarded on the next refresh. Making the filesystem
11
+ * refuse the write turns a confusing data-loss bug into an obvious error.
12
+ *
13
+ * Resolution is offline, so building the mount list never reaches the network.
14
+ */
15
+ export declare function conversationPackageSkillMounts(options: ResolvePackagesOptions): Array<{
16
+ source: string;
17
+ target: string;
18
+ readOnly: true;
19
+ }>;
20
+ /**
21
+ * Resolve the package set for one conversation. Reads both scopes' settings,
22
+ * dedups, and reports the directories to load from.
23
+ */
24
+ export declare function resolveConversationPackages(options: ResolvePackagesOptions): ResolvedPackages;
25
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/packages/resolve.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAKV,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAwB3E,+DAA+D;AAC/D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,sBAAsB,GAC9B,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC,CAM3D;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,sBAAsB,GAAG,gBAAgB,CAqC7F"}