@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
@@ -1,13 +1,16 @@
1
- import { existsSync, readdirSync, readFileSync, rmSync, statSync } from "fs";
1
+ import { existsSync, readdirSync, readFileSync, statSync } from "fs";
2
2
  import { basename, join, resolve as pathResolve, sep as pathSep } from "path";
3
- import { MikanModels, SessionStore } from "../../harness/index.js";
4
- import { loadConversationAutoReplyConfig, loadGlobalSettings, resolveConversationSettings, saveConversationAutoReplyConfig, updateConversationSettings, updateGlobalSettings, } from "../../config.js";
3
+ import { MikanModels, parseFrontmatter, SessionStore } from "../../harness/index.js";
4
+ import { loadConversationAutoReplyConfig, loadGlobalSettings, resolveConversationSettings, saveConversationAutoReplyConfig, } from "../../config.js";
5
+ import { applyConversationSettings, applyGlobalSettings } from "../../settings-mutation.js";
6
+ import { effectiveStateDir } from "../../cli/arg-grammar.js";
7
+ import { addPackage, inspectConversationPackages, refreshPackage, removePackage, } from "../../packages/index.js";
5
8
  import { escapeHtml } from "../../utils/html.js";
6
9
  import { readRawBody } from "../../utils/http-body.js";
7
- import { renderPortalShell } from "../../portal-shell.js";
10
+ import { renderPortalShell } from "../portal-shell.js";
8
11
  import { resolveExistingSessionFile } from "../session-view/service.js";
9
12
  import { PRODUCT_NAME } from "../../platform-messages.js";
10
- import { resolveActorVaultKey } from "../../vault/routing.js";
13
+ import { credentialAuthorizationKey } from "../../sandbox/identity.js";
11
14
  import { sharedVaultKey } from "../../vault/index.js";
12
15
  import { modelKey, resolveAdminModelAccessStatuses } from "./provider-models.js";
13
16
  // ── Handler ────────────────────────────────────────────────────────────────────
@@ -87,8 +90,12 @@ async function routeApiRequest(req, res, url, services) {
87
90
  serveSkillFile(res, url, services, token);
88
91
  return;
89
92
  }
93
+ if (url.pathname === "/admin/api/packages") {
94
+ await servePackagesList(res, url, services, token);
95
+ return;
96
+ }
90
97
  if (url.pathname === "/admin/api/events") {
91
- serveEventsList(res, services);
98
+ await serveEventsList(res, services);
92
99
  return;
93
100
  }
94
101
  if (url.pathname === "/admin/api/events/file") {
@@ -96,7 +103,7 @@ async function routeApiRequest(req, res, url, services) {
96
103
  return;
97
104
  }
98
105
  if (url.pathname === "/admin/api/conversations/events") {
99
- serveConversationEventsList(res, url, services, token);
106
+ await serveConversationEventsList(res, url, services, token);
100
107
  return;
101
108
  }
102
109
  jsonRes(res, 404, { error: "Not found" });
@@ -140,19 +147,23 @@ async function routeApiRequest(req, res, url, services) {
140
147
  return;
141
148
  }
142
149
  if (url.pathname === "/admin/api/conversations/events/delete") {
143
- serveConversationEventDelete(res, body, services, token);
150
+ await serveConversationEventDelete(res, body, services, token);
151
+ return;
152
+ }
153
+ if (url.pathname === "/admin/api/packages/mutate") {
154
+ servePackageMutation(res, body, services, token);
144
155
  return;
145
156
  }
146
157
  if (url.pathname === "/admin/api/settings/model") {
147
- serveGlobalModelUpdate(res, body);
158
+ serveGlobalModelUpdate(res, body, services);
148
159
  return;
149
160
  }
150
161
  if (url.pathname === "/admin/api/settings/sandbox") {
151
- serveGlobalSandboxUpdate(res, body);
162
+ serveGlobalSandboxUpdate(res, body, services);
152
163
  return;
153
164
  }
154
165
  if (url.pathname === "/admin/api/settings/slack") {
155
- serveGlobalSlackUpdate(res, body);
166
+ serveGlobalSlackUpdate(res, body, services);
156
167
  return;
157
168
  }
158
169
  jsonRes(res, 404, { error: "Not found" });
@@ -193,7 +204,7 @@ const SETTINGS_FILES = new Set(["settings.json", "auto-reply", "auto-reply.disab
193
204
  function listConversationDirs(workingDir) {
194
205
  if (!existsSync(workingDir))
195
206
  return [];
196
- const skip = new Set(["vaults", "skills", "events", "node_modules", ".git"]);
207
+ const skip = new Set(["vaults", "skills", "events", "agents", "node_modules", ".git"]);
197
208
  return readdirSync(workingDir, { withFileTypes: true })
198
209
  .filter((entry) => entry.isDirectory() && !entry.name.startsWith(".") && !skip.has(entry.name))
199
210
  .map((entry) => entry.name)
@@ -465,8 +476,8 @@ function serveConversationState(res, url, services, token) {
465
476
  globalProvider: globalConfig.provider,
466
477
  globalModel: globalConfig.model,
467
478
  globalThinkingLevel: globalConfig.thinkingLevel,
468
- sandboxImageWorkspaceMount: conversationConfig.sandboxImageWorkspaceMount ?? null,
469
- globalSandboxImageWorkspaceMount: globalConfig.sandboxImageWorkspaceMount ?? null,
479
+ sandboxImageWorkspaceMount: conversationConfig.sandbox?.image?.workspaceMount ?? null,
480
+ globalSandboxImageWorkspaceMount: globalConfig.sandbox?.image?.workspaceMount ?? null,
470
481
  autoReplyEnabled: autoReply.enabled,
471
482
  autoReplyRules: autoReply.rules,
472
483
  slack: {
@@ -482,12 +493,12 @@ function serveGlobalSettings(res) {
482
493
  provider: config.provider,
483
494
  model: config.model,
484
495
  thinkingLevel: config.thinkingLevel,
485
- sandboxCpus: config.sandboxCpus ?? null,
486
- sandboxMemory: config.sandboxMemory ?? null,
487
- sandboxBoostCpus: config.sandboxBoostCpus ?? null,
488
- sandboxBoostMemory: config.sandboxBoostMemory ?? null,
489
- sandboxImageWorkspaceMount: config.sandboxImageWorkspaceMount ?? null,
490
- defaultSharedVault: config.defaultSharedVault ?? null,
496
+ sandboxCpus: config.sandbox?.cpus ?? null,
497
+ sandboxMemory: config.sandbox?.memory ?? null,
498
+ sandboxBoostCpus: config.sandbox?.boost?.cpus ?? null,
499
+ sandboxBoostMemory: config.sandbox?.boost?.memory ?? null,
500
+ sandboxImageWorkspaceMount: config.sandbox?.image?.workspaceMount ?? null,
501
+ defaultSharedVault: config.sandbox?.defaultSharedVault ?? null,
491
502
  slack: {
492
503
  replyMode: config.slack?.replyMode ?? "top-level",
493
504
  },
@@ -518,7 +529,7 @@ async function serveModelsList(res) {
518
529
  jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
519
530
  }
520
531
  }
521
- const VALID_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh"]);
532
+ const VALID_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
522
533
  function serveConversationModelUpdate(res, body, services, token) {
523
534
  const provider = typeof body.provider === "string" ? body.provider.trim() : "";
524
535
  const model = typeof body.model === "string" ? body.model.trim() : "";
@@ -537,18 +548,19 @@ function serveConversationModelUpdate(res, body, services, token) {
537
548
  const workingDir = requireAdminWorkingDir(res, services);
538
549
  if (!workingDir)
539
550
  return;
540
- const dir = join(workingDir, scope.conversationId);
541
551
  try {
542
- updateConversationSettings(dir, {
552
+ const result = applyConversationSettings(services.runtime, workingDir, scope.conversationId, {
543
553
  provider,
544
554
  model,
545
555
  ...(thinkingLevel ? { thinkingLevel } : {}),
546
556
  });
547
- let runtimeSwitched = null;
548
- if (services.runtime) {
549
- runtimeSwitched = services.runtime.switchConversationModel(scope.conversationId, provider, model);
557
+ if (!result.ok) {
558
+ jsonRes(res, 409, {
559
+ error: "Conversation has a running job; retry after it finishes (or /stop it).",
560
+ });
561
+ return;
550
562
  }
551
- jsonRes(res, 200, { ok: true, runtimeSwitched });
563
+ jsonRes(res, 200, { ok: true, runtimeSwitched: result.runtimeSwitched });
552
564
  }
553
565
  catch (err) {
554
566
  jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
@@ -568,9 +580,10 @@ function serveConversationSandboxUpdate(res, body, services, token) {
568
580
  const workingDir = requireAdminWorkingDir(res, services);
569
581
  if (!workingDir)
570
582
  return;
571
- const dir = join(workingDir, scope.conversationId);
572
583
  try {
573
- updateConversationSettings(dir, { sandboxImageWorkspaceMount: workspaceMount });
584
+ applyConversationSettings(services.runtime, workingDir, scope.conversationId, {
585
+ sandbox: { image: { workspaceMount } },
586
+ });
574
587
  jsonRes(res, 200, { ok: true });
575
588
  }
576
589
  catch (err) {
@@ -591,9 +604,10 @@ function serveConversationSlackUpdate(res, body, services, token) {
591
604
  const workingDir = requireAdminWorkingDir(res, services);
592
605
  if (!workingDir)
593
606
  return;
594
- const dir = join(workingDir, scope.conversationId);
595
607
  try {
596
- updateConversationSettings(dir, { slack: { replyMode } });
608
+ applyConversationSettings(services.runtime, workingDir, scope.conversationId, {
609
+ slack: { replyMode },
610
+ });
597
611
  jsonRes(res, 200, { ok: true });
598
612
  }
599
613
  catch (err) {
@@ -688,7 +702,10 @@ function serveConversationLoginLink(res, body, services, token) {
688
702
  }
689
703
  else {
690
704
  try {
691
- vaultId = resolveActorVaultKey(services.sandbox, token.platformUserId, scope.conversationId);
705
+ vaultId = credentialAuthorizationKey(services.sandbox, {
706
+ userId: token.platformUserId,
707
+ conversationId: scope.conversationId,
708
+ });
692
709
  }
693
710
  catch (err) {
694
711
  jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
@@ -704,7 +721,7 @@ function serveConversationLoginLink(res, body, services, token) {
704
721
  jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
705
722
  }
706
723
  }
707
- function serveGlobalModelUpdate(res, body) {
724
+ function serveGlobalModelUpdate(res, body, services) {
708
725
  const provider = typeof body.provider === "string" ? body.provider.trim() : "";
709
726
  const model = typeof body.model === "string" ? body.model.trim() : "";
710
727
  const thinkingLevel = typeof body.thinkingLevel === "string" && VALID_THINKING_LEVELS.has(body.thinkingLevel)
@@ -715,55 +732,57 @@ function serveGlobalModelUpdate(res, body) {
715
732
  return;
716
733
  }
717
734
  try {
718
- updateGlobalSettings({
735
+ const result = applyGlobalSettings(services.runtime, {
719
736
  provider,
720
737
  model,
721
738
  ...(thinkingLevel ? { thinkingLevel } : {}),
722
739
  });
723
- jsonRes(res, 200, { ok: true });
740
+ jsonRes(res, 200, { ok: true, staleConversations: result.staleConversations });
724
741
  }
725
742
  catch (err) {
726
743
  jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
727
744
  }
728
745
  }
729
- function serveGlobalSlackUpdate(res, body) {
746
+ function serveGlobalSlackUpdate(res, body, services) {
730
747
  const replyMode = body.replyMode;
731
748
  if (replyMode !== "top-level" && replyMode !== "thread") {
732
749
  jsonRes(res, 400, { error: "replyMode must be 'top-level' or 'thread'" });
733
750
  return;
734
751
  }
735
752
  try {
736
- updateGlobalSettings({ slack: { replyMode } });
753
+ applyGlobalSettings(services.runtime, { slack: { replyMode } });
737
754
  jsonRes(res, 200, { ok: true });
738
755
  }
739
756
  catch (err) {
740
757
  jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
741
758
  }
742
759
  }
743
- function serveGlobalSandboxUpdate(res, body) {
760
+ function serveGlobalSandboxUpdate(res, body, services) {
744
761
  const cpus = typeof body.cpus === "string" ? body.cpus.trim() : "";
745
762
  const memory = typeof body.memory === "string" ? body.memory.trim() : "";
746
763
  const boostCpus = typeof body.boostCpus === "string" ? body.boostCpus.trim() : "";
747
764
  const boostMemory = typeof body.boostMemory === "string" ? body.boostMemory.trim() : "";
748
765
  const workspaceMount = body.workspaceMount;
749
766
  const validMount = workspaceMount === "private" || workspaceMount === "full";
750
- const update = {};
751
- if (cpus)
752
- update.sandboxCpus = cpus;
753
- if (memory)
754
- update.sandboxMemory = memory;
755
- if (boostCpus)
756
- update.sandboxBoostCpus = boostCpus;
757
- if (boostMemory)
758
- update.sandboxBoostMemory = boostMemory;
759
- if (validMount)
760
- update.sandboxImageWorkspaceMount = workspaceMount;
767
+ const update = {
768
+ ...(cpus ? { cpus } : {}),
769
+ ...(memory ? { memory } : {}),
770
+ ...(boostCpus || boostMemory
771
+ ? {
772
+ boost: {
773
+ ...(boostCpus ? { cpus: boostCpus } : {}),
774
+ ...(boostMemory ? { memory: boostMemory } : {}),
775
+ },
776
+ }
777
+ : {}),
778
+ ...(validMount ? { image: { workspaceMount: workspaceMount } } : {}),
779
+ };
761
780
  if (Object.keys(update).length === 0) {
762
781
  jsonRes(res, 400, { error: "No valid sandbox fields provided" });
763
782
  return;
764
783
  }
765
784
  try {
766
- updateGlobalSettings(update);
785
+ applyGlobalSettings(services.runtime, { sandbox: update });
767
786
  jsonRes(res, 200, { ok: true });
768
787
  }
769
788
  catch (err) {
@@ -994,7 +1013,12 @@ function serveWorkspaceFile(res, url, services, token) {
994
1013
  }
995
1014
  servePreviewFile(res, safe.absolute, { path: requestedPath }, "File not found");
996
1015
  }
997
- function parseSkillFrontmatter(filePath) {
1016
+ /**
1017
+ * Read skill metadata via the harness frontmatter parser (the owning module).
1018
+ * The portal historically accepted frontmatter keys case-insensitively, so
1019
+ * the lookup — not the parser — preserves that leniency.
1020
+ */
1021
+ function readSkillMeta(filePath) {
998
1022
  let text;
999
1023
  try {
1000
1024
  text = readFileSync(filePath, "utf-8");
@@ -1002,31 +1026,18 @@ function parseSkillFrontmatter(filePath) {
1002
1026
  catch {
1003
1027
  return {};
1004
1028
  }
1005
- if (!text.startsWith("---"))
1006
- return {};
1007
- const end = text.indexOf("\n---", 3);
1008
- if (end < 0)
1009
- return {};
1010
- const block = text.slice(3, end);
1029
+ const { values } = parseFrontmatter(text);
1011
1030
  const out = {};
1012
- for (const line of block.split("\n")) {
1013
- const colon = line.indexOf(":");
1014
- if (colon < 0)
1015
- continue;
1016
- const key = line.slice(0, colon).trim().toLowerCase();
1017
- let value = line.slice(colon + 1).trim();
1018
- if ((value.startsWith('"') && value.endsWith('"')) ||
1019
- (value.startsWith("'") && value.endsWith("'"))) {
1020
- value = value.slice(1, -1);
1021
- }
1022
- if (key === "name")
1031
+ for (const [key, value] of Object.entries(values)) {
1032
+ const normalized = key.toLowerCase();
1033
+ if (normalized === "name")
1023
1034
  out.name = value;
1024
- if (key === "description")
1035
+ if (normalized === "description")
1025
1036
  out.description = value;
1026
1037
  }
1027
1038
  return out;
1028
1039
  }
1029
- function readSkillsFromDir(skillsDir, source) {
1040
+ export function readSkillsFromDir(skillsDir, source) {
1030
1041
  if (!existsSync(skillsDir))
1031
1042
  return [];
1032
1043
  const out = [];
@@ -1043,7 +1054,7 @@ function readSkillsFromDir(skillsDir, source) {
1043
1054
  const skillMd = join(skillsDir, entry.name, "SKILL.md");
1044
1055
  if (!existsSync(skillMd))
1045
1056
  continue;
1046
- const meta = parseSkillFrontmatter(skillMd);
1057
+ const meta = readSkillMeta(skillMd);
1047
1058
  out.push({
1048
1059
  name: meta.name ?? entry.name,
1049
1060
  description: meta.description ?? "",
@@ -1054,6 +1065,80 @@ function readSkillsFromDir(skillsDir, source) {
1054
1065
  }
1055
1066
  return out.toSorted((a, b) => a.name.localeCompare(b.name));
1056
1067
  }
1068
+ /** Inventory of both scopes' declared packages for the selected conversation. */
1069
+ async function servePackagesList(res, url, services, token) {
1070
+ const scope = resolveConversationFromQuery(url, token);
1071
+ if (scope.error) {
1072
+ jsonRes(res, 403, { error: scope.error });
1073
+ return;
1074
+ }
1075
+ const workingDir = requireAdminWorkingDir(res, services);
1076
+ if (!workingDir)
1077
+ return;
1078
+ try {
1079
+ const inventory = await inspectConversationPackages({
1080
+ conversationId: scope.conversationId,
1081
+ stateDir: effectiveStateDir(),
1082
+ conversationDir: join(workingDir, scope.conversationId),
1083
+ });
1084
+ jsonRes(res, 200, { conversationId: scope.conversationId, ...inventory });
1085
+ }
1086
+ catch (err) {
1087
+ jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
1088
+ }
1089
+ }
1090
+ /**
1091
+ * Add / remove / refresh, in one route because they share validation and all
1092
+ * three answer with the freshly re-read inventory: the panel never has to
1093
+ * guess what the write did.
1094
+ */
1095
+ function servePackageMutation(res, body, services, token) {
1096
+ const action = body.action;
1097
+ if (action !== "add" && action !== "remove" && action !== "refresh") {
1098
+ jsonRes(res, 400, { error: "action must be 'add', 'remove', or 'refresh'" });
1099
+ return;
1100
+ }
1101
+ const packageScope = body.scope === "global" ? "global" : "conversation";
1102
+ const source = typeof body.source === "string" ? body.source.trim() : "";
1103
+ if (!source) {
1104
+ jsonRes(res, 400, { error: "source is required" });
1105
+ return;
1106
+ }
1107
+ const scope = resolveTargetConversation(body, token);
1108
+ if (scope.error) {
1109
+ jsonRes(res, 403, { error: scope.error });
1110
+ return;
1111
+ }
1112
+ const workingDir = requireAdminWorkingDir(res, services);
1113
+ if (!workingDir)
1114
+ return;
1115
+ const context = {
1116
+ conversationId: scope.conversationId,
1117
+ stateDir: effectiveStateDir(),
1118
+ conversationDir: join(workingDir, scope.conversationId),
1119
+ workingDir,
1120
+ runtime: services.runtime,
1121
+ };
1122
+ try {
1123
+ if (action === "add") {
1124
+ const result = addPackage(packageScope, source, context);
1125
+ jsonRes(res, 200, { ok: true, source: result.source, dir: result.dir });
1126
+ return;
1127
+ }
1128
+ if (action === "refresh") {
1129
+ const result = refreshPackage(packageScope, source, context);
1130
+ jsonRes(res, 200, { ok: true, source: result.source, dir: result.dir });
1131
+ return;
1132
+ }
1133
+ const removed = removePackage(packageScope, source, context);
1134
+ jsonRes(res, removed ? 200 : 404, removed ? { ok: true } : { error: "Not declared here." });
1135
+ }
1136
+ catch (err) {
1137
+ // Fetch/validation failures are the admin's problem to fix, not a server
1138
+ // fault: report them as a bad request with git's own message.
1139
+ jsonRes(res, 400, { error: err instanceof Error ? err.message : String(err) });
1140
+ }
1141
+ }
1057
1142
  function serveSkillsList(res, url, services, token) {
1058
1143
  const scope = resolveConversationFromQuery(url, token);
1059
1144
  if (scope.error) {
@@ -1104,75 +1189,53 @@ function serveSkillFile(res, url, services, token) {
1104
1189
  }
1105
1190
  // ── Events ─────────────────────────────────────────────────────────────────────
1106
1191
  const EVENTS_FILE_MAX_BYTES = 64 * 1024;
1107
- function listAllEvents(workingDir) {
1108
- const dir = join(workingDir, "events");
1109
- if (!existsSync(dir))
1110
- return [];
1111
- let entries;
1112
- try {
1113
- entries = readdirSync(dir, { withFileTypes: true });
1114
- }
1115
- catch {
1116
- return [];
1117
- }
1118
- return entries
1119
- .filter((e) => e.isFile() && e.name.endsWith(".json"))
1120
- .map((e) => {
1121
- const filePath = join(dir, e.name);
1122
- let stats;
1123
- try {
1124
- stats = statSync(filePath);
1125
- }
1126
- catch {
1127
- return null;
1128
- }
1129
- let parsed = null;
1130
- try {
1131
- parsed = JSON.parse(readFileSync(filePath, "utf-8"));
1132
- }
1133
- catch {
1134
- // Keep entry; just omit parsed fields.
1135
- }
1136
- const meta = parsed && typeof parsed === "object" ? parsed : {};
1137
- // events.ts accepts `channelId` as a legacy alias for `conversationId`.
1138
- const conversationId = typeof meta.conversationId === "string"
1139
- ? meta.conversationId
1140
- : typeof meta.channelId === "string"
1141
- ? meta.channelId
1142
- : null;
1192
+ /**
1193
+ * List events through the owning store, whose payloads are validated by the
1194
+ * event-format module (files that fail validation stay visible with a null
1195
+ * payload so operators can delete them).
1196
+ */
1197
+ export async function listAllEvents(store) {
1198
+ const entries = await store.list();
1199
+ return entries.map((entry) => {
1200
+ const payload = entry.payload;
1143
1201
  return {
1144
- name: e.name,
1145
- size: stats.size,
1146
- mtimeMs: stats.mtimeMs,
1147
- type: typeof meta.type === "string" ? meta.type : null,
1148
- platform: typeof meta.platform === "string" ? meta.platform : null,
1149
- conversationId,
1150
- text: typeof meta.text === "string" ? meta.text : null,
1151
- at: typeof meta.at === "string" ? meta.at : null,
1152
- schedule: typeof meta.schedule === "string" ? meta.schedule : null,
1153
- timezone: typeof meta.timezone === "string" ? meta.timezone : null,
1202
+ name: entry.filename,
1203
+ size: entry.size,
1204
+ mtimeMs: entry.mtimeMs,
1205
+ type: payload?.type ?? null,
1206
+ platform: payload?.platform ?? null,
1207
+ conversationId: payload?.conversationId ?? null,
1208
+ text: payload?.text ?? null,
1209
+ at: payload?.type === "one-shot" ? payload.at : null,
1210
+ schedule: payload?.type === "periodic" ? payload.schedule : null,
1211
+ timezone: payload?.type === "periodic" ? payload.timezone : null,
1154
1212
  };
1155
- })
1156
- .filter((e) => e !== null)
1157
- .toSorted((a, b) => a.name.localeCompare(b.name));
1213
+ });
1158
1214
  }
1159
- function serveEventsList(res, services) {
1160
- const workingDir = requireAdminWorkingDir(res, services);
1161
- if (!workingDir)
1215
+ function requireAdminEventStore(res, services) {
1216
+ if (!services.eventStore) {
1217
+ jsonRes(res, 503, { error: "Working directory not available" });
1218
+ return null;
1219
+ }
1220
+ return services.eventStore;
1221
+ }
1222
+ async function serveEventsList(res, services) {
1223
+ const store = requireAdminEventStore(res, services);
1224
+ if (!store)
1162
1225
  return;
1163
- jsonRes(res, 200, { events: listAllEvents(workingDir) });
1226
+ jsonRes(res, 200, { events: await listAllEvents(store) });
1164
1227
  }
1165
1228
  /** Per-conversation listing — filter all events by conversationId match. */
1166
- function serveConversationEventsList(res, url, services, token) {
1229
+ async function serveConversationEventsList(res, url, services, token) {
1167
1230
  const scope = resolveConversationFromQuery(url, token);
1168
1231
  if (scope.error) {
1169
1232
  jsonRes(res, 403, { error: scope.error });
1170
1233
  return;
1171
1234
  }
1172
- const workingDir = requireAdminWorkingDir(res, services);
1173
- if (!workingDir)
1235
+ const store = requireAdminEventStore(res, services);
1236
+ if (!store)
1174
1237
  return;
1175
- const events = listAllEvents(workingDir).filter((e) => e.conversationId === scope.conversationId);
1238
+ const events = (await listAllEvents(store)).filter((e) => e.conversationId === scope.conversationId);
1176
1239
  jsonRes(res, 200, { conversationId: scope.conversationId, events });
1177
1240
  }
1178
1241
  function serveEventsFile(res, url, services) {
@@ -1212,7 +1275,7 @@ function serveEventsFile(res, url, services) {
1212
1275
  jsonRes(res, 200, { name, content: raw });
1213
1276
  }
1214
1277
  /** Delete a single event file scoped to the caller's conversation. */
1215
- function serveConversationEventDelete(res, body, services, token) {
1278
+ async function serveConversationEventDelete(res, body, services, token) {
1216
1279
  const scope = resolveTargetConversation(body, token);
1217
1280
  if (scope.error) {
1218
1281
  jsonRes(res, 403, { error: scope.error });
@@ -1223,38 +1286,24 @@ function serveConversationEventDelete(res, body, services, token) {
1223
1286
  jsonRes(res, 400, { error: "Invalid name" });
1224
1287
  return;
1225
1288
  }
1226
- const workingDir = requireAdminWorkingDir(res, services);
1227
- if (!workingDir)
1289
+ const store = requireAdminEventStore(res, services);
1290
+ if (!store)
1228
1291
  return;
1229
- const filePath = join(workingDir, "events", name);
1230
- let raw;
1292
+ let payload;
1231
1293
  try {
1232
- raw = readFileSync(filePath, "utf-8");
1294
+ payload = (await store.read(name)).payload;
1233
1295
  }
1234
1296
  catch {
1235
1297
  jsonRes(res, 404, { error: "Event not found" });
1236
1298
  return;
1237
1299
  }
1238
- let parsed = {};
1239
- try {
1240
- const j = JSON.parse(raw);
1241
- if (j && typeof j === "object")
1242
- parsed = j;
1243
- }
1244
- catch {
1245
- // Malformed events cannot be associated with a conversation below.
1246
- }
1247
- const eventConvId = typeof parsed.conversationId === "string"
1248
- ? parsed.conversationId
1249
- : typeof parsed.channelId === "string"
1250
- ? parsed.channelId
1251
- : null;
1252
- if (eventConvId !== scope.conversationId) {
1300
+ // The store normalizes the legacy `channelId` alias into `conversationId`.
1301
+ if (payload?.conversationId !== scope.conversationId) {
1253
1302
  jsonRes(res, 403, { error: "Event does not belong to this conversation." });
1254
1303
  return;
1255
1304
  }
1256
1305
  try {
1257
- rmSync(filePath, { force: true });
1306
+ await store.delete(name);
1258
1307
  jsonRes(res, 200, { ok: true });
1259
1308
  }
1260
1309
  catch (err) {
@@ -1330,6 +1379,25 @@ function renderAdminPage(token) {
1330
1379
  </div>
1331
1380
  </section>
1332
1381
 
1382
+ <section class="card sect" id="sect-packages" data-section="packages">
1383
+ <header class="sect-head">
1384
+ <div>
1385
+ <p class="eyebrow">Extensions</p>
1386
+ <h2 class="card-title">此對話的 extension 套件</h2>
1387
+ </div>
1388
+ <button class="refresh-btn" onclick="loadPackages()">↻</button>
1389
+ </header>
1390
+ <div class="pkg-add">
1391
+ <input id="pkg-conv-url" class="pkg-input" type="text" spellcheck="false"
1392
+ placeholder="github:owner/repo 或 https://github.com/owner/repo.git" />
1393
+ <input id="pkg-conv-ref" class="pkg-input pkg-input-ref" type="text" spellcheck="false"
1394
+ placeholder="tag / branch / commit(可留空)" />
1395
+ <button class="primary-action-btn" onclick="addPackage('conversation')">Add</button>
1396
+ </div>
1397
+ <div id="pkg-conv-msg" class="pkg-msg" style="display:none"></div>
1398
+ <div id="pkg-conv-content"><div class="loading-msg">Loading…</div></div>
1399
+ </section>
1400
+
1333
1401
  <section class="card sect" id="sect-vault" data-section="vault">
1334
1402
  <header class="sect-head">
1335
1403
  <div>
@@ -1407,6 +1475,25 @@ function renderAdminPage(token) {
1407
1475
  <div id="global-settings-content"><div class="loading-msg">Loading…</div></div>
1408
1476
  </section>
1409
1477
 
1478
+ <section class="card sect">
1479
+ <header class="sect-head">
1480
+ <div>
1481
+ <p class="eyebrow">Global Extensions</p>
1482
+ <h2 class="card-title">所有對話都會載入的 extension 套件</h2>
1483
+ </div>
1484
+ <button class="refresh-btn" onclick="loadPackages()">↻</button>
1485
+ </header>
1486
+ <div class="pkg-add">
1487
+ <input id="pkg-global-url" class="pkg-input" type="text" spellcheck="false"
1488
+ placeholder="github:owner/repo 或 https://github.com/owner/repo.git" />
1489
+ <input id="pkg-global-ref" class="pkg-input pkg-input-ref" type="text" spellcheck="false"
1490
+ placeholder="tag / branch / commit(可留空)" />
1491
+ <button class="primary-action-btn" onclick="addPackage('global')">Add</button>
1492
+ </div>
1493
+ <div id="pkg-global-msg" class="pkg-msg" style="display:none"></div>
1494
+ <div id="pkg-global-content"><div class="loading-msg">Loading…</div></div>
1495
+ </section>
1496
+
1410
1497
  <section class="card sect">
1411
1498
  <header class="sect-head">
1412
1499
  <div>
@@ -1558,6 +1645,7 @@ function renderAdminPage(token) {
1558
1645
  loadSettings();
1559
1646
  loadWorkspace();
1560
1647
  loadSkills();
1648
+ loadPackages();
1561
1649
  loadConversationEvents();
1562
1650
  openLogin(true);
1563
1651
  openSessionView(true);
@@ -1578,7 +1666,7 @@ function renderAdminPage(token) {
1578
1666
  }
1579
1667
 
1580
1668
  function renderSettings(data) {
1581
- const thinking = ['off','minimal','low','medium','high','xhigh'];
1669
+ const thinking = ['off','minimal','low','medium','high','xhigh','max'];
1582
1670
  const thinkingOpts = thinking.map((t) =>
1583
1671
  '<option value="' + t + '"' + (data.thinkingLevel === t ? ' selected' : '') + '>' + t + '</option>'
1584
1672
  ).join('');
@@ -1647,9 +1735,7 @@ function renderAdminPage(token) {
1647
1735
  conversationId: activeConversationId, provider, model, thinkingLevel,
1648
1736
  });
1649
1737
  result.style.display = 'block'; result.className = 'inline-result ok';
1650
- result.textContent = data.runtimeSwitched === false
1651
- ? 'Saved — running session pinned; new model applies on next start.'
1652
- : 'Saved ✓';
1738
+ result.textContent = 'Saved ✓';
1653
1739
  } catch (err) {
1654
1740
  result.style.display = 'block'; result.className = 'inline-result err';
1655
1741
  result.textContent = err.message;
@@ -1764,6 +1850,101 @@ function renderAdminPage(token) {
1764
1850
 
1765
1851
  // ── Skills ───────────────────────────────────────────────────────────────────
1766
1852
 
1853
+ function packageMessage(scope, text, kind) {
1854
+ const el = document.getElementById(scope === 'global' ? 'pkg-global-msg' : 'pkg-conv-msg');
1855
+ if (!text) { el.style.display = 'none'; return; }
1856
+ el.className = 'pkg-msg pkg-msg-' + kind;
1857
+ el.textContent = text;
1858
+ el.style.display = 'block';
1859
+ }
1860
+
1861
+ function renderPackageList(container, rows, scope) {
1862
+ if (rows.length === 0) {
1863
+ container.innerHTML = '<div class="empty-state">尚未加入任何套件</div>';
1864
+ return;
1865
+ }
1866
+ container.innerHTML = '<div class="pkg-list">' + rows.map((p) => {
1867
+ const provides = []
1868
+ .concat(p.extensions.map((s) => 'ext: ' + s))
1869
+ .concat(p.skills.map((s) => 'skill: ' + s));
1870
+ const status = p.error
1871
+ ? '<span class="pkg-badge pkg-badge-err">' + escHtml(p.error) + '</span>'
1872
+ : p.shadowed
1873
+ ? '<span class="pkg-badge pkg-badge-warn">被此對話的同名套件覆蓋,不會載入</span>'
1874
+ : '<span class="pkg-badge pkg-badge-ok">ready</span>';
1875
+ return '<div class="pkg-row">' +
1876
+ '<div class="pkg-row-main">' +
1877
+ '<code class="pkg-source">' + escHtml(p.source) + '</code>' + status +
1878
+ '</div>' +
1879
+ (provides.length > 0
1880
+ ? '<div class="pkg-provides">' + provides.map((t) => '<span class="pkg-chip">' + escHtml(t) + '</span>').join('') + '</div>'
1881
+ : '<div class="pkg-provides pkg-provides-empty">此套件沒有提供 extension 或 skill</div>') +
1882
+ '<div class="pkg-actions">' +
1883
+ '<button class="pkg-btn" data-pkg-action="refresh" data-pkg-scope="' + scope + '" data-pkg-source="' + escAttr(p.source) + '">Update</button>' +
1884
+ '<button class="pkg-btn pkg-btn-danger" data-pkg-action="remove" data-pkg-scope="' + scope + '" data-pkg-source="' + escAttr(p.source) + '">Remove</button>' +
1885
+ '</div>' +
1886
+ '</div>';
1887
+ }).join('') + '</div>';
1888
+ }
1889
+
1890
+ async function loadPackages() {
1891
+ const convEl = document.getElementById('pkg-conv-content');
1892
+ const globalEl = document.getElementById('pkg-global-content');
1893
+ if (convEl) convEl.innerHTML = '<div class="loading-msg">Loading…</div>';
1894
+ if (globalEl) globalEl.innerHTML = '<div class="loading-msg">Loading…</div>';
1895
+ try {
1896
+ const data = await apiGet('/admin/api/packages?conversationId=' + encodeURIComponent(activeConversationId));
1897
+ if (convEl) renderPackageList(convEl, data.conversation, 'conversation');
1898
+ if (globalEl) renderPackageList(globalEl, data.global, 'global');
1899
+ } catch (err) {
1900
+ if (convEl) convEl.innerHTML = '<div class="err-msg">' + escHtml(err.message) + '</div>';
1901
+ if (globalEl) globalEl.innerHTML = '<div class="err-msg">' + escHtml(err.message) + '</div>';
1902
+ }
1903
+ }
1904
+
1905
+ async function mutatePackage(scope, action, source) {
1906
+ packageMessage(scope, action === 'remove' ? '移除中…' : '取得中…', 'busy');
1907
+ try {
1908
+ const result = await apiPost('/admin/api/packages/mutate', {
1909
+ action: action,
1910
+ scope: scope,
1911
+ source: source,
1912
+ conversationId: activeConversationId,
1913
+ });
1914
+ packageMessage(
1915
+ scope,
1916
+ action === 'remove'
1917
+ ? '已移除。對話輸入 /pi-new 生效。'
1918
+ : '完成:' + result.source + '(對話輸入 /pi-new 生效)',
1919
+ 'ok',
1920
+ );
1921
+ await loadPackages();
1922
+ } catch (err) {
1923
+ // Fetch and validation failures land here, next to the input that
1924
+ // caused them, rather than turning into a silently missing feature.
1925
+ packageMessage(scope, err.message, 'err');
1926
+ }
1927
+ }
1928
+
1929
+ async function addPackage(scope) {
1930
+ const urlEl = document.getElementById(scope === 'global' ? 'pkg-global-url' : 'pkg-conv-url');
1931
+ const refEl = document.getElementById(scope === 'global' ? 'pkg-global-ref' : 'pkg-conv-ref');
1932
+ const url = urlEl.value.trim();
1933
+ const ref = refEl.value.trim();
1934
+ if (!url) { packageMessage(scope, '請填入 git URL', 'err'); return; }
1935
+ // Assembled here so nobody has to hand-write the @ref form, whose
1936
+ // ambiguity with git@host:owner/repo is the one sharp edge in the syntax.
1937
+ await mutatePackage(scope, 'add', ref ? url + '@' + ref : url);
1938
+ urlEl.value = '';
1939
+ refEl.value = '';
1940
+ }
1941
+
1942
+ document.addEventListener('click', (event) => {
1943
+ const btn = event.target.closest('[data-pkg-action]');
1944
+ if (!btn) return;
1945
+ void mutatePackage(btn.dataset.pkgScope, btn.dataset.pkgAction, btn.dataset.pkgSource);
1946
+ });
1947
+
1767
1948
  async function loadSkills() {
1768
1949
  const container = document.getElementById('skills-content');
1769
1950
  const previewEl = document.getElementById('skills-preview');
@@ -2130,7 +2311,7 @@ function renderAdminPage(token) {
2130
2311
  }
2131
2312
 
2132
2313
  function renderGlobalSettings(data) {
2133
- const thinking = ['off','minimal','low','medium','high','xhigh'];
2314
+ const thinking = ['off','minimal','low','medium','high','xhigh','max'];
2134
2315
  const thinkingOpts = thinking.map((t) =>
2135
2316
  '<option value="' + t + '"' + (data.thinkingLevel === t ? ' selected' : '') + '>' + t + '</option>'
2136
2317
  ).join('');
@@ -2251,6 +2432,7 @@ function renderAdminPage(token) {
2251
2432
  loadSettings();
2252
2433
  loadWorkspace();
2253
2434
  loadSkills();
2435
+ loadPackages();
2254
2436
  loadConversationEvents();
2255
2437
  });
2256
2438
  `;
@@ -2433,6 +2615,54 @@ const adminViewStyles = `
2433
2615
  .skill-source-conversation { background: rgba(217,119,6,0.1); color: var(--accent); }
2434
2616
  .skill-desc { color: var(--muted); font-size: 0.82rem; margin-top: 4px; line-height: 1.5; }
2435
2617
 
2618
+ /* ── Packages ───────────────────────────────────────────────────────── */
2619
+
2620
+ .pkg-add { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
2621
+ .pkg-input {
2622
+ flex: 1 1 240px; min-width: 0; padding: 8px 10px;
2623
+ border: 1px solid var(--border); border-radius: 8px; background: var(--card);
2624
+ font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.8rem; color: var(--text);
2625
+ }
2626
+ .pkg-input-ref { flex: 0 1 200px; }
2627
+ .pkg-msg {
2628
+ padding: 8px 12px; border-radius: 8px; margin-bottom: 12px;
2629
+ font-size: 0.82rem; line-height: 1.5; word-break: break-word;
2630
+ }
2631
+ .pkg-msg-ok { background: rgba(22,163,74,0.1); color: #15803d; }
2632
+ .pkg-msg-err { background: rgba(220,38,38,0.1); color: #b91c1c; }
2633
+ .pkg-msg-busy { background: rgba(0,0,0,0.05); color: var(--muted); }
2634
+ .pkg-list { display: flex; flex-direction: column; gap: 8px; }
2635
+ .pkg-row {
2636
+ padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
2637
+ background: rgba(0,0,0,0.02);
2638
+ }
2639
+ .pkg-row-main { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
2640
+ .pkg-source {
2641
+ font-family: 'JetBrains Mono', ui-monospace, monospace;
2642
+ font-size: 0.78rem; color: var(--text); word-break: break-all;
2643
+ }
2644
+ .pkg-badge {
2645
+ padding: 1px 8px; border-radius: 999px; font-size: 0.7rem;
2646
+ font-weight: 600; letter-spacing: 0.03em;
2647
+ }
2648
+ .pkg-badge-ok { background: rgba(22,163,74,0.1); color: #15803d; }
2649
+ .pkg-badge-warn { background: rgba(217,119,6,0.12); color: var(--accent); }
2650
+ .pkg-badge-err { background: rgba(220,38,38,0.1); color: #b91c1c; }
2651
+ .pkg-provides { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; }
2652
+ .pkg-provides-empty { color: var(--subtle); font-size: 0.78rem; }
2653
+ .pkg-chip {
2654
+ padding: 1px 8px; border-radius: 6px; background: rgba(59,130,246,0.1);
2655
+ color: #1d4ed8; font-size: 0.72rem;
2656
+ font-family: 'JetBrains Mono', ui-monospace, monospace;
2657
+ }
2658
+ .pkg-actions { margin-top: 8px; display: flex; gap: 8px; }
2659
+ .pkg-btn {
2660
+ padding: 4px 10px; border: 1px solid var(--border); border-radius: 7px;
2661
+ background: var(--card); color: var(--text); font-size: 0.76rem; cursor: pointer;
2662
+ }
2663
+ .pkg-btn:hover { background: rgba(0,0,0,0.05); }
2664
+ .pkg-btn-danger { color: #b91c1c; }
2665
+
2436
2666
  /* ── Events ─────────────────────────────────────────────────────────── */
2437
2667
 
2438
2668
  .events-list { display: flex; flex-direction: column; gap: 8px; }