@hienlh/ppm 0.18.1 → 0.18.3
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 +22 -0
- package/CLAUDE.md +1 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +6 -1
- package/dist/web/assets/{ai-resource-editor-Bmk4P0YS.js → ai-resource-editor-3Zk3gYSZ.js} +1 -1
- package/dist/web/assets/{angular-html-C-Kjr43S.js → angular-html-jfMqUuRd.js} +1 -1
- package/dist/web/assets/{angular-ts-CaDDbZqm.js → angular-ts-wytn9PMm.js} +1 -1
- package/dist/web/assets/api-client-CzABTreM.js +1 -0
- package/dist/web/assets/{api-settings-CAhcNpj5.js → api-settings-DfNRPr1q.js} +1 -1
- package/dist/web/assets/api-settings-DlcoR5QT.js +1 -0
- package/dist/web/assets/{api-themes-CAjg_Bt9.js → api-themes-CEyYK7AK.js} +1 -1
- package/dist/web/assets/{apl-B1WsQFAb.js → apl-i-ahKx6O.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-Bs7wzj-W.js +1 -0
- package/dist/web/assets/arrow-right-DubGFkN8.js +1 -0
- package/dist/web/assets/{astro-Bdnz7nVp.js → astro-DVBCJfG6.js} +1 -1
- package/dist/web/assets/audio-preview-DG2Tw0cO.js +1 -0
- package/dist/web/assets/{blade-B2euh8sS.js → blade-BHlL8SqU.js} +1 -1
- package/dist/web/assets/{bsl-GNeMaxd0.js → bsl-D-UOfR1F.js} +1 -1
- package/dist/web/assets/button-B4MWPjWj.js +1 -0
- package/dist/web/assets/{cairo-D7G0W7-s.js → cairo-Bn6rucli.js} +1 -1
- package/dist/web/assets/chat-tab-DvbbVMBi.js +15 -0
- package/dist/web/assets/{cobol-Q6YgysnI.js → cobol-Byn9FYKu.js} +1 -1
- package/dist/web/assets/code-editor-BKg7Li-L.js +10 -0
- package/dist/web/assets/{coffee-BjufWxVc.js → coffee-DjBl4gm-.js} +1 -1
- package/dist/web/assets/{conflict-editor-DC3liBm_.js → conflict-editor-CJNtovCh.js} +3 -3
- package/dist/web/assets/{context-menu-q-RHHAWz.js → context-menu-DkQdt6YA.js} +1 -1
- package/dist/web/assets/{cpp-CqWU0gCR.js → cpp-CKzic-3E.js} +1 -1
- package/dist/web/assets/{crystal-ylayVajF.js → crystal-Bkg-Ly_g.js} +1 -1
- package/dist/web/assets/{csv-preview-BhCOjgq1.js → csv-preview-BR6gCSZJ.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-BzPfsCfd.js → data-grid-overlay-editor-B1mTl3KS.js} +1 -1
- package/dist/web/assets/{database-viewer-Z6uLyZVO.js → database-viewer-DzuwuFSr.js} +1 -1
- package/dist/web/assets/diff-viewer-DL3_tISz.js +4 -0
- package/dist/web/assets/{docx-preview-C_fSjfy_.js → docx-preview-BzgyssBV.js} +1 -1
- package/dist/web/assets/download-D9UYwY0-.js +1 -0
- package/dist/web/assets/{edge-DX4NxQfh.js → edge-DVbZnd3Y.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-DfX-9om9.js → edit-diff-preview-HTZPC9VP.js} +1 -1
- package/dist/web/assets/{elixir-CSh3NjbV.js → elixir-Dwi8Wu7W.js} +1 -1
- package/dist/web/assets/{elm-DBzwFYq9.js → elm-DtIv-HXJ.js} +1 -1
- package/dist/web/assets/{erb-yxVOb8aB.js → erb-D3HEDz1x.js} +1 -1
- package/dist/web/assets/{erlang-5XIDkYrM.js → erlang-2MjTCzGz.js} +1 -1
- package/dist/web/assets/{esm-DO4el2OJ.js → esm-CZ8B8Ba2.js} +1 -1
- package/dist/web/assets/explorer-body-CrrY1HbH.js +2 -0
- package/dist/web/assets/explorer-window-content-CvQPeiwU.js +1 -0
- package/dist/web/assets/{extension-webview-ePIM2fwM.js → extension-webview-DH1PfQF2.js} +1 -1
- package/dist/web/assets/{fortran-fixed-form-D4tE5VWY.js → fortran-fixed-form-BLyAtyPM.js} +1 -1
- package/dist/web/assets/{fsharp-By8soj6-.js → fsharp-Bxbn_gbr.js} +1 -1
- package/dist/web/assets/{gdresource-DoSwM7Hv.js → gdresource-sFMY4D2Q.js} +1 -1
- package/dist/web/assets/{git-commit-_ZiciHIx.js → git-commit-BzB9Lio5.js} +1 -1
- package/dist/web/assets/{git-log-panel-BRWmTzX1.js → git-log-panel-gUm4E3wo.js} +1 -1
- package/dist/web/assets/{git-rebase-C3Y5N9-s.js → git-rebase-CKSVd848.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-D7i54kbM.js +1 -0
- package/dist/web/assets/glide-data-grid-D8J5lwUP.js +138 -0
- package/dist/web/assets/{glimmer-js-BPBTXVlC.js → glimmer-js-BY8aExAJ.js} +1 -1
- package/dist/web/assets/{glimmer-ts-BQSZdy_D.js → glimmer-ts-Bak54dBX.js} +1 -1
- package/dist/web/assets/{glsl-CbQdxpU-.js → glsl-nR2eaJQe.js} +1 -1
- package/dist/web/assets/{graphql-GMlKikpY.js → graphql-CGPPFAU6.js} +1 -1
- package/dist/web/assets/group-chat-tab-DihiQPSi.js +1 -0
- package/dist/web/assets/{hack-DyshcLec.js → hack-CXIMX-Ol.js} +1 -1
- package/dist/web/assets/{haml-rqCqWzsq.js → haml-tPY-9Pfm.js} +1 -1
- package/dist/web/assets/{handlebars-BCKwSWjR.js → handlebars-BuW1LT7T.js} +1 -1
- package/dist/web/assets/{html-Cg29xPR1.js → html-bgVcwZ-t.js} +1 -1
- package/dist/web/assets/{html-derivative-geltIVg8.js → html-derivative-D6-IxTgn.js} +1 -1
- package/dist/web/assets/{http-pG7Vp237.js → http-CJ1zyB-h.js} +1 -1
- package/dist/web/assets/{hurl-Di3Uu_Mc.js → hurl-CmoT7l3T.js} +1 -1
- package/dist/web/assets/{hxml-CRy4lbv8.js → hxml-CztOsL8o.js} +1 -1
- package/dist/web/assets/{image-preview-CP82lor8.js → image-preview-DOQBNgwl.js} +1 -1
- package/dist/web/assets/index-BtncTUyM.js +52 -0
- package/dist/web/assets/index-Bucbpby-.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-BV41AzR9.js +1 -0
- package/dist/web/assets/{jinja-C8GyVnvd.js → jinja-B1pq3jJq.js} +1 -1
- package/dist/web/assets/{jison-BywnqPn6.js → jison-D8B5pCwA.js} +1 -1
- package/dist/web/assets/{julia-DTrO3T3B.js → julia-D0K3bwpU.js} +1 -1
- package/dist/web/assets/{just-CA3KSHPi.js → just-B9Jlddu-.js} +1 -1
- package/dist/web/assets/keybindings-store-AynYQVnV.js +1 -0
- package/dist/web/assets/{latex-BC5xUMpc.js → latex-BPJSSE6j.js} +1 -1
- package/dist/web/assets/{liquid-Chd8tSyQ.js → liquid-lv10fo4U.js} +1 -1
- package/dist/web/assets/{lua-DHaEtwLv.js → lua-PNuaIBEF.js} +1 -1
- package/dist/web/assets/markdown-renderer-BBlGpszb.js +1 -0
- package/dist/web/assets/{markdown-renderer-DDgl5zDc.js → markdown-renderer-CVGub2iS.js} +3 -3
- package/dist/web/assets/{marko-Desx_bC-.js → marko-Du3frD6X.js} +1 -1
- package/dist/web/assets/{mdc-DahWHc1t.js → mdc-BeDVcFRl.js} +1 -1
- package/dist/web/assets/media-url-C5vA0ha9.js +1 -0
- package/dist/web/assets/{mobile-bottom-sheet-BQt45q9T.js → mobile-bottom-sheet-CS3XMwFw.js} +1 -1
- package/dist/web/assets/mobile-explorer-sheet-CSgc5JOk.js +1 -0
- package/dist/web/assets/{nextflow-3A7lutCA.js → nextflow-DkcXP71s.js} +1 -1
- package/dist/web/assets/{nginx-XQda6Hdy.js → nginx-C5n8N_bt.js} +1 -1
- package/dist/web/assets/{nim-DHqlpwP1.js → nim-CIhyfs-A.js} +1 -1
- package/dist/web/assets/notification-store-1ksB0YwR.js +1 -0
- package/dist/web/assets/{number-overlay-editor-DgZtViPO.js → number-overlay-editor-NgOsWJ7x.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-CaJoP44m.js +1 -0
- package/dist/web/assets/{panel-store-s6Qx49RK.js → panel-store-DCD82zc1.js} +1 -1
- package/dist/web/assets/{pdf-preview-BXDOe7bG.js → pdf-preview-DSAkWbxY.js} +1 -1
- package/dist/web/assets/{perl-M-ncjACb.js → perl-Cf31sZYE.js} +1 -1
- package/dist/web/assets/{php-CKIajrZi.js → php-Dzl_MDIW.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-DSGZmNw2.js +1 -0
- package/dist/web/assets/plus-DmjC2iRB.js +1 -0
- package/dist/web/assets/{postgres-viewer-DkHYV33h.js → postgres-viewer-DOiM_5Nv.js} +3 -3
- package/dist/web/assets/{project-store-DyaEpHVG.js → project-store-B8BkHXy5.js} +1 -1
- package/dist/web/assets/{pug-DO0u_gO4.js → pug-CxSYHrB3.js} +1 -1
- package/dist/web/assets/{qml-UEje1PAA.js → qml-DlEjGhwN.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-Be4VUTs0.js +1 -0
- package/dist/web/assets/{razor-lCs5T1Ib.js → razor-KVt5uW14.js} +1 -1
- package/dist/web/assets/resolve-theme-CJvkL8hU.js +1 -0
- package/dist/web/assets/{rst-CZX_O0z4.js → rst-D5BwNTnw.js} +1 -1
- package/dist/web/assets/{ruby-idycVAyE.js → ruby-D5fejQwd.js} +1 -1
- package/dist/web/assets/run-in-terminal-B8TDtaM_.js +1 -0
- package/dist/web/assets/{sas-o5gTfUwp.js → sas-Bj7B1CB2.js} +1 -1
- package/dist/web/assets/{scss-CRTk3iBQ.js → scss-BB0CUoCL.js} +1 -1
- package/dist/web/assets/send-to-chat-CuBAVC8l.js +1 -0
- package/dist/web/assets/{settings-store-ChqHdT2V.js → settings-store-CY-4_U3H.js} +2 -2
- package/dist/web/assets/settings-tab-D_oruJB9.js +1 -0
- package/dist/web/assets/{shaderlab-3e5ln8ci.js → shaderlab-BdjEZUMc.js} +1 -1
- package/dist/web/assets/{shellsession-CGQjQ75I.js → shellsession-Bp1OA1rR.js} +1 -1
- package/dist/web/assets/{soy-CxY0VwX2.js → soy-DlYz3wsC.js} +1 -1
- package/dist/web/assets/{sparql-CBAGAFuq.js → sparql-CdfII5Jd.js} +1 -1
- package/dist/web/assets/sql-query-editor-PWpuw-O5.js +1 -0
- package/dist/web/assets/{sqlite-viewer-Cpq06-nz.js → sqlite-viewer-1S6cwVWa.js} +1 -1
- package/dist/web/assets/{stata-BoezhOvk.js → stata-BvUA6GUW.js} +1 -1
- package/dist/web/assets/{surrealql-CHEzAhu7.js → surrealql--DLNbTyI.js} +1 -1
- package/dist/web/assets/{svelte-y6xtu2zX.js → svelte-CBfSsG4n.js} +1 -1
- package/dist/web/assets/system-monitor-tab-U0Jh9-2v.js +1 -0
- package/dist/web/assets/{tab-store-C42sktPo.js → tab-store-DAsvpx4t.js} +1 -1
- package/dist/web/assets/team-member-window-content-DSZL4GIj.js +1 -0
- package/dist/web/assets/{templ-DbG2y5yD.js → templ-Dv8zpKZW.js} +1 -1
- package/dist/web/assets/terminal-tab-uVhX8AGG.js +3 -0
- package/dist/web/assets/{tex-CeKQhrQG.js → tex-CsrOiqh1.js} +1 -1
- package/dist/web/assets/tool-cards-QuTCNfYR.js +8 -0
- package/dist/web/assets/treemap-KZPCXAKY-Cu2zgbxU.js +1 -0
- package/dist/web/assets/{ts-tags-iKKOXJjG.js → ts-tags-3T98k4EJ.js} +1 -1
- package/dist/web/assets/{twig-DK8Vrp-G.js → twig-u6QZ45FH.js} +1 -1
- package/dist/web/assets/{use-blob-url-DYtOHK7u.js → use-blob-url-BmlYYZ8L.js} +1 -1
- package/dist/web/assets/use-is-mobile-B8FA4kQf.js +1 -0
- package/dist/web/assets/use-monaco-theme-DvmINdhI.js +1 -0
- package/dist/web/assets/use-websocket-DoZdQS0G.js +1 -0
- package/dist/web/assets/{vendor-mermaid-C977xNeE.js → vendor-mermaid-Bg4vE8QA.js} +1 -1
- package/dist/web/assets/video-preview-CzU09X0C.js +1 -0
- package/dist/web/assets/{vue-JkIEObMV.js → vue-CxIsxtwn.js} +1 -1
- package/dist/web/assets/{vue-html-D8SqnU86.js → vue-html-BGL5qnuH.js} +1 -1
- package/dist/web/assets/{vue-vine-DJj7N4WD.js → vue-vine-DHPh_gMr.js} +1 -1
- package/dist/web/assets/{xml-C-00w9Rv.js → xml-C-vM2m7J.js} +1 -1
- package/dist/web/assets/{xsl-CVdCwPHV.js → xsl-DvTXNwuO.js} +1 -1
- package/dist/web/index.html +21 -20
- package/dist/web/sw.js +1 -1
- package/docs/codebase-summary.md +1 -0
- package/package.json +1 -1
- package/scripts/dev-quick-tunnel-retry.mjs +51 -0
- package/src/providers/claude-agent-sdk.ts +6 -0
- package/src/server/helpers/media-route-handlers.ts +66 -0
- package/src/server/helpers/range-file-response.ts +86 -0
- package/src/server/index.ts +24 -17
- package/src/server/middleware/auth.ts +3 -2
- package/src/server/routes/files.ts +40 -7
- package/src/server/routes/fs-browse.ts +43 -5
- package/src/server/routes/fs-upload.ts +32 -0
- package/src/server/routes/teams.ts +34 -0
- package/src/server/ws/chat.ts +64 -16
- package/src/server/ws/team-inbox-watcher.ts +61 -22
- package/src/server/ws/terminal.ts +24 -6
- package/src/services/fs-ops/fs-ops-upload.service.ts +120 -0
- package/src/services/media-transcode/ffmpeg-capabilities.ts +89 -0
- package/src/services/media-transcode/media-probe.ts +63 -0
- package/src/services/media-transcode/transcode-stream.ts +129 -0
- package/src/services/subagent-transcript-merger.ts +1 -1
- package/src/services/team-member-activity/member-activity.service.ts +117 -0
- package/src/services/team-member-activity/outbound-message-scanner.ts +121 -0
- package/src/services/team-member-activity/subagent-transcript-index.ts +95 -0
- package/src/services/team-member-activity/transcript-tail-summary.ts +125 -0
- package/src/shared/background-agent-status.ts +79 -0
- package/src/types/api.ts +1 -0
- package/src/types/chat.ts +6 -1
- package/src/web/components/chat/chat-history-bar.tsx +4 -2
- package/src/web/components/chat/chat-tab.tsx +1 -0
- package/src/web/components/chat/message-input.tsx +13 -6
- package/src/web/components/chat/mini-markdown.tsx +17 -0
- package/src/web/components/chat/send-message-card.tsx +134 -0
- package/src/web/components/chat/send-message-parse.ts +159 -0
- package/src/web/components/chat/team-activity-panel.tsx +107 -121
- package/src/web/components/chat/team-member-activity-row.tsx +92 -0
- package/src/web/components/chat/team-member-list.tsx +43 -0
- package/src/web/components/chat/team-member-window-content.tsx +97 -0
- package/src/web/components/chat/team-message-badges.ts +18 -0
- package/src/web/components/chat/team-message-list.tsx +88 -0
- package/src/web/components/chat/team-message-preview.ts +87 -0
- package/src/web/components/chat/tool-cards.tsx +44 -18
- package/src/web/components/editor/audio-preview.tsx +6 -7
- package/src/web/components/editor/video-player/use-video-keyboard-shortcuts.ts +62 -0
- package/src/web/components/editor/video-player/video-player-controls.tsx +103 -0
- package/src/web/components/editor/video-player/video-player.tsx +190 -0
- package/src/web/components/editor/video-player/video-settings-menu.tsx +92 -0
- package/src/web/components/editor/video-player/video-transform.ts +49 -0
- package/src/web/components/editor/video-preview.tsx +75 -14
- package/src/web/components/explorer/file-tree.tsx +6 -0
- package/src/web/components/explorer/tree-node-context-menu.tsx +5 -1
- package/src/web/components/floating-window/window-content-registry.ts +5 -0
- package/src/web/components/floating-window/window-store-types.ts +1 -1
- package/src/web/components/os-explorer/actions/explorer-actions-upload.ts +96 -0
- package/src/web/components/os-explorer/actions/use-explorer-actions.ts +23 -2
- package/src/web/components/os-explorer/actions/use-explorer-upload-actions.tsx +41 -0
- package/src/web/components/os-explorer/dnd/use-drop-transfer.tsx +10 -1
- package/src/web/components/os-explorer/dnd/use-entry-row-dnd.ts +8 -1
- package/src/web/components/os-explorer/dnd/use-external-file-drop.ts +84 -0
- package/src/web/components/os-explorer/dnd/use-path-drop-target.ts +46 -3
- package/src/web/components/os-explorer/explorer-body.tsx +1 -1
- package/src/web/components/os-explorer/explorer-context-menu.tsx +10 -0
- package/src/web/components/os-explorer/explorer-dialogs.tsx +2 -0
- package/src/web/components/os-explorer/explorer-sidebar.tsx +10 -5
- package/src/web/components/os-explorer/explorer-toolbar.tsx +32 -2
- package/src/web/components/os-explorer/mobile/mobile-bottom-toolbar.tsx +5 -1
- package/src/web/components/os-explorer/upload/collect-dropped-entries.ts +81 -0
- package/src/web/components/os-explorer/upload/upload-queue.ts +79 -0
- package/src/web/components/os-explorer/upload/use-upload-picker.tsx +74 -0
- package/src/web/components/os-explorer/views/column-row.tsx +3 -1
- package/src/web/components/os-explorer/views/column-view-column.tsx +6 -1
- package/src/web/components/os-explorer/views/icons-view-tile.tsx +1 -1
- package/src/web/components/os-explorer/views/icons-view.tsx +5 -1
- package/src/web/components/os-explorer/views/list-row.tsx +1 -1
- package/src/web/components/os-explorer/views/list-view.tsx +5 -1
- package/src/web/components/shared/markdown-code-block.tsx +3 -7
- package/src/web/components/terminal/terminal-tab.tsx +19 -25
- package/src/web/hooks/use-chat.ts +77 -15
- package/src/web/hooks/use-team-activity-feed.ts +92 -0
- package/src/web/hooks/use-terminal-command-queue.ts +108 -0
- package/src/web/hooks/use-terminal.ts +45 -3
- package/src/web/lib/fs-api.ts +9 -0
- package/src/web/lib/fs-upload-xhr.ts +62 -0
- package/src/web/lib/media-url.ts +51 -0
- package/src/web/lib/open-terminal-at.ts +22 -0
- package/src/web/lib/run-in-terminal.ts +55 -0
- package/src/web/lib/send-to-chat.ts +118 -0
- package/src/web/lib/ws-auth.ts +13 -0
- package/src/web/lib/ws-client.ts +10 -5
- package/src/web/theme/builtin/aurora.ts +8 -5
- package/.release-run.sh +0 -5
- package/dist/web/assets/api-client-CaRE4HYh.js +0 -1
- package/dist/web/assets/api-settings-DBcXfeJ8.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-B4J2-O8Q.js +0 -1
- package/dist/web/assets/audio-preview-CikvnAOI.js +0 -1
- package/dist/web/assets/chat-tab-B3-KcCn2.js +0 -13
- package/dist/web/assets/code-editor-BpbZw13T.js +0 -10
- package/dist/web/assets/dialog-CkI7rwrh.js +0 -1
- package/dist/web/assets/diff-viewer-CT1ALWt2.js +0 -4
- package/dist/web/assets/explorer-body-CQCyGEet.js +0 -2
- package/dist/web/assets/explorer-window-content-EtyTAZSh.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-CtQ3yXN-.js +0 -1
- package/dist/web/assets/glide-data-grid-DCJCz4XB.js +0 -138
- package/dist/web/assets/group-chat-tab-C3UD2bcm.js +0 -1
- package/dist/web/assets/index-BYetJoXQ.js +0 -52
- package/dist/web/assets/index-D-xwjNyX.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-Cg0mIJn9.js +0 -1
- package/dist/web/assets/keybindings-store-yBWU8ZYT.js +0 -1
- package/dist/web/assets/markdown-renderer-B2D4gdok.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-BtxyynR3.js +0 -1
- package/dist/web/assets/notification-store-DKw_mGED.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-D79vAFR_.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-DYUOH68U.js +0 -1
- package/dist/web/assets/plus-9LatwJMx.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-B1eznNtd.js +0 -1
- package/dist/web/assets/resolve-theme-B0eotaPq.js +0 -1
- package/dist/web/assets/settings-tab-ESL-6MAA.js +0 -1
- package/dist/web/assets/sql-query-editor-CZdZuawP.js +0 -1
- package/dist/web/assets/system-monitor-tab-XR8NXHpv.js +0 -1
- package/dist/web/assets/terminal-tab-CCCB-_50.js +0 -3
- package/dist/web/assets/tool-cards-CsTs5go2.js +0 -7
- package/dist/web/assets/treemap-KZPCXAKY-SeI2TxLs.js +0 -1
- package/dist/web/assets/use-is-mobile-DnFSkUG2.js +0 -1
- package/dist/web/assets/use-monaco-theme-CZh7xTJZ.js +0 -1
- package/dist/web/assets/video-preview-KbRcyuAA.js +0 -1
- package/src/web/components/chat/team-activity-popover.tsx +0 -202
- /package/dist/web/assets/{abap-DrMyiWmK.js → abap-C1K0-wzc.js} +0 -0
- /package/dist/web/assets/{actionscript-3-BlSOyi0y.js → actionscript-3-CJhQVjLA.js} +0 -0
- /package/dist/web/assets/{ada-B_m96icB.js → ada-Bt8r9fME.js} +0 -0
- /package/dist/web/assets/{andromeeda-Ch3vOiZB.js → andromeeda-DF1I8qi3.js} +0 -0
- /package/dist/web/assets/{apache-CdsaXc1n.js → apache-CnlleE6P.js} +0 -0
- /package/dist/web/assets/{apex-0AnsBevk.js → apex-j0C6Xmk6.js} +0 -0
- /package/dist/web/assets/{api-client-rTAGdEKo.js → api-client-BSB14J4w.js} +0 -0
- /package/dist/web/assets/{applescript-CSxLolzy.js → applescript-DO7AnO8U.js} +0 -0
- /package/dist/web/assets/{apply-theme-CMQXnUAa.js → apply-theme-CNj1iA-v.js} +0 -0
- /package/dist/web/assets/{ara-DXZS0jA5.js → ara-i83AydZj.js} +0 -0
- /package/dist/web/assets/{asciidoc-DDy3pH2A.js → asciidoc-DbBA6-sF.js} +0 -0
- /package/dist/web/assets/{asm-Bd17hhqg.js → asm-B5S47Rgr.js} +0 -0
- /package/dist/web/assets/{aurora-x-C62HJRs-.js → aurora-x-De_IaSKw.js} +0 -0
- /package/dist/web/assets/{awk-Cc-nazni.js → awk-CfyLHXqS.js} +0 -0
- /package/dist/web/assets/{ayu-dark-BsfmNWCU.js → ayu-dark-DTLdZ1Si.js} +0 -0
- /package/dist/web/assets/{ayu-light-BZ4HLa4X.js → ayu-light-DTOfkzhu.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-Bhyjyiqr.js → ayu-mirage-DsAECCMv.js} +0 -0
- /package/dist/web/assets/{ballerina-QiWgir3v.js → ballerina-CumGp9A7.js} +0 -0
- /package/dist/web/assets/{bat-DxtlkwN3.js → bat-Ca2SBbYN.js} +0 -0
- /package/dist/web/assets/{beancount-Bt21X7M_.js → beancount-CqyXBwwF.js} +0 -0
- /package/dist/web/assets/{berry-Cksre7lO.js → berry-yl-kJr_H.js} +0 -0
- /package/dist/web/assets/{bibtex-DkakgDlR.js → bibtex-DoFFszjV.js} +0 -0
- /package/dist/web/assets/{bicep-8crmcyXU.js → bicep-CWPi4nfK.js} +0 -0
- /package/dist/web/assets/{bird2-CewQ2I_Z.js → bird2-DXew-ut0.js} +0 -0
- /package/dist/web/assets/{bot-nk1k3ELu.js → bot-CunPuEdW.js} +0 -0
- /package/dist/web/assets/{c-C_6zE8Ha.js → c-clbySDvd.js} +0 -0
- /package/dist/web/assets/{c3-DLWB9-dp.js → c3-B65jvSM1.js} +0 -0
- /package/dist/web/assets/{cadence-D8qYS6pR.js → cadence-Cm8tQTHN.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-BzVXoV-d.js → can-open-in-ppm-Cu-XYIgu.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-Bh95lNRy.js → catppuccin-frappe-DLeGslh_.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-C1PlN3G0.js → catppuccin-latte-CR5GeHws.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-CldtgdK4.js → catppuccin-macchiato-p-XgjxhP.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-BiwqxX9A.js → catppuccin-mocha-B8QOAZLl.js} +0 -0
- /package/dist/web/assets/{clarity-CGiU22jY.js → clarity-DPulbvKH.js} +0 -0
- /package/dist/web/assets/{clojure-COIC3doh.js → clojure-DFuWS20u.js} +0 -0
- /package/dist/web/assets/{cmake-DWUEQfHv.js → cmake-DejCqcu4.js} +0 -0
- /package/dist/web/assets/{codeowners-BNHiAQea.js → codeowners-BwAyqWIH.js} +0 -0
- /package/dist/web/assets/{codeql-BuKaoS0j.js → codeql-DgSwFjqI.js} +0 -0
- /package/dist/web/assets/{common-lisp-D5IKbxsd.js → common-lisp-CxIVJCtf.js} +0 -0
- /package/dist/web/assets/{coq-BMVS-p94.js → coq-DLSjSnmf.js} +0 -0
- /package/dist/web/assets/{csharp-DMlbXbM4.js → csharp-C1HHzXBp.js} +0 -0
- /package/dist/web/assets/{css-CjkJC89X.js → css-VXsMY--y.js} +0 -0
- /package/dist/web/assets/{csv-DoNVBBf0.js → csv-BEbcJdHz.js} +0 -0
- /package/dist/web/assets/{csv-parser-DHvoTjMF.js → csv-parser-r-Nk1oHT.js} +0 -0
- /package/dist/web/assets/{cue-DoTRbBg-.js → cue-BkDnFqUD.js} +0 -0
- /package/dist/web/assets/{cypher-DVsNdTT3.js → cypher-1cMqojSQ.js} +0 -0
- /package/dist/web/assets/{d-EX7BBSrv.js → d-BnYjRXtH.js} +0 -0
- /package/dist/web/assets/{dark-plus-P_YTHwlh.js → dark-plus-XfbaH7kZ.js} +0 -0
- /package/dist/web/assets/{dart-Do-rgU4S.js → dart-Ca7s-8hK.js} +0 -0
- /package/dist/web/assets/{data-grid-types-CUx8cusN.js → data-grid-types-BXwlFMzs.js} +0 -0
- /package/dist/web/assets/{dax-DxOieacu.js → dax-CmuOw-mY.js} +0 -0
- /package/dist/web/assets/{desktop-CvdV7SBf.js → desktop-C2gJ6Ovb.js} +0 -0
- /package/dist/web/assets/{diff-CNOetGen.js → diff-BCEo1Ej7.js} +0 -0
- /package/dist/web/assets/{dist-CMfLpPW_.js → dist-CUPbqNnL.js} +0 -0
- /package/dist/web/assets/{dist-DduBIVkD.js → dist-DOlBnxFX.js} +0 -0
- /package/dist/web/assets/{docker-DAlG4_q-.js → docker-DN2jlyAh.js} +0 -0
- /package/dist/web/assets/{dotenv-Dh3qf6yx.js → dotenv-NExMY2kS.js} +0 -0
- /package/dist/web/assets/{dracula-baAGmJYG.js → dracula-B9lbE01y.js} +0 -0
- /package/dist/web/assets/{dracula-soft-l7ZIyums.js → dracula-soft-CMBBfKF_.js} +0 -0
- /package/dist/web/assets/{dream-maker-DeRjdBn8.js → dream-maker-DEyDwFsd.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-CB05-jQA.js → emacs-lisp-D_qP2zS6.js} +0 -0
- /package/dist/web/assets/{everforest-dark-CT-llQBT.js → everforest-dark-DbHa2U-p.js} +0 -0
- /package/dist/web/assets/{everforest-light-ByPJkTT7.js → everforest-light-BISkJchP.js} +0 -0
- /package/dist/web/assets/{fennel-CeMarbvn.js → fennel-6B22SfJR.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-COAwgNGw.js → file-exclamation-point-a8f3_w7a.js} +0 -0
- /package/dist/web/assets/{fish-BYrt6Xtb.js → fish-CubIIvJD.js} +0 -0
- /package/dist/web/assets/{fluent-Cr5VcAwh.js → fluent-DF55zQ09.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-DQmKtrLa.js → fortran-free-form-DvOu8jAt.js} +0 -0
- /package/dist/web/assets/{gdscript-QTDKjzhY.js → gdscript-DCPxdLpq.js} +0 -0
- /package/dist/web/assets/{gdshader-Chr-5UYt.js → gdshader-CTZ381FO.js} +0 -0
- /package/dist/web/assets/{genie-kWHMWnt0.js → genie-C_QDtvgU.js} +0 -0
- /package/dist/web/assets/{gherkin-DtEBQFUo.js → gherkin-BcvK42tF.js} +0 -0
- /package/dist/web/assets/{github-dark-B5aiUta2.js → github-dark-C9afs_4w.js} +0 -0
- /package/dist/web/assets/{github-dark-default-BkxtsTqR.js → github-dark-default-CKGVrl3Z.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-B9QjR_0K.js → github-dark-dimmed-C3dQZ_LC.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-D6bO-5c0.js → github-dark-high-contrast-DW78QukY.js} +0 -0
- /package/dist/web/assets/{github-light-Cg2ZW_CJ.js → github-light-BnP2dznS.js} +0 -0
- /package/dist/web/assets/{github-light-default-eD7qUVlQ.js → github-light-default-C2fPZzPG.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-CFnlSVjd.js → github-light-high-contrast-BzIuUFR2.js} +0 -0
- /package/dist/web/assets/{gleam-BpYoOqIT.js → gleam-BpeKwEIO.js} +0 -0
- /package/dist/web/assets/{gn-BxwtZPau.js → gn-nUb_Mit0.js} +0 -0
- /package/dist/web/assets/{gnuplot-CRyiZDfl.js → gnuplot-D7I0v20p.js} +0 -0
- /package/dist/web/assets/{go-Dw1Qx94W.js → go-D7Qqska7.js} +0 -0
- /package/dist/web/assets/{groovy-zq_SbWk-.js → groovy-DS-pne5-.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-DbbNy8-Q.js → gruvbox-dark-hard-C0W01fsq.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-BQZ7Kj6C.js → gruvbox-dark-medium-Bqo6fQbg.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-vNavErXi.js → gruvbox-dark-soft-D-XSM_fu.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-AOFbCd7i.js → gruvbox-light-hard-IVAwMJRl.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-DqtxND6H.js → gruvbox-light-medium-38ATiG7i.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-Cg0basu6.js → gruvbox-light-soft-DnZr3c_0.js} +0 -0
- /package/dist/web/assets/{haskell-CcsmcOez.js → haskell-uQcywkDH.js} +0 -0
- /package/dist/web/assets/{haxe-BimYY9X4.js → haxe-c6bI4_GT.js} +0 -0
- /package/dist/web/assets/{hcl-CTrXCK40.js → hcl-CQXTiEXq.js} +0 -0
- /package/dist/web/assets/{hjson-CmqqU6Qg.js → hjson-ChETf2bz.js} +0 -0
- /package/dist/web/assets/{hlsl-CuJtX_uf.js → hlsl-BMC4JGoE.js} +0 -0
- /package/dist/web/assets/{horizon-BGeSjDYJ.js → horizon-BusFlhLW.js} +0 -0
- /package/dist/web/assets/{horizon-bright-GYMgd3R0.js → horizon-bright-2oD0Mz7W.js} +0 -0
- /package/dist/web/assets/{houston--JD_5r2q.js → houston-DdbbjqFg.js} +0 -0
- /package/dist/web/assets/{hy-C9ILOiqk.js → hy-D_SOuqw9.js} +0 -0
- /package/dist/web/assets/{image-gallery-BWFpZAAP.js → image-gallery-CrM5fHKy.js} +0 -0
- /package/dist/web/assets/{imba-B6F3yus5.js → imba-BxLOHO5I.js} +0 -0
- /package/dist/web/assets/{ini-BfkQswMZ.js → ini-ox-CFcg0.js} +0 -0
- /package/dist/web/assets/{java-DEH5avQ1.js → java-Bzo8yIal.js} +0 -0
- /package/dist/web/assets/{javascript-Dr4yHuV2.js → javascript-DHuz9VXn.js} +0 -0
- /package/dist/web/assets/{json-BuR35ewf.js → json-0_y80FD5.js} +0 -0
- /package/dist/web/assets/{json5-Ny9ZiJAC.js → json5-CEQ50pGM.js} +0 -0
- /package/dist/web/assets/{jsonc-zYVuoZkR.js → jsonc-CfrLEAKA.js} +0 -0
- /package/dist/web/assets/{jsonl-B9xthb_H.js → jsonl-fKbrANC2.js} +0 -0
- /package/dist/web/assets/{jsonnet-CCoLJbMP.js → jsonnet-DKbkPaQ2.js} +0 -0
- /package/dist/web/assets/{jssm-W0GDlQXi.js → jssm-Dxxx1Hqu.js} +0 -0
- /package/dist/web/assets/{jsx-BrLJpWC-.js → jsx-DlJL-Oj3.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-CuVwt_MO.js → kanagawa-dragon-CwN4SV1c.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-B3W_617P.js → kanagawa-lotus-BHltayiE.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-CEx4MP5W.js → kanagawa-wave-D-KXPjw6.js} +0 -0
- /package/dist/web/assets/{kdl-DilRejnB.js → kdl-DvtoJdFo.js} +0 -0
- /package/dist/web/assets/{kotlin-Bq5JtKaa.js → kotlin-CTS4MLcx.js} +0 -0
- /package/dist/web/assets/{kusto-Bhp2KYog.js → kusto-HtSE_sKm.js} +0 -0
- /package/dist/web/assets/{laserwave-WA_7c5hu.js → laserwave-DaXZG9ge.js} +0 -0
- /package/dist/web/assets/{lean-AEGcXwS-.js → lean-BYtGUfWx.js} +0 -0
- /package/dist/web/assets/{less-NPqH-26u.js → less-BoxmU_Mk.js} +0 -0
- /package/dist/web/assets/{lib-BFetOULu.js → lib-BzxL1ARZ.js} +0 -0
- /package/dist/web/assets/{libesm-tR4XlhMj.js → libesm-ah-mr-sh.js} +0 -0
- /package/dist/web/assets/{light-plus-B4xW7cgY.js → light-plus-Bt5CyUuo.js} +0 -0
- /package/dist/web/assets/{llvm-CPyWNcDE.js → llvm-CSdk9q9V.js} +0 -0
- /package/dist/web/assets/{log-CeQmiQSz.js → log-B-kp_3CL.js} +0 -0
- /package/dist/web/assets/{logo-BO0VrjBm.js → logo-DdIsXFDO.js} +0 -0
- /package/dist/web/assets/{luau-B6GT9kA1.js → luau-DUBpLlzQ.js} +0 -0
- /package/dist/web/assets/{make-CwfmN7e_.js → make-B3JVjoW_.js} +0 -0
- /package/dist/web/assets/{markdown-Bbe4FlLp.js → markdown-Seon0vHs.js} +0 -0
- /package/dist/web/assets/{material-theme-iD9XbfsB.js → material-theme-Nq-ChX1P.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-u7M3XGe7.js → material-theme-darker-CPV4ayXJ.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-BGdI48zn.js → material-theme-lighter-0kyjYqEd.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-_mk62F5q.js → material-theme-ocean-DGpAp5co.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-CxFbDyAu.js → material-theme-palenight-B0AUn0NG.js} +0 -0
- /package/dist/web/assets/{matlab-Z0RUE3V_.js → matlab-C2waytxs.js} +0 -0
- /package/dist/web/assets/{mdx-BZ5wPYzV.js → mdx-DAis6R6I.js} +0 -0
- /package/dist/web/assets/{mermaid-CY1_aP-h.js → mermaid-_rnT2YGD.js} +0 -0
- /package/dist/web/assets/{min-dark-DKWtxOre.js → min-dark-BSSjchUB.js} +0 -0
- /package/dist/web/assets/{min-light-e1iwHDfP.js → min-light-DomAFQsa.js} +0 -0
- /package/dist/web/assets/{mipsasm-BiDfQ4ir.js → mipsasm-bBgtvPyG.js} +0 -0
- /package/dist/web/assets/{mojo-DteFEHsj.js → mojo-Cp9BayW0.js} +0 -0
- /package/dist/web/assets/{monokai-BgPbE9xZ.js → monokai-CL_9gbmn.js} +0 -0
- /package/dist/web/assets/{moonbit-mEbRp-mA.js → moonbit-BS_fcr-P.js} +0 -0
- /package/dist/web/assets/{move-CogqZw7A.js → move-C79AH45U.js} +0 -0
- /package/dist/web/assets/{narrat-BD2qjmy1.js → narrat-CJ5s3BDf.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-BNX8GOD_.js → nextflow-groovy-ZHa4JrPJ.js} +0 -0
- /package/dist/web/assets/{night-owl-ed3GbziD.js → night-owl-Jkf9zFQK.js} +0 -0
- /package/dist/web/assets/{night-owl-light-B0j7O0Wn.js → night-owl-light-DRPeaG5J.js} +0 -0
- /package/dist/web/assets/{nix-DFDbcQQm.js → nix-D2Jet9DN.js} +0 -0
- /package/dist/web/assets/{nord-D93TxEQi.js → nord-CREVs22j.js} +0 -0
- /package/dist/web/assets/{nushell-3_H_XKja.js → nushell-CAiDi_mR.js} +0 -0
- /package/dist/web/assets/{objective-c-BM3u6nlm.js → objective-c-CVkmJkC1.js} +0 -0
- /package/dist/web/assets/{objective-cpp-DZ73h42g.js → objective-cpp-DIKDO1Ly.js} +0 -0
- /package/dist/web/assets/{ocaml-B1PU5gmh.js → ocaml-R9qtGQhs.js} +0 -0
- /package/dist/web/assets/{odin-D14L6aRL.js → odin-DTYNQqVr.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-Bj-94Z8v.js → one-dark-pro-BSLWUJn5.js} +0 -0
- /package/dist/web/assets/{one-light-DTdGWyOZ.js → one-light-DbkRXG3t.js} +0 -0
- /package/dist/web/assets/{openscad-Ciq554Sj.js → openscad-BlPcSnmT.js} +0 -0
- /package/dist/web/assets/{pascal-Bfd4qdGi.js → pascal-B1Y46ZZB.js} +0 -0
- /package/dist/web/assets/{pkl-CTurDUfj.js → pkl-BhJSJbFv.js} +0 -0
- /package/dist/web/assets/{plastic-BLQfZXQp.js → plastic-BzxsCTpi.js} +0 -0
- /package/dist/web/assets/{plsql-DyYfP9kQ.js → plsql-DBba7dyP.js} +0 -0
- /package/dist/web/assets/{po-CgXdT8vQ.js → po-BvgLlnNo.js} +0 -0
- /package/dist/web/assets/{poimandres-DOg5fK6s.js → poimandres-DUaI_1JP.js} +0 -0
- /package/dist/web/assets/{polar-Dv4aoL6X.js → polar-C7uILwJn.js} +0 -0
- /package/dist/web/assets/{postcss-DxugHnJD.js → postcss-BgJlpFdw.js} +0 -0
- /package/dist/web/assets/{powerquery-CR3kzRyX.js → powerquery-Dn1MIpZu.js} +0 -0
- /package/dist/web/assets/{powershell-BE91xJQB.js → powershell-Bo-DYzOS.js} +0 -0
- /package/dist/web/assets/{prisma-B_3yUlRQ.js → prisma-CTLs5IdT.js} +0 -0
- /package/dist/web/assets/{prolog-DcT781Ht.js → prolog-QRGun3eG.js} +0 -0
- /package/dist/web/assets/{proto-CSf-w5k2.js → proto-B7PI7apn.js} +0 -0
- /package/dist/web/assets/{puppet-CLGO6QWl.js → puppet-CBq0tLrP.js} +0 -0
- /package/dist/web/assets/{purescript-Bah2McKd.js → purescript-DFewOQb2.js} +0 -0
- /package/dist/web/assets/{python-DUH8qy7N.js → python-iWuxKXvT.js} +0 -0
- /package/dist/web/assets/{qmldir-YIsHnjKq.js → qmldir-cXiW3AsF.js} +0 -0
- /package/dist/web/assets/{qss-CLmoVNA4.js → qss-DASwAbBL.js} +0 -0
- /package/dist/web/assets/{r-Pon-b-vz.js → r-TU2eaIPw.js} +0 -0
- /package/dist/web/assets/{racket-BA09P5Kg.js → racket-SkRKqrLY.js} +0 -0
- /package/dist/web/assets/{raku-DlpzU7Fe.js → raku-D31lthkZ.js} +0 -0
- /package/dist/web/assets/{react-w6wINGnd.js → react-I_EwPIZi.js} +0 -0
- /package/dist/web/assets/{red-l7VuCR6d.js → red-CTcQZevb.js} +0 -0
- /package/dist/web/assets/{reg-g_k7gQEr.js → reg-D8YAsTGf.js} +0 -0
- /package/dist/web/assets/{regexp-CT17B7I7.js → regexp-CD2uvAWx.js} +0 -0
- /package/dist/web/assets/{rel-DkPCS7Bp.js → rel-CAaI-1fg.js} +0 -0
- /package/dist/web/assets/{riscv-CYuFTw30.js → riscv-DR-hJVIj.js} +0 -0
- /package/dist/web/assets/{ron-cY7u_yEu.js → ron-CuUCJ0n4.js} +0 -0
- /package/dist/web/assets/{rose-pine-Cr_h_Ubo.js → rose-pine-aFHxW48i.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-rRewaSZg.js → rose-pine-dawn-Bqz2sBRY.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-3VX5Xwca.js → rose-pine-moon-wqyh0an4.js} +0 -0
- /package/dist/web/assets/{rosmsg-Du4ie5PU.js → rosmsg-CI1ywimO.js} +0 -0
- /package/dist/web/assets/{rust-B7xWL-Eh.js → rust-p7Imk4G_.js} +0 -0
- /package/dist/web/assets/{sass-oXbOG8de.js → sass-C8JfaqCV.js} +0 -0
- /package/dist/web/assets/{save-C4z1p51e.js → save-DRPrDfTt.js} +0 -0
- /package/dist/web/assets/{scala-nlZJhKHf.js → scala-DNxCW1By.js} +0 -0
- /package/dist/web/assets/{scheme-FZ9_Zy8D.js → scheme-BYuUPJoL.js} +0 -0
- /package/dist/web/assets/{sdbl-D_lyvXiu.js → sdbl-DbPeJPUr.js} +0 -0
- /package/dist/web/assets/{shellscript-DRWRboAd.js → shellscript-DMiHlR3q.js} +0 -0
- /package/dist/web/assets/{shield-check-C5laObJv.js → shield-check-8GObuUAn.js} +0 -0
- /package/dist/web/assets/{shield-off-DULFtyLS.js → shield-off-egKAZEwR.js} +0 -0
- /package/dist/web/assets/{slack-dark-BGk2uVHu.js → slack-dark-C4xGcQXI.js} +0 -0
- /package/dist/web/assets/{slack-ochin-PAoSX041.js → slack-ochin-BzgRt_wm.js} +0 -0
- /package/dist/web/assets/{smalltalk-qP0zvICo.js → smalltalk-LDeL9PYH.js} +0 -0
- /package/dist/web/assets/{snazzy-light-B7uccpH6.js → snazzy-light-CXE7a5j_.js} +0 -0
- /package/dist/web/assets/{solarized-dark-CbICLZs3.js → solarized-dark-DgUhY74x.js} +0 -0
- /package/dist/web/assets/{solarized-light-CprWhyjj.js → solarized-light-DD9C-H-9.js} +0 -0
- /package/dist/web/assets/{solidity-B7pcm2K6.js → solidity-CAbDB4D4.js} +0 -0
- /package/dist/web/assets/{splunk-Co2LL4J_.js → splunk-kQREPfIc.js} +0 -0
- /package/dist/web/assets/{sql-cETIdGnT.js → sql-CBzeNAD8.js} +0 -0
- /package/dist/web/assets/{ssh-config-DETG6JCD.js → ssh-config-L1euxrsM.js} +0 -0
- /package/dist/web/assets/{stylus-tmTre2-O.js → stylus-DvBnYniP.js} +0 -0
- /package/dist/web/assets/{swift-BeKQbULV.js → swift-DF5NDQp6.js} +0 -0
- /package/dist/web/assets/{synthwave-84-eCL4-Xdn.js → synthwave-84-DbBhB_Hq.js} +0 -0
- /package/dist/web/assets/{system-verilog-CviwWvEx.js → system-verilog-D8s2ZW_k.js} +0 -0
- /package/dist/web/assets/{systemd-WuoFIbBS.js → systemd-a5-XZJsG.js} +0 -0
- /package/dist/web/assets/{table-CHmxuh6M.js → table-BX2ZrJfM.js} +0 -0
- /package/dist/web/assets/{talonscript-B9VBu7VI.js → talonscript-BLa0URTW.js} +0 -0
- /package/dist/web/assets/{tasl-CN7r11ky.js → tasl-DIoV4XcC.js} +0 -0
- /package/dist/web/assets/{tcl-e1cdhe3h.js → tcl-ztYAdXfQ.js} +0 -0
- /package/dist/web/assets/{terraform-BEP0mfa_.js → terraform-DvpCCiOZ.js} +0 -0
- /package/dist/web/assets/{tokyo-night-BfA_dA37.js → tokyo-night-BkHlYUv0.js} +0 -0
- /package/dist/web/assets/{toml-BrDIfNnt.js → toml-acIrxos6.js} +0 -0
- /package/dist/web/assets/{tsv-CyfGyE4i.js → tsv-BJB5EVCT.js} +0 -0
- /package/dist/web/assets/{tsx-BrFA8Iwf.js → tsx-B1MmXGT3.js} +0 -0
- /package/dist/web/assets/{turtle-9GBtR0mP.js → turtle-DFceTiqd.js} +0 -0
- /package/dist/web/assets/{typescript-BuTRZ65V.js → typescript-Dz9wU5Y1.js} +0 -0
- /package/dist/web/assets/{typespec-CRiNNRXF.js → typespec-CPuYZijj.js} +0 -0
- /package/dist/web/assets/{typst-CmpTnnkl.js → typst-CfsCIYv8.js} +0 -0
- /package/dist/web/assets/{utils-B9H0d3Fh.js → utils-DoY4yTP-.js} +0 -0
- /package/dist/web/assets/{v-DnIi2aab.js → v-CGo0jcXA.js} +0 -0
- /package/dist/web/assets/{vala-B7VxCNZP.js → vala-AsSR0hrb.js} +0 -0
- /package/dist/web/assets/{vb-DGoQ3pBT.js → vb-C7tvbXv1.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-ClRVIJ-k.js → vendor-xterm-BeaIjRrv.js} +0 -0
- /package/dist/web/assets/{verilog-zGOC4qwV.js → verilog--a33ND-p.js} +0 -0
- /package/dist/web/assets/{vesper-DXR9-06q.js → vesper-B_Z0h4pn.js} +0 -0
- /package/dist/web/assets/{vhdl-CCO0oz0l.js → vhdl-CWL5dZPN.js} +0 -0
- /package/dist/web/assets/{viml-Dxwr-QNN.js → viml-BglmT14Y.js} +0 -0
- /package/dist/web/assets/{vitesse-black-Bhah7RxE.js → vitesse-black-RKFsSqQI.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-CGK6XVwc.js → vitesse-dark-D7zDWNmc.js} +0 -0
- /package/dist/web/assets/{vitesse-light-ne5kfw8h.js → vitesse-light-MAp87W5b.js} +0 -0
- /package/dist/web/assets/{vyper-ErDFqVoP.js → vyper-CgCBYg1G.js} +0 -0
- /package/dist/web/assets/{wasm-DtWvUWGr.js → wasm-BOG7ZeTT.js} +0 -0
- /package/dist/web/assets/{wasm-Bd258nS1.js → wasm-Bwl4txwp.js} +0 -0
- /package/dist/web/assets/{wenyan-EZe1IEYT.js → wenyan-DpShPKXZ.js} +0 -0
- /package/dist/web/assets/{wgsl-B1o5_I_9.js → wgsl-BakcCblK.js} +0 -0
- /package/dist/web/assets/{wikitext-C_rwp8An.js → wikitext-NroRWVAO.js} +0 -0
- /package/dist/web/assets/{wit-gbYtF3rY.js → wit-B5CM2pg6.js} +0 -0
- /package/dist/web/assets/{wolfram-DrcQFe2n.js → wolfram-7MTFBJpR.js} +0 -0
- /package/dist/web/assets/{x-B1qHmLdR.js → x-BcqfTY_7.js} +0 -0
- /package/dist/web/assets/{yaml-CzDAObLX.js → yaml-Bwr01G2K.js} +0 -0
- /package/dist/web/assets/{zenscript-B-J1phtg.js → zenscript-Dj8GATvi.js} +0 -0
- /package/dist/web/assets/{zig-BlzNia0O.js → zig-LAE-fbS-.js} +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Card surfaces for the SendMessage tool (agent teams / cross-session peers).
|
|
3
|
+
*
|
|
4
|
+
* Rendered by `tool-cards.tsx`; the payload shaping lives in `send-message-parse.ts`.
|
|
5
|
+
* The design mirrors the team activity panel — same badge vocabulary, an explicit
|
|
6
|
+
* recipient, and prose rendered as prose — so a peer message reads as a message
|
|
7
|
+
* instead of a JSON dump.
|
|
8
|
+
*/
|
|
9
|
+
import { useState } from "react";
|
|
10
|
+
import { ArrowRight, Code, Clock, CheckCircle2, XCircle } from "lucide-react";
|
|
11
|
+
import { MiniMarkdown } from "./mini-markdown";
|
|
12
|
+
import { TYPE_BADGES } from "./team-message-badges";
|
|
13
|
+
import { normalizeSendMessage, parseSendMessageResult } from "./send-message-parse";
|
|
14
|
+
|
|
15
|
+
/** Badge for a message kind. Ordinary prose gets no badge — the icon already says "message". */
|
|
16
|
+
function KindBadge({ kind }: { kind: string }) {
|
|
17
|
+
if (kind === "message") return null;
|
|
18
|
+
const badge = TYPE_BADGES[kind];
|
|
19
|
+
return (
|
|
20
|
+
<span className={`inline-block rounded px-1.5 py-0.5 text-[10px] ${badge?.className ?? "bg-panel-2 text-text-3"}`}>
|
|
21
|
+
{badge?.label ?? kind}
|
|
22
|
+
</span>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* One-line header: who it went to plus the author's own label for the row. Falls back
|
|
28
|
+
* to the first line of the body, which is exactly what the recipient previews.
|
|
29
|
+
*/
|
|
30
|
+
export function SendMessageSummary({ name, input }: { name: string; input: Record<string, unknown> }) {
|
|
31
|
+
const msg = normalizeSendMessage(input);
|
|
32
|
+
const raw = msg.summary || msg.firstLine || (msg.protocol ? msg.kind : "");
|
|
33
|
+
// The header is a single truncating line; cap the text so a long first line cannot
|
|
34
|
+
// push the status icons out of view on a narrow screen.
|
|
35
|
+
const label = raw.length > 72 ? `${raw.slice(0, 72)}…` : raw;
|
|
36
|
+
// No leading icon here: the card's chip already carries the Send glyph.
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
{name}{" "}
|
|
40
|
+
<span className="text-text-subtle">
|
|
41
|
+
<ArrowRight className="size-3 inline" /> {msg.to || "unknown"}
|
|
42
|
+
{label ? ` · ${label}` : ""}
|
|
43
|
+
</span>
|
|
44
|
+
{msg.notifyWhenIdle && <Clock className="size-3 inline ml-1 text-text-3" />}
|
|
45
|
+
</>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Expanded body: recipient row, then the message itself. */
|
|
50
|
+
export function SendMessageDetails({ input }: { input: Record<string, unknown> }) {
|
|
51
|
+
const msg = normalizeSendMessage(input);
|
|
52
|
+
return (
|
|
53
|
+
<div className="space-y-1.5">
|
|
54
|
+
<div className="flex flex-wrap items-center gap-1.5">
|
|
55
|
+
<span className="text-text-subtle">To</span>
|
|
56
|
+
<span className="font-medium text-text-primary">{msg.to || "unknown"}</span>
|
|
57
|
+
<KindBadge kind={msg.kind} />
|
|
58
|
+
{msg.notifyWhenIdle && (
|
|
59
|
+
<span className="inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] bg-panel-2 text-text-3">
|
|
60
|
+
<Clock className="size-3" /> notify when idle
|
|
61
|
+
</span>
|
|
62
|
+
)}
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
{/* The summary is not repeated here — the collapsed header already shows it. */}
|
|
66
|
+
{!!msg.text && <MiniMarkdown content={msg.text} maxHeight="max-h-40" />}
|
|
67
|
+
|
|
68
|
+
{msg.protocol && (
|
|
69
|
+
<div className="space-y-0.5 text-text-secondary">
|
|
70
|
+
{msg.protocol.approve != null && (
|
|
71
|
+
<p>
|
|
72
|
+
{msg.protocol.approve ? "Approved" : "Rejected"}
|
|
73
|
+
{msg.protocol.request_id ? (
|
|
74
|
+
<span className="text-text-subtle font-mono"> · {msg.protocol.request_id}</span>
|
|
75
|
+
) : null}
|
|
76
|
+
</p>
|
|
77
|
+
)}
|
|
78
|
+
{!!msg.protocol.reason && <p className="text-text-subtle">{msg.protocol.reason}</p>}
|
|
79
|
+
{!!msg.protocol.feedback && <p className="text-text-subtle">{msg.protocol.feedback}</p>}
|
|
80
|
+
</div>
|
|
81
|
+
)}
|
|
82
|
+
|
|
83
|
+
{msg.extras.length > 0 && (
|
|
84
|
+
<div className="space-y-0.5">
|
|
85
|
+
{msg.extras.map((e) => (
|
|
86
|
+
<p key={e.key} className="text-text-subtle">
|
|
87
|
+
<span className="font-mono">{e.key}</span>: {e.value}
|
|
88
|
+
</p>
|
|
89
|
+
))}
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Delivery status. The runtime answers with JSON nested inside JSON, so it collapses
|
|
98
|
+
* to a single status line with the raw payload kept one click away.
|
|
99
|
+
*/
|
|
100
|
+
export function SendMessageOutcomeView({ output }: { output: string }) {
|
|
101
|
+
const [showRaw, setShowRaw] = useState(false);
|
|
102
|
+
const outcome = parseSendMessageResult(output);
|
|
103
|
+
if (!outcome) return null;
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<div className="border-t border-border pt-1.5 space-y-1">
|
|
107
|
+
<div className="flex items-center gap-1.5 flex-wrap">
|
|
108
|
+
{outcome.ok ? (
|
|
109
|
+
<CheckCircle2 className="size-3 text-success shrink-0" />
|
|
110
|
+
) : (
|
|
111
|
+
<XCircle className="size-3 text-error shrink-0" />
|
|
112
|
+
)}
|
|
113
|
+
<span className={outcome.ok ? "text-success" : "text-error"}>
|
|
114
|
+
{outcome.ok ? "Delivered" : "Not delivered"}
|
|
115
|
+
</span>
|
|
116
|
+
{!!outcome.detail && <span className="text-text-subtle">· {outcome.detail}</span>}
|
|
117
|
+
{!!outcome.ref && <span className="text-text-3 font-mono text-[10px]">[{outcome.ref}]</span>}
|
|
118
|
+
</div>
|
|
119
|
+
<button
|
|
120
|
+
type="button"
|
|
121
|
+
onClick={() => setShowRaw(!showRaw)}
|
|
122
|
+
className="flex items-center gap-1 text-[10px] text-text-subtle hover:text-text-secondary transition-colors"
|
|
123
|
+
>
|
|
124
|
+
<Code className="size-3" />
|
|
125
|
+
{showRaw ? "Hide" : "Show"} raw
|
|
126
|
+
</button>
|
|
127
|
+
{showRaw && (
|
|
128
|
+
<pre className="overflow-x-auto text-text-subtle font-mono max-h-40 whitespace-pre-wrap break-all text-[10px]">
|
|
129
|
+
{output}
|
|
130
|
+
</pre>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalisation for the SendMessage tool (agent teams / cross-session peers).
|
|
3
|
+
*
|
|
4
|
+
* Two things make the raw tool input unfit to render directly:
|
|
5
|
+
*
|
|
6
|
+
* 1. The canonical schema is `{ to, message, summary?, notify_when_idle? }`, but older
|
|
7
|
+
* team instructions taught a `{ type, recipient, content }` shape. Agents that were
|
|
8
|
+
* told both send both, so the same text arrives twice in one payload.
|
|
9
|
+
* 2. `message` is either plain text or a protocol object (shutdown / plan approval),
|
|
10
|
+
* and the object form also shows up as a JSON *string* when a teammate relays it.
|
|
11
|
+
*
|
|
12
|
+
* Everything here is pure so the card stays a thin renderer.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Protocol payloads a teammate can send instead of prose. */
|
|
16
|
+
export interface SendMessageProtocol {
|
|
17
|
+
type: string;
|
|
18
|
+
request_id?: string;
|
|
19
|
+
approve?: boolean;
|
|
20
|
+
reason?: string;
|
|
21
|
+
feedback?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface NormalizedSendMessage {
|
|
25
|
+
/** Recipient name — canonical `to`, falling back to the legacy `recipient`. */
|
|
26
|
+
to: string;
|
|
27
|
+
/** Author-side label for this row; never transmitted to the recipient. */
|
|
28
|
+
summary?: string;
|
|
29
|
+
/** Prose body. Empty when the message is a protocol payload. */
|
|
30
|
+
text: string;
|
|
31
|
+
/** First non-empty line of `text` — the only part the recipient previews. */
|
|
32
|
+
firstLine: string;
|
|
33
|
+
/** Set when the message is a protocol payload rather than prose. */
|
|
34
|
+
protocol?: SendMessageProtocol;
|
|
35
|
+
/** Message kind, used for the badge. `"message"` for ordinary prose. */
|
|
36
|
+
kind: string;
|
|
37
|
+
/** Recipient was asked to report back when it next goes idle. */
|
|
38
|
+
notifyWhenIdle: boolean;
|
|
39
|
+
/** Unrecognised keys, so a future schema field is surfaced instead of swallowed. */
|
|
40
|
+
extras: Array<{ key: string; value: string }>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Keys the card renders explicitly — everything else becomes an `extras` row. */
|
|
44
|
+
const KNOWN_KEYS = new Set([
|
|
45
|
+
"to",
|
|
46
|
+
"message",
|
|
47
|
+
"summary",
|
|
48
|
+
"notify_when_idle",
|
|
49
|
+
// Legacy aliases from earlier team instructions.
|
|
50
|
+
"recipient",
|
|
51
|
+
"content",
|
|
52
|
+
"type",
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
const str = (v: unknown): string => (typeof v === "string" ? v : v == null ? "" : String(v));
|
|
56
|
+
|
|
57
|
+
/** Protocol object if `v` looks like one (`{ type: string, ... }`), else null. */
|
|
58
|
+
function asProtocol(v: unknown): SendMessageProtocol | null {
|
|
59
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return null;
|
|
60
|
+
const p = v as Record<string, unknown>;
|
|
61
|
+
if (typeof p.type !== "string" || !p.type) return null;
|
|
62
|
+
return {
|
|
63
|
+
type: p.type,
|
|
64
|
+
request_id: typeof p.request_id === "string" ? p.request_id : undefined,
|
|
65
|
+
approve: typeof p.approve === "boolean" ? p.approve : undefined,
|
|
66
|
+
reason: typeof p.reason === "string" ? p.reason : undefined,
|
|
67
|
+
feedback: typeof p.feedback === "string" ? p.feedback : undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Same check for a body that arrived as a JSON string. */
|
|
72
|
+
function protocolFromJsonText(text: string): SendMessageProtocol | null {
|
|
73
|
+
const trimmed = text.trim();
|
|
74
|
+
if (!trimmed.startsWith("{")) return null;
|
|
75
|
+
try {
|
|
76
|
+
return asProtocol(JSON.parse(trimmed));
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function normalizeSendMessage(input: Record<string, unknown>): NormalizedSendMessage {
|
|
83
|
+
const to = str(input.to) || str(input.recipient);
|
|
84
|
+
// Canonical field wins; `content` only fills in when `message` is absent. When both
|
|
85
|
+
// are present they are the duplicate described above — the legacy copy is often a
|
|
86
|
+
// truncated prefix, so keeping it would only add noise.
|
|
87
|
+
const rawBody = input.message ?? input.content;
|
|
88
|
+
const protocol = asProtocol(rawBody) ?? protocolFromJsonText(str(rawBody));
|
|
89
|
+
const text = protocol ? "" : str(rawBody);
|
|
90
|
+
const legacyType = str(input.type);
|
|
91
|
+
const kind = protocol?.type || (legacyType && legacyType !== "message" ? legacyType : "message");
|
|
92
|
+
const summary = str(input.summary).trim();
|
|
93
|
+
|
|
94
|
+
const extras = Object.entries(input)
|
|
95
|
+
.filter(([key]) => !KNOWN_KEYS.has(key))
|
|
96
|
+
.map(([key, value]) => ({
|
|
97
|
+
key,
|
|
98
|
+
value: typeof value === "string" ? value : (JSON.stringify(value) ?? ""),
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
to,
|
|
103
|
+
summary: summary || undefined,
|
|
104
|
+
text,
|
|
105
|
+
firstLine: text.split("\n").map((l) => l.trim()).find((l) => l.length > 0) ?? "",
|
|
106
|
+
protocol: protocol ?? undefined,
|
|
107
|
+
kind,
|
|
108
|
+
notifyWhenIdle: input.notify_when_idle === true,
|
|
109
|
+
extras,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** What the tool result says happened to the message. */
|
|
114
|
+
export interface SendMessageOutcome {
|
|
115
|
+
ok: boolean;
|
|
116
|
+
/** Human-readable detail, e.g. "Resuming agent dev-p1". */
|
|
117
|
+
detail?: string;
|
|
118
|
+
/** Peer name the runtime resolved the send to. */
|
|
119
|
+
peer?: string;
|
|
120
|
+
/** Disambiguating ref of that peer, when the runtime pinned one. */
|
|
121
|
+
ref?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Unwrap the tool result. The SDK returns `[{ type: "text", text }]` where `text` is
|
|
126
|
+
* itself the JSON status object, so a raw dump shows JSON inside JSON. Returns null
|
|
127
|
+
* when the shape is anything else, so the caller can fall back to raw output.
|
|
128
|
+
*/
|
|
129
|
+
export function parseSendMessageResult(output: string): SendMessageOutcome | null {
|
|
130
|
+
if (!output) return null;
|
|
131
|
+
let payload: unknown;
|
|
132
|
+
try {
|
|
133
|
+
payload = JSON.parse(output);
|
|
134
|
+
} catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
if (Array.isArray(payload)) {
|
|
138
|
+
const textBlock = payload.find(
|
|
139
|
+
(b) => b && typeof b === "object" && (b as Record<string, unknown>).type === "text"
|
|
140
|
+
) as Record<string, unknown> | undefined;
|
|
141
|
+
const inner = str(textBlock?.text);
|
|
142
|
+
if (!inner) return null;
|
|
143
|
+
try {
|
|
144
|
+
payload = JSON.parse(inner);
|
|
145
|
+
} catch {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return null;
|
|
150
|
+
const o = payload as Record<string, unknown>;
|
|
151
|
+
if (typeof o.success !== "boolean") return null;
|
|
152
|
+
const pin = (o.pin && typeof o.pin === "object" ? o.pin : null) as Record<string, unknown> | null;
|
|
153
|
+
return {
|
|
154
|
+
ok: o.success,
|
|
155
|
+
detail: str(o.message) || str(o.error) || undefined,
|
|
156
|
+
peer: pin ? str(pin.name) || undefined : undefined,
|
|
157
|
+
ref: pin ? str(pin.ref) || undefined : undefined,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Agent-team panel: the team's roster and its conversation, as two tabs.
|
|
3
|
+
*
|
|
4
|
+
* They are deliberately not one scroll. A team runs ~20 members and produces a
|
|
5
|
+
* long conversation, so a single list pushed the roster — the part that answers
|
|
6
|
+
* "who is working right now" — off screen the moment messages accumulated.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
2
10
|
import { RefreshCw } from "lucide-react";
|
|
3
11
|
import { cn } from "@/lib/utils";
|
|
4
|
-
import { api } from "@/lib/api-client";
|
|
5
12
|
import type { TeamMessageItem } from "@/hooks/use-chat";
|
|
13
|
+
import { useTeamActivityFeed } from "@/hooks/use-team-activity-feed";
|
|
14
|
+
import { useWindowStore } from "@/components/floating-window/window-store";
|
|
15
|
+
import { usePrefersCoarsePointer } from "@/components/os-explorer/use-coarse-long-press";
|
|
16
|
+
import { TeamMemberList } from "./team-member-list";
|
|
17
|
+
import { TeamMessageList } from "./team-message-list";
|
|
18
|
+
|
|
19
|
+
type TeamTab = "members" | "messages";
|
|
6
20
|
|
|
7
21
|
interface TeamActivityPanelProps {
|
|
8
22
|
teamNames: string[];
|
|
9
23
|
messages: TeamMessageItem[];
|
|
24
|
+
/** Current session id — the implicit team is named after it */
|
|
25
|
+
sessionId?: string | null;
|
|
26
|
+
/** Passed to a member window so its steps resolve project-relative paths. */
|
|
27
|
+
projectName?: string;
|
|
10
28
|
}
|
|
11
29
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const TYPE_BADGES: Record<string, { label: string; className: string }> = {
|
|
19
|
-
task_assignment: { label: "task", className: "bg-primary/20 text-primary" },
|
|
20
|
-
idle_notification: { label: "idle", className: "bg-warning/20 text-warning" },
|
|
21
|
-
completion: { label: "done", className: "bg-success/20 text-success" },
|
|
22
|
-
shutdown_request: { label: "shutdown", className: "bg-error/20 text-error" },
|
|
23
|
-
shutdown_approved: { label: "shutdown ✓", className: "bg-text-3/20 text-text-3" },
|
|
24
|
-
};
|
|
30
|
+
/** Implicit teams are named after the session, which is an unreadable uuid. */
|
|
31
|
+
function teamLabel(name: string, sessionId?: string | null): string {
|
|
32
|
+
return name === sessionId ? "Team (current session)" : name;
|
|
33
|
+
}
|
|
25
34
|
|
|
26
|
-
export function TeamActivityPanel({ teamNames, messages }: TeamActivityPanelProps) {
|
|
35
|
+
export function TeamActivityPanel({ teamNames, messages, sessionId, projectName }: TeamActivityPanelProps) {
|
|
27
36
|
const [selectedTeam, setSelectedTeam] = useState(teamNames[0] ?? "");
|
|
28
|
-
const [
|
|
29
|
-
const
|
|
30
|
-
|
|
37
|
+
const [tab, setTab] = useState<TeamTab>("members");
|
|
38
|
+
const openWindow = useWindowStore((s) => s.open);
|
|
39
|
+
// Touch needs the 44px minimum even at desktop width; a mouse does not.
|
|
40
|
+
const coarse = usePrefersCoarsePointer();
|
|
31
41
|
|
|
32
42
|
// Sync selected team when teamNames changes
|
|
33
43
|
useEffect(() => {
|
|
@@ -36,32 +46,48 @@ export function TeamActivityPanel({ teamNames, messages }: TeamActivityPanelProp
|
|
|
36
46
|
}
|
|
37
47
|
}, [teamNames, selectedTeam]);
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
const detail = await api.get<any>(`/api/teams/${encodeURIComponent(name)}`);
|
|
43
|
-
setMembers(detail?.members ?? []);
|
|
44
|
-
} catch { setMembers([]); }
|
|
45
|
-
setLoading(false);
|
|
46
|
-
}, []);
|
|
49
|
+
// The panel only renders while open, so mounting is the right poll gate.
|
|
50
|
+
const { members, outbound, loading, refresh } = useTeamActivityFeed(selectedTeam, Boolean(selectedTeam));
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
const openMemberSession = useCallback(
|
|
53
|
+
(memberName: string) => {
|
|
54
|
+
openWindow("team-member", { teamName: selectedTeam, memberName, projectName });
|
|
55
|
+
},
|
|
56
|
+
[openWindow, selectedTeam, projectName],
|
|
57
|
+
);
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Inbox messages are lead → member only. A teammate's own reports live in its
|
|
61
|
+
* transcript as SendMessage calls, so both directions are merged here — without
|
|
62
|
+
* it the panel shows tasks going out and nothing ever coming back.
|
|
63
|
+
*/
|
|
64
|
+
const displayMessages = useMemo(() => {
|
|
65
|
+
const replies = outbound.map((m) => ({
|
|
66
|
+
from: m.from,
|
|
67
|
+
to: m.to,
|
|
68
|
+
text: m.text,
|
|
69
|
+
timestamp: m.timestamp,
|
|
70
|
+
...(m.summary ? { summary: m.summary } : {}),
|
|
71
|
+
})) as TeamMessageItem[];
|
|
72
|
+
return [...messages, ...replies]
|
|
73
|
+
.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())
|
|
74
|
+
.slice(-200);
|
|
75
|
+
}, [messages, outbound]);
|
|
57
76
|
|
|
58
|
-
const
|
|
77
|
+
const workingCount = members.filter((m) => m.workState === "working").length;
|
|
78
|
+
|
|
79
|
+
const tabClass = (active: boolean) =>
|
|
80
|
+
cn(
|
|
81
|
+
"flex items-center gap-1.5 px-2.5 rounded-md text-[11px] whitespace-nowrap transition-colors",
|
|
82
|
+
coarse ? "min-h-[44px]" : "py-1",
|
|
83
|
+
active ? "bg-primary/10 text-primary font-medium" : "text-text-subtle hover:text-text-primary",
|
|
84
|
+
);
|
|
59
85
|
|
|
60
86
|
return (
|
|
61
|
-
<div className="
|
|
62
|
-
{/* Team
|
|
63
|
-
|
|
64
|
-
<div className="flex items-center gap-1 overflow-x-auto min-w-0
|
|
87
|
+
<div className="flex flex-col min-h-0">
|
|
88
|
+
{/* Team selector — only meaningful when a session tracks more than one team */}
|
|
89
|
+
{teamNames.length > 1 && (
|
|
90
|
+
<div className="flex items-center gap-1 overflow-x-auto min-w-0 mb-1.5">
|
|
65
91
|
{teamNames.map((name) => (
|
|
66
92
|
<button
|
|
67
93
|
key={name}
|
|
@@ -70,100 +96,60 @@ export function TeamActivityPanel({ teamNames, messages }: TeamActivityPanelProp
|
|
|
70
96
|
"px-2 py-0.5 text-[11px] rounded-md whitespace-nowrap transition-colors",
|
|
71
97
|
selectedTeam === name
|
|
72
98
|
? "bg-primary/10 text-primary font-medium"
|
|
73
|
-
: "text-text-subtle hover:text-text-primary"
|
|
99
|
+
: "text-text-subtle hover:text-text-primary",
|
|
74
100
|
)}
|
|
75
101
|
>
|
|
76
|
-
{name}
|
|
102
|
+
{teamLabel(name, sessionId)}
|
|
77
103
|
</button>
|
|
78
104
|
))}
|
|
79
105
|
</div>
|
|
106
|
+
)}
|
|
107
|
+
|
|
108
|
+
{/* Members / Messages tabs + refresh */}
|
|
109
|
+
<div className="flex items-center gap-1 mb-1.5 shrink-0" role="tablist">
|
|
110
|
+
<button
|
|
111
|
+
role="tab"
|
|
112
|
+
aria-selected={tab === "members"}
|
|
113
|
+
onClick={() => setTab("members")}
|
|
114
|
+
className={tabClass(tab === "members")}
|
|
115
|
+
>
|
|
116
|
+
<span>Members</span>
|
|
117
|
+
<span className="text-text-subtle">{members.length}</span>
|
|
118
|
+
{workingCount > 0 && (
|
|
119
|
+
<span className="flex items-center gap-1 text-success">
|
|
120
|
+
<span className="size-1.5 rounded-full bg-success animate-pulse" />
|
|
121
|
+
{workingCount}
|
|
122
|
+
</span>
|
|
123
|
+
)}
|
|
124
|
+
</button>
|
|
80
125
|
<button
|
|
81
|
-
|
|
82
|
-
|
|
126
|
+
role="tab"
|
|
127
|
+
aria-selected={tab === "messages"}
|
|
128
|
+
onClick={() => setTab("messages")}
|
|
129
|
+
className={tabClass(tab === "messages")}
|
|
130
|
+
>
|
|
131
|
+
<span>Messages</span>
|
|
132
|
+
<span className="text-text-subtle">{displayMessages.length}</span>
|
|
133
|
+
</button>
|
|
134
|
+
<button
|
|
135
|
+
onClick={refresh}
|
|
136
|
+
className={cn("ml-auto text-text-subtle hover:text-foreground shrink-0", coarse ? "p-3" : "p-1")}
|
|
83
137
|
aria-label="Refresh"
|
|
84
138
|
>
|
|
85
139
|
<RefreshCw className={cn("size-3", loading && "animate-spin")} />
|
|
86
140
|
</button>
|
|
87
141
|
</div>
|
|
88
142
|
|
|
89
|
-
{
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{m.model && m.model !== "unknown" && (
|
|
99
|
-
<span className="text-text-subtle text-[10px]">({m.model})</span>
|
|
100
|
-
)}
|
|
101
|
-
<span className="ml-auto text-text-subtle text-[10px]">{m.status}</span>
|
|
102
|
-
</div>
|
|
103
|
-
))}
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
143
|
+
{tab === "members" ? (
|
|
144
|
+
<TeamMemberList
|
|
145
|
+
members={members}
|
|
146
|
+
loading={loading}
|
|
147
|
+
onOpenMember={openMemberSession}
|
|
148
|
+
className="max-h-56"
|
|
149
|
+
/>
|
|
150
|
+
) : (
|
|
151
|
+
<TeamMessageList messages={displayMessages} className="max-h-56" />
|
|
106
152
|
)}
|
|
107
|
-
|
|
108
|
-
{/* Messages */}
|
|
109
|
-
<div className="max-h-40 overflow-y-auto">
|
|
110
|
-
{displayMessages.length === 0 ? (
|
|
111
|
-
<p className="text-xs text-text-subtle text-center py-2">No messages yet</p>
|
|
112
|
-
) : (
|
|
113
|
-
<div className="space-y-2">
|
|
114
|
-
{displayMessages.map((msg, i) => {
|
|
115
|
-
const badge = msg.parsedType ? TYPE_BADGES[msg.parsedType] : null;
|
|
116
|
-
const time = formatTime(msg.timestamp);
|
|
117
|
-
return (
|
|
118
|
-
<div key={`${msg.timestamp}-${i}`} className="text-xs">
|
|
119
|
-
<div className="flex items-center gap-1 text-text-subtle">
|
|
120
|
-
<span className="font-medium" style={safeColor(msg.color)}>
|
|
121
|
-
{msg.from}
|
|
122
|
-
</span>
|
|
123
|
-
<span>→</span>
|
|
124
|
-
<span>{msg.to}</span>
|
|
125
|
-
<span className="ml-auto text-[10px]">{time}</span>
|
|
126
|
-
</div>
|
|
127
|
-
<div className="mt-0.5 text-foreground/90 break-words">
|
|
128
|
-
{badge && (
|
|
129
|
-
<span className={cn("inline-block px-1 py-0 rounded text-[9px] mr-1", badge.className)}>
|
|
130
|
-
{badge.label}
|
|
131
|
-
</span>
|
|
132
|
-
)}
|
|
133
|
-
{msg.summary ?? truncateText(msg.text)}
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
);
|
|
137
|
-
})}
|
|
138
|
-
<div ref={messagesEndRef} />
|
|
139
|
-
</div>
|
|
140
|
-
)}
|
|
141
|
-
</div>
|
|
142
153
|
</div>
|
|
143
154
|
);
|
|
144
155
|
}
|
|
145
|
-
|
|
146
|
-
function formatTime(timestamp: string): string {
|
|
147
|
-
try {
|
|
148
|
-
const d = new Date(timestamp);
|
|
149
|
-
return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
150
|
-
} catch { return ""; }
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/** Sanitize color value to prevent CSS injection */
|
|
154
|
-
function safeColor(color?: string): React.CSSProperties | undefined {
|
|
155
|
-
if (!color) return undefined;
|
|
156
|
-
if (/^#[0-9a-fA-F]{3,8}$/.test(color) || /^[a-zA-Z]{3,20}$/.test(color)) {
|
|
157
|
-
return { color };
|
|
158
|
-
}
|
|
159
|
-
return undefined;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function truncateText(text: string, max = 120): string {
|
|
163
|
-
if (!text) return "";
|
|
164
|
-
try {
|
|
165
|
-
const parsed = JSON.parse(text);
|
|
166
|
-
return parsed.summary ?? parsed.text ?? text.slice(0, max);
|
|
167
|
-
} catch {}
|
|
168
|
-
return text.length > max ? text.slice(0, max) + "..." : text;
|
|
169
|
-
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One teammate row: who it is, whether it is working, and what it is doing.
|
|
3
|
+
*
|
|
4
|
+
* The status dot is driven by `workState` (derived from transcript writes), not
|
|
5
|
+
* by the inbox — an inbox-derived status reads "active" for every member forever,
|
|
6
|
+
* which is exactly the display that made it impossible to tell who was running.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Loader2, ChevronRight } from "lucide-react";
|
|
10
|
+
import { cn } from "@/lib/utils";
|
|
11
|
+
import type { TeamMemberActivity } from "@/hooks/use-team-activity-feed";
|
|
12
|
+
|
|
13
|
+
interface TeamMemberActivityRowProps {
|
|
14
|
+
member: TeamMemberActivity;
|
|
15
|
+
/** Opens the teammate's full work session. */
|
|
16
|
+
onOpen: (name: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const STATE_LABEL: Record<string, string> = {
|
|
20
|
+
working: "working",
|
|
21
|
+
paused: "paused",
|
|
22
|
+
"no-transcript": "no session",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** Trailing agent-type segment — `ak-engineer:tester` reads as `tester`. */
|
|
26
|
+
function shortAgentType(agentType?: string): string | undefined {
|
|
27
|
+
if (!agentType) return undefined;
|
|
28
|
+
const tail = agentType.split(":").pop();
|
|
29
|
+
return tail && tail !== "general-purpose" ? tail : agentType;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** `1h 4m` / `12m` / `45s` — compact enough for a dense row. */
|
|
33
|
+
export function formatDuration(fromIso?: string, toIso?: string): string | undefined {
|
|
34
|
+
if (!fromIso) return undefined;
|
|
35
|
+
const from = new Date(fromIso).getTime();
|
|
36
|
+
const to = toIso ? new Date(toIso).getTime() : Date.now();
|
|
37
|
+
if (!Number.isFinite(from) || !Number.isFinite(to) || to < from) return undefined;
|
|
38
|
+
const totalSeconds = Math.floor((to - from) / 1000);
|
|
39
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
40
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
41
|
+
if (hours > 0) return `${hours}h ${minutes}m`;
|
|
42
|
+
if (minutes > 0) return `${minutes}m`;
|
|
43
|
+
return `${totalSeconds}s`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Best one-line answer to "what is it doing" from the transcript tail. */
|
|
47
|
+
function currentStep(member: TeamMemberActivity): string | undefined {
|
|
48
|
+
if (member.lastTool) {
|
|
49
|
+
return member.lastToolArg ? `${member.lastTool}: ${member.lastToolArg}` : member.lastTool;
|
|
50
|
+
}
|
|
51
|
+
return member.lastNarrative ?? member.description;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function TeamMemberActivityRow({ member, onOpen }: TeamMemberActivityRowProps) {
|
|
55
|
+
const working = member.workState === "working";
|
|
56
|
+
const step = currentStep(member);
|
|
57
|
+
const elapsed = formatDuration(member.startedAt, working ? undefined : member.lastEventAt);
|
|
58
|
+
const agentType = shortAgentType(member.agentType);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<button
|
|
62
|
+
type="button"
|
|
63
|
+
onClick={() => onOpen(member.name)}
|
|
64
|
+
// 44px min height keeps the row a valid touch target on mobile.
|
|
65
|
+
className="w-full text-left min-h-[44px] px-1.5 py-1 rounded-md hover:bg-surface-elevated transition-colors group"
|
|
66
|
+
>
|
|
67
|
+
<div className="flex items-center gap-2 text-xs">
|
|
68
|
+
{working ? (
|
|
69
|
+
<Loader2 className="size-3 shrink-0 animate-spin text-success" />
|
|
70
|
+
) : (
|
|
71
|
+
<span
|
|
72
|
+
className={cn(
|
|
73
|
+
"size-1.5 rounded-full shrink-0",
|
|
74
|
+
member.workState === "paused" ? "bg-warning" : "bg-text-3",
|
|
75
|
+
)}
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
<span className="font-medium truncate">{member.name}</span>
|
|
79
|
+
{agentType && <span className="text-text-subtle text-[10px] truncate">{agentType}</span>}
|
|
80
|
+
{member.model && <span className="text-text-subtle text-[10px]">({member.model})</span>}
|
|
81
|
+
<span className="ml-auto flex items-center gap-1 shrink-0 text-[10px] text-text-subtle">
|
|
82
|
+
{elapsed && <span>{elapsed}</span>}
|
|
83
|
+
<span className={cn(working && "text-success")}>{STATE_LABEL[member.workState]}</span>
|
|
84
|
+
<ChevronRight className="size-3 opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
85
|
+
</span>
|
|
86
|
+
</div>
|
|
87
|
+
{step && (
|
|
88
|
+
<div className="mt-0.5 pl-5 text-[11px] text-text-subtle truncate font-mono">{step}</div>
|
|
89
|
+
)}
|
|
90
|
+
</button>
|
|
91
|
+
);
|
|
92
|
+
}
|