@hienlh/ppm 0.9.0-beta.9 → 0.9.1

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 (262) hide show
  1. package/CHANGELOG.md +233 -0
  2. package/bun.lock +17 -0
  3. package/dist/web/assets/{_basePickBy-3Xe18azI.js → _basePickBy-5PGDJbfF.js} +1 -1
  4. package/dist/web/assets/{_baseUniq-Yy35llnn.js → _baseUniq-BT4Ow4Kk.js} +1 -1
  5. package/dist/web/assets/api-settings-BUvk6Saw.js +1 -0
  6. package/dist/web/assets/{arc-B9n1Gvb5.js → arc-BAOivWpI.js} +1 -1
  7. package/dist/web/assets/architecture-PBZL5I3N-DEO2f3VD.js +1 -0
  8. package/dist/web/assets/{architectureDiagram-2XIMDMQ5-DqAZP_F6.js → architectureDiagram-2XIMDMQ5-Z-4eN4za.js} +1 -1
  9. package/dist/web/assets/arrow-up-BYhx9ckd.js +1 -0
  10. package/dist/web/assets/{blockDiagram-WCTKOSBZ-h3cDF2vI.js → blockDiagram-WCTKOSBZ-BCLqzhuZ.js} +1 -1
  11. package/dist/web/assets/browser-tab-CrkhFCaw.js +1 -0
  12. package/dist/web/assets/{c4Diagram-IC4MRINW--pF1r5lr.js → c4Diagram-IC4MRINW-0Vp0Jeas.js} +1 -1
  13. package/dist/web/assets/channel-By7bn0Yq.js +1 -0
  14. package/dist/web/assets/chat-tab-C6jpiwh7.js +8 -0
  15. package/dist/web/assets/chevron-right-5HgK6l7K.js +1 -0
  16. package/dist/web/assets/{chunk-4BX2VUAB-C3aZvW7B.js → chunk-4BX2VUAB-D4tOov49.js} +1 -1
  17. package/dist/web/assets/{chunk-55IACEB6-D5cABeB9.js → chunk-55IACEB6-DJ6BynZ4.js} +1 -1
  18. package/dist/web/assets/{chunk-7E7YKBS2-CkFGv6Zs.js → chunk-7E7YKBS2-CiyUJxNI.js} +1 -1
  19. package/dist/web/assets/{chunk-7R4GIKGN-Dvbyu4Zw.js → chunk-7R4GIKGN-Dv-4cAYn.js} +2 -2
  20. package/dist/web/assets/{chunk-C72U2L5F-CtqKiH4q.js → chunk-C72U2L5F-D21mS_6G.js} +1 -1
  21. package/dist/web/assets/{chunk-EGIJ26TM-Cpr87sBR.js → chunk-EGIJ26TM-DzqmU2Z7.js} +1 -1
  22. package/dist/web/assets/{chunk-FMBD7UC4-D23YVTOU.js → chunk-FMBD7UC4-DXncblvW.js} +1 -1
  23. package/dist/web/assets/{chunk-GEFDOKGD-tDjHsAUs.js → chunk-GEFDOKGD-D-pKjlVd.js} +1 -1
  24. package/dist/web/assets/chunk-GLR3WWYH-DKikpoJM.js +2 -0
  25. package/dist/web/assets/chunk-HHEYEP7N-C7vxA5i9.js +1 -0
  26. package/dist/web/assets/{chunk-JSJVCQXG-BBmymCjA.js → chunk-JSJVCQXG-99JzIdPr.js} +1 -1
  27. package/dist/web/assets/{chunk-KX2RTZJC-DP36BDiU.js → chunk-KX2RTZJC-CRq1OBZv.js} +1 -1
  28. package/dist/web/assets/{chunk-KYZI473N-Djw13C-3.js → chunk-KYZI473N-Bb0MCaIO.js} +1 -1
  29. package/dist/web/assets/{chunk-L3YUKLVL-HG_eMj_C.js → chunk-L3YUKLVL-C7qGJrfV.js} +1 -1
  30. package/dist/web/assets/{chunk-MX3YWQON-C2UEioMs.js → chunk-MX3YWQON-BpS_PtKp.js} +1 -1
  31. package/dist/web/assets/{chunk-NQ4KR5QH-DXUTQ-BL.js → chunk-NQ4KR5QH-z_blpjxi.js} +1 -1
  32. package/dist/web/assets/{chunk-O4XLMI2P-BsUWb9d0.js → chunk-O4XLMI2P-nDhi_cVu.js} +1 -1
  33. package/dist/web/assets/{chunk-OZEHJAEY-rG0P22U9.js → chunk-OZEHJAEY-BXhYx3nO.js} +1 -1
  34. package/dist/web/assets/{chunk-PQ6SQG4A-DX0xW7kO.js → chunk-PQ6SQG4A-TF58UVMU.js} +1 -1
  35. package/dist/web/assets/{chunk-PU5JKC2W-C7Gry6md.js → chunk-PU5JKC2W-ek7k4QVB.js} +1 -1
  36. package/dist/web/assets/chunk-QZHKN3VN-CYaTbeZf.js +1 -0
  37. package/dist/web/assets/{chunk-R5LLSJPH-CMY0PkRK.js → chunk-R5LLSJPH-CFwSJijQ.js} +1 -1
  38. package/dist/web/assets/{chunk-WL4C6EOR-CXuQvlyu.js → chunk-WL4C6EOR-ByUrSRin.js} +1 -1
  39. package/dist/web/assets/{chunk-XIRO2GV7-DRJEb7Zb.js → chunk-XIRO2GV7-Djlmrely.js} +1 -1
  40. package/dist/web/assets/{chunk-XPW4576I-BPEX8KhL.js → chunk-XPW4576I-BPQQBakK.js} +1 -1
  41. package/dist/web/assets/{chunk-XZSTWKYB-Cb0iqycX.js → chunk-XZSTWKYB-DxAOx4hG.js} +1 -1
  42. package/dist/web/assets/{chunk-YBOYWFTD-av5aeHLq.js → chunk-YBOYWFTD-rQG3QH5s.js} +1 -1
  43. package/dist/web/assets/classDiagram-VBA2DB6C-BA8Nj-_C.js +1 -0
  44. package/dist/web/assets/classDiagram-v2-RAHNMMFH-DjYu-6mn.js +1 -0
  45. package/dist/web/assets/clone-LRxlvnMj.js +1 -0
  46. package/dist/web/assets/code-editor-CBIPzlP2.js +2 -0
  47. package/dist/web/assets/columns-2-cEVJHYd7.js +1 -0
  48. package/dist/web/assets/{cose-bilkent-S5V4N54A-qudEiMCT.js → cose-bilkent-S5V4N54A-B_AWZsOP.js} +1 -1
  49. package/dist/web/assets/createLucideIcon-PuMiQgHl.js +1 -0
  50. package/dist/web/assets/{csv-preview-DUbHtTAS.js → csv-preview-ncSOnJSC.js} +2 -2
  51. package/dist/web/assets/{dagre-BFcnKyBF.js → dagre-DHq9bhnd.js} +1 -1
  52. package/dist/web/assets/{dagre-KLK3FWXG-C3O-MTLf.js → dagre-KLK3FWXG-BdJr7Byp.js} +1 -1
  53. package/dist/web/assets/database-viewer-BqOJR_zi.js +1 -0
  54. package/dist/web/assets/{diagram-E7M64L7V-DxPjK7_c.js → diagram-E7M64L7V-_db4pBVA.js} +1 -1
  55. package/dist/web/assets/{diagram-IFDJBPK2-sqTog_XV.js → diagram-IFDJBPK2-xKoeuiJx.js} +1 -1
  56. package/dist/web/assets/{diagram-P4PSJMXO-hzmp0GHK.js → diagram-P4PSJMXO-C8tjJsev.js} +1 -1
  57. package/dist/web/assets/diff-viewer-CcLyp4eY.js +4 -0
  58. package/dist/web/assets/{dist-CALwEtco.js → dist-DIV6WgAG.js} +1 -1
  59. package/dist/web/assets/{dist-DGDPTxs1.js → dist-ovWkrgO-.js} +1 -1
  60. package/dist/web/assets/{erDiagram-INFDFZHY-DLeYhAAT.js → erDiagram-INFDFZHY-BSh2z9Df.js} +1 -1
  61. package/dist/web/assets/extension-webview-NiZ7Ybvv.js +3 -0
  62. package/dist/web/assets/{flowDiagram-PKNHOUZH-CRxlE9Sr.js → flowDiagram-PKNHOUZH-oYaovqyp.js} +1 -1
  63. package/dist/web/assets/{ganttDiagram-A5KZAMGK-BdjmoMLS.js → ganttDiagram-A5KZAMGK-DmL26q2P.js} +1 -1
  64. package/dist/web/assets/git-graph-CoTvMrIo.js +1 -0
  65. package/dist/web/assets/gitGraph-HDMCJU4V-Bwna3and.js +1 -0
  66. package/dist/web/assets/{gitGraphDiagram-K3NZZRJ6-BeHSX7kk.js → gitGraphDiagram-K3NZZRJ6-CMoukSrY.js} +1 -1
  67. package/dist/web/assets/{graphlib-Duh_bWLa.js → graphlib-BcsNnGcW.js} +1 -1
  68. package/dist/web/assets/index-C8byznLO.js +37 -0
  69. package/dist/web/assets/index-KwC2YrG4.css +2 -0
  70. package/dist/web/assets/info-3K5VOQVL-_vRxVNUm.js +1 -0
  71. package/dist/web/assets/infoDiagram-LFFYTUFH-DWwumDkq.js +2 -0
  72. package/dist/web/assets/{isEmpty-B9L-Ge-H.js → isEmpty-bnrF3Qbc.js} +1 -1
  73. package/dist/web/assets/{ishikawaDiagram-PHBUUO56-Cu0Rt1Ok.js → ishikawaDiagram-PHBUUO56-D05_LyL7.js} +1 -1
  74. package/dist/web/assets/{journeyDiagram-4ABVD52K-CgDI-UG4.js → journeyDiagram-4ABVD52K-B_L20qMe.js} +1 -1
  75. package/dist/web/assets/jsx-runtime-kMwlnEGE.js +1 -0
  76. package/dist/web/assets/{kanban-definition-K7BYSVSG-h4g10UHL.js → kanban-definition-K7BYSVSG-CZ535BbZ.js} +1 -1
  77. package/dist/web/assets/keybindings-store-DPYzBe_M.js +1 -0
  78. package/dist/web/assets/{line-B75-Rx70.js → line-CVvo3dRu.js} +1 -1
  79. package/dist/web/assets/{linear-Bcjv9FQt.js → linear-DP4mkX3m.js} +1 -1
  80. package/dist/web/assets/{markdown-renderer-VIZB1GXE.js → markdown-renderer-DPLdR9xc.js} +5 -5
  81. package/dist/web/assets/{mermaid-parser.core-8u2leTXI.js → mermaid-parser.core-C7UwoIh6.js} +2 -2
  82. package/dist/web/assets/{mindmap-definition-YRQLILUH-BaOBwb-W.js → mindmap-definition-YRQLILUH-x0MTutJp.js} +1 -1
  83. package/dist/web/assets/{ordinal-LFEjVtwQ.js → ordinal-_K3x1fkz.js} +1 -1
  84. package/dist/web/assets/packet-RMMSAZCW-DY5PNnZU.js +1 -0
  85. package/dist/web/assets/pie-UPGHQEXC-BHncZutv.js +1 -0
  86. package/dist/web/assets/{pieDiagram-SKSYHLDU-At5Kz0KK.js → pieDiagram-SKSYHLDU-C1Gjrtzy.js} +1 -1
  87. package/dist/web/assets/postgres-viewer-BeiK4lCa.js +1 -0
  88. package/dist/web/assets/{quadrantDiagram-337W2JSQ-CdjGIDfw.js → quadrantDiagram-337W2JSQ-C8bzJCjQ.js} +1 -1
  89. package/dist/web/assets/radar-KQ55EAFF-DH0AOkUy.js +1 -0
  90. package/dist/web/assets/{requirementDiagram-Z7DCOOCP-B9F_Cx_p.js → requirementDiagram-Z7DCOOCP-pQyah6WB.js} +1 -1
  91. package/dist/web/assets/{sankeyDiagram-WA2Y5GQK-RolPi8bU.js → sankeyDiagram-WA2Y5GQK-T6RgG-N8.js} +1 -1
  92. package/dist/web/assets/{sequenceDiagram-2WXFIKYE-DM-tMAhx.js → sequenceDiagram-2WXFIKYE-BQDJ4CVs.js} +1 -1
  93. package/dist/web/assets/settings-tab-D3AvU4lu.js +1 -0
  94. package/dist/web/assets/sqlite-viewer-nA2sD4Yv.js +1 -0
  95. package/dist/web/assets/{stateDiagram-RAJIS63D-C4EMl6jf.js → stateDiagram-RAJIS63D-66vhiIuk.js} +1 -1
  96. package/dist/web/assets/stateDiagram-v2-FVOUBMTO-BGVqj_g9.js +1 -0
  97. package/dist/web/assets/tab-store-BOgTrqRr.js +1 -0
  98. package/dist/web/assets/table-DFevCOMd.js +1 -0
  99. package/dist/web/assets/tag-CXMT0QB6.js +1 -0
  100. package/dist/web/assets/{terminal-tab-XhKfb4ei.js → terminal-tab-BBi0pEji.js} +1 -1
  101. package/dist/web/assets/{timeline-definition-YZTLITO2-A4PN_Efm.js → timeline-definition-YZTLITO2-DwZqB3nn.js} +1 -1
  102. package/dist/web/assets/treemap-KZPCXAKY-B2Xkyv-K.js +1 -0
  103. package/dist/web/assets/{use-monaco-theme-0p0-84jJ.js → use-monaco-theme-B5pG2d1w.js} +1 -1
  104. package/dist/web/assets/{vennDiagram-LZ73GAT5-ywK7LMaH.js → vennDiagram-LZ73GAT5-s9Z71fz-.js} +1 -1
  105. package/dist/web/assets/{xychartDiagram-JWTSCODW-DylHYNtJ.js → xychartDiagram-JWTSCODW-DRa_TH4B.js} +1 -1
  106. package/dist/web/index.html +10 -9
  107. package/dist/web/monacoeditorwork/css.worker.bundle.js +122 -122
  108. package/dist/web/monacoeditorwork/editor.worker.bundle.js +78 -78
  109. package/dist/web/monacoeditorwork/html.worker.bundle.js +110 -110
  110. package/dist/web/monacoeditorwork/json.worker.bundle.js +108 -108
  111. package/dist/web/monacoeditorwork/ts.worker.bundle.js +81 -81
  112. package/dist/web/sw.js +1 -1
  113. package/docs/code-standards.md +128 -1
  114. package/docs/codebase-summary.md +79 -12
  115. package/docs/extension-development-guide.md +532 -0
  116. package/docs/project-changelog.md +51 -1
  117. package/docs/project-roadmap.md +9 -3
  118. package/docs/streaming-input-guide.md +267 -0
  119. package/docs/system-architecture.md +432 -3
  120. package/package.json +6 -3
  121. package/packages/ext-database/package.json +41 -0
  122. package/packages/ext-database/src/connection-tree.ts +142 -0
  123. package/packages/ext-database/src/extension.ts +346 -0
  124. package/packages/ext-database/src/query-panel.ts +120 -0
  125. package/packages/ext-database/src/table-viewer-panel.ts +410 -0
  126. package/packages/ext-database/tsconfig.json +8 -0
  127. package/packages/vscode-compat/package.json +16 -0
  128. package/packages/vscode-compat/src/commands.ts +39 -0
  129. package/packages/vscode-compat/src/context.ts +65 -0
  130. package/packages/vscode-compat/src/disposable.ts +21 -0
  131. package/packages/vscode-compat/src/env.ts +20 -0
  132. package/packages/vscode-compat/src/event-emitter.ts +28 -0
  133. package/packages/vscode-compat/src/index.ts +93 -0
  134. package/packages/vscode-compat/src/not-supported.ts +15 -0
  135. package/packages/vscode-compat/src/types.ts +167 -0
  136. package/packages/vscode-compat/src/uri.ts +65 -0
  137. package/packages/vscode-compat/src/window.ts +229 -0
  138. package/packages/vscode-compat/src/workspace.ts +76 -0
  139. package/packages/vscode-compat/tsconfig.json +10 -0
  140. package/snapshot-state.md +1526 -0
  141. package/src/cli/commands/autostart.ts +1 -1
  142. package/src/cli/commands/ext-cmd.ts +121 -0
  143. package/src/cli/commands/restart.ts +9 -1
  144. package/src/cli/commands/status.ts +19 -0
  145. package/src/index.ts +5 -3
  146. package/src/providers/claude-agent-sdk.ts +221 -17
  147. package/src/providers/cli-provider-base.ts +6 -0
  148. package/src/server/index.ts +55 -155
  149. package/src/server/routes/chat.ts +81 -11
  150. package/src/server/routes/extensions.ts +81 -0
  151. package/src/server/routes/project-scoped.ts +2 -0
  152. package/src/server/routes/settings.ts +27 -0
  153. package/src/server/routes/workspace.ts +35 -0
  154. package/src/server/ws/chat.ts +9 -3
  155. package/src/server/ws/extensions.ts +175 -0
  156. package/src/services/account-selector.service.ts +14 -5
  157. package/src/services/account.service.ts +7 -7
  158. package/src/services/claude-usage.service.ts +11 -11
  159. package/src/services/cloud-ws.service.ts +228 -0
  160. package/src/services/cloud.service.ts +1 -0
  161. package/src/services/contribution-registry.ts +110 -0
  162. package/src/services/db.service.ts +181 -4
  163. package/src/services/extension-host-worker.ts +160 -0
  164. package/src/services/extension-installer.ts +112 -0
  165. package/src/services/extension-manifest.ts +65 -0
  166. package/src/services/extension-rpc-handlers.ts +235 -0
  167. package/src/services/extension-rpc.ts +105 -0
  168. package/src/services/extension.service.ts +228 -0
  169. package/src/services/mcp-config.service.ts +15 -6
  170. package/src/services/supervisor.ts +271 -25
  171. package/src/types/api.ts +1 -0
  172. package/src/types/chat.ts +4 -0
  173. package/src/types/extension-messages.ts +64 -0
  174. package/src/types/extension.ts +131 -0
  175. package/src/web/app.tsx +69 -48
  176. package/src/web/components/chat/account-rotation-settings.tsx +163 -0
  177. package/src/web/components/chat/chat-history-bar.tsx +106 -10
  178. package/src/web/components/chat/chat-tab.tsx +15 -10
  179. package/src/web/components/chat/chat-welcome.tsx +148 -0
  180. package/src/web/components/chat/message-list.tsx +19 -6
  181. package/src/web/components/chat/session-picker.tsx +80 -32
  182. package/src/web/components/chat/usage-badge.tsx +68 -8
  183. package/src/web/components/extensions/extension-inputbox.tsx +92 -0
  184. package/src/web/components/extensions/extension-quickpick.tsx +194 -0
  185. package/src/web/components/extensions/extension-tree-view.tsx +240 -0
  186. package/src/web/components/extensions/extension-webview.tsx +83 -0
  187. package/src/web/components/layout/command-palette.tsx +22 -2
  188. package/src/web/components/layout/editor-panel.tsx +163 -18
  189. package/src/web/components/layout/mobile-nav.tsx +2 -1
  190. package/src/web/components/layout/sidebar.tsx +21 -3
  191. package/src/web/components/layout/status-bar.tsx +64 -0
  192. package/src/web/components/layout/tab-bar.tsx +2 -0
  193. package/src/web/components/layout/tab-content.tsx +5 -0
  194. package/src/web/components/layout/upgrade-banner.tsx +15 -5
  195. package/src/web/components/settings/change-password-section.tsx +128 -0
  196. package/src/web/components/settings/extension-manager-section.tsx +214 -0
  197. package/src/web/components/settings/settings-tab.tsx +9 -2
  198. package/src/web/components/shared/connection-lost-overlay.tsx +89 -0
  199. package/src/web/hooks/use-chat.ts +28 -0
  200. package/src/web/hooks/use-extension-ws.ts +181 -0
  201. package/src/web/hooks/use-global-keybindings.ts +18 -2
  202. package/src/web/hooks/use-server-reload.ts +9 -0
  203. package/src/web/hooks/use-url-sync.ts +173 -21
  204. package/src/web/stores/connection-store.ts +39 -0
  205. package/src/web/stores/extension-store.ts +204 -0
  206. package/src/web/stores/panel-store.ts +63 -9
  207. package/src/web/stores/panel-utils.ts +145 -3
  208. package/src/web/stores/settings-store.ts +7 -2
  209. package/src/web/stores/tab-store.ts +2 -1
  210. package/test-session-ops.mjs +444 -0
  211. package/test-tokens.mjs +212 -0
  212. package/tsconfig.json +3 -1
  213. package/dist/web/assets/api-settings-CEMxVMCV.js +0 -1
  214. package/dist/web/assets/architecture-PBZL5I3N-CFzkFKEL.js +0 -1
  215. package/dist/web/assets/arrow-up--LjUXLEt.js +0 -1
  216. package/dist/web/assets/browser-tab-D1Zua62g.js +0 -1
  217. package/dist/web/assets/channel-C2fMafck.js +0 -1
  218. package/dist/web/assets/chat-tab-BnD27Vp9.js +0 -7
  219. package/dist/web/assets/chevron-right-CHnjJt4E.js +0 -1
  220. package/dist/web/assets/chunk-GLR3WWYH-DBdWQ3zy.js +0 -2
  221. package/dist/web/assets/chunk-HHEYEP7N-BBw_z0fW.js +0 -1
  222. package/dist/web/assets/chunk-QZHKN3VN-DFKFM_C1.js +0 -1
  223. package/dist/web/assets/classDiagram-VBA2DB6C-Dp4Kk3Yb.js +0 -1
  224. package/dist/web/assets/classDiagram-v2-RAHNMMFH-D8IvcV_B.js +0 -1
  225. package/dist/web/assets/clone-B2hUek6n.js +0 -1
  226. package/dist/web/assets/code-editor-DGRg8stf.js +0 -2
  227. package/dist/web/assets/columns-2-DbesTfa7.js +0 -1
  228. package/dist/web/assets/database-viewer-DxCXZQcE.js +0 -1
  229. package/dist/web/assets/diff-viewer-C1sDJG35.js +0 -4
  230. package/dist/web/assets/git-graph-BDn-EiGE.js +0 -1
  231. package/dist/web/assets/gitGraph-HDMCJU4V-CNlas3Rz.js +0 -1
  232. package/dist/web/assets/index-Bun94AK3.js +0 -37
  233. package/dist/web/assets/index-Db8uky1a.css +0 -2
  234. package/dist/web/assets/info-3K5VOQVL-BDzTLc11.js +0 -1
  235. package/dist/web/assets/infoDiagram-LFFYTUFH-ZZmpgc6t.js +0 -2
  236. package/dist/web/assets/jsx-runtime-BRW_vwa9.js +0 -1
  237. package/dist/web/assets/keybindings-store-COmK4Dte.js +0 -1
  238. package/dist/web/assets/packet-RMMSAZCW-IVa5F-go.js +0 -1
  239. package/dist/web/assets/pie-UPGHQEXC-CvXHKAzp.js +0 -1
  240. package/dist/web/assets/postgres-viewer-CvQZ8gkh.js +0 -1
  241. package/dist/web/assets/radar-KQ55EAFF-Z-Tr5wtS.js +0 -1
  242. package/dist/web/assets/settings-tab-RCnvZ29H.js +0 -1
  243. package/dist/web/assets/sqlite-viewer-CEEm2W4C.js +0 -1
  244. package/dist/web/assets/stateDiagram-v2-FVOUBMTO-B-UjZch3.js +0 -1
  245. package/dist/web/assets/tab-store-Bjh6bXFP.js +0 -1
  246. package/dist/web/assets/table-CQVQM2SB.js +0 -1
  247. package/dist/web/assets/tag-Q2dZiSPX.js +0 -1
  248. package/dist/web/assets/treemap-KZPCXAKY-C9TYRE0k.js +0 -1
  249. /package/dist/web/assets/{api-client-BKIT_Qeg.js → api-client-BfBM3I7n.js} +0 -0
  250. /package/dist/web/assets/{array-DqLCdDFv.js → array-B9UHiPd-.js} +0 -0
  251. /package/dist/web/assets/{cytoscape.esm-CWPXKqbJ.js → cytoscape.esm-BW-DbntU.js} +0 -0
  252. /package/dist/web/assets/{defaultLocale-CrJzLgRD.js → defaultLocale-5eAKkKJC.js} +0 -0
  253. /package/dist/web/assets/{dist-Cep75xXf.js → dist-CSJdAyA9.js} +0 -0
  254. /package/dist/web/assets/{init-C0r9Gk5G.js → init-DlZdxViB.js} +0 -0
  255. /package/dist/web/assets/{isArrayLikeObject-CGBoxvCD.js → isArrayLikeObject-B_v2FtYn.js} +0 -0
  256. /package/dist/web/assets/{katex-DzXRfQ_m.js → katex-Bqvo_ZG0.js} +0 -0
  257. /package/dist/web/assets/{lib-BeaDXEkP.js → lib-BQ34Db2e.js} +0 -0
  258. /package/dist/web/assets/{math-y9zN1W-N.js → math-069Z4SuC.js} +0 -0
  259. /package/dist/web/assets/{path-DIKpVbHL.js → path-6uRLdFF7.js} +0 -0
  260. /package/dist/web/assets/{rough.esm-nHaDi0Kw.js → rough.esm-JX0wREDd.js} +0 -0
  261. /package/dist/web/assets/{src-Dw4QhedI.js → src-BqX54PbV.js} +0 -0
  262. /package/dist/web/assets/{utils-DMiycH3O.js → utils-BNytJOb1.js} +0 -0
@@ -35,8 +35,27 @@ const LOG_FILE = resolve(PPM_DIR, "ppm.log");
35
35
  let serverChild: Subprocess | null = null;
36
36
  let tunnelChild: Subprocess | null = null;
37
37
  let tunnelUrl: string | null = null;
38
+ let adoptedTunnelPid: number | null = null; // PID of tunnel kept alive across upgrade
38
39
  let shuttingDown = false;
39
40
 
41
+ type SupervisorState = "running" | "paused" | "upgrading";
42
+ let supervisorState: SupervisorState = "running";
43
+
44
+ let resumeResolve: (() => void) | null = null;
45
+
46
+ function waitForResume(): Promise<void> {
47
+ return new Promise((resolve) => {
48
+ resumeResolve = resolve;
49
+ });
50
+ }
51
+
52
+ function triggerResume(): void {
53
+ if (resumeResolve) {
54
+ resumeResolve();
55
+ resumeResolve = null;
56
+ }
57
+ }
58
+
40
59
  let serverRestarts = 0;
41
60
  let lastServerCrash = 0;
42
61
  let tunnelRestarts = 0;
@@ -129,8 +148,25 @@ export async function spawnServer(
129
148
  serverRestarts++;
130
149
 
131
150
  if (serverRestarts > MAX_RESTARTS) {
132
- log("FATAL", `Server exceeded ${MAX_RESTARTS} restarts, giving up`);
133
- shutdown();
151
+ log("WARN", `Server exceeded ${MAX_RESTARTS} restarts, pausing`);
152
+ notifyStateChange("running", "paused", "max_restarts_exceeded");
153
+ supervisorState = "paused";
154
+ updateStatus({
155
+ state: "paused",
156
+ pid: null,
157
+ pausedAt: new Date().toISOString(),
158
+ pauseReason: "max_restarts",
159
+ lastCrashError: `exit ${exitCode}`,
160
+ });
161
+ // Wait for resume signal — supervisor stays alive
162
+ await waitForResume();
163
+ // Resumed — reset and respawn
164
+ notifyStateChange("paused", "running", "user_resume");
165
+ supervisorState = "running";
166
+ serverRestarts = 0;
167
+ updateStatus({ state: "running", pausedAt: null, pauseReason: null });
168
+ log("INFO", "Resuming server after pause");
169
+ if (!shuttingDown) return spawnServer(serverArgs, logFd);
134
170
  return;
135
171
  }
136
172
 
@@ -189,12 +225,7 @@ async function syncUrlToCloud(url: string) {
189
225
  } catch {}
190
226
  }
191
227
 
192
- function startCloudHeartbeat(url: string) {
193
- if (heartbeatTimer) clearInterval(heartbeatTimer);
194
- heartbeatTimer = setInterval(() => {
195
- if (tunnelUrl) syncUrlToCloud(tunnelUrl);
196
- }, 5 * 60 * 1000);
197
- }
228
+ // HTTP heartbeat removed — WS is the sole heartbeat mechanism (Phase 4)
198
229
 
199
230
  export async function spawnTunnel(port: number): Promise<void> {
200
231
  let bin: string;
@@ -230,9 +261,8 @@ export async function spawnTunnel(port: number): Promise<void> {
230
261
  updateStatus({ shareUrl: tunnelUrl, tunnelPid: tunnelChild.pid });
231
262
  log("INFO", `Tunnel ready: ${tunnelUrl} (PID: ${tunnelChild.pid})`);
232
263
 
233
- // Sync new URL to cloud immediately + start periodic heartbeat
264
+ // One-time sync of tunnel URL to cloud (WS handles periodic heartbeat)
234
265
  await syncUrlToCloud(tunnelUrl);
235
- startCloudHeartbeat(tunnelUrl);
236
266
 
237
267
  const exitCode = await tunnelChild.exited;
238
268
  tunnelChild = null;
@@ -282,26 +312,46 @@ function startServerHealthCheck(port: number) {
282
312
 
283
313
  function startTunnelProbe(port: number) {
284
314
  tunnelProbeTimer = setInterval(async () => {
285
- if (shuttingDown || !tunnelUrl || !tunnelChild) {
286
- tunnelFailCount = 0;
287
- return;
315
+ if (shuttingDown || !tunnelUrl) { tunnelFailCount = 0; return; }
316
+ if (!tunnelChild && !adoptedTunnelPid) { tunnelFailCount = 0; return; }
317
+
318
+ // Check if adopted tunnel process is still alive
319
+ if (adoptedTunnelPid && !tunnelChild) {
320
+ try { process.kill(adoptedTunnelPid, 0); } catch {
321
+ log("WARN", "Adopted tunnel process died, respawning");
322
+ adoptedTunnelPid = null;
323
+ tunnelUrl = null;
324
+ updateStatus({ shareUrl: null, tunnelPid: null });
325
+ tunnelFailCount = 0;
326
+ spawnTunnel(port);
327
+ return;
328
+ }
288
329
  }
330
+
289
331
  try {
290
332
  const res = await fetch(`${tunnelUrl}/api/health`, {
291
333
  signal: AbortSignal.timeout(10_000),
292
334
  });
293
335
  if (res.ok) {
294
336
  tunnelFailCount = 0;
295
- tunnelRestarts = 0; // reset on success
337
+ tunnelRestarts = 0;
296
338
  return;
297
339
  }
298
340
  } catch {}
299
341
  tunnelFailCount++;
300
- if (tunnelFailCount >= TUNNEL_PROBE_FAIL_THRESHOLD && tunnelChild) {
342
+ if (tunnelFailCount >= TUNNEL_PROBE_FAIL_THRESHOLD) {
301
343
  log("WARN", `Tunnel URL dead (${tunnelFailCount} failures), regenerating`);
302
- try { tunnelChild.kill(); } catch {}
344
+ if (tunnelChild) {
345
+ try { tunnelChild.kill(); } catch {}
346
+ // spawnTunnel loop handles respawn via exited promise
347
+ } else if (adoptedTunnelPid) {
348
+ try { process.kill(adoptedTunnelPid, "SIGTERM"); } catch {}
349
+ adoptedTunnelPid = null;
350
+ tunnelUrl = null;
351
+ updateStatus({ shareUrl: null, tunnelPid: null });
352
+ spawnTunnel(port);
353
+ }
303
354
  tunnelFailCount = 0;
304
- // spawnTunnel loop handles respawn via exited promise
305
355
  }
306
356
  }, TUNNEL_PROBE_INTERVAL_MS);
307
357
  }
@@ -322,6 +372,39 @@ async function checkAvailableVersion() {
322
372
  }
323
373
  }
324
374
 
375
+ /** Try to adopt an existing tunnel process from status.json (survives upgrade) */
376
+ function adoptTunnel(): boolean {
377
+ try {
378
+ const status = readStatus();
379
+ const pid = status.tunnelPid as number;
380
+ const url = status.shareUrl as string;
381
+ if (!pid || !url) {
382
+ log("DEBUG", `adoptTunnel: missing tunnelPid(${pid}) or shareUrl(${url}) in status`);
383
+ return false;
384
+ }
385
+ process.kill(pid, 0); // throws if process is dead
386
+ adoptedTunnelPid = pid;
387
+ tunnelUrl = url;
388
+ log("INFO", `Adopted existing tunnel (PID: ${pid}, URL: ${url})`);
389
+ return true;
390
+ } catch (e) {
391
+ log("WARN", `adoptTunnel: tunnel PID ${(readStatus().tunnelPid)} unreachable: ${e}`);
392
+ return false;
393
+ }
394
+ }
395
+
396
+ /** Kill stale tunnel PID from status.json (cleanup after failed adoption) */
397
+ function killStaleTunnel() {
398
+ try {
399
+ const status = readStatus();
400
+ const pid = status.tunnelPid as number;
401
+ if (!pid) return;
402
+ try { process.kill(pid, "SIGTERM"); } catch {}
403
+ log("INFO", `Killed stale tunnel (PID: ${pid})`);
404
+ } catch {}
405
+ updateStatus({ tunnelPid: null, shareUrl: null });
406
+ }
407
+
325
408
  /** Spawn new supervisor from updated code, wait for it to be healthy, then exit */
326
409
  async function selfReplace(): Promise<{ success: boolean; error?: string }> {
327
410
  log("INFO", "Starting self-replace for upgrade");
@@ -330,11 +413,13 @@ async function selfReplace(): Promise<{ success: boolean; error?: string }> {
330
413
  try {
331
414
  // Prevent spawnServer crash-restart loop from respawning killed children
332
415
  shuttingDown = true;
416
+ notifyStateChange(supervisorState, "upgrading", "self_replace");
417
+ supervisorState = "upgrading";
418
+ updateStatus({ state: "upgrading" });
333
419
 
334
- // Kill server + tunnel children FIRST to free the port for the new supervisor
335
- log("INFO", "Stopping server and tunnel before spawning new supervisor");
420
+ // Kill server child to free the port; keep tunnel alive for domain continuity
421
+ log("INFO", "Stopping server before spawning new supervisor (tunnel kept alive)");
336
422
  if (serverChild) { try { serverChild.kill(); } catch {} serverChild = null; }
337
- if (tunnelChild) { try { tunnelChild.kill(); } catch {} tunnelChild = null; }
338
423
  // Clear health timers so we don't try to respawn killed children
339
424
  if (healthTimer) { clearInterval(healthTimer); healthTimer = null; }
340
425
  if (tunnelProbeTimer) { clearInterval(tunnelProbeTimer); tunnelProbeTimer = null; }
@@ -372,20 +457,159 @@ async function selfReplace(): Promise<{ success: boolean; error?: string }> {
372
457
  log("ERROR", "Self-replace timeout: new supervisor did not start");
373
458
  try { child.kill(); } catch {}
374
459
  shuttingDown = false;
460
+ notifyStateChange("upgrading", "running", "upgrade_failed");
461
+ supervisorState = "running";
462
+ updateStatus({ state: "running" });
375
463
  return { success: false, error: "New supervisor failed to start within 30s" };
376
464
  } catch (e) {
377
465
  log("ERROR", `Self-replace error: ${e}`);
378
466
  shuttingDown = false;
467
+ notifyStateChange("upgrading", "running", "upgrade_failed");
468
+ supervisorState = "running";
469
+ updateStatus({ state: "running" });
379
470
  return { success: false, error: (e as Error).message };
380
471
  }
381
472
  }
382
473
 
474
+ // ─── Cloud WS integration ─────────────────────────────────────────────
475
+
476
+ /** Notify Cloud of supervisor state change via WS */
477
+ async function notifyStateChange(from: string, to: string, reason: string) {
478
+ try {
479
+ const { send, isConnected } = await import("./cloud-ws.service.ts");
480
+ if (isConnected()) {
481
+ send({
482
+ type: "state_change",
483
+ from,
484
+ to,
485
+ reason,
486
+ timestamp: new Date().toISOString(),
487
+ });
488
+ }
489
+ } catch {}
490
+ }
491
+
492
+ /** Connect supervisor to Cloud via WebSocket (if device is linked) */
493
+ async function connectCloud(opts: { port: number }, serverArgs: string[], logFd: number) {
494
+ try {
495
+ const { getCloudDevice } = await import("./cloud.service.ts");
496
+ const device = getCloudDevice();
497
+ if (!device) return; // not linked to cloud
498
+
499
+ const { connect, onCommand } = await import("./cloud-ws.service.ts");
500
+ const { VERSION } = await import("../version.ts");
501
+ const startTime = Date.now();
502
+
503
+ connect({
504
+ cloudUrl: device.cloud_url,
505
+ deviceId: device.device_id,
506
+ secretKey: device.secret_key,
507
+ heartbeatFn: () => {
508
+ const status = readStatus();
509
+ // Re-read device file each heartbeat to pick up name changes
510
+ const currentDevice = getCloudDevice();
511
+ return {
512
+ type: "heartbeat" as const,
513
+ tunnelUrl,
514
+ state: supervisorState,
515
+ // Use server-reported version (source of truth) with supervisor fallback
516
+ appVersion: (status.serverVersion as string) || VERSION,
517
+ availableVersion: (status.availableVersion as string) || null,
518
+ serverPid: serverChild?.pid ?? null,
519
+ uptime: Math.floor((Date.now() - startTime) / 1000),
520
+ deviceName: currentDevice?.name ?? device.name,
521
+ timestamp: new Date().toISOString(),
522
+ };
523
+ },
524
+ });
525
+
526
+ // Handle commands from Cloud
527
+ onCommand(async (cmd) => {
528
+ const { send } = await import("./cloud-ws.service.ts");
529
+ const sendResult = (success: boolean, error?: string, data?: Record<string, unknown>) => {
530
+ send({
531
+ type: "command_result",
532
+ id: cmd.id,
533
+ success,
534
+ error,
535
+ data,
536
+ timestamp: new Date().toISOString(),
537
+ });
538
+ };
539
+
540
+ log("INFO", `Cloud command received: ${cmd.action}`);
541
+
542
+ // Send immediate ack so Cloud can update UI before processing
543
+ send({
544
+ type: "command_ack",
545
+ id: cmd.id,
546
+ timestamp: new Date().toISOString(),
547
+ });
548
+
549
+ switch (cmd.action) {
550
+ case "restart":
551
+ if (serverChild) {
552
+ serverRestartRequested = true;
553
+ try { serverChild.kill(); } catch {}
554
+ sendResult(true);
555
+ } else if (supervisorState === "paused") {
556
+ triggerResume();
557
+ sendResult(true);
558
+ } else {
559
+ sendResult(false, "No server child to restart");
560
+ }
561
+ break;
562
+
563
+ case "resume":
564
+ if (supervisorState === "paused") {
565
+ triggerResume();
566
+ sendResult(true);
567
+ } else {
568
+ sendResult(false, "Not in paused state");
569
+ }
570
+ break;
571
+
572
+ case "stop":
573
+ sendResult(true);
574
+ // Delay exit to allow WS buffer to flush
575
+ setTimeout(() => {
576
+ shutdown();
577
+ process.exit(0);
578
+ }, 500);
579
+ break;
580
+
581
+ case "status":
582
+ sendResult(true, undefined, {
583
+ state: supervisorState,
584
+ serverPid: serverChild?.pid ?? null,
585
+ tunnelUrl,
586
+ serverRestarts,
587
+ });
588
+ break;
589
+
590
+ default:
591
+ sendResult(false, `Unknown action: ${cmd.action}`);
592
+ }
593
+ });
594
+ } catch (e) {
595
+ log("WARN", `Cloud WS setup failed: ${e}`);
596
+ }
597
+ }
598
+
383
599
  // ─── Shutdown ──────────────────────────────────────────────────────────
384
600
  export function shutdown() {
385
601
  if (shuttingDown) return;
386
602
  shuttingDown = true;
387
603
  log("INFO", "Supervisor shutting down");
388
604
 
605
+ // Unblock if paused
606
+ triggerResume();
607
+
608
+ // Disconnect Cloud WS
609
+ import("./cloud-ws.service.ts")
610
+ .then(({ disconnect }) => disconnect())
611
+ .catch(() => {});
612
+
389
613
  if (healthTimer) clearInterval(healthTimer);
390
614
  if (tunnelProbeTimer) clearInterval(tunnelProbeTimer);
391
615
  if (heartbeatTimer) clearInterval(heartbeatTimer);
@@ -394,6 +618,7 @@ export function shutdown() {
394
618
 
395
619
  if (serverChild) { try { serverChild.kill(); } catch {} }
396
620
  if (tunnelChild) { try { tunnelChild.kill(); } catch {} }
621
+ if (adoptedTunnelPid) { try { process.kill(adoptedTunnelPid, "SIGTERM"); } catch {} }
397
622
  }
398
623
 
399
624
  // ─── Main entry ────────────────────────────────────────────────────────
@@ -414,7 +639,10 @@ export async function runSupervisor(opts: {
414
639
 
415
640
  // Write supervisor PID + clear stale availableVersion from previous run
416
641
  writeFileSync(PID_FILE, String(process.pid));
417
- updateStatus({ supervisorPid: process.pid, port: opts.port, host: opts.host, availableVersion: null });
642
+ updateStatus({
643
+ supervisorPid: process.pid, port: opts.port, host: opts.host, availableVersion: null,
644
+ state: "running", pausedAt: null, pauseReason: null, lastCrashError: null,
645
+ });
418
646
 
419
647
  // Build __serve__ args
420
648
  const serverArgs = [
@@ -428,8 +656,13 @@ export async function runSupervisor(opts: {
428
656
  process.on("SIGTERM", () => { shutdown(); process.exit(0); });
429
657
  process.on("SIGINT", () => { shutdown(); process.exit(0); });
430
658
 
431
- // SIGUSR2 = graceful server restart (tunnel stays alive)
659
+ // SIGUSR2 = graceful server restart (tunnel stays alive) or resume from paused
432
660
  process.on("SIGUSR2", () => {
661
+ if (supervisorState === "paused") {
662
+ log("INFO", "SIGUSR2 received while paused, resuming server");
663
+ triggerResume();
664
+ return;
665
+ }
433
666
  log("INFO", "SIGUSR2 received, restarting server only");
434
667
  if (serverChild) {
435
668
  serverRestartRequested = true; // flag so spawnServer skips backoff
@@ -443,9 +676,9 @@ export async function runSupervisor(opts: {
443
676
  const result = await selfReplace();
444
677
  if (!result.success) {
445
678
  log("ERROR", `Self-replace failed: ${result.error}, restarting children`);
446
- // Respawn server (and tunnel if configured) since selfReplace killed them
447
679
  spawnServer(serverArgs, logFd);
448
- if (opts.share) spawnTunnel(opts.port);
680
+ // Tunnel was kept alive during selfReplace; only respawn if dead
681
+ if (opts.share && !tunnelChild && !tunnelUrl) spawnTunnel(opts.port);
449
682
  }
450
683
  });
451
684
 
@@ -458,16 +691,29 @@ export async function runSupervisor(opts: {
458
691
  upgradeCheckTimer = setInterval(checkAvailableVersion, UPGRADE_CHECK_INTERVAL_MS);
459
692
  }, UPGRADE_SKIP_INITIAL_MS);
460
693
 
694
+ // Connect to Cloud via WebSocket (if device is linked)
695
+ connectCloud(opts, serverArgs, logFd);
696
+
461
697
  // Spawn server + tunnel in parallel
462
698
  const promises: Promise<void>[] = [spawnServer(serverArgs, logFd)];
463
699
 
464
700
  if (opts.share) {
465
701
  startTunnelProbe(opts.port);
466
- promises.push(spawnTunnel(opts.port));
702
+ // Try adopting tunnel kept alive from previous upgrade; spawn new if dead
703
+ if (!adoptTunnel()) {
704
+ killStaleTunnel(); // kill orphaned tunnel before spawning new one
705
+ promises.push(spawnTunnel(opts.port));
706
+ }
467
707
  }
468
708
 
469
709
  await Promise.all(promises);
470
710
 
711
+ // If upgrading, selfReplace handles process.exit — wait for it
712
+ if (supervisorState === "upgrading") {
713
+ log("INFO", "Server loop exited during upgrade, waiting for selfReplace to finish");
714
+ await new Promise(() => {}); // selfReplace will call process.exit()
715
+ }
716
+
471
717
  // If we get here, both loops exited (shutdown or max restarts)
472
718
  log("INFO", "Supervisor exiting");
473
719
  process.exit(shuttingDown ? 0 : 1);
package/src/types/api.ts CHANGED
@@ -44,4 +44,5 @@ export type ChatWsServerMessage =
44
44
  | { type: "session_state"; sessionId: string; phase: SessionPhase; pendingApproval: { requestId: string; tool: string; input: unknown } | null; sessionTitle: string | null }
45
45
  | { type: "turn_events"; events: unknown[] }
46
46
  | { type: "title_updated"; title: string }
47
+ | { type: "compact_status"; status: "compacting" | "done" }
47
48
  | { type: "ping" };
package/src/types/chat.ts CHANGED
@@ -29,6 +29,8 @@ export interface AIProvider {
29
29
  listSessionsByDir?(dir: string): Promise<SessionInfo[]>;
30
30
  ensureProjectPath?(sessionId: string, path: string): void;
31
31
  setForkSource?(sessionId: string, sourceSessionId: string): void;
32
+ forkAtMessage?(sessionId: string, messageId: string, opts?: { title?: string; dir?: string }): Promise<{ sessionId: string }>;
33
+ markAsResumed?(sessionId: string): void;
32
34
  isAvailable?(): Promise<boolean>;
33
35
  listModels?(): Promise<ModelOption[]>;
34
36
  }
@@ -61,6 +63,7 @@ export interface SessionInfo {
61
63
  projectName?: string;
62
64
  createdAt: string;
63
65
  updatedAt?: string;
66
+ pinned?: boolean;
64
67
  }
65
68
 
66
69
  export interface LimitBucket {
@@ -111,6 +114,7 @@ export type ChatEvent =
111
114
  | { type: "done"; sessionId: string; resultSubtype?: ResultSubtype; numTurns?: number; contextWindowPct?: number }
112
115
  | { type: "session_migrated"; oldSessionId: string; newSessionId: string }
113
116
  | { type: "account_info"; accountId: string; accountLabel: string }
117
+ | { type: "account_retry"; reason: string; accountId?: string; accountLabel?: string }
114
118
  | { type: "system"; subtype: string };
115
119
 
116
120
  export type ToolApprovalHandler = (
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Shared message types for the Extension WebSocket bridge.
3
+ * Server ↔ Client communication for extension UI updates.
4
+ */
5
+ import type { ExtensionContributes } from "./extension.ts";
6
+
7
+ // --- UI types (shared with extension-store) ---
8
+
9
+ export interface StatusBarItemMsg {
10
+ id: string;
11
+ text: string;
12
+ tooltip?: string;
13
+ command?: string;
14
+ alignment: "left" | "right";
15
+ priority: number;
16
+ extensionId?: string;
17
+ }
18
+
19
+ export interface TreeItemMsg {
20
+ id: string;
21
+ label: string;
22
+ description?: string;
23
+ tooltip?: string;
24
+ icon?: string;
25
+ collapsibleState: "none" | "collapsed" | "expanded";
26
+ command?: string;
27
+ children?: TreeItemMsg[];
28
+ contextValue?: string;
29
+ }
30
+
31
+ export interface QuickPickItemMsg {
32
+ label: string;
33
+ description?: string;
34
+ detail?: string;
35
+ picked?: boolean;
36
+ }
37
+
38
+ // --- Server → Client messages ---
39
+
40
+ export type ExtServerMsg =
41
+ | { type: "tree:update"; viewId: string; items: TreeItemMsg[]; parentId?: string }
42
+ | { type: "tree:refresh"; viewId: string }
43
+ | { type: "statusbar:update"; item: StatusBarItemMsg }
44
+ | { type: "statusbar:remove"; itemId: string }
45
+ | { type: "notification"; id: string; level: "info" | "warn" | "error"; message: string; actions?: string[] }
46
+ | { type: "quickpick:show"; requestId: string; items: QuickPickItemMsg[]; options?: { placeholder?: string; canPickMany?: boolean } }
47
+ | { type: "inputbox:show"; requestId: string; options: { prompt?: string; value?: string; placeholder?: string; password?: boolean } }
48
+ | { type: "webview:create"; panelId: string; extensionId: string; viewType: string; title: string }
49
+ | { type: "webview:html"; panelId: string; html: string }
50
+ | { type: "webview:dispose"; panelId: string }
51
+ | { type: "webview:postMessage"; panelId: string; message: unknown }
52
+ | { type: "contributions:update"; contributions: ExtensionContributes };
53
+
54
+ // --- Client → Server messages ---
55
+
56
+ export type ExtClientMsg =
57
+ | { type: "ready" }
58
+ | { type: "command:execute"; command: string; args?: unknown[] }
59
+ | { type: "tree:expand"; viewId: string; itemId: string }
60
+ | { type: "tree:click"; viewId: string; itemId: string; command?: string }
61
+ | { type: "webview:message"; panelId: string; message: unknown }
62
+ | { type: "quickpick:resolve"; requestId: string; selected: QuickPickItemMsg[] | null }
63
+ | { type: "inputbox:resolve"; requestId: string; value: string | null }
64
+ | { type: "notification:action"; id: string; action: string | null };
@@ -0,0 +1,131 @@
1
+ /** Extension manifest — parsed from package.json of an installed extension */
2
+ export interface ExtensionManifest {
3
+ id: string; // npm package name, e.g. @ppm/ext-database
4
+ version: string;
5
+ main: string; // JS entry point relative to extension root
6
+ displayName?: string;
7
+ description?: string;
8
+ icon?: string;
9
+ engines?: { ppm?: string };
10
+ activationEvents?: string[];
11
+ contributes?: ExtensionContributes;
12
+ ppm?: {
13
+ displayName?: string;
14
+ icon?: string;
15
+ webviewDir?: string;
16
+ };
17
+ permissions?: string[];
18
+ }
19
+
20
+ /** VSCode-compatible contributes section */
21
+ export interface ExtensionContributes {
22
+ commands?: ContributedCommand[];
23
+ views?: Record<string, ContributedView[]>;
24
+ configuration?: { properties?: Record<string, ConfigProperty> };
25
+ menus?: Record<string, ContributedMenu[]>;
26
+ }
27
+
28
+ export interface ContributedCommand {
29
+ command: string;
30
+ title: string;
31
+ icon?: string;
32
+ category?: string;
33
+ }
34
+
35
+ export interface ContributedView {
36
+ id: string;
37
+ name: string;
38
+ type?: "tree" | "webview";
39
+ icon?: string;
40
+ }
41
+
42
+ export interface ConfigProperty {
43
+ type?: string;
44
+ default?: unknown;
45
+ description?: string;
46
+ enum?: unknown[];
47
+ }
48
+
49
+ export interface ContributedMenu {
50
+ command: string;
51
+ when?: string;
52
+ group?: string;
53
+ }
54
+
55
+ /** Runtime extension info returned by API */
56
+ export interface ExtensionInfo {
57
+ id: string;
58
+ version: string;
59
+ displayName: string;
60
+ description: string;
61
+ icon: string;
62
+ enabled: boolean;
63
+ activated: boolean;
64
+ manifest: ExtensionManifest;
65
+ }
66
+
67
+ /** DB row for extensions table */
68
+ export interface ExtensionRow {
69
+ id: string;
70
+ version: string;
71
+ display_name: string | null;
72
+ description: string | null;
73
+ icon: string | null;
74
+ enabled: number; // 0 | 1
75
+ manifest: string; // JSON
76
+ installed_at: string;
77
+ updated_at: string;
78
+ }
79
+
80
+ /** DB row for extension_storage table */
81
+ export interface ExtensionStorageRow {
82
+ ext_id: string;
83
+ scope: string;
84
+ key: string;
85
+ value: string | null; // JSON
86
+ }
87
+
88
+ /** Extension activation context passed to ext.activate() */
89
+ export interface ExtensionContext {
90
+ extensionId: string;
91
+ extensionPath: string;
92
+ globalState: StateStore;
93
+ workspaceState: StateStore;
94
+ subscriptions: Disposable[];
95
+ }
96
+
97
+ export interface StateStore {
98
+ get<T = unknown>(key: string, defaultValue?: T): T | undefined;
99
+ update(key: string, value: unknown): Promise<void>;
100
+ keys(): readonly string[];
101
+ }
102
+
103
+ export interface Disposable {
104
+ dispose(): void;
105
+ }
106
+
107
+ /** RPC message types between main process and extension host worker */
108
+ export type RpcMessage =
109
+ | RpcRequest
110
+ | RpcResponse
111
+ | RpcEvent;
112
+
113
+ export interface RpcRequest {
114
+ type: "request";
115
+ id: number;
116
+ method: string;
117
+ params: unknown[];
118
+ }
119
+
120
+ export interface RpcResponse {
121
+ type: "response";
122
+ id: number;
123
+ result?: unknown;
124
+ error?: string;
125
+ }
126
+
127
+ export interface RpcEvent {
128
+ type: "event";
129
+ event: string;
130
+ data: unknown;
131
+ }