@hienlh/ppm 0.9.0-beta.9 → 0.9.2

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 (256) hide show
  1. package/.claude.bak/agent-memory/tester/MEMORY.md +3 -0
  2. package/.claude.bak/agent-memory/tester/project-ppm-test-conventions.md +32 -0
  3. package/CHANGELOG.md +240 -0
  4. package/bun.lock +17 -0
  5. package/dist/web/assets/{_basePickBy-3Xe18azI.js → _basePickBy-5PGDJbfF.js} +1 -1
  6. package/dist/web/assets/{_baseUniq-Yy35llnn.js → _baseUniq-BT4Ow4Kk.js} +1 -1
  7. package/dist/web/assets/api-settings-BUvk6Saw.js +1 -0
  8. package/dist/web/assets/{arc-B9n1Gvb5.js → arc-BAOivWpI.js} +1 -1
  9. package/dist/web/assets/architecture-PBZL5I3N-DEO2f3VD.js +1 -0
  10. package/dist/web/assets/{architectureDiagram-2XIMDMQ5-DqAZP_F6.js → architectureDiagram-2XIMDMQ5-Z-4eN4za.js} +1 -1
  11. package/dist/web/assets/arrow-up-BYhx9ckd.js +1 -0
  12. package/dist/web/assets/{blockDiagram-WCTKOSBZ-h3cDF2vI.js → blockDiagram-WCTKOSBZ-BCLqzhuZ.js} +1 -1
  13. package/dist/web/assets/browser-tab-CjUzlPYv.js +1 -0
  14. package/dist/web/assets/{c4Diagram-IC4MRINW--pF1r5lr.js → c4Diagram-IC4MRINW-0Vp0Jeas.js} +1 -1
  15. package/dist/web/assets/channel-By7bn0Yq.js +1 -0
  16. package/dist/web/assets/chat-tab-moB4W7-w.js +8 -0
  17. package/dist/web/assets/chevron-right-5HgK6l7K.js +1 -0
  18. package/dist/web/assets/{chunk-4BX2VUAB-C3aZvW7B.js → chunk-4BX2VUAB-D4tOov49.js} +1 -1
  19. package/dist/web/assets/{chunk-55IACEB6-D5cABeB9.js → chunk-55IACEB6-DJ6BynZ4.js} +1 -1
  20. package/dist/web/assets/{chunk-7E7YKBS2-CkFGv6Zs.js → chunk-7E7YKBS2-CiyUJxNI.js} +1 -1
  21. package/dist/web/assets/{chunk-7R4GIKGN-Dvbyu4Zw.js → chunk-7R4GIKGN-Dv-4cAYn.js} +2 -2
  22. package/dist/web/assets/{chunk-C72U2L5F-CtqKiH4q.js → chunk-C72U2L5F-D21mS_6G.js} +1 -1
  23. package/dist/web/assets/{chunk-EGIJ26TM-Cpr87sBR.js → chunk-EGIJ26TM-DzqmU2Z7.js} +1 -1
  24. package/dist/web/assets/{chunk-FMBD7UC4-D23YVTOU.js → chunk-FMBD7UC4-DXncblvW.js} +1 -1
  25. package/dist/web/assets/{chunk-GEFDOKGD-tDjHsAUs.js → chunk-GEFDOKGD-D-pKjlVd.js} +1 -1
  26. package/dist/web/assets/chunk-GLR3WWYH-DKikpoJM.js +2 -0
  27. package/dist/web/assets/chunk-HHEYEP7N-C7vxA5i9.js +1 -0
  28. package/dist/web/assets/{chunk-JSJVCQXG-BBmymCjA.js → chunk-JSJVCQXG-99JzIdPr.js} +1 -1
  29. package/dist/web/assets/{chunk-KX2RTZJC-DP36BDiU.js → chunk-KX2RTZJC-CRq1OBZv.js} +1 -1
  30. package/dist/web/assets/{chunk-KYZI473N-Djw13C-3.js → chunk-KYZI473N-Bb0MCaIO.js} +1 -1
  31. package/dist/web/assets/{chunk-L3YUKLVL-HG_eMj_C.js → chunk-L3YUKLVL-C7qGJrfV.js} +1 -1
  32. package/dist/web/assets/{chunk-MX3YWQON-C2UEioMs.js → chunk-MX3YWQON-BpS_PtKp.js} +1 -1
  33. package/dist/web/assets/{chunk-NQ4KR5QH-DXUTQ-BL.js → chunk-NQ4KR5QH-z_blpjxi.js} +1 -1
  34. package/dist/web/assets/{chunk-O4XLMI2P-BsUWb9d0.js → chunk-O4XLMI2P-nDhi_cVu.js} +1 -1
  35. package/dist/web/assets/{chunk-OZEHJAEY-rG0P22U9.js → chunk-OZEHJAEY-BXhYx3nO.js} +1 -1
  36. package/dist/web/assets/{chunk-PQ6SQG4A-DX0xW7kO.js → chunk-PQ6SQG4A-TF58UVMU.js} +1 -1
  37. package/dist/web/assets/{chunk-PU5JKC2W-C7Gry6md.js → chunk-PU5JKC2W-ek7k4QVB.js} +1 -1
  38. package/dist/web/assets/chunk-QZHKN3VN-CYaTbeZf.js +1 -0
  39. package/dist/web/assets/{chunk-R5LLSJPH-CMY0PkRK.js → chunk-R5LLSJPH-CFwSJijQ.js} +1 -1
  40. package/dist/web/assets/{chunk-WL4C6EOR-CXuQvlyu.js → chunk-WL4C6EOR-ByUrSRin.js} +1 -1
  41. package/dist/web/assets/{chunk-XIRO2GV7-DRJEb7Zb.js → chunk-XIRO2GV7-Djlmrely.js} +1 -1
  42. package/dist/web/assets/{chunk-XPW4576I-BPEX8KhL.js → chunk-XPW4576I-BPQQBakK.js} +1 -1
  43. package/dist/web/assets/{chunk-XZSTWKYB-Cb0iqycX.js → chunk-XZSTWKYB-DxAOx4hG.js} +1 -1
  44. package/dist/web/assets/{chunk-YBOYWFTD-av5aeHLq.js → chunk-YBOYWFTD-rQG3QH5s.js} +1 -1
  45. package/dist/web/assets/classDiagram-VBA2DB6C-BA8Nj-_C.js +1 -0
  46. package/dist/web/assets/classDiagram-v2-RAHNMMFH-DjYu-6mn.js +1 -0
  47. package/dist/web/assets/clone-LRxlvnMj.js +1 -0
  48. package/dist/web/assets/code-editor-aQQZUc2m.js +2 -0
  49. package/dist/web/assets/columns-2-cEVJHYd7.js +1 -0
  50. package/dist/web/assets/{cose-bilkent-S5V4N54A-qudEiMCT.js → cose-bilkent-S5V4N54A-B_AWZsOP.js} +1 -1
  51. package/dist/web/assets/createLucideIcon-PuMiQgHl.js +1 -0
  52. package/dist/web/assets/{csv-preview-DUbHtTAS.js → csv-preview-ncSOnJSC.js} +2 -2
  53. package/dist/web/assets/{dagre-BFcnKyBF.js → dagre-DHq9bhnd.js} +1 -1
  54. package/dist/web/assets/{dagre-KLK3FWXG-C3O-MTLf.js → dagre-KLK3FWXG-BdJr7Byp.js} +1 -1
  55. package/dist/web/assets/database-viewer-ChyP1N3c.js +1 -0
  56. package/dist/web/assets/{diagram-E7M64L7V-DxPjK7_c.js → diagram-E7M64L7V-_db4pBVA.js} +1 -1
  57. package/dist/web/assets/{diagram-IFDJBPK2-sqTog_XV.js → diagram-IFDJBPK2-xKoeuiJx.js} +1 -1
  58. package/dist/web/assets/{diagram-P4PSJMXO-hzmp0GHK.js → diagram-P4PSJMXO-C8tjJsev.js} +1 -1
  59. package/dist/web/assets/diff-viewer-ktwO5JbX.js +4 -0
  60. package/dist/web/assets/{dist-CALwEtco.js → dist-DIV6WgAG.js} +1 -1
  61. package/dist/web/assets/{dist-DGDPTxs1.js → dist-ovWkrgO-.js} +1 -1
  62. package/dist/web/assets/{erDiagram-INFDFZHY-DLeYhAAT.js → erDiagram-INFDFZHY-BSh2z9Df.js} +1 -1
  63. package/dist/web/assets/extension-webview-Bx1TlP6q.js +3 -0
  64. package/dist/web/assets/{flowDiagram-PKNHOUZH-CRxlE9Sr.js → flowDiagram-PKNHOUZH-oYaovqyp.js} +1 -1
  65. package/dist/web/assets/{ganttDiagram-A5KZAMGK-BdjmoMLS.js → ganttDiagram-A5KZAMGK-DmL26q2P.js} +1 -1
  66. package/dist/web/assets/git-graph-BIrGMX6e.js +1 -0
  67. package/dist/web/assets/gitGraph-HDMCJU4V-Bwna3and.js +1 -0
  68. package/dist/web/assets/{gitGraphDiagram-K3NZZRJ6-BeHSX7kk.js → gitGraphDiagram-K3NZZRJ6-CMoukSrY.js} +1 -1
  69. package/dist/web/assets/{graphlib-Duh_bWLa.js → graphlib-BcsNnGcW.js} +1 -1
  70. package/dist/web/assets/index-C6KLr58u.js +37 -0
  71. package/dist/web/assets/index-DpBKDbIW.css +2 -0
  72. package/dist/web/assets/info-3K5VOQVL-_vRxVNUm.js +1 -0
  73. package/dist/web/assets/infoDiagram-LFFYTUFH-DWwumDkq.js +2 -0
  74. package/dist/web/assets/{isEmpty-B9L-Ge-H.js → isEmpty-bnrF3Qbc.js} +1 -1
  75. package/dist/web/assets/{ishikawaDiagram-PHBUUO56-Cu0Rt1Ok.js → ishikawaDiagram-PHBUUO56-D05_LyL7.js} +1 -1
  76. package/dist/web/assets/{journeyDiagram-4ABVD52K-CgDI-UG4.js → journeyDiagram-4ABVD52K-B_L20qMe.js} +1 -1
  77. package/dist/web/assets/jsx-runtime-kMwlnEGE.js +1 -0
  78. package/dist/web/assets/{kanban-definition-K7BYSVSG-h4g10UHL.js → kanban-definition-K7BYSVSG-CZ535BbZ.js} +1 -1
  79. package/dist/web/assets/keybindings-store-D3Y5c5uS.js +1 -0
  80. package/dist/web/assets/{line-B75-Rx70.js → line-CVvo3dRu.js} +1 -1
  81. package/dist/web/assets/{linear-Bcjv9FQt.js → linear-DP4mkX3m.js} +1 -1
  82. package/dist/web/assets/{markdown-renderer-VIZB1GXE.js → markdown-renderer-A7J2gdKT.js} +5 -5
  83. package/dist/web/assets/{mermaid-parser.core-8u2leTXI.js → mermaid-parser.core-C7UwoIh6.js} +2 -2
  84. package/dist/web/assets/{mindmap-definition-YRQLILUH-BaOBwb-W.js → mindmap-definition-YRQLILUH-x0MTutJp.js} +1 -1
  85. package/dist/web/assets/{ordinal-LFEjVtwQ.js → ordinal-_K3x1fkz.js} +1 -1
  86. package/dist/web/assets/packet-RMMSAZCW-DY5PNnZU.js +1 -0
  87. package/dist/web/assets/pie-UPGHQEXC-BHncZutv.js +1 -0
  88. package/dist/web/assets/{pieDiagram-SKSYHLDU-At5Kz0KK.js → pieDiagram-SKSYHLDU-C1Gjrtzy.js} +1 -1
  89. package/dist/web/assets/postgres-viewer-C9-Acry_.js +1 -0
  90. package/dist/web/assets/{quadrantDiagram-337W2JSQ-CdjGIDfw.js → quadrantDiagram-337W2JSQ-C8bzJCjQ.js} +1 -1
  91. package/dist/web/assets/radar-KQ55EAFF-DH0AOkUy.js +1 -0
  92. package/dist/web/assets/{requirementDiagram-Z7DCOOCP-B9F_Cx_p.js → requirementDiagram-Z7DCOOCP-pQyah6WB.js} +1 -1
  93. package/dist/web/assets/{sankeyDiagram-WA2Y5GQK-RolPi8bU.js → sankeyDiagram-WA2Y5GQK-T6RgG-N8.js} +1 -1
  94. package/dist/web/assets/{sequenceDiagram-2WXFIKYE-DM-tMAhx.js → sequenceDiagram-2WXFIKYE-BQDJ4CVs.js} +1 -1
  95. package/dist/web/assets/settings-tab-C17exmRv.js +1 -0
  96. package/dist/web/assets/sqlite-viewer-Dr5oWCWA.js +1 -0
  97. package/dist/web/assets/{stateDiagram-RAJIS63D-C4EMl6jf.js → stateDiagram-RAJIS63D-66vhiIuk.js} +1 -1
  98. package/dist/web/assets/stateDiagram-v2-FVOUBMTO-BGVqj_g9.js +1 -0
  99. package/dist/web/assets/tab-store-BOgTrqRr.js +1 -0
  100. package/dist/web/assets/table-DFevCOMd.js +1 -0
  101. package/dist/web/assets/tag-CXMT0QB6.js +1 -0
  102. package/dist/web/assets/{terminal-tab-XhKfb4ei.js → terminal-tab-CpyKvyfC.js} +1 -1
  103. package/dist/web/assets/{timeline-definition-YZTLITO2-A4PN_Efm.js → timeline-definition-YZTLITO2-DwZqB3nn.js} +1 -1
  104. package/dist/web/assets/treemap-KZPCXAKY-B2Xkyv-K.js +1 -0
  105. package/dist/web/assets/{use-monaco-theme-0p0-84jJ.js → use-monaco-theme-BjPAik5w.js} +1 -1
  106. package/dist/web/assets/{vennDiagram-LZ73GAT5-ywK7LMaH.js → vennDiagram-LZ73GAT5-s9Z71fz-.js} +1 -1
  107. package/dist/web/assets/{xychartDiagram-JWTSCODW-DylHYNtJ.js → xychartDiagram-JWTSCODW-DRa_TH4B.js} +1 -1
  108. package/dist/web/index.html +10 -9
  109. package/dist/web/sw.js +1 -1
  110. package/docs/code-standards.md +128 -1
  111. package/docs/codebase-summary.md +79 -12
  112. package/docs/extension-development-guide.md +532 -0
  113. package/docs/project-changelog.md +51 -1
  114. package/docs/project-roadmap.md +9 -3
  115. package/docs/system-architecture.md +432 -3
  116. package/package.json +6 -3
  117. package/packages/ext-database/package.json +41 -0
  118. package/packages/ext-database/src/connection-tree.ts +142 -0
  119. package/packages/ext-database/src/extension.ts +346 -0
  120. package/packages/ext-database/src/query-panel.ts +120 -0
  121. package/packages/ext-database/src/table-viewer-panel.ts +410 -0
  122. package/packages/ext-database/tsconfig.json +8 -0
  123. package/packages/vscode-compat/package.json +16 -0
  124. package/packages/vscode-compat/src/commands.ts +39 -0
  125. package/packages/vscode-compat/src/context.ts +65 -0
  126. package/packages/vscode-compat/src/disposable.ts +21 -0
  127. package/packages/vscode-compat/src/env.ts +20 -0
  128. package/packages/vscode-compat/src/event-emitter.ts +28 -0
  129. package/packages/vscode-compat/src/index.ts +93 -0
  130. package/packages/vscode-compat/src/not-supported.ts +15 -0
  131. package/packages/vscode-compat/src/types.ts +167 -0
  132. package/packages/vscode-compat/src/uri.ts +65 -0
  133. package/packages/vscode-compat/src/window.ts +229 -0
  134. package/packages/vscode-compat/src/workspace.ts +76 -0
  135. package/packages/vscode-compat/tsconfig.json +10 -0
  136. package/src/cli/commands/autostart.ts +1 -1
  137. package/src/cli/commands/ext-cmd.ts +121 -0
  138. package/src/cli/commands/restart.ts +9 -1
  139. package/src/cli/commands/status.ts +19 -0
  140. package/src/index.ts +5 -3
  141. package/src/providers/claude-agent-sdk.ts +221 -17
  142. package/src/providers/cli-provider-base.ts +6 -0
  143. package/src/server/index.ts +55 -155
  144. package/src/server/routes/chat.ts +81 -11
  145. package/src/server/routes/extensions.ts +81 -0
  146. package/src/server/routes/project-scoped.ts +2 -0
  147. package/src/server/routes/settings.ts +27 -0
  148. package/src/server/routes/workspace.ts +35 -0
  149. package/src/server/ws/chat.ts +9 -3
  150. package/src/server/ws/extensions.ts +175 -0
  151. package/src/services/account-selector.service.ts +14 -5
  152. package/src/services/account.service.ts +7 -7
  153. package/src/services/claude-usage.service.ts +11 -11
  154. package/src/services/cloud-ws.service.ts +228 -0
  155. package/src/services/cloud.service.ts +1 -0
  156. package/src/services/contribution-registry.ts +110 -0
  157. package/src/services/db.service.ts +181 -4
  158. package/src/services/extension-host-worker.ts +160 -0
  159. package/src/services/extension-installer.ts +112 -0
  160. package/src/services/extension-manifest.ts +65 -0
  161. package/src/services/extension-rpc-handlers.ts +235 -0
  162. package/src/services/extension-rpc.ts +105 -0
  163. package/src/services/extension.service.ts +228 -0
  164. package/src/services/mcp-config.service.ts +15 -6
  165. package/src/services/supervisor.ts +271 -25
  166. package/src/types/api.ts +1 -0
  167. package/src/types/chat.ts +4 -0
  168. package/src/types/extension-messages.ts +64 -0
  169. package/src/types/extension.ts +131 -0
  170. package/src/web/app.tsx +69 -48
  171. package/src/web/components/chat/account-rotation-settings.tsx +163 -0
  172. package/src/web/components/chat/chat-history-bar.tsx +106 -10
  173. package/src/web/components/chat/chat-tab.tsx +15 -10
  174. package/src/web/components/chat/chat-welcome.tsx +148 -0
  175. package/src/web/components/chat/message-input.tsx +29 -29
  176. package/src/web/components/chat/message-list.tsx +19 -6
  177. package/src/web/components/chat/session-picker.tsx +80 -32
  178. package/src/web/components/chat/usage-badge.tsx +83 -10
  179. package/src/web/components/extensions/extension-inputbox.tsx +92 -0
  180. package/src/web/components/extensions/extension-quickpick.tsx +194 -0
  181. package/src/web/components/extensions/extension-tree-view.tsx +240 -0
  182. package/src/web/components/extensions/extension-webview.tsx +83 -0
  183. package/src/web/components/layout/command-palette.tsx +22 -2
  184. package/src/web/components/layout/editor-panel.tsx +163 -18
  185. package/src/web/components/layout/mobile-nav.tsx +2 -1
  186. package/src/web/components/layout/sidebar.tsx +21 -3
  187. package/src/web/components/layout/status-bar.tsx +64 -0
  188. package/src/web/components/layout/tab-bar.tsx +2 -0
  189. package/src/web/components/layout/tab-content.tsx +5 -0
  190. package/src/web/components/layout/upgrade-banner.tsx +15 -5
  191. package/src/web/components/settings/change-password-section.tsx +128 -0
  192. package/src/web/components/settings/extension-manager-section.tsx +214 -0
  193. package/src/web/components/settings/settings-tab.tsx +9 -2
  194. package/src/web/components/shared/connection-lost-overlay.tsx +89 -0
  195. package/src/web/hooks/use-chat.ts +28 -0
  196. package/src/web/hooks/use-extension-ws.ts +181 -0
  197. package/src/web/hooks/use-global-keybindings.ts +18 -2
  198. package/src/web/hooks/use-server-reload.ts +9 -0
  199. package/src/web/hooks/use-url-sync.ts +173 -21
  200. package/src/web/stores/connection-store.ts +39 -0
  201. package/src/web/stores/extension-store.ts +204 -0
  202. package/src/web/stores/panel-store.ts +63 -9
  203. package/src/web/stores/panel-utils.ts +145 -3
  204. package/src/web/stores/settings-store.ts +7 -2
  205. package/src/web/stores/tab-store.ts +2 -1
  206. package/tsconfig.json +3 -1
  207. package/dist/web/assets/api-settings-CEMxVMCV.js +0 -1
  208. package/dist/web/assets/architecture-PBZL5I3N-CFzkFKEL.js +0 -1
  209. package/dist/web/assets/arrow-up--LjUXLEt.js +0 -1
  210. package/dist/web/assets/browser-tab-D1Zua62g.js +0 -1
  211. package/dist/web/assets/channel-C2fMafck.js +0 -1
  212. package/dist/web/assets/chat-tab-BnD27Vp9.js +0 -7
  213. package/dist/web/assets/chevron-right-CHnjJt4E.js +0 -1
  214. package/dist/web/assets/chunk-GLR3WWYH-DBdWQ3zy.js +0 -2
  215. package/dist/web/assets/chunk-HHEYEP7N-BBw_z0fW.js +0 -1
  216. package/dist/web/assets/chunk-QZHKN3VN-DFKFM_C1.js +0 -1
  217. package/dist/web/assets/classDiagram-VBA2DB6C-Dp4Kk3Yb.js +0 -1
  218. package/dist/web/assets/classDiagram-v2-RAHNMMFH-D8IvcV_B.js +0 -1
  219. package/dist/web/assets/clone-B2hUek6n.js +0 -1
  220. package/dist/web/assets/code-editor-DGRg8stf.js +0 -2
  221. package/dist/web/assets/columns-2-DbesTfa7.js +0 -1
  222. package/dist/web/assets/database-viewer-DxCXZQcE.js +0 -1
  223. package/dist/web/assets/diff-viewer-C1sDJG35.js +0 -4
  224. package/dist/web/assets/git-graph-BDn-EiGE.js +0 -1
  225. package/dist/web/assets/gitGraph-HDMCJU4V-CNlas3Rz.js +0 -1
  226. package/dist/web/assets/index-Bun94AK3.js +0 -37
  227. package/dist/web/assets/index-Db8uky1a.css +0 -2
  228. package/dist/web/assets/info-3K5VOQVL-BDzTLc11.js +0 -1
  229. package/dist/web/assets/infoDiagram-LFFYTUFH-ZZmpgc6t.js +0 -2
  230. package/dist/web/assets/jsx-runtime-BRW_vwa9.js +0 -1
  231. package/dist/web/assets/keybindings-store-COmK4Dte.js +0 -1
  232. package/dist/web/assets/packet-RMMSAZCW-IVa5F-go.js +0 -1
  233. package/dist/web/assets/pie-UPGHQEXC-CvXHKAzp.js +0 -1
  234. package/dist/web/assets/postgres-viewer-CvQZ8gkh.js +0 -1
  235. package/dist/web/assets/radar-KQ55EAFF-Z-Tr5wtS.js +0 -1
  236. package/dist/web/assets/settings-tab-RCnvZ29H.js +0 -1
  237. package/dist/web/assets/sqlite-viewer-CEEm2W4C.js +0 -1
  238. package/dist/web/assets/stateDiagram-v2-FVOUBMTO-B-UjZch3.js +0 -1
  239. package/dist/web/assets/tab-store-Bjh6bXFP.js +0 -1
  240. package/dist/web/assets/table-CQVQM2SB.js +0 -1
  241. package/dist/web/assets/tag-Q2dZiSPX.js +0 -1
  242. package/dist/web/assets/treemap-KZPCXAKY-C9TYRE0k.js +0 -1
  243. /package/dist/web/assets/{api-client-BKIT_Qeg.js → api-client-BfBM3I7n.js} +0 -0
  244. /package/dist/web/assets/{array-DqLCdDFv.js → array-B9UHiPd-.js} +0 -0
  245. /package/dist/web/assets/{cytoscape.esm-CWPXKqbJ.js → cytoscape.esm-BW-DbntU.js} +0 -0
  246. /package/dist/web/assets/{defaultLocale-CrJzLgRD.js → defaultLocale-5eAKkKJC.js} +0 -0
  247. /package/dist/web/assets/{dist-Cep75xXf.js → dist-CSJdAyA9.js} +0 -0
  248. /package/dist/web/assets/{init-C0r9Gk5G.js → init-DlZdxViB.js} +0 -0
  249. /package/dist/web/assets/{isArrayLikeObject-CGBoxvCD.js → isArrayLikeObject-B_v2FtYn.js} +0 -0
  250. /package/dist/web/assets/{katex-DzXRfQ_m.js → katex-Bqvo_ZG0.js} +0 -0
  251. /package/dist/web/assets/{lib-BeaDXEkP.js → lib-BQ34Db2e.js} +0 -0
  252. /package/dist/web/assets/{math-y9zN1W-N.js → math-069Z4SuC.js} +0 -0
  253. /package/dist/web/assets/{path-DIKpVbHL.js → path-6uRLdFF7.js} +0 -0
  254. /package/dist/web/assets/{rough.esm-nHaDi0Kw.js → rough.esm-JX0wREDd.js} +0 -0
  255. /package/dist/web/assets/{src-Dw4QhedI.js → src-BqX54PbV.js} +0 -0
  256. /package/dist/web/assets/{utils-DMiycH3O.js → utils-BNytJOb1.js} +0 -0
@@ -0,0 +1,532 @@
1
+ # PPM Extension Development Guide
2
+
3
+ Build extensions that add features to PPM. Extensions are TypeScript packages that hook into PPM's UI, commands, file system, and configuration.
4
+
5
+ ---
6
+
7
+ ## Extension Basics
8
+
9
+ ### Structure
10
+
11
+ A PPM extension is a directory with `package.json` manifest and TypeScript entry point:
12
+
13
+ ```
14
+ my-extension/
15
+ ├── package.json
16
+ ├── tsconfig.json
17
+ ├── src/
18
+ │ └── extension.ts # Entry point with activate() & deactivate()
19
+ ├── webview/ # Optional: webview HTML/CSS/JS
20
+ │ └── index.html
21
+ └── README.md
22
+ ```
23
+
24
+ ### Manifest (package.json)
25
+
26
+ ```json
27
+ {
28
+ "name": "@org/ext-myfeature",
29
+ "version": "1.0.0",
30
+ "main": "src/extension.ts",
31
+ "engines": { "ppm": ">=0.9.0" },
32
+ "activationEvents": [
33
+ "onCommand:myext.doSomething",
34
+ "onView:myext.sidebar"
35
+ ],
36
+ "contributes": {
37
+ "commands": [
38
+ { "command": "myext.doSomething", "title": "My Feature: Do Something" }
39
+ ],
40
+ "views": {
41
+ "sidebar": [
42
+ { "id": "myext.sidebar", "name": "My Sidebar", "type": "tree" }
43
+ ]
44
+ },
45
+ "menus": {
46
+ "commandPalette": [
47
+ { "command": "myext.doSomething" }
48
+ ]
49
+ },
50
+ "configuration": {
51
+ "properties": {
52
+ "myext.setting": { "type": "boolean", "default": true }
53
+ }
54
+ }
55
+ },
56
+ "ppm": {
57
+ "displayName": "My Feature",
58
+ "icon": "star",
59
+ "webviewDir": "webview"
60
+ }
61
+ }
62
+ ```
63
+
64
+ **Key fields:**
65
+ - `main` — TypeScript file with `export function activate(context, vscode) {}`
66
+ - `engines.ppm` — minimum PPM version (not `vscode`)
67
+ - `activationEvents` — when extension loads (commands, views, or startup)
68
+ - `contributes` — UI elements: commands, views, menus, config
69
+ - `ppm.displayName` — human-readable name in extension UI
70
+ - `ppm.icon` — icon name (standard VSCode icon set)
71
+ - `ppm.webviewDir` — directory containing webview HTML
72
+
73
+ ---
74
+
75
+ ## Activation & Lifecycle
76
+
77
+ Extensions run in an isolated Bun Worker thread. The Worker receives `context` and `vscode` API:
78
+
79
+ ```typescript
80
+ /** Runs when activation event fires */
81
+ export function activate(context: ExtensionContext, vscode: VscodeApi): void {
82
+ console.log("Extension activated");
83
+
84
+ // Register commands, listeners, views, etc.
85
+ context.subscriptions.push(
86
+ vscode.commands.registerCommand("myext.foo", () => {
87
+ // ...
88
+ })
89
+ );
90
+ }
91
+
92
+ /** Cleanup on disable/uninstall */
93
+ export function deactivate(): void {
94
+ console.log("Extension deactivated");
95
+ // Browser/streams are auto-closed; use this for final logging
96
+ }
97
+ ```
98
+
99
+ **Important:** Push ALL disposables (commands, listeners, panels, views) to `context.subscriptions` for automatic cleanup.
100
+
101
+ ---
102
+
103
+ ## API Surface
104
+
105
+ ### Commands
106
+
107
+ Register and execute commands:
108
+
109
+ ```typescript
110
+ // Register
111
+ const cmd = vscode.commands.registerCommand("myext.foo", (arg1, arg2) => {
112
+ return "result";
113
+ });
114
+ context.subscriptions.push(cmd);
115
+
116
+ // Execute (from command palette or button click)
117
+ // vscode.commands.executeCommand("myext.foo", arg1, arg2);
118
+ ```
119
+
120
+ ### Messages (Dialogs)
121
+
122
+ ```typescript
123
+ // Information
124
+ await vscode.window.showInformationMessage("Done!", "OK", "Cancel");
125
+
126
+ // Warning
127
+ await vscode.window.showWarningMessage("Are you sure?", "Yes", "No");
128
+
129
+ // Error
130
+ await vscode.window.showErrorMessage("Failed!", "Retry");
131
+ ```
132
+
133
+ ### Quick Pick
134
+
135
+ ```typescript
136
+ const selected = await vscode.window.showQuickPick(
137
+ [
138
+ { label: "Option A", description: "First choice" },
139
+ { label: "Option B", description: "Second choice" }
140
+ ],
141
+ {
142
+ title: "Choose one",
143
+ placeHolder: "Start typing to filter...",
144
+ canPickMany: false,
145
+ matchOnDescription: true
146
+ }
147
+ );
148
+ ```
149
+
150
+ ### Input Box
151
+
152
+ ```typescript
153
+ const input = await vscode.window.showInputBox({
154
+ title: "Enter name",
155
+ prompt: "What is your name?",
156
+ placeHolder: "John Doe",
157
+ password: false
158
+ });
159
+ ```
160
+
161
+ ### Status Bar
162
+
163
+ ```typescript
164
+ const item = vscode.window.createStatusBarItem(
165
+ vscode.StatusBarAlignment.Right,
166
+ 100 // priority
167
+ );
168
+ item.text = "⚙️ Status";
169
+ item.tooltip = "Click for menu";
170
+ item.command = "myext.openMenu";
171
+ item.show();
172
+ context.subscriptions.push(item);
173
+ ```
174
+
175
+ ### Tree View
176
+
177
+ Sidebar tree for displaying hierarchical data:
178
+
179
+ ```typescript
180
+ class MyTreeProvider {
181
+ getChildren(element?: NodeData): Promise<NodeData[]> {
182
+ if (!element) {
183
+ // Root items
184
+ return [
185
+ { id: "1", label: "Item 1" },
186
+ { id: "2", label: "Item 2" }
187
+ ];
188
+ }
189
+ // Children of element
190
+ return [];
191
+ }
192
+
193
+ getTreeItem(element: NodeData) {
194
+ return {
195
+ id: element.id,
196
+ label: element.label,
197
+ collapsibleState: element.children?.length ?
198
+ vscode.TreeItemCollapsibleState.Collapsed :
199
+ vscode.TreeItemCollapsibleState.None,
200
+ command: { command: "myext.selectNode", arguments: [element.id] }
201
+ };
202
+ }
203
+ }
204
+
205
+ const provider = new MyTreeProvider();
206
+ const tree = vscode.window.createTreeView("myext.tree", {
207
+ treeDataProvider: provider
208
+ });
209
+ context.subscriptions.push(tree);
210
+ ```
211
+
212
+ **viewId** must match the `contributes.views[].id` in package.json.
213
+
214
+ ### Webview Panel
215
+
216
+ Sandboxed iframe for custom UI:
217
+
218
+ ```typescript
219
+ const panel = vscode.window.createWebviewPanel(
220
+ "myext.panel", // viewType (unique)
221
+ "My Panel", // title (shown in tab)
222
+ vscode.ViewColumn.Active
223
+ );
224
+
225
+ // Set HTML (scripts auto-sandboxed, allow-scripts only)
226
+ panel.webview.html = `
227
+ <!DOCTYPE html>
228
+ <html>
229
+ <body>
230
+ <button id="btn">Click me</button>
231
+ <script>
232
+ const vscode = acquireVsCodeApi();
233
+ document.getElementById("btn").onclick = () => {
234
+ vscode.postMessage({ type: "buttonClicked" });
235
+ };
236
+
237
+ window.addEventListener("message", (e) => {
238
+ console.log("From extension:", e.data);
239
+ });
240
+ </script>
241
+ </body>
242
+ </html>
243
+ `;
244
+
245
+ // Receive messages from webview
246
+ panel.webview.onDidReceiveMessage(async (msg) => {
247
+ if (msg.type === "buttonClicked") {
248
+ await vscode.window.showInformationMessage("Button clicked!");
249
+ await panel.webview.postMessage({ type: "response", data: "Hello from extension" });
250
+ }
251
+ });
252
+
253
+ context.subscriptions.push(panel.onDidDispose(() => {
254
+ console.log("Panel closed");
255
+ }));
256
+ ```
257
+
258
+ ### Configuration
259
+
260
+ ```typescript
261
+ // Read
262
+ const config = vscode.workspace.getConfiguration("myext");
263
+ const timeout = config.get<number>("timeout", 5000);
264
+
265
+ // Update
266
+ await config.update("timeout", 10000, vscode.ConfigurationTarget.Global);
267
+ ```
268
+
269
+ ### Storage (Memento)
270
+
271
+ Persist data across sessions:
272
+
273
+ ```typescript
274
+ // Global (user-wide)
275
+ await context.globalState.update("key", { foo: "bar" });
276
+ const value = context.globalState.get("key");
277
+
278
+ // Workspace-scoped
279
+ await context.workspaceState.update("project", "data");
280
+ ```
281
+
282
+ ### Utilities
283
+
284
+ ```typescript
285
+ // URI
286
+ const uri = vscode.Uri.file("/path/to/file");
287
+ const webUri = panel.webview.asWebviewUri(uri);
288
+
289
+ // Disposable
290
+ const disposable = vscode.Disposable.from(
291
+ vscode.commands.registerCommand("a", () => {}),
292
+ vscode.commands.registerCommand("b", () => {})
293
+ );
294
+
295
+ // EventEmitter
296
+ const emitter = new vscode.EventEmitter<string>();
297
+ emitter.fire("event data"); // Notify listeners
298
+ // const unsub = emitter.event((data) => {});
299
+ ```
300
+
301
+ ---
302
+
303
+ ## API Support Matrix
304
+
305
+ | Feature | Status | Notes |
306
+ |---------|--------|-------|
307
+ | **Commands** | ✅ Supported | `registerCommand`, `executeCommand` |
308
+ | **Messages** | ✅ Supported | Info, warning, error dialogs |
309
+ | **Quick Pick** | ✅ Supported | Single/multi-select, filtering |
310
+ | **Input Box** | ✅ Supported | Text input with validation (client-side) |
311
+ | **Status Bar** | ✅ Supported | Left/right alignment, priority, commands |
312
+ | **Tree View** | ✅ Supported | Hierarchical sidebar trees |
313
+ | **Webview Panel** | ✅ Supported | Sandboxed iframe, 2-way messaging |
314
+ | **Workspace Config** | ✅ Supported | Read/write user & workspace settings |
315
+ | **Workspace FS** | ⚠️ Partial | Read, write, stat, readDirectory (no watch) |
316
+ | **Storage (Memento)** | ✅ Supported | Global & workspace state, auto-persisted |
317
+ | **Uri** | ✅ Supported | File/webview URI utilities |
318
+ | **EventEmitter** | ✅ Supported | Custom event streams |
319
+ | **Disposable** | ✅ Supported | Cleanup & resource management |
320
+ | **Environment** | ✅ Supported | App name, machine ID |
321
+ | **Languages** | ❌ Not supported | Syntax highlighting, language services |
322
+ | **Debug** | ❌ Not supported | Debugger integration |
323
+ | **Tasks** | ❌ Not supported | Task provider, task execution |
324
+ | **SCM** | ❌ Not supported | Source control providers |
325
+ | **Notebooks** | ❌ Not supported | Notebook editing |
326
+ | **Authentication** | ❌ Not supported | Auth provider, sessions |
327
+ | **Tests** | ❌ Not supported | Test controller |
328
+
329
+ ---
330
+
331
+ ## Webview Details
332
+
333
+ ### Sandbox
334
+
335
+ Webviews run in a sandboxed iframe with **`allow-scripts` only** — no inline styles, event handlers, or external scripts. Use a bundler or inline `<style>` tags.
336
+
337
+ ### Communication
338
+
339
+ **From webview to extension:**
340
+ ```typescript
341
+ const vscode = acquireVsCodeApi();
342
+ vscode.postMessage({ type: "action", data: "..." });
343
+ ```
344
+
345
+ **From extension to webview:**
346
+ ```typescript
347
+ panel.webview.postMessage({ type: "update", data: "..." });
348
+ panel.webview.onDidReceiveMessage((msg) => {
349
+ console.log("From webview:", msg);
350
+ });
351
+ ```
352
+
353
+ ### HTML Setup
354
+
355
+ ```html
356
+ <!DOCTYPE html>
357
+ <html>
358
+ <head>
359
+ <style>
360
+ body { font-family: sans-serif; padding: 20px; }
361
+ button { padding: 8px 16px; cursor: pointer; }
362
+ </style>
363
+ </head>
364
+ <body>
365
+ <h1>My Webview</h1>
366
+ <button id="btn">Send Message</button>
367
+
368
+ <script>
369
+ const vscode = acquireVsCodeApi();
370
+
371
+ document.getElementById("btn").onclick = () => {
372
+ vscode.postMessage({ type: "click", time: Date.now() });
373
+ };
374
+
375
+ window.addEventListener("message", (e) => {
376
+ const { type, data } = e.data;
377
+ if (type === "update") {
378
+ document.body.innerHTML += `<p>${data}</p>`;
379
+ }
380
+ });
381
+ </script>
382
+ </body>
383
+ </html>
384
+ ```
385
+
386
+ ---
387
+
388
+ ## Porting from VSCode
389
+
390
+ PPM uses the same API shape as VSCode. Porting is straightforward:
391
+
392
+ ### 1. Update imports
393
+
394
+ **Before (VSCode):**
395
+ ```typescript
396
+ import * as vscode from "vscode";
397
+
398
+ export function activate(context: vscode.ExtensionContext) {
399
+ // ...
400
+ }
401
+ ```
402
+
403
+ **After (PPM):**
404
+ ```typescript
405
+ import type { ExtensionContext } from "@ppm/vscode-compat";
406
+
407
+ export function activate(context: ExtensionContext, vscode: any) {
408
+ // vscode is passed as 2nd argument
409
+ // ...
410
+ }
411
+ ```
412
+
413
+ Or import for type checking:
414
+ ```typescript
415
+ import * as vscode from "@ppm/vscode-compat";
416
+
417
+ export function activate(context: ExtensionContext, _vscode: typeof vscode) {
418
+ // ...
419
+ }
420
+ ```
421
+
422
+ ### 2. Update package.json
423
+
424
+ ```json
425
+ {
426
+ "engines": { "ppm": ">=0.9.0" } // was vscode
427
+ }
428
+ ```
429
+
430
+ ### 3. Check API support
431
+
432
+ Verify unsupported features aren't used (see API Support Matrix above).
433
+
434
+ ### 4. Test
435
+
436
+ ```bash
437
+ ppm ext dev ./path/to/extension
438
+ ```
439
+
440
+ ---
441
+
442
+ ## Example: Database Viewer
443
+
444
+ See `packages/ext-database/` in the PPM repo for a complete reference extension:
445
+
446
+ - **Tree view** of database connections
447
+ - **Commands** to open query panel
448
+ - **Webview panel** for SQL editor
449
+ - **Status bar** icon
450
+ - **Configuration** (maxRows, autoConnect)
451
+ - **RPC to backend** for queries
452
+
453
+ ```typescript
454
+ export function activate(context: ExtensionContext, vscode: any) {
455
+ // Tree view
456
+ const provider = new ConnectionTreeProvider();
457
+ const tree = vscode.window.createTreeView("ppm-db.connections", {
458
+ treeDataProvider: provider
459
+ });
460
+ context.subscriptions.push(tree);
461
+
462
+ // Command
463
+ context.subscriptions.push(
464
+ vscode.commands.registerCommand("ppm-db.openViewer", (connId) => {
465
+ const panel = vscode.window.createWebviewPanel(
466
+ "ppm-db.query",
467
+ "Query",
468
+ vscode.ViewColumn.Active
469
+ );
470
+ panel.webview.html = `...`;
471
+ panel.webview.onDidReceiveMessage(async (msg) => {
472
+ if (msg.type === "query") {
473
+ const res = await fetch(`/api/db/${connId}/query`, {
474
+ method: "POST",
475
+ body: JSON.stringify({ sql: msg.sql })
476
+ });
477
+ await panel.webview.postMessage(await res.json());
478
+ }
479
+ });
480
+ })
481
+ );
482
+
483
+ // Status bar
484
+ const status = vscode.window.createStatusBarItem(
485
+ vscode.StatusBarAlignment.Right
486
+ );
487
+ status.text = "DB";
488
+ status.show();
489
+ context.subscriptions.push(status);
490
+ }
491
+ ```
492
+
493
+ ---
494
+
495
+ ## Best Practices
496
+
497
+ 1. **Cleanup**: Always push disposables to `context.subscriptions`.
498
+ 2. **Errors**: Catch and show errors via `showErrorMessage()`.
499
+ 3. **Async**: Use `await` for RPC calls; block UI during long operations.
500
+ 4. **Storage**: Use `Memento` for persistence, not file system (unless granted access).
501
+ 5. **Webview Security**: Never use `eval()`, `innerHTML` with user input, or external CDNs.
502
+ 6. **Activation**: Lazy-load expensive code via activation events, not on require.
503
+ 7. **Testing**: Use `ppm ext dev` to load locally before publishing.
504
+
505
+ ---
506
+
507
+ ## Publishing
508
+
509
+ Register your extension with PPM's extension registry (coming in v0.9). For now, distribute via npm or GitHub.
510
+
511
+ ---
512
+
513
+ ## Troubleshooting
514
+
515
+ | Issue | Solution |
516
+ |-------|----------|
517
+ | Extension doesn't activate | Check `activationEvents` in package.json matches your commands/views |
518
+ | Command not found | Verify `contributes.commands[].command` id |
519
+ | Tree view empty | Implement `getChildren()` and `getTreeItem()` in provider |
520
+ | Webview blank | Check `panel.webview.html` is valid HTML; test in browser first |
521
+ | RPC timeout | Network issue or long-running request; add retry logic |
522
+ | Storage not persisted | Use `Memento.update()`, not local variables |
523
+ | Unsupported API error | Check API Support Matrix; file issue if critical |
524
+
525
+ ---
526
+
527
+ ## Learn More
528
+
529
+ - [VSCode Extension API](https://code.visualstudio.com/api) — reference (PPM subset)
530
+ - `packages/ext-database/` — working example
531
+ - `packages/vscode-compat/src/` — API implementation
532
+ - GitHub issues — feature requests & bugs
@@ -2,7 +2,57 @@
2
2
 
3
3
  All notable changes to PPM are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/).
4
4
 
5
- **Current Version:** v0.8.63
5
+ **Current Version:** v0.9.0
6
+
7
+ ---
8
+
9
+ ## [0.9.0] — 2026-04-03
10
+
11
+ ### Added
12
+ - **Extension System (Phase 1-6)** — VSCode-compatible npm extensions with Bun Worker isolation, RPC protocol, @ppm/vscode-compat API shim, UI components (TreeView, WebviewPanel, StatusBar, QuickPick, InputBox), WS bridge, ext-database demo extension, Extension Manager UI, CLI support
13
+ - **Multi-Provider AI** — ProviderInterface, CliProvider base, CursorCliProvider with NDJSON streaming, provider selector UI
14
+ - **MCP Server Management** — REST API CRUD, SQLite storage, Settings UI, auto-import from ~/.claude.json, SDK integration
15
+ - **ext-database extension** — Connection tree with color dots/badges/actions, table viewer webview with data grid/inline editing/pagination/SQL panel, add connection via QuickPick+InputBox flow
16
+
17
+ ### Technical Details
18
+ - Extension architecture: npm packages isolated in Bun Workers, communicate via RPC, manifest-driven contribution points (commands, views, menus, configuration)
19
+ - Multi-provider: Tier 1 (Claude Agent SDK, full agentic), Tier 2 (Cursor CLI, agentic via own tool system)
20
+ - MCP: Servers passed to SDK as `mcpServers`, tools auto-allowed via `mcp__*` wildcard
21
+
22
+ ---
23
+
24
+ ## [0.8.77] — 2026-04-01
25
+
26
+ ### Added
27
+ - **Deterministic Tab URLs + Backend Workspace Sync**
28
+ - Tab IDs now deterministic ({type}:{identifier}) instead of random (tab-xxxx)
29
+ - URL format changed: `/project/{name}/{tabType}/{identifier}` (e.g., `/project/ppm/editor/src/index.ts`)
30
+ - New `workspace_state` database table (schema v10) persists tab layout per project
31
+ - GET/PUT `/api/project/:name/workspace` endpoints for server-side persistence
32
+ - Frontend syncs workspace layout to server with 1.5s debounce
33
+ - Deep linking from URL auto-creates tabs if missing
34
+ - Latest-wins conflict resolution: server timestamp > client localStorage
35
+ - Tab ID patterns standardized: `editor:path`, `chat:provider/sessionId`, `terminal:index`, etc.
36
+ - Migration from random IDs to deterministic IDs on first load
37
+
38
+ ### Technical Details
39
+ - **Files Created:**
40
+ - `src/server/routes/workspace.ts` — Workspace GET/PUT endpoints
41
+ - `src/web/hooks/use-workspace-sync.ts` — Server sync orchestration with debounce
42
+ - **Files Modified:**
43
+ - `src/services/db.service.ts` — Added workspace_state table (schema v10), helper functions
44
+ - `src/web/stores/panel-utils.ts` — Deterministic tab ID derivation logic
45
+ - `src/web/hooks/use-url-sync.ts` — URL parsing/building with new format
46
+ - `src/web/stores/panel-store.ts` — Load workspace from server on project switch
47
+ - `src/web/stores/tab-store.ts` — Tab interface updated with metadata
48
+ - **Breaking Changes:** URLs changed; old `/project/{name}/tab/{id}` URLs redirected or ignored (fallback to project root)
49
+ - **Migration:** Client-side: old random tab IDs migrated to deterministic format on first load
50
+
51
+ ### Benefits
52
+ - **Shareable deep links** — URLs point to specific files/chats (e.g., `/project/ppm/editor/src/index.ts`)
53
+ - **Cross-device persistence** — Workspace layout saved on server, restored on any device
54
+ - **URL-driven navigation** — Paste URL to recreate workspace state
55
+ - **Conflict-free sync** — Latest timestamp wins; no manual merge dialogs
6
56
 
7
57
  ---
8
58
 
@@ -58,25 +58,31 @@ PPM is the **lightest path from phone to code** — a self-hosted, BYOK, multi-d
58
58
 
59
59
  **Theme:** Multi-provider AI (Claude + Cursor) + extension system. Ship a focused release, expand providers later.
60
60
 
61
- **Overall progress: ~53%** (2/3 features complete, merge all at 100%)
61
+ **Overall progress: 100%** (All 3 features complete)
62
62
 
63
63
  | Feature | Priority | Status | Description |
64
64
  |---------|----------|--------|-------------|
65
65
  | **Multi-provider AI** | Critical | ✅ Done | ProviderInterface, registry, Cursor CLI, CLI provider base, UI provider/model selector, permission mode selector, system prompt customization, comprehensive tests — all on beta branch. |
66
66
  | **MCP Management** | Medium | ✅ Done | REST API (CRUD + import), SQLite storage, Settings UI, auto-import from `~/.claude.json`, validation, SDK integration. |
67
- | **Extension architecture** | High | 🔴 0% | Dynamic extension loading. Extensions = npm packages. First extension: extract DB viewer from core. Extension API: register routes, UI panels, sidebar tabs, skills. Config: `"extensions": ["@ppm/ext-database", "@ppm/ext-docker"]`. |
67
+ | **Extension architecture (Phase 1-6)** | High | Done | VSCode-compatible npm extensions, Bun Worker isolation, RPC protocol, state persistence, contribution registry, CLI support, dev mode. @ppm/vscode-compat API shim (commands, window, workspace). UI components (StatusBar, TreeView, WebviewPanel, QuickPick, InputBox). WS bridge for real-time ext↔browser communication. First extension: ext-database with tree view + SQL query panel. Unit tests + extension dev guide. |
68
68
 
69
69
  **Multi-provider — v0.9 scope (reduced):**
70
70
  - Tier 1 (full agentic): Claude Agent SDK — file edit, terminal, git, full autonomy
71
71
  - Tier 2 (agentic CLI): Cursor — agentic via its own tool system
72
72
  - Provider interface is clean enough to add more providers later without refactor
73
73
 
74
- **Deferred to v0.9.5+:**
74
+ **Deferred to v0.9.5+ (Multi-Provider Phase 2):**
75
75
  - Gemini CLI (Tier 2)
76
76
  - OpenAI Codex (Tier 2)
77
77
  - Tier 3 (chat-only): Any OpenAI-compatible API
78
78
  - Chinese providers (DeepSeek, Qwen) — v1.0+
79
79
 
80
+ **Extension System — remaining for v0.10+:**
81
+ - Settings UI auto-generation from manifest
82
+ - Hot reload during dev (`ppm ext dev --watch`)
83
+ - Extension template scaffold (`ppm ext create <name>`)
84
+ - Extension marketplace (v1.0)
85
+
80
86
  **Extension architecture — design principles:**
81
87
  - Extensions are npm packages: `ppm ext install @ppm/ext-database`
82
88
  - Extension manifest defines: skills, UI panels, sidebar tabs, routes, settings schema