@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.
Files changed (519) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/CLAUDE.md +1 -0
  3. package/assets/skills/ppm/SKILL.md +1 -1
  4. package/assets/skills/ppm/references/http-api.md +6 -1
  5. package/dist/web/assets/{ai-resource-editor-Bmk4P0YS.js → ai-resource-editor-3Zk3gYSZ.js} +1 -1
  6. package/dist/web/assets/{angular-html-C-Kjr43S.js → angular-html-jfMqUuRd.js} +1 -1
  7. package/dist/web/assets/{angular-ts-CaDDbZqm.js → angular-ts-wytn9PMm.js} +1 -1
  8. package/dist/web/assets/api-client-CzABTreM.js +1 -0
  9. package/dist/web/assets/{api-settings-CAhcNpj5.js → api-settings-DfNRPr1q.js} +1 -1
  10. package/dist/web/assets/api-settings-DlcoR5QT.js +1 -0
  11. package/dist/web/assets/{api-themes-CAjg_Bt9.js → api-themes-CEyYK7AK.js} +1 -1
  12. package/dist/web/assets/{apl-B1WsQFAb.js → apl-i-ahKx6O.js} +1 -1
  13. package/dist/web/assets/architecture-PBZL5I3N-Bs7wzj-W.js +1 -0
  14. package/dist/web/assets/arrow-right-DubGFkN8.js +1 -0
  15. package/dist/web/assets/{astro-Bdnz7nVp.js → astro-DVBCJfG6.js} +1 -1
  16. package/dist/web/assets/audio-preview-DG2Tw0cO.js +1 -0
  17. package/dist/web/assets/{blade-B2euh8sS.js → blade-BHlL8SqU.js} +1 -1
  18. package/dist/web/assets/{bsl-GNeMaxd0.js → bsl-D-UOfR1F.js} +1 -1
  19. package/dist/web/assets/button-B4MWPjWj.js +1 -0
  20. package/dist/web/assets/{cairo-D7G0W7-s.js → cairo-Bn6rucli.js} +1 -1
  21. package/dist/web/assets/chat-tab-DvbbVMBi.js +15 -0
  22. package/dist/web/assets/{cobol-Q6YgysnI.js → cobol-Byn9FYKu.js} +1 -1
  23. package/dist/web/assets/code-editor-BKg7Li-L.js +10 -0
  24. package/dist/web/assets/{coffee-BjufWxVc.js → coffee-DjBl4gm-.js} +1 -1
  25. package/dist/web/assets/{conflict-editor-DC3liBm_.js → conflict-editor-CJNtovCh.js} +3 -3
  26. package/dist/web/assets/{context-menu-q-RHHAWz.js → context-menu-DkQdt6YA.js} +1 -1
  27. package/dist/web/assets/{cpp-CqWU0gCR.js → cpp-CKzic-3E.js} +1 -1
  28. package/dist/web/assets/{crystal-ylayVajF.js → crystal-Bkg-Ly_g.js} +1 -1
  29. package/dist/web/assets/{csv-preview-BhCOjgq1.js → csv-preview-BR6gCSZJ.js} +1 -1
  30. package/dist/web/assets/{data-grid-overlay-editor-BzPfsCfd.js → data-grid-overlay-editor-B1mTl3KS.js} +1 -1
  31. package/dist/web/assets/{database-viewer-Z6uLyZVO.js → database-viewer-DzuwuFSr.js} +1 -1
  32. package/dist/web/assets/diff-viewer-DL3_tISz.js +4 -0
  33. package/dist/web/assets/{docx-preview-C_fSjfy_.js → docx-preview-BzgyssBV.js} +1 -1
  34. package/dist/web/assets/download-D9UYwY0-.js +1 -0
  35. package/dist/web/assets/{edge-DX4NxQfh.js → edge-DVbZnd3Y.js} +1 -1
  36. package/dist/web/assets/{edit-diff-preview-DfX-9om9.js → edit-diff-preview-HTZPC9VP.js} +1 -1
  37. package/dist/web/assets/{elixir-CSh3NjbV.js → elixir-Dwi8Wu7W.js} +1 -1
  38. package/dist/web/assets/{elm-DBzwFYq9.js → elm-DtIv-HXJ.js} +1 -1
  39. package/dist/web/assets/{erb-yxVOb8aB.js → erb-D3HEDz1x.js} +1 -1
  40. package/dist/web/assets/{erlang-5XIDkYrM.js → erlang-2MjTCzGz.js} +1 -1
  41. package/dist/web/assets/{esm-DO4el2OJ.js → esm-CZ8B8Ba2.js} +1 -1
  42. package/dist/web/assets/explorer-body-CrrY1HbH.js +2 -0
  43. package/dist/web/assets/explorer-window-content-CvQPeiwU.js +1 -0
  44. package/dist/web/assets/{extension-webview-ePIM2fwM.js → extension-webview-DH1PfQF2.js} +1 -1
  45. package/dist/web/assets/{fortran-fixed-form-D4tE5VWY.js → fortran-fixed-form-BLyAtyPM.js} +1 -1
  46. package/dist/web/assets/{fsharp-By8soj6-.js → fsharp-Bxbn_gbr.js} +1 -1
  47. package/dist/web/assets/{gdresource-DoSwM7Hv.js → gdresource-sFMY4D2Q.js} +1 -1
  48. package/dist/web/assets/{git-commit-_ZiciHIx.js → git-commit-BzB9Lio5.js} +1 -1
  49. package/dist/web/assets/{git-log-panel-BRWmTzX1.js → git-log-panel-gUm4E3wo.js} +1 -1
  50. package/dist/web/assets/{git-rebase-C3Y5N9-s.js → git-rebase-CKSVd848.js} +1 -1
  51. package/dist/web/assets/gitGraph-HDMCJU4V-D7i54kbM.js +1 -0
  52. package/dist/web/assets/glide-data-grid-D8J5lwUP.js +138 -0
  53. package/dist/web/assets/{glimmer-js-BPBTXVlC.js → glimmer-js-BY8aExAJ.js} +1 -1
  54. package/dist/web/assets/{glimmer-ts-BQSZdy_D.js → glimmer-ts-Bak54dBX.js} +1 -1
  55. package/dist/web/assets/{glsl-CbQdxpU-.js → glsl-nR2eaJQe.js} +1 -1
  56. package/dist/web/assets/{graphql-GMlKikpY.js → graphql-CGPPFAU6.js} +1 -1
  57. package/dist/web/assets/group-chat-tab-DihiQPSi.js +1 -0
  58. package/dist/web/assets/{hack-DyshcLec.js → hack-CXIMX-Ol.js} +1 -1
  59. package/dist/web/assets/{haml-rqCqWzsq.js → haml-tPY-9Pfm.js} +1 -1
  60. package/dist/web/assets/{handlebars-BCKwSWjR.js → handlebars-BuW1LT7T.js} +1 -1
  61. package/dist/web/assets/{html-Cg29xPR1.js → html-bgVcwZ-t.js} +1 -1
  62. package/dist/web/assets/{html-derivative-geltIVg8.js → html-derivative-D6-IxTgn.js} +1 -1
  63. package/dist/web/assets/{http-pG7Vp237.js → http-CJ1zyB-h.js} +1 -1
  64. package/dist/web/assets/{hurl-Di3Uu_Mc.js → hurl-CmoT7l3T.js} +1 -1
  65. package/dist/web/assets/{hxml-CRy4lbv8.js → hxml-CztOsL8o.js} +1 -1
  66. package/dist/web/assets/{image-preview-CP82lor8.js → image-preview-DOQBNgwl.js} +1 -1
  67. package/dist/web/assets/index-BtncTUyM.js +52 -0
  68. package/dist/web/assets/index-Bucbpby-.css +2 -0
  69. package/dist/web/assets/info-3K5VOQVL-BV41AzR9.js +1 -0
  70. package/dist/web/assets/{jinja-C8GyVnvd.js → jinja-B1pq3jJq.js} +1 -1
  71. package/dist/web/assets/{jison-BywnqPn6.js → jison-D8B5pCwA.js} +1 -1
  72. package/dist/web/assets/{julia-DTrO3T3B.js → julia-D0K3bwpU.js} +1 -1
  73. package/dist/web/assets/{just-CA3KSHPi.js → just-B9Jlddu-.js} +1 -1
  74. package/dist/web/assets/keybindings-store-AynYQVnV.js +1 -0
  75. package/dist/web/assets/{latex-BC5xUMpc.js → latex-BPJSSE6j.js} +1 -1
  76. package/dist/web/assets/{liquid-Chd8tSyQ.js → liquid-lv10fo4U.js} +1 -1
  77. package/dist/web/assets/{lua-DHaEtwLv.js → lua-PNuaIBEF.js} +1 -1
  78. package/dist/web/assets/markdown-renderer-BBlGpszb.js +1 -0
  79. package/dist/web/assets/{markdown-renderer-DDgl5zDc.js → markdown-renderer-CVGub2iS.js} +3 -3
  80. package/dist/web/assets/{marko-Desx_bC-.js → marko-Du3frD6X.js} +1 -1
  81. package/dist/web/assets/{mdc-DahWHc1t.js → mdc-BeDVcFRl.js} +1 -1
  82. package/dist/web/assets/media-url-C5vA0ha9.js +1 -0
  83. package/dist/web/assets/{mobile-bottom-sheet-BQt45q9T.js → mobile-bottom-sheet-CS3XMwFw.js} +1 -1
  84. package/dist/web/assets/mobile-explorer-sheet-CSgc5JOk.js +1 -0
  85. package/dist/web/assets/{nextflow-3A7lutCA.js → nextflow-DkcXP71s.js} +1 -1
  86. package/dist/web/assets/{nginx-XQda6Hdy.js → nginx-C5n8N_bt.js} +1 -1
  87. package/dist/web/assets/{nim-DHqlpwP1.js → nim-CIhyfs-A.js} +1 -1
  88. package/dist/web/assets/notification-store-1ksB0YwR.js +1 -0
  89. package/dist/web/assets/{number-overlay-editor-DgZtViPO.js → number-overlay-editor-NgOsWJ7x.js} +1 -1
  90. package/dist/web/assets/packet-RMMSAZCW-CaJoP44m.js +1 -0
  91. package/dist/web/assets/{panel-store-s6Qx49RK.js → panel-store-DCD82zc1.js} +1 -1
  92. package/dist/web/assets/{pdf-preview-BXDOe7bG.js → pdf-preview-DSAkWbxY.js} +1 -1
  93. package/dist/web/assets/{perl-M-ncjACb.js → perl-Cf31sZYE.js} +1 -1
  94. package/dist/web/assets/{php-CKIajrZi.js → php-Dzl_MDIW.js} +1 -1
  95. package/dist/web/assets/pie-UPGHQEXC-DSGZmNw2.js +1 -0
  96. package/dist/web/assets/plus-DmjC2iRB.js +1 -0
  97. package/dist/web/assets/{postgres-viewer-DkHYV33h.js → postgres-viewer-DOiM_5Nv.js} +3 -3
  98. package/dist/web/assets/{project-store-DyaEpHVG.js → project-store-B8BkHXy5.js} +1 -1
  99. package/dist/web/assets/{pug-DO0u_gO4.js → pug-CxSYHrB3.js} +1 -1
  100. package/dist/web/assets/{qml-UEje1PAA.js → qml-DlEjGhwN.js} +1 -1
  101. package/dist/web/assets/radar-KQ55EAFF-Be4VUTs0.js +1 -0
  102. package/dist/web/assets/{razor-lCs5T1Ib.js → razor-KVt5uW14.js} +1 -1
  103. package/dist/web/assets/resolve-theme-CJvkL8hU.js +1 -0
  104. package/dist/web/assets/{rst-CZX_O0z4.js → rst-D5BwNTnw.js} +1 -1
  105. package/dist/web/assets/{ruby-idycVAyE.js → ruby-D5fejQwd.js} +1 -1
  106. package/dist/web/assets/run-in-terminal-B8TDtaM_.js +1 -0
  107. package/dist/web/assets/{sas-o5gTfUwp.js → sas-Bj7B1CB2.js} +1 -1
  108. package/dist/web/assets/{scss-CRTk3iBQ.js → scss-BB0CUoCL.js} +1 -1
  109. package/dist/web/assets/send-to-chat-CuBAVC8l.js +1 -0
  110. package/dist/web/assets/{settings-store-ChqHdT2V.js → settings-store-CY-4_U3H.js} +2 -2
  111. package/dist/web/assets/settings-tab-D_oruJB9.js +1 -0
  112. package/dist/web/assets/{shaderlab-3e5ln8ci.js → shaderlab-BdjEZUMc.js} +1 -1
  113. package/dist/web/assets/{shellsession-CGQjQ75I.js → shellsession-Bp1OA1rR.js} +1 -1
  114. package/dist/web/assets/{soy-CxY0VwX2.js → soy-DlYz3wsC.js} +1 -1
  115. package/dist/web/assets/{sparql-CBAGAFuq.js → sparql-CdfII5Jd.js} +1 -1
  116. package/dist/web/assets/sql-query-editor-PWpuw-O5.js +1 -0
  117. package/dist/web/assets/{sqlite-viewer-Cpq06-nz.js → sqlite-viewer-1S6cwVWa.js} +1 -1
  118. package/dist/web/assets/{stata-BoezhOvk.js → stata-BvUA6GUW.js} +1 -1
  119. package/dist/web/assets/{surrealql-CHEzAhu7.js → surrealql--DLNbTyI.js} +1 -1
  120. package/dist/web/assets/{svelte-y6xtu2zX.js → svelte-CBfSsG4n.js} +1 -1
  121. package/dist/web/assets/system-monitor-tab-U0Jh9-2v.js +1 -0
  122. package/dist/web/assets/{tab-store-C42sktPo.js → tab-store-DAsvpx4t.js} +1 -1
  123. package/dist/web/assets/team-member-window-content-DSZL4GIj.js +1 -0
  124. package/dist/web/assets/{templ-DbG2y5yD.js → templ-Dv8zpKZW.js} +1 -1
  125. package/dist/web/assets/terminal-tab-uVhX8AGG.js +3 -0
  126. package/dist/web/assets/{tex-CeKQhrQG.js → tex-CsrOiqh1.js} +1 -1
  127. package/dist/web/assets/tool-cards-QuTCNfYR.js +8 -0
  128. package/dist/web/assets/treemap-KZPCXAKY-Cu2zgbxU.js +1 -0
  129. package/dist/web/assets/{ts-tags-iKKOXJjG.js → ts-tags-3T98k4EJ.js} +1 -1
  130. package/dist/web/assets/{twig-DK8Vrp-G.js → twig-u6QZ45FH.js} +1 -1
  131. package/dist/web/assets/{use-blob-url-DYtOHK7u.js → use-blob-url-BmlYYZ8L.js} +1 -1
  132. package/dist/web/assets/use-is-mobile-B8FA4kQf.js +1 -0
  133. package/dist/web/assets/use-monaco-theme-DvmINdhI.js +1 -0
  134. package/dist/web/assets/use-websocket-DoZdQS0G.js +1 -0
  135. package/dist/web/assets/{vendor-mermaid-C977xNeE.js → vendor-mermaid-Bg4vE8QA.js} +1 -1
  136. package/dist/web/assets/video-preview-CzU09X0C.js +1 -0
  137. package/dist/web/assets/{vue-JkIEObMV.js → vue-CxIsxtwn.js} +1 -1
  138. package/dist/web/assets/{vue-html-D8SqnU86.js → vue-html-BGL5qnuH.js} +1 -1
  139. package/dist/web/assets/{vue-vine-DJj7N4WD.js → vue-vine-DHPh_gMr.js} +1 -1
  140. package/dist/web/assets/{xml-C-00w9Rv.js → xml-C-vM2m7J.js} +1 -1
  141. package/dist/web/assets/{xsl-CVdCwPHV.js → xsl-DvTXNwuO.js} +1 -1
  142. package/dist/web/index.html +21 -20
  143. package/dist/web/sw.js +1 -1
  144. package/docs/codebase-summary.md +1 -0
  145. package/package.json +1 -1
  146. package/scripts/dev-quick-tunnel-retry.mjs +51 -0
  147. package/src/providers/claude-agent-sdk.ts +6 -0
  148. package/src/server/helpers/media-route-handlers.ts +66 -0
  149. package/src/server/helpers/range-file-response.ts +86 -0
  150. package/src/server/index.ts +24 -17
  151. package/src/server/middleware/auth.ts +3 -2
  152. package/src/server/routes/files.ts +40 -7
  153. package/src/server/routes/fs-browse.ts +43 -5
  154. package/src/server/routes/fs-upload.ts +32 -0
  155. package/src/server/routes/teams.ts +34 -0
  156. package/src/server/ws/chat.ts +64 -16
  157. package/src/server/ws/team-inbox-watcher.ts +61 -22
  158. package/src/server/ws/terminal.ts +24 -6
  159. package/src/services/fs-ops/fs-ops-upload.service.ts +120 -0
  160. package/src/services/media-transcode/ffmpeg-capabilities.ts +89 -0
  161. package/src/services/media-transcode/media-probe.ts +63 -0
  162. package/src/services/media-transcode/transcode-stream.ts +129 -0
  163. package/src/services/subagent-transcript-merger.ts +1 -1
  164. package/src/services/team-member-activity/member-activity.service.ts +117 -0
  165. package/src/services/team-member-activity/outbound-message-scanner.ts +121 -0
  166. package/src/services/team-member-activity/subagent-transcript-index.ts +95 -0
  167. package/src/services/team-member-activity/transcript-tail-summary.ts +125 -0
  168. package/src/shared/background-agent-status.ts +79 -0
  169. package/src/types/api.ts +1 -0
  170. package/src/types/chat.ts +6 -1
  171. package/src/web/components/chat/chat-history-bar.tsx +4 -2
  172. package/src/web/components/chat/chat-tab.tsx +1 -0
  173. package/src/web/components/chat/message-input.tsx +13 -6
  174. package/src/web/components/chat/mini-markdown.tsx +17 -0
  175. package/src/web/components/chat/send-message-card.tsx +134 -0
  176. package/src/web/components/chat/send-message-parse.ts +159 -0
  177. package/src/web/components/chat/team-activity-panel.tsx +107 -121
  178. package/src/web/components/chat/team-member-activity-row.tsx +92 -0
  179. package/src/web/components/chat/team-member-list.tsx +43 -0
  180. package/src/web/components/chat/team-member-window-content.tsx +97 -0
  181. package/src/web/components/chat/team-message-badges.ts +18 -0
  182. package/src/web/components/chat/team-message-list.tsx +88 -0
  183. package/src/web/components/chat/team-message-preview.ts +87 -0
  184. package/src/web/components/chat/tool-cards.tsx +44 -18
  185. package/src/web/components/editor/audio-preview.tsx +6 -7
  186. package/src/web/components/editor/video-player/use-video-keyboard-shortcuts.ts +62 -0
  187. package/src/web/components/editor/video-player/video-player-controls.tsx +103 -0
  188. package/src/web/components/editor/video-player/video-player.tsx +190 -0
  189. package/src/web/components/editor/video-player/video-settings-menu.tsx +92 -0
  190. package/src/web/components/editor/video-player/video-transform.ts +49 -0
  191. package/src/web/components/editor/video-preview.tsx +75 -14
  192. package/src/web/components/explorer/file-tree.tsx +6 -0
  193. package/src/web/components/explorer/tree-node-context-menu.tsx +5 -1
  194. package/src/web/components/floating-window/window-content-registry.ts +5 -0
  195. package/src/web/components/floating-window/window-store-types.ts +1 -1
  196. package/src/web/components/os-explorer/actions/explorer-actions-upload.ts +96 -0
  197. package/src/web/components/os-explorer/actions/use-explorer-actions.ts +23 -2
  198. package/src/web/components/os-explorer/actions/use-explorer-upload-actions.tsx +41 -0
  199. package/src/web/components/os-explorer/dnd/use-drop-transfer.tsx +10 -1
  200. package/src/web/components/os-explorer/dnd/use-entry-row-dnd.ts +8 -1
  201. package/src/web/components/os-explorer/dnd/use-external-file-drop.ts +84 -0
  202. package/src/web/components/os-explorer/dnd/use-path-drop-target.ts +46 -3
  203. package/src/web/components/os-explorer/explorer-body.tsx +1 -1
  204. package/src/web/components/os-explorer/explorer-context-menu.tsx +10 -0
  205. package/src/web/components/os-explorer/explorer-dialogs.tsx +2 -0
  206. package/src/web/components/os-explorer/explorer-sidebar.tsx +10 -5
  207. package/src/web/components/os-explorer/explorer-toolbar.tsx +32 -2
  208. package/src/web/components/os-explorer/mobile/mobile-bottom-toolbar.tsx +5 -1
  209. package/src/web/components/os-explorer/upload/collect-dropped-entries.ts +81 -0
  210. package/src/web/components/os-explorer/upload/upload-queue.ts +79 -0
  211. package/src/web/components/os-explorer/upload/use-upload-picker.tsx +74 -0
  212. package/src/web/components/os-explorer/views/column-row.tsx +3 -1
  213. package/src/web/components/os-explorer/views/column-view-column.tsx +6 -1
  214. package/src/web/components/os-explorer/views/icons-view-tile.tsx +1 -1
  215. package/src/web/components/os-explorer/views/icons-view.tsx +5 -1
  216. package/src/web/components/os-explorer/views/list-row.tsx +1 -1
  217. package/src/web/components/os-explorer/views/list-view.tsx +5 -1
  218. package/src/web/components/shared/markdown-code-block.tsx +3 -7
  219. package/src/web/components/terminal/terminal-tab.tsx +19 -25
  220. package/src/web/hooks/use-chat.ts +77 -15
  221. package/src/web/hooks/use-team-activity-feed.ts +92 -0
  222. package/src/web/hooks/use-terminal-command-queue.ts +108 -0
  223. package/src/web/hooks/use-terminal.ts +45 -3
  224. package/src/web/lib/fs-api.ts +9 -0
  225. package/src/web/lib/fs-upload-xhr.ts +62 -0
  226. package/src/web/lib/media-url.ts +51 -0
  227. package/src/web/lib/open-terminal-at.ts +22 -0
  228. package/src/web/lib/run-in-terminal.ts +55 -0
  229. package/src/web/lib/send-to-chat.ts +118 -0
  230. package/src/web/lib/ws-auth.ts +13 -0
  231. package/src/web/lib/ws-client.ts +10 -5
  232. package/src/web/theme/builtin/aurora.ts +8 -5
  233. package/.release-run.sh +0 -5
  234. package/dist/web/assets/api-client-CaRE4HYh.js +0 -1
  235. package/dist/web/assets/api-settings-DBcXfeJ8.js +0 -1
  236. package/dist/web/assets/architecture-PBZL5I3N-B4J2-O8Q.js +0 -1
  237. package/dist/web/assets/audio-preview-CikvnAOI.js +0 -1
  238. package/dist/web/assets/chat-tab-B3-KcCn2.js +0 -13
  239. package/dist/web/assets/code-editor-BpbZw13T.js +0 -10
  240. package/dist/web/assets/dialog-CkI7rwrh.js +0 -1
  241. package/dist/web/assets/diff-viewer-CT1ALWt2.js +0 -4
  242. package/dist/web/assets/explorer-body-CQCyGEet.js +0 -2
  243. package/dist/web/assets/explorer-window-content-EtyTAZSh.js +0 -1
  244. package/dist/web/assets/gitGraph-HDMCJU4V-CtQ3yXN-.js +0 -1
  245. package/dist/web/assets/glide-data-grid-DCJCz4XB.js +0 -138
  246. package/dist/web/assets/group-chat-tab-C3UD2bcm.js +0 -1
  247. package/dist/web/assets/index-BYetJoXQ.js +0 -52
  248. package/dist/web/assets/index-D-xwjNyX.css +0 -2
  249. package/dist/web/assets/info-3K5VOQVL-Cg0mIJn9.js +0 -1
  250. package/dist/web/assets/keybindings-store-yBWU8ZYT.js +0 -1
  251. package/dist/web/assets/markdown-renderer-B2D4gdok.js +0 -1
  252. package/dist/web/assets/mobile-explorer-sheet-BtxyynR3.js +0 -1
  253. package/dist/web/assets/notification-store-DKw_mGED.js +0 -1
  254. package/dist/web/assets/packet-RMMSAZCW-D79vAFR_.js +0 -1
  255. package/dist/web/assets/pie-UPGHQEXC-DYUOH68U.js +0 -1
  256. package/dist/web/assets/plus-9LatwJMx.js +0 -1
  257. package/dist/web/assets/radar-KQ55EAFF-B1eznNtd.js +0 -1
  258. package/dist/web/assets/resolve-theme-B0eotaPq.js +0 -1
  259. package/dist/web/assets/settings-tab-ESL-6MAA.js +0 -1
  260. package/dist/web/assets/sql-query-editor-CZdZuawP.js +0 -1
  261. package/dist/web/assets/system-monitor-tab-XR8NXHpv.js +0 -1
  262. package/dist/web/assets/terminal-tab-CCCB-_50.js +0 -3
  263. package/dist/web/assets/tool-cards-CsTs5go2.js +0 -7
  264. package/dist/web/assets/treemap-KZPCXAKY-SeI2TxLs.js +0 -1
  265. package/dist/web/assets/use-is-mobile-DnFSkUG2.js +0 -1
  266. package/dist/web/assets/use-monaco-theme-CZh7xTJZ.js +0 -1
  267. package/dist/web/assets/video-preview-KbRcyuAA.js +0 -1
  268. package/src/web/components/chat/team-activity-popover.tsx +0 -202
  269. /package/dist/web/assets/{abap-DrMyiWmK.js → abap-C1K0-wzc.js} +0 -0
  270. /package/dist/web/assets/{actionscript-3-BlSOyi0y.js → actionscript-3-CJhQVjLA.js} +0 -0
  271. /package/dist/web/assets/{ada-B_m96icB.js → ada-Bt8r9fME.js} +0 -0
  272. /package/dist/web/assets/{andromeeda-Ch3vOiZB.js → andromeeda-DF1I8qi3.js} +0 -0
  273. /package/dist/web/assets/{apache-CdsaXc1n.js → apache-CnlleE6P.js} +0 -0
  274. /package/dist/web/assets/{apex-0AnsBevk.js → apex-j0C6Xmk6.js} +0 -0
  275. /package/dist/web/assets/{api-client-rTAGdEKo.js → api-client-BSB14J4w.js} +0 -0
  276. /package/dist/web/assets/{applescript-CSxLolzy.js → applescript-DO7AnO8U.js} +0 -0
  277. /package/dist/web/assets/{apply-theme-CMQXnUAa.js → apply-theme-CNj1iA-v.js} +0 -0
  278. /package/dist/web/assets/{ara-DXZS0jA5.js → ara-i83AydZj.js} +0 -0
  279. /package/dist/web/assets/{asciidoc-DDy3pH2A.js → asciidoc-DbBA6-sF.js} +0 -0
  280. /package/dist/web/assets/{asm-Bd17hhqg.js → asm-B5S47Rgr.js} +0 -0
  281. /package/dist/web/assets/{aurora-x-C62HJRs-.js → aurora-x-De_IaSKw.js} +0 -0
  282. /package/dist/web/assets/{awk-Cc-nazni.js → awk-CfyLHXqS.js} +0 -0
  283. /package/dist/web/assets/{ayu-dark-BsfmNWCU.js → ayu-dark-DTLdZ1Si.js} +0 -0
  284. /package/dist/web/assets/{ayu-light-BZ4HLa4X.js → ayu-light-DTOfkzhu.js} +0 -0
  285. /package/dist/web/assets/{ayu-mirage-Bhyjyiqr.js → ayu-mirage-DsAECCMv.js} +0 -0
  286. /package/dist/web/assets/{ballerina-QiWgir3v.js → ballerina-CumGp9A7.js} +0 -0
  287. /package/dist/web/assets/{bat-DxtlkwN3.js → bat-Ca2SBbYN.js} +0 -0
  288. /package/dist/web/assets/{beancount-Bt21X7M_.js → beancount-CqyXBwwF.js} +0 -0
  289. /package/dist/web/assets/{berry-Cksre7lO.js → berry-yl-kJr_H.js} +0 -0
  290. /package/dist/web/assets/{bibtex-DkakgDlR.js → bibtex-DoFFszjV.js} +0 -0
  291. /package/dist/web/assets/{bicep-8crmcyXU.js → bicep-CWPi4nfK.js} +0 -0
  292. /package/dist/web/assets/{bird2-CewQ2I_Z.js → bird2-DXew-ut0.js} +0 -0
  293. /package/dist/web/assets/{bot-nk1k3ELu.js → bot-CunPuEdW.js} +0 -0
  294. /package/dist/web/assets/{c-C_6zE8Ha.js → c-clbySDvd.js} +0 -0
  295. /package/dist/web/assets/{c3-DLWB9-dp.js → c3-B65jvSM1.js} +0 -0
  296. /package/dist/web/assets/{cadence-D8qYS6pR.js → cadence-Cm8tQTHN.js} +0 -0
  297. /package/dist/web/assets/{can-open-in-ppm-BzVXoV-d.js → can-open-in-ppm-Cu-XYIgu.js} +0 -0
  298. /package/dist/web/assets/{catppuccin-frappe-Bh95lNRy.js → catppuccin-frappe-DLeGslh_.js} +0 -0
  299. /package/dist/web/assets/{catppuccin-latte-C1PlN3G0.js → catppuccin-latte-CR5GeHws.js} +0 -0
  300. /package/dist/web/assets/{catppuccin-macchiato-CldtgdK4.js → catppuccin-macchiato-p-XgjxhP.js} +0 -0
  301. /package/dist/web/assets/{catppuccin-mocha-BiwqxX9A.js → catppuccin-mocha-B8QOAZLl.js} +0 -0
  302. /package/dist/web/assets/{clarity-CGiU22jY.js → clarity-DPulbvKH.js} +0 -0
  303. /package/dist/web/assets/{clojure-COIC3doh.js → clojure-DFuWS20u.js} +0 -0
  304. /package/dist/web/assets/{cmake-DWUEQfHv.js → cmake-DejCqcu4.js} +0 -0
  305. /package/dist/web/assets/{codeowners-BNHiAQea.js → codeowners-BwAyqWIH.js} +0 -0
  306. /package/dist/web/assets/{codeql-BuKaoS0j.js → codeql-DgSwFjqI.js} +0 -0
  307. /package/dist/web/assets/{common-lisp-D5IKbxsd.js → common-lisp-CxIVJCtf.js} +0 -0
  308. /package/dist/web/assets/{coq-BMVS-p94.js → coq-DLSjSnmf.js} +0 -0
  309. /package/dist/web/assets/{csharp-DMlbXbM4.js → csharp-C1HHzXBp.js} +0 -0
  310. /package/dist/web/assets/{css-CjkJC89X.js → css-VXsMY--y.js} +0 -0
  311. /package/dist/web/assets/{csv-DoNVBBf0.js → csv-BEbcJdHz.js} +0 -0
  312. /package/dist/web/assets/{csv-parser-DHvoTjMF.js → csv-parser-r-Nk1oHT.js} +0 -0
  313. /package/dist/web/assets/{cue-DoTRbBg-.js → cue-BkDnFqUD.js} +0 -0
  314. /package/dist/web/assets/{cypher-DVsNdTT3.js → cypher-1cMqojSQ.js} +0 -0
  315. /package/dist/web/assets/{d-EX7BBSrv.js → d-BnYjRXtH.js} +0 -0
  316. /package/dist/web/assets/{dark-plus-P_YTHwlh.js → dark-plus-XfbaH7kZ.js} +0 -0
  317. /package/dist/web/assets/{dart-Do-rgU4S.js → dart-Ca7s-8hK.js} +0 -0
  318. /package/dist/web/assets/{data-grid-types-CUx8cusN.js → data-grid-types-BXwlFMzs.js} +0 -0
  319. /package/dist/web/assets/{dax-DxOieacu.js → dax-CmuOw-mY.js} +0 -0
  320. /package/dist/web/assets/{desktop-CvdV7SBf.js → desktop-C2gJ6Ovb.js} +0 -0
  321. /package/dist/web/assets/{diff-CNOetGen.js → diff-BCEo1Ej7.js} +0 -0
  322. /package/dist/web/assets/{dist-CMfLpPW_.js → dist-CUPbqNnL.js} +0 -0
  323. /package/dist/web/assets/{dist-DduBIVkD.js → dist-DOlBnxFX.js} +0 -0
  324. /package/dist/web/assets/{docker-DAlG4_q-.js → docker-DN2jlyAh.js} +0 -0
  325. /package/dist/web/assets/{dotenv-Dh3qf6yx.js → dotenv-NExMY2kS.js} +0 -0
  326. /package/dist/web/assets/{dracula-baAGmJYG.js → dracula-B9lbE01y.js} +0 -0
  327. /package/dist/web/assets/{dracula-soft-l7ZIyums.js → dracula-soft-CMBBfKF_.js} +0 -0
  328. /package/dist/web/assets/{dream-maker-DeRjdBn8.js → dream-maker-DEyDwFsd.js} +0 -0
  329. /package/dist/web/assets/{emacs-lisp-CB05-jQA.js → emacs-lisp-D_qP2zS6.js} +0 -0
  330. /package/dist/web/assets/{everforest-dark-CT-llQBT.js → everforest-dark-DbHa2U-p.js} +0 -0
  331. /package/dist/web/assets/{everforest-light-ByPJkTT7.js → everforest-light-BISkJchP.js} +0 -0
  332. /package/dist/web/assets/{fennel-CeMarbvn.js → fennel-6B22SfJR.js} +0 -0
  333. /package/dist/web/assets/{file-exclamation-point-COAwgNGw.js → file-exclamation-point-a8f3_w7a.js} +0 -0
  334. /package/dist/web/assets/{fish-BYrt6Xtb.js → fish-CubIIvJD.js} +0 -0
  335. /package/dist/web/assets/{fluent-Cr5VcAwh.js → fluent-DF55zQ09.js} +0 -0
  336. /package/dist/web/assets/{fortran-free-form-DQmKtrLa.js → fortran-free-form-DvOu8jAt.js} +0 -0
  337. /package/dist/web/assets/{gdscript-QTDKjzhY.js → gdscript-DCPxdLpq.js} +0 -0
  338. /package/dist/web/assets/{gdshader-Chr-5UYt.js → gdshader-CTZ381FO.js} +0 -0
  339. /package/dist/web/assets/{genie-kWHMWnt0.js → genie-C_QDtvgU.js} +0 -0
  340. /package/dist/web/assets/{gherkin-DtEBQFUo.js → gherkin-BcvK42tF.js} +0 -0
  341. /package/dist/web/assets/{github-dark-B5aiUta2.js → github-dark-C9afs_4w.js} +0 -0
  342. /package/dist/web/assets/{github-dark-default-BkxtsTqR.js → github-dark-default-CKGVrl3Z.js} +0 -0
  343. /package/dist/web/assets/{github-dark-dimmed-B9QjR_0K.js → github-dark-dimmed-C3dQZ_LC.js} +0 -0
  344. /package/dist/web/assets/{github-dark-high-contrast-D6bO-5c0.js → github-dark-high-contrast-DW78QukY.js} +0 -0
  345. /package/dist/web/assets/{github-light-Cg2ZW_CJ.js → github-light-BnP2dznS.js} +0 -0
  346. /package/dist/web/assets/{github-light-default-eD7qUVlQ.js → github-light-default-C2fPZzPG.js} +0 -0
  347. /package/dist/web/assets/{github-light-high-contrast-CFnlSVjd.js → github-light-high-contrast-BzIuUFR2.js} +0 -0
  348. /package/dist/web/assets/{gleam-BpYoOqIT.js → gleam-BpeKwEIO.js} +0 -0
  349. /package/dist/web/assets/{gn-BxwtZPau.js → gn-nUb_Mit0.js} +0 -0
  350. /package/dist/web/assets/{gnuplot-CRyiZDfl.js → gnuplot-D7I0v20p.js} +0 -0
  351. /package/dist/web/assets/{go-Dw1Qx94W.js → go-D7Qqska7.js} +0 -0
  352. /package/dist/web/assets/{groovy-zq_SbWk-.js → groovy-DS-pne5-.js} +0 -0
  353. /package/dist/web/assets/{gruvbox-dark-hard-DbbNy8-Q.js → gruvbox-dark-hard-C0W01fsq.js} +0 -0
  354. /package/dist/web/assets/{gruvbox-dark-medium-BQZ7Kj6C.js → gruvbox-dark-medium-Bqo6fQbg.js} +0 -0
  355. /package/dist/web/assets/{gruvbox-dark-soft-vNavErXi.js → gruvbox-dark-soft-D-XSM_fu.js} +0 -0
  356. /package/dist/web/assets/{gruvbox-light-hard-AOFbCd7i.js → gruvbox-light-hard-IVAwMJRl.js} +0 -0
  357. /package/dist/web/assets/{gruvbox-light-medium-DqtxND6H.js → gruvbox-light-medium-38ATiG7i.js} +0 -0
  358. /package/dist/web/assets/{gruvbox-light-soft-Cg0basu6.js → gruvbox-light-soft-DnZr3c_0.js} +0 -0
  359. /package/dist/web/assets/{haskell-CcsmcOez.js → haskell-uQcywkDH.js} +0 -0
  360. /package/dist/web/assets/{haxe-BimYY9X4.js → haxe-c6bI4_GT.js} +0 -0
  361. /package/dist/web/assets/{hcl-CTrXCK40.js → hcl-CQXTiEXq.js} +0 -0
  362. /package/dist/web/assets/{hjson-CmqqU6Qg.js → hjson-ChETf2bz.js} +0 -0
  363. /package/dist/web/assets/{hlsl-CuJtX_uf.js → hlsl-BMC4JGoE.js} +0 -0
  364. /package/dist/web/assets/{horizon-BGeSjDYJ.js → horizon-BusFlhLW.js} +0 -0
  365. /package/dist/web/assets/{horizon-bright-GYMgd3R0.js → horizon-bright-2oD0Mz7W.js} +0 -0
  366. /package/dist/web/assets/{houston--JD_5r2q.js → houston-DdbbjqFg.js} +0 -0
  367. /package/dist/web/assets/{hy-C9ILOiqk.js → hy-D_SOuqw9.js} +0 -0
  368. /package/dist/web/assets/{image-gallery-BWFpZAAP.js → image-gallery-CrM5fHKy.js} +0 -0
  369. /package/dist/web/assets/{imba-B6F3yus5.js → imba-BxLOHO5I.js} +0 -0
  370. /package/dist/web/assets/{ini-BfkQswMZ.js → ini-ox-CFcg0.js} +0 -0
  371. /package/dist/web/assets/{java-DEH5avQ1.js → java-Bzo8yIal.js} +0 -0
  372. /package/dist/web/assets/{javascript-Dr4yHuV2.js → javascript-DHuz9VXn.js} +0 -0
  373. /package/dist/web/assets/{json-BuR35ewf.js → json-0_y80FD5.js} +0 -0
  374. /package/dist/web/assets/{json5-Ny9ZiJAC.js → json5-CEQ50pGM.js} +0 -0
  375. /package/dist/web/assets/{jsonc-zYVuoZkR.js → jsonc-CfrLEAKA.js} +0 -0
  376. /package/dist/web/assets/{jsonl-B9xthb_H.js → jsonl-fKbrANC2.js} +0 -0
  377. /package/dist/web/assets/{jsonnet-CCoLJbMP.js → jsonnet-DKbkPaQ2.js} +0 -0
  378. /package/dist/web/assets/{jssm-W0GDlQXi.js → jssm-Dxxx1Hqu.js} +0 -0
  379. /package/dist/web/assets/{jsx-BrLJpWC-.js → jsx-DlJL-Oj3.js} +0 -0
  380. /package/dist/web/assets/{kanagawa-dragon-CuVwt_MO.js → kanagawa-dragon-CwN4SV1c.js} +0 -0
  381. /package/dist/web/assets/{kanagawa-lotus-B3W_617P.js → kanagawa-lotus-BHltayiE.js} +0 -0
  382. /package/dist/web/assets/{kanagawa-wave-CEx4MP5W.js → kanagawa-wave-D-KXPjw6.js} +0 -0
  383. /package/dist/web/assets/{kdl-DilRejnB.js → kdl-DvtoJdFo.js} +0 -0
  384. /package/dist/web/assets/{kotlin-Bq5JtKaa.js → kotlin-CTS4MLcx.js} +0 -0
  385. /package/dist/web/assets/{kusto-Bhp2KYog.js → kusto-HtSE_sKm.js} +0 -0
  386. /package/dist/web/assets/{laserwave-WA_7c5hu.js → laserwave-DaXZG9ge.js} +0 -0
  387. /package/dist/web/assets/{lean-AEGcXwS-.js → lean-BYtGUfWx.js} +0 -0
  388. /package/dist/web/assets/{less-NPqH-26u.js → less-BoxmU_Mk.js} +0 -0
  389. /package/dist/web/assets/{lib-BFetOULu.js → lib-BzxL1ARZ.js} +0 -0
  390. /package/dist/web/assets/{libesm-tR4XlhMj.js → libesm-ah-mr-sh.js} +0 -0
  391. /package/dist/web/assets/{light-plus-B4xW7cgY.js → light-plus-Bt5CyUuo.js} +0 -0
  392. /package/dist/web/assets/{llvm-CPyWNcDE.js → llvm-CSdk9q9V.js} +0 -0
  393. /package/dist/web/assets/{log-CeQmiQSz.js → log-B-kp_3CL.js} +0 -0
  394. /package/dist/web/assets/{logo-BO0VrjBm.js → logo-DdIsXFDO.js} +0 -0
  395. /package/dist/web/assets/{luau-B6GT9kA1.js → luau-DUBpLlzQ.js} +0 -0
  396. /package/dist/web/assets/{make-CwfmN7e_.js → make-B3JVjoW_.js} +0 -0
  397. /package/dist/web/assets/{markdown-Bbe4FlLp.js → markdown-Seon0vHs.js} +0 -0
  398. /package/dist/web/assets/{material-theme-iD9XbfsB.js → material-theme-Nq-ChX1P.js} +0 -0
  399. /package/dist/web/assets/{material-theme-darker-u7M3XGe7.js → material-theme-darker-CPV4ayXJ.js} +0 -0
  400. /package/dist/web/assets/{material-theme-lighter-BGdI48zn.js → material-theme-lighter-0kyjYqEd.js} +0 -0
  401. /package/dist/web/assets/{material-theme-ocean-_mk62F5q.js → material-theme-ocean-DGpAp5co.js} +0 -0
  402. /package/dist/web/assets/{material-theme-palenight-CxFbDyAu.js → material-theme-palenight-B0AUn0NG.js} +0 -0
  403. /package/dist/web/assets/{matlab-Z0RUE3V_.js → matlab-C2waytxs.js} +0 -0
  404. /package/dist/web/assets/{mdx-BZ5wPYzV.js → mdx-DAis6R6I.js} +0 -0
  405. /package/dist/web/assets/{mermaid-CY1_aP-h.js → mermaid-_rnT2YGD.js} +0 -0
  406. /package/dist/web/assets/{min-dark-DKWtxOre.js → min-dark-BSSjchUB.js} +0 -0
  407. /package/dist/web/assets/{min-light-e1iwHDfP.js → min-light-DomAFQsa.js} +0 -0
  408. /package/dist/web/assets/{mipsasm-BiDfQ4ir.js → mipsasm-bBgtvPyG.js} +0 -0
  409. /package/dist/web/assets/{mojo-DteFEHsj.js → mojo-Cp9BayW0.js} +0 -0
  410. /package/dist/web/assets/{monokai-BgPbE9xZ.js → monokai-CL_9gbmn.js} +0 -0
  411. /package/dist/web/assets/{moonbit-mEbRp-mA.js → moonbit-BS_fcr-P.js} +0 -0
  412. /package/dist/web/assets/{move-CogqZw7A.js → move-C79AH45U.js} +0 -0
  413. /package/dist/web/assets/{narrat-BD2qjmy1.js → narrat-CJ5s3BDf.js} +0 -0
  414. /package/dist/web/assets/{nextflow-groovy-BNX8GOD_.js → nextflow-groovy-ZHa4JrPJ.js} +0 -0
  415. /package/dist/web/assets/{night-owl-ed3GbziD.js → night-owl-Jkf9zFQK.js} +0 -0
  416. /package/dist/web/assets/{night-owl-light-B0j7O0Wn.js → night-owl-light-DRPeaG5J.js} +0 -0
  417. /package/dist/web/assets/{nix-DFDbcQQm.js → nix-D2Jet9DN.js} +0 -0
  418. /package/dist/web/assets/{nord-D93TxEQi.js → nord-CREVs22j.js} +0 -0
  419. /package/dist/web/assets/{nushell-3_H_XKja.js → nushell-CAiDi_mR.js} +0 -0
  420. /package/dist/web/assets/{objective-c-BM3u6nlm.js → objective-c-CVkmJkC1.js} +0 -0
  421. /package/dist/web/assets/{objective-cpp-DZ73h42g.js → objective-cpp-DIKDO1Ly.js} +0 -0
  422. /package/dist/web/assets/{ocaml-B1PU5gmh.js → ocaml-R9qtGQhs.js} +0 -0
  423. /package/dist/web/assets/{odin-D14L6aRL.js → odin-DTYNQqVr.js} +0 -0
  424. /package/dist/web/assets/{one-dark-pro-Bj-94Z8v.js → one-dark-pro-BSLWUJn5.js} +0 -0
  425. /package/dist/web/assets/{one-light-DTdGWyOZ.js → one-light-DbkRXG3t.js} +0 -0
  426. /package/dist/web/assets/{openscad-Ciq554Sj.js → openscad-BlPcSnmT.js} +0 -0
  427. /package/dist/web/assets/{pascal-Bfd4qdGi.js → pascal-B1Y46ZZB.js} +0 -0
  428. /package/dist/web/assets/{pkl-CTurDUfj.js → pkl-BhJSJbFv.js} +0 -0
  429. /package/dist/web/assets/{plastic-BLQfZXQp.js → plastic-BzxsCTpi.js} +0 -0
  430. /package/dist/web/assets/{plsql-DyYfP9kQ.js → plsql-DBba7dyP.js} +0 -0
  431. /package/dist/web/assets/{po-CgXdT8vQ.js → po-BvgLlnNo.js} +0 -0
  432. /package/dist/web/assets/{poimandres-DOg5fK6s.js → poimandres-DUaI_1JP.js} +0 -0
  433. /package/dist/web/assets/{polar-Dv4aoL6X.js → polar-C7uILwJn.js} +0 -0
  434. /package/dist/web/assets/{postcss-DxugHnJD.js → postcss-BgJlpFdw.js} +0 -0
  435. /package/dist/web/assets/{powerquery-CR3kzRyX.js → powerquery-Dn1MIpZu.js} +0 -0
  436. /package/dist/web/assets/{powershell-BE91xJQB.js → powershell-Bo-DYzOS.js} +0 -0
  437. /package/dist/web/assets/{prisma-B_3yUlRQ.js → prisma-CTLs5IdT.js} +0 -0
  438. /package/dist/web/assets/{prolog-DcT781Ht.js → prolog-QRGun3eG.js} +0 -0
  439. /package/dist/web/assets/{proto-CSf-w5k2.js → proto-B7PI7apn.js} +0 -0
  440. /package/dist/web/assets/{puppet-CLGO6QWl.js → puppet-CBq0tLrP.js} +0 -0
  441. /package/dist/web/assets/{purescript-Bah2McKd.js → purescript-DFewOQb2.js} +0 -0
  442. /package/dist/web/assets/{python-DUH8qy7N.js → python-iWuxKXvT.js} +0 -0
  443. /package/dist/web/assets/{qmldir-YIsHnjKq.js → qmldir-cXiW3AsF.js} +0 -0
  444. /package/dist/web/assets/{qss-CLmoVNA4.js → qss-DASwAbBL.js} +0 -0
  445. /package/dist/web/assets/{r-Pon-b-vz.js → r-TU2eaIPw.js} +0 -0
  446. /package/dist/web/assets/{racket-BA09P5Kg.js → racket-SkRKqrLY.js} +0 -0
  447. /package/dist/web/assets/{raku-DlpzU7Fe.js → raku-D31lthkZ.js} +0 -0
  448. /package/dist/web/assets/{react-w6wINGnd.js → react-I_EwPIZi.js} +0 -0
  449. /package/dist/web/assets/{red-l7VuCR6d.js → red-CTcQZevb.js} +0 -0
  450. /package/dist/web/assets/{reg-g_k7gQEr.js → reg-D8YAsTGf.js} +0 -0
  451. /package/dist/web/assets/{regexp-CT17B7I7.js → regexp-CD2uvAWx.js} +0 -0
  452. /package/dist/web/assets/{rel-DkPCS7Bp.js → rel-CAaI-1fg.js} +0 -0
  453. /package/dist/web/assets/{riscv-CYuFTw30.js → riscv-DR-hJVIj.js} +0 -0
  454. /package/dist/web/assets/{ron-cY7u_yEu.js → ron-CuUCJ0n4.js} +0 -0
  455. /package/dist/web/assets/{rose-pine-Cr_h_Ubo.js → rose-pine-aFHxW48i.js} +0 -0
  456. /package/dist/web/assets/{rose-pine-dawn-rRewaSZg.js → rose-pine-dawn-Bqz2sBRY.js} +0 -0
  457. /package/dist/web/assets/{rose-pine-moon-3VX5Xwca.js → rose-pine-moon-wqyh0an4.js} +0 -0
  458. /package/dist/web/assets/{rosmsg-Du4ie5PU.js → rosmsg-CI1ywimO.js} +0 -0
  459. /package/dist/web/assets/{rust-B7xWL-Eh.js → rust-p7Imk4G_.js} +0 -0
  460. /package/dist/web/assets/{sass-oXbOG8de.js → sass-C8JfaqCV.js} +0 -0
  461. /package/dist/web/assets/{save-C4z1p51e.js → save-DRPrDfTt.js} +0 -0
  462. /package/dist/web/assets/{scala-nlZJhKHf.js → scala-DNxCW1By.js} +0 -0
  463. /package/dist/web/assets/{scheme-FZ9_Zy8D.js → scheme-BYuUPJoL.js} +0 -0
  464. /package/dist/web/assets/{sdbl-D_lyvXiu.js → sdbl-DbPeJPUr.js} +0 -0
  465. /package/dist/web/assets/{shellscript-DRWRboAd.js → shellscript-DMiHlR3q.js} +0 -0
  466. /package/dist/web/assets/{shield-check-C5laObJv.js → shield-check-8GObuUAn.js} +0 -0
  467. /package/dist/web/assets/{shield-off-DULFtyLS.js → shield-off-egKAZEwR.js} +0 -0
  468. /package/dist/web/assets/{slack-dark-BGk2uVHu.js → slack-dark-C4xGcQXI.js} +0 -0
  469. /package/dist/web/assets/{slack-ochin-PAoSX041.js → slack-ochin-BzgRt_wm.js} +0 -0
  470. /package/dist/web/assets/{smalltalk-qP0zvICo.js → smalltalk-LDeL9PYH.js} +0 -0
  471. /package/dist/web/assets/{snazzy-light-B7uccpH6.js → snazzy-light-CXE7a5j_.js} +0 -0
  472. /package/dist/web/assets/{solarized-dark-CbICLZs3.js → solarized-dark-DgUhY74x.js} +0 -0
  473. /package/dist/web/assets/{solarized-light-CprWhyjj.js → solarized-light-DD9C-H-9.js} +0 -0
  474. /package/dist/web/assets/{solidity-B7pcm2K6.js → solidity-CAbDB4D4.js} +0 -0
  475. /package/dist/web/assets/{splunk-Co2LL4J_.js → splunk-kQREPfIc.js} +0 -0
  476. /package/dist/web/assets/{sql-cETIdGnT.js → sql-CBzeNAD8.js} +0 -0
  477. /package/dist/web/assets/{ssh-config-DETG6JCD.js → ssh-config-L1euxrsM.js} +0 -0
  478. /package/dist/web/assets/{stylus-tmTre2-O.js → stylus-DvBnYniP.js} +0 -0
  479. /package/dist/web/assets/{swift-BeKQbULV.js → swift-DF5NDQp6.js} +0 -0
  480. /package/dist/web/assets/{synthwave-84-eCL4-Xdn.js → synthwave-84-DbBhB_Hq.js} +0 -0
  481. /package/dist/web/assets/{system-verilog-CviwWvEx.js → system-verilog-D8s2ZW_k.js} +0 -0
  482. /package/dist/web/assets/{systemd-WuoFIbBS.js → systemd-a5-XZJsG.js} +0 -0
  483. /package/dist/web/assets/{table-CHmxuh6M.js → table-BX2ZrJfM.js} +0 -0
  484. /package/dist/web/assets/{talonscript-B9VBu7VI.js → talonscript-BLa0URTW.js} +0 -0
  485. /package/dist/web/assets/{tasl-CN7r11ky.js → tasl-DIoV4XcC.js} +0 -0
  486. /package/dist/web/assets/{tcl-e1cdhe3h.js → tcl-ztYAdXfQ.js} +0 -0
  487. /package/dist/web/assets/{terraform-BEP0mfa_.js → terraform-DvpCCiOZ.js} +0 -0
  488. /package/dist/web/assets/{tokyo-night-BfA_dA37.js → tokyo-night-BkHlYUv0.js} +0 -0
  489. /package/dist/web/assets/{toml-BrDIfNnt.js → toml-acIrxos6.js} +0 -0
  490. /package/dist/web/assets/{tsv-CyfGyE4i.js → tsv-BJB5EVCT.js} +0 -0
  491. /package/dist/web/assets/{tsx-BrFA8Iwf.js → tsx-B1MmXGT3.js} +0 -0
  492. /package/dist/web/assets/{turtle-9GBtR0mP.js → turtle-DFceTiqd.js} +0 -0
  493. /package/dist/web/assets/{typescript-BuTRZ65V.js → typescript-Dz9wU5Y1.js} +0 -0
  494. /package/dist/web/assets/{typespec-CRiNNRXF.js → typespec-CPuYZijj.js} +0 -0
  495. /package/dist/web/assets/{typst-CmpTnnkl.js → typst-CfsCIYv8.js} +0 -0
  496. /package/dist/web/assets/{utils-B9H0d3Fh.js → utils-DoY4yTP-.js} +0 -0
  497. /package/dist/web/assets/{v-DnIi2aab.js → v-CGo0jcXA.js} +0 -0
  498. /package/dist/web/assets/{vala-B7VxCNZP.js → vala-AsSR0hrb.js} +0 -0
  499. /package/dist/web/assets/{vb-DGoQ3pBT.js → vb-C7tvbXv1.js} +0 -0
  500. /package/dist/web/assets/{vendor-xterm-ClRVIJ-k.js → vendor-xterm-BeaIjRrv.js} +0 -0
  501. /package/dist/web/assets/{verilog-zGOC4qwV.js → verilog--a33ND-p.js} +0 -0
  502. /package/dist/web/assets/{vesper-DXR9-06q.js → vesper-B_Z0h4pn.js} +0 -0
  503. /package/dist/web/assets/{vhdl-CCO0oz0l.js → vhdl-CWL5dZPN.js} +0 -0
  504. /package/dist/web/assets/{viml-Dxwr-QNN.js → viml-BglmT14Y.js} +0 -0
  505. /package/dist/web/assets/{vitesse-black-Bhah7RxE.js → vitesse-black-RKFsSqQI.js} +0 -0
  506. /package/dist/web/assets/{vitesse-dark-CGK6XVwc.js → vitesse-dark-D7zDWNmc.js} +0 -0
  507. /package/dist/web/assets/{vitesse-light-ne5kfw8h.js → vitesse-light-MAp87W5b.js} +0 -0
  508. /package/dist/web/assets/{vyper-ErDFqVoP.js → vyper-CgCBYg1G.js} +0 -0
  509. /package/dist/web/assets/{wasm-DtWvUWGr.js → wasm-BOG7ZeTT.js} +0 -0
  510. /package/dist/web/assets/{wasm-Bd258nS1.js → wasm-Bwl4txwp.js} +0 -0
  511. /package/dist/web/assets/{wenyan-EZe1IEYT.js → wenyan-DpShPKXZ.js} +0 -0
  512. /package/dist/web/assets/{wgsl-B1o5_I_9.js → wgsl-BakcCblK.js} +0 -0
  513. /package/dist/web/assets/{wikitext-C_rwp8An.js → wikitext-NroRWVAO.js} +0 -0
  514. /package/dist/web/assets/{wit-gbYtF3rY.js → wit-B5CM2pg6.js} +0 -0
  515. /package/dist/web/assets/{wolfram-DrcQFe2n.js → wolfram-7MTFBJpR.js} +0 -0
  516. /package/dist/web/assets/{x-B1qHmLdR.js → x-BcqfTY_7.js} +0 -0
  517. /package/dist/web/assets/{yaml-CzDAObLX.js → yaml-Bwr01G2K.js} +0 -0
  518. /package/dist/web/assets/{zenscript-B-J1phtg.js → zenscript-Dj8GATvi.js} +0 -0
  519. /package/dist/web/assets/{zig-BlzNia0O.js → zig-LAE-fbS-.js} +0 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Per-teammate live activity for the team panel.
3
+ *
4
+ * Answers the two questions the inbox cannot: *is anyone working right now*, and
5
+ * *how far along are they*. Neither is derivable from `~/.claude/teams/<team>/`
6
+ * — every member there reads "active" forever, because an inbox only records the
7
+ * task it was handed. The signal lives in the agent transcripts instead: a
8
+ * transcript being appended to right now is a teammate working right now.
9
+ */
10
+
11
+ import { join } from "node:path";
12
+ import { resolveSessionDir } from "../subagent-transcript-merger.ts";
13
+ import { indexTranscriptsByMember, type SubagentTranscriptEntry } from "./subagent-transcript-index.ts";
14
+ import { summarizeTranscriptTail } from "./transcript-tail-summary.ts";
15
+ import { scanOutboundMessages, type OutboundTeamMessage } from "./outbound-message-scanner.ts";
16
+
17
+ /** A transcript touched within this window means the agent is mid-work. */
18
+ export const WORKING_WINDOW_MS = 90_000;
19
+
20
+ export type MemberWorkState = "working" | "paused" | "no-transcript";
21
+
22
+ export interface TeamMemberActivity {
23
+ name: string;
24
+ /** `working` while the transcript is being appended to, else `paused`. */
25
+ workState: MemberWorkState;
26
+ agentType?: string;
27
+ model?: string;
28
+ /** Spawn-time description of the job. */
29
+ description?: string;
30
+ /** tool_use id of the spawning Agent call — links to the chat card. */
31
+ toolUseId?: string;
32
+ startedAt?: string;
33
+ lastEventAt?: string;
34
+ /** Latest tool the agent ran, and its headline argument. */
35
+ lastTool?: string;
36
+ lastToolArg?: string;
37
+ /** Latest prose the agent wrote about its own progress. */
38
+ lastNarrative?: string;
39
+ /** Transcript size — a rough "how much work happened" measure. */
40
+ sizeBytes: number;
41
+ }
42
+
43
+ /** Locate a team's subagents dir. An implicit team is named after its session. */
44
+ export function resolveTeamSubagentsDir(teamName: string, projectPath?: string | null): string | null {
45
+ const sessionDir = resolveSessionDir(teamName, projectPath);
46
+ return sessionDir ? join(sessionDir, "subagents") : null;
47
+ }
48
+
49
+ function workStateFor(entry: SubagentTranscriptEntry, now: number): MemberWorkState {
50
+ if (!entry.sizeBytes) return "no-transcript";
51
+ return now - entry.modifiedAt <= WORKING_WINDOW_MS ? "working" : "paused";
52
+ }
53
+
54
+ /**
55
+ * Activity for every teammate that has a transcript, newest work first.
56
+ *
57
+ * Only head/tail slices are read per member, so this stays cheap enough to poll
58
+ * while the panel is open.
59
+ */
60
+ export async function readTeamMemberActivity(
61
+ teamName: string,
62
+ projectPath?: string | null,
63
+ ): Promise<TeamMemberActivity[]> {
64
+ const subagentsDir = resolveTeamSubagentsDir(teamName, projectPath);
65
+ if (!subagentsDir) return [];
66
+ const byMember = indexTranscriptsByMember(subagentsDir);
67
+ const now = Date.now();
68
+
69
+ const rows = await Promise.all(
70
+ [...byMember.entries()].map(async ([name, entry]) => {
71
+ const tail = await summarizeTranscriptTail(entry.transcriptPath);
72
+ return {
73
+ name,
74
+ workState: workStateFor(entry, now),
75
+ agentType: entry.agentType,
76
+ model: entry.model,
77
+ description: entry.description,
78
+ toolUseId: entry.toolUseId,
79
+ sizeBytes: entry.sizeBytes,
80
+ ...tail,
81
+ } satisfies TeamMemberActivity;
82
+ }),
83
+ );
84
+
85
+ // Whoever is working belongs at the top; within a group, most recent first.
86
+ return rows.sort((a, b) => {
87
+ if (a.workState !== b.workState) return a.workState === "working" ? -1 : b.workState === "working" ? 1 : 0;
88
+ return (b.lastEventAt ?? "").localeCompare(a.lastEventAt ?? "");
89
+ });
90
+ }
91
+
92
+ /** Every reply teammates sent out, across the team's transcripts. */
93
+ export async function readTeamOutboundMessages(
94
+ teamName: string,
95
+ projectPath?: string | null,
96
+ ): Promise<OutboundTeamMessage[]> {
97
+ const subagentsDir = resolveTeamSubagentsDir(teamName, projectPath);
98
+ if (!subagentsDir) return [];
99
+ const byMember = indexTranscriptsByMember(subagentsDir);
100
+ const batches = await Promise.all(
101
+ [...byMember.entries()].map(([name, entry]) => scanOutboundMessages(entry.transcriptPath, name)),
102
+ );
103
+ return batches
104
+ .flat()
105
+ .sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
106
+ }
107
+
108
+ /** Transcript path for one teammate, or null when it has none. */
109
+ export function resolveMemberTranscript(
110
+ teamName: string,
111
+ memberName: string,
112
+ projectPath?: string | null,
113
+ ): string | null {
114
+ const subagentsDir = resolveTeamSubagentsDir(teamName, projectPath);
115
+ if (!subagentsDir) return null;
116
+ return indexTranscriptsByMember(subagentsDir).get(memberName)?.transcriptPath ?? null;
117
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Recover the replies teammates send back, which the inboxes do not hold.
3
+ *
4
+ * A team inbox only ever contains what was sent *to* that handle, and in
5
+ * practice that is just the lead's task assignments. A teammate's own reports
6
+ * ("phase 3 done, commit 5344b74", "blocked, need file ownership") are
7
+ * `SendMessage` tool calls inside its transcript, addressed to the orchestrator.
8
+ * Reading them here is what turns the activity panel from a one-way task list
9
+ * into the actual conversation.
10
+ *
11
+ * Transcripts are append-only, so each is scanned incrementally: only bytes
12
+ * added since the last scan are read, which keeps a 6 MB transcript from being
13
+ * re-parsed on every poll.
14
+ */
15
+
16
+ import { open, stat } from "node:fs/promises";
17
+
18
+ export interface OutboundTeamMessage {
19
+ /** Teammate handle that sent it. */
20
+ from: string;
21
+ /** Recipient as addressed by the agent — often `main` for the orchestrator. */
22
+ to: string;
23
+ /** Raw message body; may itself be a JSON protocol payload. */
24
+ text: string;
25
+ /** Author-supplied one-line label, when given. */
26
+ summary?: string;
27
+ /** ISO timestamp of the record carrying the call. */
28
+ timestamp: string;
29
+ }
30
+
31
+ interface ScanState {
32
+ /** Byte offset of the first unscanned byte. */
33
+ offset: number;
34
+ messages: OutboundTeamMessage[];
35
+ }
36
+
37
+ /** Per-transcript incremental scan state, keyed by absolute path. */
38
+ const scanCache = new Map<string, ScanState>();
39
+
40
+ const str = (v: unknown): string => (typeof v === "string" ? v : "");
41
+
42
+ /** Extract SendMessage calls from one transcript record. */
43
+ function collectFromRecord(rec: Record<string, unknown>, from: string, into: OutboundTeamMessage[]): void {
44
+ const content = (rec.message as Record<string, unknown> | undefined)?.content;
45
+ if (!Array.isArray(content)) return;
46
+ const timestamp = str(rec.timestamp);
47
+ for (const block of content as Record<string, unknown>[]) {
48
+ if (block?.type !== "tool_use" || block.name !== "SendMessage") continue;
49
+ const input = (block.input ?? {}) as Record<string, unknown>;
50
+ // Canonical schema is `{ to, message }`; older team prompts taught
51
+ // `{ recipient, content }` and agents still emit both shapes.
52
+ const to = str(input.to) || str(input.recipient);
53
+ const message = input.message ?? input.content;
54
+ const text = typeof message === "string" ? message : message == null ? "" : JSON.stringify(message);
55
+ if (!to && !text) continue;
56
+ const summary = str(input.summary);
57
+ into.push({ from, to: to || "main", text, timestamp, ...(summary ? { summary } : {}) });
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Messages a teammate sent out, from its transcript.
63
+ *
64
+ * @param path Absolute transcript path.
65
+ * @param from Teammate handle to attribute the messages to.
66
+ */
67
+ export async function scanOutboundMessages(path: string, from: string): Promise<OutboundTeamMessage[]> {
68
+ let size = 0;
69
+ try {
70
+ size = (await stat(path)).size;
71
+ } catch {
72
+ return [];
73
+ }
74
+
75
+ const cached = scanCache.get(path);
76
+ // A shrunk file was rewritten, not appended — the cached offset is meaningless.
77
+ const state: ScanState = cached && cached.offset <= size ? cached : { offset: 0, messages: [] };
78
+ scanCache.set(path, state);
79
+ if (state.offset >= size) return state.messages;
80
+
81
+ const length = size - state.offset;
82
+ let handle;
83
+ try {
84
+ handle = await open(path, "r");
85
+ } catch {
86
+ return state.messages;
87
+ }
88
+ let chunk = "";
89
+ try {
90
+ const buf = Buffer.alloc(length);
91
+ const { bytesRead } = await handle.read(buf, 0, length, state.offset);
92
+ chunk = buf.subarray(0, bytesRead).toString("utf8");
93
+ } catch {
94
+ return state.messages;
95
+ } finally {
96
+ await handle.close().catch(() => {});
97
+ }
98
+
99
+ // Advance only past the last complete line; a partial trailing record is
100
+ // re-read on the next scan once the writer has finished it.
101
+ const lastNewline = chunk.lastIndexOf("\n");
102
+ if (lastNewline < 0) return state.messages;
103
+ const complete = chunk.slice(0, lastNewline);
104
+ state.offset += Buffer.byteLength(complete, "utf8") + 1;
105
+
106
+ for (const line of complete.split("\n")) {
107
+ const trimmed = line.trim();
108
+ if (!trimmed || !trimmed.includes("SendMessage")) continue;
109
+ try {
110
+ collectFromRecord(JSON.parse(trimmed), from, state.messages);
111
+ } catch {
112
+ /* malformed record */
113
+ }
114
+ }
115
+ return state.messages;
116
+ }
117
+
118
+ /** Drop cached scan state (used by tests and when a team is deleted). */
119
+ export function clearOutboundScanCache(): void {
120
+ scanCache.clear();
121
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Index a session's subagent transcripts by teammate name.
3
+ *
4
+ * Claude Code writes one transcript per spawned agent at
5
+ * ~/.claude/projects/<slug>/<sessionId>/subagents/agent-<id>.jsonl
6
+ * with a sibling `agent-<id>.meta.json` carrying `{ agentType, description,
7
+ * name, toolUseId, model }`. That `name` is the same handle the team inbox uses
8
+ * (`dev-p1`, `lead`, …), which is what lets a team member be joined to the
9
+ * transcript of the work it actually did.
10
+ *
11
+ * A team's inbox only records the task it was handed; the transcript is the sole
12
+ * record of what it then did, so this index is the bridge between the two.
13
+ */
14
+
15
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
16
+ import { join } from "node:path";
17
+
18
+ export interface SubagentTranscriptEntry {
19
+ /** Teammate handle from the meta file; absent for unnamed one-off agents. */
20
+ name?: string;
21
+ /** Registered agent type, e.g. `ak-engineer:fullstack-developer`. */
22
+ agentType?: string;
23
+ /** Spawn-time description of the job. */
24
+ description?: string;
25
+ /** Model the agent ran on, when the meta records one. */
26
+ model?: string;
27
+ /** tool_use id of the spawning Agent call — links back to the chat card. */
28
+ toolUseId?: string;
29
+ /** Absolute path of the agent's JSONL transcript. */
30
+ transcriptPath: string;
31
+ /** Transcript size in bytes — the cheap "how much work" signal. */
32
+ sizeBytes: number;
33
+ /** Last write time in epoch ms — the cheap "is it still running" signal. */
34
+ modifiedAt: number;
35
+ }
36
+
37
+ /** Read every `*.meta.json` in a subagents dir, paired with its transcript. */
38
+ export function listSubagentTranscripts(subagentsDir: string): SubagentTranscriptEntry[] {
39
+ let entries: string[];
40
+ try {
41
+ entries = readdirSync(subagentsDir);
42
+ } catch {
43
+ return []; // no subagents dir — session never spawned an agent
44
+ }
45
+
46
+ const out: SubagentTranscriptEntry[] = [];
47
+ for (const file of entries) {
48
+ if (!file.endsWith(".meta.json")) continue;
49
+ const transcriptPath = join(subagentsDir, file.replace(/\.meta\.json$/, ".jsonl"));
50
+ if (!existsSync(transcriptPath)) continue;
51
+ let meta: Record<string, unknown> = {};
52
+ try {
53
+ meta = JSON.parse(readFileSync(join(subagentsDir, file), "utf8"));
54
+ } catch {
55
+ /* unreadable meta — still surface the transcript, just unlabelled */
56
+ }
57
+ let sizeBytes = 0;
58
+ let modifiedAt = 0;
59
+ try {
60
+ const st = statSync(transcriptPath);
61
+ sizeBytes = st.size;
62
+ modifiedAt = st.mtimeMs;
63
+ } catch {
64
+ /* raced with a delete — treat as empty */
65
+ }
66
+ out.push({
67
+ name: typeof meta.name === "string" ? meta.name : undefined,
68
+ agentType: typeof meta.agentType === "string" ? meta.agentType : undefined,
69
+ description: typeof meta.description === "string" ? meta.description : undefined,
70
+ model: typeof meta.model === "string" ? meta.model : undefined,
71
+ toolUseId: typeof meta.toolUseId === "string" ? meta.toolUseId : undefined,
72
+ transcriptPath,
73
+ sizeBytes,
74
+ modifiedAt,
75
+ });
76
+ }
77
+ return out;
78
+ }
79
+
80
+ /**
81
+ * Newest transcript per teammate name.
82
+ *
83
+ * A retried teammate reuses its handle (`dev-p8`, then `dev-p8b`), but a plain
84
+ * re-spawn under the same name would collide — the most recently written
85
+ * transcript is the one describing current work, so it wins.
86
+ */
87
+ export function indexTranscriptsByMember(subagentsDir: string): Map<string, SubagentTranscriptEntry> {
88
+ const byName = new Map<string, SubagentTranscriptEntry>();
89
+ for (const entry of listSubagentTranscripts(subagentsDir)) {
90
+ if (!entry.name) continue;
91
+ const existing = byName.get(entry.name);
92
+ if (!existing || entry.modifiedAt > existing.modifiedAt) byName.set(entry.name, entry);
93
+ }
94
+ return byName;
95
+ }
@@ -0,0 +1,125 @@
1
+ /**
2
+ * "What is this agent doing right now" from a transcript, without reading it all.
3
+ *
4
+ * A single teammate transcript reaches 6 MB, and a team has ~25 of them. The
5
+ * members list is polled while the panel is open, so a full parse per poll would
6
+ * read tens of MB every few seconds. Only the head (for the start time) and a
7
+ * bounded tail (for the latest activity) are read here; the full transcript is
8
+ * parsed lazily, and only for the one member whose window is open.
9
+ */
10
+
11
+ import { open, stat } from "node:fs/promises";
12
+
13
+ /** Tail budget. Big enough to hold several records, small enough to stay cheap. */
14
+ const TAIL_BYTES = 256 * 1024;
15
+ /** Head budget — the first record carries the earliest timestamp. */
16
+ const HEAD_BYTES = 64 * 1024;
17
+
18
+ export interface TranscriptTailSummary {
19
+ /** ISO timestamp of the transcript's first record. */
20
+ startedAt?: string;
21
+ /** ISO timestamp of the most recent record. */
22
+ lastEventAt?: string;
23
+ /** Most recent tool the agent invoked, e.g. `PowerShell`. */
24
+ lastTool?: string;
25
+ /** Compact argument of that tool call — command, path or pattern. */
26
+ lastToolArg?: string;
27
+ /** Most recent prose the agent wrote about what it is doing. */
28
+ lastNarrative?: string;
29
+ }
30
+
31
+ /** Read a byte range as utf-8, tolerating a short or missing file. */
32
+ async function readRange(path: string, start: number, length: number): Promise<string> {
33
+ if (length <= 0) return "";
34
+ let handle;
35
+ try {
36
+ handle = await open(path, "r");
37
+ } catch {
38
+ return "";
39
+ }
40
+ try {
41
+ const buf = Buffer.alloc(length);
42
+ const { bytesRead } = await handle.read(buf, 0, length, start);
43
+ return buf.subarray(0, bytesRead).toString("utf8");
44
+ } catch {
45
+ return "";
46
+ } finally {
47
+ await handle.close().catch(() => {});
48
+ }
49
+ }
50
+
51
+ /** Parse whole JSONL lines out of a possibly-truncated chunk. */
52
+ function parseRecords(chunk: string, dropFirstPartial: boolean): Record<string, unknown>[] {
53
+ const lines = chunk.split("\n");
54
+ // A mid-file read almost always starts inside a record — that fragment is not JSON.
55
+ if (dropFirstPartial) lines.shift();
56
+ const out: Record<string, unknown>[] = [];
57
+ for (const line of lines) {
58
+ const trimmed = line.trim();
59
+ if (!trimmed) continue;
60
+ try {
61
+ out.push(JSON.parse(trimmed));
62
+ } catch {
63
+ /* truncated tail record or mid-write line */
64
+ }
65
+ }
66
+ return out;
67
+ }
68
+
69
+ /** The most informative single argument of a tool call, for a one-line preview. */
70
+ function toolArg(input: unknown): string | undefined {
71
+ if (!input || typeof input !== "object") return undefined;
72
+ const i = input as Record<string, unknown>;
73
+ for (const key of ["command", "file_path", "path", "pattern", "description", "prompt", "url"]) {
74
+ const v = i[key];
75
+ if (typeof v === "string" && v.trim()) {
76
+ // Multi-line commands are common; the first line identifies the action.
77
+ return v.trim().split("\n")[0]!.slice(0, 160);
78
+ }
79
+ }
80
+ return undefined;
81
+ }
82
+
83
+ /** Pull the latest tool call and prose out of records in stream order. */
84
+ function summarizeRecords(records: Record<string, unknown>[], into: TranscriptTailSummary): void {
85
+ for (const rec of records) {
86
+ const ts = rec.timestamp;
87
+ if (typeof ts === "string") into.lastEventAt = ts;
88
+ const content = (rec.message as Record<string, unknown> | undefined)?.content;
89
+ if (!Array.isArray(content)) continue;
90
+ for (const block of content as Record<string, unknown>[]) {
91
+ if (block?.type === "tool_use" && typeof block.name === "string") {
92
+ into.lastTool = block.name;
93
+ into.lastToolArg = toolArg(block.input);
94
+ } else if (block?.type === "text" && typeof block.text === "string" && block.text.trim()) {
95
+ into.lastNarrative = block.text.trim().split("\n")[0]!.slice(0, 200);
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ /** Latest activity in a transcript, reading only its head and tail. */
102
+ export async function summarizeTranscriptTail(path: string): Promise<TranscriptTailSummary> {
103
+ let size = 0;
104
+ try {
105
+ size = (await stat(path)).size;
106
+ } catch {
107
+ return {};
108
+ }
109
+ const summary: TranscriptTailSummary = {};
110
+
111
+ const head = parseRecords(await readRange(path, 0, Math.min(HEAD_BYTES, size)), false);
112
+ const firstTs = head.find((r) => typeof r.timestamp === "string")?.timestamp;
113
+ if (typeof firstTs === "string") summary.startedAt = firstTs;
114
+
115
+ // When the file fits in one read, head already holds everything.
116
+ if (size <= HEAD_BYTES) {
117
+ summarizeRecords(head, summary);
118
+ return summary;
119
+ }
120
+
121
+ const tailStart = Math.max(0, size - TAIL_BYTES);
122
+ const tail = parseRecords(await readRange(path, tailStart, size - tailStart), tailStart > 0);
123
+ summarizeRecords(tail, summary);
124
+ return summary;
125
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Lifecycle of a backgrounded subagent (`Agent`/`Task` with `run_in_background`).
3
+ *
4
+ * The tool call itself returns the instant the agent is spawned — its result is a launch
5
+ * acknowledgement, not a report. The agent then runs past the end of the turn and only
6
+ * reports back through a `<task-notification>` the CLI injects as a user message.
7
+ *
8
+ * A tool card that treats the launch ack as "finished" therefore shows a green check while
9
+ * the agent is still working and its step count keeps climbing. Everything here exists so
10
+ * both the transcript loader and the live stream can tell the two apart.
11
+ */
12
+
13
+ import type { ChatEvent, ChatMessage } from "../types/chat";
14
+
15
+ /** Terminal states the CLI reports for a background task. */
16
+ export type BackgroundAgentStatus = "completed" | "failed" | "stopped";
17
+
18
+ /** Text the Agent/Task tool returns when it only spawned the agent. */
19
+ const LAUNCH_ACK = "Async agent launched successfully";
20
+
21
+ /**
22
+ * Whether an Agent/Task tool result is a launch acknowledgement rather than the agent's
23
+ * report. Keyed off the result text, not `input.run_in_background`: that flag is optional
24
+ * (backgrounding is the default) and absent from most recorded calls, whereas the ack text
25
+ * is emitted for every async launch and never for a synchronous one.
26
+ */
27
+ export function isAsyncAgentLaunchAck(output: string | undefined): boolean {
28
+ return !!output && output.includes(LAUNCH_ACK);
29
+ }
30
+
31
+ const NOTIFICATION_RE = /<task-notification>([\s\S]*?)<\/task-notification>/g;
32
+
33
+ /** Terminal statuses reported by `<task-notification>` blocks, keyed by Agent tool_use id. */
34
+ export function parseTaskNotifications(content: string): Map<string, BackgroundAgentStatus> {
35
+ const out = new Map<string, BackgroundAgentStatus>();
36
+ if (!content.includes("<task-notification>")) return out;
37
+ for (const [, body] of content.matchAll(NOTIFICATION_RE)) {
38
+ const toolUseId = body!.match(/<tool-use-id>([\s\S]*?)<\/tool-use-id>/)?.[1]?.trim();
39
+ const status = body!.match(/<status>([\s\S]*?)<\/status>/)?.[1]?.trim();
40
+ // Orphan-scan summaries carry task ids but no tool-use-id — nothing to attach them to.
41
+ if (!toolUseId || !isTerminalAgentStatus(status)) continue;
42
+ out.set(toolUseId, status);
43
+ }
44
+ return out;
45
+ }
46
+
47
+ /** Whether a CLI-reported task status means the agent has stopped running for good. */
48
+ export function isTerminalAgentStatus(v: string | undefined): v is BackgroundAgentStatus {
49
+ return v === "completed" || v === "failed" || v === "stopped";
50
+ }
51
+
52
+ /**
53
+ * Stamp `bgStatus` onto every backgrounded Agent/Task tool_use in a loaded transcript.
54
+ *
55
+ * Notifications land in user messages that come after — sometimes many turns after — the
56
+ * message holding the tool call, so this has to run across the whole transcript rather than
57
+ * per message. Agents with no notification yet are left unstamped: the card reads that as
58
+ * still running.
59
+ */
60
+ export function applyBackgroundAgentStatus(messages: ChatMessage[]): void {
61
+ const statuses = new Map<string, BackgroundAgentStatus>();
62
+ for (const msg of messages) {
63
+ if (msg.role !== "user" || !msg.content) continue;
64
+ for (const [id, status] of parseTaskNotifications(msg.content)) statuses.set(id, status);
65
+ }
66
+ if (statuses.size === 0) return;
67
+
68
+ for (const msg of messages) {
69
+ for (const ev of msg.events ?? []) {
70
+ if (!isSubagentToolUse(ev) || !ev.toolUseId) continue;
71
+ const status = statuses.get(ev.toolUseId);
72
+ if (status) ev.bgStatus = status;
73
+ }
74
+ }
75
+ }
76
+
77
+ function isSubagentToolUse(ev: ChatEvent): ev is Extract<ChatEvent, { type: "tool_use" }> {
78
+ return ev.type === "tool_use" && (ev.tool === "Agent" || ev.tool === "Task");
79
+ }
package/src/types/api.ts CHANGED
@@ -63,6 +63,7 @@ export type ChatWsServerMessage =
63
63
  | { type: "tool_result"; output: string; isError?: boolean; toolUseId?: string; parentToolUseId?: string }
64
64
  | { type: "bash_output"; toolUseId: string; content: string; lineCount: number }
65
65
  | { type: "background_registry"; sessionId: string; shells: BackgroundShell[] }
66
+ | { type: "subagent_status"; toolUseId: string; status: import("../shared/background-agent-status").BackgroundAgentStatus }
66
67
  | { type: "approval_request"; requestId: string; tool: string; input: unknown }
67
68
  | { type: "done"; sessionId: string; contextWindowPct?: number }
68
69
  | { type: "error"; message: string }
package/src/types/chat.ts CHANGED
@@ -158,7 +158,12 @@ export type ResultSubtype =
158
158
  export type ChatEvent =
159
159
  | { type: "text"; content: string; parentToolUseId?: string }
160
160
  | { type: "thinking"; content: string; parentToolUseId?: string }
161
- | { type: "tool_use"; tool: string; input: unknown; toolUseId?: string; parentToolUseId?: string; children?: ChatEvent[] }
161
+ | {
162
+ type: "tool_use"; tool: string; input: unknown; toolUseId?: string; parentToolUseId?: string; children?: ChatEvent[];
163
+ /** Terminal state of a backgrounded Agent/Task, once its `<task-notification>` arrives.
164
+ * Absent on a launched-but-unfinished agent — the card renders that as still running. */
165
+ bgStatus?: import("../shared/background-agent-status").BackgroundAgentStatus;
166
+ }
162
167
  | { type: "tool_result"; output: string; isError?: boolean; toolUseId?: string; parentToolUseId?: string }
163
168
  | { type: "approval_request"; requestId: string; tool: string; input: unknown }
164
169
  | { type: "error"; message: string }
@@ -598,12 +598,14 @@ export function ChatHistoryBar({
598
598
  </div>
599
599
  )}
600
600
 
601
- {/* Team activity panel */}
601
+ {/* Team activity panel — its tabs each scroll on their own, so no outer scroll */}
602
602
  {activePanel === "team" && teamActivity?.hasTeams && (
603
- <div className="border-t border-border/30 bg-surface px-3 py-2 max-h-[280px] overflow-y-auto">
603
+ <div className="border-t border-border/30 bg-surface px-3 py-2">
604
604
  <TeamActivityPanel
605
605
  teamNames={teamActivity.teamNames}
606
606
  messages={teamMessages ?? []}
607
+ sessionId={sessionId}
608
+ projectName={projectName}
607
609
  />
608
610
  </div>
609
611
  )}
@@ -696,6 +696,7 @@ export function ChatTab({ metadata, tabId }: ChatTabProps) {
696
696
  {/* Input — gate on first draft load to avoid empty→filled flash, then keep mounted */}
697
697
  {(inputReady || !draftLoading) && (
698
698
  <MessageInput
699
+ tabId={tabId}
699
700
  onSend={handleInputSend}
700
701
  isStreaming={isStreaming}
701
702
  onCancel={cancelStreaming}
@@ -4,6 +4,7 @@ import { useVoiceInput } from "@/hooks/use-voice-input";
4
4
  import { api, projectUrl, getAuthToken } from "@/lib/api-client";
5
5
  import { randomId } from "@/lib/utils";
6
6
  import { ownsGlobalShortcut } from "@/lib/owns-global-shortcut";
7
+ import { SEND_TO_CHAT_EVENT, SEND_TO_CHAT_ACK_EVENT, type SendToChatDetail } from "@/lib/send-to-chat";
7
8
  import { isImageFile } from "@/lib/file-support";
8
9
  import { AttachmentChips } from "./attachment-chips";
9
10
  import { stepHistory } from "./message-history-recall";
@@ -32,6 +33,8 @@ export interface ChatAttachment {
32
33
  export type MessagePriority = 'now' | 'next' | 'later';
33
34
 
34
35
  interface MessageInputProps {
36
+ /** Tab id of the owning chat tab — addresses "Send to Chat" at this tab only. */
37
+ tabId?: string;
35
38
  onSend: (content: string, attachments: ChatAttachment[], priority?: MessagePriority) => void;
36
39
  isStreaming?: boolean;
37
40
  onCancel?: () => void;
@@ -86,6 +89,7 @@ interface MessageInputProps {
86
89
  }
87
90
 
88
91
  export const MessageInput = memo(function MessageInput({
92
+ tabId,
89
93
  onSend,
90
94
  isStreaming,
91
95
  onCancel,
@@ -231,12 +235,15 @@ export const MessageInput = memo(function MessageInput({
231
235
  return () => window.removeEventListener("toggle-voice-input", handler);
232
236
  }, [voice.supported, handleVoiceToggle, getVisibleTextarea]);
233
237
 
234
- // Listen for "Send to Chat" from terminal or other tabs — add as attachment chip
238
+ // "Send to Chat" (terminal output, other tabs) — add as an attachment chip.
239
+ // Every chat tab stays mounted, so the event is addressed: only the tab it names
240
+ // may consume it, or the same output lands in every open chat at once.
235
241
  useEffect(() => {
236
242
  const handler = (e: Event) => {
237
- const { text, label } = (e as CustomEvent).detail ?? {};
243
+ const { text, label, targetTabId } = ((e as CustomEvent).detail ?? {}) as SendToChatDetail;
238
244
  if (!text) return;
239
- window.dispatchEvent(new Event("ppm:send-to-chat:ack"));
245
+ if (targetTabId ? targetTabId !== tabId : !ownsGlobalShortcut(getVisibleTextarea())) return;
246
+ window.dispatchEvent(new Event(SEND_TO_CHAT_ACK_EVENT));
240
247
  const att: ChatAttachment = {
241
248
  id: randomId(),
242
249
  name: label ?? "Terminal output",
@@ -248,9 +255,9 @@ export const MessageInput = memo(function MessageInput({
248
255
  setAttachments((prev) => [...prev, att]);
249
256
  getVisibleTextarea()?.focus();
250
257
  };
251
- window.addEventListener("ppm:send-to-chat", handler);
252
- return () => window.removeEventListener("ppm:send-to-chat", handler);
253
- }, [getVisibleTextarea]);
258
+ window.addEventListener(SEND_TO_CHAT_EVENT, handler);
259
+ return () => window.removeEventListener(SEND_TO_CHAT_EVENT, handler);
260
+ }, [getVisibleTextarea, tabId]);
254
261
 
255
262
  // Apply initialValue when it changes (e.g. "Ask AI" from command palette).
256
263
  // A restored draft can land after the input is already on screen, so never
@@ -0,0 +1,17 @@
1
+ import { lazy, Suspense } from "react";
2
+
3
+ const MarkdownRenderer = lazy(() =>
4
+ import("@/components/shared/markdown-renderer").then((m) => ({ default: m.MarkdownRenderer }))
5
+ );
6
+
7
+ /**
8
+ * Compact, height-capped markdown for tool cards. Lazy so the markdown bundle only
9
+ * loads once a card is actually expanded.
10
+ */
11
+ export function MiniMarkdown({ content, maxHeight = "max-h-48" }: { content: string; maxHeight?: string }) {
12
+ return (
13
+ <Suspense fallback={<div className="animate-pulse h-4 bg-muted rounded" />}>
14
+ <MarkdownRenderer content={content} className={`text-text-secondary overflow-auto ${maxHeight}`} />
15
+ </Suspense>
16
+ );
17
+ }