@hienlh/ppm 0.17.16 → 0.17.18
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 +19 -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-BgWg-ty8.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-CLn1LTxc.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-tTUVo4G3.js +13 -0
- package/dist/web/assets/{cobol-CpuUx69s.js → cobol-IM3E3iCH.js} +1 -1
- package/dist/web/assets/code-editor-DMfUjdk5.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-BosR4PW3.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-BqszurHp.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-CiomoOU6.js +1 -0
- package/dist/web/assets/dialog-BpkAWOy8.js +1 -0
- package/dist/web/assets/{diff-viewer-BfWixe_z.js → diff-viewer-aOrOaGWx.js} +1 -1
- package/dist/web/assets/dist-Bn3E6I4R.js +11 -0
- package/dist/web/assets/{docx-preview-CguUoTKe.js → docx-preview-BAzpJdua.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-CKUUvgOr.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-B6GFWhj4.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-z9FPvRBG.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-Bu31mwmF.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-CaX4gpN6.js} +1 -1
- package/dist/web/assets/index-4M24PSHW.js +50 -0
- package/dist/web/assets/index-BYFXiFsa.css +2 -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-Cv-U85V6.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-BNXJygz9.js} +3 -3
- package/dist/web/assets/markdown-renderer-DCsEEdo7.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-DADt1gJH.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-DZzbm9A4.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-BxpeiVkt.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-DJOhpW09.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-9TwIPvRj.js} +1 -1
- package/dist/web/assets/sqlite-viewer-D-3i_x28.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-CuVVp2wt.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-DrSqSrdX.js} +2 -2
- package/dist/web/assets/{tex-C3H3uMZf.js → tex-DJFSsuTD.js} +1 -1
- package/dist/web/assets/tool-cards-CtE_JnF-.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-BvzqffqR.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-DxdyVATR.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/cloud-share-popover.tsx +10 -2
- package/src/web/components/layout/mobile-drawer-tab-bar.tsx +10 -0
- package/src/web/components/layout/mobile-drawer.tsx +26 -9
- 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
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// Feasibility spike v2 — shared-channel group DISCUSSION (member<->member).
|
|
2
|
+
// Throwaway diagnostic. Mirrors test-tool.mjs (direct provider, no DB/UI).
|
|
3
|
+
//
|
|
4
|
+
// Implements the agreed model:
|
|
5
|
+
// - shared broadcast channel (in-memory bus) — all agents see it
|
|
6
|
+
// - windowed context injection (last K messages) per turn
|
|
7
|
+
// - speaker selection: @mention-driven, leader as fallback facilitator
|
|
8
|
+
// - talk = sequential turns; termination = leader "DONE:" OR max-turns cap OR budget-ish (turn cap)
|
|
9
|
+
// - prints the full GROUP CHAT HISTORY at the end (what the user asked to see)
|
|
10
|
+
//
|
|
11
|
+
// Usage: bun spike-group-channel.mjs [projectPath] [--turns N] [--keep]
|
|
12
|
+
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { readdir, mkdir, copyFile, rm, stat } from "node:fs/promises";
|
|
16
|
+
import { ClaudeAgentSdkProvider } from "./src/providers/claude-agent-sdk.ts";
|
|
17
|
+
import { configService } from "./src/services/config.service.ts";
|
|
18
|
+
|
|
19
|
+
configService.load();
|
|
20
|
+
delete process.env.CLAUDECODE;
|
|
21
|
+
|
|
22
|
+
const projectPath = process.argv.find((a, i) => i >= 2 && !a.startsWith("--")) || process.cwd();
|
|
23
|
+
const KEEP = process.argv.includes("--keep");
|
|
24
|
+
const turnsArg = process.argv.indexOf("--turns");
|
|
25
|
+
const MAX_TURNS = turnsArg > -1 ? Number(process.argv[turnsArg + 1]) : 8;
|
|
26
|
+
const WINDOW = 8; // inject last N channel messages
|
|
27
|
+
const TIMEOUT_MS = 120_000;
|
|
28
|
+
const CLAUDE_PROJECTS = join(homedir(), ".claude", "projects");
|
|
29
|
+
const ARCHIVE_DIR = join(homedir(), ".ppm", "teams", "spike", "transcripts");
|
|
30
|
+
|
|
31
|
+
const provider = new ClaudeAgentSdkProvider();
|
|
32
|
+
const opts = { permissionMode: "bypassPermissions" };
|
|
33
|
+
|
|
34
|
+
// The group. Leader is a normal participant that also facilitates + finalizes.
|
|
35
|
+
const TEAM = [
|
|
36
|
+
{ name: "lead", role: "the team LEAD. You kick off, keep discussion on track, and are the ONLY one who may finalize." },
|
|
37
|
+
{ name: "alice", role: "a backend engineer who favors simple, minimal schemas (YAGNI)." },
|
|
38
|
+
{ name: "bob", role: "a backend engineer who worries about query flexibility and future needs." },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const TASK =
|
|
42
|
+
"Agree on how to store the group-chat message bus in PPM: ONE single SQLite table, " +
|
|
43
|
+
"or SEPARATE tables per concern. Discuss briefly, then lead finalizes with the decision + 1 reason.";
|
|
44
|
+
|
|
45
|
+
const sessions = {}; // name -> session
|
|
46
|
+
const channel = []; // { from, to, text }
|
|
47
|
+
|
|
48
|
+
function log(...a) { console.log(...a); }
|
|
49
|
+
function hr(t) { log("\n" + "=".repeat(64) + "\n" + t + "\n" + "=".repeat(64)); }
|
|
50
|
+
|
|
51
|
+
async function run(sessionId, prompt) {
|
|
52
|
+
const abort = new AbortController();
|
|
53
|
+
const timer = setTimeout(() => abort.abort(), TIMEOUT_MS);
|
|
54
|
+
let full = "", error = null;
|
|
55
|
+
try {
|
|
56
|
+
for await (const ev of provider.sendMessage(sessionId, prompt, { ...opts, signal: abort.signal })) {
|
|
57
|
+
if (abort.signal.aborted) break;
|
|
58
|
+
if (ev.type === "text") full += ev.content ?? "";
|
|
59
|
+
else if (ev.type === "error") error = ev.message;
|
|
60
|
+
else if (ev.type === "done") break;
|
|
61
|
+
}
|
|
62
|
+
} catch (e) { error = e instanceof Error ? e.message : String(e); }
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
return { text: full.trim(), error };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function windowed() {
|
|
68
|
+
return channel.slice(-WINDOW)
|
|
69
|
+
.map((m) => `${m.from} -> ${m.to}: ${m.text}`)
|
|
70
|
+
.join("\n") || "(channel empty)";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function turnPrompt(member, isFinalForced) {
|
|
74
|
+
const others = TEAM.filter((t) => t.name !== member.name).map((t) => t.name).join(", ");
|
|
75
|
+
return (
|
|
76
|
+
`You are "${member.name}", ${member.role}\n` +
|
|
77
|
+
`Team task: ${TASK}\n\n` +
|
|
78
|
+
`TEAM CHANNEL (recent, others: ${others}):\n${windowed()}\n\n` +
|
|
79
|
+
`Reply as ${member.name} in MAX 2 sentences. Address a teammate with @name (e.g. @bob).\n` +
|
|
80
|
+
(member.name === "lead"
|
|
81
|
+
? (isFinalForced
|
|
82
|
+
? `You MUST finalize now: start your message with "DONE:" then the decision + 1 reason.`
|
|
83
|
+
: `If the team has converged, start with "DONE:" then the decision + 1 reason. Otherwise steer the discussion and @ someone.`)
|
|
84
|
+
: `Do NOT write "DONE:" — only lead finalizes.`)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// pick next speaker from an @mention in text; else fall back to lead.
|
|
89
|
+
function nextSpeaker(text, current) {
|
|
90
|
+
const names = TEAM.map((t) => t.name);
|
|
91
|
+
const m = text.toLowerCase().match(/@(\w+)/);
|
|
92
|
+
if (m && names.includes(m[1]) && m[1] !== current) return m[1];
|
|
93
|
+
return current === "lead" ? "alice" : "lead"; // fallback keeps it moving
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function findJsonl(id) {
|
|
97
|
+
let dirs = [];
|
|
98
|
+
try { dirs = await readdir(CLAUDE_PROJECTS); } catch { return null; }
|
|
99
|
+
for (const d of dirs) {
|
|
100
|
+
const p = join(CLAUDE_PROJECTS, d, `${id}.jsonl`);
|
|
101
|
+
try { await stat(p); return p; } catch {}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
async function archiveAndDelete(id) {
|
|
106
|
+
const src = await findJsonl(id);
|
|
107
|
+
if (!src) return;
|
|
108
|
+
await mkdir(ARCHIVE_DIR, { recursive: true });
|
|
109
|
+
await copyFile(src, join(ARCHIVE_DIR, `${id}.jsonl`));
|
|
110
|
+
await rm(src, { force: true });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
hr(`SPIKE v2: shared-channel group discussion | project=${projectPath} | maxTurns=${MAX_TURNS}`);
|
|
115
|
+
|
|
116
|
+
for (const m of TEAM) {
|
|
117
|
+
sessions[m.name] = await provider.createSession({ title: `spike-${m.name}`, projectPath });
|
|
118
|
+
log(` ${m.name} session: ${sessions[m.name].id}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let speaker = "lead";
|
|
122
|
+
let done = false;
|
|
123
|
+
for (let turn = 1; turn <= MAX_TURNS && !done; turn++) {
|
|
124
|
+
const member = TEAM.find((t) => t.name === speaker);
|
|
125
|
+
const forceFinal = turn === MAX_TURNS && speaker === "lead";
|
|
126
|
+
const { text, error } = await run(sessions[speaker].id, turnPrompt(member, forceFinal));
|
|
127
|
+
if (error) { log(`\n[turn ${turn}] ${speaker} ERROR: ${error}`); break; }
|
|
128
|
+
|
|
129
|
+
const isDone = speaker === "lead" && /^\s*DONE:/i.test(text);
|
|
130
|
+
const to = (text.match(/@(\w+)/) || [])[1] || "all";
|
|
131
|
+
channel.push({ from: speaker, to: isDone ? "all" : to, text });
|
|
132
|
+
log(`\n[turn ${turn}] ${speaker} -> ${isDone ? "all" : to}:\n ${text.replace(/\n/g, "\n ")}`);
|
|
133
|
+
|
|
134
|
+
if (isDone) { done = true; break; }
|
|
135
|
+
|
|
136
|
+
// If max-turns is about to hit and lead hasn't spoken, force lead next to finalize.
|
|
137
|
+
speaker = (turn === MAX_TURNS - 1) ? "lead" : nextSpeaker(text, speaker);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!done) log("\n(!) discussion hit turn cap without explicit DONE — see last lead message");
|
|
141
|
+
|
|
142
|
+
// ---- what the user asked to see: the group chat history ----
|
|
143
|
+
hr("GROUP CHAT HISTORY (channel transcript)");
|
|
144
|
+
for (const m of channel) {
|
|
145
|
+
log(`[${m.from} -> ${m.to}] ${m.text}`);
|
|
146
|
+
log("");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ---- Option A+ cleanup (proves clean-up path again) ----
|
|
150
|
+
if (!KEEP) {
|
|
151
|
+
hr("Option A+ archive-and-delete");
|
|
152
|
+
for (const m of TEAM) { await archiveAndDelete(sessions[m.name].id); }
|
|
153
|
+
log(`archived to ${ARCHIVE_DIR}, raw JSONL removed from ~/.claude/projects`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
hr(`RESULT: ${done ? "CONVERGED with leader DONE" : "capped"} | ${channel.length} messages | member<->member exchange demonstrated`);
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// Feasibility spike for the native PPM group-chat engine.
|
|
2
|
+
// Throwaway diagnostic — NOT production code. Mirrors test-tool.mjs (direct provider, no DB/UI).
|
|
3
|
+
//
|
|
4
|
+
// Proves, headless & real (no mocks):
|
|
5
|
+
// 1. Parallel multi-agent: 1 leader + N member sessions on the SAME project cwd.
|
|
6
|
+
// 2. Leader-driven task split -> dispatch to members -> collect (the orchestration loop).
|
|
7
|
+
// 3. Summary-vs-full (#2): capture short summary for the feed + full text kept aside.
|
|
8
|
+
// 4. Option A+ (#3): archive each member JSONL to ~/.ppm/teams/<group>/transcripts/,
|
|
9
|
+
// then delete the raw JSONL from ~/.claude/projects so CLI/VSCode stay clean.
|
|
10
|
+
// 5. Synthesis: feed member summaries back to the leader for a final group answer.
|
|
11
|
+
//
|
|
12
|
+
// Usage: bun spike-group-chat.mjs [projectPath] [--keep]
|
|
13
|
+
// --keep : skip the archive+delete step (leave raw JSONLs in place)
|
|
14
|
+
|
|
15
|
+
import { homedir, tmpdir } from "node:os";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { readdir, mkdir, copyFile, rm, stat } from "node:fs/promises";
|
|
18
|
+
import { ClaudeAgentSdkProvider } from "./src/providers/claude-agent-sdk.ts";
|
|
19
|
+
import { configService } from "./src/services/config.service.ts";
|
|
20
|
+
|
|
21
|
+
configService.load();
|
|
22
|
+
delete process.env.CLAUDECODE; // avoid nested-session error
|
|
23
|
+
|
|
24
|
+
const projectPath = process.argv.find((a, i) => i >= 2 && !a.startsWith("--")) || process.cwd();
|
|
25
|
+
const KEEP = process.argv.includes("--keep");
|
|
26
|
+
const GROUP = "spike";
|
|
27
|
+
const CLAUDE_PROJECTS = join(homedir(), ".claude", "projects");
|
|
28
|
+
const ARCHIVE_DIR = join(homedir(), ".ppm", "teams", GROUP, "transcripts");
|
|
29
|
+
const TIMEOUT_MS = 180_000;
|
|
30
|
+
|
|
31
|
+
const provider = new ClaudeAgentSdkProvider();
|
|
32
|
+
const opts = { permissionMode: "bypassPermissions" };
|
|
33
|
+
const results = {}; // criterion -> boolean
|
|
34
|
+
|
|
35
|
+
// The user's "task" given to the group.
|
|
36
|
+
const TASK =
|
|
37
|
+
"Working from the CLAUDE.md in this project, report two facts: (a) the runtime used, " +
|
|
38
|
+
"(b) the command to run tests.";
|
|
39
|
+
|
|
40
|
+
function log(...a) { console.log(...a); }
|
|
41
|
+
function hr(t) { log("\n" + "=".repeat(64) + "\n" + t + "\n" + "=".repeat(64)); }
|
|
42
|
+
|
|
43
|
+
// Run one prompt on a session, capture summary (last assistant text) + full text.
|
|
44
|
+
async function run(sessionId, prompt) {
|
|
45
|
+
const abort = new AbortController();
|
|
46
|
+
const timer = setTimeout(() => abort.abort(), TIMEOUT_MS);
|
|
47
|
+
let full = "", last = "", error = null;
|
|
48
|
+
try {
|
|
49
|
+
for await (const ev of provider.sendMessage(sessionId, prompt, { ...opts, signal: abort.signal })) {
|
|
50
|
+
if (abort.signal.aborted) break;
|
|
51
|
+
if (ev.type === "text") { last = ev.content ?? ""; full += ev.content ?? ""; }
|
|
52
|
+
else if (ev.type === "error") { error = ev.message; }
|
|
53
|
+
else if (ev.type === "done") break;
|
|
54
|
+
}
|
|
55
|
+
} catch (e) { error = e instanceof Error ? e.message : String(e); }
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
return { summary: (last || full).trim().slice(0, 400), full: full.trim(), error };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Locate <sessionId>.jsonl anywhere under ~/.claude/projects (avoids slug guessing).
|
|
61
|
+
async function findJsonl(sessionId) {
|
|
62
|
+
let dirs = [];
|
|
63
|
+
try { dirs = await readdir(CLAUDE_PROJECTS); } catch { return null; }
|
|
64
|
+
for (const d of dirs) {
|
|
65
|
+
const p = join(CLAUDE_PROJECTS, d, `${sessionId}.jsonl`);
|
|
66
|
+
try { await stat(p); return p; } catch { /* keep looking */ }
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Option A+: archive JSONL to PPM store, then delete the raw file.
|
|
72
|
+
async function archiveAndDelete(sessionId) {
|
|
73
|
+
const src = await findJsonl(sessionId);
|
|
74
|
+
if (!src) return { archived: false, deleted: false, reason: "raw JSONL not found" };
|
|
75
|
+
await mkdir(ARCHIVE_DIR, { recursive: true });
|
|
76
|
+
const dest = join(ARCHIVE_DIR, `${sessionId}.jsonl`);
|
|
77
|
+
await copyFile(src, dest);
|
|
78
|
+
const archived = await stat(dest).then(() => true).catch(() => false);
|
|
79
|
+
await rm(src, { force: true });
|
|
80
|
+
const stillThere = await stat(src).then(() => true).catch(() => false);
|
|
81
|
+
return { archived, deleted: !stillThere, dest };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
hr(`SPIKE: native group-chat engine | project=${projectPath} | keep=${KEEP}`);
|
|
86
|
+
|
|
87
|
+
// --- Criterion 1 + 2: leader session decides the work split -----------------
|
|
88
|
+
hr("STEP 1 — Leader splits the task");
|
|
89
|
+
const leader = await provider.createSession({ title: "spike-leader", projectPath });
|
|
90
|
+
log(`leader session: ${leader.id}`);
|
|
91
|
+
|
|
92
|
+
const splitPrompt =
|
|
93
|
+
`You are the LEADER of an agent team on this project. User task:\n"${TASK}"\n\n` +
|
|
94
|
+
`Split it into EXACTLY 2 independent subtasks. Reply with ONLY two lines, no preamble:\n` +
|
|
95
|
+
`M1: <subtask one>\nM2: <subtask two>`;
|
|
96
|
+
const split = await run(leader.id, splitPrompt);
|
|
97
|
+
log("leader raw:\n" + split.full);
|
|
98
|
+
|
|
99
|
+
let subtasks = split.full
|
|
100
|
+
.split("\n")
|
|
101
|
+
.map((l) => l.replace(/^M\d+:\s*/i, "").trim())
|
|
102
|
+
.filter((l) => l && /subtask|report|find|read|runtime|test|command|CLAUDE/i.test(l))
|
|
103
|
+
.slice(0, 2);
|
|
104
|
+
if (subtasks.length < 2) {
|
|
105
|
+
log("!! parse fallback — leader output not in expected format, using default split");
|
|
106
|
+
subtasks = [
|
|
107
|
+
"Read CLAUDE.md and report ONLY the runtime used. One sentence.",
|
|
108
|
+
"Read CLAUDE.md and report ONLY the command to run tests. One sentence.",
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
results["1_leader_split"] = subtasks.length === 2;
|
|
112
|
+
log("subtasks:", subtasks);
|
|
113
|
+
|
|
114
|
+
// --- Criterion 1 (parallel) + 3 (summary/full): members work concurrently ---
|
|
115
|
+
hr("STEP 2 — Members work in parallel (own sessions)");
|
|
116
|
+
const members = await Promise.all(
|
|
117
|
+
subtasks.map((_, i) => provider.createSession({ title: `spike-m${i + 1}`, projectPath })),
|
|
118
|
+
);
|
|
119
|
+
members.forEach((m, i) => log(`member${i + 1} session: ${m.id}`));
|
|
120
|
+
|
|
121
|
+
const memberRuns = await Promise.all(
|
|
122
|
+
subtasks.map((st, i) =>
|
|
123
|
+
run(members[i].id, `${st}\n\nReply with a 1-2 sentence summary only.`),
|
|
124
|
+
),
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
results["2_parallel_members"] = memberRuns.every((r) => !r.error);
|
|
128
|
+
results["3_summary_vs_full"] = memberRuns.every((r) => r.summary.length > 0 && r.full.length >= r.summary.length);
|
|
129
|
+
memberRuns.forEach((r, i) => {
|
|
130
|
+
log(`\n--- member${i + 1} ---`);
|
|
131
|
+
if (r.error) log(` ERROR: ${r.error}`);
|
|
132
|
+
log(` FEED (summary): ${r.summary}`);
|
|
133
|
+
log(` FULL kept aside: ${r.full.length} chars (hidden from feed)`);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// --- Criterion 4: Option A+ archive-and-delete ------------------------------
|
|
137
|
+
hr("STEP 3 — Option A+ archive-and-delete member transcripts");
|
|
138
|
+
let aPlusOk = true;
|
|
139
|
+
if (KEEP) {
|
|
140
|
+
log("(--keep) skipping archive/delete");
|
|
141
|
+
aPlusOk = false;
|
|
142
|
+
} else {
|
|
143
|
+
for (const m of members) {
|
|
144
|
+
const res = await archiveAndDelete(m.id);
|
|
145
|
+
log(`member ${m.id}: archived=${res.archived} deleted=${res.deleted}` + (res.reason ? ` (${res.reason})` : ""));
|
|
146
|
+
if (!res.archived || !res.deleted) aPlusOk = false;
|
|
147
|
+
}
|
|
148
|
+
log(`archive dir: ${ARCHIVE_DIR}`);
|
|
149
|
+
}
|
|
150
|
+
results["4_archive_delete"] = aPlusOk;
|
|
151
|
+
|
|
152
|
+
// --- Criterion 5: leader synthesizes member summaries -----------------------
|
|
153
|
+
hr("STEP 4 — Leader synthesizes final group answer");
|
|
154
|
+
const synthPrompt =
|
|
155
|
+
`Your members reported:\n` +
|
|
156
|
+
memberRuns.map((r, i) => `- member${i + 1}: ${r.summary}`).join("\n") +
|
|
157
|
+
`\n\nSynthesize a short final answer to the user's task.`;
|
|
158
|
+
const synth = await run(leader.id, synthPrompt);
|
|
159
|
+
log("FINAL group answer:\n" + synth.summary);
|
|
160
|
+
results["5_synthesis"] = !synth.error && synth.summary.length > 0;
|
|
161
|
+
|
|
162
|
+
// Clean up leader too (it created a JSONL).
|
|
163
|
+
if (!KEEP) { await archiveAndDelete(leader.id).catch(() => {}); }
|
|
164
|
+
|
|
165
|
+
// --- Verdict ----------------------------------------------------------------
|
|
166
|
+
hr("VERDICT");
|
|
167
|
+
const labels = {
|
|
168
|
+
"1_leader_split": "Leader splits task into subtasks",
|
|
169
|
+
"2_parallel_members": "Members run in parallel (own sessions)",
|
|
170
|
+
"3_summary_vs_full": "Summary (feed) vs full (hidden) captured",
|
|
171
|
+
"4_archive_delete": "Option A+ archive-and-delete works",
|
|
172
|
+
"5_synthesis": "Leader synthesizes final answer",
|
|
173
|
+
};
|
|
174
|
+
let allPass = true;
|
|
175
|
+
for (const [k, label] of Object.entries(labels)) {
|
|
176
|
+
const ok = results[k];
|
|
177
|
+
if (!ok && !(k === "4_archive_delete" && KEEP)) allPass = false;
|
|
178
|
+
log(` ${ok ? "PASS" : (k === "4_archive_delete" && KEEP ? "SKIP" : "FAIL")} ${label}`);
|
|
179
|
+
}
|
|
180
|
+
hr(allPass ? "FEASIBLE — core engine works end-to-end" : "NEEDS ATTENTION — see failures above");
|
|
181
|
+
process.exit(allPass ? 0 : 1);
|
|
@@ -6,15 +6,22 @@ import {
|
|
|
6
6
|
listGroups,
|
|
7
7
|
deleteGroup,
|
|
8
8
|
addMember,
|
|
9
|
+
getMember,
|
|
10
|
+
updateMember,
|
|
11
|
+
removeMember,
|
|
9
12
|
listMembers,
|
|
10
13
|
readMessages,
|
|
14
|
+
setGroupMaxTurns,
|
|
11
15
|
} from "../../services/group-chat/group-chat.store.ts";
|
|
12
16
|
import { groupChatService } from "../../services/group-chat/group-chat.service.ts";
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
17
|
+
import { resolveTranscriptPath } from "../../services/group-chat/transcript-archive.ts";
|
|
18
|
+
import { parseJsonlTranscript, parseTranscriptConfig } from "../../services/jsonl-transcript-parser.ts";
|
|
19
|
+
import type { AddMemberInput, UpdateMemberInput } from "../../types/group-chat.ts";
|
|
15
20
|
|
|
16
21
|
/** Allowlist: group ids are UUIDs — alphanumeric + hyphens only. */
|
|
17
22
|
const VALID_GROUP_ID = /^[a-zA-Z0-9-]+$/;
|
|
23
|
+
/** Member ids are UUIDs too. */
|
|
24
|
+
const VALID_MEMBER_ID = /^[a-zA-Z0-9-]+$/;
|
|
18
25
|
/** Session refs are Claude session UUIDs. */
|
|
19
26
|
const VALID_SESSION_REF = /^[a-zA-Z0-9-]+$/;
|
|
20
27
|
|
|
@@ -79,6 +86,101 @@ groupChatRoutes.get("/:id", (c) => {
|
|
|
79
86
|
return c.json(ok({ ...group, members: listMembers(id) }));
|
|
80
87
|
});
|
|
81
88
|
|
|
89
|
+
// Group settings (reply-burst cap) -----------------------------------------
|
|
90
|
+
groupChatRoutes.patch("/:id", async (c) => {
|
|
91
|
+
const id = c.req.param("id");
|
|
92
|
+
if (!VALID_GROUP_ID.test(id)) return c.json(err("Invalid group id"), 400);
|
|
93
|
+
if (!getGroup(id)) return c.json(err("Group not found"), 404);
|
|
94
|
+
let body: { maxTurns?: number };
|
|
95
|
+
try { body = await c.req.json(); } catch { return c.json(err("Invalid JSON body"), 400); }
|
|
96
|
+
if (body.maxTurns !== undefined) {
|
|
97
|
+
const n = Math.floor(Number(body.maxTurns));
|
|
98
|
+
if (!Number.isFinite(n) || n < 1 || n > 50) return c.json(err("maxTurns must be 1–50"), 400);
|
|
99
|
+
setGroupMaxTurns(id, n);
|
|
100
|
+
}
|
|
101
|
+
return c.json(ok({ ...getGroup(id)!, members: listMembers(id) }));
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Member management (add / update / remove) -------------------------------
|
|
105
|
+
// Invariant: a group always has exactly one leader and at least one member.
|
|
106
|
+
|
|
107
|
+
groupChatRoutes.post("/:id/members", async (c) => {
|
|
108
|
+
const id = c.req.param("id");
|
|
109
|
+
if (!VALID_GROUP_ID.test(id)) return c.json(err("Invalid group id"), 400);
|
|
110
|
+
if (!getGroup(id)) return c.json(err("Group not found"), 404);
|
|
111
|
+
|
|
112
|
+
let body: { role?: string; name?: string; persona?: string; model?: string; color?: string };
|
|
113
|
+
try { body = await c.req.json(); } catch { return c.json(err("Invalid JSON body"), 400); }
|
|
114
|
+
const name = body.name?.trim();
|
|
115
|
+
if (!name) return c.json(err("member name is required"), 400);
|
|
116
|
+
const role = body.role === "leader" ? "leader" : "member";
|
|
117
|
+
|
|
118
|
+
// Promoting a new leader demotes the current one (keep exactly one leader).
|
|
119
|
+
if (role === "leader") {
|
|
120
|
+
for (const m of listMembers(id)) {
|
|
121
|
+
if (m.role === "leader") updateMember(m.id, { role: "member" });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const input: AddMemberInput = {
|
|
125
|
+
groupId: id, role, name,
|
|
126
|
+
persona: body.persona ?? null, model: body.model ?? null, color: body.color ?? null,
|
|
127
|
+
};
|
|
128
|
+
return c.json(ok(addMember(input)));
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
groupChatRoutes.patch("/:id/members/:memberId", async (c) => {
|
|
132
|
+
const id = c.req.param("id");
|
|
133
|
+
const memberId = c.req.param("memberId");
|
|
134
|
+
if (!VALID_GROUP_ID.test(id) || !VALID_MEMBER_ID.test(memberId)) return c.json(err("Invalid id"), 400);
|
|
135
|
+
if (!getGroup(id)) return c.json(err("Group not found"), 404);
|
|
136
|
+
const member = getMember(memberId);
|
|
137
|
+
if (!member || member.groupId !== id) return c.json(err("Member not found"), 404);
|
|
138
|
+
|
|
139
|
+
let body: { role?: string; name?: string; persona?: string; model?: string; color?: string };
|
|
140
|
+
try { body = await c.req.json(); } catch { return c.json(err("Invalid JSON body"), 400); }
|
|
141
|
+
|
|
142
|
+
const patch: UpdateMemberInput = {};
|
|
143
|
+
if (body.name !== undefined) {
|
|
144
|
+
const n = body.name.trim();
|
|
145
|
+
if (!n) return c.json(err("member name cannot be empty"), 400);
|
|
146
|
+
patch.name = n;
|
|
147
|
+
}
|
|
148
|
+
if (body.persona !== undefined) patch.persona = body.persona || null;
|
|
149
|
+
if (body.model !== undefined) patch.model = body.model || null;
|
|
150
|
+
if (body.color !== undefined) patch.color = body.color || null;
|
|
151
|
+
|
|
152
|
+
if (body.role !== undefined) {
|
|
153
|
+
if (body.role !== "leader" && body.role !== "member") return c.json(err("invalid role"), 400);
|
|
154
|
+
if (body.role === "leader") {
|
|
155
|
+
// Demote the current leader(s) before promoting this member.
|
|
156
|
+
for (const m of listMembers(id)) {
|
|
157
|
+
if (m.role === "leader" && m.id !== memberId) updateMember(m.id, { role: "member" });
|
|
158
|
+
}
|
|
159
|
+
patch.role = "leader";
|
|
160
|
+
} else if (member.role === "leader") {
|
|
161
|
+
return c.json(err("promote another member to leader before demoting this one"), 400);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return c.json(ok(updateMember(memberId, patch)));
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
groupChatRoutes.delete("/:id/members/:memberId", async (c) => {
|
|
168
|
+
const id = c.req.param("id");
|
|
169
|
+
const memberId = c.req.param("memberId");
|
|
170
|
+
if (!VALID_GROUP_ID.test(id) || !VALID_MEMBER_ID.test(memberId)) return c.json(err("Invalid id"), 400);
|
|
171
|
+
const group = getGroup(id);
|
|
172
|
+
if (!group) return c.json(err("Group not found"), 404);
|
|
173
|
+
const member = getMember(memberId);
|
|
174
|
+
if (!member || member.groupId !== id) return c.json(err("Member not found"), 404);
|
|
175
|
+
|
|
176
|
+
const members = listMembers(id);
|
|
177
|
+
if (members.length <= 1) return c.json(err("a group needs at least one member"), 400);
|
|
178
|
+
if (member.role === "leader") return c.json(err("reassign the leader before removing this member"), 400);
|
|
179
|
+
await groupChatService.archiveMemberSession(group.name, member.sessionId);
|
|
180
|
+
removeMember(memberId);
|
|
181
|
+
return c.json(ok({ deleted: memberId }));
|
|
182
|
+
});
|
|
183
|
+
|
|
82
184
|
// Feed (windowed/paginated) ------------------------------------------------
|
|
83
185
|
groupChatRoutes.get("/:id/feed", (c) => {
|
|
84
186
|
const id = c.req.param("id");
|
|
@@ -93,8 +195,9 @@ groupChatRoutes.get("/:id/feed", (c) => {
|
|
|
93
195
|
return c.json(ok({ messages }));
|
|
94
196
|
});
|
|
95
197
|
|
|
96
|
-
// Archived transcript for a member session (powers "view full")
|
|
97
|
-
|
|
198
|
+
// Archived transcript for a member session (powers "view full") — parsed into
|
|
199
|
+
// chat-style messages (text/thinking/tool_use/tool_result) + input config.
|
|
200
|
+
groupChatRoutes.get("/:id/transcript", async (c) => {
|
|
98
201
|
const id = c.req.param("id");
|
|
99
202
|
if (!VALID_GROUP_ID.test(id)) return c.json(err("Invalid group id"), 400);
|
|
100
203
|
const group = getGroup(id);
|
|
@@ -104,9 +207,13 @@ groupChatRoutes.get("/:id/transcript", (c) => {
|
|
|
104
207
|
if (!sessionRef || !VALID_SESSION_REF.test(sessionRef)) {
|
|
105
208
|
return c.json(err("Invalid sessionRef"), 400);
|
|
106
209
|
}
|
|
107
|
-
const
|
|
108
|
-
if (
|
|
109
|
-
|
|
210
|
+
const path = await resolveTranscriptPath(sessionRef, group.name);
|
|
211
|
+
if (path === null) return c.json(err("Transcript not found"), 404);
|
|
212
|
+
const [messages, config] = await Promise.all([
|
|
213
|
+
parseJsonlTranscript(path),
|
|
214
|
+
parseTranscriptConfig(path),
|
|
215
|
+
]);
|
|
216
|
+
return c.json(ok({ messages, config }));
|
|
110
217
|
});
|
|
111
218
|
|
|
112
219
|
// Send a message → starts / feeds the engine ------------------------------
|
|
@@ -150,11 +257,13 @@ groupChatRoutes.post("/:id/resume", async (c) => {
|
|
|
150
257
|
});
|
|
151
258
|
|
|
152
259
|
// Delete -------------------------------------------------------------------
|
|
153
|
-
groupChatRoutes.delete("/:id", (c) => {
|
|
260
|
+
groupChatRoutes.delete("/:id", async (c) => {
|
|
154
261
|
const id = c.req.param("id");
|
|
155
262
|
if (!VALID_GROUP_ID.test(id)) return c.json(err("Invalid group id"), 400);
|
|
156
263
|
if (!getGroup(id)) return c.json(err("Group not found"), 404);
|
|
157
|
-
|
|
264
|
+
// Archive member sessions (keep-alive means they live until now) BEFORE the store
|
|
265
|
+
// cascade removes the member rows.
|
|
266
|
+
await groupChatService.archiveAndForget(id);
|
|
158
267
|
deleteGroup(id);
|
|
159
268
|
return c.json(ok({ deleted: id }));
|
|
160
269
|
});
|
|
@@ -10,8 +10,8 @@ export interface ChatBackend {
|
|
|
10
10
|
providerId: string,
|
|
11
11
|
sessionId: string,
|
|
12
12
|
prompt: string,
|
|
13
|
-
opts?: { permissionMode?: string; signal?: AbortSignal },
|
|
14
|
-
): AsyncIterable<{ type: string; content?: string; costUsd?: number; usage?: { costUsd?: number } }>;
|
|
13
|
+
opts?: { permissionMode?: string; signal?: AbortSignal; model?: string; oneMContext?: boolean },
|
|
14
|
+
): AsyncIterable<{ type: string; content?: string; message?: string; costUsd?: number; usage?: { costUsd?: number } }>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface AgentRunResult {
|
|
@@ -38,12 +38,25 @@ export async function runAgentTurn(
|
|
|
38
38
|
|
|
39
39
|
const events = backend.sendMessage(providerId, member.sessionId, prompt, {
|
|
40
40
|
permissionMode: "bypassPermissions",
|
|
41
|
+
// Honor the member's configured model (e.g. haiku); falls back to the provider
|
|
42
|
+
// default when unset. Without this the turn always used the provider default.
|
|
43
|
+
model: member.model ?? undefined,
|
|
44
|
+
// Group turns are short/windowed — never request the 1M-context beta. If the user's
|
|
45
|
+
// config has context_1m on, the [1m] model suffix triggers "long context beta not
|
|
46
|
+
// available for this subscription" (HTTP 400). Opt out here (like the router).
|
|
47
|
+
oneMContext: false,
|
|
41
48
|
signal: opts.signal,
|
|
42
49
|
});
|
|
43
50
|
|
|
44
51
|
for await (const ev of events) {
|
|
45
52
|
if (opts.signal?.aborted) break;
|
|
46
53
|
if (ev.type === "text") full += ev.content ?? "";
|
|
54
|
+
else if (ev.type === "error") {
|
|
55
|
+
// Provider errors (auth, rate limit, crash) are terminal for this turn.
|
|
56
|
+
// Throw so the turn loop aborts and surfaces the error to the UI instead
|
|
57
|
+
// of appending an empty message and looping to the turn cap.
|
|
58
|
+
throw new Error(ev.message || `agent turn failed for ${member.name}`);
|
|
59
|
+
}
|
|
47
60
|
else if (ev.type === "done") {
|
|
48
61
|
costUsd = ev.costUsd ?? ev.usage?.costUsd;
|
|
49
62
|
break;
|
|
@@ -41,3 +41,18 @@ export function renderWindow(window: GroupMessage[]): string {
|
|
|
41
41
|
if (window.length === 0) return "(channel empty)";
|
|
42
42
|
return window.map(line).join("\n");
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
/** Full turn text stored on the bus (`data.full`), falling back to the short feed
|
|
46
|
+
* summary for legacy rows that predate full-text storage. */
|
|
47
|
+
export function fullText(m: GroupMessage): string {
|
|
48
|
+
const full = (m.data as { full?: string } | null)?.full;
|
|
49
|
+
return typeof full === "string" && full.length > 0 ? full : (m.summary ?? "");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Render messages using FULL text (not the 600-char feed clip) for prompt injection. */
|
|
53
|
+
export function renderFull(messages: GroupMessage[]): string {
|
|
54
|
+
if (messages.length === 0) return "(channel empty)";
|
|
55
|
+
return messages
|
|
56
|
+
.map((m) => `${m.fromMember} -> ${m.toMember ?? "all"}: ${fullText(m)}`.trim())
|
|
57
|
+
.join("\n");
|
|
58
|
+
}
|