@hienlh/ppm 0.17.16 → 0.17.17
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.
- package/CHANGELOG.md +14 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- package/assets/skills/ppm/references/http-api.md +5 -1
- package/dist/web/assets/{ai-resource-editor-CsossqDO.js → ai-resource-editor-37UxM2lK.js} +1 -1
- package/dist/web/assets/{angular-html-CkxY2iBQ.js → angular-html-2g8YGiJY.js} +1 -1
- package/dist/web/assets/{angular-ts-BePeGkkC.js → angular-ts-BwSmoLfh.js} +1 -1
- package/dist/web/assets/{api-settings-DAk7D-NP.js → api-settings-BJTjIG4U.js} +1 -1
- package/dist/web/assets/{api-themes-84MT-XqR.js → api-themes-DuLpbQFV.js} +1 -1
- package/dist/web/assets/{apl-DBS7PWvB.js → apl-B44SMKHp.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-gLlhsjM9.js +1 -0
- package/dist/web/assets/{astro-Clbk1k4h.js → astro-E5620wek.js} +1 -1
- package/dist/web/assets/{audio-preview-DIkokvPM.js → audio-preview-BG8uEB67.js} +1 -1
- package/dist/web/assets/{blade-BeBsBuGS.js → blade-D-VQWAHB.js} +1 -1
- package/dist/web/assets/{bsl-DYigT3JZ.js → bsl-Bq5qFzpU.js} +1 -1
- package/dist/web/assets/{cairo-BjpO78wI.js → cairo-Cn9-ZKRa.js} +1 -1
- package/dist/web/assets/chat-tab-6G5LulPM.js +13 -0
- package/dist/web/assets/{cobol-CpuUx69s.js → cobol-IM3E3iCH.js} +1 -1
- package/dist/web/assets/code-editor-BlBFI3jn.js +10 -0
- package/dist/web/assets/{coffee-FoFd2Cxo.js → coffee-24wG7ekn.js} +1 -1
- package/dist/web/assets/{conflict-editor-Dqm1bkyL.js → conflict-editor-CYZjqn46.js} +3 -3
- package/dist/web/assets/{cpp-CO_nPfdr.js → cpp-DH9Cqt4g.js} +1 -1
- package/dist/web/assets/{crystal-D-UygAAF.js → crystal-4nZYHhdi.js} +1 -1
- package/dist/web/assets/{csv-preview-CvP4xzug.js → csv-preview-YxR9adj_.js} +1 -1
- package/dist/web/assets/data-grid-overlay-editor-DxdOKRAY.js +1 -0
- package/dist/web/assets/data-grid-types-CzEQU9PJ.js +1 -0
- package/dist/web/assets/database-viewer-CrdTyPIN.js +1 -0
- package/dist/web/assets/dialog-BpkAWOy8.js +1 -0
- package/dist/web/assets/{diff-viewer-BfWixe_z.js → diff-viewer-DiYj_kRC.js} +1 -1
- package/dist/web/assets/dist-Bn3E6I4R.js +11 -0
- package/dist/web/assets/{docx-preview-CguUoTKe.js → docx-preview-Dsrm2Hgu.js} +1 -1
- package/dist/web/assets/{edge-BSzxzX11.js → edge-DTI9d2Qi.js} +1 -1
- package/dist/web/assets/{elixir-DH1-Mrep.js → elixir-Ys0wioho.js} +1 -1
- package/dist/web/assets/{elm-B0ln5J70.js → elm-Cihc9TAz.js} +1 -1
- package/dist/web/assets/{erb-GIz6NnlZ.js → erb-BwYBWK2-.js} +1 -1
- package/dist/web/assets/{erlang-B8MgYhib.js → erlang-CzlD_Joo.js} +1 -1
- package/dist/web/assets/esm-JLkfN0k-.js +2 -0
- package/dist/web/assets/{extension-webview-DTpFt1eL.js → extension-webview-B8ph2gI9.js} +1 -1
- package/dist/web/assets/{fortran-fixed-form-D_-TrK6U.js → fortran-fixed-form-CT90EtSp.js} +1 -1
- package/dist/web/assets/{fsharp-C9cLCk2b.js → fsharp-LasxezlU.js} +1 -1
- package/dist/web/assets/{gdresource-CsZ3lXwY.js → gdresource-XqgPdfiE.js} +1 -1
- package/dist/web/assets/{git-commit-xmq0KqrA.js → git-commit-CZBgPolw.js} +1 -1
- package/dist/web/assets/{git-log-panel-DUX7N5tN.js → git-log-panel-qIsOpM57.js} +1 -1
- package/dist/web/assets/{git-rebase-D3O-jsSX.js → git-rebase-C2VzKDB1.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-BKGq--Jw.js +1 -0
- package/dist/web/assets/glide-data-grid-BrQskOnP.js +138 -0
- package/dist/web/assets/{glimmer-js-g74gESrC.js → glimmer-js-DfjWcOLD.js} +1 -1
- package/dist/web/assets/{glimmer-ts-DF4aDWHT.js → glimmer-ts-DBldQATc.js} +1 -1
- package/dist/web/assets/{glsl-D5LmfW7l.js → glsl-CzNv1NPP.js} +1 -1
- package/dist/web/assets/{graphql-_KI4RuXL.js → graphql-DDyLtQb4.js} +1 -1
- package/dist/web/assets/group-chat-tab-DYgRs0zS.js +1 -0
- package/dist/web/assets/{hack-B1NaTC39.js → hack-CtoYNYkC.js} +1 -1
- package/dist/web/assets/{haml-DDFXadZ4.js → haml-CnBVap7G.js} +1 -1
- package/dist/web/assets/{handlebars-Bp-Jq3K9.js → handlebars-Dg51esUH.js} +1 -1
- package/dist/web/assets/{html-DyB9_5Tj.js → html-Ec2_evSy.js} +1 -1
- package/dist/web/assets/{html-derivative-CC60wi-3.js → html-derivative-Cy-F7ZqL.js} +1 -1
- package/dist/web/assets/{http-C-9qngH4.js → http-C236v8Tg.js} +1 -1
- package/dist/web/assets/{hurl-BtxgpNDs.js → hurl-0rMD2gPU.js} +1 -1
- package/dist/web/assets/{hxml-DOoOS9op.js → hxml-e5uS5jTD.js} +1 -1
- package/dist/web/assets/{image-preview-CZg6FQ3w.js → image-preview-B9EWGEFv.js} +1 -1
- package/dist/web/assets/index-BYFXiFsa.css +2 -0
- package/dist/web/assets/index-BiHrB3KU.js +50 -0
- package/dist/web/assets/info-3K5VOQVL-BOhGriBF.js +1 -0
- package/dist/web/assets/{jinja-cN-150ao.js → jinja-DybFmhfq.js} +1 -1
- package/dist/web/assets/{jison-CqjsqPq5.js → jison-hkHbixdZ.js} +1 -1
- package/dist/web/assets/{julia-C-I5m8W4.js → julia-QnxY6sRE.js} +1 -1
- package/dist/web/assets/{just-CgsSW9zs.js → just-1Rs-nm8g.js} +1 -1
- package/dist/web/assets/keybindings-store-CWi8IGEx.js +1 -0
- package/dist/web/assets/{latex-BFzR9N2d.js → latex-jEBQqA7u.js} +1 -1
- package/dist/web/assets/{liquid-BWfr-_iC.js → liquid-DfJaZpxG.js} +1 -1
- package/dist/web/assets/{lua-DsXVun6g.js → lua-ti0Jr6-C.js} +1 -1
- package/dist/web/assets/{markdown-renderer-CiQkvWP_.js → markdown-renderer-B4rtk2Hq.js} +3 -3
- package/dist/web/assets/markdown-renderer-XIhxiUQq.js +1 -0
- package/dist/web/assets/{marko-DWBbo09n.js → marko-DNj4AhPg.js} +1 -1
- package/dist/web/assets/{mdc-CUMe9LOG.js → mdc-DPFwQFe4.js} +1 -1
- package/dist/web/assets/mobile-bottom-sheet--5_YEewV.js +1 -0
- package/dist/web/assets/{nextflow-CoYbADOm.js → nextflow-BUrFV5aB.js} +1 -1
- package/dist/web/assets/{nginx-z-JRZREw.js → nginx-BrW9NdOb.js} +1 -1
- package/dist/web/assets/{nim-Ci4LHyBm.js → nim-DS_6PF2p.js} +1 -1
- package/dist/web/assets/notification-store-DEIj7OrE.js +1 -0
- package/dist/web/assets/{number-overlay-editor-lnnuUpPI.js → number-overlay-editor-CReXWiQ1.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-CdLFnL8a.js +1 -0
- package/dist/web/assets/{panel-store-D6RV_ztx.js → panel-store-DnbT1c8L.js} +1 -1
- package/dist/web/assets/{pdf-preview-B6ZqANpw.js → pdf-preview-Zl3KICd5.js} +1 -1
- package/dist/web/assets/{perl-pbDimKOO.js → perl-ytm9vKO_.js} +1 -1
- package/dist/web/assets/{php-B003E5v7.js → php-DWTD1Usw.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-COC-h0zz.js +1 -0
- package/dist/web/assets/{trash-2-CbbD5QF1.js → plus-DcuJuDC3.js} +1 -1
- package/dist/web/assets/postgres-viewer-BTupZTmP.js +3 -0
- package/dist/web/assets/{project-store-Cekcjcom.js → project-store-Sbnqc41N.js} +1 -1
- package/dist/web/assets/{pug-AoueAWJo.js → pug-Bt7KL3_r.js} +1 -1
- package/dist/web/assets/{qml-CepxioQA.js → qml-Dexdon5J.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-CiCfdJNL.js +1 -0
- package/dist/web/assets/{razor-lIvU-Gu-.js → razor-DnYCSl0G.js} +1 -1
- package/dist/web/assets/{rst-Dn-dwElE.js → rst-BEFYzwF8.js} +1 -1
- package/dist/web/assets/{ruby-DmsD1Iz5.js → ruby-BPaXFEjN.js} +1 -1
- package/dist/web/assets/{sas-6IM2P4YP.js → sas-CywiNBp8.js} +1 -1
- package/dist/web/assets/{scss-RgYEZQqh.js → scss-CGk0L6hN.js} +1 -1
- package/dist/web/assets/{settings-store-BkSf4SPQ.js → settings-store-DkRZhj-g.js} +2 -2
- package/dist/web/assets/settings-tab-BF069B1K.js +1 -0
- package/dist/web/assets/{shaderlab-B0MNEwt4.js → shaderlab-Byjk0kH7.js} +1 -1
- package/dist/web/assets/{shellsession-F8S4LrQI.js → shellsession-DbA70QB6.js} +1 -1
- package/dist/web/assets/{soy-DDlMbX7u.js → soy-Bm97kWiA.js} +1 -1
- package/dist/web/assets/sparkles-B3DmG8PJ.js +1 -0
- package/dist/web/assets/{sparql-kthmGAAe.js → sparql-CawLnniT.js} +1 -1
- package/dist/web/assets/{sql-query-editor-BYNM0RRl.js → sql-query-editor-RwHY1p-a.js} +1 -1
- package/dist/web/assets/sqlite-viewer-3UxftoM7.js +1 -0
- package/dist/web/assets/{stata-Tfbew8La.js → stata-RifEDtNO.js} +1 -1
- package/dist/web/assets/{surrealql-C0LIGqRx.js → surrealql-DGRQa5Lm.js} +1 -1
- package/dist/web/assets/{svelte-CfTy8CGF.js → svelte-w9Hb12aM.js} +1 -1
- package/dist/web/assets/system-monitor-tab-Ck1cIP7g.js +1 -0
- package/dist/web/assets/{tab-store-CcLQfu8H.js → tab-store-vn0viMOP.js} +1 -1
- package/dist/web/assets/{templ-V5H1Sbfy.js → templ-BpUwjJXV.js} +1 -1
- package/dist/web/assets/{terminal-tab-CK3lX-0Y.js → terminal-tab-B9opPxft.js} +2 -2
- package/dist/web/assets/{tex-C3H3uMZf.js → tex-DJFSsuTD.js} +1 -1
- package/dist/web/assets/tool-cards-C7iLwehG.js +7 -0
- package/dist/web/assets/treemap-KZPCXAKY-CZwuSCtA.js +1 -0
- package/dist/web/assets/{ts-tags-7AXgG5YS.js → ts-tags-vp9Qvx2O.js} +1 -1
- package/dist/web/assets/{twig-BSyS38T3.js → twig-CoazxjRB.js} +1 -1
- package/dist/web/assets/{use-blob-url-CpyRr7Cx.js → use-blob-url-DdXgVqfz.js} +1 -1
- package/dist/web/assets/use-is-mobile-CE6AamG6.js +1 -0
- package/dist/web/assets/{use-monaco-theme-Jj2OxkAE.js → use-monaco-theme-jtYkroys.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-DGOXKrJC.js → vendor-mermaid-DPpYkrMf.js} +193 -193
- package/dist/web/assets/{video-preview-BOHxkwKG.js → video-preview-Ced_VIvq.js} +1 -1
- package/dist/web/assets/{vue-C4d_br9u.js → vue-CnshsiXd.js} +1 -1
- package/dist/web/assets/{vue-html-CGdoz4vW.js → vue-html-CZshynFp.js} +1 -1
- package/dist/web/assets/{vue-vine-CqNolQlN.js → vue-vine-C5gtp_T1.js} +1 -1
- package/dist/web/assets/{xml-UmCmu-Od.js → xml-BEGJasgj.js} +1 -1
- package/dist/web/assets/{xsl-DJG6USGh.js → xsl-DXpRLjYk.js} +1 -1
- package/dist/web/index.html +22 -20
- package/dist/web/monacoeditorwork/css.worker.bundle.js +122 -122
- package/dist/web/monacoeditorwork/editor.worker.bundle.js +78 -78
- package/dist/web/monacoeditorwork/html.worker.bundle.js +110 -110
- package/dist/web/monacoeditorwork/json.worker.bundle.js +108 -108
- package/dist/web/monacoeditorwork/ts.worker.bundle.js +81 -81
- package/dist/web/sw.js +1 -1
- package/docs/journal/binary-self-upgrade-260724.md +66 -0
- package/nul/docs/claude-agent-sdk-reference.md +780 -0
- package/nul/docs/code-standards.md +1080 -0
- package/nul/docs/codebase-summary.md +916 -0
- package/nul/docs/deployment-guide.md +702 -0
- package/nul/docs/design-guidelines.md +767 -0
- package/nul/docs/extension-development-guide.md +629 -0
- package/nul/docs/journals/260414-1400-ext-git-graph-port-complete.md +147 -0
- package/nul/docs/journals/260414-1452-git-graph-faithful-port.md +144 -0
- package/nul/docs/journals/260414-1810-git-graph-ui-improvements-complete.md +261 -0
- package/nul/docs/journals/260414-2001-bundled-extensions.md +219 -0
- package/nul/docs/journals/260415-frontend-memory-optimization.md +73 -0
- package/nul/docs/lessons-learned.md +70 -0
- package/nul/docs/project-changelog.md +574 -0
- package/nul/docs/project-overview-pdr.md +205 -0
- package/nul/docs/project-roadmap.md +222 -0
- package/nul/docs/system-architecture.md +1961 -0
- package/package.json +1 -1
- package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
- package/spike-group-channel.mjs +156 -0
- package/spike-group-chat.mjs +181 -0
- package/src/server/routes/group-chat.ts +118 -9
- package/src/services/group-chat/agent-runner.ts +15 -2
- package/src/services/group-chat/context-window.ts +15 -0
- package/src/services/group-chat/group-chat.service.ts +178 -79
- package/src/services/group-chat/group-chat.store.ts +30 -0
- package/src/services/group-chat/responder-router.ts +110 -0
- package/src/services/group-chat/transcript-archive.ts +18 -0
- package/src/services/group-chat/turn-engine.ts +183 -105
- package/src/services/jsonl-transcript-parser.ts +36 -0
- package/src/types/group-chat-ws.ts +2 -2
- package/src/types/group-chat.ts +33 -4
- package/src/web/components/group-chat/group-chat-tab.tsx +109 -14
- package/src/web/components/group-chat/group-create-dialog.tsx +10 -3
- package/src/web/components/group-chat/group-full-transcript-view.tsx +9 -8
- package/src/web/components/group-chat/group-member-edit-dialog.tsx +108 -0
- package/src/web/components/group-chat/group-member-roster.tsx +51 -23
- package/src/web/components/group-chat/group-message-item.tsx +45 -26
- package/src/web/components/group-chat/group-transcript-messages.tsx +126 -0
- package/src/web/components/layout/mobile-drawer-tab-bar.tsx +10 -0
- package/src/web/components/layout/nav-section-rail.tsx +8 -2
- package/src/web/components/layout/upgrade-button.tsx +33 -11
- package/src/web/hooks/use-group-chat.ts +8 -1
- package/src/web/lib/api-group-chat.ts +47 -4
- package/src/web/lib/sidebar-tabs/tab-registry.ts +3 -1
- package/dist/web/assets/architecture-PBZL5I3N-NAS99xy0.js +0 -1
- package/dist/web/assets/chat-tab-Bh6l253v.js +0 -18
- package/dist/web/assets/click-outside-container-DXZVmhaX.js +0 -1
- package/dist/web/assets/code-editor-B7F-d4DK.js +0 -10
- package/dist/web/assets/data-grid-overlay-editor-CUlFsD-D.js +0 -1
- package/dist/web/assets/database-viewer-5oNTPgjF.js +0 -1
- package/dist/web/assets/dist-BsziT-tR.js +0 -11
- package/dist/web/assets/esm-CjVeOTNQ.js +0 -2
- package/dist/web/assets/gitGraph-HDMCJU4V-B4I3L4Sf.js +0 -1
- package/dist/web/assets/glide-data-grid-7vB1SNne.js +0 -138
- package/dist/web/assets/group-chat-tab-CNECY-zg.js +0 -1
- package/dist/web/assets/index-D2G6kmTs.js +0 -50
- package/dist/web/assets/index-DCmrZnq0.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-CBbbOe3C.js +0 -1
- package/dist/web/assets/input-24Nf_edC.js +0 -1
- package/dist/web/assets/keybindings-store-D8Cppv4w.js +0 -1
- package/dist/web/assets/notification-store-DOGxkWih.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-fr8-QSTF.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-Biu7_Pbb.js +0 -1
- package/dist/web/assets/postgres-viewer-B23xTCSs.js +0 -3
- package/dist/web/assets/radar-KQ55EAFF-CMtNRpK6.js +0 -1
- package/dist/web/assets/settings-tab-D5hAA1bY.js +0 -1
- package/dist/web/assets/sparkles-2ii4lR7b.js +0 -1
- package/dist/web/assets/sqlite-viewer-DW9f2Hqj.js +0 -1
- package/dist/web/assets/system-monitor-tab-B5f4pgdX.js +0 -1
- package/dist/web/assets/treemap-KZPCXAKY-ZYVFjoaN.js +0 -1
- package/dist/web/assets/use-websocket-DrDBgIWU.js +0 -1
- /package/dist/web/assets/{abap-BZ3J5hF3.js → abap-wT6fgqwv.js} +0 -0
- /package/dist/web/assets/{actionscript-3-CkyGfT-8.js → actionscript-3-CqcHpPYj.js} +0 -0
- /package/dist/web/assets/{ada-CxNLBoe7.js → ada-DWE3Hn4E.js} +0 -0
- /package/dist/web/assets/{andromeeda-BPN5rsDz.js → andromeeda-DpQ-y-Jt.js} +0 -0
- /package/dist/web/assets/{apache-C1F5wHL6.js → apache-LRTUP4r3.js} +0 -0
- /package/dist/web/assets/{apex-BaNixdO-.js → apex-DwVeH5_h.js} +0 -0
- /package/dist/web/assets/{api-client-Dvzcc_EO.js → api-client-BK4NPNoY.js} +0 -0
- /package/dist/web/assets/{applescript-Cl_pdcch.js → applescript-DyQiO9JU.js} +0 -0
- /package/dist/web/assets/{apply-theme-ORrEdHKT.js → apply-theme-DxKsrDLA.js} +0 -0
- /package/dist/web/assets/{ara-B6UAE7M2.js → ara-Cf-OWd2S.js} +0 -0
- /package/dist/web/assets/{asciidoc-D9c9Twki.js → asciidoc-gocbKcVK.js} +0 -0
- /package/dist/web/assets/{asm-CNmtv7Y9.js → asm-C3meb5HY.js} +0 -0
- /package/dist/web/assets/{aurora-x-C9z-NyzR.js → aurora-x-BYcXaCIg.js} +0 -0
- /package/dist/web/assets/{awk-BfLHEnKa.js → awk-BcT6nIdN.js} +0 -0
- /package/dist/web/assets/{ayu-dark-Bn7trkt_.js → ayu-dark-CLZPoccg.js} +0 -0
- /package/dist/web/assets/{ayu-light-Dpya9hPf.js → ayu-light-CTyRQdS2.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-Cc0jfABD.js → ayu-mirage-DjqfqZdo.js} +0 -0
- /package/dist/web/assets/{ballerina-BtiCmN7T.js → ballerina-BCARR-zK.js} +0 -0
- /package/dist/web/assets/{bat-tmFM76zR.js → bat-_yaRjWOb.js} +0 -0
- /package/dist/web/assets/{beancount-BjPqRrcH.js → beancount-BPESBMS9.js} +0 -0
- /package/dist/web/assets/{berry-D0SQBxN2.js → berry-BSLE-Sf8.js} +0 -0
- /package/dist/web/assets/{bibtex-CkjRWQKr.js → bibtex-CvUWWCVx.js} +0 -0
- /package/dist/web/assets/{bicep-Bhq28Cxc.js → bicep--vcqqALZ.js} +0 -0
- /package/dist/web/assets/{bird2-DFGInYb3.js → bird2-Clclqgh6.js} +0 -0
- /package/dist/web/assets/{c-CP8cB4k_.js → c-CSC2LwTp.js} +0 -0
- /package/dist/web/assets/{c3-oRytyeWo.js → c3-Cl1_jUnm.js} +0 -0
- /package/dist/web/assets/{cadence-Inf1rGb7.js → cadence-BwAD7vSC.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-DAzribQo.js → catppuccin-frappe-hr0HKoFX.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-B6Y_mCCQ.js → catppuccin-latte-DXEIYlFO.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-COLbYqVL.js → catppuccin-macchiato-B2zST7sA.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-DKWaML1B.js → catppuccin-mocha-CvrdnYv9.js} +0 -0
- /package/dist/web/assets/{chevron-right-BBc6ATtm.js → chevron-right-DeUue2aK.js} +0 -0
- /package/dist/web/assets/{circle-question-mark-CveWaCux.js → circle-question-mark-PaJgx-3d.js} +0 -0
- /package/dist/web/assets/{clarity-_ZLLrrsX.js → clarity-BeQd5TQD.js} +0 -0
- /package/dist/web/assets/{clojure-DWGVCg_P.js → clojure-Csdo0vb_.js} +0 -0
- /package/dist/web/assets/{cmake-Cwh3mug7.js → cmake-Cf0q7ddg.js} +0 -0
- /package/dist/web/assets/{code-7ZAlTvsm.js → code-TekEnDFM.js} +0 -0
- /package/dist/web/assets/{codeowners-BdV6CFYi.js → codeowners-CUEzlC7R.js} +0 -0
- /package/dist/web/assets/{codeql-NvupDIDf.js → codeql-DxHyogQt.js} +0 -0
- /package/dist/web/assets/{common-lisp-B-vtBh5k.js → common-lisp-WLb-tAda.js} +0 -0
- /package/dist/web/assets/{coq-M8-FTfiZ.js → coq-DFtMD6Wn.js} +0 -0
- /package/dist/web/assets/{csharp-B7Ugdtd-.js → csharp-DEnvXVjs.js} +0 -0
- /package/dist/web/assets/{css-86k3Z-YA.js → css-DMPpCfkZ.js} +0 -0
- /package/dist/web/assets/{csv-BX5XYhfH.js → csv-DTSgNSaP.js} +0 -0
- /package/dist/web/assets/{csv-parser-d56Fzpwc.js → csv-parser-B_xNn07y.js} +0 -0
- /package/dist/web/assets/{cue-B7099gQa.js → cue-BEmVIZmd.js} +0 -0
- /package/dist/web/assets/{cypher-D99mWVIu.js → cypher-CncQVhvU.js} +0 -0
- /package/dist/web/assets/{d-CFE8oQwh.js → d-BzUSBVex.js} +0 -0
- /package/dist/web/assets/{dark-plus-BEeeDwdg.js → dark-plus-mysFNRq2.js} +0 -0
- /package/dist/web/assets/{dart-HVSWGnI5.js → dart-BBu3nkcE.js} +0 -0
- /package/dist/web/assets/{database-BLht7BVM.js → database-COYAMZaw.js} +0 -0
- /package/dist/web/assets/{dax-DjDgSJkh.js → dax-DcLVz9_9.js} +0 -0
- /package/dist/web/assets/{desktop-B5A3i7J1.js → desktop-DS2PdvoU.js} +0 -0
- /package/dist/web/assets/{diff-CpTrlaE9.js → diff-aUYk5Qys.js} +0 -0
- /package/dist/web/assets/{dist-BSCgJs-V.js → dist-Dxl3dqhC.js} +0 -0
- /package/dist/web/assets/{docker-xBhmJeHj.js → docker-12Lj1QUD.js} +0 -0
- /package/dist/web/assets/{dotenv-DKKhLEv5.js → dotenv-D-P4bzvl.js} +0 -0
- /package/dist/web/assets/{dracula-CVwQuzra.js → dracula-C-eRNn4o.js} +0 -0
- /package/dist/web/assets/{dracula-soft-CG6mB-lf.js → dracula-soft-CBB1BI7O.js} +0 -0
- /package/dist/web/assets/{dream-maker-SC-IdYY3.js → dream-maker-C_j5A0r7.js} +0 -0
- /package/dist/web/assets/{edit-diff-preview-C50i1H63.js → edit-diff-preview-CRMu-6r1.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-CIBFq6W8.js → emacs-lisp-W54LT7rh.js} +0 -0
- /package/dist/web/assets/{everforest-dark-odRT_lec.js → everforest-dark-B_ISUDeh.js} +0 -0
- /package/dist/web/assets/{everforest-light-or1Voqjl.js → everforest-light-CNUYa354.js} +0 -0
- /package/dist/web/assets/{fennel-tQd1z3iu.js → fennel-DK82-oso.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-C-lL0g_E.js → file-exclamation-point-DBEC-Kst.js} +0 -0
- /package/dist/web/assets/{fish-DSuZQG0k.js → fish-CbJVJzQj.js} +0 -0
- /package/dist/web/assets/{fluent-D7xI8a8e.js → fluent-Cug5cOL1.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-BlAtcPd3.js → fortran-free-form-amHz32Zw.js} +0 -0
- /package/dist/web/assets/{gdscript-VsEQXBPm.js → gdscript-t_G6VYpv.js} +0 -0
- /package/dist/web/assets/{gdshader-iqHMOdwW.js → gdshader-DqZaHh4E.js} +0 -0
- /package/dist/web/assets/{genie-C4XU4g1a.js → genie-CIJtFlZK.js} +0 -0
- /package/dist/web/assets/{gherkin-C4nfQzAB.js → gherkin-CalidqLY.js} +0 -0
- /package/dist/web/assets/{github-dark-B_pbG3CC.js → github-dark-BG2xX0wa.js} +0 -0
- /package/dist/web/assets/{github-dark-default-kFbx7C95.js → github-dark-default-tDp_EOBs.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-CpVfQEqs.js → github-dark-dimmed-DlSfPwW2.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-DYKqQwZh.js → github-dark-high-contrast-qZM7j5KB.js} +0 -0
- /package/dist/web/assets/{github-light-gEYBmKaj.js → github-light-CnvWTiyb.js} +0 -0
- /package/dist/web/assets/{github-light-default-DVHfMPQ2.js → github-light-default-Dy6OAt2Q.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-ClVJDu-q.js → github-light-high-contrast-1BHQCOPl.js} +0 -0
- /package/dist/web/assets/{gleam-BLaPu7ft.js → gleam-D-2cpXVX.js} +0 -0
- /package/dist/web/assets/{gn-BKgerUyI.js → gn-C1cC4xLc.js} +0 -0
- /package/dist/web/assets/{gnuplot-cqJuEFb-.js → gnuplot-2Gp459mV.js} +0 -0
- /package/dist/web/assets/{go-B2EHdyD8.js → go-BA1q0q8h.js} +0 -0
- /package/dist/web/assets/{groovy-DdImoj8s.js → groovy-BlIa-VfI.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-DlwstAds.js → gruvbox-dark-hard-BMIwVwaJ.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-CiYEd1vd.js → gruvbox-dark-medium-DxfuBW3n.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-C-wEa4h4.js → gruvbox-dark-soft-_NSslDDi.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-BqYmfna-.js → gruvbox-light-hard-CP5MIsL9.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-CxmfalT2.js → gruvbox-light-medium-BTMursH0.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-DGWXXMCB.js → gruvbox-light-soft-Bv6zFoVX.js} +0 -0
- /package/dist/web/assets/{haskell-H_C_IuVb.js → haskell-Da8UeSv-.js} +0 -0
- /package/dist/web/assets/{haxe-CGNSMpeZ.js → haxe-mcKlcxBa.js} +0 -0
- /package/dist/web/assets/{hcl-B7bSTSQf.js → hcl-BdZcx5JX.js} +0 -0
- /package/dist/web/assets/{hjson-DlJ-glQZ.js → hjson-pFXYbN4t.js} +0 -0
- /package/dist/web/assets/{hlsl-CehW5SJN.js → hlsl-Z0II0KR8.js} +0 -0
- /package/dist/web/assets/{horizon-Beabcz2d.js → horizon-CufN8DyP.js} +0 -0
- /package/dist/web/assets/{horizon-bright-BC87RXPa.js → horizon-bright-5qoQVyIY.js} +0 -0
- /package/dist/web/assets/{houston-Da7RFwUy.js → houston-DOFkQwep.js} +0 -0
- /package/dist/web/assets/{hy-m1H70w19.js → hy-BVbDMDcG.js} +0 -0
- /package/dist/web/assets/{imba-MExFsdAA.js → imba-DRM6LLS5.js} +0 -0
- /package/dist/web/assets/{ini-CJy_zmwy.js → ini-2KCnNvmz.js} +0 -0
- /package/dist/web/assets/{java-DqDFvJBH.js → java-BmvH-Ou1.js} +0 -0
- /package/dist/web/assets/{javascript-C3Wyv22X.js → javascript-B7VhU1Yc.js} +0 -0
- /package/dist/web/assets/{json-DnGBw_DZ.js → json-X1pNk0n7.js} +0 -0
- /package/dist/web/assets/{json5-CRN-zoN4.js → json5-CJeEJPTg.js} +0 -0
- /package/dist/web/assets/{jsonc-CKRUZNRo.js → jsonc-C1haTBsf.js} +0 -0
- /package/dist/web/assets/{jsonl-CGfD6FrH.js → jsonl-wQ8-AJgs.js} +0 -0
- /package/dist/web/assets/{jsonnet-nbFuDj0o.js → jsonnet-BrEjY3Xh.js} +0 -0
- /package/dist/web/assets/{jssm-D0ShzIqD.js → jssm-C6LgYbOs.js} +0 -0
- /package/dist/web/assets/{jsx-D27hbRbs.js → jsx-B2cfD_Fb.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-Ov3f8K0T.js → kanagawa-dragon-6UCcJpLw.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-CLyOqh-g.js → kanagawa-lotus-DOmfpsRg.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-Kj3dzabH.js → kanagawa-wave-CpxmPE7N.js} +0 -0
- /package/dist/web/assets/{kdl-DFF58Gu4.js → kdl-BrLEivmb.js} +0 -0
- /package/dist/web/assets/{kotlin-BM4PKaB4.js → kotlin-BO2FUnDB.js} +0 -0
- /package/dist/web/assets/{kusto-DrvHLCv5.js → kusto-Cev1yiq9.js} +0 -0
- /package/dist/web/assets/{laserwave-Db6i6ZkO.js → laserwave-BlEkf-eH.js} +0 -0
- /package/dist/web/assets/{lean-D0hEjzwk.js → lean-BLS3Xk2w.js} +0 -0
- /package/dist/web/assets/{less-BEj4npGG.js → less-BXmcsqcq.js} +0 -0
- /package/dist/web/assets/{lib-CBdlQ75W.js → lib-CxSBdrd7.js} +0 -0
- /package/dist/web/assets/{light-plus-DLIIbDea.js → light-plus-DS6zriYl.js} +0 -0
- /package/dist/web/assets/{llvm-DMt6umsO.js → llvm-C_wLnJgX.js} +0 -0
- /package/dist/web/assets/{log-BopvdtPW.js → log-Cg8pvmWi.js} +0 -0
- /package/dist/web/assets/{logo-CYSUFPFR.js → logo-C9-kEvPW.js} +0 -0
- /package/dist/web/assets/{luau-XC611HNO.js → luau-NwaGugfZ.js} +0 -0
- /package/dist/web/assets/{make-BMYZIfBj.js → make-DBpJE-Z8.js} +0 -0
- /package/dist/web/assets/{markdown-BLza5nvF.js → markdown-B7ZTAu7B.js} +0 -0
- /package/dist/web/assets/{material-theme-Uw27UfJW.js → material-theme-BsXH-Mss.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-dfqt8XBY.js → material-theme-darker-CW9OlIeY.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-CPtBTblV.js → material-theme-lighter-D2PAh0Kw.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-BfZgVqC-.js → material-theme-ocean-Vz6DBVi3.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-DAZoVYg8.js → material-theme-palenight-D-GleP3G.js} +0 -0
- /package/dist/web/assets/{matlab-cSzmquiW.js → matlab-C7MYlMSn.js} +0 -0
- /package/dist/web/assets/{mdx-Dq0kW5VM.js → mdx-FkOOX3Dq.js} +0 -0
- /package/dist/web/assets/{mermaid-DoIKF0yS.js → mermaid-C_9qw5it.js} +0 -0
- /package/dist/web/assets/{min-dark-DyraimDU.js → min-dark-BowNvxk2.js} +0 -0
- /package/dist/web/assets/{min-light-Co9cbcUv.js → min-light-x8oWUmbL.js} +0 -0
- /package/dist/web/assets/{mipsasm-ph6cKgHn.js → mipsasm-Dmi1AZOT.js} +0 -0
- /package/dist/web/assets/{mojo-BBT0XwmY.js → mojo-C6z7mry2.js} +0 -0
- /package/dist/web/assets/{monokai-IP0T5Rtg.js → monokai-BQ4e_Hn0.js} +0 -0
- /package/dist/web/assets/{moonbit-B8cogNXl.js → moonbit-CEeNIoB4.js} +0 -0
- /package/dist/web/assets/{move-DkY26NtM.js → move-bALfKUa7.js} +0 -0
- /package/dist/web/assets/{narrat-rBs3byG0.js → narrat-DX4JlAWT.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-DkO9wMLP.js → nextflow-groovy-CKQWtRkO.js} +0 -0
- /package/dist/web/assets/{night-owl-jVR4lFji.js → night-owl-D4PQd726.js} +0 -0
- /package/dist/web/assets/{night-owl-light-fBYJ7s3U.js → night-owl-light-BQo_YHll.js} +0 -0
- /package/dist/web/assets/{nix-WX9oavu6.js → nix-B1jThkGj.js} +0 -0
- /package/dist/web/assets/{nord-Cf7G21Pu.js → nord-35quHUKo.js} +0 -0
- /package/dist/web/assets/{nushell-DQdzcJ1H.js → nushell-L6DbJTuL.js} +0 -0
- /package/dist/web/assets/{objective-c-JSO2uvZ-.js → objective-c-CTZ4bR2U.js} +0 -0
- /package/dist/web/assets/{objective-cpp-CZMGJ9Fb.js → objective-cpp-Dm1YDIdA.js} +0 -0
- /package/dist/web/assets/{ocaml-C4S4NSDo.js → ocaml-B3n__LGy.js} +0 -0
- /package/dist/web/assets/{odin-Y2jXCgVq.js → odin-DmqZ8n3i.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-dVIxuoJY.js → one-dark-pro-16_UaUig.js} +0 -0
- /package/dist/web/assets/{one-light-BQ1IKfD1.js → one-light-B-GGjWn5.js} +0 -0
- /package/dist/web/assets/{openscad-Bddw4I3z.js → openscad-DTFB9Sj6.js} +0 -0
- /package/dist/web/assets/{pascal-BKVXrzC1.js → pascal-RcT1dQYN.js} +0 -0
- /package/dist/web/assets/{pkl-BTd-YRsO.js → pkl-Dr4yLQ_o.js} +0 -0
- /package/dist/web/assets/{plastic-eiGvBIxV.js → plastic-hp2Nry0R.js} +0 -0
- /package/dist/web/assets/{plsql-C290tieP.js → plsql-pFcO4WZ0.js} +0 -0
- /package/dist/web/assets/{po-DyDwh0tx.js → po-BkZ0_HvY.js} +0 -0
- /package/dist/web/assets/{poimandres-B87zc_g-.js → poimandres-BcTrxj7f.js} +0 -0
- /package/dist/web/assets/{polar-Cdub1YMT.js → polar-DHK3q8FF.js} +0 -0
- /package/dist/web/assets/{postcss-BcI_3K0v.js → postcss-Bv7WzijA.js} +0 -0
- /package/dist/web/assets/{powerquery-OdMrkJSe.js → powerquery-DpaU_hW9.js} +0 -0
- /package/dist/web/assets/{powershell-C8auT6xg.js → powershell-_Rqc0MGP.js} +0 -0
- /package/dist/web/assets/{prisma-DIbVv8PA.js → prisma-wyegE8us.js} +0 -0
- /package/dist/web/assets/{prolog-DbTOH3Ld.js → prolog-DspHCURv.js} +0 -0
- /package/dist/web/assets/{proto-C4Cq2dCD.js → proto-BOBiNGf5.js} +0 -0
- /package/dist/web/assets/{puppet-DJp3uqum.js → puppet-DfLvV8h2.js} +0 -0
- /package/dist/web/assets/{purescript-CLsV4rPU.js → purescript-BY5ZSOZy.js} +0 -0
- /package/dist/web/assets/{python-2gBtEza2.js → python-B758mMeg.js} +0 -0
- /package/dist/web/assets/{qmldir-DfhULcua.js → qmldir-C75bpHvy.js} +0 -0
- /package/dist/web/assets/{qss-DK--VTTV.js → qss-DcLTlbLd.js} +0 -0
- /package/dist/web/assets/{r-BArBO2Sa.js → r-D0G_Y1P5.js} +0 -0
- /package/dist/web/assets/{racket-5mijHsVy.js → racket-DTye_5qn.js} +0 -0
- /package/dist/web/assets/{raku-ir0suElk.js → raku-uJXBXkV0.js} +0 -0
- /package/dist/web/assets/{react-J9g6e3Rq.js → react-CorNPdie.js} +0 -0
- /package/dist/web/assets/{red-DSecpIOT.js → red-rs3HE3re.js} +0 -0
- /package/dist/web/assets/{reg-Dp30FusS.js → reg-DkTIaX7a.js} +0 -0
- /package/dist/web/assets/{regexp-DXJnEM_6.js → regexp-4TLSs4_m.js} +0 -0
- /package/dist/web/assets/{rel-Dr483ozj.js → rel-B0jumCjt.js} +0 -0
- /package/dist/web/assets/{resolve-theme-DJORYzKu.js → resolve-theme-CCoakF2E.js} +0 -0
- /package/dist/web/assets/{riscv-ZfBy5IA1.js → riscv-DtaWMlo0.js} +0 -0
- /package/dist/web/assets/{ron-ZJ_CljGP.js → ron-BCPxwJD6.js} +0 -0
- /package/dist/web/assets/{rose-pine-CcW_eJ6G.js → rose-pine-CNryoqGi.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-v2l_UF-j.js → rose-pine-dawn-C-gJOQVP.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-CNXkwf3D.js → rose-pine-moon-BdXSXpZh.js} +0 -0
- /package/dist/web/assets/{rosmsg-BMYMVW84.js → rosmsg-CPG8X-D5.js} +0 -0
- /package/dist/web/assets/{rust-BR-zJh5q.js → rust-CxfW3ePx.js} +0 -0
- /package/dist/web/assets/{sass-BukPOBFz.js → sass-D-7bxo_L.js} +0 -0
- /package/dist/web/assets/{save-DO5xjW95.js → save-BM4p9_9n.js} +0 -0
- /package/dist/web/assets/{scala-DUFY7D6D.js → scala-DyUsfHNc.js} +0 -0
- /package/dist/web/assets/{scheme-Dl-dNNxQ.js → scheme-ROgrwiO-.js} +0 -0
- /package/dist/web/assets/{sdbl-DdmlQhia.js → sdbl-B1EAQWpp.js} +0 -0
- /package/dist/web/assets/{shellscript-UyhrvGcd.js → shellscript-HhmB_Ufy.js} +0 -0
- /package/dist/web/assets/{shield-check-m2QzZTuZ.js → shield-check-C3qYSU8a.js} +0 -0
- /package/dist/web/assets/{shield-off-DNn7VzJe.js → shield-off-D5tU7gQT.js} +0 -0
- /package/dist/web/assets/{slack-dark-Cv6Szr-q.js → slack-dark-DnmSY72G.js} +0 -0
- /package/dist/web/assets/{slack-ochin-V6Ii3lAm.js → slack-ochin-q97gHjcd.js} +0 -0
- /package/dist/web/assets/{smalltalk-BUCv5G91.js → smalltalk-B-1waXvA.js} +0 -0
- /package/dist/web/assets/{snazzy-light-B67a78qi.js → snazzy-light-C8yWDN2g.js} +0 -0
- /package/dist/web/assets/{solarized-dark-ccWnfYyA.js → solarized-dark-ClVDEMJZ.js} +0 -0
- /package/dist/web/assets/{solarized-light-C3WyRO5I.js → solarized-light-Bts6CUIP.js} +0 -0
- /package/dist/web/assets/{solidity-BFbRPNi_.js → solidity-DYxwp0om.js} +0 -0
- /package/dist/web/assets/{splunk-zdpwCJLE.js → splunk-jK6-Sr06.js} +0 -0
- /package/dist/web/assets/{sql-B2IPUsfz.js → sql-DPpd8aUS.js} +0 -0
- /package/dist/web/assets/{ssh-config-Co4cXifq.js → ssh-config-Bimb9LVr.js} +0 -0
- /package/dist/web/assets/{stylus-CmI75XY8.js → stylus-B2DgJRJw.js} +0 -0
- /package/dist/web/assets/{swift-Dfks9YQI.js → swift-ChEH2nFL.js} +0 -0
- /package/dist/web/assets/{synthwave-84-B3LERzNS.js → synthwave-84-DwSLbgAm.js} +0 -0
- /package/dist/web/assets/{system-verilog-BFvldiwl.js → system-verilog-DoVBMhJ8.js} +0 -0
- /package/dist/web/assets/{systemd-Cu4Vvgbu.js → systemd--Ux4VAYD.js} +0 -0
- /package/dist/web/assets/{table-CAVmgQMT.js → table-Di8pv2Y_.js} +0 -0
- /package/dist/web/assets/{talonscript-Bnq32pUB.js → talonscript-DQNx9nak.js} +0 -0
- /package/dist/web/assets/{tasl-Nwe2K3J1.js → tasl-Bwy_Y9uD.js} +0 -0
- /package/dist/web/assets/{tcl-zOnpywrl.js → tcl-Drea-2jA.js} +0 -0
- /package/dist/web/assets/{terraform-Bc9Vj-n3.js → terraform-4rS5HoFk.js} +0 -0
- /package/dist/web/assets/{tokyo-night-9_KyM8M2.js → tokyo-night-C9MqaxIn.js} +0 -0
- /package/dist/web/assets/{toml-ByH-fxOY.js → toml-tSgOSv42.js} +0 -0
- /package/dist/web/assets/{tsv-DrCnDClP.js → tsv-BmL4O1Zx.js} +0 -0
- /package/dist/web/assets/{tsx-B8LafSYr.js → tsx-BwzeA880.js} +0 -0
- /package/dist/web/assets/{turtle-DuyP_QCJ.js → turtle-2DYvssFL.js} +0 -0
- /package/dist/web/assets/{typescript-BTBJb5RD.js → typescript-ZC-vonSh.js} +0 -0
- /package/dist/web/assets/{typespec-DdOFo7M5.js → typespec-DkCEO45F.js} +0 -0
- /package/dist/web/assets/{typst-LYvnBWQu.js → typst-DAZdb2n6.js} +0 -0
- /package/dist/web/assets/{utils-CTg5uAYR.js → utils-CSCvNZxE.js} +0 -0
- /package/dist/web/assets/{v-BuBYA1_x.js → v-B_wsb4C1.js} +0 -0
- /package/dist/web/assets/{vala-vRIBYYe3.js → vala-BDBNS784.js} +0 -0
- /package/dist/web/assets/{vb-DwGi-IYM.js → vb-CuOoJSSa.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-i6SHFTfU.js → vendor-xterm-CImj6i6Z.js} +0 -0
- /package/dist/web/assets/{verilog-6B1X4G2-.js → verilog-BCcOvOcc.js} +0 -0
- /package/dist/web/assets/{vesper-Dw1y_Ae7.js → vesper-vN8CREK5.js} +0 -0
- /package/dist/web/assets/{vhdl-DK8JwBzJ.js → vhdl-CI8PoqeM.js} +0 -0
- /package/dist/web/assets/{viml-BTKIEIqm.js → viml-B66dNP1B.js} +0 -0
- /package/dist/web/assets/{vitesse-black-BqqolhEg.js → vitesse-black-0bGIaCfD.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-B9JL5WQA.js → vitesse-dark-Dk-RSXq-.js} +0 -0
- /package/dist/web/assets/{vitesse-light-DYJKj2se.js → vitesse-light-BUsA5RhG.js} +0 -0
- /package/dist/web/assets/{vyper-D-jDI3WH.js → vyper-dNodzEa8.js} +0 -0
- /package/dist/web/assets/{wasm-1-GlNdpk.js → wasm-BDxaNPCj.js} +0 -0
- /package/dist/web/assets/{wasm-BBW4WmT2.js → wasm-d6SE2_qm.js} +0 -0
- /package/dist/web/assets/{wenyan-B6cM7sDO.js → wenyan-D0h8Uz55.js} +0 -0
- /package/dist/web/assets/{wgsl-FaHGQgko.js → wgsl-vKs_vsvQ.js} +0 -0
- /package/dist/web/assets/{wikitext-DtIyPUrk.js → wikitext-BIWsPJit.js} +0 -0
- /package/dist/web/assets/{wit-BMVRif5Y.js → wit-6vmKi2H3.js} +0 -0
- /package/dist/web/assets/{wolfram-DQsCGohn.js → wolfram-zoNg6F1a.js} +0 -0
- /package/dist/web/assets/{x-C2VSAp7O.js → x-BsFLg-T8.js} +0 -0
- /package/dist/web/assets/{yaml-C-Va56Gt.js → yaml-W95qP6-B.js} +0 -0
- /package/dist/web/assets/{zenscript-DdobKGI-.js → zenscript-BxircxDx.js} +0 -0
- /package/dist/web/assets/{zig-vqDFwj6q.js → zig-DD79WQtz.js} +0 -0
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
# PPM Codebase Summary
|
|
2
|
+
|
|
3
|
+
**Last Updated:** 2026-04-15
|
|
4
|
+
**Version:** 0.9.86
|
|
5
|
+
**Repository:** PPM (Project & Process Manager) — Multi-provider web IDE/project manager with Claude Agent SDK
|
|
6
|
+
|
|
7
|
+
**Core Statistics:**
|
|
8
|
+
- **366 files** across CLI, server, web, packages, and test layers
|
|
9
|
+
- **885,308 tokens** total codebase size (repomix)
|
|
10
|
+
- **500+ passing tests**
|
|
11
|
+
- **Tech Stack:** Bun (runtime), Hono (HTTP), React (UI), Claude Agent SDK (AI)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Directory Structure
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
src/
|
|
19
|
+
├── cli/
|
|
20
|
+
│ ├── commands/ # 14 CLI commands (start, stop, init, config, chat, db, git, ext, etc.)
|
|
21
|
+
│ │ └── ext-cmd.ts # Extension CLI (install/remove/list/enable/disable/dev)
|
|
22
|
+
│ └── utils/
|
|
23
|
+
│ └── project-resolver.ts # Resolve project name -> path
|
|
24
|
+
├── server/
|
|
25
|
+
│ ├── index.ts # Hono server setup, Bun.serve, WebSocket upgrade
|
|
26
|
+
│ ├── middleware/
|
|
27
|
+
│ │ └── auth.ts # Token validation middleware
|
|
28
|
+
│ ├── routes/
|
|
29
|
+
│ │ ├── settings.ts # GET/PUT /api/settings/ai, GET /api/settings/ai/providers/:id/models
|
|
30
|
+
│ │ ├── chat.ts # Sessions, messages, GET /chat/providers/:providerId/models
|
|
31
|
+
│ │ ├── projects.ts # Project CRUD, reorder, color
|
|
32
|
+
│ │ ├── accounts.ts # Account management (multi-account support)
|
|
33
|
+
│ │ ├── database.ts # DB connection CRUD, schema management
|
|
34
|
+
│ │ ├── git.ts # Git operations (status, commit, log, graph)
|
|
35
|
+
│ │ ├── files.ts # File operations (read, write, tree)
|
|
36
|
+
│ │ ├── mcp.ts # MCP server CRUD + import (GET, POST, PUT, DELETE)
|
|
37
|
+
│ │ ├── extensions.ts # Extension install/remove/list/enable/disable, contributions
|
|
38
|
+
│ │ ├── upgrade.ts # Version checking, upgrade
|
|
39
|
+
│ │ └── static.ts # Serve frontend (dist/web)
|
|
40
|
+
│ ├── helpers/
|
|
41
|
+
│ │ └── resolve-project.ts # Resolve project from request params
|
|
42
|
+
│ └── ws/
|
|
43
|
+
│ ├── chat.ts # WebSocket chat streaming
|
|
44
|
+
│ └── terminal.ts # WebSocket terminal I/O
|
|
45
|
+
├── providers/ # AI Provider adapters
|
|
46
|
+
│ ├── provider.interface.ts # AIProvider interface (ADDED: listModels?())
|
|
47
|
+
│ ├── claude-agent-sdk.ts # Primary provider (listModels: hardcoded 2 models)
|
|
48
|
+
│ ├── cursor-cli/
|
|
49
|
+
│ │ └── cursor-provider.ts # CLI-based provider (listModels: subprocess with TTL cache)
|
|
50
|
+
│ ├── cli-provider-base.ts # Abstract base for CLI providers
|
|
51
|
+
│ ├── mock-provider.ts # Test provider
|
|
52
|
+
│ └── registry.ts # Provider routing (list() vs listAll())
|
|
53
|
+
├── services/ # Business logic (30+ files)
|
|
54
|
+
│ ├── chat.service.ts # Session/message streaming
|
|
55
|
+
│ ├── config.service.ts # Config loading/persistence
|
|
56
|
+
│ ├── db.service.ts # SQLite CRUD (schema migrations, extension_storage)
|
|
57
|
+
│ ├── file.service.ts # File operations
|
|
58
|
+
│ ├── git.service.ts # Git commands
|
|
59
|
+
│ ├── terminal.service.ts # PTY management
|
|
60
|
+
│ ├── account.service.ts # Account CRUD & encryption
|
|
61
|
+
│ ├── upgrade.service.ts # Version checking, installation
|
|
62
|
+
│ ├── mcp-config.service.ts # MCP server CRUD (list, get, set, remove, import)
|
|
63
|
+
│ ├── extension.service.ts # Extension lifecycle, activation, state management (bundled + user discovery)
|
|
64
|
+
│ ├── extension-installer.ts # npm install, symlink, removal
|
|
65
|
+
│ ├── extension-manifest.ts # Parse manifests + bundled discovery from packages/ext-*
|
|
66
|
+
│ ├── extension-rpc.ts # RPC channel (request/response/events)
|
|
67
|
+
│ ├── extension-host-worker.ts # Worker-side extension loading
|
|
68
|
+
│ ├── contribution-registry.ts # Central registry for commands, views, config
|
|
69
|
+
│ ├── slash-discovery/ # Modular slash command discovery engine
|
|
70
|
+
│ │ ├── types.ts # DefinitionSource, SkillRoot, SlashItem, DiscoveryResult types
|
|
71
|
+
│ │ ├── definition-source.ts # Priority ranking + scope mapping
|
|
72
|
+
│ │ ├── discover-skill-roots.ts # Ancestor walking, env vars, user-global, bundled roots
|
|
73
|
+
│ │ ├── skill-loader.ts # SKILL.md + loose .md + commands parsing
|
|
74
|
+
│ │ ├── resolve-overrides.ts # Shadowing resolution
|
|
75
|
+
│ │ ├── fuzzy-search.ts # Levenshtein-based fuzzy matching
|
|
76
|
+
│ │ ├── builtin-commands.ts # Built-in command registry (9 commands)
|
|
77
|
+
│ │ ├── builtin-handlers.ts # PPM-executed handlers (/skills, /version)
|
|
78
|
+
│ │ └── index.ts # Main pipeline + exports
|
|
79
|
+
│ ├── ppmbot/ # PPMBot coordinator service layer
|
|
80
|
+
│ │ ├── ppmbot-service.ts # Main orchestrator (poller lifecycle, message routing)
|
|
81
|
+
│ │ ├── ppmbot-session.ts # Coordinator session manager, project resolver
|
|
82
|
+
│ │ ├── ppmbot-telegram.ts # Telegram API (long-polling, send, edit, typing)
|
|
83
|
+
│ │ ├── ppmbot-memory.ts # SQLite memory (project memories, context recall)
|
|
84
|
+
│ │ ├── ppmbot-delegation.ts # Task execution (creates isolated session per project)
|
|
85
|
+
│ │ ├── ppmbot-formatter.ts # Markdown → Telegram HTML, chunking
|
|
86
|
+
│ │ └── ppmbot-streamer.ts # ChatEvent → progressive message edits
|
|
87
|
+
│ ├── clawbot/ # Legacy: Telegram bot service layer (deprecated v0.9.11)
|
|
88
|
+
│ │ ├── clawbot.service.ts # (Original direct-chat model, replaced by coordinator)
|
|
89
|
+
│ │ └── ... (other files)
|
|
90
|
+
│ ├── database/
|
|
91
|
+
│ │ ├── adapter-registry.ts # SQLite/Postgres adapter registry
|
|
92
|
+
│ │ ├── sqlite-adapter.ts
|
|
93
|
+
│ │ ├── postgres-adapter.ts
|
|
94
|
+
│ │ └── readonly-check.ts # CTE-safe readonly validation
|
|
95
|
+
│ └── ... (20+ other services)
|
|
96
|
+
├── lib/
|
|
97
|
+
│ ├── account-crypto.ts # AES-256 encryption
|
|
98
|
+
│ └── network-utils.ts
|
|
99
|
+
├── types/
|
|
100
|
+
│ ├── chat.ts # Session, Message, ChatEvent, ModelOption, AIProvider
|
|
101
|
+
│ ├── api.ts # ApiResponse envelope
|
|
102
|
+
│ ├── config.ts
|
|
103
|
+
│ ├── database.ts
|
|
104
|
+
│ ├── git.ts
|
|
105
|
+
│ ├── mcp.ts # McpServerConfig, McpTransportType, validation
|
|
106
|
+
│ ├── extension.ts # ExtensionManifest, ExtensionInfo, RpcMessage, ExtensionContext
|
|
107
|
+
│ ├── ppmbot.ts # BotTask, TelegramUpdate, PPMBotCommand (coordinator types)
|
|
108
|
+
│ ├── project.ts
|
|
109
|
+
│ └── terminal.ts
|
|
110
|
+
└── web/ # React frontend (Vite + React 18)
|
|
111
|
+
├── app.tsx # Root component
|
|
112
|
+
├── stores/ # Zustand state (6 stores)
|
|
113
|
+
├── hooks/ # Custom hooks (9 hooks)
|
|
114
|
+
├── components/
|
|
115
|
+
│ ├── chat/
|
|
116
|
+
│ │ ├── chat-tab.tsx
|
|
117
|
+
│ │ ├── message-list.tsx
|
|
118
|
+
│ │ ├── message-input.tsx
|
|
119
|
+
│ │ ├── provider-selector.tsx
|
|
120
|
+
│ │ ├── chat-history-bar.tsx # ADDED: Provider badges, provider-aware usage
|
|
121
|
+
│ │ └── ... (6 other chat components)
|
|
122
|
+
│ ├── settings/
|
|
123
|
+
│ │ ├── ai-settings-section.tsx # UPDATED: Per-provider tabs, dynamic model dropdowns
|
|
124
|
+
│ │ ├── mcp-settings-section.tsx # ADDED: MCP servers tab (list, add, edit, delete)
|
|
125
|
+
│ │ └── mcp-server-dialog.tsx # ADDED: Add/Edit MCP server dialog
|
|
126
|
+
│ ├── database/
|
|
127
|
+
│ ├── editor/
|
|
128
|
+
│ ├── explorer/
|
|
129
|
+
│ ├── git/
|
|
130
|
+
│ ├── layout/
|
|
131
|
+
│ ├── terminal/
|
|
132
|
+
│ └── ui/
|
|
133
|
+
└── lib/
|
|
134
|
+
│ │ ├── use-url-sync.ts # Sync browser URL with active project/tab state
|
|
135
|
+
│ │ ├── use-tab-drag.ts # Tab drag-and-drop logic
|
|
136
|
+
│ │ ├── use-global-keybindings.ts # Global shortcuts (Shift+Shift palette, Alt+[/] tab cycling)
|
|
137
|
+
│ │ ├── use-health-check.ts # Detect server crashes/restarts via health endpoint
|
|
138
|
+
│ │ ├── use-usage.ts # Fetch token usage from backend
|
|
139
|
+
│ │ └── use-push-notification.ts # Web push notifications via Service Worker
|
|
140
|
+
│ ├── lib/ # Utilities (12 files)
|
|
141
|
+
│ │ ├── api-client.ts # Fetch wrapper with auth token, envelope unwrapping
|
|
142
|
+
│ │ ├── api-settings.ts # AI settings API client (GET/PUT /api/settings/ai)
|
|
143
|
+
│ │ ├── api-mcp.ts # ADDED: MCP settings API client (CRUD + import)
|
|
144
|
+
│ │ ├── ws-client.ts # WebSocket with exponential backoff + Cloudflare handshake
|
|
145
|
+
│ │ ├── file-support.ts # File type detection (language, icons, preview)
|
|
146
|
+
│ │ ├── project-avatar.ts # Smart project initials (collision resolution)
|
|
147
|
+
│ │ ├── project-palette.ts # 12-color palette for project avatars
|
|
148
|
+
│ │ ├── use-monaco-theme.ts # Sync Monaco Editor theme with app theme
|
|
149
|
+
│ │ ├── color-utils.ts # WCAG color contrast helper
|
|
150
|
+
│ │ ├── csv-parser.ts # CSV state-machine parser/serializer
|
|
151
|
+
│ │ └── utils.ts # Helpers (cn, randomId, basename, etc.)
|
|
152
|
+
│ ├── styles/
|
|
153
|
+
│ │ └── globals.css # Tailwind directives, custom CSS
|
|
154
|
+
│ └── components/ # React components (organized by feature)
|
|
155
|
+
│ ├── auth/ # Login screen (88 LOC)
|
|
156
|
+
│ ├── chat/ # Chat UI (12 files)
|
|
157
|
+
│ │ ├── chat-tab.tsx # Main chat container, session picker, streaming
|
|
158
|
+
│ │ ├── chat-history-bar.tsx # Session history sidebar, inline rename
|
|
159
|
+
│ │ ├── chat-history-panel.tsx # Full session list modal
|
|
160
|
+
│ │ ├── message-list.tsx # Scrolling message view with tool results
|
|
161
|
+
│ │ ├── message-input.tsx # Textarea with attachments, @ slash commands
|
|
162
|
+
│ │ ├── session-picker.tsx # Dropdown to select/create session
|
|
163
|
+
│ │ ├── file-picker.tsx # Filterable file tree picker
|
|
164
|
+
│ │ ├── slash-command-picker.tsx # Command palette for / prefix
|
|
165
|
+
│ │ ├── tool-cards.tsx # Render SDK tool results/approvals
|
|
166
|
+
│ │ ├── usage-badge.tsx # Token usage display
|
|
167
|
+
│ │ ├── attachment-chips.tsx # Display attached files
|
|
168
|
+
│ │ └── chat-placeholder.tsx # Empty state
|
|
169
|
+
│ ├── editor/ # Code editor (900+ LOC, 7 files)
|
|
170
|
+
│ │ ├── code-editor.tsx # Monaco Editor integration (@monaco-editor/react, v2.0+)
|
|
171
|
+
│ │ ├── diff-viewer.tsx # Monaco diff viewer for git diffs (v2.0+)
|
|
172
|
+
│ │ ├── conflict-editor.tsx # Inline conflict resolution (3-way markers, visual highlighting, v0.9.86+)
|
|
173
|
+
│ │ ├── editor-breadcrumb.tsx # VSCode-style breadcrumb with nested dropdown
|
|
174
|
+
│ │ ├── editor-toolbar.tsx # File-type contextual toolbar
|
|
175
|
+
│ │ ├── csv-preview.tsx # CSV table viewer with @tanstack/react-table
|
|
176
|
+
│ │ └── editor-placeholder.tsx
|
|
177
|
+
│ ├── explorer/ # File tree (489 LOC, 2 files)
|
|
178
|
+
│ │ ├── file-tree.tsx # Directory tree view
|
|
179
|
+
│ │ └── file-actions.tsx # Create/delete/rename context menu
|
|
180
|
+
│ ├── git/ # Git UI (1632 LOC, 3 files)
|
|
181
|
+
│ │ ├── git-status-panel.tsx # Status, staging UI
|
|
182
|
+
│ │ ├── git-graph.tsx # Mermaid-based commit graph
|
|
183
|
+
│ │ └── git-placeholder.tsx
|
|
184
|
+
│ ├── layout/ # Layout components (13 files)
|
|
185
|
+
│ │ ├── panel-layout.tsx # Main grid layout (react-resizable-panels)
|
|
186
|
+
│ │ ├── editor-panel.tsx # Wrapper for tab content within a panel (v0.9.85+: fallback guards)
|
|
187
|
+
│ │ ├── project-bar.tsx # 52px sidebar with project avatars, share popover
|
|
188
|
+
│ │ ├── project-bottom-sheet.tsx # Mobile project switcher
|
|
189
|
+
│ │ ├── sidebar.tsx # Left sidebar (Explorer/Git/Database/Settings tabs)
|
|
190
|
+
│ │ ├── tab-bar.tsx # Tab bar with icons, connection color display (v0.9.85+: fallback guards)
|
|
191
|
+
│ │ ├── draggable-tab.tsx # Draggable tab with context menu, rename, connection color
|
|
192
|
+
│ │ ├── tab-content.tsx # Router for tab content (v0.9.85+: fallback guards)
|
|
193
|
+
│ │ ├── split-drop-overlay.tsx # Drop zone for tab splitting
|
|
194
|
+
│ │ ├── command-palette.tsx # Global command palette (Shift+Shift, DB table search)
|
|
195
|
+
│ │ ├── add-project-form.tsx # Modal form to add projects
|
|
196
|
+
│ │ ├── mobile-nav.tsx # Bottom navigation for mobile (v0.9.85+: fallback guards)
|
|
197
|
+
│ │ └── mobile-drawer.tsx # Mobile overlay drawer
|
|
198
|
+
│ ├── database/ # Database management (5 files, 300+ LOC)
|
|
199
|
+
│ │ ├── database-sidebar.tsx # Sidebar tab container (connection list, form)
|
|
200
|
+
│ │ ├── connection-list.tsx # Connections list with actions, color badges
|
|
201
|
+
│ │ ├── connection-form-dialog.tsx # Create/edit connection form (SQLite/Postgres)
|
|
202
|
+
│ │ ├── connection-color-picker.tsx # WCAG contrast-aware color picker
|
|
203
|
+
│ │ └── use-connections.ts # Hook for connection CRUD operations
|
|
204
|
+
│ ├── projects/ # Project management (339 LOC, 2 files)
|
|
205
|
+
│ ├── settings/ # Settings panel (theme + AI provider + accounts config UI)
|
|
206
|
+
│ │ ├── settings-tab.tsx # Main settings panel with tabs
|
|
207
|
+
│ │ ├── ai-settings-section.tsx # AI provider configuration
|
|
208
|
+
│ │ └── accounts-settings-section.tsx # Multi-account management (add, edit, delete, activate)
|
|
209
|
+
│ ├── terminal/ # xterm.js wrapper (143 LOC, 2 files)
|
|
210
|
+
│ ├── shared/ # Shared components (2 files)
|
|
211
|
+
│ │ ├── markdown-renderer.tsx # Render Markdown with syntax highlighting
|
|
212
|
+
│ │ └── bug-report-popup.tsx # Global bug report popup
|
|
213
|
+
│ ├── sqlite/ # SQLite viewer (unified connectionId API mode)
|
|
214
|
+
│ │ ├── sqlite-viewer.tsx # Display table data, execute queries
|
|
215
|
+
│ │ └── use-sqlite.ts # Hook for SQLite operations via /api/db routes
|
|
216
|
+
│ ├── postgres/ # PostgreSQL viewer (unified connectionId API mode)
|
|
217
|
+
│ │ ├── postgres-viewer.tsx # Display table data, execute queries
|
|
218
|
+
│ │ └── use-postgres.ts # Hook for Postgres operations via /api/db routes
|
|
219
|
+
│ └── ui/ # Radix + shadcn primitives (14 files)
|
|
220
|
+
│ └── button, input, label, dialog, dropdown-menu, select, tabs, tooltip, etc.
|
|
221
|
+
├── tests/
|
|
222
|
+
│ ├── test-setup.ts # Disable auth for tests
|
|
223
|
+
│ ├── unit/
|
|
224
|
+
│ │ ├── providers/ # Mock provider, SDK tests
|
|
225
|
+
│ │ └── services/ # Chat, config, db, session-log, push-notification tests
|
|
226
|
+
│ └── integration/
|
|
227
|
+
│ ├── claude-agent-sdk-integration.test.ts
|
|
228
|
+
│ ├── sqlite-migration.test.ts # SQLite migration validation
|
|
229
|
+
│ ├── api/ # Chat route tests
|
|
230
|
+
│ └── ws/ # WebSocket tests
|
|
231
|
+
├── scripts/
|
|
232
|
+
│ ├── build.ts # Build CLI binary (bun build --compile)
|
|
233
|
+
│ └── dev.ts # Dev server helpers
|
|
234
|
+
├── dist/ # Build output
|
|
235
|
+
│ ├── ppm # Compiled CLI binary
|
|
236
|
+
│ └── web/ # Frontend bundle
|
|
237
|
+
├── node_modules/
|
|
238
|
+
├── .env.example # Environment template
|
|
239
|
+
├── ppm.yaml # Auto-generated project config
|
|
240
|
+
├── tsconfig.json # TS config (strict mode, path aliases)
|
|
241
|
+
├── vite.config.ts # Vite config (React, PWA, proxy to :8080)
|
|
242
|
+
├── tailwind.config.ts # Tailwind (dark mode, custom colors)
|
|
243
|
+
├── package.json # Dependencies
|
|
244
|
+
├── bunfig.toml # Bun config (root directory)
|
|
245
|
+
└── README.md # Project overview
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Key Module Responsibilities
|
|
249
|
+
|
|
250
|
+
### CLI Layer (src/cli/)
|
|
251
|
+
- **Responsibility:** Command-line interface for managing PPM
|
|
252
|
+
- **Key Functions:**
|
|
253
|
+
- `start` — Start Hono server (background by default, --foreground/-f for foreground, --share/-s for tunnel)
|
|
254
|
+
- `stop` — Stop daemon (reads status.json first, falls back to ppm.pid)
|
|
255
|
+
- `open` — Launch browser to active server
|
|
256
|
+
- `init` — Scan filesystem for git repos, create ppm.yaml
|
|
257
|
+
- `projects` — Add/remove/list projects in config
|
|
258
|
+
- `config` — View/edit config values
|
|
259
|
+
- `git` — Run git operations on active project
|
|
260
|
+
- `chat` — Send messages to chat session (CLI mode)
|
|
261
|
+
- **Pattern:** Command handler pattern (Commander.js)
|
|
262
|
+
|
|
263
|
+
### Server Layer (src/server/)
|
|
264
|
+
- **Responsibility:** HTTP REST API + WebSocket server
|
|
265
|
+
- **Key Routes:**
|
|
266
|
+
- `/api/health` — Health check
|
|
267
|
+
- `/api/auth/check` — Verify token validity
|
|
268
|
+
- `/api/projects` — CRUD projects
|
|
269
|
+
- `/api/project/:name/*` — Project-scoped routes (chat, git, files)
|
|
270
|
+
- `/ws/project/:name/chat/:sessionId` — Chat streaming
|
|
271
|
+
- `/ws/project/:name/terminal/:id` — Terminal I/O
|
|
272
|
+
- **Pattern:** Project-scoped routing via ProviderRegistry
|
|
273
|
+
|
|
274
|
+
### Service Layer (src/services/)
|
|
275
|
+
- **Responsibility:** Business logic, data operations, infrastructure (tunneling, database connections)
|
|
276
|
+
- **Services:**
|
|
277
|
+
- **ChatService** — Session lifecycle, message queueing, streaming
|
|
278
|
+
- **ConfigService** — Config loading (YAML→SQLite migration)
|
|
279
|
+
- **DbService** — SQLite persistence (9 tables, WAL mode, schema v5, connection/account CRUD, table cache)
|
|
280
|
+
- **AccountService** — Multi-account management, token encryption/decryption
|
|
281
|
+
- **AccountSelectorService** — Select active account based on config
|
|
282
|
+
- **GitService** — Git commands via simple-git
|
|
283
|
+
- **FileService** — File ops with path validation
|
|
284
|
+
- **ProjectService** — Project CRUD, scanning, resolution
|
|
285
|
+
- **TerminalService** — PTY lifecycle, shell spawning
|
|
286
|
+
- **ClaudeUsageService** — Token tracking, cost calculation
|
|
287
|
+
- **PushNotificationService** — Web push subscriptions
|
|
288
|
+
- **SessionLogService** — Audit logs with sensitive data redaction
|
|
289
|
+
- **CloudflaredService** — Download/cache cloudflared binary (platform-aware)
|
|
290
|
+
- **TunnelService** — Spawn tunnel, extract URL, cleanup on exit
|
|
291
|
+
- **TableCacheService** — Cache table metadata across connections, search tables by name
|
|
292
|
+
- **DatabaseAdapterRegistry** — Register/retrieve DatabaseAdapter implementations (extensible pattern)
|
|
293
|
+
- **SQLiteAdapter** — SQLite connection/query execution with readonly checks
|
|
294
|
+
- **PostgresAdapter** — PostgreSQL connection/query execution with readonly checks
|
|
295
|
+
- **PPMBotService** — Coordinator orchestrator (startup, shutdown, message routing, task polling)
|
|
296
|
+
- **PPMBotSessionManager** — Coordinator session per chat in ~/.ppm/bot/, project resolver
|
|
297
|
+
- **PPMBotTelegramService** — Telegram API (long-polling, send, edit, typing, command handling)
|
|
298
|
+
- **PPMBotMemoryService** — SQLite memory persistence (save, recall, project-aware search)
|
|
299
|
+
- **executeDelegation()** — Task execution (creates isolated session, runs prompt, captures result)
|
|
300
|
+
- **PPMBotFormatterService** — Markdown → Telegram HTML, message chunking (4096 char limit)
|
|
301
|
+
- **PPMBotStreamerService** — ChatEvent streaming → progressive Telegram message editing
|
|
302
|
+
- **ClawBotService** — Legacy Telegram bot (deprecated v0.9.11, replaced by PPMBot coordinator)
|
|
303
|
+
- **ClawBotTelegramService** — Legacy Telegram API
|
|
304
|
+
- **ClawBotSessionService** — Legacy session mapping
|
|
305
|
+
- **ClawBotMemoryService** — Legacy memory service
|
|
306
|
+
- **ClawBotFormatterService** — Legacy formatter
|
|
307
|
+
- **ClawBotStreamerService** — Legacy streamer
|
|
308
|
+
- **Pattern:** Singleton services, dependency injection via imports, adapter registry for extensibility
|
|
309
|
+
|
|
310
|
+
### Provider Layer (src/providers/)
|
|
311
|
+
- **Responsibility:** AI model abstraction, config-driven initialization
|
|
312
|
+
- **Providers:**
|
|
313
|
+
- **claude-agent-sdk** — Primary (official SDK, streaming, tool use). Reads model/effort/maxTurns/budget/thinking from config.
|
|
314
|
+
- **mock** — Test provider (ignores config)
|
|
315
|
+
- **Interface:** Async generator streaming, tool approval callback
|
|
316
|
+
- **Pattern:** Registry pattern for pluggable AI providers. Config read fresh per query (configService integration).
|
|
317
|
+
|
|
318
|
+
### Frontend Layer (src/web/)
|
|
319
|
+
- **Responsibility:** React UI for project management, chat, terminal, editor
|
|
320
|
+
- **Key Stores:**
|
|
321
|
+
- **ProjectStore** — Active project, project list, localStorage persistence
|
|
322
|
+
- **TabStore** — Tab facade, delegates to panel-store
|
|
323
|
+
- **PanelStore** — Grid layout, panel creation, keep-alive snapshots
|
|
324
|
+
- **FileStore** — File cache
|
|
325
|
+
- **SettingsStore** — Theme, sidebar, git view, device name
|
|
326
|
+
- **Pattern:** Zustand for state, React.lazy() for tab content splitting
|
|
327
|
+
|
|
328
|
+
## Data Flow Diagrams
|
|
329
|
+
|
|
330
|
+
### Chat Streaming Flow
|
|
331
|
+
```
|
|
332
|
+
User types message
|
|
333
|
+
↓
|
|
334
|
+
MessageInput captures text
|
|
335
|
+
↓
|
|
336
|
+
useChat hook calls POST /api/project/:name/chat/sessions/:id/messages
|
|
337
|
+
↓
|
|
338
|
+
ChatService streams AI response
|
|
339
|
+
↓
|
|
340
|
+
WebSocket connection streams ChatEvent objects
|
|
341
|
+
↓
|
|
342
|
+
useChat accumulates message
|
|
343
|
+
↓
|
|
344
|
+
MessageList renders streamed content
|
|
345
|
+
↓
|
|
346
|
+
User approves tool use (if needed)
|
|
347
|
+
↓
|
|
348
|
+
ChatWsClientMessage sent with approval_response
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Terminal I/O Flow
|
|
352
|
+
```
|
|
353
|
+
User types in terminal
|
|
354
|
+
↓
|
|
355
|
+
xterm.js captures keypress
|
|
356
|
+
↓
|
|
357
|
+
useTerminal sends {type: "input", data: "..."} via WebSocket
|
|
358
|
+
↓
|
|
359
|
+
TerminalService writes to PTY stdin
|
|
360
|
+
↓
|
|
361
|
+
Shell output captured from PTY stdout
|
|
362
|
+
↓
|
|
363
|
+
{type: "output", data: "..."} sent back via WebSocket
|
|
364
|
+
↓
|
|
365
|
+
xterm.js renders output
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Git Operation Flow
|
|
369
|
+
```
|
|
370
|
+
User stages file in UI
|
|
371
|
+
↓
|
|
372
|
+
FileActions calls POST /api/project/:name/git/stage
|
|
373
|
+
↓
|
|
374
|
+
GitService runs git add <file>
|
|
375
|
+
↓
|
|
376
|
+
GitStatusPanel refreshes: GET /api/project/:name/git/status
|
|
377
|
+
↓
|
|
378
|
+
UI updates staged/unstaged lists
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Git Workflow Enhancements (v0.9.86+)
|
|
382
|
+
|
|
383
|
+
**Stash Management:**
|
|
384
|
+
- Toolbar popover lists all stashes (index, abbreviated hash, message)
|
|
385
|
+
- Apply/Pop/Drop actions per stash with visual feedback
|
|
386
|
+
- "Stash Changes" button saves uncommitted work to stash list
|
|
387
|
+
- Stash state integrated into RepoInfo and refreshed on status changes
|
|
388
|
+
|
|
389
|
+
**Conflict Detection & Resolution:**
|
|
390
|
+
- Detects merge/rebase/cherry-pick state from .git sentinel files (MERGE_HEAD, rebase-merge/, CHERRY_PICK_HEAD)
|
|
391
|
+
- Parses git status UU/AA/DD/AU/UA/DU/UD codes for unmerged entries
|
|
392
|
+
- Conflict state banner shows state type, progress (e.g., "3/5" for rebase), and Continue/Skip/Abort actions
|
|
393
|
+
- New `conflict-editor` tab type with Monaco-based visual conflict resolution
|
|
394
|
+
- Parses 3-way conflict markers (<<<<<<, =======, >>>>>>>)
|
|
395
|
+
- Highlights current (green), incoming (blue), and marker lines (gray)
|
|
396
|
+
- Accept buttons for Current / Incoming / Both with automatic save
|
|
397
|
+
- Real-time conflict counter: "N conflicts remaining" → "All resolved"
|
|
398
|
+
|
|
399
|
+
**Rebase from Context Menu:**
|
|
400
|
+
- Right-click commits to open rebase menu
|
|
401
|
+
- Confirmation dialog with branch/target selection
|
|
402
|
+
- Rebase state tracking and progress display during operation
|
|
403
|
+
|
|
404
|
+
**Worktree Management:**
|
|
405
|
+
- Popover UI for listing, creating, removing, pruning worktrees
|
|
406
|
+
- Current worktree highlighted with active badge
|
|
407
|
+
- "Create Worktree Here..." option in commit context menu
|
|
408
|
+
- Auto-add unregistered worktrees as projects with confirmation
|
|
409
|
+
- Branch-already-exists handling with force-replace option
|
|
410
|
+
|
|
411
|
+
### Tab System Safety (v0.9.85+)
|
|
412
|
+
|
|
413
|
+
All tab routing and rendering components now include fallback guards for unknown tab types:
|
|
414
|
+
|
|
415
|
+
**Components Updated:**
|
|
416
|
+
- `tab-bar.tsx` — Tab item rendering with fallback icon/label
|
|
417
|
+
- `mobile-nav.tsx` — Mobile tab selection with fallback handling
|
|
418
|
+
- `tab-content.tsx` — Content router with "Unknown tab type" fallback
|
|
419
|
+
- `editor-panel.tsx` — Panel wrapper with graceful unknown type handling
|
|
420
|
+
|
|
421
|
+
**Behavior:**
|
|
422
|
+
- Unknown tab types no longer crash the UI
|
|
423
|
+
- Fallback displays icon + tab identifier
|
|
424
|
+
- Users can still close/manage unknown tabs
|
|
425
|
+
- Enables safe extension tab additions without core UI changes
|
|
426
|
+
|
|
427
|
+
**Motivation:** Support future extension-contributed tab types without requiring core UI updates.
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Critical Types
|
|
432
|
+
|
|
433
|
+
| Type | Location | Purpose |
|
|
434
|
+
|---|---|---|
|
|
435
|
+
| `ApiResponse<T>` | types/api.ts | Standard envelope for all REST responses |
|
|
436
|
+
| `AIProvider` | providers/provider.interface.ts | Interface for AI model adapters |
|
|
437
|
+
| `ChatEvent` | types/chat.ts | Union of streaming message types |
|
|
438
|
+
| `GitStatus` | types/git.ts | Current branch, staged, unstaged, untracked files (includes conflicted field v0.9.86+) |
|
|
439
|
+
| `Session` | types/chat.ts | Chat session with ID, projectName, title, createdAt |
|
|
440
|
+
| `Project` | types/project.ts | Project config (name, path) |
|
|
441
|
+
| `MergeState` | ext-git-graph/src/types.ts | Merge/rebase/cherry-pick state with progress tracking (v0.9.86+) |
|
|
442
|
+
| `TabType` | web/stores/tab-store.ts | "editor" \| "chat" \| "terminal" \| "database" \| "git-graph" \| "conflict-editor" \| "settings" (v0.9.86+) |
|
|
443
|
+
|
|
444
|
+
## External Dependencies
|
|
445
|
+
|
|
446
|
+
| Package | Purpose | Version |
|
|
447
|
+
|---------|---------|---------|
|
|
448
|
+
| hono | HTTP framework | 4.12.8 |
|
|
449
|
+
| simple-git | Git CLI wrapper | 3.33 |
|
|
450
|
+
| @monaco-editor/react | Code editor | 4.7.0 |
|
|
451
|
+
| xterm | Terminal emulator | 6.0 |
|
|
452
|
+
| zustand | State management | 5.0.11 |
|
|
453
|
+
| @anthropic-ai/claude-agent-sdk | AI provider | 0.2.81 |
|
|
454
|
+
| vite | Frontend bundler | 8.0 |
|
|
455
|
+
| tailwindcss | Utility CSS | 4.2 |
|
|
456
|
+
| radix-ui | Accessible components | 1.4.3 |
|
|
457
|
+
| next-themes | Theme switcher | 0.4.6 |
|
|
458
|
+
| @tanstack/react-table | Table library | 8.21.3 |
|
|
459
|
+
| @tanstack/react-virtual | Virtual scrolling | 3.13.23 |
|
|
460
|
+
|
|
461
|
+
## Build Output
|
|
462
|
+
|
|
463
|
+
**CLI Binary:** `dist/ppm` (compiled via `bun build --compile`)
|
|
464
|
+
- Single-file executable
|
|
465
|
+
- Includes embedded server + frontend assets
|
|
466
|
+
- Runnable on Linux/macOS without Bun installed
|
|
467
|
+
|
|
468
|
+
**Frontend:** `dist/web/` (Vite bundle)
|
|
469
|
+
- index.html + chunks
|
|
470
|
+
- PWA manifest, service worker
|
|
471
|
+
- Assets (~500KB gzipped)
|
|
472
|
+
|
|
473
|
+
## Multi-Provider Architecture (v0.8.60)
|
|
474
|
+
|
|
475
|
+
### Dynamic Model Listing Feature
|
|
476
|
+
|
|
477
|
+
**Problem:** Different AI providers expose different models. Claude has hardcoded models, but CLI-based providers (e.g., Cursor) discover models at runtime.
|
|
478
|
+
|
|
479
|
+
**Solution:** Optional `listModels()` method on `AIProvider` interface
|
|
480
|
+
|
|
481
|
+
### Provider Interface
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
// src/types/chat.ts
|
|
485
|
+
export interface ModelOption {
|
|
486
|
+
value: string; // Model ID (e.g., "claude-sonnet-4-6")
|
|
487
|
+
label: string; // Display name (e.g., "Claude Sonnet 4.6")
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
interface AIProvider {
|
|
491
|
+
// Required methods
|
|
492
|
+
createSession(): Promise<Session>;
|
|
493
|
+
sendMessage(sessionId, message, context?): AsyncIterable<ChatEvent>;
|
|
494
|
+
|
|
495
|
+
// Optional methods
|
|
496
|
+
listModels?(): Promise<ModelOption[]>;
|
|
497
|
+
isAvailable?(): Promise<boolean>;
|
|
498
|
+
// ... (5 other optional methods)
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Provider Implementations
|
|
503
|
+
|
|
504
|
+
#### Claude (agent-sdk.ts)
|
|
505
|
+
- `listModels()` returns hardcoded 2 models: Sonnet 4.6, Opus 4.6
|
|
506
|
+
- Direct implementation (no subprocess)
|
|
507
|
+
|
|
508
|
+
#### Cursor (cursor-provider.ts)
|
|
509
|
+
- `listModels()` runs `cursor-agent --list-models` subprocess
|
|
510
|
+
- 5-minute TTL cache (prevents repeated subprocess calls)
|
|
511
|
+
- 10-second timeout (graceful fallback to empty list)
|
|
512
|
+
- Extends `CliProvider` abstract base
|
|
513
|
+
|
|
514
|
+
#### Mock (mock-provider.ts)
|
|
515
|
+
- For testing; returns canned models
|
|
516
|
+
|
|
517
|
+
### API Endpoints
|
|
518
|
+
|
|
519
|
+
**Global Models Endpoint** (`GET /api/settings/ai/providers/:id/models`)
|
|
520
|
+
```typescript
|
|
521
|
+
// Used in Settings UI (no project context needed)
|
|
522
|
+
settingsRoutes.get("/ai/providers/:id/models", async (c) => {
|
|
523
|
+
const provider = providerRegistry.get(c.req.param("id"));
|
|
524
|
+
const models = await provider.listModels?.() ?? [];
|
|
525
|
+
return c.json(ok(models));
|
|
526
|
+
});
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
**Project-Scoped Models Endpoint** (`GET /api/project/:name/chat/providers/:providerId/models`)
|
|
530
|
+
```typescript
|
|
531
|
+
// Used in Chat tab (scoped to project for consistency)
|
|
532
|
+
chatRoutes.get("/providers/:providerId/models", async (c) => {
|
|
533
|
+
const provider = providerRegistry.get(c.req.param("providerId"));
|
|
534
|
+
const models = await provider.listModels?.() ?? [];
|
|
535
|
+
return c.json(ok(models));
|
|
536
|
+
});
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Provider Registry Pattern
|
|
540
|
+
|
|
541
|
+
**list() — User-facing providers:**
|
|
542
|
+
```typescript
|
|
543
|
+
list(): ProviderInfo[] {
|
|
544
|
+
return [
|
|
545
|
+
{ id: "claude", name: "Claude" },
|
|
546
|
+
{ id: "cursor", name: "Cursor" }
|
|
547
|
+
// mock excluded
|
|
548
|
+
];
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
**listAll() — All providers (internal):**
|
|
553
|
+
```typescript
|
|
554
|
+
listAll(): ProviderInfo[] {
|
|
555
|
+
return [..., { id: "mock", name: "Mock" }];
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
**Auto-Bootstrap:**
|
|
560
|
+
```typescript
|
|
561
|
+
// On startup, detect CLI providers
|
|
562
|
+
async bootstrapProviders() {
|
|
563
|
+
const cursor = this.providers.get("cursor");
|
|
564
|
+
if (cursor && await cursor.isAvailable?.()) {
|
|
565
|
+
// Auto-create config entry if detected
|
|
566
|
+
// Save config (only if new)
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### UI Components
|
|
572
|
+
|
|
573
|
+
#### AI Settings Section (ai-settings-section.tsx) — UPDATED
|
|
574
|
+
- Per-provider tabs (Claude, Cursor, etc.)
|
|
575
|
+
- Dynamic model dropdowns fetched from `/api/settings/ai/providers/:id/models`
|
|
576
|
+
- Fallback to hardcoded models if API call fails
|
|
577
|
+
- Provider-aware settings (SDK vs CLI options)
|
|
578
|
+
|
|
579
|
+
#### Chat History Bar (chat-history-bar.tsx) — ADDED
|
|
580
|
+
- Provider badges showing active provider for each session
|
|
581
|
+
- Provider-aware usage display:
|
|
582
|
+
- **Claude:** Full stats `(tokens_in:X, tokens_out:Y, cost: $Z)`
|
|
583
|
+
- **Other:** Context-only `(tokens: X)`
|
|
584
|
+
|
|
585
|
+
### Configuration
|
|
586
|
+
|
|
587
|
+
```yaml
|
|
588
|
+
ai:
|
|
589
|
+
default_provider: claude
|
|
590
|
+
providers:
|
|
591
|
+
claude:
|
|
592
|
+
type: agent-sdk
|
|
593
|
+
model: claude-sonnet-4-6 # from listModels()
|
|
594
|
+
effort: high
|
|
595
|
+
max_turns: 100
|
|
596
|
+
cursor:
|
|
597
|
+
type: cli
|
|
598
|
+
model: cursor-fast # from listModels()
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
### Testing
|
|
602
|
+
|
|
603
|
+
**New Integration Tests (13 tests):**
|
|
604
|
+
- `provider-models-api.test.ts` — Model API endpoints
|
|
605
|
+
- `chat-service-multi-provider.test.ts` — Multi-provider flows
|
|
606
|
+
- `cursor-provider.test.ts` — Subprocess TTL cache, timeout handling
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Testing Strategy
|
|
611
|
+
|
|
612
|
+
| Test Type | Location | Coverage |
|
|
613
|
+
|-----------|----------|----------|
|
|
614
|
+
| Unit | tests/unit/ | Services, utilities |
|
|
615
|
+
| Integration | tests/integration/ | API routes, WebSocket, provider models |
|
|
616
|
+
| E2E | None yet | Planned for v3 |
|
|
617
|
+
|
|
618
|
+
**Key Gotchas:**
|
|
619
|
+
- Test DB isolated per test (never writes to ~/.ppm/ppm.db)
|
|
620
|
+
- Auth disabled in test mode (test-setup.ts)
|
|
621
|
+
- Mock provider used for deterministic responses
|
|
622
|
+
- 492 passing tests (0 failures, v0.8.60)
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
## Extension System (v0.9.0+)
|
|
627
|
+
|
|
628
|
+
### Core Architecture
|
|
629
|
+
|
|
630
|
+
**Installation Directory:** `~/.ppm/extensions/node_modules/`
|
|
631
|
+
**State Storage:** SQLite `extension_storage` table (globalState + workspaceState)
|
|
632
|
+
**Worker Isolation:** Bun Worker threads per activated extension
|
|
633
|
+
**RPC Protocol:** Typed request/response/event messaging
|
|
634
|
+
|
|
635
|
+
### New Files & Services
|
|
636
|
+
- `src/types/extension.ts` — ExtensionManifest, ExtensionContext, RpcMessage types
|
|
637
|
+
- `src/server/routes/extensions.ts` — REST API (GET/POST/DELETE/PATCH)
|
|
638
|
+
- `src/services/extension.service.ts` — Lifecycle, activation, state management (120 LOC)
|
|
639
|
+
- `src/services/extension-installer.ts` — npm install, symlink, removal (100 LOC)
|
|
640
|
+
- `src/services/extension-manifest.ts` — Parse + discover manifests (70 LOC)
|
|
641
|
+
- `src/services/extension-rpc.ts` — RPC channel implementation (120 LOC)
|
|
642
|
+
- `src/services/extension-host-worker.ts` — Worker-side extension loading (150 LOC)
|
|
643
|
+
- `src/services/contribution-registry.ts` — Central command/view/config registry (80 LOC)
|
|
644
|
+
- `src/cli/commands/ext-cmd.ts` — Extension CLI commands (121 LOC)
|
|
645
|
+
|
|
646
|
+
### Manifest Example (package.json)
|
|
647
|
+
```json
|
|
648
|
+
{
|
|
649
|
+
"name": "@ppm/ext-database",
|
|
650
|
+
"ppm": {
|
|
651
|
+
"displayName": "Database Browser",
|
|
652
|
+
"main": "dist/extension.js",
|
|
653
|
+
"activationEvents": ["onView:databases"],
|
|
654
|
+
"contributes": {
|
|
655
|
+
"commands": [{"command": "ppm.database.openConnection", "title": "..."}],
|
|
656
|
+
"views": {"explorer": [{"id": "databases", "name": "Databases"}]},
|
|
657
|
+
"configuration": {"properties": {"ppm.database.maxRows": {"type": "number"}}}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
### REST API Endpoints
|
|
664
|
+
- `GET /api/extensions` — List installed
|
|
665
|
+
- `POST /api/extensions` — Install from npm
|
|
666
|
+
- `DELETE /api/extensions/:id` — Remove
|
|
667
|
+
- `PATCH /api/extensions/:id` — Enable/disable
|
|
668
|
+
- `GET /api/extensions/contributions` — List all contributions
|
|
669
|
+
|
|
670
|
+
### CLI Commands
|
|
671
|
+
```
|
|
672
|
+
ppm ext list # List extensions
|
|
673
|
+
ppm ext install @ppm/ext-db # Install
|
|
674
|
+
ppm ext remove @ppm/ext-db # Uninstall
|
|
675
|
+
ppm ext enable @ppm/ext-db # Enable
|
|
676
|
+
ppm ext disable @ppm/ext-db # Disable
|
|
677
|
+
ppm ext dev /path/to/src # Dev symlink
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Bundled Extensions (v0.9.85+)
|
|
681
|
+
|
|
682
|
+
PPM ships with pre-built extensions in `packages/ext-*` that are auto-discovered and available out-of-the-box:
|
|
683
|
+
|
|
684
|
+
**Discovery:**
|
|
685
|
+
- `discoverBundledManifests()` scans `packages/` for directories matching `ext-*`
|
|
686
|
+
- Bundled extensions loaded during `discover()` before user-installed extensions
|
|
687
|
+
- User-installed extensions override bundled if same ID (user takes precedence)
|
|
688
|
+
|
|
689
|
+
**Behavior:**
|
|
690
|
+
- `ppm ext list` shows "Source" column: `bundled` (cyan) vs `user`
|
|
691
|
+
- Bundled extensions cannot be removed (`ppm ext remove` rejected with helpful message)
|
|
692
|
+
- Use `ppm ext disable` to turn off bundled extensions
|
|
693
|
+
- Removal protection prevents accidental deletion of core extensions
|
|
694
|
+
|
|
695
|
+
**Current Bundled Extensions:**
|
|
696
|
+
- `@ppm/ext-git-graph` — Interactive git history visualization with workflow actions
|
|
697
|
+
|
|
698
|
+
**Architecture:**
|
|
699
|
+
- Extension paths tracked in `extensionService.extensionPaths` (ID → directory)
|
|
700
|
+
- Bundled IDs tracked in `extensionService.bundledIds` Set
|
|
701
|
+
- `isBundled(id)` public method for checking extension source
|
|
702
|
+
|
|
703
|
+
---
|
|
704
|
+
|
|
705
|
+
## ext-git-graph Extension (Git History Visualization)
|
|
706
|
+
|
|
707
|
+
### Overview
|
|
708
|
+
The git-graph extension provides an interactive SVG visualization of repository commit history with comprehensive git workflow support. Implements the vscode-git-graph deterministic layout algorithm with faithful branch path rendering.
|
|
709
|
+
|
|
710
|
+
### Key Features
|
|
711
|
+
|
|
712
|
+
**Graph Visualization:**
|
|
713
|
+
- Single SVG model with continuous Bézier branch paths for smooth merge visualization
|
|
714
|
+
- Deterministic lane assignment algorithm with greedy color reuse for branch lanes
|
|
715
|
+
- Shadow lines for visual depth and branch continuity
|
|
716
|
+
- Proper HEAD/stash node rendering (hollow circle for HEAD, nested circles for stash)
|
|
717
|
+
- Mobile SVG alignment: gridY matches 44px CSS row height for responsive layouts
|
|
718
|
+
|
|
719
|
+
**Git Workflow Actions:**
|
|
720
|
+
- **File Operations:** Stage/unstage files, open in editor, discard changes
|
|
721
|
+
- **Commits:** Create commits directly from webview with message and file selection
|
|
722
|
+
- **Branch Operations:** Stash/reset/clean with context menu and safety warnings
|
|
723
|
+
- **Repository:** Auto-fetch with configurable interval, manual fetch button
|
|
724
|
+
- **Filters:** Branch/tag/remote filters, tree/list view toggle
|
|
725
|
+
|
|
726
|
+
**UI Components:**
|
|
727
|
+
- Resizable graph column for flexible workspace adjustment
|
|
728
|
+
- Branch filter dropdown for quick navigation
|
|
729
|
+
- Tree/list view toggle for different visualization modes
|
|
730
|
+
- Commit detail panel with file diffs and action buttons
|
|
731
|
+
- Context menus with destructive operation warnings
|
|
732
|
+
|
|
733
|
+
### Architecture
|
|
734
|
+
|
|
735
|
+
**Location:** `packages/ext-git-graph/`
|
|
736
|
+
|
|
737
|
+
**Files:**
|
|
738
|
+
- `extension.ts` (370 LOC) — RPC handlers, git operations, settings management
|
|
739
|
+
- `webview-html.ts` (443 additions) — Faithful SVG graph rendering with deterministic layout
|
|
740
|
+
- `types.ts` — Extension settings, message types, git operation definitions
|
|
741
|
+
- `git-log-parser.ts` — Parse git log with branches, tags, remotes, stashes
|
|
742
|
+
- `extension.test.ts` (230+ lines) — Integration tests for RPC handlers
|
|
743
|
+
- `webview-html.test.ts` — Graph rendering and layout tests
|
|
744
|
+
|
|
745
|
+
**RPC Protocol:**
|
|
746
|
+
- `gitStatus()` — Get current repo state
|
|
747
|
+
- `gitLog()` — Fetch commit history
|
|
748
|
+
- `stage(path)` / `unstage(path)` — File staging
|
|
749
|
+
- `commit(message, files)` — Create commit
|
|
750
|
+
- `stash()` / `reset(ref)` / `clean()` — Branch operations
|
|
751
|
+
- `openFile(path)` — Open in editor (IPC to main window)
|
|
752
|
+
|
|
753
|
+
**Settings:**
|
|
754
|
+
- `autoFetchInterval: number` — Seconds between auto-fetches (0 = disabled)
|
|
755
|
+
|
|
756
|
+
### Security
|
|
757
|
+
|
|
758
|
+
**Path Validation:**
|
|
759
|
+
- `assertSafePath()` in extension-rpc-handlers ensures git operations only on registered project paths
|
|
760
|
+
- Prevents directory traversal attacks
|
|
761
|
+
- Cross-project workspace safety via RPC sandboxing
|
|
762
|
+
|
|
763
|
+
**XSS Prevention:**
|
|
764
|
+
- `escHtml()` applied to parent hashes and file status in detail panel
|
|
765
|
+
- Sanitized commit messages and metadata display
|
|
766
|
+
|
|
767
|
+
### Mobile & Responsive
|
|
768
|
+
|
|
769
|
+
- Long-press support for context menus on touch devices
|
|
770
|
+
- Responsive CSS with flexible column sizing
|
|
771
|
+
- Dark/light theme support via CSS variables
|
|
772
|
+
- Touch-friendly button sizing (44px minimum)
|
|
773
|
+
|
|
774
|
+
### Testing
|
|
775
|
+
|
|
776
|
+
**62 unit tests** covering:
|
|
777
|
+
- Git log parsing (commits, branches, tags, stashes)
|
|
778
|
+
- Parser edge cases (merge commits, rebases, detached HEAD)
|
|
779
|
+
- RPC handler validation and error cases
|
|
780
|
+
- Webview HTML rendering and layout algorithms
|
|
781
|
+
- Integration with main extension lifecycle
|
|
782
|
+
|
|
783
|
+
---
|
|
784
|
+
|
|
785
|
+
## Slash-Discovery Module (Modular Command Engine)
|
|
786
|
+
|
|
787
|
+
### Overview
|
|
788
|
+
Modular discovery engine for slash commands and skills. Replaces monolithic `slash-items.service.ts` with composable, testable modules. Supports:
|
|
789
|
+
- Skill roots: user-global (`~/.claude/skills/`), env vars, bundled assets
|
|
790
|
+
- SKILL.md parsing + loose `.md` files + command registry
|
|
791
|
+
- Shadowing resolution (project > user > bundled)
|
|
792
|
+
- Fuzzy search via Levenshtein distance
|
|
793
|
+
- Built-in commands (9 commands: /skills, /version, /help, etc.)
|
|
794
|
+
- Server-side + client-side search
|
|
795
|
+
|
|
796
|
+
### Architecture
|
|
797
|
+
**Location:** `src/services/slash-discovery/`
|
|
798
|
+
|
|
799
|
+
**Core Modules:**
|
|
800
|
+
- `types.ts` — DefinitionSource, SkillRoot, SlashItem, DiscoveryResult
|
|
801
|
+
- `definition-source.ts` — Priority ranking (project > user > bundled), scope mapping
|
|
802
|
+
- `discover-skill-roots.ts` — Ancestor walking, env var expansion, root discovery
|
|
803
|
+
- `skill-loader.ts` — SKILL.md extraction, loose .md + commands parsing
|
|
804
|
+
- `resolve-overrides.ts` — Shadowing resolution logic
|
|
805
|
+
- `fuzzy-search.ts` — Levenshtein-based matching with configurable threshold
|
|
806
|
+
- `builtin-commands.ts` — 9 built-in commands + descriptions
|
|
807
|
+
- `builtin-handlers.ts` — PPM-side handlers (/skills list, /version)
|
|
808
|
+
- `index.ts` — Main pipeline, exports
|
|
809
|
+
|
|
810
|
+
### Key Features
|
|
811
|
+
**Skill Discovery:**
|
|
812
|
+
```
|
|
813
|
+
~/.claude/skills/ppm-guide/SKILL.md → Parse [ppm-guide] commands
|
|
814
|
+
$CLAUDE_SKILLS_PATH/custom/ → Env-var roots
|
|
815
|
+
assets/skills/bundled/ → Built-in (ppm-guide)
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
**Shadowing Resolution:**
|
|
819
|
+
- Project-level overrides user-level overrides bundled defaults
|
|
820
|
+
- Prevents duplicate entries, maintains priority order
|
|
821
|
+
|
|
822
|
+
**Fuzzy Matching:**
|
|
823
|
+
- Levenshtein distance algorithm
|
|
824
|
+
- Configurable tolerance for typo handling
|
|
825
|
+
- Powers `/skills search <query>`
|
|
826
|
+
|
|
827
|
+
### API & CLI
|
|
828
|
+
|
|
829
|
+
**REST API:**
|
|
830
|
+
- `GET /chat/slash-items?q=<query>` — Optional server-side fuzzy search
|
|
831
|
+
- Response includes `type: "builtin"` items
|
|
832
|
+
|
|
833
|
+
**CLI Commands:**
|
|
834
|
+
```
|
|
835
|
+
ppm skills list # List discovered skills with source info
|
|
836
|
+
ppm skills search <query> # Fuzzy search skills
|
|
837
|
+
ppm skills info <name> # Detail view (name, description, source)
|
|
838
|
+
ppm skills --json # Machine-readable output
|
|
839
|
+
ppm skills --project <path> # Custom project scope
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
**WebSocket Interception:**
|
|
843
|
+
- Messages starting with `/skills` or `/version` intercepted by PPM before SDK
|
|
844
|
+
- Builtin handlers execute locally, reducing SDK subprocess overhead
|
|
845
|
+
|
|
846
|
+
### Bundled Guide Skill
|
|
847
|
+
- `assets/skills/ppm-guide/SKILL.md` — Auto-generated from `docs/`
|
|
848
|
+
- `scripts/generate-ppm-guide.ts` — Generator script
|
|
849
|
+
- `bun run generate:guide` — npm script to regenerate
|
|
850
|
+
|
|
851
|
+
---
|
|
852
|
+
|
|
853
|
+
## Recent Changes (v0.9.0+)
|
|
854
|
+
|
|
855
|
+
### v0.9.11 (PPMBot Coordinator Redesign)
|
|
856
|
+
- **Architecture Shift** — PPMBot transformed from direct AI chat executor to intelligent coordinator/team leader
|
|
857
|
+
- Single persistent coordinator session per chat in `~/.ppm/bot/` workspace
|
|
858
|
+
- Delegates project-specific tasks to subagents (spawns fresh PPM sessions per project)
|
|
859
|
+
- Decision framework: Answer directly if no project context needed, delegate if file access required
|
|
860
|
+
- Telegram commands reduced from 13 to 3 public (/start, /help, /status) + 1 hidden (/restart)
|
|
861
|
+
- **Delegation Flow**
|
|
862
|
+
- CLI: `ppm bot delegate --chat <id> --project <name> --prompt "<enriched>"` creates task
|
|
863
|
+
- Background task poller (5s interval) executes pending tasks
|
|
864
|
+
- Task execution: Creates isolated session, runs async generator, captures result summary
|
|
865
|
+
- UI: Settings panel shows delegated tasks with auto-refresh
|
|
866
|
+
- Abort/timeout handling: 900s default timeout per task
|
|
867
|
+
- **Database Schema v14** — New `bot_tasks` table (taskId, chatId, projectName, prompt, status, result, error, timeout)
|
|
868
|
+
- **Coordinator Identity** — `coordinator.md` replaces per-session identity, loaded from `~/.ppm/bot/coordinator.md`
|
|
869
|
+
- Cross-provider identity via XML context block injected into SDK subprocess
|
|
870
|
+
- Coordinator tools: bash-accessible `ppm bot` CLI commands (delegate, task-status, task-result, tasks)
|
|
871
|
+
- **CLI Expansion** — New `ppm bot` command group
|
|
872
|
+
- Delegation: `delegate`, `task-status`, `task-result`, `tasks`
|
|
873
|
+
- Project management: `project list`, `project current`, `project switch`
|
|
874
|
+
- Session mgmt: `session new`, `session list`, `session resume`, `session stop`
|
|
875
|
+
- Status/help: `status`, `version`, `restart`, `help`
|
|
876
|
+
- **Files Created:**
|
|
877
|
+
- `src/services/ppmbot/ppmbot-delegation.ts` — Delegation execution + result capture
|
|
878
|
+
- Updated: `src/services/ppmbot/ppmbot-service.ts` (task poller lifecycle)
|
|
879
|
+
- Updated: `src/cli/commands/bot-cmd.ts` (delegation + project/session commands)
|
|
880
|
+
- Updated: `src/services/db.service.ts` (bot_tasks table, schema v14 migration)
|
|
881
|
+
|
|
882
|
+
### v0.9.10 (ClawBot Telegram Integration)
|
|
883
|
+
- **Telegram Bot Service** — Long-polling Telegram bot with message routing
|
|
884
|
+
- Session mapping: chatID → PPM sessionID (per-user thread isolation)
|
|
885
|
+
- Pairing system: Code-based device pairing with owner approval in web UI
|
|
886
|
+
- Message queue: Handle concurrent Telegram messages without race conditions
|
|
887
|
+
- **Memory System** — FTS5 persistent conversation memory
|
|
888
|
+
- Hybrid extraction: AI extraction (primary) + regex fallback
|
|
889
|
+
- Cross-project search: Auto-detect project name mentions → include memories
|
|
890
|
+
- Decay/supersede: Memory relevance based on age + custom decay factors
|
|
891
|
+
- **Response Streaming** — Progressive Telegram message editing
|
|
892
|
+
- ChatEvent streaming with 1s throttle
|
|
893
|
+
- Markdown → Telegram HTML formatting with chunking (4096 char limit)
|
|
894
|
+
- **Settings & History**
|
|
895
|
+
- Settings UI: Enable/disable, paired devices, default project, system prompt, display toggles, debounce config
|
|
896
|
+
- Chat history: [Claw] prefix sessions with robot icon for easy identification
|
|
897
|
+
- **Database Schema v13** — `clawbot_sessions`, `clawbot_memories` (FTS5), `clawbot_paired_chats` tables
|
|
898
|
+
|
|
899
|
+
### v0.9.0 (Extension System Phase 1)
|
|
900
|
+
- **Extension Framework** — VSCode-compatible npm-installable extensions
|
|
901
|
+
- **Worker Isolation** — Crash-safe extension execution in Bun Workers
|
|
902
|
+
- **RPC Protocol** — Bidirectional messaging (request/response/events)
|
|
903
|
+
- **State Management** — globalState + workspaceState persistence in SQLite
|
|
904
|
+
- **Contribution Registry** — Commands, views, configuration registry
|
|
905
|
+
- **CLI Support** — `ppm ext` commands for lifecycle management
|
|
906
|
+
- **Dev Mode** — Symlink local extensions for development
|
|
907
|
+
|
|
908
|
+
### v0.8.60
|
|
909
|
+
- **Dynamic Model Listing** — `listModels?()` on AIProvider interface
|
|
910
|
+
- **Provider Models APIs** — Global and project-scoped endpoints
|
|
911
|
+
- **AI Settings UI** — Per-provider tabs with dynamic model dropdowns
|
|
912
|
+
- **Chat History Badges** — Provider-aware usage display
|
|
913
|
+
- **13 new integration tests** for provider models API
|
|
914
|
+
|
|
915
|
+
---
|
|
916
|
+
|