@yancyyu/openhermit 1.5.8

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 (980) hide show
  1. package/LICENSE +611 -0
  2. package/README.md +220 -0
  3. package/bin/hermit.mjs +364 -0
  4. package/bin/kill-dev.js +20 -0
  5. package/dist-renderer/assets/01-BApSFlV4.png +0 -0
  6. package/dist-renderer/assets/02-CRQGs29u.png +0 -0
  7. package/dist-renderer/assets/03-BFCM2jnD.png +0 -0
  8. package/dist-renderer/assets/04-B2FThbKO.png +0 -0
  9. package/dist-renderer/assets/05-D9p0Znkd.png +0 -0
  10. package/dist-renderer/assets/06-DZAfbDlP.png +0 -0
  11. package/dist-renderer/assets/07-B_PXWGCc.png +0 -0
  12. package/dist-renderer/assets/08-DGRMZ6sl.png +0 -0
  13. package/dist-renderer/assets/09-SGCQvc7U.png +0 -0
  14. package/dist-renderer/assets/10-Cve81Q3W.png +0 -0
  15. package/dist-renderer/assets/11-DGglolDW.png +0 -0
  16. package/dist-renderer/assets/12-C3lnu79c.png +0 -0
  17. package/dist-renderer/assets/13-M59meqdw.png +0 -0
  18. package/dist-renderer/assets/ProjectEditorOverlay-BNoDw9T1.js +57 -0
  19. package/dist-renderer/assets/TeamGraphOverlay-CfGRKQIu.js +1 -0
  20. package/dist-renderer/assets/_basePickBy-Ct8Hm5_h.js +1 -0
  21. package/dist-renderer/assets/_baseUniq-BofrAFBx.js +1 -0
  22. package/dist-renderer/assets/apl-B4CMkyY2.js +1 -0
  23. package/dist-renderer/assets/arc-AbJgatzR.js +1 -0
  24. package/dist-renderer/assets/architectureDiagram-VXUJARFQ-gpniCJVk.js +36 -0
  25. package/dist-renderer/assets/asciiarmor-Df11BRmG.js +1 -0
  26. package/dist-renderer/assets/asn1-EdZsLKOL.js +1 -0
  27. package/dist-renderer/assets/asterisk-B-8jnY81.js +1 -0
  28. package/dist-renderer/assets/blockDiagram-VD42YOAC-aBbbmONC.js +122 -0
  29. package/dist-renderer/assets/brainfuck-C4LP7Hcl.js +1 -0
  30. package/dist-renderer/assets/c4Diagram-YG6GDRKO-DJio1IsU.js +10 -0
  31. package/dist-renderer/assets/channel-CZ8sd5Xf.js +1 -0
  32. package/dist-renderer/assets/chunk-4BX2VUAB-D1_HKao2.js +1 -0
  33. package/dist-renderer/assets/chunk-55IACEB6-NAmVxF4k.js +1 -0
  34. package/dist-renderer/assets/chunk-B4BG7PRW-Ce829laz.js +165 -0
  35. package/dist-renderer/assets/chunk-DI55MBZ5-Ct2Le12y.js +220 -0
  36. package/dist-renderer/assets/chunk-FMBD7UC4-Cie3DzKk.js +15 -0
  37. package/dist-renderer/assets/chunk-QN33PNHL-4f5Yb50e.js +1 -0
  38. package/dist-renderer/assets/chunk-QZHKN3VN-D9ranl9c.js +1 -0
  39. package/dist-renderer/assets/chunk-TZMSLE5B-bdGZWlEy.js +1 -0
  40. package/dist-renderer/assets/classDiagram-2ON5EDUG-CMcfSKj5.js +1 -0
  41. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CMcfSKj5.js +1 -0
  42. package/dist-renderer/assets/clike-B9uivgTg.js +1 -0
  43. package/dist-renderer/assets/clojure-BMjYHr_A.js +1 -0
  44. package/dist-renderer/assets/clone-CMuwA8RV.js +1 -0
  45. package/dist-renderer/assets/cmake-BQqOBYOt.js +1 -0
  46. package/dist-renderer/assets/cobol-CWcv1MsR.js +1 -0
  47. package/dist-renderer/assets/coffeescript-S37ZYGWr.js +1 -0
  48. package/dist-renderer/assets/commonlisp-DBKNyK5s.js +1 -0
  49. package/dist-renderer/assets/cose-bilkent-S5V4N54A-C6tvfcVi.js +1 -0
  50. package/dist-renderer/assets/crystal-SjHAIU92.js +1 -0
  51. package/dist-renderer/assets/css-BnMrqG3P.js +1 -0
  52. package/dist-renderer/assets/cypher-C_CwsFkJ.js +1 -0
  53. package/dist-renderer/assets/cytoscape.esm-DsxaTqgk.js +331 -0
  54. package/dist-renderer/assets/d-pRatUO7H.js +1 -0
  55. package/dist-renderer/assets/dagre-6UL2VRFP-B-4qcZam.js +4 -0
  56. package/dist-renderer/assets/defaultLocale-DX6XiGOO.js +1 -0
  57. package/dist-renderer/assets/diagram-PSM6KHXK-CwT3TLjx.js +24 -0
  58. package/dist-renderer/assets/diagram-QEK2KX5R-BWH6-ZFd.js +43 -0
  59. package/dist-renderer/assets/diagram-S2PKOQOG-DfpPnfi1.js +24 -0
  60. package/dist-renderer/assets/diff-DbItnlRl.js +1 -0
  61. package/dist-renderer/assets/dockerfile-BKs6k2Af.js +1 -0
  62. package/dist-renderer/assets/dtd-DF_7sFjM.js +1 -0
  63. package/dist-renderer/assets/dylan-DwRh75JA.js +1 -0
  64. package/dist-renderer/assets/ebnf-CDyGwa7X.js +1 -0
  65. package/dist-renderer/assets/ecl-Cabwm37j.js +1 -0
  66. package/dist-renderer/assets/eiffel-CnydiIhH.js +1 -0
  67. package/dist-renderer/assets/elm-vLlmbW-K.js +1 -0
  68. package/dist-renderer/assets/erDiagram-Q2GNP2WA-BFbEFR4x.js +60 -0
  69. package/dist-renderer/assets/erlang-BNw1qcRV.js +1 -0
  70. package/dist-renderer/assets/factor-kuTfRLto.js +1 -0
  71. package/dist-renderer/assets/favicon-B8xY-GVk.png +0 -0
  72. package/dist-renderer/assets/fcl-Kvtd6kyn.js +1 -0
  73. package/dist-renderer/assets/flowDiagram-NV44I4VS-Dg3cf5hW.js +162 -0
  74. package/dist-renderer/assets/forth-Ffai-XNe.js +1 -0
  75. package/dist-renderer/assets/fortran-DYz_wnZ1.js +1 -0
  76. package/dist-renderer/assets/ganttDiagram-JELNMOA3-B21y55W5.js +267 -0
  77. package/dist-renderer/assets/gas-Bneqetm1.js +1 -0
  78. package/dist-renderer/assets/gherkin-heZmZLOM.js +1 -0
  79. package/dist-renderer/assets/gitGraphDiagram-V2S2FVAM-BDV3BJzn.js +65 -0
  80. package/dist-renderer/assets/graph-BfaZ4hZt.js +1 -0
  81. package/dist-renderer/assets/groovy-D9Dt4D0W.js +1 -0
  82. package/dist-renderer/assets/haskell-BWDZoCOh.js +1 -0
  83. package/dist-renderer/assets/haxe-H-WmDvRZ.js +1 -0
  84. package/dist-renderer/assets/http-DBlCnlav.js +1 -0
  85. package/dist-renderer/assets/idl-BEugSyMb.js +1 -0
  86. package/dist-renderer/assets/index-BMXHMpkG.js +1 -0
  87. package/dist-renderer/assets/index-CCqtDawH.js +1 -0
  88. package/dist-renderer/assets/index-CVMSpK8C.js +1 -0
  89. package/dist-renderer/assets/index-CZltVMDP.js +1844 -0
  90. package/dist-renderer/assets/index-CaG9mf8s.css +1 -0
  91. package/dist-renderer/assets/index-Ct0-y9TF.js +1 -0
  92. package/dist-renderer/assets/index-pMg_LlsS.js +1 -0
  93. package/dist-renderer/assets/infoDiagram-HS3SLOUP-DvMlS0CL.js +2 -0
  94. package/dist-renderer/assets/init-Gi6I4Gst.js +1 -0
  95. package/dist-renderer/assets/javascript-qCveANmP.js +1 -0
  96. package/dist-renderer/assets/journeyDiagram-XKPGCS4Q-DIyMluRv.js +139 -0
  97. package/dist-renderer/assets/julia-DuME0IfC.js +1 -0
  98. package/dist-renderer/assets/kanban-definition-3W4ZIXB7-CVOx8f-7.js +89 -0
  99. package/dist-renderer/assets/katex-DGN8GczM.js +261 -0
  100. package/dist-renderer/assets/layout-BPKIXUf4.js +1 -0
  101. package/dist-renderer/assets/linear-CScZGLr2.js +1 -0
  102. package/dist-renderer/assets/livescript-BwQOo05w.js +1 -0
  103. package/dist-renderer/assets/lua-BgMRiT3U.js +1 -0
  104. package/dist-renderer/assets/mathematica-DTrFuWx2.js +1 -0
  105. package/dist-renderer/assets/mbox-CNhZ1qSd.js +1 -0
  106. package/dist-renderer/assets/mindmap-definition-VGOIOE7T-CmDQ7Wo6.js +68 -0
  107. package/dist-renderer/assets/mirc-CjQqDB4T.js +1 -0
  108. package/dist-renderer/assets/mllike-CXdrOF99.js +1 -0
  109. package/dist-renderer/assets/modelica-Dc1JOy9r.js +1 -0
  110. package/dist-renderer/assets/mscgen-BA5vi2Kp.js +1 -0
  111. package/dist-renderer/assets/mumps-BT43cFF4.js +1 -0
  112. package/dist-renderer/assets/nginx-DdIZxoE0.js +1 -0
  113. package/dist-renderer/assets/nsis-LdVXkNf5.js +1 -0
  114. package/dist-renderer/assets/ntriples-BfvgReVJ.js +1 -0
  115. package/dist-renderer/assets/octave-Ck1zUtKM.js +1 -0
  116. package/dist-renderer/assets/ordinal-Cboi1Yqb.js +1 -0
  117. package/dist-renderer/assets/oz-BzwKVEFT.js +1 -0
  118. package/dist-renderer/assets/pascal--L3eBynH.js +1 -0
  119. package/dist-renderer/assets/perl-CdXCOZ3F.js +1 -0
  120. package/dist-renderer/assets/pieDiagram-ADFJNKIX-DbVClin-.js +30 -0
  121. package/dist-renderer/assets/pig-CevX1Tat.js +1 -0
  122. package/dist-renderer/assets/powershell-CFHJl5sT.js +1 -0
  123. package/dist-renderer/assets/properties-C78fOPTZ.js +1 -0
  124. package/dist-renderer/assets/protobuf-ChK-085T.js +1 -0
  125. package/dist-renderer/assets/pug-DukmZTjD.js +1 -0
  126. package/dist-renderer/assets/puppet-DMA9R1ak.js +1 -0
  127. package/dist-renderer/assets/python-BuPzkPfP.js +1 -0
  128. package/dist-renderer/assets/q-pXgVlZs6.js +1 -0
  129. package/dist-renderer/assets/quadrantDiagram-AYHSOK5B-CAB0MYcW.js +7 -0
  130. package/dist-renderer/assets/r-DUYO_cvP.js +1 -0
  131. package/dist-renderer/assets/requirementDiagram-UZGBJVZJ-w2Lfpg3T.js +64 -0
  132. package/dist-renderer/assets/rpm-CTu-6PCP.js +1 -0
  133. package/dist-renderer/assets/ruby-B2Rjki9n.js +1 -0
  134. package/dist-renderer/assets/sankeyDiagram-TZEHDZUN-kvG1QoKY.js +10 -0
  135. package/dist-renderer/assets/sas-B4kiWyti.js +1 -0
  136. package/dist-renderer/assets/scheme-C41bIUwD.js +1 -0
  137. package/dist-renderer/assets/sequenceDiagram-WL72ISMW-DCVBQ23J.js +145 -0
  138. package/dist-renderer/assets/shell-CjFT_Tl9.js +1 -0
  139. package/dist-renderer/assets/sieve-C3Gn_uJK.js +1 -0
  140. package/dist-renderer/assets/simple-mode-GW_nhZxv.js +1 -0
  141. package/dist-renderer/assets/smalltalk-CnHTOXQT.js +1 -0
  142. package/dist-renderer/assets/solr-DehyRSwq.js +1 -0
  143. package/dist-renderer/assets/sparql-DkYu6x3z.js +1 -0
  144. package/dist-renderer/assets/splashScene-C8lWNnm4.js +1 -0
  145. package/dist-renderer/assets/spreadsheet-BCZA_wO0.js +1 -0
  146. package/dist-renderer/assets/sql-D0XecflT.js +1 -0
  147. package/dist-renderer/assets/stateDiagram-FKZM4ZOC-ItZ0JBvq.js +1 -0
  148. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-Hpmw4dMm.js +1 -0
  149. package/dist-renderer/assets/stex-C3f8Ysf7.js +1 -0
  150. package/dist-renderer/assets/stylus-B533Al4x.js +1 -0
  151. package/dist-renderer/assets/swift-BzpIVaGY.js +1 -0
  152. package/dist-renderer/assets/tcl-DVfN8rqt.js +1 -0
  153. package/dist-renderer/assets/textile-CnDTJFAw.js +1 -0
  154. package/dist-renderer/assets/tiddlywiki-DO-Gjzrf.js +1 -0
  155. package/dist-renderer/assets/tiki-DGYXhP31.js +1 -0
  156. package/dist-renderer/assets/timeline-definition-IT6M3QCI-BzSFaAjV.js +61 -0
  157. package/dist-renderer/assets/toml-Bm5Em-hy.js +1 -0
  158. package/dist-renderer/assets/treemap-GDKQZRPO-fSz4hQn0.js +162 -0
  159. package/dist-renderer/assets/troff-wAsdV37c.js +1 -0
  160. package/dist-renderer/assets/ttcn-CfJYG6tj.js +1 -0
  161. package/dist-renderer/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  162. package/dist-renderer/assets/turtle-B1tBg_DP.js +1 -0
  163. package/dist-renderer/assets/vb-CmGdzxic.js +1 -0
  164. package/dist-renderer/assets/vbscript-BuJXcnF6.js +1 -0
  165. package/dist-renderer/assets/velocity-D8B20fx6.js +1 -0
  166. package/dist-renderer/assets/verilog-C6RDOZhf.js +1 -0
  167. package/dist-renderer/assets/vhdl-lSbBsy5d.js +1 -0
  168. package/dist-renderer/assets/webidl-ZXfAyPTL.js +1 -0
  169. package/dist-renderer/assets/xquery-CQfU5ijd.js +1 -0
  170. package/dist-renderer/assets/xychartDiagram-PRI3JC2R-CT1kaGlv.js +7 -0
  171. package/dist-renderer/assets/yacas-BJ4BC0dw.js +1 -0
  172. package/dist-renderer/assets/z80-Hz9HOZM7.js +1 -0
  173. package/dist-renderer/index.html +1274 -0
  174. package/package.json +181 -0
  175. package/src/features/README.md +24 -0
  176. package/src/features/agent-graph/README.md +21 -0
  177. package/src/features/agent-graph/STABLE_SLOT_LAYOUT_PLAN.md +2846 -0
  178. package/src/features/agent-graph/core/domain/buildInlineActivityEntries.ts +416 -0
  179. package/src/features/agent-graph/core/domain/collapseOverflowStacks.ts +126 -0
  180. package/src/features/agent-graph/core/domain/graphOwnerIdentity.ts +55 -0
  181. package/src/features/agent-graph/core/domain/taskGraphSemantics.ts +48 -0
  182. package/src/features/agent-graph/renderer/adapters/TeamGraphAdapter.ts +1400 -0
  183. package/src/features/agent-graph/renderer/hooks/useGraphActivityContext.ts +34 -0
  184. package/src/features/agent-graph/renderer/hooks/useGraphCreateTaskDialog.tsx +126 -0
  185. package/src/features/agent-graph/renderer/hooks/useGraphMemberPopoverContext.ts +34 -0
  186. package/src/features/agent-graph/renderer/hooks/useGraphSidebarVisibility.ts +52 -0
  187. package/src/features/agent-graph/renderer/hooks/useTeamGraphAdapter.ts +173 -0
  188. package/src/features/agent-graph/renderer/hooks/useTeamGraphSurfaceActions.ts +98 -0
  189. package/src/features/agent-graph/renderer/index.ts +14 -0
  190. package/src/features/agent-graph/renderer/ui/GraphActivityCard.tsx +96 -0
  191. package/src/features/agent-graph/renderer/ui/GraphActivityHud.tsx +498 -0
  192. package/src/features/agent-graph/renderer/ui/GraphBlockingEdgePopover.tsx +207 -0
  193. package/src/features/agent-graph/renderer/ui/GraphNodePopover.tsx +573 -0
  194. package/src/features/agent-graph/renderer/ui/GraphProvisioningHud.tsx +113 -0
  195. package/src/features/agent-graph/renderer/ui/GraphTaskCard.tsx +149 -0
  196. package/src/features/agent-graph/renderer/ui/GraphTransientHandoffHud.tsx +176 -0
  197. package/src/features/agent-graph/renderer/ui/TeamGraphOverlay.tsx +224 -0
  198. package/src/features/agent-graph/renderer/ui/TeamGraphTab.tsx +257 -0
  199. package/src/features/agent-graph/renderer/ui/buildTransientHandoffMessage.ts +70 -0
  200. package/src/features/recent-projects/contracts/api.ts +5 -0
  201. package/src/features/recent-projects/contracts/channels.ts +2 -0
  202. package/src/features/recent-projects/contracts/dto.ts +24 -0
  203. package/src/features/recent-projects/contracts/index.ts +4 -0
  204. package/src/features/recent-projects/contracts/normalize.ts +32 -0
  205. package/src/features/recent-projects/core/application/models/ListDashboardRecentProjectsResponse.ts +6 -0
  206. package/src/features/recent-projects/core/application/ports/ClockPort.ts +3 -0
  207. package/src/features/recent-projects/core/application/ports/ListDashboardRecentProjectsOutputPort.ts +5 -0
  208. package/src/features/recent-projects/core/application/ports/LoggerPort.ts +5 -0
  209. package/src/features/recent-projects/core/application/ports/RecentProjectsCachePort.ts +5 -0
  210. package/src/features/recent-projects/core/application/ports/RecentProjectsSourcePort.ts +14 -0
  211. package/src/features/recent-projects/core/application/use-cases/ListDashboardRecentProjectsUseCase.ts +191 -0
  212. package/src/features/recent-projects/core/domain/models/ProviderId.ts +1 -0
  213. package/src/features/recent-projects/core/domain/models/RecentProjectAggregate.ts +14 -0
  214. package/src/features/recent-projects/core/domain/models/RecentProjectCandidate.ts +14 -0
  215. package/src/features/recent-projects/core/domain/models/RecentProjectOpenTarget.ts +3 -0
  216. package/src/features/recent-projects/core/domain/policies/mergeRecentProjectCandidates.ts +88 -0
  217. package/src/features/recent-projects/main/adapters/input/http/registerRecentProjectsHttp.ts +30 -0
  218. package/src/features/recent-projects/main/adapters/output/presenters/DashboardRecentProjectsPresenter.ts +27 -0
  219. package/src/features/recent-projects/main/adapters/output/sources/ClaudeRecentProjectsSourceAdapter.ts +91 -0
  220. package/src/features/recent-projects/main/adapters/output/sources/CodexRecentProjectsSourceAdapter.ts +326 -0
  221. package/src/features/recent-projects/main/composition/createRecentProjectsFeature.ts +43 -0
  222. package/src/features/recent-projects/main/index.ts +3 -0
  223. package/src/features/recent-projects/main/infrastructure/cache/InMemoryRecentProjectsCache.ts +34 -0
  224. package/src/features/recent-projects/main/infrastructure/codex/CodexAppServerClient.ts +116 -0
  225. package/src/features/recent-projects/main/infrastructure/identity/RecentProjectIdentityResolver.ts +20 -0
  226. package/src/features/recent-projects/main/infrastructure/identity/normalizeIdentityPath.ts +10 -0
  227. package/src/features/recent-projects/renderer/adapters/RecentProjectsSectionAdapter.ts +132 -0
  228. package/src/features/recent-projects/renderer/hooks/useOpenRecentProject.ts +143 -0
  229. package/src/features/recent-projects/renderer/hooks/useRecentProjectsSection.ts +289 -0
  230. package/src/features/recent-projects/renderer/index.ts +2 -0
  231. package/src/features/recent-projects/renderer/ui/RecentProjectCard.tsx +221 -0
  232. package/src/features/recent-projects/renderer/ui/RecentProjectsSection.tsx +167 -0
  233. package/src/features/recent-projects/renderer/utils/activeProjectTeams.ts +48 -0
  234. package/src/features/recent-projects/renderer/utils/navigation.ts +65 -0
  235. package/src/features/recent-projects/renderer/utils/projectDecorations.ts +11 -0
  236. package/src/features/recent-projects/renderer/utils/recentProjectOpenHistory.ts +268 -0
  237. package/src/features/recent-projects/renderer/utils/recentProjectsClientCache.ts +78 -0
  238. package/src/main/constants/messageTags.ts +46 -0
  239. package/src/main/constants/worktreePatterns.ts +47 -0
  240. package/src/main/server.ts +3705 -0
  241. package/src/main/services/UpdateService.ts +166 -0
  242. package/src/main/services/ccConnect/CcConnectBridge.ts +313 -0
  243. package/src/main/services/ccConnect/CcConnectClient.ts +397 -0
  244. package/src/main/services/ccConnect/MessageBridge.ts +162 -0
  245. package/src/main/services/ccConnect/ProjectMappingStore.ts +148 -0
  246. package/src/main/services/ccConnect/index.ts +8 -0
  247. package/src/main/services/teams-mvp/TeamProvisioningService.ts +275 -0
  248. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +404 -0
  249. package/src/main/services/teams-mvp/index.ts +26 -0
  250. package/src/main/types/chunks.ts +506 -0
  251. package/src/main/types/domain.ts +342 -0
  252. package/src/main/types/index.ts +24 -0
  253. package/src/main/types/jsonl.ts +355 -0
  254. package/src/main/types/messages.ts +395 -0
  255. package/src/renderer/App.tsx +287 -0
  256. package/src/renderer/api/httpClient.ts +2207 -0
  257. package/src/renderer/api/index.ts +19 -0
  258. package/src/renderer/api/providers.ts +77 -0
  259. package/src/renderer/assets/participant-avatars/01.png +0 -0
  260. package/src/renderer/assets/participant-avatars/02.png +0 -0
  261. package/src/renderer/assets/participant-avatars/03.png +0 -0
  262. package/src/renderer/assets/participant-avatars/04.png +0 -0
  263. package/src/renderer/assets/participant-avatars/05.png +0 -0
  264. package/src/renderer/assets/participant-avatars/06.png +0 -0
  265. package/src/renderer/assets/participant-avatars/07.png +0 -0
  266. package/src/renderer/assets/participant-avatars/08.png +0 -0
  267. package/src/renderer/assets/participant-avatars/09.png +0 -0
  268. package/src/renderer/assets/participant-avatars/10.png +0 -0
  269. package/src/renderer/assets/participant-avatars/11.png +0 -0
  270. package/src/renderer/assets/participant-avatars/12.png +0 -0
  271. package/src/renderer/assets/participant-avatars/13.png +0 -0
  272. package/src/renderer/components/chat/AIChatGroup.tsx +519 -0
  273. package/src/renderer/components/chat/ChatHistory.tsx +1115 -0
  274. package/src/renderer/components/chat/ChatHistoryEmptyState.tsx +15 -0
  275. package/src/renderer/components/chat/ChatHistoryItem.tsx +144 -0
  276. package/src/renderer/components/chat/ChatHistoryLoadingState.tsx +45 -0
  277. package/src/renderer/components/chat/CompactBoundary.tsx +169 -0
  278. package/src/renderer/components/chat/ContextBadge.tsx +582 -0
  279. package/src/renderer/components/chat/DisplayItemList.tsx +431 -0
  280. package/src/renderer/components/chat/LastOutputDisplay.tsx +259 -0
  281. package/src/renderer/components/chat/SessionContextPanel/DirectoryTree/DirectoryTreeNode.tsx +125 -0
  282. package/src/renderer/components/chat/SessionContextPanel/DirectoryTree/buildDirectoryTree.ts +47 -0
  283. package/src/renderer/components/chat/SessionContextPanel/DirectoryTree/types.ts +12 -0
  284. package/src/renderer/components/chat/SessionContextPanel/components/ClaudeMdFilesSection.tsx +90 -0
  285. package/src/renderer/components/chat/SessionContextPanel/components/ClaudeMdSection.tsx +86 -0
  286. package/src/renderer/components/chat/SessionContextPanel/components/CollapsibleSection.tsx +77 -0
  287. package/src/renderer/components/chat/SessionContextPanel/components/FlatInjectionList.tsx +248 -0
  288. package/src/renderer/components/chat/SessionContextPanel/components/MentionedFilesSection.tsx +50 -0
  289. package/src/renderer/components/chat/SessionContextPanel/components/RankedInjectionList.tsx +284 -0
  290. package/src/renderer/components/chat/SessionContextPanel/components/SessionContextHeader.tsx +290 -0
  291. package/src/renderer/components/chat/SessionContextPanel/components/SessionContextHelpTooltip.tsx +165 -0
  292. package/src/renderer/components/chat/SessionContextPanel/components/TaskCoordinationSection.tsx +47 -0
  293. package/src/renderer/components/chat/SessionContextPanel/components/ThinkingTextSection.tsx +47 -0
  294. package/src/renderer/components/chat/SessionContextPanel/components/ToolOutputsSection.tsx +47 -0
  295. package/src/renderer/components/chat/SessionContextPanel/components/UserMessagesSection.tsx +47 -0
  296. package/src/renderer/components/chat/SessionContextPanel/index.tsx +314 -0
  297. package/src/renderer/components/chat/SessionContextPanel/items/ClaudeMdItem.tsx +76 -0
  298. package/src/renderer/components/chat/SessionContextPanel/items/MentionedFileItem.tsx +91 -0
  299. package/src/renderer/components/chat/SessionContextPanel/items/TaskCoordinationItem.tsx +116 -0
  300. package/src/renderer/components/chat/SessionContextPanel/items/ThinkingTextItem.tsx +96 -0
  301. package/src/renderer/components/chat/SessionContextPanel/items/ToolBreakdownItem.tsx +38 -0
  302. package/src/renderer/components/chat/SessionContextPanel/items/ToolOutputItem.tsx +113 -0
  303. package/src/renderer/components/chat/SessionContextPanel/items/UserMessageItem.tsx +69 -0
  304. package/src/renderer/components/chat/SessionContextPanel/types.ts +96 -0
  305. package/src/renderer/components/chat/SessionContextPanel/utils/formatting.ts +6 -0
  306. package/src/renderer/components/chat/SessionContextPanel/utils/pathParsing.ts +23 -0
  307. package/src/renderer/components/chat/SystemChatGroup.tsx +60 -0
  308. package/src/renderer/components/chat/UserChatGroup.tsx +668 -0
  309. package/src/renderer/components/chat/items/BaseItem.tsx +213 -0
  310. package/src/renderer/components/chat/items/ExecutionTrace.tsx +279 -0
  311. package/src/renderer/components/chat/items/LinkedToolItem.tsx +235 -0
  312. package/src/renderer/components/chat/items/MetricsPill.tsx +215 -0
  313. package/src/renderer/components/chat/items/SlashItem.tsx +81 -0
  314. package/src/renderer/components/chat/items/SubagentItem.tsx +592 -0
  315. package/src/renderer/components/chat/items/TeammateMessageItem.tsx +261 -0
  316. package/src/renderer/components/chat/items/TextItem.tsx +82 -0
  317. package/src/renderer/components/chat/items/ThinkingItem.tsx +82 -0
  318. package/src/renderer/components/chat/items/baseItemHelpers.ts +42 -0
  319. package/src/renderer/components/chat/items/linkedTool/CollapsibleOutputSection.tsx +57 -0
  320. package/src/renderer/components/chat/items/linkedTool/DefaultToolViewer.tsx +56 -0
  321. package/src/renderer/components/chat/items/linkedTool/EditToolViewer.tsx +74 -0
  322. package/src/renderer/components/chat/items/linkedTool/ReadToolViewer.tsx +102 -0
  323. package/src/renderer/components/chat/items/linkedTool/SkillToolViewer.tsx +67 -0
  324. package/src/renderer/components/chat/items/linkedTool/ToolErrorDisplay.tsx +43 -0
  325. package/src/renderer/components/chat/items/linkedTool/WriteToolViewer.tsx +66 -0
  326. package/src/renderer/components/chat/items/linkedTool/index.ts +13 -0
  327. package/src/renderer/components/chat/items/linkedTool/renderHelpers.tsx +259 -0
  328. package/src/renderer/components/chat/markdownComponents.tsx +257 -0
  329. package/src/renderer/components/chat/markdownCopyUtils.ts +18 -0
  330. package/src/renderer/components/chat/searchHighlightUtils.ts +166 -0
  331. package/src/renderer/components/chat/viewers/CodeBlockViewer.tsx +244 -0
  332. package/src/renderer/components/chat/viewers/DiffViewer.tsx +459 -0
  333. package/src/renderer/components/chat/viewers/FileLink.tsx +182 -0
  334. package/src/renderer/components/chat/viewers/MarkdownViewer.tsx +1093 -0
  335. package/src/renderer/components/chat/viewers/MermaidDiagram.tsx +116 -0
  336. package/src/renderer/components/chat/viewers/index.ts +3 -0
  337. package/src/renderer/components/chat/viewers/syntaxHighlighter.ts +583 -0
  338. package/src/renderer/components/common/AppLogo.tsx +61 -0
  339. package/src/renderer/components/common/CliInstallWarningBanner.tsx +57 -0
  340. package/src/renderer/components/common/ConfirmDialog.tsx +176 -0
  341. package/src/renderer/components/common/ConnectionStatusBadge.tsx +56 -0
  342. package/src/renderer/components/common/ContextSwitchOverlay.tsx +38 -0
  343. package/src/renderer/components/common/CopyButton.tsx +85 -0
  344. package/src/renderer/components/common/CopyablePath.tsx +68 -0
  345. package/src/renderer/components/common/ErrorBoundary.tsx +211 -0
  346. package/src/renderer/components/common/ExportDropdown.tsx +142 -0
  347. package/src/renderer/components/common/FileTree.tsx +182 -0
  348. package/src/renderer/components/common/GlobalProviderStatusHeader.tsx +316 -0
  349. package/src/renderer/components/common/OngoingIndicator.tsx +67 -0
  350. package/src/renderer/components/common/ProviderBrandLogo.tsx +206 -0
  351. package/src/renderer/components/common/RepositoryDropdown.tsx +230 -0
  352. package/src/renderer/components/common/TokenUsageDisplay.tsx +581 -0
  353. package/src/renderer/components/common/WarningBanner.tsx +25 -0
  354. package/src/renderer/components/common/WorkspaceIndicator.tsx +183 -0
  355. package/src/renderer/components/common/WorktreeBadge.tsx +123 -0
  356. package/src/renderer/components/dashboard/CliStatusBanner.tsx +1845 -0
  357. package/src/renderer/components/dashboard/DashboardView.tsx +274 -0
  358. package/src/renderer/components/extensions/ExtensionStoreView.tsx +591 -0
  359. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +52 -0
  360. package/src/renderer/components/extensions/apikeys/ApiKeyCard.tsx +143 -0
  361. package/src/renderer/components/extensions/apikeys/ApiKeyFormDialog.tsx +282 -0
  362. package/src/renderer/components/extensions/apikeys/ApiKeysPanel.tsx +280 -0
  363. package/src/renderer/components/extensions/common/InstallButton.tsx +186 -0
  364. package/src/renderer/components/extensions/common/InstallCountBadge.tsx +21 -0
  365. package/src/renderer/components/extensions/common/SearchInput.tsx +70 -0
  366. package/src/renderer/components/extensions/common/SourceBadge.tsx +31 -0
  367. package/src/renderer/components/extensions/mcp/CustomMcpServerDialog.tsx +560 -0
  368. package/src/renderer/components/extensions/mcp/McpServerCard.tsx +314 -0
  369. package/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +669 -0
  370. package/src/renderer/components/extensions/mcp/McpServersPanel.tsx +543 -0
  371. package/src/renderer/components/extensions/plugins/CapabilityChips.tsx +70 -0
  372. package/src/renderer/components/extensions/plugins/CategoryChips.tsx +67 -0
  373. package/src/renderer/components/extensions/plugins/PluginCard.tsx +146 -0
  374. package/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx +270 -0
  375. package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +436 -0
  376. package/src/renderer/components/extensions/skills/SkillCodeEditor.tsx +117 -0
  377. package/src/renderer/components/extensions/skills/SkillDetailDialog.tsx +372 -0
  378. package/src/renderer/components/extensions/skills/SkillEditorDialog.tsx +856 -0
  379. package/src/renderer/components/extensions/skills/SkillImportDialog.tsx +343 -0
  380. package/src/renderer/components/extensions/skills/SkillReviewDialog.tsx +166 -0
  381. package/src/renderer/components/extensions/skills/SkillsPanel.tsx +784 -0
  382. package/src/renderer/components/extensions/skills/skillDraftUtils.ts +234 -0
  383. package/src/renderer/components/extensions/skills/skillFolderNameUtils.ts +19 -0
  384. package/src/renderer/components/extensions/skills/skillProjectUtils.ts +13 -0
  385. package/src/renderer/components/extensions/skills/skillValidationUtils.ts +31 -0
  386. package/src/renderer/components/layout/MiddlePanel.tsx +18 -0
  387. package/src/renderer/components/layout/MoreMenu.tsx +243 -0
  388. package/src/renderer/components/layout/PaneContainer.tsx +27 -0
  389. package/src/renderer/components/layout/PaneContent.tsx +84 -0
  390. package/src/renderer/components/layout/PaneResizeHandle.tsx +85 -0
  391. package/src/renderer/components/layout/PaneSplitDropZone.tsx +54 -0
  392. package/src/renderer/components/layout/PaneView.tsx +75 -0
  393. package/src/renderer/components/layout/SessionTabContent.tsx +102 -0
  394. package/src/renderer/components/layout/Sidebar.tsx +205 -0
  395. package/src/renderer/components/layout/SortableTab.tsx +261 -0
  396. package/src/renderer/components/layout/TabBar.tsx +354 -0
  397. package/src/renderer/components/layout/TabBarActions.tsx +176 -0
  398. package/src/renderer/components/layout/TabBarRow.tsx +99 -0
  399. package/src/renderer/components/layout/TabContextMenu.tsx +171 -0
  400. package/src/renderer/components/layout/TabbedLayout.tsx +186 -0
  401. package/src/renderer/components/layout/TeamTabSectionNav.tsx +146 -0
  402. package/src/renderer/components/notifications/NotificationRow.tsx +228 -0
  403. package/src/renderer/components/notifications/NotificationsView.tsx +371 -0
  404. package/src/renderer/components/report/AssessmentBadge.tsx +78 -0
  405. package/src/renderer/components/report/ReportSection.tsx +58 -0
  406. package/src/renderer/components/report/SessionReportTab.tsx +102 -0
  407. package/src/renderer/components/report/sections/CostSection.tsx +259 -0
  408. package/src/renderer/components/report/sections/ErrorSection.tsx +100 -0
  409. package/src/renderer/components/report/sections/FrictionSection.tsx +91 -0
  410. package/src/renderer/components/report/sections/GitSection.tsx +72 -0
  411. package/src/renderer/components/report/sections/InsightsSection.tsx +207 -0
  412. package/src/renderer/components/report/sections/KeyTakeawaysSection.tsx +55 -0
  413. package/src/renderer/components/report/sections/OverviewSection.tsx +64 -0
  414. package/src/renderer/components/report/sections/QualitySection.tsx +151 -0
  415. package/src/renderer/components/report/sections/SubagentSection.tsx +88 -0
  416. package/src/renderer/components/report/sections/TimelineSection.tsx +111 -0
  417. package/src/renderer/components/report/sections/TokenSection.tsx +116 -0
  418. package/src/renderer/components/report/sections/ToolSection.tsx +77 -0
  419. package/src/renderer/components/runtime/ProviderModelBadges.tsx +142 -0
  420. package/src/renderer/components/runtime/ProviderRuntimeBackendSelector.tsx +327 -0
  421. package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +288 -0
  422. package/src/renderer/components/runtime/providerConnectionUi.ts +408 -0
  423. package/src/renderer/components/schedules/SchedulesView.tsx +529 -0
  424. package/src/renderer/components/search/CommandPalette.tsx +610 -0
  425. package/src/renderer/components/search/SearchBar.tsx +171 -0
  426. package/src/renderer/components/settings/NotificationTriggerSettings/components/AddTriggerForm.tsx +233 -0
  427. package/src/renderer/components/settings/NotificationTriggerSettings/components/ColorPaletteSelector.tsx +144 -0
  428. package/src/renderer/components/settings/NotificationTriggerSettings/components/DynamicConfigSection.tsx +189 -0
  429. package/src/renderer/components/settings/NotificationTriggerSettings/components/GeneralInfoSection.tsx +68 -0
  430. package/src/renderer/components/settings/NotificationTriggerSettings/components/IgnorePatternsSection.tsx +73 -0
  431. package/src/renderer/components/settings/NotificationTriggerSettings/components/ModeSelector.tsx +45 -0
  432. package/src/renderer/components/settings/NotificationTriggerSettings/components/RepositoryScopeSection.tsx +63 -0
  433. package/src/renderer/components/settings/NotificationTriggerSettings/components/SectionHeader.tsx +15 -0
  434. package/src/renderer/components/settings/NotificationTriggerSettings/components/TriggerCard.tsx +150 -0
  435. package/src/renderer/components/settings/NotificationTriggerSettings/components/TriggerCardHeader.tsx +125 -0
  436. package/src/renderer/components/settings/NotificationTriggerSettings/components/TriggerConfiguration.tsx +342 -0
  437. package/src/renderer/components/settings/NotificationTriggerSettings/components/TriggerPreview.tsx +108 -0
  438. package/src/renderer/components/settings/NotificationTriggerSettings/hooks/useAddTriggerFormHandlers.ts +218 -0
  439. package/src/renderer/components/settings/NotificationTriggerSettings/hooks/useAddTriggerFormState.ts +135 -0
  440. package/src/renderer/components/settings/NotificationTriggerSettings/hooks/useRepositoryLookup.ts +47 -0
  441. package/src/renderer/components/settings/NotificationTriggerSettings/hooks/useTriggerCardState.ts +281 -0
  442. package/src/renderer/components/settings/NotificationTriggerSettings/hooks/useTriggerForm.ts +185 -0
  443. package/src/renderer/components/settings/NotificationTriggerSettings/index.tsx +87 -0
  444. package/src/renderer/components/settings/NotificationTriggerSettings/types.ts +39 -0
  445. package/src/renderer/components/settings/NotificationTriggerSettings/utils/constants.ts +50 -0
  446. package/src/renderer/components/settings/NotificationTriggerSettings/utils/trigger.ts +113 -0
  447. package/src/renderer/components/settings/SettingsTabs.tsx +110 -0
  448. package/src/renderer/components/settings/SettingsView.tsx +153 -0
  449. package/src/renderer/components/settings/components/SettingRow.tsx +44 -0
  450. package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +24 -0
  451. package/src/renderer/components/settings/components/SettingsSelect.tsx +100 -0
  452. package/src/renderer/components/settings/components/SettingsToggle.tsx +45 -0
  453. package/src/renderer/components/settings/components/index.ts +8 -0
  454. package/src/renderer/components/settings/hooks/index.ts +6 -0
  455. package/src/renderer/components/settings/hooks/useSettingsConfig.ts +270 -0
  456. package/src/renderer/components/settings/hooks/useSettingsHandlers.ts +468 -0
  457. package/src/renderer/components/settings/sections/AdvancedSection.tsx +234 -0
  458. package/src/renderer/components/settings/sections/CliStatusSection.tsx +930 -0
  459. package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +391 -0
  460. package/src/renderer/components/settings/sections/GeneralSection.tsx +665 -0
  461. package/src/renderer/components/settings/sections/HarnessSection.tsx +133 -0
  462. package/src/renderer/components/settings/sections/PlatformsSection.tsx +517 -0
  463. package/src/renderer/components/settings/sections/index.ts +8 -0
  464. package/src/renderer/components/sidebar/DateGroupedSessions.tsx +1115 -0
  465. package/src/renderer/components/sidebar/GlobalTaskList.tsx +853 -0
  466. package/src/renderer/components/sidebar/SessionContextMenu.tsx +182 -0
  467. package/src/renderer/components/sidebar/SessionFiltersPopover.tsx +115 -0
  468. package/src/renderer/components/sidebar/SessionItem.tsx +393 -0
  469. package/src/renderer/components/sidebar/SidebarSessions.tsx +542 -0
  470. package/src/renderer/components/sidebar/SidebarTaskItem.tsx +286 -0
  471. package/src/renderer/components/sidebar/TaskContextMenu.tsx +86 -0
  472. package/src/renderer/components/sidebar/TaskFiltersPopover.tsx +203 -0
  473. package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +370 -0
  474. package/src/renderer/components/sidebar/dateGroupedSessionsSelection.ts +33 -0
  475. package/src/renderer/components/sidebar/projectGroupPagination.ts +89 -0
  476. package/src/renderer/components/sidebar/taskFiltersState.ts +82 -0
  477. package/src/renderer/components/splash/splashScene.ts +979 -0
  478. package/src/renderer/components/team/CcSessionsSection.tsx +202 -0
  479. package/src/renderer/components/team/ClaudeLogsDialog.tsx +71 -0
  480. package/src/renderer/components/team/ClaudeLogsFilterPopover.tsx +213 -0
  481. package/src/renderer/components/team/ClaudeLogsPanel.tsx +170 -0
  482. package/src/renderer/components/team/ClaudeLogsSection.tsx +154 -0
  483. package/src/renderer/components/team/CliLogsRichView.tsx +640 -0
  484. package/src/renderer/components/team/CollapsibleTeamSection.tsx +177 -0
  485. package/src/renderer/components/team/HarnessCards.ts +38 -0
  486. package/src/renderer/components/team/MemberBadge.tsx +117 -0
  487. package/src/renderer/components/team/ProcessesSection.tsx +193 -0
  488. package/src/renderer/components/team/ProvisioningProgressBlock.tsx +389 -0
  489. package/src/renderer/components/team/RoleSelect.tsx +171 -0
  490. package/src/renderer/components/team/StepProgressBar.tsx +165 -0
  491. package/src/renderer/components/team/TaskTooltip.tsx +197 -0
  492. package/src/renderer/components/team/TeamDetailView.tsx +3002 -0
  493. package/src/renderer/components/team/TeamEmptyState.tsx +102 -0
  494. package/src/renderer/components/team/TeamListFilterPopover.tsx +183 -0
  495. package/src/renderer/components/team/TeamListView.tsx +1336 -0
  496. package/src/renderer/components/team/TeamProvisioningBanner.tsx +16 -0
  497. package/src/renderer/components/team/TeamProvisioningPanel.tsx +115 -0
  498. package/src/renderer/components/team/TeamSessionsSection.tsx +267 -0
  499. package/src/renderer/components/team/ToolApprovalDiffPreview.tsx +206 -0
  500. package/src/renderer/components/team/ToolApprovalSheet.tsx +675 -0
  501. package/src/renderer/components/team/UnreadCommentsBadge.tsx +37 -0
  502. package/src/renderer/components/team/activity/ActiveTasksBlock.tsx +191 -0
  503. package/src/renderer/components/team/activity/ActivityItem.tsx +1649 -0
  504. package/src/renderer/components/team/activity/ActivityTimeline.tsx +959 -0
  505. package/src/renderer/components/team/activity/AnimatedHeightReveal.tsx +117 -0
  506. package/src/renderer/components/team/activity/LeadThoughtsGroup.tsx +1152 -0
  507. package/src/renderer/components/team/activity/MessageExpandDialog.tsx +213 -0
  508. package/src/renderer/components/team/activity/PendingRepliesBlock.tsx +275 -0
  509. package/src/renderer/components/team/activity/ReplyQuoteBlock.tsx +79 -0
  510. package/src/renderer/components/team/activity/ThoughtBodyContent.tsx +150 -0
  511. package/src/renderer/components/team/activity/activityMarkdown.ts +36 -0
  512. package/src/renderer/components/team/activity/activityMessageContext.ts +68 -0
  513. package/src/renderer/components/team/activity/collapseState.ts +66 -0
  514. package/src/renderer/components/team/activity/useNewItemKeys.ts +70 -0
  515. package/src/renderer/components/team/attachments/AttachmentDisplay.tsx +132 -0
  516. package/src/renderer/components/team/attachments/AttachmentPreviewItem.tsx +62 -0
  517. package/src/renderer/components/team/attachments/AttachmentPreviewList.tsx +193 -0
  518. package/src/renderer/components/team/attachments/AttachmentThumbnail.tsx +42 -0
  519. package/src/renderer/components/team/attachments/DropZoneOverlay.tsx +54 -0
  520. package/src/renderer/components/team/attachments/ImageLightbox.tsx +132 -0
  521. package/src/renderer/components/team/attachments/SourceMessageAttachments.tsx +70 -0
  522. package/src/renderer/components/team/dialogs/AddMemberDialog.tsx +222 -0
  523. package/src/renderer/components/team/dialogs/AdvancedCliSection.tsx +347 -0
  524. package/src/renderer/components/team/dialogs/AnthropicFastModeSelector.tsx +120 -0
  525. package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +489 -0
  526. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +484 -0
  527. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +448 -0
  528. package/src/renderer/components/team/dialogs/EffortLevelSelector.tsx +69 -0
  529. package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +165 -0
  530. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +2859 -0
  531. package/src/renderer/components/team/dialogs/LimitContextCheckbox.tsx +57 -0
  532. package/src/renderer/components/team/dialogs/MembersJsonEditor.tsx +123 -0
  533. package/src/renderer/components/team/dialogs/OptionalSettingsSection.tsx +124 -0
  534. package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +145 -0
  535. package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +289 -0
  536. package/src/renderer/components/team/dialogs/ProjectPathSelector.tsx +330 -0
  537. package/src/renderer/components/team/dialogs/ProvisioningProviderStatusList.tsx +744 -0
  538. package/src/renderer/components/team/dialogs/ReviewDialog.tsx +130 -0
  539. package/src/renderer/components/team/dialogs/SendMessageDialog.tsx +530 -0
  540. package/src/renderer/components/team/dialogs/SkipPermissionsCheckbox.tsx +62 -0
  541. package/src/renderer/components/team/dialogs/StatusHistoryTimeline.tsx +229 -0
  542. package/src/renderer/components/team/dialogs/TaskAttachments.tsx +394 -0
  543. package/src/renderer/components/team/dialogs/TaskCommentAwaitingReply.tsx +57 -0
  544. package/src/renderer/components/team/dialogs/TaskCommentInput.tsx +420 -0
  545. package/src/renderer/components/team/dialogs/TaskCommentsSection.tsx +620 -0
  546. package/src/renderer/components/team/dialogs/TaskDetailDialog.tsx +1480 -0
  547. package/src/renderer/components/team/dialogs/TeamModelSelector.tsx +560 -0
  548. package/src/renderer/components/team/dialogs/TeammateRuntimeCompatibilityNotice.tsx +60 -0
  549. package/src/renderer/components/team/dialogs/ToolApprovalSettingsPanel.tsx +173 -0
  550. package/src/renderer/components/team/dialogs/editTeamRuntimeChanges.ts +179 -0
  551. package/src/renderer/components/team/dialogs/globalTaskDetailDialogLoading.ts +34 -0
  552. package/src/renderer/components/team/dialogs/launchDialogPrefill.ts +125 -0
  553. package/src/renderer/components/team/dialogs/memberModelScope.ts +77 -0
  554. package/src/renderer/components/team/dialogs/platformMeta.ts +118 -0
  555. package/src/renderer/components/team/dialogs/projectPathOptions.ts +50 -0
  556. package/src/renderer/components/team/dialogs/providerPrepareDiagnostics.ts +222 -0
  557. package/src/renderer/components/team/dialogs/providerPrepareRequestSignature.ts +122 -0
  558. package/src/renderer/components/team/dialogs/provisioningMemberScope.ts +10 -0
  559. package/src/renderer/components/team/dialogs/provisioningModelIssues.ts +124 -0
  560. package/src/renderer/components/team/dialogs/teamNameSets.ts +67 -0
  561. package/src/renderer/components/team/dialogs/teamRelaunchFlow.ts +30 -0
  562. package/src/renderer/components/team/dialogs/teammateLaunchMode.ts +49 -0
  563. package/src/renderer/components/team/dialogs/teammateRuntimeCompatibility.tsx +101 -0
  564. package/src/renderer/components/team/editor/CodeMirrorEditor.tsx +506 -0
  565. package/src/renderer/components/team/editor/EditorBinaryPlaceholder.tsx +43 -0
  566. package/src/renderer/components/team/editor/EditorBinaryState.tsx +29 -0
  567. package/src/renderer/components/team/editor/EditorBreadcrumb.tsx +84 -0
  568. package/src/renderer/components/team/editor/EditorContextMenu.tsx +213 -0
  569. package/src/renderer/components/team/editor/EditorEmptyState.tsx +35 -0
  570. package/src/renderer/components/team/editor/EditorErrorBoundary.tsx +63 -0
  571. package/src/renderer/components/team/editor/EditorErrorState.tsx +41 -0
  572. package/src/renderer/components/team/editor/EditorFileTree.tsx +903 -0
  573. package/src/renderer/components/team/editor/EditorImagePreview.tsx +138 -0
  574. package/src/renderer/components/team/editor/EditorSearchPanel.tsx +508 -0
  575. package/src/renderer/components/team/editor/EditorSelectionMenu.tsx +112 -0
  576. package/src/renderer/components/team/editor/EditorShortcutsHelp.tsx +125 -0
  577. package/src/renderer/components/team/editor/EditorStatusBar.tsx +72 -0
  578. package/src/renderer/components/team/editor/EditorTabBar.tsx +265 -0
  579. package/src/renderer/components/team/editor/EditorTabContextMenu.tsx +88 -0
  580. package/src/renderer/components/team/editor/EditorToolbar.tsx +163 -0
  581. package/src/renderer/components/team/editor/FileIcon.tsx +66 -0
  582. package/src/renderer/components/team/editor/GitStatusBadge.tsx +47 -0
  583. package/src/renderer/components/team/editor/GoToLineDialog.tsx +186 -0
  584. package/src/renderer/components/team/editor/MarkdownPreviewPane.tsx +57 -0
  585. package/src/renderer/components/team/editor/MarkdownSplitView.tsx +127 -0
  586. package/src/renderer/components/team/editor/NewFileDialog.tsx +131 -0
  587. package/src/renderer/components/team/editor/ProjectEditorOverlay.tsx +924 -0
  588. package/src/renderer/components/team/editor/QuickOpenDialog.tsx +163 -0
  589. package/src/renderer/components/team/editor/SearchInFilesPanel.tsx +358 -0
  590. package/src/renderer/components/team/editor/fileIcons.ts +222 -0
  591. package/src/renderer/components/team/kanban/KanbanBoard.tsx +664 -0
  592. package/src/renderer/components/team/kanban/KanbanColumn.tsx +61 -0
  593. package/src/renderer/components/team/kanban/KanbanFilterPopover.tsx +210 -0
  594. package/src/renderer/components/team/kanban/KanbanGridLayout.tsx +460 -0
  595. package/src/renderer/components/team/kanban/KanbanSearchInput.tsx +284 -0
  596. package/src/renderer/components/team/kanban/KanbanSortPopover.tsx +140 -0
  597. package/src/renderer/components/team/kanban/KanbanTaskCard.test.tsx +199 -0
  598. package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +446 -0
  599. package/src/renderer/components/team/kanban/TrashDialog.tsx +112 -0
  600. package/src/renderer/components/team/members/CurrentTaskIndicator.tsx +56 -0
  601. package/src/renderer/components/team/members/LeadModelRow.test.tsx +133 -0
  602. package/src/renderer/components/team/members/LeadModelRow.tsx +183 -0
  603. package/src/renderer/components/team/members/MemberCard.tsx +665 -0
  604. package/src/renderer/components/team/members/MemberDetailDialog.tsx +309 -0
  605. package/src/renderer/components/team/members/MemberDetailHeader.tsx +183 -0
  606. package/src/renderer/components/team/members/MemberDetailStats.tsx +80 -0
  607. package/src/renderer/components/team/members/MemberDraftRow.test.tsx +184 -0
  608. package/src/renderer/components/team/members/MemberDraftRow.tsx +515 -0
  609. package/src/renderer/components/team/members/MemberExecutionLog.tsx +224 -0
  610. package/src/renderer/components/team/members/MemberHoverCard.tsx +292 -0
  611. package/src/renderer/components/team/members/MemberLaunchDiagnosticsButton.tsx +60 -0
  612. package/src/renderer/components/team/members/MemberList.tsx +405 -0
  613. package/src/renderer/components/team/members/MemberLogsTab.tsx +958 -0
  614. package/src/renderer/components/team/members/MemberMessagesTab.tsx +251 -0
  615. package/src/renderer/components/team/members/MemberPresenceDot.tsx +28 -0
  616. package/src/renderer/components/team/members/MemberRoleEditor.tsx +84 -0
  617. package/src/renderer/components/team/members/MemberStatsTab.tsx +299 -0
  618. package/src/renderer/components/team/members/MemberTasksTab.tsx +87 -0
  619. package/src/renderer/components/team/members/MemberWorkspaceTab.tsx +141 -0
  620. package/src/renderer/components/team/members/MembersEditorSection.tsx +495 -0
  621. package/src/renderer/components/team/members/SubagentRecentMessagesPreview.tsx +125 -0
  622. package/src/renderer/components/team/members/TeamRosterEditorSection.tsx +153 -0
  623. package/src/renderer/components/team/members/memberActivityEntries.ts +42 -0
  624. package/src/renderer/components/team/members/memberDetailTypes.ts +3 -0
  625. package/src/renderer/components/team/members/memberNameSets.ts +65 -0
  626. package/src/renderer/components/team/members/membersEditorTypes.ts +21 -0
  627. package/src/renderer/components/team/members/membersEditorUtils.ts +267 -0
  628. package/src/renderer/components/team/messages/MessageComposer.tsx +939 -0
  629. package/src/renderer/components/team/messages/MessagesFilterPopover.tsx +228 -0
  630. package/src/renderer/components/team/messages/MessagesPanel.tsx +1508 -0
  631. package/src/renderer/components/team/messages/OpenCodeDeliveryWarning.tsx +151 -0
  632. package/src/renderer/components/team/messages/StatusBlock.tsx +126 -0
  633. package/src/renderer/components/team/provisioningSteps.ts +363 -0
  634. package/src/renderer/components/team/review/ChangeReviewDialog.tsx +133 -0
  635. package/src/renderer/components/team/schedule/CcCronScheduleDialog.tsx +218 -0
  636. package/src/renderer/components/team/schedule/CronScheduleInput.tsx +254 -0
  637. package/src/renderer/components/team/schedule/ScheduleEmptyState.tsx +15 -0
  638. package/src/renderer/components/team/schedule/ScheduleRunLogDialog.tsx +277 -0
  639. package/src/renderer/components/team/schedule/ScheduleRunRow.tsx +106 -0
  640. package/src/renderer/components/team/schedule/ScheduleSection.tsx +281 -0
  641. package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +55 -0
  642. package/src/renderer/components/team/sidebar/TeamSidebarHost.tsx +76 -0
  643. package/src/renderer/components/team/sidebar/TeamSidebarPortalManager.ts +173 -0
  644. package/src/renderer/components/team/sidebar/TeamSidebarPortalSource.tsx +66 -0
  645. package/src/renderer/components/team/sidebar/TeamSidebarRail.tsx +68 -0
  646. package/src/renderer/components/team/sidebar/teamSidebarUiState.ts +136 -0
  647. package/src/renderer/components/team/taskLogs/ExactTaskLogCard.tsx +132 -0
  648. package/src/renderer/components/team/taskLogs/ExactTaskLogsSection.tsx +258 -0
  649. package/src/renderer/components/team/taskLogs/ExecutionSessionsSection.tsx +48 -0
  650. package/src/renderer/components/team/taskLogs/TaskActivityLinkedToolCard.tsx +31 -0
  651. package/src/renderer/components/team/taskLogs/TaskActivitySection.tsx +462 -0
  652. package/src/renderer/components/team/taskLogs/TaskLogStreamSection.tsx +375 -0
  653. package/src/renderer/components/team/taskLogs/TaskLogsPanel.tsx +294 -0
  654. package/src/renderer/components/team/taskLogs/featureGates.ts +22 -0
  655. package/src/renderer/components/team/tasks/TaskList.tsx +111 -0
  656. package/src/renderer/components/team/tasks/TaskRow.tsx +65 -0
  657. package/src/renderer/components/team/teamProjectSelection.ts +156 -0
  658. package/src/renderer/components/team/teamSessionFetchGuards.ts +26 -0
  659. package/src/renderer/components/team/useClaudeLogsController.ts +668 -0
  660. package/src/renderer/components/team/useTeamProvisioningPresentation.ts +54 -0
  661. package/src/renderer/components/terminal/TerminalLogPanel.tsx +37 -0
  662. package/src/renderer/components/ui/ChipInteractionLayer.tsx +255 -0
  663. package/src/renderer/components/ui/CodeChipBadge.tsx +37 -0
  664. package/src/renderer/components/ui/ExpandableContent.tsx +110 -0
  665. package/src/renderer/components/ui/MemberSelect.tsx +209 -0
  666. package/src/renderer/components/ui/MentionInteractionLayer.tsx +121 -0
  667. package/src/renderer/components/ui/MentionSuggestionList.tsx +274 -0
  668. package/src/renderer/components/ui/MentionableTextarea.tsx +1426 -0
  669. package/src/renderer/components/ui/SlashCommandInteractionLayer.tsx +88 -0
  670. package/src/renderer/components/ui/TaskReferenceInteractionLayer.tsx +101 -0
  671. package/src/renderer/components/ui/UrlInteractionLayer.tsx +102 -0
  672. package/src/renderer/components/ui/alert-dialog.tsx +127 -0
  673. package/src/renderer/components/ui/auto-resize-textarea.tsx +93 -0
  674. package/src/renderer/components/ui/badge.tsx +37 -0
  675. package/src/renderer/components/ui/button.tsx +54 -0
  676. package/src/renderer/components/ui/checkbox.tsx +29 -0
  677. package/src/renderer/components/ui/combobox.tsx +168 -0
  678. package/src/renderer/components/ui/context-menu.tsx +124 -0
  679. package/src/renderer/components/ui/dialog.tsx +114 -0
  680. package/src/renderer/components/ui/hover-card.tsx +30 -0
  681. package/src/renderer/components/ui/input.tsx +22 -0
  682. package/src/renderer/components/ui/label.tsx +21 -0
  683. package/src/renderer/components/ui/popover.tsx +31 -0
  684. package/src/renderer/components/ui/select.tsx +150 -0
  685. package/src/renderer/components/ui/tabs.tsx +52 -0
  686. package/src/renderer/components/ui/textarea.tsx +21 -0
  687. package/src/renderer/components/ui/tiptap/TiptapBubbleMenu.tsx +75 -0
  688. package/src/renderer/components/ui/tiptap/TiptapEditor.tsx +73 -0
  689. package/src/renderer/components/ui/tiptap/TiptapToolbar.tsx +269 -0
  690. package/src/renderer/components/ui/tiptap/index.ts +3 -0
  691. package/src/renderer/components/ui/tiptap/presets.ts +46 -0
  692. package/src/renderer/components/ui/tiptap/tiptapStyles.css +235 -0
  693. package/src/renderer/components/ui/tiptap/types.ts +32 -0
  694. package/src/renderer/components/ui/tiptap/useTiptapEditor.ts +94 -0
  695. package/src/renderer/components/ui/tooltip.tsx +32 -0
  696. package/src/renderer/constants/cssVariables.ts +226 -0
  697. package/src/renderer/constants/layout.ts +6 -0
  698. package/src/renderer/constants/teamColors.ts +397 -0
  699. package/src/renderer/constants/teamRoles.ts +41 -0
  700. package/src/renderer/contexts/TabUIContext.tsx +51 -0
  701. package/src/renderer/contexts/useTabUIContext.ts +18 -0
  702. package/src/renderer/favicon.png +0 -0
  703. package/src/renderer/features/CLAUDE.md +19 -0
  704. package/src/renderer/hooks/navigation/utils.ts +263 -0
  705. package/src/renderer/hooks/useAttachments.ts +312 -0
  706. package/src/renderer/hooks/useAutoScrollBottom.ts +285 -0
  707. package/src/renderer/hooks/useBranchSync.ts +105 -0
  708. package/src/renderer/hooks/useChipDraftPersistence.ts +172 -0
  709. package/src/renderer/hooks/useCliInstaller.ts +106 -0
  710. package/src/renderer/hooks/useCollapsedGroups.ts +71 -0
  711. package/src/renderer/hooks/useComposerDraft.ts +504 -0
  712. package/src/renderer/hooks/useContinuousScrollNav.ts +50 -0
  713. package/src/renderer/hooks/useCreateTeamDraft.ts +280 -0
  714. package/src/renderer/hooks/useDraftPersistence.ts +140 -0
  715. package/src/renderer/hooks/useEditorKeyboardShortcuts.ts +257 -0
  716. package/src/renderer/hooks/useEffectiveCliProviderStatus.ts +66 -0
  717. package/src/renderer/hooks/useExtensionsTabState.ts +206 -0
  718. package/src/renderer/hooks/useFileListCacheWarmer.ts +38 -0
  719. package/src/renderer/hooks/useFileSuggestions.ts +255 -0
  720. package/src/renderer/hooks/useKeyboardShortcuts.ts +363 -0
  721. package/src/renderer/hooks/useLazyFileContent.ts +150 -0
  722. package/src/renderer/hooks/useMarkCommentsRead.ts +27 -0
  723. package/src/renderer/hooks/useMarkdownScrollSync.ts +158 -0
  724. package/src/renderer/hooks/useMemberStats.ts +45 -0
  725. package/src/renderer/hooks/useMentionDetection.ts +375 -0
  726. package/src/renderer/hooks/usePersistedGridLayout.ts +109 -0
  727. package/src/renderer/hooks/useResizableColumns.ts +140 -0
  728. package/src/renderer/hooks/useResizablePanel.ts +144 -0
  729. package/src/renderer/hooks/useStableTeamMentionMeta.ts +68 -0
  730. package/src/renderer/hooks/useSyncedAnimationStyle.ts +29 -0
  731. package/src/renderer/hooks/useTabNavigationController.ts +524 -0
  732. package/src/renderer/hooks/useTabUI.ts +252 -0
  733. package/src/renderer/hooks/useTaskLocalState.ts +163 -0
  734. package/src/renderer/hooks/useTaskSuggestions.ts +131 -0
  735. package/src/renderer/hooks/useTeamMessagesExpanded.ts +34 -0
  736. package/src/renderer/hooks/useTeamMessagesRead.ts +52 -0
  737. package/src/renderer/hooks/useTeamSuggestions.ts +78 -0
  738. package/src/renderer/hooks/useTheme.ts +138 -0
  739. package/src/renderer/hooks/useToolApprovalDiff.ts +212 -0
  740. package/src/renderer/hooks/useUnreadCommentCount.ts +14 -0
  741. package/src/renderer/hooks/useViewedFiles.ts +74 -0
  742. package/src/renderer/hooks/useViewportCommentRead.ts +147 -0
  743. package/src/renderer/hooks/useViewportObserver.ts +138 -0
  744. package/src/renderer/hooks/useVisibleAIGroup.ts +122 -0
  745. package/src/renderer/hooks/useVisibleFileSection.ts +114 -0
  746. package/src/renderer/hooks/useZoomFactor.ts +36 -0
  747. package/src/renderer/index.css +1560 -0
  748. package/src/renderer/index.html +1293 -0
  749. package/src/renderer/lib/utils.ts +6 -0
  750. package/src/renderer/main.tsx +30 -0
  751. package/src/renderer/sentry.ts +104 -0
  752. package/src/renderer/services/__tests__/createTeamPreferences.test.ts +67 -0
  753. package/src/renderer/services/commentReadStorage.ts +349 -0
  754. package/src/renderer/services/composerDraftStorage.ts +271 -0
  755. package/src/renderer/services/contextStorage.ts +201 -0
  756. package/src/renderer/services/createTeamDraftStorage.ts +151 -0
  757. package/src/renderer/services/createTeamPreferences.ts +361 -0
  758. package/src/renderer/services/dashboardCliStatusBannerPreference.ts +20 -0
  759. package/src/renderer/services/draftStorage.ts +128 -0
  760. package/src/renderer/services/layout-system/BrowserGridLayoutRepository.ts +111 -0
  761. package/src/renderer/services/layout-system/GridLayoutRepository.ts +8 -0
  762. package/src/renderer/services/layout-system/gridLayoutSchema.ts +137 -0
  763. package/src/renderer/services/layout-system/gridLayoutTypes.ts +17 -0
  764. package/src/renderer/store/index.ts +1556 -0
  765. package/src/renderer/store/slices/changeReviewSlice.ts +1694 -0
  766. package/src/renderer/store/slices/cliInstallerSlice.ts +689 -0
  767. package/src/renderer/store/slices/configSlice.ts +111 -0
  768. package/src/renderer/store/slices/connectionSlice.ts +221 -0
  769. package/src/renderer/store/slices/contextSlice.ts +394 -0
  770. package/src/renderer/store/slices/conversationSlice.ts +510 -0
  771. package/src/renderer/store/slices/editorSlice.ts +1455 -0
  772. package/src/renderer/store/slices/extensionsSlice.ts +1415 -0
  773. package/src/renderer/store/slices/notificationSlice.ts +277 -0
  774. package/src/renderer/store/slices/paneSlice.ts +357 -0
  775. package/src/renderer/store/slices/projectSlice.ts +70 -0
  776. package/src/renderer/store/slices/repositorySlice.ts +165 -0
  777. package/src/renderer/store/slices/scheduleSlice.ts +246 -0
  778. package/src/renderer/store/slices/sessionDetailSlice.ts +755 -0
  779. package/src/renderer/store/slices/sessionSlice.ts +539 -0
  780. package/src/renderer/store/slices/subagentSlice.ts +145 -0
  781. package/src/renderer/store/slices/tabSlice.ts +842 -0
  782. package/src/renderer/store/slices/tabUISlice.ts +319 -0
  783. package/src/renderer/store/slices/teamSlice.ts +5080 -0
  784. package/src/renderer/store/slices/uiSlice.ts +45 -0
  785. package/src/renderer/store/types.ts +103 -0
  786. package/src/renderer/store/utils/paneHelpers.ts +134 -0
  787. package/src/renderer/store/utils/pathResolution.ts +121 -0
  788. package/src/renderer/store/utils/stateResetHelpers.ts +72 -0
  789. package/src/renderer/types/api.ts +8 -0
  790. package/src/renderer/types/claudeMd.ts +74 -0
  791. package/src/renderer/types/contextInjection.ts +309 -0
  792. package/src/renderer/types/data.ts +144 -0
  793. package/src/renderer/types/groups.ts +406 -0
  794. package/src/renderer/types/inlineChip.ts +110 -0
  795. package/src/renderer/types/mention.ts +38 -0
  796. package/src/renderer/types/notifications.ts +18 -0
  797. package/src/renderer/types/panes.ts +35 -0
  798. package/src/renderer/types/sessionReport.ts +386 -0
  799. package/src/renderer/types/tabs.ts +249 -0
  800. package/src/renderer/types/teamMessagesPanelMode.ts +1 -0
  801. package/src/renderer/utils/__tests__/teamEffortOptions.test.ts +217 -0
  802. package/src/renderer/utils/__tests__/teamModelAvailability.codexCatalog.test.ts +383 -0
  803. package/src/renderer/utils/agentMessageFormatting.ts +139 -0
  804. package/src/renderer/utils/aiGroupEnhancer.ts +78 -0
  805. package/src/renderer/utils/aiGroupHelpers.ts +208 -0
  806. package/src/renderer/utils/attachmentUtils.ts +60 -0
  807. package/src/renderer/utils/bootstrapPromptSanitizer.ts +225 -0
  808. package/src/renderer/utils/bugReportUtils.ts +157 -0
  809. package/src/renderer/utils/buildSelectionAction.ts +116 -0
  810. package/src/renderer/utils/chipUtils.ts +372 -0
  811. package/src/renderer/utils/claudeCodeOnlyProviders.ts +126 -0
  812. package/src/renderer/utils/claudeMdTracker.ts +644 -0
  813. package/src/renderer/utils/codemirrorLanguages.ts +141 -0
  814. package/src/renderer/utils/codemirrorSelectionInfo.ts +41 -0
  815. package/src/renderer/utils/codemirrorTheme.ts +138 -0
  816. package/src/renderer/utils/contextMath.ts +55 -0
  817. package/src/renderer/utils/contextTracker.ts +1100 -0
  818. package/src/renderer/utils/crossTeamPendingReplies.ts +92 -0
  819. package/src/renderer/utils/dateGrouping.ts +91 -0
  820. package/src/renderer/utils/diffViewedStorage.ts +120 -0
  821. package/src/renderer/utils/displayItemBuilder.ts +587 -0
  822. package/src/renderer/utils/displaySummary.ts +74 -0
  823. package/src/renderer/utils/editorBridge.ts +90 -0
  824. package/src/renderer/utils/fileTreeBuilder.ts +110 -0
  825. package/src/renderer/utils/formatAgentRole.ts +24 -0
  826. package/src/renderer/utils/formatters.ts +61 -0
  827. package/src/renderer/utils/groupTransformer.ts +744 -0
  828. package/src/renderer/utils/idleNotificationSemantics.ts +76 -0
  829. package/src/renderer/utils/keyboardUtils.ts +92 -0
  830. package/src/renderer/utils/lastOutputDetector.ts +150 -0
  831. package/src/renderer/utils/markdownPlugins.ts +60 -0
  832. package/src/renderer/utils/memberAvatarCatalog.ts +38 -0
  833. package/src/renderer/utils/memberHelpers.ts +858 -0
  834. package/src/renderer/utils/memberLaunchDiagnostics.ts +216 -0
  835. package/src/renderer/utils/memberRuntimeSummary.ts +122 -0
  836. package/src/renderer/utils/memberSpawnStatusPolling.ts +29 -0
  837. package/src/renderer/utils/mentionLinkify.ts +90 -0
  838. package/src/renderer/utils/mentionSuggestions.ts +34 -0
  839. package/src/renderer/utils/mergeTeamMessages.ts +27 -0
  840. package/src/renderer/utils/messageRenderEquality.ts +158 -0
  841. package/src/renderer/utils/modelExtractor.ts +90 -0
  842. package/src/renderer/utils/multimodelProviderVisibility.ts +32 -0
  843. package/src/renderer/utils/openCodeModelRecommendations.ts +1326 -0
  844. package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +79 -0
  845. package/src/renderer/utils/pathDisplay.ts +149 -0
  846. package/src/renderer/utils/pathNormalize.ts +61 -0
  847. package/src/renderer/utils/pathUtils.ts +47 -0
  848. package/src/renderer/utils/platformKeys.ts +24 -0
  849. package/src/renderer/utils/previewRegistry.ts +45 -0
  850. package/src/renderer/utils/projectColor.ts +54 -0
  851. package/src/renderer/utils/projectLookup.ts +64 -0
  852. package/src/renderer/utils/providerBackendIdentity.ts +43 -0
  853. package/src/renderer/utils/providerSlashCommands.ts +122 -0
  854. package/src/renderer/utils/quickOpenCache.ts +40 -0
  855. package/src/renderer/utils/refreshCliStatus.ts +17 -0
  856. package/src/renderer/utils/reportAssessments.ts +555 -0
  857. package/src/renderer/utils/reviewDecisionScope.ts +81 -0
  858. package/src/renderer/utils/reviewKey.ts +132 -0
  859. package/src/renderer/utils/runtimeDisplayName.ts +26 -0
  860. package/src/renderer/utils/scheduleFormatters.ts +45 -0
  861. package/src/renderer/utils/sessionAnalyzer.ts +1346 -0
  862. package/src/renderer/utils/sessionExporter.ts +427 -0
  863. package/src/renderer/utils/sessionTitleParser.ts +69 -0
  864. package/src/renderer/utils/skillCommandSuggestions.ts +77 -0
  865. package/src/renderer/utils/slashCommandExtractor.ts +154 -0
  866. package/src/renderer/utils/streamJsonParser.ts +393 -0
  867. package/src/renderer/utils/stringUtils.ts +50 -0
  868. package/src/renderer/utils/syntaxHighlighter.ts +158 -0
  869. package/src/renderer/utils/tabLabelDisambiguation.ts +99 -0
  870. package/src/renderer/utils/taskChangePresence.ts +19 -0
  871. package/src/renderer/utils/taskChangeRequest.ts +122 -0
  872. package/src/renderer/utils/taskCommentPendingReply.ts +74 -0
  873. package/src/renderer/utils/taskGrouping.ts +151 -0
  874. package/src/renderer/utils/taskReferenceUtils.ts +331 -0
  875. package/src/renderer/utils/teamEffortOptions.ts +150 -0
  876. package/src/renderer/utils/teamLaunchSummaryCopy.ts +17 -0
  877. package/src/renderer/utils/teamMessageExpandStorage.ts +39 -0
  878. package/src/renderer/utils/teamMessageFiltering.ts +95 -0
  879. package/src/renderer/utils/teamMessageKey.ts +14 -0
  880. package/src/renderer/utils/teamMessageReadStorage.ts +49 -0
  881. package/src/renderer/utils/teamModelAvailability.ts +465 -0
  882. package/src/renderer/utils/teamModelCatalog.ts +502 -0
  883. package/src/renderer/utils/teamModelContext.ts +34 -0
  884. package/src/renderer/utils/teamProvisioningPresentation.ts +772 -0
  885. package/src/renderer/utils/teamRuntimeSummary.ts +53 -0
  886. package/src/renderer/utils/toolLinkingEngine.ts +117 -0
  887. package/src/renderer/utils/toolRendering/index.ts +14 -0
  888. package/src/renderer/utils/toolRendering/toolContentChecks.ts +58 -0
  889. package/src/renderer/utils/toolRendering/toolSummaryHelpers.ts +276 -0
  890. package/src/renderer/utils/toolRendering/toolTokens.ts +57 -0
  891. package/src/renderer/utils/unwrapIpc.ts +31 -0
  892. package/src/renderer/utils/urlMatchUtils.ts +45 -0
  893. package/src/renderer/vite-env.d.ts +21 -0
  894. package/src/shared/constants/agentBlocks.ts +129 -0
  895. package/src/shared/constants/attachments.ts +175 -0
  896. package/src/shared/constants/cache.ts +12 -0
  897. package/src/shared/constants/cli.ts +15 -0
  898. package/src/shared/constants/crossTeam.ts +126 -0
  899. package/src/shared/constants/index.ts +15 -0
  900. package/src/shared/constants/kanban.ts +9 -0
  901. package/src/shared/constants/memberColors.ts +140 -0
  902. package/src/shared/constants/opencodeTaskLogAttribution.ts +1 -0
  903. package/src/shared/constants/teamLimits.ts +2 -0
  904. package/src/shared/constants/trafficLights.ts +60 -0
  905. package/src/shared/constants/triggerColors.ts +126 -0
  906. package/src/shared/constants/window.ts +12 -0
  907. package/src/shared/types/api.ts +1062 -0
  908. package/src/shared/types/ccConnect.ts +399 -0
  909. package/src/shared/types/cliInstaller.ts +335 -0
  910. package/src/shared/types/editor.ts +279 -0
  911. package/src/shared/types/extensions/api.ts +90 -0
  912. package/src/shared/types/extensions/apikey.ts +40 -0
  913. package/src/shared/types/extensions/common.ts +16 -0
  914. package/src/shared/types/extensions/index.ts +67 -0
  915. package/src/shared/types/extensions/mcp.ts +132 -0
  916. package/src/shared/types/extensions/plugin.ts +85 -0
  917. package/src/shared/types/extensions/skill.ts +173 -0
  918. package/src/shared/types/index.ts +48 -0
  919. package/src/shared/types/ipc.ts +5 -0
  920. package/src/shared/types/notifications.ts +407 -0
  921. package/src/shared/types/providers.ts +116 -0
  922. package/src/shared/types/review.ts +319 -0
  923. package/src/shared/types/schedule.ts +124 -0
  924. package/src/shared/types/team.ts +1726 -0
  925. package/src/shared/types/terminal.ts +49 -0
  926. package/src/shared/types/visualization.ts +60 -0
  927. package/src/shared/utils/__tests__/contextMetrics.test.ts +260 -0
  928. package/src/shared/utils/__tests__/ephemeralProjectPath.test.ts +42 -0
  929. package/src/shared/utils/__tests__/teamProvider.test.ts +29 -0
  930. package/src/shared/utils/agentLanguage.ts +122 -0
  931. package/src/shared/utils/anthropicLaunchModel.ts +96 -0
  932. package/src/shared/utils/anthropicModelDefaults.ts +3 -0
  933. package/src/shared/utils/apiErrorDetector.ts +13 -0
  934. package/src/shared/utils/boardTaskActivityLabels.ts +128 -0
  935. package/src/shared/utils/boardTaskActivityPresentation.ts +75 -0
  936. package/src/shared/utils/cliArgsParser.ts +129 -0
  937. package/src/shared/utils/contentSanitizer.ts +207 -0
  938. package/src/shared/utils/contextMetrics.ts +236 -0
  939. package/src/shared/utils/costFormatting.ts +45 -0
  940. package/src/shared/utils/diffContextHash.ts +22 -0
  941. package/src/shared/utils/effortLevels.ts +73 -0
  942. package/src/shared/utils/ephemeralProjectPath.ts +41 -0
  943. package/src/shared/utils/errorHandling.ts +26 -0
  944. package/src/shared/utils/extensionNormalizers.ts +336 -0
  945. package/src/shared/utils/idleNotificationSemantics.ts +86 -0
  946. package/src/shared/utils/inboxNoise.ts +158 -0
  947. package/src/shared/utils/leadDetection.ts +63 -0
  948. package/src/shared/utils/logger.ts +69 -0
  949. package/src/shared/utils/markdownTextSearch.ts +210 -0
  950. package/src/shared/utils/mcpScopes.ts +36 -0
  951. package/src/shared/utils/modelParser.ts +158 -0
  952. package/src/shared/utils/opencodeModelRef.ts +78 -0
  953. package/src/shared/utils/platformPath.ts +103 -0
  954. package/src/shared/utils/pricing.ts +129 -0
  955. package/src/shared/utils/providerBackend.ts +90 -0
  956. package/src/shared/utils/providerExtensionCapabilities.ts +92 -0
  957. package/src/shared/utils/providerModelSelection.ts +5 -0
  958. package/src/shared/utils/providerModelVisibility.ts +47 -0
  959. package/src/shared/utils/rateLimitDetector.ts +334 -0
  960. package/src/shared/utils/reviewState.ts +74 -0
  961. package/src/shared/utils/sentryConfig.ts +26 -0
  962. package/src/shared/utils/skillRoots.ts +93 -0
  963. package/src/shared/utils/slashCommands.ts +128 -0
  964. package/src/shared/utils/taskChangePresence.ts +35 -0
  965. package/src/shared/utils/taskChangeSince.ts +51 -0
  966. package/src/shared/utils/taskChangeState.ts +49 -0
  967. package/src/shared/utils/taskHistory.ts +82 -0
  968. package/src/shared/utils/taskIdentity.ts +32 -0
  969. package/src/shared/utils/teamGraphDefaultLayout.ts +97 -0
  970. package/src/shared/utils/teamMemberColors.ts +107 -0
  971. package/src/shared/utils/teamMemberName.ts +77 -0
  972. package/src/shared/utils/teamProvider.ts +73 -0
  973. package/src/shared/utils/teamStableOwnerId.ts +12 -0
  974. package/src/shared/utils/teammateMessageParser.ts +52 -0
  975. package/src/shared/utils/tokenFormatting.ts +91 -0
  976. package/src/shared/utils/toolSummary.ts +279 -0
  977. package/src/shared/utils/version.ts +29 -0
  978. package/src/types/agent-teams-controller.d.ts +163 -0
  979. package/src/types/node-pty.d.ts +22 -0
  980. package/src/types/pidusage.d.ts +23 -0
@@ -0,0 +1,1426 @@
1
+ import * as React from 'react';
2
+
3
+ import { PROSE_LINK } from '@renderer/constants/cssVariables';
4
+ import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors';
5
+ import { useFileSuggestions } from '@renderer/hooks/useFileSuggestions';
6
+ import { useMentionDetection } from '@renderer/hooks/useMentionDetection';
7
+ import { useTheme } from '@renderer/hooks/useTheme';
8
+ import { cn } from '@renderer/lib/utils';
9
+ import { chipToken } from '@renderer/types/inlineChip';
10
+ import {
11
+ createChipFromSelection,
12
+ findChipBoundary,
13
+ reconcileChips,
14
+ removeChipTokenFromText,
15
+ } from '@renderer/utils/chipUtils';
16
+ import {
17
+ doesSuggestionMatchQuery,
18
+ getSuggestionInsertionText,
19
+ } from '@renderer/utils/mentionSuggestions';
20
+ import { nameColorSet } from '@renderer/utils/projectColor';
21
+ import { findTaskReferenceMatches } from '@renderer/utils/taskReferenceUtils';
22
+ import {
23
+ findUrlBoundary,
24
+ findUrlMatches,
25
+ removeUrlMatchFromText,
26
+ } from '@renderer/utils/urlMatchUtils';
27
+ import { getKnownSlashCommand, parseStandaloneSlashCommand } from '@shared/utils/slashCommands';
28
+
29
+ import { AutoResizeTextarea } from './auto-resize-textarea';
30
+ import { ChipInteractionLayer } from './ChipInteractionLayer';
31
+ import { CodeChipBadge } from './CodeChipBadge';
32
+ import { MentionInteractionLayer } from './MentionInteractionLayer';
33
+ import { MentionSuggestionList } from './MentionSuggestionList';
34
+ import { SlashCommandInteractionLayer } from './SlashCommandInteractionLayer';
35
+ import { TaskReferenceInteractionLayer } from './TaskReferenceInteractionLayer';
36
+ import { UrlInteractionLayer } from './UrlInteractionLayer';
37
+
38
+ import type { AutoResizeTextareaProps } from './auto-resize-textarea';
39
+ import type { InlineChip } from '@renderer/types/inlineChip';
40
+ import type { MentionSuggestion } from '@renderer/types/mention';
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Segment types
44
+ // ---------------------------------------------------------------------------
45
+
46
+ interface TextSegment {
47
+ type: 'text';
48
+ value: string;
49
+ }
50
+
51
+ interface MentionSegment {
52
+ type: 'mention';
53
+ value: string;
54
+ suggestion: MentionSuggestion;
55
+ }
56
+
57
+ interface TaskSegment {
58
+ type: 'task';
59
+ value: string;
60
+ suggestion: MentionSuggestion;
61
+ encoded: boolean;
62
+ /** Zero-width metadata chars rendered in backdrop for caret alignment */
63
+ hiddenSuffix?: string;
64
+ }
65
+
66
+ interface UrlSegment {
67
+ type: 'url';
68
+ value: string;
69
+ }
70
+
71
+ interface ChipSegment {
72
+ type: 'chip';
73
+ value: string;
74
+ chip: InlineChip;
75
+ }
76
+
77
+ interface SlashCommandSegment {
78
+ type: 'slash_command';
79
+ value: string;
80
+ known: boolean;
81
+ }
82
+
83
+ type Segment =
84
+ | TextSegment
85
+ | MentionSegment
86
+ | TaskSegment
87
+ | UrlSegment
88
+ | ChipSegment
89
+ | SlashCommandSegment;
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Mention segment parsing (splits text into plain text + @mention segments)
93
+ // ---------------------------------------------------------------------------
94
+
95
+ /**
96
+ * Splits text into alternating text / @mention segments.
97
+ *
98
+ * Rules:
99
+ * - `@` must be at start of text or preceded by whitespace
100
+ * - The name after `@` must exactly match a suggestion name (case-insensitive)
101
+ * - The character after the name must be whitespace, punctuation, or end-of-text
102
+ * - Longer names are tried first (greedy matching)
103
+ */
104
+ function parseMentionSegments(text: string, suggestions: MentionSuggestion[]): Segment[] {
105
+ if (!text || suggestions.length === 0) return [{ type: 'text', value: text }];
106
+
107
+ // Sort by name length descending for greedy matching
108
+ const sorted = [...suggestions]
109
+ .filter((suggestion) => suggestion.type !== 'task')
110
+ .sort((a, b) => b.name.length - a.name.length);
111
+
112
+ const segments: Segment[] = [];
113
+ let i = 0;
114
+ let textStart = 0;
115
+
116
+ while (i < text.length) {
117
+ if (text[i] !== '@') {
118
+ i++;
119
+ continue;
120
+ }
121
+
122
+ // @ must be at start or after whitespace
123
+ if (i > 0) {
124
+ const ch = text[i - 1];
125
+ if (ch !== ' ' && ch !== '\t' && ch !== '\n' && ch !== '\r') {
126
+ i++;
127
+ continue;
128
+ }
129
+ }
130
+
131
+ let matched = false;
132
+ for (const suggestion of sorted) {
133
+ const insertionText = getSuggestionInsertionText(suggestion);
134
+ const end = i + 1 + insertionText.length;
135
+ if (end > text.length) continue;
136
+ if (text.slice(i + 1, end).toLowerCase() !== insertionText.toLowerCase()) continue;
137
+
138
+ // Character after name must be boundary
139
+ if (end < text.length) {
140
+ const after = text[end];
141
+ // eslint-disable-next-line no-useless-escape -- escaped chars needed for regex character class
142
+ if (!/[\s,.:;!?\)\]\}\-]/.test(after)) continue;
143
+ }
144
+
145
+ // Flush preceding text
146
+ if (i > textStart) {
147
+ segments.push({ type: 'text', value: text.slice(textStart, i) });
148
+ }
149
+
150
+ segments.push({ type: 'mention', value: text.slice(i, end), suggestion });
151
+ i = end;
152
+ textStart = i;
153
+ matched = true;
154
+ break;
155
+ }
156
+
157
+ if (!matched) i++;
158
+ }
159
+
160
+ if (textStart < text.length) {
161
+ segments.push({ type: 'text', value: text.slice(textStart) });
162
+ }
163
+
164
+ return segments;
165
+ }
166
+
167
+ function parseSuggestionSegments(
168
+ text: string,
169
+ mentionSuggestions: MentionSuggestion[],
170
+ taskSuggestions: MentionSuggestion[]
171
+ ): Segment[] {
172
+ if (!text) return [{ type: 'text', value: text }];
173
+
174
+ const urlMatches = findUrlMatches(text);
175
+ if (urlMatches.length > 0) {
176
+ const segments: Segment[] = [];
177
+ let lastEnd = 0;
178
+
179
+ for (const match of urlMatches) {
180
+ if (match.start > lastEnd) {
181
+ segments.push(
182
+ ...parseSuggestionSegments(
183
+ text.slice(lastEnd, match.start),
184
+ mentionSuggestions,
185
+ taskSuggestions
186
+ )
187
+ );
188
+ }
189
+ segments.push({
190
+ type: 'url',
191
+ value: match.value,
192
+ });
193
+ lastEnd = match.end;
194
+ }
195
+
196
+ if (lastEnd < text.length) {
197
+ segments.push(
198
+ ...parseSuggestionSegments(text.slice(lastEnd), mentionSuggestions, taskSuggestions)
199
+ );
200
+ }
201
+
202
+ return segments;
203
+ }
204
+
205
+ const taskMatches = findTaskReferenceMatches(text, taskSuggestions);
206
+ if (taskMatches.length === 0) {
207
+ return parseMentionSegments(text, mentionSuggestions);
208
+ }
209
+
210
+ const segments: Segment[] = [];
211
+ let lastEnd = 0;
212
+
213
+ for (const match of taskMatches) {
214
+ if (match.start > lastEnd) {
215
+ segments.push(...parseMentionSegments(text.slice(lastEnd, match.start), mentionSuggestions));
216
+ }
217
+ // Compute hidden suffix: zero-width metadata chars between visible text and match.end
218
+ const visibleEnd = match.start + match.raw.length;
219
+ const hiddenSuffix =
220
+ match.encoded && match.end > visibleEnd ? text.slice(visibleEnd, match.end) : undefined;
221
+ segments.push({
222
+ type: 'task',
223
+ value: match.raw,
224
+ suggestion: match.suggestion,
225
+ encoded: match.encoded,
226
+ hiddenSuffix,
227
+ });
228
+ lastEnd = match.end;
229
+ }
230
+
231
+ if (lastEnd < text.length) {
232
+ segments.push(...parseMentionSegments(text.slice(lastEnd), mentionSuggestions));
233
+ }
234
+
235
+ return segments;
236
+ }
237
+
238
+ // ---------------------------------------------------------------------------
239
+ // Extended segment parser: chips + mentions
240
+ // ---------------------------------------------------------------------------
241
+
242
+ /**
243
+ * Parses text into segments: first extracts chip tokens, then runs mention parsing
244
+ * on the text fragments between chips.
245
+ */
246
+ function parseSegments(
247
+ text: string,
248
+ mentionSuggestions: MentionSuggestion[],
249
+ taskSuggestions: MentionSuggestion[],
250
+ chips: InlineChip[]
251
+ ): Segment[] {
252
+ if (!text) return [{ type: 'text', value: text }];
253
+ const slashCommand = parseStandaloneSlashCommand(text);
254
+ if (slashCommand) {
255
+ return [
256
+ {
257
+ type: 'slash_command',
258
+ value: slashCommand.raw,
259
+ known: getKnownSlashCommand(slashCommand.name) !== null,
260
+ },
261
+ ];
262
+ }
263
+ if (chips.length === 0) return parseSuggestionSegments(text, mentionSuggestions, taskSuggestions);
264
+
265
+ // Build a map of chip tokens for fast lookup
266
+ const chipTokenMap = new Map<string, InlineChip>();
267
+ for (const chip of chips) {
268
+ chipTokenMap.set(chipToken(chip), chip);
269
+ }
270
+
271
+ // Find all chip token positions, sorted by index
272
+ const chipPositions: { start: number; end: number; token: string; chip: InlineChip }[] = [];
273
+ for (const [token, chip] of chipTokenMap) {
274
+ let searchFrom = 0;
275
+ while (searchFrom < text.length) {
276
+ const idx = text.indexOf(token, searchFrom);
277
+ if (idx === -1) break;
278
+ chipPositions.push({ start: idx, end: idx + token.length, token, chip });
279
+ searchFrom = idx + 1;
280
+ }
281
+ }
282
+ chipPositions.sort((a, b) => a.start - b.start);
283
+
284
+ if (chipPositions.length === 0) {
285
+ return parseSuggestionSegments(text, mentionSuggestions, taskSuggestions);
286
+ }
287
+
288
+ const segments: Segment[] = [];
289
+ let lastEnd = 0;
290
+
291
+ for (const pos of chipPositions) {
292
+ // Text before this chip → parse for mentions
293
+ if (pos.start > lastEnd) {
294
+ const fragment = text.slice(lastEnd, pos.start);
295
+ segments.push(...parseSuggestionSegments(fragment, mentionSuggestions, taskSuggestions));
296
+ }
297
+ segments.push({ type: 'chip', value: pos.token, chip: pos.chip });
298
+ lastEnd = pos.end;
299
+ }
300
+
301
+ // Remaining text after last chip → parse for mentions
302
+ if (lastEnd < text.length) {
303
+ segments.push(
304
+ ...parseSuggestionSegments(text.slice(lastEnd), mentionSuggestions, taskSuggestions)
305
+ );
306
+ }
307
+
308
+ return segments;
309
+ }
310
+
311
+ // Default fallback color for mentions without a team color
312
+ const DEFAULT_MENTION_BG = 'rgba(59, 130, 246, 0.15)';
313
+ const DEFAULT_MENTION_TEXT = '#60a5fa';
314
+ const URL_BADGE_BG = 'var(--url-badge-bg)';
315
+ const URL_BADGE_BORDER = 'var(--url-badge-border)';
316
+ const URL_BADGE_TEXT = 'var(--url-badge-text)';
317
+
318
+ // ---------------------------------------------------------------------------
319
+ // Component
320
+ // ---------------------------------------------------------------------------
321
+
322
+ interface MentionableTextareaProps extends Omit<
323
+ AutoResizeTextareaProps,
324
+ 'value' | 'onChange' | 'onKeyDown' | 'onSelect'
325
+ > {
326
+ value: string;
327
+ onValueChange: (v: string) => void;
328
+ suggestions: MentionSuggestion[];
329
+ /** Surface class applied behind the textarea/overlay content. */
330
+ surfaceClassName?: string;
331
+ /** Optional decorative treatment for the surface shell. */
332
+ surfaceDecoration?: 'none' | 'orbit-border';
333
+ /** Solid color used by the bottom fade behind corner actions. */
334
+ surfaceFadeColor?: string;
335
+ hintText?: string;
336
+ showHint?: boolean;
337
+ /** Content rendered at the right side of the footer row (e.g. "Saved") */
338
+ footerRight?: React.ReactNode;
339
+ /** Content rendered in the bottom-right corner inside the textarea (e.g. send button) */
340
+ cornerAction?: React.ReactNode;
341
+ /** Content rendered in the bottom-left corner inside the textarea (e.g. mode selector) */
342
+ cornerActionLeft?: React.ReactNode;
343
+ /** Density of the reserved bottom inset used by corner actions. */
344
+ cornerActionInset?: 'default' | 'compact';
345
+ /** Inline code chips to display as badges */
346
+ chips?: InlineChip[];
347
+ /** Called when a chip is removed (by X button, backspace, or reconciliation) */
348
+ onChipRemove?: (chipId: string) => void;
349
+ /** Project path for @file search. When provided, enables file suggestions alongside members. */
350
+ projectPath?: string | null;
351
+ /** Called when a file chip is created via @ selection. Parent must add chip to state. */
352
+ onFileChipInsert?: (chip: InlineChip) => void;
353
+ /** Team suggestions for cross-team @mentions */
354
+ teamSuggestions?: MentionSuggestion[];
355
+ /** Task suggestions for #task references */
356
+ taskSuggestions?: MentionSuggestion[];
357
+ /** Slash command suggestions for /command autocomplete */
358
+ commandSuggestions?: MentionSuggestion[];
359
+ /** Called when Enter (without Shift) is pressed. */
360
+ onModEnter?: () => void;
361
+ /** Called when Shift+Tab is pressed. */
362
+ onShiftTab?: () => void;
363
+ /** Ref that receives the dismiss callback to close mention dropdown from outside */
364
+ dismissMentionsRef?: React.MutableRefObject<(() => void) | null>;
365
+ /** Additional rotating tips to append after the defaults */
366
+ extraTips?: string[];
367
+ }
368
+
369
+ export const MentionableTextarea = React.forwardRef<HTMLTextAreaElement, MentionableTextareaProps>(
370
+ (
371
+ {
372
+ value,
373
+ onValueChange,
374
+ suggestions,
375
+ surfaceClassName,
376
+ surfaceDecoration = 'none',
377
+ surfaceFadeColor = 'var(--color-surface-raised)',
378
+ hintText,
379
+ showHint = true,
380
+ footerRight,
381
+ cornerAction,
382
+ cornerActionLeft,
383
+ cornerActionInset = 'default',
384
+ chips = [],
385
+ onChipRemove,
386
+ projectPath,
387
+ onFileChipInsert,
388
+ teamSuggestions = [],
389
+ taskSuggestions = [],
390
+ commandSuggestions = [],
391
+ onModEnter,
392
+ onShiftTab,
393
+ dismissMentionsRef,
394
+ extraTips = [],
395
+ style,
396
+ className,
397
+ ...textareaProps
398
+ },
399
+ forwardedRef
400
+ ) => {
401
+ const internalRef = React.useRef<HTMLTextAreaElement | null>(null);
402
+ const backdropRef = React.useRef<HTMLDivElement>(null);
403
+ const surfaceShellRef = React.useRef<HTMLDivElement | null>(null);
404
+ const [scrollTop, setScrollTop] = React.useState(0);
405
+ const { isLight } = useTheme();
406
+ const orbitGlowId = React.useId();
407
+ const [surfaceShellMetrics, setSurfaceShellMetrics] = React.useState(() => ({
408
+ width: 0,
409
+ height: 0,
410
+ borderRadius: 6,
411
+ }));
412
+
413
+ // --- File search activation ---
414
+ const enableFiles = !!projectPath;
415
+ const enableTaskSearch = taskSuggestions.length > 0;
416
+
417
+ const setRefs = React.useCallback(
418
+ (node: HTMLTextAreaElement | null) => {
419
+ internalRef.current = node;
420
+ if (typeof forwardedRef === 'function') {
421
+ forwardedRef(node);
422
+ } else if (forwardedRef) {
423
+ forwardedRef.current = node;
424
+ }
425
+ },
426
+ [forwardedRef]
427
+ );
428
+
429
+ const {
430
+ isOpen,
431
+ activeTriggerChar,
432
+ query,
433
+ selectedIndex,
434
+ setSelectedIndex,
435
+ dropdownPosition,
436
+ selectSuggestion,
437
+ dismiss,
438
+ getTriggerIndex,
439
+ handleKeyDown: mentionHandleKeyDown,
440
+ handleChange: mentionHandleChange,
441
+ handleSelect: mentionHandleSelect,
442
+ } = useMentionDetection({
443
+ value,
444
+ onValueChange,
445
+ textareaRef: internalRef,
446
+ triggerChars:
447
+ commandSuggestions.length > 0 ? ['@', '#', '/'] : enableTaskSearch ? ['@', '#'] : ['@'],
448
+ isTriggerEnabled: (triggerChar) => {
449
+ if (triggerChar === '#') return enableTaskSearch;
450
+ if (triggerChar === '/') return commandSuggestions.length > 0;
451
+ return suggestions.length > 0 || enableFiles || teamSuggestions.length > 0;
452
+ },
453
+ isTriggerMatchValid: (trigger, text) => {
454
+ if (trigger.triggerChar !== '/') return true;
455
+ return text.slice(0, trigger.triggerIndex).trim().length === 0;
456
+ },
457
+ });
458
+
459
+ // Expose dismiss to parent via ref for external close (e.g. Send button click)
460
+ React.useEffect(() => {
461
+ if (dismissMentionsRef) dismissMentionsRef.current = dismiss;
462
+ }, [dismiss, dismissMentionsRef]);
463
+
464
+ // --- File suggestions ---
465
+ const { suggestions: fileSuggestions, loading: filesLoading } = useFileSuggestions(
466
+ enableFiles ? projectPath : null,
467
+ activeTriggerChar === '@' ? query : '',
468
+ isOpen && enableFiles && activeTriggerChar === '@'
469
+ );
470
+
471
+ const isAtTrigger = activeTriggerChar !== '#' && activeTriggerChar !== '/';
472
+
473
+ const memberSuggestions = React.useMemo(() => {
474
+ if (!isOpen || !isAtTrigger) return [];
475
+ if (!query) return suggestions;
476
+ return suggestions.filter((member) => doesSuggestionMatchQuery(member, query));
477
+ }, [isAtTrigger, isOpen, query, suggestions]);
478
+
479
+ // --- Team suggestions filtered by query ---
480
+ const filteredTeamSuggestions = React.useMemo(() => {
481
+ if (teamSuggestions.length === 0 || !isOpen || !isAtTrigger) return [];
482
+ if (!query) return teamSuggestions;
483
+ return teamSuggestions.filter((team) => doesSuggestionMatchQuery(team, query));
484
+ }, [teamSuggestions, isAtTrigger, isOpen, query]);
485
+
486
+ const filteredTaskSuggestions = React.useMemo(() => {
487
+ if (taskSuggestions.length === 0 || !isOpen || activeTriggerChar !== '#') return [];
488
+ if (!query) return taskSuggestions;
489
+ return taskSuggestions.filter((task) => doesSuggestionMatchQuery(task, query));
490
+ }, [taskSuggestions, activeTriggerChar, isOpen, query]);
491
+
492
+ const filteredCommandSuggestions = React.useMemo(() => {
493
+ if (commandSuggestions.length === 0 || !isOpen || activeTriggerChar !== '/') return [];
494
+ if (!query) return commandSuggestions;
495
+ return commandSuggestions.filter((command) => doesSuggestionMatchQuery(command, query));
496
+ }, [commandSuggestions, activeTriggerChar, isOpen, query]);
497
+
498
+ // Merged suggestion list: members → online teams → offline teams → files
499
+ const atSuggestions = React.useMemo(() => {
500
+ const onlineTeams = filteredTeamSuggestions.filter((t) => t.isOnline);
501
+ const offlineTeams = filteredTeamSuggestions.filter((t) => !t.isOnline);
502
+ const merged = [...memberSuggestions, ...onlineTeams, ...offlineTeams];
503
+ if (!enableFiles) return merged;
504
+ if (fileSuggestions.length === 0) return merged;
505
+ return [...merged, ...fileSuggestions];
506
+ }, [memberSuggestions, filteredTeamSuggestions, enableFiles, fileSuggestions]);
507
+ const effectiveSuggestions =
508
+ activeTriggerChar === '/'
509
+ ? filteredCommandSuggestions
510
+ : activeTriggerChar === '#'
511
+ ? filteredTaskSuggestions
512
+ : atSuggestions;
513
+
514
+ React.useEffect(() => {
515
+ if (!isOpen) return;
516
+ if (effectiveSuggestions.length === 0) {
517
+ setSelectedIndex(0);
518
+ return;
519
+ }
520
+ if (selectedIndex >= effectiveSuggestions.length) {
521
+ setSelectedIndex(0);
522
+ }
523
+ }, [effectiveSuggestions.length, isOpen, selectedIndex, setSelectedIndex]);
524
+
525
+ // --- File selection handler ---
526
+ const handleFileSelect = React.useCallback(
527
+ (s: MentionSuggestion) => {
528
+ const textarea = internalRef.current;
529
+ const triggerIdx = getTriggerIndex();
530
+ if (!textarea || triggerIdx < 0 || !s.filePath) return;
531
+
532
+ const replaceStart = triggerIdx;
533
+ const replaceEnd = triggerIdx + 1 + query.length;
534
+ const before = value.slice(0, replaceStart);
535
+ const after = value.slice(replaceEnd);
536
+
537
+ if (onFileChipInsert && onChipRemove) {
538
+ // Chip mode: create InlineChip and insert chip token
539
+ const chip = createChipFromSelection(
540
+ {
541
+ type: 'sendMessage',
542
+ filePath: s.filePath,
543
+ fromLine: null,
544
+ toLine: null,
545
+ selectedText: '',
546
+ formattedContext: '',
547
+ displayPath: s.relativePath,
548
+ },
549
+ chips
550
+ );
551
+
552
+ if (chip) {
553
+ const token = chipToken(chip);
554
+ const newValue = before + token + after;
555
+ onValueChange(newValue);
556
+ onFileChipInsert(chip);
557
+ dismiss();
558
+
559
+ requestAnimationFrame(() => {
560
+ const cursor = before.length + token.length;
561
+ textarea.setSelectionRange(cursor, cursor);
562
+ });
563
+ } else {
564
+ // Duplicate chip — just dismiss
565
+ dismiss();
566
+ }
567
+ } else {
568
+ // Text mode: insert backtick-wrapped relative path
569
+ const displayPath = s.relativePath ?? s.name;
570
+ const insertion = `\`${displayPath}\` `;
571
+ const newValue = before + insertion + after;
572
+ onValueChange(newValue);
573
+ dismiss();
574
+
575
+ requestAnimationFrame(() => {
576
+ const cursor = before.length + insertion.length;
577
+ textarea.setSelectionRange(cursor, cursor);
578
+ });
579
+ }
580
+ },
581
+ [getTriggerIndex, query, value, chips, onValueChange, onFileChipInsert, onChipRemove, dismiss]
582
+ );
583
+
584
+ // --- Folder selection handler (inserts folder as chip with folder icon) ---
585
+ const handleFolderSelect = React.useCallback(
586
+ (s: MentionSuggestion) => {
587
+ const textarea = internalRef.current;
588
+ const triggerIdx = getTriggerIndex();
589
+ if (!textarea || triggerIdx < 0) return;
590
+
591
+ const replaceStart = triggerIdx;
592
+ const replaceEnd = triggerIdx + 1 + query.length;
593
+ const before = value.slice(0, replaceStart);
594
+ const after = value.slice(replaceEnd);
595
+
596
+ if (onFileChipInsert && onChipRemove) {
597
+ // Chip mode: create folder InlineChip
598
+ const chip = createChipFromSelection(
599
+ {
600
+ type: 'sendMessage',
601
+ filePath: s.filePath ?? '',
602
+ fromLine: null,
603
+ toLine: null,
604
+ selectedText: '',
605
+ formattedContext: '',
606
+ displayPath: s.relativePath,
607
+ isFolder: true,
608
+ },
609
+ chips
610
+ );
611
+
612
+ if (chip) {
613
+ const token = chipToken(chip);
614
+ const newValue = before + token + after;
615
+ onValueChange(newValue);
616
+ onFileChipInsert(chip);
617
+ dismiss();
618
+
619
+ requestAnimationFrame(() => {
620
+ const cursor = before.length + token.length;
621
+ textarea.setSelectionRange(cursor, cursor);
622
+ });
623
+ } else {
624
+ dismiss();
625
+ }
626
+ } else {
627
+ // Text mode fallback: insert backtick-wrapped relative path
628
+ const displayPath = s.relativePath ?? s.name;
629
+ const insertion = `\`${displayPath}\` `;
630
+ const newValue = before + insertion + after;
631
+ onValueChange(newValue);
632
+ dismiss();
633
+
634
+ requestAnimationFrame(() => {
635
+ const cursor = before.length + insertion.length;
636
+ textarea.setSelectionRange(cursor, cursor);
637
+ });
638
+ }
639
+ },
640
+ [getTriggerIndex, query, value, chips, onValueChange, onFileChipInsert, onChipRemove, dismiss]
641
+ );
642
+
643
+ // --- Active selection handler ---
644
+ const handleActiveSelect = React.useCallback(
645
+ (s: MentionSuggestion) => {
646
+ if (s.type === 'file') {
647
+ handleFileSelect(s);
648
+ } else if (s.type === 'folder') {
649
+ handleFolderSelect(s);
650
+ } else {
651
+ selectSuggestion(s);
652
+ }
653
+ },
654
+ [handleFileSelect, handleFolderSelect, selectSuggestion]
655
+ );
656
+
657
+ // Sync backdrop font with textarea computed font to prevent caret drift.
658
+ React.useLayoutEffect(() => {
659
+ const textarea = internalRef.current;
660
+ const backdrop = backdropRef.current;
661
+ if (!textarea || !backdrop) return;
662
+ const cs = window.getComputedStyle(textarea);
663
+ backdrop.style.font = cs.font;
664
+ backdrop.style.letterSpacing = cs.letterSpacing;
665
+ backdrop.style.wordSpacing = cs.wordSpacing;
666
+ backdrop.style.textIndent = cs.textIndent;
667
+ backdrop.style.textTransform = cs.textTransform;
668
+ backdrop.style.tabSize = cs.tabSize;
669
+ }, [value]);
670
+
671
+ React.useLayoutEffect(() => {
672
+ if (surfaceDecoration !== 'orbit-border') return;
673
+ const shell = surfaceShellRef.current;
674
+ if (!shell) return;
675
+
676
+ const updateMetrics = () => {
677
+ const rect = shell.getBoundingClientRect();
678
+ const computedStyle = window.getComputedStyle(shell);
679
+ const borderRadius = Number.parseFloat(computedStyle.borderTopLeftRadius) || 6;
680
+ setSurfaceShellMetrics((prev) => {
681
+ if (
682
+ Math.abs(prev.width - rect.width) < 0.5 &&
683
+ Math.abs(prev.height - rect.height) < 0.5 &&
684
+ Math.abs(prev.borderRadius - borderRadius) < 0.5
685
+ ) {
686
+ return prev;
687
+ }
688
+ return {
689
+ width: rect.width,
690
+ height: rect.height,
691
+ borderRadius,
692
+ };
693
+ });
694
+ };
695
+
696
+ updateMetrics();
697
+ const resizeObserver = new ResizeObserver(() => {
698
+ updateMetrics();
699
+ });
700
+ resizeObserver.observe(shell);
701
+ return () => resizeObserver.disconnect();
702
+ }, [surfaceDecoration]);
703
+
704
+ // --- Overlay activation ---
705
+ const hasOverlay =
706
+ value.includes('http://') ||
707
+ value.includes('https://') ||
708
+ parseStandaloneSlashCommand(value) !== null ||
709
+ suggestions.length > 0 ||
710
+ teamSuggestions.length > 0 ||
711
+ taskSuggestions.length > 0 ||
712
+ chips.length > 0;
713
+
714
+ // Combine member + team suggestions for overlay parsing
715
+ const mentionOverlaySuggestions = React.useMemo(
716
+ () => (teamSuggestions.length > 0 ? [...suggestions, ...teamSuggestions] : suggestions),
717
+ [suggestions, teamSuggestions]
718
+ );
719
+ const slashCommand = React.useMemo(() => parseStandaloneSlashCommand(value), [value]);
720
+ const knownSlashCommand = React.useMemo(
721
+ () => (slashCommand ? getKnownSlashCommand(slashCommand.name) : null),
722
+ [slashCommand]
723
+ );
724
+
725
+ const segments = React.useMemo(
726
+ () =>
727
+ hasOverlay ? parseSegments(value, mentionOverlaySuggestions, taskSuggestions, chips) : [],
728
+ [hasOverlay, value, mentionOverlaySuggestions, taskSuggestions, chips]
729
+ );
730
+
731
+ // Sync backdrop scroll with textarea scroll + track scrollTop for interaction layer
732
+ const handleScroll = React.useCallback(() => {
733
+ const textarea = internalRef.current;
734
+ const backdrop = backdropRef.current;
735
+ if (textarea) {
736
+ if (backdrop) {
737
+ backdrop.scrollTop = textarea.scrollTop;
738
+ }
739
+ setScrollTop(textarea.scrollTop);
740
+ }
741
+ }, []);
742
+
743
+ // --- Chip keyboard handling (atomic cursor / backspace / delete) ---
744
+ const findEncodedTaskBoundary = React.useCallback(
745
+ (cursorPos: number) => {
746
+ const boundary = findTaskReferenceMatches(value, taskSuggestions).find(
747
+ (match) => match.encoded && cursorPos >= match.start && cursorPos <= match.end
748
+ );
749
+ return boundary ? { start: boundary.start, end: boundary.end } : null;
750
+ },
751
+ [taskSuggestions, value]
752
+ );
753
+
754
+ const findUrlTokenBoundary = React.useCallback(
755
+ (cursorPos: number) => findUrlBoundary(value, cursorPos),
756
+ [value]
757
+ );
758
+
759
+ const handleChipKeyDown = React.useCallback(
760
+ (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
761
+ const textarea = internalRef.current;
762
+ if (!textarea) return;
763
+
764
+ const { selectionStart, selectionEnd } = textarea;
765
+ // Only act on collapsed cursor
766
+ if (selectionStart !== selectionEnd && !e.shiftKey) return;
767
+
768
+ const cursorPos = selectionStart;
769
+
770
+ if (e.key === 'Backspace') {
771
+ const urlBoundary = findUrlTokenBoundary(cursorPos);
772
+ if (cursorPos === urlBoundary?.end) {
773
+ e.preventDefault();
774
+ const newText = removeUrlMatchFromText(value, urlBoundary);
775
+ onValueChange(newText);
776
+ requestAnimationFrame(() => {
777
+ textarea.setSelectionRange(urlBoundary.start, urlBoundary.start);
778
+ });
779
+ return;
780
+ }
781
+ const taskBoundary = findEncodedTaskBoundary(cursorPos);
782
+ if (cursorPos === taskBoundary?.end) {
783
+ e.preventDefault();
784
+ const newText = value.slice(0, taskBoundary.start) + value.slice(taskBoundary.end);
785
+ onValueChange(newText);
786
+ requestAnimationFrame(() => {
787
+ textarea.setSelectionRange(taskBoundary.start, taskBoundary.start);
788
+ });
789
+ return;
790
+ }
791
+ if (chips.length === 0 || !onChipRemove) return;
792
+ // If cursor is at chip end → delete entire chip
793
+ const boundary = findChipBoundary(value, chips, cursorPos);
794
+ if (cursorPos === boundary?.end) {
795
+ e.preventDefault();
796
+ const newText = removeChipTokenFromText(value, boundary.chip);
797
+ onValueChange(newText);
798
+ onChipRemove(boundary.chip.id);
799
+ // Set cursor to where chip started
800
+ requestAnimationFrame(() => {
801
+ textarea.setSelectionRange(boundary.start, boundary.start);
802
+ });
803
+ }
804
+ } else if (e.key === 'Delete') {
805
+ const urlBoundary = findUrlTokenBoundary(cursorPos);
806
+ if (cursorPos === urlBoundary?.start) {
807
+ e.preventDefault();
808
+ const newText = removeUrlMatchFromText(value, urlBoundary);
809
+ onValueChange(newText);
810
+ requestAnimationFrame(() => {
811
+ textarea.setSelectionRange(urlBoundary.start, urlBoundary.start);
812
+ });
813
+ return;
814
+ }
815
+ const taskBoundary = findEncodedTaskBoundary(cursorPos);
816
+ if (cursorPos === taskBoundary?.start) {
817
+ e.preventDefault();
818
+ const newText = value.slice(0, taskBoundary.start) + value.slice(taskBoundary.end);
819
+ onValueChange(newText);
820
+ requestAnimationFrame(() => {
821
+ textarea.setSelectionRange(taskBoundary.start, taskBoundary.start);
822
+ });
823
+ return;
824
+ }
825
+ if (chips.length === 0 || !onChipRemove) return;
826
+ // If cursor is at chip start → delete entire chip
827
+ const boundary = findChipBoundary(value, chips, cursorPos);
828
+ if (cursorPos === boundary?.start) {
829
+ e.preventDefault();
830
+ const newText = removeChipTokenFromText(value, boundary.chip);
831
+ onValueChange(newText);
832
+ onChipRemove(boundary.chip.id);
833
+ requestAnimationFrame(() => {
834
+ textarea.setSelectionRange(boundary.start, boundary.start);
835
+ });
836
+ }
837
+ } else if (e.key === 'ArrowLeft' && !e.shiftKey) {
838
+ const urlBoundary = findUrlTokenBoundary(cursorPos);
839
+ if (cursorPos === urlBoundary?.end) {
840
+ e.preventDefault();
841
+ textarea.setSelectionRange(urlBoundary.start, urlBoundary.start);
842
+ return;
843
+ }
844
+ const taskBoundary = findEncodedTaskBoundary(cursorPos);
845
+ if (cursorPos === taskBoundary?.end) {
846
+ e.preventDefault();
847
+ textarea.setSelectionRange(taskBoundary.start, taskBoundary.start);
848
+ return;
849
+ }
850
+ if (chips.length === 0 || !onChipRemove) return;
851
+ // If cursor is at chip end → jump to chip start
852
+ const boundary = findChipBoundary(value, chips, cursorPos);
853
+ if (cursorPos === boundary?.end) {
854
+ e.preventDefault();
855
+ textarea.setSelectionRange(boundary.start, boundary.start);
856
+ }
857
+ } else if (e.key === 'ArrowRight' && !e.shiftKey) {
858
+ const urlBoundary = findUrlTokenBoundary(cursorPos);
859
+ if (cursorPos === urlBoundary?.start) {
860
+ e.preventDefault();
861
+ textarea.setSelectionRange(urlBoundary.end, urlBoundary.end);
862
+ return;
863
+ }
864
+ const taskBoundary = findEncodedTaskBoundary(cursorPos);
865
+ if (cursorPos === taskBoundary?.start) {
866
+ e.preventDefault();
867
+ textarea.setSelectionRange(taskBoundary.end, taskBoundary.end);
868
+ return;
869
+ }
870
+ if (chips.length === 0 || !onChipRemove) return;
871
+ // If cursor is at chip start → jump to chip end
872
+ const boundary = findChipBoundary(value, chips, cursorPos);
873
+ if (cursorPos === boundary?.start) {
874
+ e.preventDefault();
875
+ textarea.setSelectionRange(boundary.end, boundary.end);
876
+ }
877
+ } else if (e.key === 'ArrowLeft' && e.shiftKey) {
878
+ const urlBoundary = findUrlTokenBoundary(cursorPos);
879
+ if (cursorPos === urlBoundary?.end) {
880
+ e.preventDefault();
881
+ textarea.setSelectionRange(urlBoundary.start, selectionEnd);
882
+ return;
883
+ }
884
+ const taskBoundary = findEncodedTaskBoundary(cursorPos);
885
+ if (cursorPos === taskBoundary?.end) {
886
+ e.preventDefault();
887
+ textarea.setSelectionRange(taskBoundary.start, selectionEnd);
888
+ return;
889
+ }
890
+ if (chips.length === 0 || !onChipRemove) return;
891
+ // Extend selection past chip atomically
892
+ const boundary = findChipBoundary(value, chips, cursorPos);
893
+ if (cursorPos === boundary?.end) {
894
+ e.preventDefault();
895
+ textarea.setSelectionRange(boundary.start, selectionEnd);
896
+ }
897
+ } else if (e.key === 'ArrowRight' && e.shiftKey) {
898
+ const urlBoundary = findUrlTokenBoundary(cursorPos);
899
+ if (cursorPos === urlBoundary?.start) {
900
+ e.preventDefault();
901
+ textarea.setSelectionRange(selectionStart, urlBoundary.end);
902
+ return;
903
+ }
904
+ const taskBoundary = findEncodedTaskBoundary(cursorPos);
905
+ if (cursorPos === taskBoundary?.start) {
906
+ e.preventDefault();
907
+ textarea.setSelectionRange(selectionStart, taskBoundary.end);
908
+ return;
909
+ }
910
+ if (chips.length === 0 || !onChipRemove) return;
911
+ const boundary = findChipBoundary(value, chips, cursorPos);
912
+ if (cursorPos === boundary?.start) {
913
+ e.preventDefault();
914
+ textarea.setSelectionRange(selectionStart, boundary.end);
915
+ }
916
+ }
917
+ },
918
+ [chips, findEncodedTaskBoundary, findUrlTokenBoundary, onChipRemove, value, onValueChange]
919
+ );
920
+
921
+ // Composed key handler: suggestion logic first (when open) → Mod+Enter submit → chip logic
922
+ const composedHandleKeyDown = React.useCallback(
923
+ (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
924
+ // When the suggestion dropdown is open, let it consume Enter/Arrow keys first
925
+ if (isOpen && effectiveSuggestions.length > 0) {
926
+ mentionHandleKeyDown(e, effectiveSuggestions.length, (index) => {
927
+ const next = effectiveSuggestions[index];
928
+ if (next) handleActiveSelect(next);
929
+ });
930
+ if (e.defaultPrevented) return;
931
+ }
932
+ // Shift+Tab can be wired by callers for an optional composer shortcut.
933
+ if (e.key === 'Tab' && e.shiftKey && onShiftTab) {
934
+ e.preventDefault();
935
+ onShiftTab();
936
+ return;
937
+ }
938
+ const nativeEvent = e.nativeEvent as KeyboardEvent & { isComposing?: boolean };
939
+ const isComposing =
940
+ nativeEvent.isComposing === true || e.key === 'Process' || nativeEvent.keyCode === 229;
941
+
942
+ // Enter (without Shift) → submit; Shift+Enter → newline.
943
+ // IME composition also uses Enter to confirm candidates; never submit in that state.
944
+ if (e.key === 'Enter' && !e.shiftKey && !isComposing && onModEnter) {
945
+ e.preventDefault();
946
+ e.stopPropagation();
947
+ dismiss();
948
+ onModEnter();
949
+ return;
950
+ }
951
+ handleChipKeyDown(e);
952
+ },
953
+ [
954
+ onModEnter,
955
+ onShiftTab,
956
+ handleChipKeyDown,
957
+ mentionHandleKeyDown,
958
+ isOpen,
959
+ effectiveSuggestions.length,
960
+ effectiveSuggestions,
961
+ handleActiveSelect,
962
+ ]
963
+ );
964
+
965
+ // --- Chip reconciliation on text change ---
966
+ const composedHandleChange = React.useCallback(
967
+ (e: React.ChangeEvent<HTMLTextAreaElement>) => {
968
+ mentionHandleChange(e);
969
+
970
+ // Reconcile chips after text changes (paste/cut/undo)
971
+ if (chips.length > 0 && onChipRemove) {
972
+ const newText = e.target.value;
973
+ const surviving = reconcileChips(chips, newText);
974
+ if (surviving.length < chips.length) {
975
+ const survivingIds = new Set(surviving.map((c) => c.id));
976
+ for (const chip of chips) {
977
+ if (!survivingIds.has(chip.id)) {
978
+ onChipRemove(chip.id);
979
+ }
980
+ }
981
+ }
982
+ }
983
+ },
984
+ [mentionHandleChange, chips, onChipRemove]
985
+ );
986
+
987
+ // --- Snap cursor on click/select if inside chip ---
988
+ const composedHandleSelect = React.useCallback(
989
+ (e: React.SyntheticEvent<HTMLTextAreaElement>) => {
990
+ mentionHandleSelect(e);
991
+
992
+ if (chips.length > 0) {
993
+ const textarea = internalRef.current;
994
+ if (!textarea) return;
995
+ const { selectionStart, selectionEnd } = textarea;
996
+ // Only snap collapsed cursor
997
+ if (selectionStart !== selectionEnd) return;
998
+
999
+ const boundary = findChipBoundary(value, chips, selectionStart);
1000
+ if (boundary && selectionStart > boundary.start && selectionStart < boundary.end) {
1001
+ // Snap to nearest boundary
1002
+ const distToStart = selectionStart - boundary.start;
1003
+ const distToEnd = boundary.end - selectionStart;
1004
+ const snapTo = distToStart <= distToEnd ? boundary.start : boundary.end;
1005
+ requestAnimationFrame(() => {
1006
+ textarea.setSelectionRange(snapTo, snapTo);
1007
+ });
1008
+ }
1009
+ }
1010
+
1011
+ const textarea = internalRef.current;
1012
+ if (!textarea) return;
1013
+ const { selectionStart, selectionEnd } = textarea;
1014
+ if (selectionStart !== selectionEnd) return;
1015
+ const taskBoundary = findEncodedTaskBoundary(selectionStart);
1016
+ if (
1017
+ taskBoundary &&
1018
+ selectionStart > taskBoundary.start &&
1019
+ selectionStart < taskBoundary.end
1020
+ ) {
1021
+ const distToStart = selectionStart - taskBoundary.start;
1022
+ const distToEnd = taskBoundary.end - selectionStart;
1023
+ const snapTo = distToStart <= distToEnd ? taskBoundary.start : taskBoundary.end;
1024
+ requestAnimationFrame(() => {
1025
+ textarea.setSelectionRange(snapTo, snapTo);
1026
+ });
1027
+ return;
1028
+ }
1029
+
1030
+ const urlBoundary = findUrlTokenBoundary(selectionStart);
1031
+ if (urlBoundary && selectionStart > urlBoundary.start && selectionStart < urlBoundary.end) {
1032
+ const distToStart = selectionStart - urlBoundary.start;
1033
+ const distToEnd = urlBoundary.end - selectionStart;
1034
+ const snapTo = distToStart <= distToEnd ? urlBoundary.start : urlBoundary.end;
1035
+ requestAnimationFrame(() => {
1036
+ textarea.setSelectionRange(snapTo, snapTo);
1037
+ });
1038
+ }
1039
+ },
1040
+ [mentionHandleSelect, chips, value, findEncodedTaskBoundary, findUrlTokenBoundary]
1041
+ );
1042
+
1043
+ // --- Chip remove handler (from X button in interaction layer) ---
1044
+ const handleChipRemove = React.useCallback(
1045
+ (chipId: string) => {
1046
+ const chip = chips.find((c) => c.id === chipId);
1047
+ if (chip) {
1048
+ const newText = removeChipTokenFromText(value, chip);
1049
+ onValueChange(newText);
1050
+ }
1051
+ onChipRemove?.(chipId);
1052
+ },
1053
+ [chips, value, onValueChange, onChipRemove]
1054
+ );
1055
+
1056
+ // When overlay is active: textarea text is transparent, caret stays visible
1057
+ const textareaStyle: React.CSSProperties | undefined = hasOverlay
1058
+ ? {
1059
+ ...style,
1060
+ color: 'transparent',
1061
+ caretColor: 'var(--color-text)',
1062
+ position: 'relative' as const,
1063
+ zIndex: 10,
1064
+ background: 'transparent',
1065
+ }
1066
+ : style;
1067
+
1068
+ // --- Rotating tips ---
1069
+ const rotatingTips = React.useMemo(
1070
+ () => [
1071
+ 'Tips:输入 @ 可提及成员、团队或文件,输入 # 可引用任务。',
1072
+ 'Tips:输入“创建任务”可以把事项加入任务看板。',
1073
+ 'Tips:不要把所有工作都堆给团队负责人,可以让负责人分配给合适的成员。',
1074
+ ...extraTips,
1075
+ ],
1076
+ [extraTips]
1077
+ );
1078
+ const [tipIndex, setTipIndex] = React.useState(0);
1079
+ const [tipVisible, setTipVisible] = React.useState(true);
1080
+
1081
+ const advanceTip = React.useCallback(() => {
1082
+ setTipIndex((prev) => (prev + 1) % rotatingTips.length);
1083
+ setTipVisible(true);
1084
+ }, [rotatingTips.length]);
1085
+
1086
+ React.useEffect(() => {
1087
+ const interval = setInterval(() => {
1088
+ setTipVisible(false);
1089
+ setTimeout(advanceTip, 300);
1090
+ }, 10000);
1091
+ return () => clearInterval(interval);
1092
+ }, [advanceTip]);
1093
+
1094
+ const resolvedHintText = hintText ?? rotatingTips[tipIndex];
1095
+ const showHintRow =
1096
+ showHint &&
1097
+ (suggestions.length > 0 ||
1098
+ enableFiles ||
1099
+ teamSuggestions.length > 0 ||
1100
+ enableTaskSearch ||
1101
+ commandSuggestions.length > 0);
1102
+ const showFooter = showHintRow || footerRight;
1103
+ const hasCornerActions = Boolean(cornerAction || cornerActionLeft);
1104
+ const cornerInsetClass = cornerActionInset === 'compact' ? 'pb-10' : 'pb-12';
1105
+ const cornerFadeHeight = cornerActionInset === 'compact' ? 40 : 48;
1106
+ const cornerActionOffsetClass = cornerActionInset === 'compact' ? 'bottom-1.5' : 'bottom-2';
1107
+ const orbitTrackWidth = 1;
1108
+ const orbitStrokeWidth = 1.35;
1109
+ const orbitGlowWidth = 3;
1110
+ const orbitInset = 0;
1111
+ const orbitWidth = Math.max(surfaceShellMetrics.width, 0);
1112
+ const orbitHeight = Math.max(surfaceShellMetrics.height, 0);
1113
+ const orbitRadius = Math.max(surfaceShellMetrics.borderRadius, 0);
1114
+ const orbitRight = orbitInset + orbitWidth;
1115
+ const orbitBottom = orbitInset + orbitHeight;
1116
+ const orbitMidX = orbitInset + orbitWidth / 2;
1117
+ const orbitPathData =
1118
+ orbitWidth > 0 && orbitHeight > 0
1119
+ ? [
1120
+ `M ${orbitMidX} ${orbitInset}`,
1121
+ `H ${orbitRight - orbitRadius}`,
1122
+ `A ${orbitRadius} ${orbitRadius} 0 0 1 ${orbitRight} ${orbitInset + orbitRadius}`,
1123
+ `V ${orbitBottom - orbitRadius}`,
1124
+ `A ${orbitRadius} ${orbitRadius} 0 0 1 ${orbitRight - orbitRadius} ${orbitBottom}`,
1125
+ `H ${orbitInset + orbitRadius}`,
1126
+ `A ${orbitRadius} ${orbitRadius} 0 0 1 ${orbitInset} ${orbitBottom - orbitRadius}`,
1127
+ `V ${orbitInset + orbitRadius}`,
1128
+ `A ${orbitRadius} ${orbitRadius} 0 0 1 ${orbitInset + orbitRadius} ${orbitInset}`,
1129
+ `H ${orbitMidX}`,
1130
+ 'Z',
1131
+ ].join(' ')
1132
+ : '';
1133
+
1134
+ return (
1135
+ <div className="relative">
1136
+ {/* Inner wrapper for textarea + backdrop overlay */}
1137
+ <div ref={surfaceShellRef} className={cn('relative rounded-md', surfaceClassName)}>
1138
+ {surfaceDecoration === 'orbit-border' &&
1139
+ surfaceShellMetrics.width > 0 &&
1140
+ surfaceShellMetrics.height > 0 ? (
1141
+ <svg
1142
+ className="message-composer-orbit-svg pointer-events-none absolute inset-0 z-[16] size-full"
1143
+ viewBox={`0 0 ${surfaceShellMetrics.width} ${surfaceShellMetrics.height}`}
1144
+ aria-hidden="true"
1145
+ >
1146
+ <defs>
1147
+ <filter id={orbitGlowId} x="-50%" y="-50%" width="200%" height="200%">
1148
+ <feGaussianBlur stdDeviation="1.35" />
1149
+ </filter>
1150
+ </defs>
1151
+ <path
1152
+ className="message-composer-orbit-track"
1153
+ d={orbitPathData}
1154
+ pathLength="100"
1155
+ fill="none"
1156
+ strokeWidth={orbitTrackWidth}
1157
+ />
1158
+ <path
1159
+ className="message-composer-orbit-glow"
1160
+ d={orbitPathData}
1161
+ pathLength="100"
1162
+ fill="none"
1163
+ filter={`url(#${orbitGlowId})`}
1164
+ strokeWidth={orbitGlowWidth}
1165
+ />
1166
+ <path
1167
+ className="message-composer-orbit-glow message-composer-orbit-glow-secondary"
1168
+ d={orbitPathData}
1169
+ pathLength="100"
1170
+ fill="none"
1171
+ filter={`url(#${orbitGlowId})`}
1172
+ strokeWidth={orbitGlowWidth}
1173
+ />
1174
+ <path
1175
+ className="message-composer-orbit-path"
1176
+ d={orbitPathData}
1177
+ pathLength="100"
1178
+ fill="none"
1179
+ strokeWidth={orbitStrokeWidth}
1180
+ />
1181
+ <path
1182
+ className="message-composer-orbit-path message-composer-orbit-path-secondary"
1183
+ d={orbitPathData}
1184
+ pathLength="100"
1185
+ fill="none"
1186
+ strokeWidth={orbitStrokeWidth}
1187
+ />
1188
+ </svg>
1189
+ ) : null}
1190
+ {hasOverlay ? (
1191
+ <div
1192
+ ref={backdropRef}
1193
+ className={cn(
1194
+ 'pointer-events-none absolute inset-0 z-0 overflow-hidden rounded-md border border-transparent px-3 py-2 text-sm text-[var(--color-text)]',
1195
+ hasCornerActions && cornerInsetClass
1196
+ )}
1197
+ style={{
1198
+ whiteSpace: 'pre-wrap',
1199
+ wordWrap: 'break-word',
1200
+ overflowWrap: 'break-word',
1201
+ }}
1202
+ aria-hidden="true"
1203
+ >
1204
+ {segments.map((seg, idx) => {
1205
+ if (seg.type === 'text') {
1206
+ return <React.Fragment key={idx}>{seg.value}</React.Fragment>;
1207
+ }
1208
+ if (seg.type === 'chip') {
1209
+ return <CodeChipBadge key={idx} chip={seg.chip} tokenText={seg.value} />;
1210
+ }
1211
+ if (seg.type === 'slash_command') {
1212
+ return (
1213
+ <span
1214
+ key={idx}
1215
+ style={{
1216
+ backgroundColor: seg.known
1217
+ ? 'rgba(245, 158, 11, 0.18)'
1218
+ : 'rgba(148, 163, 184, 0.16)',
1219
+ color: seg.known ? '#f59e0b' : 'var(--color-text-secondary)',
1220
+ borderRadius: '4px',
1221
+ boxShadow: `inset 0 0 0 1px ${
1222
+ seg.known ? 'rgba(245, 158, 11, 0.3)' : 'rgba(148, 163, 184, 0.24)'
1223
+ }`,
1224
+ padding: '2px 0',
1225
+ }}
1226
+ >
1227
+ {seg.value}
1228
+ </span>
1229
+ );
1230
+ }
1231
+ if (seg.type === 'task') {
1232
+ return (
1233
+ <React.Fragment key={idx}>
1234
+ <span
1235
+ className={seg.encoded ? 'rounded' : 'underline decoration-transparent'}
1236
+ style={
1237
+ seg.encoded
1238
+ ? {
1239
+ backgroundColor: 'rgba(59, 130, 246, 0.15)',
1240
+ color: PROSE_LINK,
1241
+ // Only vertical padding (doesn't affect inline text flow).
1242
+ // No horizontal padding/margin/box-shadow spread to avoid
1243
+ // caret drift or visual overlap with adjacent text.
1244
+ padding: '2px 0',
1245
+ }
1246
+ : { color: PROSE_LINK }
1247
+ }
1248
+ >
1249
+ {seg.value}
1250
+ </span>
1251
+ {seg.hiddenSuffix}
1252
+ </React.Fragment>
1253
+ );
1254
+ }
1255
+ if (seg.type === 'url') {
1256
+ return (
1257
+ <span
1258
+ key={idx}
1259
+ style={{
1260
+ backgroundColor: URL_BADGE_BG,
1261
+ color: URL_BADGE_TEXT,
1262
+ borderRadius: '4px',
1263
+ boxShadow: `inset 0 0 0 1px ${URL_BADGE_BORDER}`,
1264
+ }}
1265
+ >
1266
+ {seg.value}
1267
+ </span>
1268
+ );
1269
+ }
1270
+ // mention (member or team)
1271
+ const isTeamMention = seg.suggestion.type === 'team';
1272
+ const colorSet = seg.suggestion.color
1273
+ ? getTeamColorSet(seg.suggestion.color)
1274
+ : isTeamMention
1275
+ ? nameColorSet(seg.suggestion.name, isLight)
1276
+ : null;
1277
+ const bg = colorSet ? getThemedBadge(colorSet, isLight) : DEFAULT_MENTION_BG;
1278
+ const fg = colorSet?.text ?? DEFAULT_MENTION_TEXT;
1279
+ return (
1280
+ <span
1281
+ key={idx}
1282
+ style={{
1283
+ backgroundColor: bg,
1284
+ color: fg,
1285
+ borderRadius: '3px',
1286
+ boxShadow: `0 0 0 1.5px ${bg}`,
1287
+ }}
1288
+ >
1289
+ {seg.value}
1290
+ </span>
1291
+ );
1292
+ })}{' '}
1293
+ </div>
1294
+ ) : null}
1295
+
1296
+ {taskSuggestions.length > 0 ? (
1297
+ <TaskReferenceInteractionLayer
1298
+ taskSuggestions={taskSuggestions}
1299
+ value={value}
1300
+ textareaRef={internalRef}
1301
+ scrollTop={scrollTop}
1302
+ />
1303
+ ) : null}
1304
+
1305
+ {value.includes('http://') || value.includes('https://') ? (
1306
+ <UrlInteractionLayer
1307
+ value={value}
1308
+ textareaRef={internalRef}
1309
+ scrollTop={scrollTop}
1310
+ onRemove={(match) => {
1311
+ const newText = removeUrlMatchFromText(value, match);
1312
+ onValueChange(newText);
1313
+ requestAnimationFrame(() => {
1314
+ internalRef.current?.setSelectionRange(match.start, match.start);
1315
+ });
1316
+ }}
1317
+ />
1318
+ ) : null}
1319
+
1320
+ {mentionOverlaySuggestions.length > 0 ? (
1321
+ <MentionInteractionLayer
1322
+ suggestions={mentionOverlaySuggestions}
1323
+ value={value}
1324
+ textareaRef={internalRef}
1325
+ scrollTop={scrollTop}
1326
+ />
1327
+ ) : null}
1328
+
1329
+ {slashCommand ? (
1330
+ <SlashCommandInteractionLayer
1331
+ command={slashCommand}
1332
+ definition={knownSlashCommand}
1333
+ value={value}
1334
+ textareaRef={internalRef}
1335
+ scrollTop={scrollTop}
1336
+ />
1337
+ ) : null}
1338
+
1339
+ <AutoResizeTextarea
1340
+ ref={setRefs}
1341
+ value={value}
1342
+ onChange={composedHandleChange}
1343
+ onKeyDown={composedHandleKeyDown}
1344
+ onSelect={composedHandleSelect}
1345
+ {...textareaProps}
1346
+ className={cn(className, hasCornerActions && cornerInsetClass)}
1347
+ onScroll={handleScroll}
1348
+ style={textareaStyle}
1349
+ />
1350
+
1351
+ {chips.length > 0 && onChipRemove ? (
1352
+ <ChipInteractionLayer
1353
+ chips={chips}
1354
+ value={value}
1355
+ textareaRef={internalRef}
1356
+ scrollTop={scrollTop}
1357
+ onRemove={handleChipRemove}
1358
+ />
1359
+ ) : null}
1360
+
1361
+ {/* Gradient fade overlay before corner action buttons */}
1362
+ {hasCornerActions ? (
1363
+ <div
1364
+ className="pointer-events-none absolute inset-x-0 bottom-0 z-[15] rounded-b-md"
1365
+ style={{
1366
+ height: cornerFadeHeight,
1367
+ background: `linear-gradient(to bottom, transparent 0%, ${surfaceFadeColor} 75%)`,
1368
+ }}
1369
+ />
1370
+ ) : null}
1371
+
1372
+ {cornerAction ? (
1373
+ <div
1374
+ className={cn(
1375
+ 'pointer-events-none absolute right-2 z-20 flex items-end justify-end',
1376
+ cornerActionOffsetClass
1377
+ )}
1378
+ >
1379
+ <div className="pointer-events-auto">{cornerAction}</div>
1380
+ </div>
1381
+ ) : null}
1382
+
1383
+ {cornerActionLeft ? (
1384
+ <div
1385
+ className={cn(
1386
+ 'pointer-events-none absolute left-2 z-20 flex items-end justify-start',
1387
+ cornerActionOffsetClass
1388
+ )}
1389
+ >
1390
+ <div className="pointer-events-auto">{cornerActionLeft}</div>
1391
+ </div>
1392
+ ) : null}
1393
+ </div>
1394
+
1395
+ {showFooter ? (
1396
+ <div className="mt-1 flex items-start justify-between gap-2">
1397
+ {showHintRow ? (
1398
+ <span
1399
+ className="block min-h-6 flex-1 overflow-hidden text-[10px] leading-3 text-[var(--color-text-muted)] transition-opacity duration-300"
1400
+ style={{ opacity: tipVisible ? 1 : 0, maxHeight: '1.5rem' }}
1401
+ >
1402
+ {resolvedHintText}
1403
+ </span>
1404
+ ) : (
1405
+ <span className="min-h-6 flex-1" />
1406
+ )}
1407
+ {footerRight}
1408
+ </div>
1409
+ ) : null}
1410
+ {isOpen && dropdownPosition ? (
1411
+ <div className="absolute left-0 z-50 w-full" style={{ top: `${dropdownPosition.top}px` }}>
1412
+ <MentionSuggestionList
1413
+ suggestions={effectiveSuggestions}
1414
+ selectedIndex={selectedIndex}
1415
+ onSelect={handleActiveSelect}
1416
+ query={query}
1417
+ hasFileSearch={enableFiles}
1418
+ filesLoading={enableFiles && filesLoading && activeTriggerChar === '@'}
1419
+ />
1420
+ </div>
1421
+ ) : null}
1422
+ </div>
1423
+ );
1424
+ }
1425
+ );
1426
+ MentionableTextarea.displayName = 'MentionableTextarea';