@pi-harness/pi-harness 0.1.2 → 0.1.4

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 (914) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +31 -7
  3. package/apps/web/dist/assets/index-CihATCjR.css +2 -0
  4. package/apps/web/dist/assets/index-NzapJoGa.js +20 -0
  5. package/apps/web/dist/assets/markdown-vendor-DUdMWn0M.js +66 -0
  6. package/apps/web/dist/assets/react-vendor-BD7-wQo9.js +9 -0
  7. package/apps/web/dist/icons/app/android-192.png +0 -0
  8. package/apps/web/dist/icons/app/android-512.png +0 -0
  9. package/apps/web/dist/icons/app/app-blue-512.png +0 -0
  10. package/apps/web/dist/icons/app/app-store-1024.png +0 -0
  11. package/apps/web/dist/icons/app/apple-touch-icon-180.png +0 -0
  12. package/apps/web/dist/icons/app/maskable-512.png +0 -0
  13. package/apps/web/dist/icons/favicon/favicon-16.png +0 -0
  14. package/apps/web/dist/icons/favicon/favicon-32.png +0 -0
  15. package/apps/web/dist/icons/favicon/favicon-48.png +0 -0
  16. package/apps/web/dist/icons/png-blue/pi-256.png +0 -0
  17. package/apps/web/dist/icons/png-blue/pi-512.png +0 -0
  18. package/apps/web/dist/icons/png-ink/pi-1024.png +0 -0
  19. package/apps/web/dist/icons/png-ink/pi-128.png +0 -0
  20. package/apps/web/dist/icons/png-ink/pi-16.png +0 -0
  21. package/apps/web/dist/icons/png-ink/pi-24.png +0 -0
  22. package/apps/web/dist/icons/png-ink/pi-256.png +0 -0
  23. package/apps/web/dist/icons/png-ink/pi-32.png +0 -0
  24. package/apps/web/dist/icons/png-ink/pi-48.png +0 -0
  25. package/apps/web/dist/icons/png-ink/pi-512.png +0 -0
  26. package/apps/web/dist/icons/png-ink/pi-64.png +0 -0
  27. package/apps/web/dist/icons/png-white/pi-1024.png +0 -0
  28. package/apps/web/dist/icons/png-white/pi-128.png +0 -0
  29. package/apps/web/dist/icons/png-white/pi-16.png +0 -0
  30. package/apps/web/dist/icons/png-white/pi-24.png +0 -0
  31. package/apps/web/dist/icons/png-white/pi-256.png +0 -0
  32. package/apps/web/dist/icons/png-white/pi-32.png +0 -0
  33. package/apps/web/dist/icons/png-white/pi-48.png +0 -0
  34. package/apps/web/dist/icons/png-white/pi-512.png +0 -0
  35. package/apps/web/dist/icons/png-white/pi-64.png +0 -0
  36. package/apps/web/dist/icons/social/og-1200x630.png +0 -0
  37. package/apps/web/dist/icons/svg/app-icon-blue.svg +13 -0
  38. package/apps/web/dist/icons/svg/app-icon-ink.svg +13 -0
  39. package/apps/web/dist/icons/svg/favicon.svg +10 -0
  40. package/apps/web/dist/icons/svg/lockup-horizontal.svg +13 -0
  41. package/apps/web/dist/icons/svg/mark-blue.svg +10 -0
  42. package/apps/web/dist/icons/svg/mark-compact.svg +10 -0
  43. package/apps/web/dist/icons/svg/mark-ink.svg +10 -0
  44. package/apps/web/dist/icons/svg/mark-white.svg +10 -0
  45. package/apps/web/dist/icons/svg/mark.svg +10 -0
  46. package/apps/web/dist/index.html +18 -6
  47. package/apps/web/dist/manifest.webmanifest +14 -0
  48. package/apps/web/index.html +14 -4
  49. package/apps/web/package.json +11 -9
  50. package/apps/web/profile/cordis.yml +222 -1
  51. package/apps/web/public/icons/app/android-192.png +0 -0
  52. package/apps/web/public/icons/app/android-512.png +0 -0
  53. package/apps/web/public/icons/app/app-blue-512.png +0 -0
  54. package/apps/web/public/icons/app/app-store-1024.png +0 -0
  55. package/apps/web/public/icons/app/apple-touch-icon-180.png +0 -0
  56. package/apps/web/public/icons/app/maskable-512.png +0 -0
  57. package/apps/web/public/icons/favicon/favicon-16.png +0 -0
  58. package/apps/web/public/icons/favicon/favicon-32.png +0 -0
  59. package/apps/web/public/icons/favicon/favicon-48.png +0 -0
  60. package/apps/web/public/icons/png-blue/pi-256.png +0 -0
  61. package/apps/web/public/icons/png-blue/pi-512.png +0 -0
  62. package/apps/web/public/icons/png-ink/pi-1024.png +0 -0
  63. package/apps/web/public/icons/png-ink/pi-128.png +0 -0
  64. package/apps/web/public/icons/png-ink/pi-16.png +0 -0
  65. package/apps/web/public/icons/png-ink/pi-24.png +0 -0
  66. package/apps/web/public/icons/png-ink/pi-256.png +0 -0
  67. package/apps/web/public/icons/png-ink/pi-32.png +0 -0
  68. package/apps/web/public/icons/png-ink/pi-48.png +0 -0
  69. package/apps/web/public/icons/png-ink/pi-512.png +0 -0
  70. package/apps/web/public/icons/png-ink/pi-64.png +0 -0
  71. package/apps/web/public/icons/png-white/pi-1024.png +0 -0
  72. package/apps/web/public/icons/png-white/pi-128.png +0 -0
  73. package/apps/web/public/icons/png-white/pi-16.png +0 -0
  74. package/apps/web/public/icons/png-white/pi-24.png +0 -0
  75. package/apps/web/public/icons/png-white/pi-256.png +0 -0
  76. package/apps/web/public/icons/png-white/pi-32.png +0 -0
  77. package/apps/web/public/icons/png-white/pi-48.png +0 -0
  78. package/apps/web/public/icons/png-white/pi-512.png +0 -0
  79. package/apps/web/public/icons/png-white/pi-64.png +0 -0
  80. package/apps/web/public/icons/social/og-1200x630.png +0 -0
  81. package/apps/web/public/icons/svg/app-icon-blue.svg +13 -0
  82. package/apps/web/public/icons/svg/app-icon-ink.svg +13 -0
  83. package/apps/web/public/icons/svg/favicon.svg +10 -0
  84. package/apps/web/public/icons/svg/lockup-horizontal.svg +13 -0
  85. package/apps/web/public/icons/svg/mark-blue.svg +10 -0
  86. package/apps/web/public/icons/svg/mark-compact.svg +10 -0
  87. package/apps/web/public/icons/svg/mark-ink.svg +10 -0
  88. package/apps/web/public/icons/svg/mark-white.svg +10 -0
  89. package/apps/web/public/icons/svg/mark.svg +10 -0
  90. package/apps/web/public/manifest.webmanifest +14 -0
  91. package/apps/web/server-dist/bin.js +19 -6
  92. package/apps/web/server-dist/bin.js.map +1 -1
  93. package/apps/web/src/command-palette.ts +28 -7
  94. package/apps/web/src/file-diff.ts +15 -10
  95. package/apps/web/src/main.ts +4 -1
  96. package/apps/web/src/runtime.css +17 -4
  97. package/apps/web/src/server/bin.ts +24 -7
  98. package/apps/web/src/style.css +2618 -8
  99. package/apps/web/src/tailwind.css +25 -0
  100. package/apps/web/tsconfig.build.json +5 -1
  101. package/apps/web/tsconfig.json +1 -1
  102. package/apps/web/vite.config.ts +20 -0
  103. package/package.json +29 -17
  104. package/packages/api-gateway/LICENSE +9 -0
  105. package/packages/api-gateway/dist/index.d.ts.map +1 -1
  106. package/packages/api-gateway/dist/index.js +1188 -42
  107. package/packages/api-gateway/dist/index.js.map +1 -1
  108. package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +31 -0
  109. package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +29 -0
  110. package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +28 -0
  111. package/packages/api-gateway/dist/marketplace-entries/official/archify.json +31 -0
  112. package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +28 -0
  113. package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +32 -0
  114. package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +32 -0
  115. package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +28 -0
  116. package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +29 -0
  117. package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +29 -0
  118. package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +30 -0
  119. package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +29 -0
  120. package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +30 -0
  121. package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +29 -0
  122. package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +30 -0
  123. package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +30 -0
  124. package/packages/api-gateway/dist/marketplace-entries/official/context.json +28 -0
  125. package/packages/api-gateway/dist/marketplace-entries/official/cordis-group.json +16 -0
  126. package/packages/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +16 -0
  127. package/packages/api-gateway/dist/marketplace-entries/official/cordis-timer.json +16 -0
  128. package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +31 -0
  129. package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +31 -0
  130. package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +29 -0
  131. package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +29 -0
  132. package/packages/api-gateway/dist/marketplace-entries/official/genui.json +28 -0
  133. package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +30 -0
  134. package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +29 -0
  135. package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +33 -0
  136. package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +29 -0
  137. package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +29 -0
  138. package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +29 -0
  139. package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +32 -0
  140. package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +29 -0
  141. package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +29 -0
  142. package/packages/api-gateway/dist/marketplace-entries/official/memory.json +28 -0
  143. package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +33 -0
  144. package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +29 -0
  145. package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +28 -0
  146. package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +30 -0
  147. package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +29 -0
  148. package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +29 -0
  149. package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +29 -0
  150. package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +29 -0
  151. package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +29 -0
  152. package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +32 -0
  153. package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +28 -0
  154. package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +29 -0
  155. package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +28 -0
  156. package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +30 -0
  157. package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +31 -0
  158. package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +29 -0
  159. package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +30 -0
  160. package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +29 -0
  161. package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +32 -0
  162. package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +30 -0
  163. package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +30 -0
  164. package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +30 -0
  165. package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +30 -0
  166. package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +30 -0
  167. package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +29 -0
  168. package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +30 -0
  169. package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +31 -0
  170. package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +29 -0
  171. package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +29 -0
  172. package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +28 -0
  173. package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +29 -0
  174. package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +29 -0
  175. package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +29 -0
  176. package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +29 -0
  177. package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +32 -0
  178. package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +32 -0
  179. package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +29 -0
  180. package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +28 -0
  181. package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +29 -0
  182. package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +29 -0
  183. package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +32 -0
  184. package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +29 -0
  185. package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +29 -0
  186. package/packages/api-gateway/dist/marketplace.d.ts +40 -2
  187. package/packages/api-gateway/dist/marketplace.d.ts.map +1 -1
  188. package/packages/api-gateway/dist/marketplace.js +225 -19
  189. package/packages/api-gateway/dist/marketplace.js.map +1 -1
  190. package/packages/api-gateway/dist/workspaces.d.ts +8 -0
  191. package/packages/api-gateway/dist/workspaces.d.ts.map +1 -0
  192. package/packages/api-gateway/dist/workspaces.js +14 -0
  193. package/packages/api-gateway/dist/workspaces.js.map +1 -0
  194. package/packages/api-gateway/package.json +20 -10
  195. package/packages/api-gateway/scripts/copy-marketplace-entries.mjs +13 -0
  196. package/packages/api-gateway/src/index.ts +1258 -61
  197. package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +31 -0
  198. package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +29 -0
  199. package/packages/api-gateway/src/marketplace-entries/official/annotation.json +28 -0
  200. package/packages/api-gateway/src/marketplace-entries/official/archify.json +31 -0
  201. package/packages/api-gateway/src/marketplace-entries/official/at-file.json +28 -0
  202. package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +32 -0
  203. package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +32 -0
  204. package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +28 -0
  205. package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +29 -0
  206. package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +29 -0
  207. package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +30 -0
  208. package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +29 -0
  209. package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +30 -0
  210. package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +29 -0
  211. package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +30 -0
  212. package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +30 -0
  213. package/packages/api-gateway/src/marketplace-entries/official/context.json +28 -0
  214. package/packages/api-gateway/src/marketplace-entries/official/cordis-group.json +16 -0
  215. package/packages/api-gateway/src/marketplace-entries/official/cordis-logger-console.json +16 -0
  216. package/packages/api-gateway/src/marketplace-entries/official/cordis-timer.json +16 -0
  217. package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +31 -0
  218. package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +31 -0
  219. package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +29 -0
  220. package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +29 -0
  221. package/packages/api-gateway/src/marketplace-entries/official/genui.json +28 -0
  222. package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +30 -0
  223. package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +29 -0
  224. package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +33 -0
  225. package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +29 -0
  226. package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +29 -0
  227. package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +29 -0
  228. package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +32 -0
  229. package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +29 -0
  230. package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +29 -0
  231. package/packages/api-gateway/src/marketplace-entries/official/memory.json +28 -0
  232. package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +33 -0
  233. package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +29 -0
  234. package/packages/api-gateway/src/marketplace-entries/official/modlens.json +28 -0
  235. package/packages/api-gateway/src/marketplace-entries/official/module-search.json +30 -0
  236. package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +29 -0
  237. package/packages/api-gateway/src/marketplace-entries/official/openpets.json +29 -0
  238. package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +29 -0
  239. package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +29 -0
  240. package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +29 -0
  241. package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +32 -0
  242. package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +28 -0
  243. package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +29 -0
  244. package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +28 -0
  245. package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +30 -0
  246. package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +31 -0
  247. package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +29 -0
  248. package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +30 -0
  249. package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +29 -0
  250. package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +32 -0
  251. package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +30 -0
  252. package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +30 -0
  253. package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +30 -0
  254. package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +30 -0
  255. package/packages/api-gateway/src/marketplace-entries/official/session-export.json +30 -0
  256. package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +29 -0
  257. package/packages/api-gateway/src/marketplace-entries/official/session-search.json +30 -0
  258. package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +31 -0
  259. package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +29 -0
  260. package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +29 -0
  261. package/packages/api-gateway/src/marketplace-entries/official/synapse.json +28 -0
  262. package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +29 -0
  263. package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +29 -0
  264. package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +29 -0
  265. package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +29 -0
  266. package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +32 -0
  267. package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +32 -0
  268. package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +29 -0
  269. package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +28 -0
  270. package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +29 -0
  271. package/packages/api-gateway/src/marketplace-entries/official/web-research.json +29 -0
  272. package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +32 -0
  273. package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +29 -0
  274. package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +29 -0
  275. package/packages/api-gateway/src/marketplace.ts +267 -22
  276. package/packages/api-gateway/src/workspaces.ts +20 -0
  277. package/packages/api-gateway/test/index.test.ts +483 -33
  278. package/packages/api-gateway/test/marketplace.test.ts +282 -3
  279. package/packages/api-gateway/test/release-version.test.ts +71 -0
  280. package/packages/api-gateway/test/workspaces.test.ts +13 -0
  281. package/packages/api-gateway/tsconfig.build.json +1 -1
  282. package/packages/api-gateway/tsconfig.json +1 -1
  283. package/packages/bundle-web-app/LICENSE +9 -0
  284. package/packages/bundle-web-app/package.json +19 -9
  285. package/packages/bundle-web-app/tsconfig.build.json +1 -1
  286. package/packages/bundle-web-app/tsconfig.json +1 -1
  287. package/packages/cli/LICENSE +9 -0
  288. package/packages/cli/dist/args.d.ts.map +1 -1
  289. package/packages/cli/dist/args.js +16 -9
  290. package/packages/cli/dist/args.js.map +1 -1
  291. package/packages/cli/dist/bin.js +12 -3
  292. package/packages/cli/dist/bin.js.map +1 -1
  293. package/packages/cli/dist/main.d.ts +1 -0
  294. package/packages/cli/dist/main.d.ts.map +1 -1
  295. package/packages/cli/dist/main.js +49 -9
  296. package/packages/cli/dist/main.js.map +1 -1
  297. package/packages/cli/dist/node-stdio.d.ts +3 -1
  298. package/packages/cli/dist/node-stdio.d.ts.map +1 -1
  299. package/packages/cli/dist/node-stdio.js +91 -13
  300. package/packages/cli/dist/node-stdio.js.map +1 -1
  301. package/packages/cli/dist/relaunch.d.ts.map +1 -1
  302. package/packages/cli/dist/relaunch.js +23 -10
  303. package/packages/cli/dist/relaunch.js.map +1 -1
  304. package/packages/cli/package.json +18 -8
  305. package/packages/cli/src/args.ts +16 -10
  306. package/packages/cli/src/bin.ts +12 -3
  307. package/packages/cli/src/main.ts +54 -10
  308. package/packages/cli/src/node-stdio.ts +85 -13
  309. package/packages/cli/src/relaunch.ts +19 -6
  310. package/packages/cli/test/args.test.ts +22 -3
  311. package/packages/cli/test/binary.test.ts +58 -0
  312. package/packages/cli/test/broken-pipe.test.ts +32 -0
  313. package/packages/cli/test/cli.test.ts +57 -8
  314. package/packages/cli/test/node-stdio.test.ts +89 -0
  315. package/packages/cli/test/relaunch.test.ts +30 -2
  316. package/packages/cli/test/stdin-shutdown.test.ts +59 -0
  317. package/packages/cli/tsconfig.build.json +1 -3
  318. package/packages/cli/tsconfig.json +1 -4
  319. package/packages/client-web/LICENSE +9 -0
  320. package/packages/client-web/dist/annotation-ui.d.ts +11 -0
  321. package/packages/client-web/dist/annotation-ui.d.ts.map +1 -0
  322. package/packages/client-web/dist/annotation-ui.js +24 -0
  323. package/packages/client-web/dist/annotation-ui.js.map +1 -0
  324. package/packages/client-web/dist/browser-session-view.d.ts +7 -0
  325. package/packages/client-web/dist/browser-session-view.d.ts.map +1 -0
  326. package/packages/client-web/dist/browser-session-view.js +8 -0
  327. package/packages/client-web/dist/browser-session-view.js.map +1 -0
  328. package/packages/client-web/dist/control-room.d.ts +151 -6
  329. package/packages/client-web/dist/control-room.d.ts.map +1 -1
  330. package/packages/client-web/dist/control-room.js +156 -11
  331. package/packages/client-web/dist/control-room.js.map +1 -1
  332. package/packages/client-web/dist/design-contract.d.ts.map +1 -1
  333. package/packages/client-web/dist/design-contract.js +178 -19
  334. package/packages/client-web/dist/design-contract.js.map +1 -1
  335. package/packages/client-web/dist/index.d.ts +4 -1
  336. package/packages/client-web/dist/index.d.ts.map +1 -1
  337. package/packages/client-web/dist/index.js +11 -3
  338. package/packages/client-web/dist/index.js.map +1 -1
  339. package/packages/client-web/dist/markdown.d.ts +5 -0
  340. package/packages/client-web/dist/markdown.d.ts.map +1 -0
  341. package/packages/client-web/dist/markdown.js +20 -0
  342. package/packages/client-web/dist/markdown.js.map +1 -0
  343. package/packages/client-web/dist/marketplace-catalog.d.ts +3 -0
  344. package/packages/client-web/dist/marketplace-catalog.d.ts.map +1 -0
  345. package/packages/client-web/dist/marketplace-catalog.js +10 -0
  346. package/packages/client-web/dist/marketplace-catalog.js.map +1 -0
  347. package/packages/client-web/dist/marketplace-navigation.d.ts +19 -0
  348. package/packages/client-web/dist/marketplace-navigation.d.ts.map +1 -0
  349. package/packages/client-web/dist/marketplace-navigation.js +31 -0
  350. package/packages/client-web/dist/marketplace-navigation.js.map +1 -0
  351. package/packages/client-web/dist/message-content.d.ts +9 -0
  352. package/packages/client-web/dist/message-content.d.ts.map +1 -0
  353. package/packages/client-web/dist/message-content.js +54 -0
  354. package/packages/client-web/dist/message-content.js.map +1 -0
  355. package/packages/client-web/dist/plugin-navigation.d.ts +3 -0
  356. package/packages/client-web/dist/plugin-navigation.d.ts.map +1 -0
  357. package/packages/client-web/dist/plugin-navigation.js +10 -0
  358. package/packages/client-web/dist/plugin-navigation.js.map +1 -0
  359. package/packages/client-web/dist/plugin-search.d.ts +2 -0
  360. package/packages/client-web/dist/plugin-search.d.ts.map +1 -0
  361. package/packages/client-web/dist/plugin-search.js +7 -0
  362. package/packages/client-web/dist/plugin-search.js.map +1 -0
  363. package/packages/client-web/dist/plugin-stars-view.d.ts +12 -0
  364. package/packages/client-web/dist/plugin-stars-view.d.ts.map +1 -0
  365. package/packages/client-web/dist/plugin-stars-view.js +8 -0
  366. package/packages/client-web/dist/plugin-stars-view.js.map +1 -0
  367. package/packages/client-web/dist/prompt-completion.d.ts +13 -0
  368. package/packages/client-web/dist/prompt-completion.d.ts.map +1 -0
  369. package/packages/client-web/dist/prompt-completion.js +17 -0
  370. package/packages/client-web/dist/prompt-completion.js.map +1 -0
  371. package/packages/client-web/dist/react-room.d.ts +2 -1
  372. package/packages/client-web/dist/react-room.d.ts.map +1 -1
  373. package/packages/client-web/dist/react-room.js +2347 -93
  374. package/packages/client-web/dist/react-room.js.map +1 -1
  375. package/packages/client-web/dist/runtime-events.d.ts +4 -0
  376. package/packages/client-web/dist/runtime-events.d.ts.map +1 -0
  377. package/packages/client-web/dist/runtime-events.js +29 -0
  378. package/packages/client-web/dist/runtime-events.js.map +1 -0
  379. package/packages/client-web/package.json +19 -7
  380. package/packages/client-web/src/annotation-ui.ts +29 -0
  381. package/packages/client-web/src/browser-session-view.ts +13 -0
  382. package/packages/client-web/src/control-room.ts +359 -11
  383. package/packages/client-web/src/design-contract.ts +248 -26
  384. package/packages/client-web/src/index.ts +17 -4
  385. package/packages/client-web/src/markdown.tsx +22 -0
  386. package/packages/client-web/src/marketplace-catalog.ts +10 -0
  387. package/packages/client-web/src/marketplace-navigation.ts +46 -0
  388. package/packages/client-web/src/message-content.ts +51 -0
  389. package/packages/client-web/src/plugin-navigation.ts +9 -0
  390. package/packages/client-web/src/plugin-search.ts +5 -0
  391. package/packages/client-web/src/plugin-stars-view.ts +19 -0
  392. package/packages/client-web/src/prompt-completion.ts +24 -0
  393. package/packages/client-web/src/react-room.tsx +7360 -54
  394. package/packages/client-web/src/runtime-events.ts +29 -0
  395. package/packages/client-web/test/annotation-ui.test.ts +21 -0
  396. package/packages/client-web/test/browser-session-view.test.ts +17 -0
  397. package/packages/client-web/test/design-contract.test.ts +46 -1
  398. package/packages/client-web/test/marketplace-catalog.test.ts +52 -0
  399. package/packages/client-web/test/message-content.test.ts +43 -0
  400. package/packages/client-web/test/plugin-navigation.test.ts +16 -0
  401. package/packages/client-web/test/plugin-search.test.ts +22 -0
  402. package/packages/client-web/test/plugin-stars-view.test.ts +20 -0
  403. package/packages/client-web/test/prompt-completion.test.ts +21 -0
  404. package/packages/client-web/test/runtime-events.test.ts +28 -0
  405. package/packages/client-web/tsconfig.build.json +13 -1
  406. package/packages/client-web/tsconfig.json +11 -1
  407. package/packages/core/LICENSE +9 -0
  408. package/packages/core/dist/boot.d.ts.map +1 -1
  409. package/packages/core/dist/boot.js +42 -3
  410. package/packages/core/dist/boot.js.map +1 -1
  411. package/packages/core/dist/config.d.ts +2 -0
  412. package/packages/core/dist/config.d.ts.map +1 -0
  413. package/packages/core/dist/config.js +8 -0
  414. package/packages/core/dist/config.js.map +1 -0
  415. package/packages/core/dist/http.d.ts +8 -0
  416. package/packages/core/dist/http.d.ts.map +1 -0
  417. package/packages/core/dist/http.js +27 -0
  418. package/packages/core/dist/http.js.map +1 -0
  419. package/packages/core/dist/index.d.ts +2 -0
  420. package/packages/core/dist/index.d.ts.map +1 -1
  421. package/packages/core/dist/index.js +2 -0
  422. package/packages/core/dist/index.js.map +1 -1
  423. package/packages/core/dist/plugins/agent-teams.d.ts +17 -0
  424. package/packages/core/dist/plugins/agent-teams.d.ts.map +1 -0
  425. package/packages/core/dist/plugins/agent-teams.js +298 -0
  426. package/packages/core/dist/plugins/agent-teams.js.map +1 -0
  427. package/packages/core/dist/plugins/anchored-standard.d.ts +14 -0
  428. package/packages/core/dist/plugins/anchored-standard.d.ts.map +1 -0
  429. package/packages/core/dist/plugins/anchored-standard.js +84 -0
  430. package/packages/core/dist/plugins/anchored-standard.js.map +1 -0
  431. package/packages/core/dist/plugins/annotation.d.ts +18 -0
  432. package/packages/core/dist/plugins/annotation.d.ts.map +1 -0
  433. package/packages/core/dist/plugins/annotation.js +94 -0
  434. package/packages/core/dist/plugins/annotation.js.map +1 -0
  435. package/packages/core/dist/plugins/archify.d.ts +23 -0
  436. package/packages/core/dist/plugins/archify.d.ts.map +1 -0
  437. package/packages/core/dist/plugins/archify.js +98 -0
  438. package/packages/core/dist/plugins/archify.js.map +1 -0
  439. package/packages/core/dist/plugins/at-file.d.ts +8 -0
  440. package/packages/core/dist/plugins/at-file.d.ts.map +1 -0
  441. package/packages/core/dist/plugins/at-file.js +52 -0
  442. package/packages/core/dist/plugins/at-file.js.map +1 -0
  443. package/packages/core/dist/plugins/auto-mode.d.ts +15 -0
  444. package/packages/core/dist/plugins/auto-mode.d.ts.map +1 -0
  445. package/packages/core/dist/plugins/auto-mode.js +114 -0
  446. package/packages/core/dist/plugins/auto-mode.js.map +1 -0
  447. package/packages/core/dist/plugins/better-sidebar.d.ts +37 -0
  448. package/packages/core/dist/plugins/better-sidebar.d.ts.map +1 -0
  449. package/packages/core/dist/plugins/better-sidebar.js +89 -0
  450. package/packages/core/dist/plugins/better-sidebar.js.map +1 -0
  451. package/packages/core/dist/plugins/browser-fetch.d.ts +14 -0
  452. package/packages/core/dist/plugins/browser-fetch.d.ts.map +1 -0
  453. package/packages/core/dist/plugins/browser-fetch.js +167 -0
  454. package/packages/core/dist/plugins/browser-fetch.js.map +1 -0
  455. package/packages/core/dist/plugins/browser-session.d.ts +14 -0
  456. package/packages/core/dist/plugins/browser-session.d.ts.map +1 -0
  457. package/packages/core/dist/plugins/browser-session.js +265 -0
  458. package/packages/core/dist/plugins/browser-session.js.map +1 -0
  459. package/packages/core/dist/plugins/canvas-draw.d.ts +8 -0
  460. package/packages/core/dist/plugins/canvas-draw.d.ts.map +1 -0
  461. package/packages/core/dist/plugins/canvas-draw.js +88 -0
  462. package/packages/core/dist/plugins/canvas-draw.js.map +1 -0
  463. package/packages/core/dist/plugins/change-verifier.d.ts +8 -0
  464. package/packages/core/dist/plugins/change-verifier.d.ts.map +1 -0
  465. package/packages/core/dist/plugins/change-verifier.js +67 -0
  466. package/packages/core/dist/plugins/change-verifier.js.map +1 -0
  467. package/packages/core/dist/plugins/cleaner.d.ts +8 -0
  468. package/packages/core/dist/plugins/cleaner.d.ts.map +1 -0
  469. package/packages/core/dist/plugins/cleaner.js +56 -0
  470. package/packages/core/dist/plugins/cleaner.js.map +1 -0
  471. package/packages/core/dist/plugins/cli-notifier.d.ts +15 -0
  472. package/packages/core/dist/plugins/cli-notifier.d.ts.map +1 -0
  473. package/packages/core/dist/plugins/cli-notifier.js +110 -0
  474. package/packages/core/dist/plugins/cli-notifier.js.map +1 -0
  475. package/packages/core/dist/plugins/code2skill.d.ts +8 -0
  476. package/packages/core/dist/plugins/code2skill.d.ts.map +1 -0
  477. package/packages/core/dist/plugins/code2skill.js +95 -0
  478. package/packages/core/dist/plugins/code2skill.js.map +1 -0
  479. package/packages/core/dist/plugins/colleague-skill.d.ts +27 -0
  480. package/packages/core/dist/plugins/colleague-skill.d.ts.map +1 -0
  481. package/packages/core/dist/plugins/colleague-skill.js +99 -0
  482. package/packages/core/dist/plugins/colleague-skill.js.map +1 -0
  483. package/packages/core/dist/plugins/context-doctor.d.ts +30 -0
  484. package/packages/core/dist/plugins/context-doctor.d.ts.map +1 -0
  485. package/packages/core/dist/plugins/context-doctor.js +95 -0
  486. package/packages/core/dist/plugins/context-doctor.js.map +1 -0
  487. package/packages/core/dist/plugins/context.d.ts +8 -0
  488. package/packages/core/dist/plugins/context.d.ts.map +1 -0
  489. package/packages/core/dist/plugins/context.js +87 -0
  490. package/packages/core/dist/plugins/context.js.map +1 -0
  491. package/packages/core/dist/plugins/cost-meter.d.ts +32 -0
  492. package/packages/core/dist/plugins/cost-meter.d.ts.map +1 -0
  493. package/packages/core/dist/plugins/cost-meter.js +204 -0
  494. package/packages/core/dist/plugins/cost-meter.js.map +1 -0
  495. package/packages/core/dist/plugins/dependency-checker.d.ts +27 -0
  496. package/packages/core/dist/plugins/dependency-checker.d.ts.map +1 -0
  497. package/packages/core/dist/plugins/dependency-checker.js +221 -0
  498. package/packages/core/dist/plugins/dependency-checker.js.map +1 -0
  499. package/packages/core/dist/plugins/docker-sandbox.d.ts +8 -0
  500. package/packages/core/dist/plugins/docker-sandbox.d.ts.map +1 -0
  501. package/packages/core/dist/plugins/docker-sandbox.js +102 -0
  502. package/packages/core/dist/plugins/docker-sandbox.js.map +1 -0
  503. package/packages/core/dist/plugins/fail-logger.d.ts +8 -0
  504. package/packages/core/dist/plugins/fail-logger.d.ts.map +1 -0
  505. package/packages/core/dist/plugins/fail-logger.js +51 -0
  506. package/packages/core/dist/plugins/fail-logger.js.map +1 -0
  507. package/packages/core/dist/plugins/genui.d.ts +8 -0
  508. package/packages/core/dist/plugins/genui.d.ts.map +1 -0
  509. package/packages/core/dist/plugins/genui.js +79 -0
  510. package/packages/core/dist/plugins/genui.js.map +1 -0
  511. package/packages/core/dist/plugins/git-time-capsule.d.ts +9 -0
  512. package/packages/core/dist/plugins/git-time-capsule.d.ts.map +1 -0
  513. package/packages/core/dist/plugins/git-time-capsule.js +90 -0
  514. package/packages/core/dist/plugins/git-time-capsule.js.map +1 -0
  515. package/packages/core/dist/plugins/graph-memory.d.ts +16 -0
  516. package/packages/core/dist/plugins/graph-memory.d.ts.map +1 -0
  517. package/packages/core/dist/plugins/graph-memory.js +382 -0
  518. package/packages/core/dist/plugins/graph-memory.js.map +1 -0
  519. package/packages/core/dist/plugins/history-compressor.d.ts +15 -0
  520. package/packages/core/dist/plugins/history-compressor.d.ts.map +1 -0
  521. package/packages/core/dist/plugins/history-compressor.js +80 -0
  522. package/packages/core/dist/plugins/history-compressor.js.map +1 -0
  523. package/packages/core/dist/plugins/hol-guard.d.ts +29 -0
  524. package/packages/core/dist/plugins/hol-guard.d.ts.map +1 -0
  525. package/packages/core/dist/plugins/hol-guard.js +139 -0
  526. package/packages/core/dist/plugins/hol-guard.js.map +1 -0
  527. package/packages/core/dist/plugins/i18n-pair.d.ts +8 -0
  528. package/packages/core/dist/plugins/i18n-pair.d.ts.map +1 -0
  529. package/packages/core/dist/plugins/i18n-pair.js +76 -0
  530. package/packages/core/dist/plugins/i18n-pair.js.map +1 -0
  531. package/packages/core/dist/plugins/image-compressor.d.ts +8 -0
  532. package/packages/core/dist/plugins/image-compressor.d.ts.map +1 -0
  533. package/packages/core/dist/plugins/image-compressor.js +150 -0
  534. package/packages/core/dist/plugins/image-compressor.js.map +1 -0
  535. package/packages/core/dist/plugins/llm-verifier.d.ts +42 -0
  536. package/packages/core/dist/plugins/llm-verifier.d.ts.map +1 -0
  537. package/packages/core/dist/plugins/llm-verifier.js +128 -0
  538. package/packages/core/dist/plugins/llm-verifier.js.map +1 -0
  539. package/packages/core/dist/plugins/mcp-client.d.ts +19 -0
  540. package/packages/core/dist/plugins/mcp-client.d.ts.map +1 -0
  541. package/packages/core/dist/plugins/mcp-client.js +534 -0
  542. package/packages/core/dist/plugins/mcp-client.js.map +1 -0
  543. package/packages/core/dist/plugins/mcp-panel.d.ts +14 -0
  544. package/packages/core/dist/plugins/mcp-panel.d.ts.map +1 -0
  545. package/packages/core/dist/plugins/mcp-panel.js +180 -0
  546. package/packages/core/dist/plugins/mcp-panel.js.map +1 -0
  547. package/packages/core/dist/plugins/memory.d.ts +15 -0
  548. package/packages/core/dist/plugins/memory.d.ts.map +1 -0
  549. package/packages/core/dist/plugins/memory.js +161 -0
  550. package/packages/core/dist/plugins/memory.js.map +1 -0
  551. package/packages/core/dist/plugins/mirage-bridge.d.ts +23 -0
  552. package/packages/core/dist/plugins/mirage-bridge.d.ts.map +1 -0
  553. package/packages/core/dist/plugins/mirage-bridge.js +149 -0
  554. package/packages/core/dist/plugins/mirage-bridge.js.map +1 -0
  555. package/packages/core/dist/plugins/mock-server.d.ts +22 -0
  556. package/packages/core/dist/plugins/mock-server.d.ts.map +1 -0
  557. package/packages/core/dist/plugins/mock-server.js +149 -0
  558. package/packages/core/dist/plugins/mock-server.js.map +1 -0
  559. package/packages/core/dist/plugins/model.d.ts +1 -1
  560. package/packages/core/dist/plugins/model.d.ts.map +1 -1
  561. package/packages/core/dist/plugins/model.js +3 -1
  562. package/packages/core/dist/plugins/model.js.map +1 -1
  563. package/packages/core/dist/plugins/models.d.ts.map +1 -1
  564. package/packages/core/dist/plugins/models.js +5 -2
  565. package/packages/core/dist/plugins/models.js.map +1 -1
  566. package/packages/core/dist/plugins/modlens.d.ts +8 -0
  567. package/packages/core/dist/plugins/modlens.d.ts.map +1 -0
  568. package/packages/core/dist/plugins/modlens.js +63 -0
  569. package/packages/core/dist/plugins/modlens.js.map +1 -0
  570. package/packages/core/dist/plugins/module-search.d.ts +27 -0
  571. package/packages/core/dist/plugins/module-search.d.ts.map +1 -0
  572. package/packages/core/dist/plugins/module-search.js +174 -0
  573. package/packages/core/dist/plugins/module-search.js.map +1 -0
  574. package/packages/core/dist/plugins/obsidian-sync.d.ts +14 -0
  575. package/packages/core/dist/plugins/obsidian-sync.d.ts.map +1 -0
  576. package/packages/core/dist/plugins/obsidian-sync.js +79 -0
  577. package/packages/core/dist/plugins/obsidian-sync.js.map +1 -0
  578. package/packages/core/dist/plugins/openpets.d.ts +14 -0
  579. package/packages/core/dist/plugins/openpets.d.ts.map +1 -0
  580. package/packages/core/dist/plugins/openpets.js +99 -0
  581. package/packages/core/dist/plugins/openpets.js.map +1 -0
  582. package/packages/core/dist/plugins/plan-execute.d.ts +8 -0
  583. package/packages/core/dist/plugins/plan-execute.d.ts.map +1 -0
  584. package/packages/core/dist/plugins/plan-execute.js +70 -0
  585. package/packages/core/dist/plugins/plan-execute.js.map +1 -0
  586. package/packages/core/dist/plugins/plugin-check.d.ts +38 -0
  587. package/packages/core/dist/plugins/plugin-check.d.ts.map +1 -0
  588. package/packages/core/dist/plugins/plugin-check.js +227 -0
  589. package/packages/core/dist/plugins/plugin-check.js.map +1 -0
  590. package/packages/core/dist/plugins/plugin-dev.d.ts +8 -0
  591. package/packages/core/dist/plugins/plugin-dev.d.ts.map +1 -0
  592. package/packages/core/dist/plugins/plugin-dev.js +44 -0
  593. package/packages/core/dist/plugins/plugin-dev.js.map +1 -0
  594. package/packages/core/dist/plugins/plugin-finder.d.ts +16 -0
  595. package/packages/core/dist/plugins/plugin-finder.d.ts.map +1 -0
  596. package/packages/core/dist/plugins/plugin-finder.js +98 -0
  597. package/packages/core/dist/plugins/plugin-finder.js.map +1 -0
  598. package/packages/core/dist/plugins/plugin-radar.d.ts +29 -0
  599. package/packages/core/dist/plugins/plugin-radar.d.ts.map +1 -0
  600. package/packages/core/dist/plugins/plugin-radar.js +146 -0
  601. package/packages/core/dist/plugins/plugin-radar.js.map +1 -0
  602. package/packages/core/dist/plugins/plugin-stars.d.ts +45 -0
  603. package/packages/core/dist/plugins/plugin-stars.d.ts.map +1 -0
  604. package/packages/core/dist/plugins/plugin-stars.js +165 -0
  605. package/packages/core/dist/plugins/plugin-stars.js.map +1 -0
  606. package/packages/core/dist/plugins/prompt-guard.d.ts +8 -0
  607. package/packages/core/dist/plugins/prompt-guard.d.ts.map +1 -0
  608. package/packages/core/dist/plugins/prompt-guard.js +114 -0
  609. package/packages/core/dist/plugins/prompt-guard.js.map +1 -0
  610. package/packages/core/dist/plugins/prompt-library.d.ts +25 -0
  611. package/packages/core/dist/plugins/prompt-library.d.ts.map +1 -0
  612. package/packages/core/dist/plugins/prompt-library.js +142 -0
  613. package/packages/core/dist/plugins/prompt-library.js.map +1 -0
  614. package/packages/core/dist/plugins/readme-gen.d.ts +25 -0
  615. package/packages/core/dist/plugins/readme-gen.d.ts.map +1 -0
  616. package/packages/core/dist/plugins/readme-gen.js +139 -0
  617. package/packages/core/dist/plugins/readme-gen.js.map +1 -0
  618. package/packages/core/dist/plugins/recall-unread.d.ts +24 -0
  619. package/packages/core/dist/plugins/recall-unread.d.ts.map +1 -0
  620. package/packages/core/dist/plugins/recall-unread.js +124 -0
  621. package/packages/core/dist/plugins/recall-unread.js.map +1 -0
  622. package/packages/core/dist/plugins/resources.d.ts +1 -0
  623. package/packages/core/dist/plugins/resources.d.ts.map +1 -1
  624. package/packages/core/dist/plugins/resources.js +31 -22
  625. package/packages/core/dist/plugins/resources.js.map +1 -1
  626. package/packages/core/dist/plugins/reverse-skill.d.ts +23 -0
  627. package/packages/core/dist/plugins/reverse-skill.d.ts.map +1 -0
  628. package/packages/core/dist/plugins/reverse-skill.js +60 -0
  629. package/packages/core/dist/plugins/reverse-skill.js.map +1 -0
  630. package/packages/core/dist/plugins/reviewer-bot.d.ts +14 -0
  631. package/packages/core/dist/plugins/reviewer-bot.d.ts.map +1 -0
  632. package/packages/core/dist/plugins/reviewer-bot.js +133 -0
  633. package/packages/core/dist/plugins/reviewer-bot.js.map +1 -0
  634. package/packages/core/dist/plugins/runtime-doctor.d.ts +33 -0
  635. package/packages/core/dist/plugins/runtime-doctor.d.ts.map +1 -0
  636. package/packages/core/dist/plugins/runtime-doctor.js +114 -0
  637. package/packages/core/dist/plugins/runtime-doctor.js.map +1 -0
  638. package/packages/core/dist/plugins/runtime.d.ts.map +1 -1
  639. package/packages/core/dist/plugins/runtime.js +63 -14
  640. package/packages/core/dist/plugins/runtime.js.map +1 -1
  641. package/packages/core/dist/plugins/secure-audit.d.ts +31 -0
  642. package/packages/core/dist/plugins/secure-audit.d.ts.map +1 -0
  643. package/packages/core/dist/plugins/secure-audit.js +121 -0
  644. package/packages/core/dist/plugins/secure-audit.js.map +1 -0
  645. package/packages/core/dist/plugins/session-bookmarks.d.ts +15 -0
  646. package/packages/core/dist/plugins/session-bookmarks.d.ts.map +1 -0
  647. package/packages/core/dist/plugins/session-bookmarks.js +87 -0
  648. package/packages/core/dist/plugins/session-bookmarks.js.map +1 -0
  649. package/packages/core/dist/plugins/session-bridge.d.ts +44 -0
  650. package/packages/core/dist/plugins/session-bridge.d.ts.map +1 -0
  651. package/packages/core/dist/plugins/session-bridge.js +265 -0
  652. package/packages/core/dist/plugins/session-bridge.js.map +1 -0
  653. package/packages/core/dist/plugins/session-compare.d.ts +33 -0
  654. package/packages/core/dist/plugins/session-compare.d.ts.map +1 -0
  655. package/packages/core/dist/plugins/session-compare.js +150 -0
  656. package/packages/core/dist/plugins/session-compare.js.map +1 -0
  657. package/packages/core/dist/plugins/session-export.d.ts +9 -0
  658. package/packages/core/dist/plugins/session-export.d.ts.map +1 -0
  659. package/packages/core/dist/plugins/session-export.js +93 -0
  660. package/packages/core/dist/plugins/session-export.js.map +1 -0
  661. package/packages/core/dist/plugins/session-insights.d.ts +8 -0
  662. package/packages/core/dist/plugins/session-insights.d.ts.map +1 -0
  663. package/packages/core/dist/plugins/session-insights.js +47 -0
  664. package/packages/core/dist/plugins/session-insights.js.map +1 -0
  665. package/packages/core/dist/plugins/session-search.d.ts +20 -0
  666. package/packages/core/dist/plugins/session-search.d.ts.map +1 -0
  667. package/packages/core/dist/plugins/session-search.js +122 -0
  668. package/packages/core/dist/plugins/session-search.js.map +1 -0
  669. package/packages/core/dist/plugins/session.d.ts.map +1 -1
  670. package/packages/core/dist/plugins/session.js +4 -2
  671. package/packages/core/dist/plugins/session.js.map +1 -1
  672. package/packages/core/dist/plugins/skill-catalog.d.ts +26 -0
  673. package/packages/core/dist/plugins/skill-catalog.d.ts.map +1 -0
  674. package/packages/core/dist/plugins/skill-catalog.js +97 -0
  675. package/packages/core/dist/plugins/skill-catalog.js.map +1 -0
  676. package/packages/core/dist/plugins/skill-guard.d.ts +26 -0
  677. package/packages/core/dist/plugins/skill-guard.d.ts.map +1 -0
  678. package/packages/core/dist/plugins/skill-guard.js +139 -0
  679. package/packages/core/dist/plugins/skill-guard.js.map +1 -0
  680. package/packages/core/dist/plugins/sql-lens.d.ts +8 -0
  681. package/packages/core/dist/plugins/sql-lens.d.ts.map +1 -0
  682. package/packages/core/dist/plugins/sql-lens.js +85 -0
  683. package/packages/core/dist/plugins/sql-lens.js.map +1 -0
  684. package/packages/core/dist/plugins/stdio.d.ts +1 -1
  685. package/packages/core/dist/plugins/stdio.d.ts.map +1 -1
  686. package/packages/core/dist/plugins/stdio.js +3 -1
  687. package/packages/core/dist/plugins/stdio.js.map +1 -1
  688. package/packages/core/dist/plugins/synapse.d.ts +38 -0
  689. package/packages/core/dist/plugins/synapse.d.ts.map +1 -0
  690. package/packages/core/dist/plugins/synapse.js +93 -0
  691. package/packages/core/dist/plugins/synapse.js.map +1 -0
  692. package/packages/core/dist/plugins/tab-manager.d.ts +8 -0
  693. package/packages/core/dist/plugins/tab-manager.d.ts.map +1 -0
  694. package/packages/core/dist/plugins/tab-manager.js +135 -0
  695. package/packages/core/dist/plugins/tab-manager.js.map +1 -0
  696. package/packages/core/dist/plugins/taskboard.d.ts +15 -0
  697. package/packages/core/dist/plugins/taskboard.d.ts.map +1 -0
  698. package/packages/core/dist/plugins/taskboard.js +347 -0
  699. package/packages/core/dist/plugins/taskboard.js.map +1 -0
  700. package/packages/core/dist/plugins/telemetry-blocker.d.ts +8 -0
  701. package/packages/core/dist/plugins/telemetry-blocker.d.ts.map +1 -0
  702. package/packages/core/dist/plugins/telemetry-blocker.js +57 -0
  703. package/packages/core/dist/plugins/telemetry-blocker.js.map +1 -0
  704. package/packages/core/dist/plugins/test-harness.d.ts +8 -0
  705. package/packages/core/dist/plugins/test-harness.d.ts.map +1 -0
  706. package/packages/core/dist/plugins/test-harness.js +64 -0
  707. package/packages/core/dist/plugins/test-harness.js.map +1 -0
  708. package/packages/core/dist/plugins/theme-studio.d.ts +29 -0
  709. package/packages/core/dist/plugins/theme-studio.d.ts.map +1 -0
  710. package/packages/core/dist/plugins/theme-studio.js +141 -0
  711. package/packages/core/dist/plugins/theme-studio.js.map +1 -0
  712. package/packages/core/dist/plugins/token-guard.d.ts +15 -0
  713. package/packages/core/dist/plugins/token-guard.d.ts.map +1 -0
  714. package/packages/core/dist/plugins/token-guard.js +78 -0
  715. package/packages/core/dist/plugins/token-guard.js.map +1 -0
  716. package/packages/core/dist/plugins/tools.d.ts.map +1 -1
  717. package/packages/core/dist/plugins/tools.js +5 -2
  718. package/packages/core/dist/plugins/tools.js.map +1 -1
  719. package/packages/core/dist/plugins/turn-rewind.d.ts +19 -0
  720. package/packages/core/dist/plugins/turn-rewind.d.ts.map +1 -0
  721. package/packages/core/dist/plugins/turn-rewind.js +74 -0
  722. package/packages/core/dist/plugins/turn-rewind.js.map +1 -0
  723. package/packages/core/dist/plugins/undo-savepoint.d.ts +17 -0
  724. package/packages/core/dist/plugins/undo-savepoint.d.ts.map +1 -0
  725. package/packages/core/dist/plugins/undo-savepoint.js +247 -0
  726. package/packages/core/dist/plugins/undo-savepoint.js.map +1 -0
  727. package/packages/core/dist/plugins/vision-toolkit.d.ts +17 -0
  728. package/packages/core/dist/plugins/vision-toolkit.d.ts.map +1 -0
  729. package/packages/core/dist/plugins/vision-toolkit.js +145 -0
  730. package/packages/core/dist/plugins/vision-toolkit.js.map +1 -0
  731. package/packages/core/dist/plugins/web-research.d.ts +17 -0
  732. package/packages/core/dist/plugins/web-research.d.ts.map +1 -0
  733. package/packages/core/dist/plugins/web-research.js +275 -0
  734. package/packages/core/dist/plugins/web-research.js.map +1 -0
  735. package/packages/core/dist/plugins/workspace-navigator.d.ts +36 -0
  736. package/packages/core/dist/plugins/workspace-navigator.d.ts.map +1 -0
  737. package/packages/core/dist/plugins/workspace-navigator.js +150 -0
  738. package/packages/core/dist/plugins/workspace-navigator.js.map +1 -0
  739. package/packages/core/dist/plugins/workspace-search.d.ts +8 -0
  740. package/packages/core/dist/plugins/workspace-search.d.ts.map +1 -0
  741. package/packages/core/dist/plugins/workspace-search.js +134 -0
  742. package/packages/core/dist/plugins/workspace-search.js.map +1 -0
  743. package/packages/core/dist/plugins/yaml-validator.d.ts +8 -0
  744. package/packages/core/dist/plugins/yaml-validator.d.ts.map +1 -0
  745. package/packages/core/dist/plugins/yaml-validator.js +94 -0
  746. package/packages/core/dist/plugins/yaml-validator.js.map +1 -0
  747. package/packages/core/dist/profile.d.ts +1 -0
  748. package/packages/core/dist/profile.d.ts.map +1 -1
  749. package/packages/core/dist/profile.js +3 -0
  750. package/packages/core/dist/profile.js.map +1 -1
  751. package/packages/core/dist/runtime.d.ts.map +1 -1
  752. package/packages/core/dist/runtime.js +13 -4
  753. package/packages/core/dist/runtime.js.map +1 -1
  754. package/packages/core/dist/services.d.ts +55 -0
  755. package/packages/core/dist/services.d.ts.map +1 -1
  756. package/packages/core/dist/services.js +58 -2
  757. package/packages/core/dist/services.js.map +1 -1
  758. package/packages/core/dist/stdio.d.ts +13 -2
  759. package/packages/core/dist/stdio.d.ts.map +1 -1
  760. package/packages/core/dist/stdio.js +75 -9
  761. package/packages/core/dist/stdio.js.map +1 -1
  762. package/packages/core/dist/workspace-path.d.ts +12 -0
  763. package/packages/core/dist/workspace-path.d.ts.map +1 -0
  764. package/packages/core/dist/workspace-path.js +62 -0
  765. package/packages/core/dist/workspace-path.js.map +1 -0
  766. package/packages/core/package.json +18 -8
  767. package/packages/core/profiles/default/cordis.yml +85 -0
  768. package/packages/core/profiles/development/cordis.yml +1 -1
  769. package/packages/core/src/boot.ts +38 -2
  770. package/packages/core/src/config.ts +5 -0
  771. package/packages/core/src/http.ts +32 -0
  772. package/packages/core/src/index.ts +2 -0
  773. package/packages/core/src/plugins/agent-teams.ts +291 -0
  774. package/packages/core/src/plugins/anchored-standard.ts +88 -0
  775. package/packages/core/src/plugins/annotation.ts +106 -0
  776. package/packages/core/src/plugins/archify.ts +124 -0
  777. package/packages/core/src/plugins/at-file.ts +54 -0
  778. package/packages/core/src/plugins/auto-mode.ts +123 -0
  779. package/packages/core/src/plugins/better-sidebar.ts +117 -0
  780. package/packages/core/src/plugins/browser-fetch.ts +171 -0
  781. package/packages/core/src/plugins/browser-session.ts +287 -0
  782. package/packages/core/src/plugins/canvas-draw.ts +90 -0
  783. package/packages/core/src/plugins/change-verifier.ts +79 -0
  784. package/packages/core/src/plugins/cleaner.ts +61 -0
  785. package/packages/core/src/plugins/cli-notifier.ts +125 -0
  786. package/packages/core/src/plugins/code2skill.ts +96 -0
  787. package/packages/core/src/plugins/colleague-skill.ts +122 -0
  788. package/packages/core/src/plugins/context-doctor.ts +117 -0
  789. package/packages/core/src/plugins/context.ts +102 -0
  790. package/packages/core/src/plugins/cost-meter.ts +231 -0
  791. package/packages/core/src/plugins/dependency-checker.ts +241 -0
  792. package/packages/core/src/plugins/docker-sandbox.ts +100 -0
  793. package/packages/core/src/plugins/fail-logger.ts +51 -0
  794. package/packages/core/src/plugins/genui.ts +88 -0
  795. package/packages/core/src/plugins/git-time-capsule.ts +97 -0
  796. package/packages/core/src/plugins/graph-memory.ts +394 -0
  797. package/packages/core/src/plugins/history-compressor.ts +81 -0
  798. package/packages/core/src/plugins/hol-guard.ts +153 -0
  799. package/packages/core/src/plugins/i18n-pair.ts +82 -0
  800. package/packages/core/src/plugins/image-compressor.ts +144 -0
  801. package/packages/core/src/plugins/llm-verifier.ts +164 -0
  802. package/packages/core/src/plugins/mcp-client.ts +559 -0
  803. package/packages/core/src/plugins/mcp-panel.ts +190 -0
  804. package/packages/core/src/plugins/memory.ts +176 -0
  805. package/packages/core/src/plugins/mirage-bridge.ts +179 -0
  806. package/packages/core/src/plugins/mock-server.ts +158 -0
  807. package/packages/core/src/plugins/model.ts +3 -1
  808. package/packages/core/src/plugins/models.ts +5 -2
  809. package/packages/core/src/plugins/modlens.ts +63 -0
  810. package/packages/core/src/plugins/module-search.ts +201 -0
  811. package/packages/core/src/plugins/obsidian-sync.ts +83 -0
  812. package/packages/core/src/plugins/openpets.ts +109 -0
  813. package/packages/core/src/plugins/plan-execute.ts +76 -0
  814. package/packages/core/src/plugins/plugin-check.ts +232 -0
  815. package/packages/core/src/plugins/plugin-dev.ts +47 -0
  816. package/packages/core/src/plugins/plugin-finder.ts +108 -0
  817. package/packages/core/src/plugins/plugin-radar.ts +179 -0
  818. package/packages/core/src/plugins/plugin-stars.ts +205 -0
  819. package/packages/core/src/plugins/prompt-guard.ts +122 -0
  820. package/packages/core/src/plugins/prompt-library.ts +165 -0
  821. package/packages/core/src/plugins/readme-gen.ts +147 -0
  822. package/packages/core/src/plugins/recall-unread.ts +142 -0
  823. package/packages/core/src/plugins/resources.ts +28 -21
  824. package/packages/core/src/plugins/reverse-skill.ts +79 -0
  825. package/packages/core/src/plugins/reviewer-bot.ts +146 -0
  826. package/packages/core/src/plugins/runtime-doctor.ts +137 -0
  827. package/packages/core/src/plugins/runtime.ts +61 -14
  828. package/packages/core/src/plugins/secure-audit.ts +146 -0
  829. package/packages/core/src/plugins/session-bookmarks.ts +89 -0
  830. package/packages/core/src/plugins/session-bridge.ts +299 -0
  831. package/packages/core/src/plugins/session-compare.ts +180 -0
  832. package/packages/core/src/plugins/session-export.ts +99 -0
  833. package/packages/core/src/plugins/session-insights.ts +47 -0
  834. package/packages/core/src/plugins/session-search.ts +126 -0
  835. package/packages/core/src/plugins/session.ts +4 -2
  836. package/packages/core/src/plugins/skill-catalog.ts +117 -0
  837. package/packages/core/src/plugins/skill-guard.ts +152 -0
  838. package/packages/core/src/plugins/sql-lens.ts +92 -0
  839. package/packages/core/src/plugins/stdio.ts +3 -1
  840. package/packages/core/src/plugins/synapse.ts +130 -0
  841. package/packages/core/src/plugins/tab-manager.ts +135 -0
  842. package/packages/core/src/plugins/taskboard.ts +412 -0
  843. package/packages/core/src/plugins/telemetry-blocker.ts +62 -0
  844. package/packages/core/src/plugins/test-harness.ts +67 -0
  845. package/packages/core/src/plugins/theme-studio.ts +165 -0
  846. package/packages/core/src/plugins/token-guard.ts +84 -0
  847. package/packages/core/src/plugins/tools.ts +5 -2
  848. package/packages/core/src/plugins/turn-rewind.ts +86 -0
  849. package/packages/core/src/plugins/undo-savepoint.ts +284 -0
  850. package/packages/core/src/plugins/vision-toolkit.ts +153 -0
  851. package/packages/core/src/plugins/web-research.ts +289 -0
  852. package/packages/core/src/plugins/workspace-navigator.ts +164 -0
  853. package/packages/core/src/plugins/workspace-search.ts +139 -0
  854. package/packages/core/src/plugins/yaml-validator.ts +97 -0
  855. package/packages/core/src/profile.ts +3 -0
  856. package/packages/core/src/runtime.ts +11 -4
  857. package/packages/core/src/services.ts +110 -3
  858. package/packages/core/src/stdio.ts +79 -9
  859. package/packages/core/src/workspace-path.ts +69 -0
  860. package/packages/core/test/agent-teams.test.ts +24 -0
  861. package/packages/core/test/archify.test.ts +33 -0
  862. package/packages/core/test/better-sidebar.test.ts +125 -0
  863. package/packages/core/test/boot.test.ts +49 -6
  864. package/packages/core/test/colleague-skill.test.ts +74 -0
  865. package/packages/core/test/config.test.ts +121 -0
  866. package/packages/core/test/context-doctor.test.ts +32 -0
  867. package/packages/core/test/dependency-checker.test.ts +60 -0
  868. package/packages/core/test/git-time-capsule.test.ts +115 -0
  869. package/packages/core/test/http.test.ts +34 -0
  870. package/packages/core/test/llm-verifier.test.ts +72 -0
  871. package/packages/core/test/mirage-bridge.test.ts +54 -0
  872. package/packages/core/test/module-search.test.ts +78 -0
  873. package/packages/core/test/plugin-check.test.ts +16 -0
  874. package/packages/core/test/plugin-stars.test.ts +55 -0
  875. package/packages/core/test/profiles.integration.test.ts +49 -15
  876. package/packages/core/test/prompt-library.test.ts +56 -0
  877. package/packages/core/test/readme-gen.test.ts +45 -0
  878. package/packages/core/test/recall-unread.test.ts +35 -0
  879. package/packages/core/test/registry.test.ts +48 -0
  880. package/packages/core/test/reverse-skill.test.ts +40 -0
  881. package/packages/core/test/runtime-doctor.test.ts +55 -0
  882. package/packages/core/test/runtime-fixture.ts +4 -4
  883. package/packages/core/test/runtime.test.ts +90 -1
  884. package/packages/core/test/secure-audit.test.ts +16 -0
  885. package/packages/core/test/services.test.ts +2024 -5
  886. package/packages/core/test/session-bookmarks.test.ts +62 -0
  887. package/packages/core/test/session-bridge.test.ts +103 -0
  888. package/packages/core/test/session-compare.test.ts +94 -0
  889. package/packages/core/test/session-export.test.ts +54 -0
  890. package/packages/core/test/session-search.test.ts +30 -0
  891. package/packages/core/test/skill-catalog.test.ts +18 -0
  892. package/packages/core/test/skill-guard.test.ts +21 -0
  893. package/packages/core/test/stdio-args.test.ts +178 -0
  894. package/packages/core/test/theme-studio.test.ts +39 -0
  895. package/packages/core/test/token-guard.test.ts +34 -0
  896. package/packages/core/test/turn-rewind.test.ts +19 -0
  897. package/packages/core/test/vision-toolkit.test.ts +38 -0
  898. package/packages/core/test/workspace-git-status.test.ts +37 -0
  899. package/packages/core/test/workspace-navigator.test.ts +33 -0
  900. package/packages/core/test/workspace-path.test.ts +34 -0
  901. package/packages/core/tsconfig.build.json +1 -3
  902. package/packages/core/tsconfig.json +1 -4
  903. package/packages/host-webserver/LICENSE +9 -0
  904. package/packages/host-webserver/dist/index.js +1 -1
  905. package/packages/host-webserver/dist/index.js.map +1 -1
  906. package/packages/host-webserver/package.json +17 -7
  907. package/packages/host-webserver/src/index.ts +1 -1
  908. package/packages/host-webserver/test/index.test.ts +4 -1
  909. package/packages/host-webserver/tsconfig.build.json +1 -1
  910. package/packages/host-webserver/tsconfig.json +1 -1
  911. package/apps/web/dist/assets/index-Bwqek8LF.js +0 -20
  912. package/apps/web/dist/assets/index-DCHSASjq.css +0 -1
  913. package/packages/api-gateway/dist/marketplace-registry.json +0 -62
  914. package/packages/api-gateway/src/marketplace-registry.json +0 -62
@@ -1,13 +1,26 @@
1
1
  import { execFile } from "node:child_process";
2
- import { rm } from "node:fs/promises";
2
+ import { mkdir, mkdtemp, readFile, rm, stat, unlink, writeFile } from "node:fs/promises";
3
3
  import type { IncomingMessage, ServerResponse } from "node:http";
4
- import { isAbsolute, relative, resolve } from "node:path";
4
+ import { basename, isAbsolute, join, relative, resolve } from "node:path";
5
+ import { tmpdir } from "node:os";
5
6
  import type { Context } from "@deepseek-ai/cordis";
6
- import { SessionManager, type AgentSessionEvent } from "@earendil-works/pi-coding-agent";
7
+ import { SessionManager, type AgentSessionEvent, type ExtensionUIContext } from "@earendil-works/pi-coding-agent";
7
8
  import type Loader from "@deepseek-ai/cordis-plugin-loader";
8
- import type { PiRuntimeService, PiModelsService, PiHarnessLaunch } from "@pi-harness/core";
9
+ import type { PiPluginUiRegistry, PiRuntimeService, PiModelsService, PiHarnessLaunch } from "@pi-harness/core";
9
10
  import type { WebServer } from "@pi-harness/host-webserver";
10
- import { MARKETPLACE_CAPABILITIES, searchMarketplace } from "./marketplace.js";
11
+ import {
12
+ MARKETPLACE_CAPABILITIES,
13
+ MARKETPLACE_CATEGORIES,
14
+ MARKETPLACE_PLUGINS,
15
+ attachMarketplaceStatistics,
16
+ createMarketplaceStatisticsLoader,
17
+ paginateMarketplace,
18
+ searchMarketplace,
19
+ needsMarketplacePackageInstall,
20
+ sortMarketplaceByRecommendation,
21
+ type MarketplacePlugin,
22
+ } from "./marketplace.js";
23
+ import { parseGitWorktrees, type WorkspaceSummary } from "./workspaces.js";
11
24
 
12
25
  interface ApiServices {
13
26
  readonly runtime: PiRuntimeService;
@@ -15,8 +28,11 @@ interface ApiServices {
15
28
  readonly launch: PiHarnessLaunch;
16
29
  readonly webServer: WebServer;
17
30
  readonly loader: Loader | undefined;
31
+ readonly pluginUi: PiPluginUiRegistry | undefined;
18
32
  }
19
33
 
34
+ const loadMarketplaceStatistics = createMarketplaceStatisticsLoader();
35
+
20
36
  function sendJson(response: ServerResponse, status: number, payload: unknown): void {
21
37
  const body = JSON.stringify(payload);
22
38
  response.writeHead(status, { "content-type": "application/json; charset=utf-8", "cache-control": "no-store", "content-length": Buffer.byteLength(body) });
@@ -55,6 +71,7 @@ function jsonSafe(value: unknown, seen = new WeakSet<object>()): unknown {
55
71
 
56
72
  function createStatus(services: ApiServices, events: readonly AgentSessionEvent[]) {
57
73
  const activeModel = services.runtime.session.model ?? services.models.model;
74
+ const cwd = activeCwd(services);
58
75
  return {
59
76
  status: services.runtime.session.isStreaming ? "running" : "ready",
60
77
  model: activeModel.provider + "/" + activeModel.id,
@@ -62,21 +79,292 @@ function createStatus(services: ApiServices, events: readonly AgentSessionEvent[
62
79
  events: events.length,
63
80
  sessionId: services.runtime.session.sessionId,
64
81
  sessionFile: services.runtime.session.sessionFile,
65
- cwd: services.launch.cwd,
82
+ cwd,
66
83
  agentDir: services.launch.agentDir,
67
84
  plugins: services.loader ? [...services.loader.entries()].filter((entry) => !entry.disabled).map((entry) => entry.options.name) : [],
68
85
  };
69
86
  }
70
87
 
88
+ function activeCwd(services: ApiServices): string {
89
+ const runtimeCwd = services.runtime.sessionRuntime?.cwd;
90
+ return typeof runtimeCwd === "string" && runtimeCwd.length > 0 ? runtimeCwd : services.launch.cwd;
91
+ }
92
+
93
+ function piConfig(services: ApiServices) {
94
+ const settings = services.runtime.session.settingsManager;
95
+ const global = settings.getGlobalSettings();
96
+ const compaction = settings.getCompactionSettings();
97
+ return {
98
+ path: join(services.launch.agentDir, "settings.json"),
99
+ scope: "global" as const,
100
+ source: JSON.stringify(global, null, 2) + "\n",
101
+ settings: {
102
+ defaultProvider: global.defaultProvider,
103
+ defaultModel: global.defaultModel,
104
+ defaultThinkingLevel: global.defaultThinkingLevel,
105
+ transport: settings.getTransport(),
106
+ steeringMode: settings.getSteeringMode(),
107
+ followUpMode: settings.getFollowUpMode(),
108
+ hideThinkingBlock: settings.getHideThinkingBlock(),
109
+ compaction,
110
+ retry: settings.getRetrySettings(),
111
+ terminal: {
112
+ showImages: settings.getShowImages(),
113
+ imageAutoResize: settings.getImageAutoResize(),
114
+ autocompleteMaxVisible: settings.getAutocompleteMaxVisible(),
115
+ },
116
+ advanced: {
117
+ quietStartup: settings.getQuietStartup(),
118
+ projectTrust: settings.getDefaultProjectTrust(),
119
+ showCacheMissNotices: settings.getShowCacheMissNotices(),
120
+ enableAnalytics: settings.getEnableAnalytics(),
121
+ enableInstallTelemetry: settings.getEnableInstallTelemetry(),
122
+ shellPath: settings.getShellPath(),
123
+ doubleEscapeAction: settings.getDoubleEscapeAction(),
124
+ treeFilterMode: settings.getTreeFilterMode(),
125
+ mermaid: settings.getMermaidRenderingMode(),
126
+ },
127
+ },
128
+ };
129
+ }
130
+
131
+ interface SessionMetadata {
132
+ readonly archived?: boolean;
133
+ readonly pinned?: boolean;
134
+ }
135
+
136
+ type SessionMetadataMap = Record<string, SessionMetadata>;
137
+
138
+ function sessionMetadataFile(manager: SessionManager): string {
139
+ return resolve(manager.getSessionDir(), ".pi-harness-session-meta.json");
140
+ }
141
+
142
+ async function readSessionMetadata(manager: SessionManager): Promise<SessionMetadataMap> {
143
+ try {
144
+ const parsed: unknown = JSON.parse(await readFile(sessionMetadataFile(manager), "utf8"));
145
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
146
+ return parsed as SessionMetadataMap;
147
+ } catch {
148
+ return {};
149
+ }
150
+ }
151
+
152
+ async function writeSessionMetadata(manager: SessionManager, metadata: SessionMetadataMap): Promise<void> {
153
+ await mkdir(manager.getSessionDir(), { recursive: true });
154
+ await writeFile(sessionMetadataFile(manager), JSON.stringify(metadata, null, 2) + "\n", "utf8");
155
+ }
156
+
157
+ function sessionPathInDirectory(path: string, manager: SessionManager): boolean {
158
+ const root = resolve(manager.getSessionDir());
159
+ const target = resolve(path);
160
+ const relativePath = relative(root, target);
161
+ return relativePath !== "" && !isAbsolute(relativePath) && relativePath !== ".." && !relativePath.startsWith(".." + "/") && target.endsWith(".jsonl");
162
+ }
163
+
164
+ const webSessionUi = {
165
+ select: (_title: string, options: string[]) => Promise.resolve(options[0]),
166
+ confirm: () => Promise.resolve(true),
167
+ input: () => Promise.resolve(undefined),
168
+ notify: () => {},
169
+ onTerminalInput: () => () => {},
170
+ setStatus: () => {},
171
+ setWorkingMessage: () => {},
172
+ setWorkingVisible: () => {},
173
+ setWorkingIndicator: () => {},
174
+ setHiddenThinkingLabel: () => {},
175
+ setWidget: () => {},
176
+ setFooter: () => {},
177
+ setHeader: () => {},
178
+ setTitle: () => {},
179
+ } as unknown as ExtensionUIContext;
180
+
181
+ async function runWebSessionChange<T>(services: ApiServices, action: () => Promise<T & { cancelled: boolean }>): Promise<T & { cancelled: boolean }> {
182
+ const runner = services.runtime.session.extensionRunner;
183
+ runner.setUIContext(webSessionUi, "rpc");
184
+ try {
185
+ const result = await action();
186
+ if (result.cancelled) runner.setUIContext(undefined, "print");
187
+ return result;
188
+ } catch (error) {
189
+ runner.setUIContext(undefined, "print");
190
+ throw error;
191
+ }
192
+ }
193
+
71
194
  function modelSummary(model: { provider: string; id: string; name?: string; reasoning?: boolean; contextWindow?: number }, active: boolean) {
72
- return { provider: model.provider, id: model.id, name: model.name ?? model.id, reasoning: model.reasoning ?? false, contextWindow: model.contextWindow ?? null, active };
195
+ return {
196
+ provider: model.provider,
197
+ id: model.id,
198
+ name: model.name ?? model.id,
199
+ reasoning: model.reasoning ?? false,
200
+ contextWindow: model.contextWindow ?? null,
201
+ active,
202
+ };
203
+ }
204
+
205
+ function visibleProviderIds(
206
+ runtime: Pick<PiModelsService["runtime"], "getModels"> &
207
+ Partial<Pick<PiModelsService["runtime"], "getProviders" | "getProviderAuthStatus" | "getRegisteredProviderConfig">>,
208
+ activeProvider: string,
209
+ ): Set<string> {
210
+ const providers = typeof runtime.getProviders === "function" ? runtime.getProviders() : [{ id: activeProvider, name: activeProvider }];
211
+ return new Set(
212
+ providers
213
+ .filter((provider) => {
214
+ if (provider.id === activeProvider) return true;
215
+ if (typeof runtime.getProviderAuthStatus !== "function") return false;
216
+ const auth = runtime.getProviderAuthStatus(provider.id);
217
+ if (typeof auth !== "object" || auth === null || (auth as { configured?: unknown }).configured !== true) return false;
218
+ if (typeof runtime.getRegisteredProviderConfig === "function") return runtime.getRegisteredProviderConfig(provider.id) !== undefined;
219
+ return true;
220
+ })
221
+ .map((provider) => provider.id),
222
+ );
223
+ }
224
+
225
+ type LoaderEntrySummary = { options: { id: string; name: string; disabled?: boolean | null }; fiber?: { state: unknown } };
226
+
227
+ function marketplacePluginForEntry(entry: LoaderEntrySummary): MarketplacePlugin | undefined {
228
+ return MARKETPLACE_PLUGINS.find((plugin) => plugin.packageName === entry.options.name);
73
229
  }
74
230
 
75
- function pluginSummary(entry: { options: { id: string; name: string; disabled?: boolean | null }; fiber?: { state: unknown } }) {
231
+ function pluginSummary(entry: LoaderEntrySummary) {
76
232
  const states = ["pending", "loading", "active", "failed", "disposed", "unloading"];
233
+ const marketplacePlugin = marketplacePluginForEntry(entry);
77
234
  const rawState = entry.fiber?.state;
78
- const state = typeof rawState === "number" ? states[rawState] ?? String(rawState) : typeof rawState === "string" ? rawState : rawState === undefined || rawState === null ? "unloaded" : "unknown";
79
- return { id: entry.options.id, name: entry.options.name, enabled: !entry.options.disabled, state };
235
+ const state =
236
+ typeof rawState === "number"
237
+ ? (states[rawState] ?? String(rawState))
238
+ : typeof rawState === "string"
239
+ ? rawState
240
+ : rawState === undefined || rawState === null
241
+ ? "unloaded"
242
+ : "unknown";
243
+ return {
244
+ id: entry.options.id,
245
+ name: entry.options.name,
246
+ enabled: !entry.options.disabled,
247
+ state,
248
+ removable: entry.options.id.startsWith("marketplace-") || marketplacePlugin !== undefined,
249
+ category: marketplacePlugin?.category,
250
+ };
251
+ }
252
+
253
+ function pluginLoaded(services: ApiServices, packageName: string): boolean {
254
+ return services.loader !== undefined && [...services.loader.entries()].some((entry) => entry.options.name === packageName && !entry.disabled);
255
+ }
256
+
257
+ function registerPluginPanels(context: Context, services: ApiServices): () => void {
258
+ if (services.pluginUi === undefined) return () => {};
259
+ const disposers = [
260
+ services.pluginUi.register({
261
+ id: "console-logger-panel",
262
+ pluginId: "@deepseek-ai/cordis-plugin-logger-console",
263
+ title: "运行时日志",
264
+ description: "查看最近的生命周期和运行时诊断输出。",
265
+ icon: "▤",
266
+ visible: () => pluginLoaded(services, "@deepseek-ai/cordis-plugin-logger-console"),
267
+ read: () => ({
268
+ total: context.logger.buffer.length,
269
+ items: context.logger.buffer.slice(-40).map((message) => ({
270
+ time: new Date(message.ts).toISOString(),
271
+ level: message.type,
272
+ source: message.name,
273
+ args: message.args,
274
+ })),
275
+ }),
276
+ }),
277
+ services.pluginUi.register({
278
+ id: "plugin-group-panel",
279
+ pluginId: "@deepseek-ai/cordis-plugin-group",
280
+ title: "插件树",
281
+ description: "查看当前运行时加载的插件树和生命周期状态。",
282
+ icon: "⌘",
283
+ visible: () => pluginLoaded(services, "@deepseek-ai/cordis-plugin-group"),
284
+ read: () => ({
285
+ entries:
286
+ services.loader === undefined
287
+ ? []
288
+ : [...services.loader.entries()].map((entry) => ({
289
+ id: entry.id,
290
+ name: entry.options.name.replace(/^@deepseek-ai\/cordis-plugin-/i, "plugin-").replace(/^cordis:/i, "runtime:"),
291
+ state: pluginSummary(entry).state,
292
+ enabled: !entry.disabled,
293
+ })),
294
+ }),
295
+ }),
296
+ services.pluginUi.register({
297
+ id: "timer-service-panel",
298
+ pluginId: "@deepseek-ai/cordis-plugin-timer",
299
+ title: "定时器服务",
300
+ description: "确认定时器服务已注册,并查看可用的生命周期绑定 API。",
301
+ icon: "◷",
302
+ visible: () => pluginLoaded(services, "@deepseek-ai/cordis-plugin-timer"),
303
+ read: () => ({
304
+ registered: context.reflect.get("timer") !== undefined,
305
+ capabilities: ["timeout", "interval", "throttle", "debounce"],
306
+ }),
307
+ }),
308
+ ];
309
+ return () => disposers.reverse().forEach((dispose) => dispose());
310
+ }
311
+
312
+ function runProcess(executable: string, args: readonly string[], cwd: string): Promise<{ stdout: string; stderr: string }> {
313
+ return new Promise((resolveProcess, rejectProcess) => {
314
+ execFile(executable, [...args], { cwd, timeout: 120_000, maxBuffer: 2 * 1024 * 1024 }, (error, stdout, stderr) => {
315
+ if (error) {
316
+ rejectProcess(new Error(`${executable} ${args.join(" ")} failed: ${stderr || error.message}`, { cause: error }));
317
+ return;
318
+ }
319
+ resolveProcess({ stdout, stderr });
320
+ });
321
+ });
322
+ }
323
+
324
+ async function appendMarketplaceProfile(configPath: string, plugin: MarketplacePlugin): Promise<string> {
325
+ const source = await readFile(configPath, "utf8");
326
+ if (source.includes(`name: ${JSON.stringify(plugin.packageName)}`)) return source;
327
+ const entryId = `marketplace-${plugin.id}`;
328
+ const config = JSON.stringify(plugin.profile.config);
329
+ const group = plugin.profile.group === true ? "\n group: true" : "";
330
+ const entry = `\n- id: ${entryId}\n name: ${JSON.stringify(plugin.packageName)}${group}\n config: ${config}\n`;
331
+ await writeFile(configPath, source.replace(/\s*$/, "") + entry, "utf8");
332
+ return source;
333
+ }
334
+
335
+ async function updateMarketplaceProfile(configPath: string, entryId: string, update: { disabled?: boolean; remove?: boolean }): Promise<string> {
336
+ const source = await readFile(configPath, "utf8");
337
+ const escapedId = entryId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
338
+ const pattern = new RegExp(`^([ \\t]*)- id: ${escapedId}[ \\t]*(?:\\r?\\n|$)`, "m");
339
+ const match = source.match(pattern);
340
+ if (match === null) throw new Error(`Installed plugin profile entry was not found: ${entryId}`);
341
+ const indent = match[1] ?? "";
342
+ const start = match.index ?? 0;
343
+ let end = source.length;
344
+ const linePattern = /^([ \t]*)(?=\S)/gm;
345
+ linePattern.lastIndex = start + match[0].length;
346
+ for (let line = linePattern.exec(source); line !== null; line = linePattern.exec(source)) {
347
+ const lineIndent = line[1] ?? "";
348
+ const content = source.slice(line.index + lineIndent.length);
349
+ if (lineIndent.length < indent.length || (lineIndent === indent && content.startsWith("- "))) {
350
+ end = line.index;
351
+ break;
352
+ }
353
+ }
354
+ const originalBlock = source.slice(start, end);
355
+ if (update.remove === true) {
356
+ await writeFile(configPath, source.slice(0, start) + source.slice(end), "utf8");
357
+ return source;
358
+ }
359
+ const childIndent = `${indent} `;
360
+ const disabledPattern = new RegExp(`^${childIndent}disabled: .*\\r?\\n`, "m");
361
+ let block = originalBlock.replace(disabledPattern, "");
362
+ if (update.disabled === true) {
363
+ const namePattern = new RegExp(`^(${childIndent}name: .*\\r?\\n)`, "m");
364
+ block = block.replace(namePattern, `$1${childIndent}disabled: true\n`);
365
+ }
366
+ await writeFile(configPath, source.slice(0, start) + block + source.slice(end), "utf8");
367
+ return source;
80
368
  }
81
369
 
82
370
  function writeSse(response: ServerResponse, payload: unknown): void {
@@ -91,7 +379,9 @@ function gitStatus(cwd: string): Promise<string> {
91
379
 
92
380
  function gitDiff(cwd: string, path: string): Promise<string> {
93
381
  return new Promise((resolveOutput) => {
94
- execFile("git", ["diff", "--no-ext-diff", "--", path], { cwd, maxBuffer: 1024 * 1024 }, (error, stdout) => resolveOutput(error && stdout.length === 0 ? "" : stdout));
382
+ execFile("git", ["diff", "--no-ext-diff", "--", path], { cwd, maxBuffer: 1024 * 1024 }, (error, stdout) =>
383
+ resolveOutput(error && stdout.length === 0 ? "" : stdout),
384
+ );
95
385
  });
96
386
  }
97
387
 
@@ -104,8 +394,62 @@ function gitCommand(cwd: string, args: readonly string[]): Promise<{ stdout: str
104
394
  });
105
395
  }
106
396
 
397
+ interface EveryApiCliAuthStatus {
398
+ configured: false;
399
+ source: "everyapi-cli";
400
+ label: string;
401
+ }
402
+
403
+ function probeEveryApiCliAuth(): Promise<EveryApiCliAuthStatus> {
404
+ const executable = process.env.EVERYAPI_CLI_PATH?.trim() || "everyapi";
405
+ return new Promise((resolveStatus) => {
406
+ execFile(executable, ["auth", "status"], { timeout: 3_000, maxBuffer: 128 * 1024 }, (error) => {
407
+ resolveStatus({
408
+ configured: false,
409
+ source: "everyapi-cli",
410
+ label: error ? "未检测到 EveryAPI CLI 登录" : "EveryAPI CLI 已登录,但 relay key 未注入当前进程",
411
+ });
412
+ });
413
+ });
414
+ }
415
+
416
+ async function listWorkspaces(cwd: string): Promise<readonly WorkspaceSummary[]> {
417
+ const result = await gitCommand(cwd, ["worktree", "list", "--porcelain"]);
418
+ const parsed = result.code === 0 ? parseGitWorktrees(result.stdout, cwd) : [];
419
+ if (parsed.some((item) => item.current)) return parsed;
420
+ return [{ path: resolve(cwd), branch: "current", current: true, name: resolve(cwd).split("/").pop() ?? resolve(cwd) }, ...parsed];
421
+ }
422
+
423
+ async function isDirectory(path: string): Promise<boolean> {
424
+ try {
425
+ return (await stat(path)).isDirectory();
426
+ } catch {
427
+ return false;
428
+ }
429
+ }
430
+
431
+ function pickDirectory(): Promise<string> {
432
+ return new Promise((resolvePath, reject) => {
433
+ execFile(
434
+ "osascript",
435
+ ["-e", 'POSIX path of (choose folder with prompt "选择 Pi 工作区")'],
436
+ { timeout: 120_000, maxBuffer: 64 * 1024 },
437
+ (error, stdout, stderr) => {
438
+ if (error) {
439
+ reject(new Error(stderr.trim() || "目录选择已取消"));
440
+ return;
441
+ }
442
+ const path = stdout.trim();
443
+ if (!path) reject(new Error("目录选择已取消"));
444
+ else resolvePath(path);
445
+ },
446
+ );
447
+ });
448
+ }
449
+
107
450
  function workspacePaths(root: string, paths: unknown): string[] | Error {
108
- if (!Array.isArray(paths) || paths.length === 0 || paths.some((path) => typeof path !== "string" || path.trim() === "")) return new Error("paths must be a non-empty array of strings");
451
+ if (!Array.isArray(paths) || paths.length === 0 || paths.some((path) => typeof path !== "string" || path.trim() === ""))
452
+ return new Error("paths must be a non-empty array of strings");
109
453
  const normalized: string[] = [];
110
454
  for (const path of paths) {
111
455
  const requested = path as string;
@@ -122,12 +466,14 @@ export default {
122
466
  inject: ["webServer", "piRuntime", "piModels", "piHarnessLaunch"],
123
467
  apply(context: Context) {
124
468
  const services: ApiServices = {
125
- runtime: context.piRuntime,
126
- models: context.piModels,
127
- launch: context.piHarnessLaunch,
469
+ runtime: context.reflect.get("piRuntime") as PiRuntimeService,
470
+ models: context.reflect.get("piModels") as PiModelsService,
471
+ launch: context.reflect.get("piHarnessLaunch") as PiHarnessLaunch,
128
472
  webServer: context.webServer,
129
473
  loader: context.reflect.get("loader") as Loader | undefined,
474
+ pluginUi: context.reflect.get("piPluginUi") as PiPluginUiRegistry | undefined,
130
475
  };
476
+ const disposePluginPanels = registerPluginPanels(context, services);
131
477
  let busy = false;
132
478
  const events: AgentSessionEvent[] = [];
133
479
  const eventClients = new Set<ServerResponse>();
@@ -142,7 +488,7 @@ export default {
142
488
  }
143
489
  };
144
490
  const unsubscribeEvents = services.runtime.sessionRuntime
145
- ? context.on("pi/session-event", handleEvent)
491
+ ? context.on("pi/session-event" as never, handleEvent as never)
146
492
  : services.runtime.session.subscribe(handleEvent);
147
493
  const disposeStatus = services.webServer.register({
148
494
  path: "/api/status",
@@ -150,26 +496,238 @@ export default {
150
496
  sendJson(response, 200, createStatus(services, events));
151
497
  },
152
498
  });
499
+ const disposeConfig = services.webServer.register({
500
+ path: "/api/config",
501
+ async handler(request, response) {
502
+ if (request.method === "GET") {
503
+ sendJson(response, 200, piConfig(services));
504
+ return;
505
+ }
506
+ if (request.method !== "POST") {
507
+ sendJson(response, 405, { error: "Method not allowed" });
508
+ return;
509
+ }
510
+ try {
511
+ const payload = JSON.parse(await bodyText(request)) as Record<string, unknown>;
512
+ const settings = services.runtime.session.settingsManager;
513
+ if (typeof payload.defaultProvider === "string" && payload.defaultProvider.trim()) settings.setDefaultProvider(payload.defaultProvider.trim());
514
+ if (typeof payload.defaultModel === "string" && payload.defaultModel.trim()) settings.setDefaultModel(payload.defaultModel.trim());
515
+ if (
516
+ payload.defaultThinkingLevel === "off" ||
517
+ payload.defaultThinkingLevel === "minimal" ||
518
+ payload.defaultThinkingLevel === "low" ||
519
+ payload.defaultThinkingLevel === "medium" ||
520
+ payload.defaultThinkingLevel === "high" ||
521
+ payload.defaultThinkingLevel === "xhigh" ||
522
+ payload.defaultThinkingLevel === "max"
523
+ )
524
+ settings.setDefaultThinkingLevel(payload.defaultThinkingLevel);
525
+ if (payload.transport === "sse" || payload.transport === "websocket" || payload.transport === "auto") settings.setTransport(payload.transport);
526
+ if (payload.steeringMode === "all" || payload.steeringMode === "one-at-a-time") settings.setSteeringMode(payload.steeringMode);
527
+ if (payload.followUpMode === "all" || payload.followUpMode === "one-at-a-time") settings.setFollowUpMode(payload.followUpMode);
528
+ if (typeof payload.hideThinkingBlock === "boolean") settings.setHideThinkingBlock(payload.hideThinkingBlock);
529
+ if (typeof payload.retry === "object" && payload.retry !== null) {
530
+ const retry = payload.retry as Record<string, unknown>;
531
+ if (typeof retry.enabled === "boolean") settings.setRetryEnabled(retry.enabled);
532
+ }
533
+ if (typeof payload.terminal === "object" && payload.terminal !== null) {
534
+ const terminal = payload.terminal as Record<string, unknown>;
535
+ if (typeof terminal.showImages === "boolean") settings.setShowImages(terminal.showImages);
536
+ if (typeof terminal.imageAutoResize === "boolean") settings.setImageAutoResize(terminal.imageAutoResize);
537
+ if (typeof terminal.autocompleteMaxVisible === "number" && Number.isInteger(terminal.autocompleteMaxVisible))
538
+ settings.setAutocompleteMaxVisible(Math.min(20, Math.max(3, terminal.autocompleteMaxVisible)));
539
+ }
540
+ if (typeof payload.advanced === "object" && payload.advanced !== null) {
541
+ const advanced = payload.advanced as Record<string, unknown>;
542
+ if (typeof advanced.quietStartup === "boolean") settings.setQuietStartup(advanced.quietStartup);
543
+ if (advanced.projectTrust === "ask" || advanced.projectTrust === "always" || advanced.projectTrust === "never")
544
+ settings.setDefaultProjectTrust(advanced.projectTrust);
545
+ if (typeof advanced.showCacheMissNotices === "boolean") settings.setShowCacheMissNotices(advanced.showCacheMissNotices);
546
+ if (typeof advanced.enableInstallTelemetry === "boolean") settings.setEnableInstallTelemetry(advanced.enableInstallTelemetry);
547
+ if (typeof advanced.shellPath === "string") settings.setShellPath(advanced.shellPath.trim() || undefined);
548
+ if (advanced.doubleEscapeAction === "fork" || advanced.doubleEscapeAction === "tree" || advanced.doubleEscapeAction === "none")
549
+ settings.setDoubleEscapeAction(advanced.doubleEscapeAction);
550
+ if (
551
+ advanced.treeFilterMode === "default" ||
552
+ advanced.treeFilterMode === "no-tools" ||
553
+ advanced.treeFilterMode === "user-only" ||
554
+ advanced.treeFilterMode === "labeled-only" ||
555
+ advanced.treeFilterMode === "all"
556
+ )
557
+ settings.setTreeFilterMode(advanced.treeFilterMode);
558
+ if (advanced.mermaid === "off" || advanced.mermaid === "final" || advanced.mermaid === "streaming")
559
+ settings.setMermaidRenderingMode(advanced.mermaid);
560
+ }
561
+ if (
562
+ typeof payload.compaction === "object" &&
563
+ payload.compaction !== null &&
564
+ typeof (payload.compaction as Record<string, unknown>).enabled === "boolean"
565
+ )
566
+ settings.setCompactionEnabled((payload.compaction as Record<string, boolean>).enabled === true);
567
+ await settings.flush();
568
+ sendJson(response, 200, piConfig(services));
569
+ } catch (error) {
570
+ sendJson(response, 400, { error: errorText(error) });
571
+ }
572
+ },
573
+ });
574
+ const disposeConfigReload = services.webServer.register({
575
+ path: "/api/config/reload",
576
+ async handler(request, response) {
577
+ if (request.method !== "POST") {
578
+ sendJson(response, 405, { error: "Method not allowed" });
579
+ return;
580
+ }
581
+ try {
582
+ await services.runtime.session.settingsManager.reload();
583
+ sendJson(response, 200, piConfig(services));
584
+ } catch (error) {
585
+ sendJson(response, 400, { error: errorText(error) });
586
+ }
587
+ },
588
+ });
589
+ const disposeConfigSource = services.webServer.register({
590
+ path: "/api/config/source",
591
+ async handler(request, response) {
592
+ if (request.method !== "POST") {
593
+ sendJson(response, 405, { error: "Method not allowed" });
594
+ return;
595
+ }
596
+ try {
597
+ const payload = JSON.parse(await bodyText(request)) as { source?: unknown };
598
+ if (typeof payload.source !== "string" || payload.source.length > 128 * 1024) {
599
+ sendJson(response, 400, { error: "source must be a JSON document smaller than 128 KiB" });
600
+ return;
601
+ }
602
+ const parsed: unknown = JSON.parse(payload.source);
603
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
604
+ sendJson(response, 400, { error: "settings source must contain a JSON object" });
605
+ return;
606
+ }
607
+ const path = join(services.launch.agentDir, "settings.json");
608
+ await writeFile(path, JSON.stringify(parsed, null, 2) + "\n", "utf8");
609
+ await services.runtime.session.settingsManager.reload();
610
+ sendJson(response, 200, piConfig(services));
611
+ } catch (error) {
612
+ sendJson(response, 400, { error: errorText(error) });
613
+ }
614
+ },
615
+ });
153
616
  const disposeModels = services.webServer.register({
154
617
  path: "/api/models",
155
618
  handler(_request, response) {
156
619
  const active = services.runtime.session.model ?? services.models.model;
157
- sendJson(response, 200, jsonSafe({ items: services.models.runtime.getModels().map((model) => modelSummary(model, model.provider === active.provider && model.id === active.id)) }));
620
+ const visible = visibleProviderIds(services.models.runtime, active.provider);
621
+ sendJson(
622
+ response,
623
+ 200,
624
+ jsonSafe({
625
+ items: services.models.runtime
626
+ .getModels()
627
+ .filter((model) => visible.has(model.provider))
628
+ .map((model) => modelSummary(model, model.provider === active.provider && model.id === active.id)),
629
+ }),
630
+ );
158
631
  },
159
632
  });
160
633
  const disposeProviders = services.webServer.register({
161
634
  path: "/api/providers",
162
635
  handler(_request, response) {
163
636
  const active = services.runtime.session.model ?? services.models.model;
164
- const runtime = services.models.runtime as typeof services.models.runtime & { getProviders?: () => readonly { id: string; name?: string }[]; getProviderAuthStatus?: (provider: string) => unknown };
637
+ const runtime = services.models.runtime as typeof services.models.runtime & {
638
+ getProviders?: () => readonly { id: string; name?: string }[];
639
+ getProviderAuthStatus?: (provider: string) => unknown;
640
+ };
165
641
  const providers = typeof runtime.getProviders === "function" ? runtime.getProviders() : [{ id: active.provider, name: active.provider }];
166
- const visible = providers.filter((provider) => {
167
- if (provider.id === active.provider) return true;
168
- if (typeof runtime.getProviderAuthStatus !== "function") return false;
169
- const auth = runtime.getProviderAuthStatus(provider.id);
170
- return typeof auth === "object" && auth !== null && (auth as { configured?: unknown }).configured === true;
171
- });
172
- sendJson(response, 200, jsonSafe({ items: visible.map((provider) => ({ provider: provider.id, name: provider.name ?? provider.id, active: provider.id === active.provider, auth: typeof runtime.getProviderAuthStatus === "function" ? runtime.getProviderAuthStatus(provider.id) : undefined, activeModel: provider.id === active.provider ? modelSummary(active, true) : undefined, models: services.models.runtime.getModels(provider.id).map((model) => modelSummary(model, model.provider === active.provider && model.id === active.id)) })) }));
642
+ const visibleIds = visibleProviderIds(runtime, active.provider);
643
+ const visible = providers.filter((provider) => visibleIds.has(provider.id));
644
+ sendJson(
645
+ response,
646
+ 200,
647
+ jsonSafe({
648
+ items: visible.map((provider) => ({
649
+ provider: provider.id,
650
+ name: provider.name ?? provider.id,
651
+ active: provider.id === active.provider,
652
+ auth: typeof runtime.getProviderAuthStatus === "function" ? runtime.getProviderAuthStatus(provider.id) : undefined,
653
+ activeModel: provider.id === active.provider ? modelSummary(active, true) : undefined,
654
+ models: services.models.runtime
655
+ .getModels(provider.id)
656
+ .map((model) => modelSummary(model, model.provider === active.provider && model.id === active.id)),
657
+ })),
658
+ }),
659
+ );
660
+ },
661
+ });
662
+ const disposeProviderAdd = services.webServer.register({
663
+ path: "/api/providers/add",
664
+ async handler(request, response) {
665
+ if (request.method !== "POST") {
666
+ sendJson(response, 405, { error: "Method not allowed" });
667
+ return;
668
+ }
669
+ try {
670
+ const payload = JSON.parse(await bodyText(request)) as {
671
+ provider?: unknown;
672
+ name?: unknown;
673
+ baseUrl?: unknown;
674
+ api?: unknown;
675
+ apiKey?: unknown;
676
+ model?: unknown;
677
+ };
678
+ const provider = typeof payload.provider === "string" ? payload.provider.trim() : "";
679
+ const name = typeof payload.name === "string" && payload.name.trim() !== "" ? payload.name.trim() : provider;
680
+ const baseUrl = typeof payload.baseUrl === "string" ? payload.baseUrl.trim() : "";
681
+ const apiKey = typeof payload.apiKey === "string" ? payload.apiKey.trim() : "";
682
+ const model = typeof payload.model === "string" ? payload.model.trim() : "";
683
+ const api = payload.api === "openai-responses" ? "openai-responses" : "openai-completions";
684
+ if (!/^[a-z0-9][a-z0-9._-]{1,63}$/i.test(provider)) {
685
+ sendJson(response, 400, { error: "provider must be 2-64 characters using letters, numbers, ., _, or -" });
686
+ return;
687
+ }
688
+ if (!/^https?:\/\/[^\s]+$/i.test(baseUrl)) {
689
+ sendJson(response, 400, { error: "baseUrl must be an http(s) URL" });
690
+ return;
691
+ }
692
+ if (!apiKey || !model) {
693
+ sendJson(response, 400, { error: "apiKey and model are required" });
694
+ return;
695
+ }
696
+ const runtime = services.models.runtime;
697
+ if (runtime.getProvider(provider) !== undefined) {
698
+ sendJson(response, 409, { error: `Provider already exists: ${provider}` });
699
+ return;
700
+ }
701
+ runtime.registerProvider(provider, {
702
+ name,
703
+ baseUrl,
704
+ api,
705
+ models: [
706
+ {
707
+ id: model,
708
+ name: model,
709
+ api,
710
+ reasoning: false,
711
+ input: ["text"],
712
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
713
+ contextWindow: 128000,
714
+ maxTokens: 8192,
715
+ },
716
+ ],
717
+ });
718
+ await runtime.setRuntimeApiKey(provider, apiKey);
719
+ sendJson(response, 201, {
720
+ provider: {
721
+ provider,
722
+ name,
723
+ active: false,
724
+ auth: runtime.getProviderAuthStatus(provider),
725
+ models: runtime.getModels(provider).map((item) => modelSummary(item, false)),
726
+ },
727
+ });
728
+ } catch (error) {
729
+ sendJson(response, 400, { error: errorText(error) });
730
+ }
173
731
  },
174
732
  });
175
733
  const disposeProviderTest = services.webServer.register({
@@ -191,6 +749,11 @@ export default {
191
749
  return;
192
750
  }
193
751
  const auth = await runtime.checkAuth(payload.provider);
752
+ if (payload.provider === "everyapi" && auth === undefined && !process.env.EVERYAPI_RELAY_KEY?.trim()) {
753
+ const cliAuth = await probeEveryApiCliAuth();
754
+ sendJson(response, 200, { provider: payload.provider, reachable: false, auth: cliAuth });
755
+ return;
756
+ }
194
757
  sendJson(response, 200, jsonSafe({ provider: payload.provider, reachable: auth !== undefined, auth }));
195
758
  } catch (error) {
196
759
  sendJson(response, 502, { error: errorText(error) });
@@ -229,9 +792,24 @@ export default {
229
792
  sendJson(response, 200, jsonSafe({ items }));
230
793
  },
231
794
  });
795
+ const disposePluginUi = services.webServer.register({
796
+ path: "/api/plugin-ui",
797
+ async handler(request, response) {
798
+ if (request.method !== "GET") {
799
+ sendJson(response, 405, { error: "Method not allowed" });
800
+ return;
801
+ }
802
+ try {
803
+ const items = services.pluginUi === undefined ? [] : await services.pluginUi.snapshot();
804
+ sendJson(response, 200, jsonSafe({ items }));
805
+ } catch (error) {
806
+ sendJson(response, 500, { error: errorText(error) });
807
+ }
808
+ },
809
+ });
232
810
  const disposeMarketplace = services.webServer.register({
233
811
  path: "/api/marketplace",
234
- handler(request, response) {
812
+ async handler(request, response) {
235
813
  if (request.method !== "GET") {
236
814
  sendJson(response, 405, { error: "Method not allowed" });
237
815
  return;
@@ -239,21 +817,264 @@ export default {
239
817
  const url = new URL(request.url ?? "/api/marketplace", "http://localhost");
240
818
  const query = url.searchParams.get("q") ?? "";
241
819
  const capability = url.searchParams.get("capability") ?? "";
242
- if (query.length > 120 || capability.length > 80) {
243
- sendJson(response, 400, { error: "Marketplace filters are too long" });
820
+ const category = url.searchParams.get("category") ?? "";
821
+ const page = Number(url.searchParams.get("page") ?? "0");
822
+ const pageSize = Number(url.searchParams.get("pageSize") ?? "24");
823
+ const sort = url.searchParams.get("sort") ?? "";
824
+ if (
825
+ query.length > 120 ||
826
+ capability.length > 80 ||
827
+ category.length > 80 ||
828
+ !Number.isInteger(page) ||
829
+ page < 0 ||
830
+ !Number.isInteger(pageSize) ||
831
+ pageSize < 1 ||
832
+ pageSize > 100 ||
833
+ (sort !== "" && sort !== "recommended")
834
+ ) {
835
+ sendJson(response, 400, { error: "Invalid marketplace query" });
836
+ return;
837
+ }
838
+ const filtered = searchMarketplace(query, capability, category);
839
+ const items =
840
+ sort === "recommended"
841
+ ? sortMarketplaceByRecommendation(attachMarketplaceStatistics(filtered, await loadMarketplaceStatistics(MARKETPLACE_PLUGINS)))
842
+ : filtered;
843
+ sendJson(response, 200, {
844
+ ...paginateMarketplace(items, page, pageSize),
845
+ capabilities: MARKETPLACE_CAPABILITIES,
846
+ categories: MARKETPLACE_CATEGORIES,
847
+ });
848
+ },
849
+ });
850
+ let marketplaceMutationInFlight = false;
851
+ const disposeMarketplaceInstall = services.webServer.register({
852
+ path: "/api/marketplace/install",
853
+ async handler(request, response) {
854
+ if (request.method !== "POST") {
855
+ sendJson(response, 405, { error: "Method not allowed" });
856
+ return;
857
+ }
858
+ if (marketplaceMutationInFlight) {
859
+ sendJson(response, 409, { error: "Another marketplace plugin change is already running" });
860
+ return;
861
+ }
862
+ const loader = services.loader;
863
+ const configPath = services.launch.configPath;
864
+ if (loader === undefined || configPath === undefined) {
865
+ sendJson(response, 501, { error: "Plugin installation is unavailable for this runtime" });
866
+ return;
867
+ }
868
+ marketplaceMutationInFlight = true;
869
+ try {
870
+ const payload = JSON.parse(await bodyText(request)) as { id?: unknown };
871
+ if (typeof payload.id !== "string" || payload.id.trim() === "") {
872
+ sendJson(response, 400, { error: "id is required" });
873
+ return;
874
+ }
875
+ const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === payload.id);
876
+ if (plugin === undefined) {
877
+ sendJson(response, 404, { error: "Marketplace plugin was not found" });
878
+ return;
879
+ }
880
+ const existing = [...loader.entries()].find((entry) => entry.options.name === plugin.packageName);
881
+ if (existing !== undefined) {
882
+ sendJson(response, 409, { error: "Plugin is already installed", plugin });
883
+ return;
884
+ }
885
+ const packageJsonPath = join(services.launch.cwd, "package.json");
886
+ const packageLockPath = join(services.launch.cwd, "package-lock.json");
887
+ const packageJsonBefore = await readFile(packageJsonPath, "utf8").catch(() => undefined);
888
+ const packageLockBefore = await readFile(packageLockPath, "utf8").catch(() => undefined);
889
+ let profileBefore: string | undefined;
890
+ let entryId: string | undefined;
891
+ try {
892
+ if (needsMarketplacePackageInstall(plugin)) {
893
+ await runProcess("npm", ["install", "--save-exact", "--package-lock=false", `${plugin.packageName}@${plugin.version}`], services.launch.cwd);
894
+ }
895
+ profileBefore = await appendMarketplaceProfile(configPath, plugin);
896
+ if (!needsMarketplacePackageInstall(plugin)) {
897
+ sendJson(response, 200, { plugin, installed: false, restartRequired: true });
898
+ return;
899
+ }
900
+ entryId = await loader.create({
901
+ id: `marketplace-${plugin.id}`,
902
+ name: plugin.packageName,
903
+ ...(plugin.profile.group === true ? { group: true } : {}),
904
+ config: plugin.profile.config,
905
+ } as never);
906
+ const entry = loader.resolve(entryId);
907
+ if (entry.fiber === undefined) throw new Error(`Plugin ${plugin.packageName} did not create a runtime fiber`);
908
+ await entry.fiber.await();
909
+ sendJson(response, 200, { plugin, installed: true });
910
+ } catch (error) {
911
+ if (entryId !== undefined) await loader.remove(entryId).catch(() => {});
912
+ if (profileBefore !== undefined) await writeFile(configPath, profileBefore, "utf8").catch(() => {});
913
+ if (packageJsonBefore !== undefined) await writeFile(packageJsonPath, packageJsonBefore, "utf8").catch(() => {});
914
+ if (packageLockBefore !== undefined) await writeFile(packageLockPath, packageLockBefore, "utf8").catch(() => {});
915
+ sendJson(response, 502, { error: errorText(error) });
916
+ }
917
+ } catch (error) {
918
+ sendJson(response, 400, { error: errorText(error) });
919
+ } finally {
920
+ marketplaceMutationInFlight = false;
921
+ }
922
+ },
923
+ });
924
+ const disposePluginToggle = services.webServer.register({
925
+ path: "/api/plugins/toggle",
926
+ async handler(request, response) {
927
+ if (request.method !== "POST") {
928
+ sendJson(response, 405, { error: "Method not allowed" });
929
+ return;
930
+ }
931
+ const configPath = services.launch.configPath;
932
+ const loader = services.loader;
933
+ if (configPath === undefined || loader === undefined) {
934
+ sendJson(response, 501, { error: "Plugin configuration is unavailable for this runtime" });
935
+ return;
936
+ }
937
+ if (marketplaceMutationInFlight) {
938
+ sendJson(response, 409, { error: "Another marketplace plugin change is already running" });
939
+ return;
940
+ }
941
+ marketplaceMutationInFlight = true;
942
+ try {
943
+ const payload = JSON.parse(await bodyText(request)) as { id?: unknown; enabled?: unknown };
944
+ if (typeof payload.id !== "string" || typeof payload.enabled !== "boolean") {
945
+ sendJson(response, 400, { error: "A marketplace plugin id and enabled boolean are required" });
946
+ return;
947
+ }
948
+ const entry = [...loader.entries()].find((item) => item.id === payload.id || item.options.id === payload.id);
949
+ if (entry === undefined) {
950
+ sendJson(response, 404, { error: "Installed plugin was not found" });
951
+ return;
952
+ }
953
+ const plugin = marketplacePluginForEntry(entry);
954
+ if (plugin === undefined) {
955
+ sendJson(response, 403, { error: "Built-in plugins cannot be changed" });
956
+ return;
957
+ }
958
+ const profileEntryId = entry.options.id;
959
+ const before = await updateMarketplaceProfile(configPath, profileEntryId, { disabled: !payload.enabled });
960
+ try {
961
+ await entry.update({ disabled: !payload.enabled });
962
+ sendJson(response, 200, { plugin: pluginSummary(entry) });
963
+ } catch (error) {
964
+ await writeFile(configPath, before, "utf8").catch(() => {});
965
+ sendJson(response, 502, { error: errorText(error) });
966
+ }
967
+ } catch (error) {
968
+ sendJson(response, 400, { error: errorText(error) });
969
+ } finally {
970
+ marketplaceMutationInFlight = false;
971
+ }
972
+ },
973
+ });
974
+ const disposePluginUninstall = services.webServer.register({
975
+ path: "/api/plugins/uninstall",
976
+ async handler(request, response) {
977
+ if (request.method !== "POST") {
978
+ sendJson(response, 405, { error: "Method not allowed" });
979
+ return;
980
+ }
981
+ const configPath = services.launch.configPath;
982
+ const loader = services.loader;
983
+ if (configPath === undefined || loader === undefined) {
984
+ sendJson(response, 501, { error: "Plugin configuration is unavailable for this runtime" });
985
+ return;
986
+ }
987
+ if (marketplaceMutationInFlight) {
988
+ sendJson(response, 409, { error: "Another marketplace plugin change is already running" });
244
989
  return;
245
990
  }
246
- sendJson(response, 200, { items: searchMarketplace(query, capability), capabilities: MARKETPLACE_CAPABILITIES });
991
+ marketplaceMutationInFlight = true;
992
+ try {
993
+ const payload = JSON.parse(await bodyText(request)) as { id?: unknown };
994
+ if (typeof payload.id !== "string") {
995
+ sendJson(response, 400, { error: "A marketplace plugin id is required" });
996
+ return;
997
+ }
998
+ const entry = [...loader.entries()].find((item) => item.id === payload.id || item.options.id === payload.id);
999
+ if (entry === undefined) {
1000
+ sendJson(response, 404, { error: "Installed plugin was not found" });
1001
+ return;
1002
+ }
1003
+ const plugin = marketplacePluginForEntry(entry);
1004
+ if (plugin === undefined) {
1005
+ sendJson(response, 403, { error: "Only marketplace plugins can be uninstalled" });
1006
+ return;
1007
+ }
1008
+ const profileEntryId = entry.options.id;
1009
+ const profileBefore = await readFile(configPath, "utf8");
1010
+ const packageJsonPath = join(services.launch.cwd, "package.json");
1011
+ const packageLockPath = join(services.launch.cwd, "package-lock.json");
1012
+ const packageJsonBefore = await readFile(packageJsonPath, "utf8").catch(() => undefined);
1013
+ const packageLockBefore = await readFile(packageLockPath, "utf8").catch(() => undefined);
1014
+ await entry.parent.remove(entry.options.id);
1015
+ entry.parent.tree.write();
1016
+ try {
1017
+ await updateMarketplaceProfile(configPath, profileEntryId, { remove: true });
1018
+ if (needsMarketplacePackageInstall(plugin)) await runProcess("npm", ["uninstall", "--package-lock=false", plugin.packageName], services.launch.cwd);
1019
+ sendJson(response, 200, { uninstalled: true, id: payload.id });
1020
+ } catch (error) {
1021
+ await writeFile(configPath, profileBefore, "utf8").catch(() => {});
1022
+ if (packageJsonBefore !== undefined) await writeFile(packageJsonPath, packageJsonBefore, "utf8").catch(() => {});
1023
+ if (packageLockBefore !== undefined) await writeFile(packageLockPath, packageLockBefore, "utf8").catch(() => {});
1024
+ const options = entry.options as { name: string; config?: unknown; group?: boolean | null };
1025
+ await loader
1026
+ .create({ id: entry.options.id, name: options.name, config: options.config, ...(options.group ? { group: true } : {}) } as never)
1027
+ .catch(() => {});
1028
+ sendJson(response, 502, { error: errorText(error) });
1029
+ }
1030
+ } catch (error) {
1031
+ sendJson(response, 400, { error: errorText(error) });
1032
+ } finally {
1033
+ marketplaceMutationInFlight = false;
1034
+ }
247
1035
  },
248
1036
  });
249
1037
  const disposeCommands = services.webServer.register({
250
1038
  path: "/api/commands",
251
1039
  handler(_request, response) {
252
1040
  const commands = services.runtime.session.extensionRunner.getRegisteredCommands();
253
- const items = commands.map((command) => ({ name: command.name, invocationName: command.invocationName, description: command.description, source: command.sourceInfo.path }));
1041
+ const items = commands.map((command) => ({
1042
+ name: command.name,
1043
+ invocationName: command.invocationName,
1044
+ description: command.description,
1045
+ source: command.sourceInfo.path,
1046
+ }));
254
1047
  sendJson(response, 200, jsonSafe({ items }));
255
1048
  },
256
1049
  });
1050
+ const disposeWorkspaces = services.webServer.register({
1051
+ path: "/api/workspaces",
1052
+ async handler(_request, response) {
1053
+ try {
1054
+ sendJson(response, 200, { items: await listWorkspaces(activeCwd(services)) });
1055
+ } catch (error) {
1056
+ sendJson(response, 500, { error: errorText(error) });
1057
+ }
1058
+ },
1059
+ });
1060
+ const disposePickDirectory = services.webServer.register({
1061
+ path: "/api/workspaces/pick",
1062
+ async handler(request, response) {
1063
+ if (request.method !== "POST") {
1064
+ sendJson(response, 405, { error: "Method not allowed" });
1065
+ return;
1066
+ }
1067
+ if (process.platform !== "darwin") {
1068
+ sendJson(response, 501, { error: "Native directory picker is only available on macOS" });
1069
+ return;
1070
+ }
1071
+ try {
1072
+ sendJson(response, 200, { path: await pickDirectory() });
1073
+ } catch (error) {
1074
+ sendJson(response, 409, { error: errorText(error) });
1075
+ }
1076
+ },
1077
+ });
257
1078
  const disposeModel = services.webServer.register({
258
1079
  path: "/api/model",
259
1080
  async handler(request, response) {
@@ -290,11 +1111,19 @@ export default {
290
1111
  const disposeFiles = services.webServer.register({
291
1112
  path: "/api/files",
292
1113
  async handler(_request, response) {
293
- const output = await gitStatus(services.launch.cwd);
294
- const items = output.split("\n").map((line) => line.trimEnd()).filter((line) => line.length > 0).map((line) => {
295
- const status = line.slice(0, 2).trim() || "??";
296
- return { path: line.slice(3), status, label: status === "??" ? "untracked" : status.includes("D") ? "deleted" : status.includes("A") ? "added" : "modified" };
297
- });
1114
+ const output = await gitStatus(activeCwd(services));
1115
+ const items = output
1116
+ .split("\n")
1117
+ .map((line) => line.trimEnd())
1118
+ .filter((line) => line.length > 0)
1119
+ .map((line) => {
1120
+ const status = line.slice(0, 2).trim() || "??";
1121
+ return {
1122
+ path: line.slice(3),
1123
+ status,
1124
+ label: status === "??" ? "untracked" : status.includes("D") ? "deleted" : status.includes("A") ? "added" : "modified",
1125
+ };
1126
+ });
298
1127
  sendJson(response, 200, { items });
299
1128
  },
300
1129
  });
@@ -311,7 +1140,7 @@ export default {
311
1140
  sendJson(response, 400, { error: "path is required" });
312
1141
  return;
313
1142
  }
314
- const root = resolve(services.launch.cwd);
1143
+ const root = resolve(activeCwd(services));
315
1144
  const absolute = resolve(root, requested);
316
1145
  const relativePath = relative(root, absolute);
317
1146
  if (isAbsolute(relativePath) || relativePath === ".." || relativePath.startsWith(".." + "/")) {
@@ -330,7 +1159,7 @@ export default {
330
1159
  }
331
1160
  try {
332
1161
  const payload = JSON.parse(await bodyText(request)) as { paths?: unknown; message?: unknown };
333
- const paths = workspacePaths(resolve(services.launch.cwd), payload.paths);
1162
+ const paths = workspacePaths(resolve(activeCwd(services)), payload.paths);
334
1163
  if (paths instanceof Error) {
335
1164
  sendJson(response, 400, { error: paths.message });
336
1165
  return;
@@ -339,7 +1168,7 @@ export default {
339
1168
  sendJson(response, 400, { error: "message is required" });
340
1169
  return;
341
1170
  }
342
- const root = resolve(services.launch.cwd);
1171
+ const root = resolve(activeCwd(services));
343
1172
  const add = await gitCommand(root, ["add", "-A", "--", ...paths]);
344
1173
  if (add.code !== 0) {
345
1174
  sendJson(response, 409, { error: add.stderr.trim() || "Unable to stage workspace files" });
@@ -370,7 +1199,7 @@ export default {
370
1199
  sendJson(response, 400, { error: "confirm must be true to discard workspace changes" });
371
1200
  return;
372
1201
  }
373
- const root = resolve(services.launch.cwd);
1202
+ const root = resolve(activeCwd(services));
374
1203
  const paths = workspacePaths(root, payload.paths);
375
1204
  if (paths instanceof Error) {
376
1205
  sendJson(response, 400, { error: paths.message });
@@ -382,7 +1211,10 @@ export default {
382
1211
  sendJson(response, 409, { error: restore.stderr.trim() || "Unable to restore workspace files" });
383
1212
  return;
384
1213
  }
385
- for (const path of untracked.stdout.split("\n").map((item) => item.trim()).filter(Boolean)) {
1214
+ for (const path of untracked.stdout
1215
+ .split("\n")
1216
+ .map((item) => item.trim())
1217
+ .filter(Boolean)) {
386
1218
  await rm(resolve(root, path), { recursive: true, force: true });
387
1219
  }
388
1220
  sendJson(response, 200, { reverted: true, paths });
@@ -394,7 +1226,12 @@ export default {
394
1226
  const disposeEvents = services.webServer.register({
395
1227
  path: "/api/events",
396
1228
  handler(_request, response) {
397
- response.writeHead(200, { "content-type": "text/event-stream; charset=utf-8", "cache-control": "no-cache, no-store", connection: "keep-alive", "x-accel-buffering": "no" });
1229
+ response.writeHead(200, {
1230
+ "content-type": "text/event-stream; charset=utf-8",
1231
+ "cache-control": "no-cache, no-store",
1232
+ connection: "keep-alive",
1233
+ "x-accel-buffering": "no",
1234
+ });
398
1235
  writeSse(response, { type: "snapshot", sessionId: services.runtime.session.sessionId, events });
399
1236
  eventClients.add(response);
400
1237
  const heartbeat = setInterval(() => {
@@ -466,13 +1303,17 @@ export default {
466
1303
  handler(_request, response) {
467
1304
  const session = services.runtime.session;
468
1305
  const sessionManager = session.sessionManager;
469
- sendJson(response, 200, jsonSafe({
470
- sessionId: session.sessionId,
471
- sessionFile: session.sessionFile,
472
- messages: session.messages,
473
- entries: typeof sessionManager?.getEntries === "function" ? sessionManager.getEntries() : [],
474
- events,
475
- }));
1306
+ sendJson(
1307
+ response,
1308
+ 200,
1309
+ jsonSafe({
1310
+ sessionId: session.sessionId,
1311
+ sessionFile: session.sessionFile,
1312
+ messages: session.messages,
1313
+ entries: typeof sessionManager?.getEntries === "function" ? sessionManager.getEntries() : [],
1314
+ events,
1315
+ }),
1316
+ );
476
1317
  },
477
1318
  });
478
1319
  const disposeNewSession = services.webServer.register({
@@ -487,14 +1328,40 @@ export default {
487
1328
  return;
488
1329
  }
489
1330
  try {
1331
+ const raw = await bodyText(request);
1332
+ const payload = raw.trim() ? (JSON.parse(raw) as { cwd?: unknown }) : {};
1333
+ const currentCwd = activeCwd(services);
1334
+ const requestedCwd = typeof payload.cwd === "string" ? resolve(payload.cwd) : resolve(currentCwd);
1335
+ const workspaces = await listWorkspaces(currentCwd);
1336
+ const workspace =
1337
+ workspaces.find((item) => item.path === requestedCwd) ??
1338
+ (typeof payload.cwd === "string" && (await isDirectory(requestedCwd))
1339
+ ? { path: requestedCwd, branch: "directory", current: false, name: basename(requestedCwd) || requestedCwd }
1340
+ : undefined);
1341
+ if (!workspace) {
1342
+ sendJson(response, 400, { error: "Workspace is not available" });
1343
+ return;
1344
+ }
490
1345
  if (services.runtime.sessionRuntime) {
491
- const result = await services.runtime.sessionRuntime.newSession();
1346
+ let result;
1347
+ if (workspace.current) {
1348
+ result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.newSession());
1349
+ } else {
1350
+ const manager = services.runtime.session.sessionManager;
1351
+ if (!manager || typeof manager.isPersisted !== "function" || !manager.isPersisted()) {
1352
+ sendJson(response, 409, { error: "Workspace switching requires JSONL session storage" });
1353
+ return;
1354
+ }
1355
+ const created = SessionManager.create(workspace.path, manager.getSessionDir());
1356
+ const sessionFile = created.newSession();
1357
+ if (!sessionFile) throw new Error("Unable to create a workspace session");
1358
+ result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.switchSession(sessionFile, { cwdOverride: workspace.path }));
1359
+ }
492
1360
  if (result.cancelled) {
493
1361
  sendJson(response, 409, { error: "Session creation was cancelled by an extension" });
494
1362
  return;
495
1363
  }
496
- }
497
- else {
1364
+ } else {
498
1365
  const session = services.runtime.session;
499
1366
  session.sessionManager.newSession();
500
1367
  session.agent.state.messages = [];
@@ -502,7 +1369,16 @@ export default {
502
1369
  events.length = 0;
503
1370
  const session = services.runtime.session;
504
1371
  for (const client of eventClients) writeSse(client, { type: "session", sessionId: session.sessionId, events: [] });
505
- sendJson(response, 200, jsonSafe({ sessionId: session.sessionId, sessionFile: session.sessionFile, messages: services.runtime.sessionRuntime ? session.messages : [], events: [] }));
1372
+ sendJson(
1373
+ response,
1374
+ 200,
1375
+ jsonSafe({
1376
+ sessionId: session.sessionId,
1377
+ sessionFile: session.sessionFile,
1378
+ messages: services.runtime.sessionRuntime ? session.messages : [],
1379
+ events: [],
1380
+ }),
1381
+ );
506
1382
  } catch (error) {
507
1383
  sendJson(response, 500, { error: errorText(error) });
508
1384
  }
@@ -527,41 +1403,344 @@ export default {
527
1403
  return;
528
1404
  }
529
1405
  const items = await SessionManager.list(services.launch.cwd, manager.getSessionDir());
530
- const target = items.find((item) => (typeof payload.path === "string" && item.path === payload.path) || (typeof payload.sessionId === "string" && item.id === payload.sessionId));
1406
+ const target = items.find(
1407
+ (item) =>
1408
+ (typeof payload.path === "string" && item.path === payload.path) || (typeof payload.sessionId === "string" && item.id === payload.sessionId),
1409
+ );
531
1410
  if (target === undefined) {
532
1411
  sendJson(response, 404, { error: "Session not found" });
533
1412
  return;
534
1413
  }
535
1414
  if (services.runtime.sessionRuntime) {
536
- const result = await services.runtime.sessionRuntime.switchSession(target.path, { cwdOverride: target.cwd });
1415
+ const result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.switchSession(target.path, { cwdOverride: target.cwd }));
537
1416
  if (result.cancelled) {
538
1417
  sendJson(response, 409, { error: "Session switch was cancelled by an extension" });
539
1418
  return;
540
1419
  }
541
- }
542
- else {
1420
+ } else {
543
1421
  manager.setSessionFile(target.path);
544
1422
  if (typeof services.runtime.session.reload === "function") await services.runtime.session.reload();
545
1423
  else services.runtime.session.agent.state.messages = manager.buildSessionContext().messages;
546
1424
  }
547
1425
  events.length = 0;
548
1426
  for (const client of eventClients) writeSse(client, { type: "session", sessionId: services.runtime.session.sessionId, events: [] });
549
- sendJson(response, 200, jsonSafe({ sessionId: services.runtime.session.sessionId, sessionFile: services.runtime.session.sessionFile, messages: services.runtime.session.messages, events: [] }));
1427
+ sendJson(
1428
+ response,
1429
+ 200,
1430
+ jsonSafe({
1431
+ sessionId: services.runtime.session.sessionId,
1432
+ sessionFile: services.runtime.session.sessionFile,
1433
+ messages: services.runtime.session.messages,
1434
+ events: [],
1435
+ }),
1436
+ );
550
1437
  } catch (error) {
551
1438
  sendJson(response, 400, { error: errorText(error) });
552
1439
  }
553
1440
  },
554
1441
  });
1442
+ const disposeRenameSession = services.webServer.register({
1443
+ path: "/api/session/rename",
1444
+ async handler(request, response) {
1445
+ if (request.method !== "POST") {
1446
+ sendJson(response, 405, { error: "Method not allowed" });
1447
+ return;
1448
+ }
1449
+ try {
1450
+ const payload = JSON.parse(await bodyText(request)) as { path?: unknown; name?: unknown };
1451
+ const manager = services.runtime.session.sessionManager;
1452
+ const path = typeof payload.path === "string" ? payload.path : services.runtime.session.sessionFile;
1453
+ const name = typeof payload.name === "string" ? payload.name.trim() : "";
1454
+ if (!path || !sessionPathInDirectory(path, manager)) {
1455
+ sendJson(response, 400, { error: "Invalid session path" });
1456
+ return;
1457
+ }
1458
+ if (name.length > 120) {
1459
+ sendJson(response, 400, { error: "Session name must be at most 120 characters" });
1460
+ return;
1461
+ }
1462
+ SessionManager.open(path, manager.getSessionDir()).appendSessionInfo(name);
1463
+ sendJson(response, 200, { path, name: name || undefined });
1464
+ } catch (error) {
1465
+ sendJson(response, 400, { error: errorText(error) });
1466
+ }
1467
+ },
1468
+ });
1469
+ const disposeDeleteSession = services.webServer.register({
1470
+ path: "/api/session/delete",
1471
+ async handler(request, response) {
1472
+ if (request.method !== "POST") {
1473
+ sendJson(response, 405, { error: "Method not allowed" });
1474
+ return;
1475
+ }
1476
+ try {
1477
+ const payload = JSON.parse(await bodyText(request)) as { path?: unknown; confirm?: unknown };
1478
+ const manager = services.runtime.session.sessionManager;
1479
+ const path = typeof payload.path === "string" ? payload.path : "";
1480
+ if (payload.confirm !== true) {
1481
+ sendJson(response, 400, { error: "confirm must be true to delete a session" });
1482
+ return;
1483
+ }
1484
+ if (!sessionPathInDirectory(path, manager)) {
1485
+ sendJson(response, 400, { error: "Invalid session path" });
1486
+ return;
1487
+ }
1488
+ if (path === services.runtime.session.sessionFile) {
1489
+ if (services.runtime.session.isStreaming) {
1490
+ sendJson(response, 409, { error: "Cannot delete the active session while a prompt is running" });
1491
+ return;
1492
+ }
1493
+ const result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.newSession());
1494
+ if (result.cancelled) {
1495
+ sendJson(response, 409, { error: "Session deletion was cancelled by an extension" });
1496
+ return;
1497
+ }
1498
+ events.length = 0;
1499
+ }
1500
+ await unlink(path);
1501
+ const metadata = await readSessionMetadata(manager);
1502
+ delete metadata[path];
1503
+ await writeSessionMetadata(manager, metadata);
1504
+ sendJson(response, 200, { deleted: true, path, sessionFile: services.runtime.session.sessionFile });
1505
+ } catch (error) {
1506
+ sendJson(response, 400, { error: errorText(error) });
1507
+ }
1508
+ },
1509
+ });
1510
+ const disposeSessionMetadata = services.webServer.register({
1511
+ path: "/api/session/metadata",
1512
+ async handler(request, response) {
1513
+ if (request.method !== "POST") {
1514
+ sendJson(response, 405, { error: "Method not allowed" });
1515
+ return;
1516
+ }
1517
+ try {
1518
+ const payload = JSON.parse(await bodyText(request)) as { path?: unknown; archived?: unknown; pinned?: unknown };
1519
+ const manager = services.runtime.session.sessionManager;
1520
+ const path = typeof payload.path === "string" ? payload.path : "";
1521
+ if (!sessionPathInDirectory(path, manager)) {
1522
+ sendJson(response, 400, { error: "Invalid session path" });
1523
+ return;
1524
+ }
1525
+ const metadata = await readSessionMetadata(manager);
1526
+ const currentMetadata = metadata[path] ?? {};
1527
+ const nextMetadata: SessionMetadata = {
1528
+ ...currentMetadata,
1529
+ ...(payload.archived === undefined ? {} : { archived: payload.archived === true }),
1530
+ ...(payload.pinned === undefined ? {} : { pinned: payload.pinned === true }),
1531
+ };
1532
+ metadata[path] = nextMetadata;
1533
+ await writeSessionMetadata(manager, metadata);
1534
+ sendJson(response, 200, { path, metadata: metadata[path] });
1535
+ } catch (error) {
1536
+ sendJson(response, 400, { error: errorText(error) });
1537
+ }
1538
+ },
1539
+ });
1540
+ const disposeBatchSessions = services.webServer.register({
1541
+ path: "/api/sessions/batch",
1542
+ async handler(request, response) {
1543
+ if (request.method !== "POST") {
1544
+ sendJson(response, 405, { error: "Method not allowed" });
1545
+ return;
1546
+ }
1547
+ try {
1548
+ const payload = JSON.parse(await bodyText(request)) as { action?: unknown; paths?: unknown; confirm?: unknown };
1549
+ const action = payload.action;
1550
+ const paths = Array.isArray(payload.paths) ? payload.paths.filter((path): path is string => typeof path === "string") : [];
1551
+ const manager = services.runtime.session.sessionManager;
1552
+ if (
1553
+ (action !== "delete" && action !== "archive" && action !== "unarchive" && action !== "pin" && action !== "unpin") ||
1554
+ paths.length === 0 ||
1555
+ paths.length > 100
1556
+ ) {
1557
+ sendJson(response, 400, { error: "action and 1-100 session paths are required" });
1558
+ return;
1559
+ }
1560
+ if (action === "delete" && payload.confirm !== true) {
1561
+ sendJson(response, 400, { error: "confirm must be true to delete sessions" });
1562
+ return;
1563
+ }
1564
+ if (paths.some((path) => !sessionPathInDirectory(path, manager))) {
1565
+ sendJson(response, 400, { error: "Invalid session path" });
1566
+ return;
1567
+ }
1568
+ if (action === "delete" && paths.includes(services.runtime.session.sessionFile ?? "")) {
1569
+ sendJson(response, 409, { error: "Cannot batch-delete the active session" });
1570
+ return;
1571
+ }
1572
+ const metadata = await readSessionMetadata(manager);
1573
+ for (const path of paths) {
1574
+ if (action === "delete") {
1575
+ await unlink(path);
1576
+ delete metadata[path];
1577
+ } else {
1578
+ const current = metadata[path] ?? {};
1579
+ metadata[path] = {
1580
+ ...current,
1581
+ ...(action === "archive" || action === "unarchive" ? { archived: action === "archive" } : {}),
1582
+ ...(action === "pin" || action === "unpin" ? { pinned: action === "pin" } : {}),
1583
+ };
1584
+ }
1585
+ }
1586
+ await writeSessionMetadata(manager, metadata);
1587
+ sendJson(response, 200, { action, count: paths.length });
1588
+ } catch (error) {
1589
+ sendJson(response, 400, { error: errorText(error) });
1590
+ }
1591
+ },
1592
+ });
1593
+ const disposeForkSession = services.webServer.register({
1594
+ path: "/api/session/fork",
1595
+ async handler(request, response) {
1596
+ if (request.method !== "POST") {
1597
+ sendJson(response, 405, { error: "Method not allowed" });
1598
+ return;
1599
+ }
1600
+ try {
1601
+ const payload = JSON.parse(await bodyText(request)) as { path?: unknown; cwd?: unknown };
1602
+ const manager = services.runtime.session.sessionManager;
1603
+ const sourcePath = typeof payload.path === "string" ? payload.path : "";
1604
+ if (!sessionPathInDirectory(sourcePath, manager)) {
1605
+ sendJson(response, 400, { error: "Invalid session path" });
1606
+ return;
1607
+ }
1608
+ const sessions = await SessionManager.list(services.launch.cwd, manager.getSessionDir());
1609
+ const source = sessions.find((item) => item.path === sourcePath);
1610
+ if (!source) {
1611
+ sendJson(response, 404, { error: "Session not found" });
1612
+ return;
1613
+ }
1614
+ const targetCwd = typeof payload.cwd === "string" && payload.cwd.trim() ? resolve(payload.cwd) : source.cwd || activeCwd(services);
1615
+ const forked = SessionManager.forkFrom(source.path, targetCwd, manager.getSessionDir());
1616
+ sendJson(response, 200, { sessionId: forked.getSessionId(), sessionFile: forked.getSessionFile(), cwd: targetCwd });
1617
+ } catch (error) {
1618
+ sendJson(response, 400, { error: errorText(error) });
1619
+ }
1620
+ },
1621
+ });
1622
+ const disposeImportSession = services.webServer.register({
1623
+ path: "/api/session/import",
1624
+ async handler(request, response) {
1625
+ if (request.method !== "POST") {
1626
+ sendJson(response, 405, { error: "Method not allowed" });
1627
+ return;
1628
+ }
1629
+ if (services.runtime.session.isStreaming) {
1630
+ sendJson(response, 409, { error: "Cannot import a session while a prompt is running" });
1631
+ return;
1632
+ }
1633
+ try {
1634
+ const payload = JSON.parse(await bodyText(request)) as { path?: unknown; content?: unknown; filename?: unknown; cwd?: unknown };
1635
+ const suppliedPath = typeof payload.path === "string" ? payload.path : "";
1636
+ const content = typeof payload.content === "string" ? payload.content : undefined;
1637
+ if ((!suppliedPath || !isAbsolute(suppliedPath)) && content === undefined) {
1638
+ sendJson(response, 400, { error: "A JSONL file path or file content is required" });
1639
+ return;
1640
+ }
1641
+ const manager = services.runtime.session.sessionManager;
1642
+ if (!manager.isPersisted()) {
1643
+ sendJson(response, 409, { error: "Session importing requires JSONL session storage" });
1644
+ return;
1645
+ }
1646
+ const targetCwd = typeof payload.cwd === "string" && payload.cwd.trim() ? resolve(payload.cwd) : activeCwd(services);
1647
+ const temporaryDirectory = content === undefined ? undefined : await mkdtemp(join(tmpdir(), "pi-harness-import-"));
1648
+ const importPath =
1649
+ suppliedPath ||
1650
+ join(temporaryDirectory as string, basename(typeof payload.filename === "string" && payload.filename.trim() ? payload.filename : "import.jsonl"));
1651
+ try {
1652
+ if (content !== undefined) {
1653
+ if (Buffer.byteLength(content, "utf8") > 10 * 1024 * 1024) {
1654
+ sendJson(response, 413, { error: "Imported session must be at most 10 MiB" });
1655
+ return;
1656
+ }
1657
+ await writeFile(importPath, content, "utf8");
1658
+ }
1659
+ const imported = SessionManager.forkFrom(importPath, targetCwd, manager.getSessionDir());
1660
+ const importedPath = imported.getSessionFile();
1661
+ if (!importedPath) throw new Error("Unable to persist imported session");
1662
+ const result = await runWebSessionChange(services, () => services.runtime.sessionRuntime.switchSession(importedPath, { cwdOverride: targetCwd }));
1663
+ if (result.cancelled) {
1664
+ sendJson(response, 409, { error: "Session import was cancelled by an extension" });
1665
+ return;
1666
+ }
1667
+ events.length = 0;
1668
+ sendJson(response, 200, {
1669
+ sessionId: services.runtime.session.sessionId,
1670
+ sessionFile: services.runtime.session.sessionFile,
1671
+ messages: services.runtime.session.messages.length,
1672
+ });
1673
+ } finally {
1674
+ if (temporaryDirectory) await rm(temporaryDirectory, { recursive: true, force: true });
1675
+ }
1676
+ } catch (error) {
1677
+ sendJson(response, 400, { error: errorText(error) });
1678
+ }
1679
+ },
1680
+ });
1681
+ const disposeExportSession = services.webServer.register({
1682
+ path: "/api/session/export",
1683
+ async handler(request, response) {
1684
+ try {
1685
+ const url = new URL(request.url ?? "/api/session/export", "http://localhost");
1686
+ const manager = services.runtime.session.sessionManager;
1687
+ const path = url.searchParams.get("path") ?? services.runtime.session.sessionFile;
1688
+ if (!path || !sessionPathInDirectory(path, manager)) {
1689
+ sendJson(response, 400, { error: "Invalid session path" });
1690
+ return;
1691
+ }
1692
+ const content = await readFile(path, "utf8");
1693
+ response.writeHead(200, {
1694
+ "content-type": "application/x-ndjson; charset=utf-8",
1695
+ "content-disposition": `attachment; filename="${basename(path)}"`,
1696
+ "cache-control": "no-store",
1697
+ });
1698
+ response.end(content);
1699
+ } catch (error) {
1700
+ sendJson(response, 404, { error: errorText(error) });
1701
+ }
1702
+ },
1703
+ });
555
1704
  const disposeSessions = services.webServer.register({
556
1705
  path: "/api/sessions",
557
1706
  async handler(_request, response) {
558
1707
  try {
559
1708
  const session = services.runtime.session;
560
1709
  const manager = session.sessionManager;
561
- const items = typeof manager.isPersisted === "function" && manager.isPersisted()
562
- ? await SessionManager.list(services.launch.cwd, manager.getSessionDir())
563
- : [];
564
- sendJson(response, 200, jsonSafe({ items: items.map((item) => ({ sessionId: item.id, path: item.path, name: item.name, cwd: item.cwd, created: item.created, modified: item.modified, messageCount: item.messageCount, firstMessage: item.firstMessage })) }));
1710
+ const url = new URL(_request.url ?? "/api/sessions", "http://localhost");
1711
+ const page = Math.max(0, Number.parseInt(url.searchParams.get("page") ?? "0", 10) || 0);
1712
+ const pageSize = Math.min(100, Math.max(1, Number.parseInt(url.searchParams.get("pageSize") ?? "50", 10) || 50));
1713
+ const includeArchived = url.searchParams.get("includeArchived") === "true";
1714
+ const metadata = await readSessionMetadata(manager);
1715
+ const items =
1716
+ typeof manager.isPersisted === "function" && manager.isPersisted() ? await SessionManager.list(services.launch.cwd, manager.getSessionDir()) : [];
1717
+ const filtered = items.filter((item) => includeArchived || metadata[item.path]?.archived !== true);
1718
+ const sorted = filtered.sort(
1719
+ (a, b) => Number(metadata[b.path]?.pinned === true) - Number(metadata[a.path]?.pinned === true) || b.modified.getTime() - a.modified.getTime(),
1720
+ );
1721
+ const paged = sorted.slice(page * pageSize, (page + 1) * pageSize);
1722
+ sendJson(
1723
+ response,
1724
+ 200,
1725
+ jsonSafe({
1726
+ items: paged.map((item) => ({
1727
+ sessionId: item.id,
1728
+ path: item.path,
1729
+ name: item.name,
1730
+ cwd: item.cwd,
1731
+ created: item.created,
1732
+ modified: item.modified,
1733
+ messageCount: item.messageCount,
1734
+ firstMessage: item.firstMessage,
1735
+ archived: metadata[item.path]?.archived === true,
1736
+ pinned: metadata[item.path]?.pinned === true,
1737
+ })),
1738
+ total: sorted.length,
1739
+ page,
1740
+ pageSize,
1741
+ hasNext: (page + 1) * pageSize < sorted.length,
1742
+ }),
1743
+ );
565
1744
  } catch (error) {
566
1745
  sendJson(response, 500, { error: errorText(error) });
567
1746
  }
@@ -569,15 +1748,26 @@ export default {
569
1748
  });
570
1749
  context.effect(() => () => {
571
1750
  disposeStatus();
1751
+ disposeConfig();
1752
+ disposeConfigReload();
1753
+ disposeConfigSource();
572
1754
  disposeEvents();
573
1755
  disposeModels();
574
1756
  disposeProviders();
575
1757
  disposeProviderTest();
576
1758
  disposeProviderRefresh();
1759
+ disposeProviderAdd();
577
1760
  disposePlugins();
1761
+ disposePluginUi();
1762
+ disposePluginPanels();
578
1763
  disposeMarketplace();
1764
+ disposeMarketplaceInstall();
1765
+ disposePluginToggle();
1766
+ disposePluginUninstall();
579
1767
  disposeCommands();
580
1768
  disposeModel();
1769
+ disposeWorkspaces();
1770
+ disposePickDirectory();
581
1771
  disposeFiles();
582
1772
  disposeFileDiff();
583
1773
  disposeFileCommit();
@@ -587,6 +1777,13 @@ export default {
587
1777
  disposeSession();
588
1778
  disposeNewSession();
589
1779
  disposeOpenSession();
1780
+ disposeRenameSession();
1781
+ disposeDeleteSession();
1782
+ disposeSessionMetadata();
1783
+ disposeBatchSessions();
1784
+ disposeForkSession();
1785
+ disposeImportSession();
1786
+ disposeExportSession();
590
1787
  disposeSessions();
591
1788
  unsubscribeEvents();
592
1789
  for (const response of eventClients) response.end();