@runfusion/fusion 0.77.0-beta.4 → 0.77.0-beta.5

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 (161) hide show
  1. package/dist/bin.js +4051 -4144
  2. package/dist/child-process-worker.js +2681 -1719
  3. package/dist/client/.vite/manifest.json +261 -261
  4. package/dist/client/assets/{AgentDetailView-CH6GtXl9.js → AgentDetailView-CSK_Rnlk.js} +1 -1
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-YTEpMhUx.js → AgentPermissionPolicyEditor-kG44Adcm.js} +1 -1
  6. package/dist/client/assets/{AgentsView-XOHHDo4a.js → AgentsView-ClKwKWnU.js} +3 -3
  7. package/dist/client/assets/ChatView-DoOqgkPX.js +13 -0
  8. package/dist/client/assets/{CommandCenter-BsH-R15f.js → CommandCenter-CJxvPbgn.js} +1 -1
  9. package/dist/client/assets/{DevServerView-CKOa-lkc.js → DevServerView-C4nyLONX.js} +1 -1
  10. package/dist/client/assets/{DirectoryPicker-DHUYTE-j.js → DirectoryPicker-BIvXWIB5.js} +1 -1
  11. package/dist/client/assets/{DocumentsView-BPzrxeP-.js → DocumentsView-DH_aZysM.js} +1 -1
  12. package/dist/client/assets/{EvalsView-DojCiv47.js → EvalsView-klRK-GJQ.js} +1 -1
  13. package/dist/client/assets/{ExperimentalAgentOnboardingModal-DuurZ8qe.js → ExperimentalAgentOnboardingModal-CgBmukIm.js} +1 -1
  14. package/dist/client/assets/{GoalsView-DDWPXcG1.js → GoalsView-ysh3X2x6.js} +1 -1
  15. package/dist/client/assets/{InsightsView-CgkMOD1A.js → InsightsView-BbMjCu7J.js} +1 -1
  16. package/dist/client/assets/{MemoryView-Cj49_z7O.js → MemoryView-B3IgA8Bx.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-B_rRJiOd.js → PiExtensionsManager-CZlIw7C3.js} +1 -1
  18. package/dist/client/assets/{PluginManager-Dxwi88oY.js → PluginManager-vy0YZ2Nx.js} +1 -1
  19. package/dist/client/assets/{PullRequestView-z-5v2hQT.js → PullRequestView-DhhsJV8I.js} +1 -1
  20. package/dist/client/assets/{ReportModal-DmOPEYWp.js → ReportModal-CQMn4i1y.js} +1 -1
  21. package/dist/client/assets/{ResearchView-D90Jbzbx.js → ResearchView-CVwfs4l3.js} +1 -1
  22. package/dist/client/assets/{SecretsView-CSyjZl5L.js → SecretsView-CrJfHle9.js} +1 -1
  23. package/dist/client/assets/{SessionTerminal-Bwb8nGmU.js → SessionTerminal-BRI8W1-G.js} +1 -1
  24. package/dist/client/assets/{SettingsModal-CJof1Ett.js → SettingsModal-B6U5Umru.js} +1 -1
  25. package/dist/client/assets/SettingsModal-h1A_aFqD.js +21 -0
  26. package/dist/client/assets/{SettingsTextareaRow-BYchnHfW.js → SettingsTextareaRow-O7-u9uMC.js} +1 -1
  27. package/dist/client/assets/{SetupWizardModal-NqV-erVf.js → SetupWizardModal-nXfJp8cA.js} +2 -2
  28. package/dist/client/assets/{SkillsView-BUrkIJ-p.js → SkillsView-CoWAjvWU.js} +1 -1
  29. package/dist/client/assets/{WorkflowNodeEditor-DcPk2A1Z.js → WorkflowNodeEditor-BFMM3RF_.js} +2 -2
  30. package/dist/client/assets/{agent-import-generation-X16OLfrL.js → agent-import-generation-BqDmtTur.js} +1 -1
  31. package/dist/client/assets/{agentsOrgChartLayout-BhPIXckU.js → agentsOrgChartLayout-C4cLqlV6.js} +1 -1
  32. package/dist/client/assets/app-BBSLJDbV.js +13 -0
  33. package/dist/client/assets/app-BKwOvuxE.js +5 -0
  34. package/dist/client/assets/app-Bvr57EZQ.js +5 -0
  35. package/dist/client/assets/app-C_PTWuI1.js +13 -0
  36. package/dist/client/assets/app-DKx18PHE.js +13 -0
  37. package/dist/client/assets/app-DRW5hIgr.js +13 -0
  38. package/dist/client/assets/app-DwvelD-n.js +13 -0
  39. package/dist/client/assets/{architectureDiagram-3BPJPVTR-WArMtdqy.js → architectureDiagram-3BPJPVTR-CdxcwdRe.js} +1 -1
  40. package/dist/client/assets/{blockDiagram-GPEHLZMM-emScogdV.js → blockDiagram-GPEHLZMM-CfQrRfHR.js} +1 -1
  41. package/dist/client/assets/{c4Diagram-AAUBKEIU-CBY7-E0T.js → c4Diagram-AAUBKEIU-Cx7-2SOm.js} +1 -1
  42. package/dist/client/assets/channel-B4WN1jC_.js +1 -0
  43. package/dist/client/assets/{chunk-2J33WTMH-Bcai1sOm.js → chunk-2J33WTMH-D8jvgP3M.js} +1 -1
  44. package/dist/client/assets/{chunk-4BX2VUAB-hjiKRusj.js → chunk-4BX2VUAB-B5tBx_s_.js} +1 -1
  45. package/dist/client/assets/{chunk-55IACEB6-DpO9nIb0.js → chunk-55IACEB6-C-F-HQ5Z.js} +1 -1
  46. package/dist/client/assets/{chunk-727SXJPM-B9JanA0o.js → chunk-727SXJPM-BP8Ln-8C.js} +1 -1
  47. package/dist/client/assets/{chunk-AQP2D5EJ-D6zdnEUE.js → chunk-AQP2D5EJ-DMnTmRmn.js} +1 -1
  48. package/dist/client/assets/{chunk-FMBD7UC4-CRkrJ51d.js → chunk-FMBD7UC4-D_YdfnNc.js} +1 -1
  49. package/dist/client/assets/{chunk-ND2GUHAM-BLQsKt7a.js → chunk-ND2GUHAM-CULXyuXq.js} +1 -1
  50. package/dist/client/assets/{chunk-QZHKN3VN-MCOlJ723.js → chunk-QZHKN3VN-CT1BWEJL.js} +1 -1
  51. package/dist/client/assets/classDiagram-4FO5ZUOK-CKE8RSOv.js +1 -0
  52. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CKE8RSOv.js +1 -0
  53. package/dist/client/assets/{cose-bilkent-S5V4N54A-Cv1XmKKG.js → cose-bilkent-S5V4N54A-M-3DXa6e.js} +1 -1
  54. package/dist/client/assets/{dagre-BM42HDAG-flnNS_RW.js → dagre-BM42HDAG-Bsiqvroz.js} +1 -1
  55. package/dist/client/assets/{dashboard-view-CrV-rL9Q.js → dashboard-view-BEBh_Ei5.js} +1 -1
  56. package/dist/client/assets/{dashboard-view-Dz7kqcJc.js → dashboard-view-Bo_gFjdO.js} +1 -1
  57. package/dist/client/assets/{dashboard-view-CC1aH-lp.js → dashboard-view-CnFFG3cW.js} +1 -1
  58. package/dist/client/assets/{dashboard-view-DEAYb_TZ.js → dashboard-view-DAHn20ph.js} +1 -1
  59. package/dist/client/assets/{diagram-2AECGRRQ-Z3S7b_6_.js → diagram-2AECGRRQ-CZiHoXo5.js} +1 -1
  60. package/dist/client/assets/{diagram-5GNKFQAL-BAZHdMFq.js → diagram-5GNKFQAL-BoJVz4Or.js} +1 -1
  61. package/dist/client/assets/{diagram-KO2AKTUF-C2y3S8F0.js → diagram-KO2AKTUF-DivGQuAL.js} +1 -1
  62. package/dist/client/assets/{diagram-LMA3HP47-Bfz0_IvT.js → diagram-LMA3HP47-DkMK7OJp.js} +1 -1
  63. package/dist/client/assets/{diagram-OG6HWLK6-BBmSQsTI.js → diagram-OG6HWLK6-DFFvRcpW.js} +1 -1
  64. package/dist/client/assets/{erDiagram-TEJ5UH35-DnpdQi66.js → erDiagram-TEJ5UH35--217vrom.js} +1 -1
  65. package/dist/client/assets/{flowDiagram-I6XJVG4X-IybTR_zf.js → flowDiagram-I6XJVG4X-CQgWO3xf.js} +1 -1
  66. package/dist/client/assets/{folder-open-Dntm63x4.js → folder-open-DR6cRcNR.js} +1 -1
  67. package/dist/client/assets/{ganttDiagram-6RSMTGT7-DEQOe2E9.js → ganttDiagram-6RSMTGT7-BjDMUrS3.js} +1 -1
  68. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BOKc-h63.js → gitGraphDiagram-PVQCEYII-gKUcDnln.js} +1 -1
  69. package/dist/client/assets/index-Dki2LBAp.css +1 -0
  70. package/dist/client/assets/index-oxnX59eO.js +2774 -0
  71. package/dist/client/assets/{infoDiagram-5YYISTIA-LqaYIdbj.js → infoDiagram-5YYISTIA-BA91T8S5.js} +1 -1
  72. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-a8qd512s.js → ishikawaDiagram-YF4QCWOH-0BY5xe-c.js} +1 -1
  73. package/dist/client/assets/{journeyDiagram-JHISSGLW-BgoNyeiy.js → journeyDiagram-JHISSGLW-B_OwenbQ.js} +1 -1
  74. package/dist/client/assets/{kanban-definition-UN3LZRKU-Bqwow7D3.js → kanban-definition-UN3LZRKU-GLabUTKp.js} +1 -1
  75. package/dist/client/assets/{mermaid.core-B2zD934i.js → mermaid.core-BXo4rxYI.js} +4 -4
  76. package/dist/client/assets/{mindmap-definition-RKZ34NQL-CCTOigWu.js → mindmap-definition-RKZ34NQL-DZl6LPoE.js} +1 -1
  77. package/dist/client/assets/{pieDiagram-4H26LBE5-Bq5DtXKR.js → pieDiagram-4H26LBE5-DtHq-4py.js} +1 -1
  78. package/dist/client/assets/{puzzle-VhTPiCit.js → puzzle-OVm-I1L4.js} +1 -1
  79. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CGMP3nUx.js → quadrantDiagram-W4KKPZXB-BdjXhd5d.js} +1 -1
  80. package/dist/client/assets/{requirementDiagram-4Y6WPE33-Ckeu_szu.js → requirementDiagram-4Y6WPE33-BoFVjELN.js} +1 -1
  81. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-SWbBDD4d.js → sankeyDiagram-5OEKKPKP-B0qyJh-P.js} +1 -1
  82. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-CiJrmL_G.js → sequenceDiagram-3UESZ5HK-ByY62Eqp.js} +1 -1
  83. package/dist/client/assets/{shield-alert-BBDlP6A5.js → shield-alert-CDy69fl7.js} +1 -1
  84. package/dist/client/assets/{standing-instructions-template-viu_kgDX.js → standing-instructions-template-BsnnRlwm.js} +1 -1
  85. package/dist/client/assets/{stateDiagram-AJRCARHV-DTCzK5Gt.js → stateDiagram-AJRCARHV-CwJ-_Phi.js} +1 -1
  86. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-BIGAwFTT.js → stateDiagram-v2-BHNVJYJU-Cfvhq8mV.js} +1 -1
  87. package/dist/client/assets/{timeline-definition-PNZ67QCA-BQZEFEug.js → timeline-definition-PNZ67QCA-Co8VfGN9.js} +1 -1
  88. package/dist/client/assets/{upload-D5w3Ehwp.js → upload-CkqDbEeE.js} +1 -1
  89. package/dist/client/assets/{useDiscoveredSkillsCache-D6zMSIaS.js → useDiscoveredSkillsCache-BHUasRiZ.js} +1 -1
  90. package/dist/client/assets/{users-Bohihi_o.js → users-B8DkpbXD.js} +1 -1
  91. package/dist/client/assets/{vennDiagram-CIIHVFJN-DnHguEv8.js → vennDiagram-CIIHVFJN-XSJteQrL.js} +1 -1
  92. package/dist/client/assets/{wardley-L42UT6IY-BOqYltGN.js → wardley-L42UT6IY-Btc0FRfF.js} +1 -1
  93. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Re0Ery2M.js → wardleyDiagram-YWT4CUSO--IcDNmrf.js} +1 -1
  94. package/dist/client/assets/{xychartDiagram-2RQKCTM6-CnVq21b2.js → xychartDiagram-2RQKCTM6-CZW93G6X.js} +1 -1
  95. package/dist/client/index.html +2 -2
  96. package/dist/client/version.json +1 -1
  97. package/dist/droid-cli/package.json +1 -1
  98. package/dist/extension.js +3085 -2130
  99. package/dist/migrations/0000_initial.sql +3 -0
  100. package/dist/migrations/0061_fn_066_activity_log_task_id_index.sql +7 -0
  101. package/dist/migrations/0062_remove_task_subtask_splitting.sql +2 -0
  102. package/dist/migrations/0063_fn_090_ai_merge_review_reconciliation.sql +2 -0
  103. package/dist/migrations/0064_fn_094_task_repository_scope.sql +2 -0
  104. package/dist/pi-claude-cli/package.json +1 -1
  105. package/dist/plugin-sdk/index.d.ts +276 -186
  106. package/dist/plugin-sdk/index.js +35 -104
  107. package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +35 -104
  108. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  109. package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +35 -104
  110. package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
  111. package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +35 -104
  112. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  113. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +35 -104
  114. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  115. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +35 -104
  116. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  117. package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +35 -104
  118. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  119. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +35 -104
  120. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  121. package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +35 -104
  122. package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
  123. package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +35 -104
  124. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  125. package/dist/plugins/fusion-plugin-linear-import/bundled.js +35 -104
  126. package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
  127. package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +35 -104
  128. package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
  129. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +35 -104
  130. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  131. package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +35 -104
  132. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  133. package/dist/plugins/fusion-plugin-quality/bundled.js +35 -104
  134. package/dist/plugins/fusion-plugin-quality/package.json +1 -1
  135. package/dist/plugins/fusion-plugin-reports/bundled.js +35 -104
  136. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  137. package/dist/plugins/fusion-plugin-roadmap/bundled.js +35 -104
  138. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  139. package/dist/plugins/fusion-plugin-todos/bundled.js +35 -104
  140. package/dist/plugins/fusion-plugin-todos/package.json +1 -1
  141. package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +35 -104
  142. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  143. package/package.json +1 -1
  144. package/skill/fusion/references/extension-tools.md +2 -1
  145. package/skill/fusion/references/fusion-capabilities.md +1 -1
  146. package/skill/fusion/references/task-structure.md +1 -1
  147. package/skill/fusion/workflows/specifications.md +2 -2
  148. package/dist/client/assets/ChatView-gH7QX3TI.js +0 -13
  149. package/dist/client/assets/SettingsModal-BAzmMjr9.js +0 -21
  150. package/dist/client/assets/app-B-TfWH9b.js +0 -5
  151. package/dist/client/assets/app-B2RDV_-t.js +0 -13
  152. package/dist/client/assets/app-CDo0mF2S.js +0 -5
  153. package/dist/client/assets/app-Cc18kAQS.js +0 -13
  154. package/dist/client/assets/app-DFF79EUn.js +0 -13
  155. package/dist/client/assets/app-DSeFHxgj.js +0 -13
  156. package/dist/client/assets/app-Ducr0y6r.js +0 -13
  157. package/dist/client/assets/channel-CP2ySYs0.js +0 -1
  158. package/dist/client/assets/classDiagram-4FO5ZUOK-DKkOBtzM.js +0 -1
  159. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DKkOBtzM.js +0 -1
  160. package/dist/client/assets/index-DXpztECA.css +0 -1
  161. package/dist/client/assets/index-I32FijPT.js +0 -2821
@@ -163136,6 +163136,7 @@ var tasks = projectSchema.table("tasks", {
163136
163136
  mergerModelId: text("merger_model_id"),
163137
163137
  mergerThinkingLevel: text("merger_thinking_level"),
163138
163138
  mergeRetries: integer("merge_retries"),
163139
+ aiMergeReviewReconciliation: text("ai_merge_review_reconciliation"),
163139
163140
  workflowStepRetries: integer("workflow_step_retries"),
163140
163141
  resumeLimboCount: integer("resume_limbo_count").default(0),
163141
163142
  graphResumeRetryCount: integer("graph_resume_retry_count").default(0),
@@ -163258,7 +163259,8 @@ var tasks = projectSchema.table("tasks", {
163258
163259
  sourceIssueClosedAt: text("source_issue_closed_at"),
163259
163260
  mergeDetails: jsonb("merge_details"),
163260
163261
  workspaceWorktrees: jsonb("workspace_worktrees"),
163261
- breakIntoSubtasks: integer("break_into_subtasks").default(0),
163262
+ // FNXC:RepositoryScope 2026-08-20-23:07: explicit task intent must survive PostgreSQL reads independently of acquired worktrees.
163263
+ repositoryScope: jsonb("repository_scope"),
163262
163264
  noCommitsExpected: integer("no_commits_expected").default(0),
163263
163265
  enabledWorkflowSteps: jsonb("enabled_workflow_steps").default([]),
163264
163266
  modifiedFiles: jsonb("modified_files").default([]),
@@ -165578,7 +165580,8 @@ var centralActivityLog = centralSchema.table("central_activity_log", {
165578
165580
  foreignKey({ columns: [t.projectId], foreignColumns: [projects.id] }).onDelete("cascade"),
165579
165581
  index("idxActivityLogTimestamp").on(t.timestamp),
165580
165582
  index("idxActivityLogType").on(t.type),
165581
- index("idxActivityLogProjectId").on(t.projectId)
165583
+ index("idxActivityLogProjectId").on(t.projectId),
165584
+ index("idxCentralActivityLogTaskIdTimestamp").on(t.taskId, t.timestamp)
165582
165585
  ]);
165583
165586
  var centralSettings = centralSchema.table("central_settings", {
165584
165587
  id: integer("id").primaryKey(),
@@ -166286,6 +166289,15 @@ var DEFAULT_GLOBAL_SETTINGS = {
166286
166289
  opt in before Fusion replaces its own binary and bounces the process under them.
166287
166290
  */
166288
166291
  autoUpdateAndRestart: false,
166292
+ /*
166293
+ FNXC:UpdateAutomation 2026-08-21-02:17:
166294
+ Fresh installations require separate opt-ins for unattended installation and
166295
+ restart. The legacy combined switch remains false and is only a fallback for
166296
+ older persisted settings.
166297
+ */
166298
+ /* FNXC:UpdateAutomation 2026-08-21-02:48: Keep these schema keys unset because defaults merge into effective settings and `undefined` is distinct from explicit false. */
166299
+ autoUpdateEnabled: void 0,
166300
+ autoRestartAfterUpdate: void 0,
166289
166301
  autoReloadOnVersionChange: true,
166290
166302
  githubTrackingDefaultRepo: void 0,
166291
166303
  reportRoadmapDedupeEnabled: void 0,
@@ -166296,6 +166308,13 @@ var DEFAULT_GLOBAL_SETTINGS = {
166296
166308
  gitlabApiBaseUrl: void 0,
166297
166309
  gitlabAuthToken: void 0,
166298
166310
  gitlabAuthTokenType: void 0,
166311
+ jiraEnabled: void 0,
166312
+ jiraBaseUrl: void 0,
166313
+ jiraApiBaseUrl: void 0,
166314
+ jiraAuthEmail: void 0,
166315
+ jiraAuthTokenSecretKey: void 0,
166316
+ jiraAuthTokenSecretScope: void 0,
166317
+ jiraBranchNameTemplate: void 0,
166299
166318
  modelOnboardingComplete: void 0,
166300
166319
  useClaudeCli: void 0,
166301
166320
  useDroidCli: void 0,
@@ -166786,6 +166805,13 @@ var DEFAULT_PROJECT_SETTINGS = {
166786
166805
  gitlabApiBaseUrl: void 0,
166787
166806
  gitlabAuthToken: void 0,
166788
166807
  gitlabAuthTokenType: void 0,
166808
+ jiraEnabled: void 0,
166809
+ jiraBaseUrl: void 0,
166810
+ jiraApiBaseUrl: void 0,
166811
+ jiraAuthEmail: void 0,
166812
+ jiraAuthTokenSecretKey: void 0,
166813
+ jiraAuthTokenSecretScope: void 0,
166814
+ jiraBranchNameTemplate: void 0,
166789
166815
  gitlabCommentOnDone: false,
166790
166816
  gitlabCommentTemplate: void 0,
166791
166817
  gitlabCloseSourceIssueOnDone: false,
@@ -169582,17 +169608,6 @@ var BUILTIN_MOVED_WORKFLOW_SETTINGS = [
169582
169608
  }
169583
169609
  ];
169584
169610
  var BUILTIN_TRIAGE_POLICY_SETTINGS = [
169585
- {
169586
- id: "triageProactiveSubtaskSplittingEnabled",
169587
- name: "Triage proactive subtask splitting",
169588
- type: "boolean",
169589
- default: true,
169590
- /*
169591
- * FNXC:TriagePolicy 2026-07-04-00:00:
169592
- * Operators need a workflow/project policy switch that disables automatic large-task splitting without weakening explicit `breakIntoSubtasks: true` requests. Keep the default enabled to preserve existing triage behavior for workflows that have no stored override.
169593
- */
169594
- description: "Enable automatic large-task splitting guidance during triage. Turn off to split only when breakIntoSubtasks is explicitly requested."
169595
- },
169596
169611
  {
169597
169612
  id: "triageSizeSmallMaxHours",
169598
169613
  name: "Triage size S max hours",
@@ -169614,48 +169629,6 @@ var BUILTIN_TRIAGE_POLICY_SETTINGS = [
169614
169629
  default: 8,
169615
169630
  description: "Upper hour boundary for Size L triage guidance; larger work should split as XL."
169616
169631
  },
169617
- {
169618
- id: "triageSubtaskStepThreshold",
169619
- name: "Triage subtask step threshold",
169620
- type: "number",
169621
- default: 7,
169622
- description: "Implementation-step count above which triage should consider splitting an M/L task."
169623
- },
169624
- {
169625
- id: "triageSubtaskLargeStepSignal",
169626
- name: "Triage large-step signal",
169627
- type: "number",
169628
- default: 9,
169629
- description: "Planned step count that is a broad-scope decomposition signal for Size L tasks."
169630
- },
169631
- {
169632
- id: "triageSubtaskAdditiveStepSignal",
169633
- name: "Triage additive step signal",
169634
- type: "number",
169635
- default: 12,
169636
- description: "Implementation-step count that independently signals possible partitioning."
169637
- },
169638
- {
169639
- id: "triageSubtaskPackageThreshold",
169640
- name: "Triage package/module threshold",
169641
- type: "number",
169642
- default: 3,
169643
- description: "Distinct package/module count above which triage should consider splitting coherent M/L work."
169644
- },
169645
- {
169646
- id: "triageSubtaskFileScopeThreshold",
169647
- name: "Triage file-scope threshold",
169648
- type: "number",
169649
- default: 20,
169650
- description: "File Scope entry count that signals broad work likely needing partitioning."
169651
- },
169652
- {
169653
- id: "triageSubtaskRemediationBatchThreshold",
169654
- name: "Triage remediation batch threshold",
169655
- type: "number",
169656
- default: 30,
169657
- description: "Quantified remediation batch size that strongly signals subsystem partitioning."
169658
- },
169659
169632
  {
169660
169633
  id: "triageNoCommitsDecisionVerbs",
169661
169634
  name: "Triage no-commits decision verbs",
@@ -170440,20 +170413,12 @@ When you plan to list a task in the \`## Dependencies\` section, first call \`fn
170440
170413
  Use what you learn \u2014 file scope, APIs, patterns, completion criteria \u2014 to make the new spec accurate: reference the right paths, avoid conflicting assumptions, and describe what the dependency must deliver before this task starts.
170441
170414
  If the dependency task has no PROMPT.md yet (not yet specified), note that in the Dependencies section.
170442
170415
 
170443
- ## Triage subtask breakdown
170444
- When the task includes \`breakIntoSubtasks: true\`, first decide whether it should be split.
170445
-
170446
- - Split only when the work is meaningfully decomposable into 2-5 independently executable child tasks.
170447
- - If splitting: use the \`fn_task_create\` tool to create child tasks in triage, include clear descriptions and dependencies between them, then stop. Do NOT write a PROMPT.md for the parent task.
170448
- - **CRITICAL \u2014 subtask dependencies:** the parent task is deleted once all subtasks are created. \`dependencies\` on a new subtask may ONLY reference sibling subtasks you have created earlier in this same split (or unrelated existing tasks). **Never depend on the parent task's id.** If a child conceptually "waits for the parent's remaining work", create a sibling subtask that does that work and depend on the sibling instead. The \`fn_task_create\` tool will reject parent-id dependencies with an error.
170449
- - If not splitting: proceed with a normal PROMPT.md specification.
170450
-
170451
- ## Proactive Subtask Breakdown for M/L Tasks
170416
+ ## One-task planning
170452
170417
  <!--
170453
- FNXC:TriagePolicy 2026-07-04-00:00:
170454
- Workflow policy can disable proactive oversized-task splitting for operators who want triage to keep large tasks whole by default. Explicit user-requested \`breakIntoSubtasks: true\` remains governed by the mandatory breakdown section above and must not be weakened by this toggle.
170418
+ FNXC:TriagePlanning 2026-08-20-17:42:
170419
+ Complexity never authorizes replacing a requested task with child tasks. Preserve the original task ID, dependencies, and documents; write one complete, detailed PROMPT.md with focused steps, realistic scope, risks, and quality gates.
170455
170420
  -->
170456
- {{triageProactiveSubtaskSplittingEnabled}}
170421
+ Create independent follow-up tasks only when they are genuinely separate work, never as an automatic decomposition of the task being planned.
170457
170422
 
170458
170423
  ## Triage tools
170459
170424
  You have these extra tools during triage:
@@ -170512,7 +170477,7 @@ This bullet is the planning-side half of the artifact-pipeline contract; keep it
170512
170477
  -->
170513
170478
  - For tasks with a visible UI surface or whose deliverable is visual/media (wireframes, mockups, designs, diagrams, screenshots, screen recordings, HTML prototypes, PDF exports), include an explicit step or checkbox instructing the executor to save each deliverable to disk and register it via \`fn_artifact_register\` (images via \`type="image", path=...\`; recordings via \`type="video", path=...\`; HTML mockups via \`type="document", mimeType="text/html"\` for live gallery previews; PDFs via \`type="document", mimeType="application/pdf", path=...\`) so it appears in the dashboard Artifacts gallery
170514
170479
  - Include a "Do NOT" section with project-appropriate guardrails
170515
- - Size assessment: S (<{{triageSizeSmallMaxHours}}h), M ({{triageSizeSmallMaxHours}}-{{triageSizeMediumMaxHours}}h), L ({{triageSizeMediumMaxHours}}-{{triageSizeLargeMaxHours}}h). Split if XL ({{triageSizeLargeMaxHours}}h+)
170480
+ - Size assessment: S (<{{triageSizeSmallMaxHours}}h), M ({{triageSizeSmallMaxHours}}-{{triageSizeMediumMaxHours}}h), L ({{triageSizeMediumMaxHours}}-{{triageSizeLargeMaxHours}}h+). Keep every requested task as one detailed plan regardless of size.
170516
170481
  - Review level scoring: Blast radius (0-2), Pattern novelty (0-2), Security (0-2), Reversibility (0-2)
170517
170482
  - 0-1 \u2192 Level 0, 2-3 \u2192 Level 1, 4-5 \u2192 Level 2, 6-8 \u2192 Level 3
170518
170483
 
@@ -170527,11 +170492,11 @@ FNXC:WorkflowRouting 2026-06-22-17:24:
170527
170492
  Standard triage must not infer workflow changes from task type. Agents preserve the project default unless the user names or explicitly requests a workflow, or the agent created the task; no-commit decisions use the header marker without automatic workflow selection.
170528
170493
  -->
170529
170494
  ## Workflow Routing
170530
- - Keep the project default workflow (\`{{triageDefaultWorkflowId}}\`) unless the user explicitly requested a specific workflow for this task or subtask, or you created that task yourself.
170495
+ - Keep the project default workflow (\`{{triageDefaultWorkflowId}}\`) unless the user explicitly requested a specific workflow for this task, or you created that task yourself.
170531
170496
  - Do NOT call \`fn_workflow_select\` or pass \`workflow_id\` to \`fn_task_create\` just because a task looks like investigation, audit, research, operational routing/coordination, decision-only work, or standard coding work.
170532
170497
  - When you create a task via \`fn_task_create\` or \`fn_delegate_task\`, you may select that created task's workflow with \`workflow_id\` at create time or \`fn_workflow_select\` afterward; do not move a task you did not create unless the user asked.
170533
170498
  - For decision-only tasks ({{triageNoCommitsDecisionVerbs}}) or other no-code tasks, set \`**No commits expected:** true\` in the PROMPT.md header when the no-commits criteria above are met; this is a header marker only and does not select \`{{triageDecisionOnlyWorkflowId}}\` or any custom investigation workflow by itself.
170534
- - If the user explicitly asks for a workflow, call \`fn_workflow_list\` to discover valid IDs, then use \`fn_workflow_select\` to set the workflow on the current task or pass \`workflow_id\` to \`fn_task_create\` when creating a requested subtask.
170499
+ - If the user explicitly asks for a workflow, call \`fn_workflow_list\` to discover valid IDs, then use \`fn_workflow_select\` to set the workflow on the current task or pass \`workflow_id\` to \`fn_task_create\` when creating requested independent work.
170535
170500
 
170536
170501
  ## Plan Review
170537
170502
 
@@ -170678,45 +170643,12 @@ Concrete examples:
170678
170643
  - **Documentation completeness:** [Must Update / Check If Affected sections present?]
170679
170644
  - **Dangling task-document references:** [No \`.fusion/tasks/<id>/<file>\` path is cited in Context, Steps, or File Scope unless the file exists or is explicitly created as a \`(new)\` artifact in this spec. References to nonexistent task-local artifacts are a blocking REVISE.]
170680
170645
  - **Sizing & review level:** [Size and review level appropriate for the work?]
170681
- - **Subtask breakdown:** [Only flag genuinely oversized specs (12+ implementation steps, OR 5+ truly independent deliverables that could ship separately). Do NOT flag a coherent vertical change just because it touches multiple packages. When borderline, prefer leaving the task whole.]
170682
170646
  - **User comment coverage:** [Were all user comments addressed? Every user comment must be reflected in the spec \u2014 missing coverage is a blocking REVISE]
170683
170647
 
170684
170648
  ### Suggestions
170685
170649
  - [Optional improvements, not blocking]
170686
170650
  \`\`\`
170687
170651
 
170688
- ## Spec Review \u2014 Undersplit Task Detection
170689
-
170690
- When reviewing specs, assess whether the task should have been broken into subtasks. The bar for splitting is high \u2014 most tasks should remain whole. Coordination overhead (worktrees, dependency wiring, merge sequencing) is real, so splitting must clearly pay for itself.
170691
-
170692
- **Default position:** do NOT flag undersplit. Reach for it only when the spec is genuinely oversized.
170693
-
170694
- **Flag as REVISE only when ALL of the following are true:**
170695
- - The spec has 12+ implementation steps, OR contains 5+ clearly independent deliverables that could be shipped separately by different people
170696
- - The deliverables are NOT a coherent vertical change (a single feature touching core + dashboard + tests is coherent \u2014 do not split it)
170697
- - Splitting would produce children that each have \u22654 steps and a clearly distinct scope
170698
-
170699
- If the spec is borderline (under those thresholds, or arguable), put your splitting suggestion in the **Suggestions** section instead of REVISE \u2014 the planner can take it or leave it.
170700
-
170701
- **How to flag an undersplit task (only when the criteria above are met):**
170702
- Say explicitly: "This task should be broken into subtasks because [specific reason]."
170703
- Recommend the number of child tasks (2-5) and what each should cover.
170704
- Instruct the planner to:
170705
- 1. Use the \`fn_task_create\` tool to create 2\u20135 child tasks from the oversized spec
170706
- 2. Do NOT write a parent PROMPT.md \u2014 the parent will be closed automatically after children are created
170707
- (Not write a parent PROMPT.md is also unacceptable.)
170708
- 3. Make each child cover one coherent deliverable with clear scope boundaries
170709
-
170710
- Example REVISE feedback for a genuinely oversized task:
170711
- "This task has 14 steps and contains 4 independent deliverables (engine integration, dashboard UI, CLI command, migration tooling) that could ship separately. Use fn_task_create to split into: (1) engine logic, (2) dashboard UI, (3) CLI integration, (4) migration tooling. Do not write a parent PROMPT."
170712
-
170713
- **Do NOT flag if ANY of these apply:**
170714
- - The spec has 11 or fewer implementation steps
170715
- - Steps are sequential and tightly coupled (e.g., a pipeline where each step depends on the previous)
170716
- - The task is a vertical change touching multiple packages for one coherent feature (typical in this monorepo)
170717
- - The task is a bug fix, regardless of how many files it touches
170718
- - Splitting would create coordination overhead that exceeds the benefit
170719
-
170720
170652
  ## Plan Granularity
170721
170653
 
170722
170654
  When reviewing plans, assess whether the approach achieves the step's OUTCOMES \u2014
@@ -171018,7 +170950,6 @@ submissions to a high bar for correctness, security, and maintainability.
171018
170950
  - **Surface enumeration:** [For bug-fix specs, is \`## Surface Enumeration\` present and does it enumerate the relevant providers/bridges/execution paths, desktop + mobile breakpoints/platforms, empty/undefined/duplicate/populated states, and shared hooks/components/modules/helpers? Missing or incomplete coverage is a blocking REVISE.]
171019
170951
  - **Documentation completeness:** [Must Update / Check If Affected sections present?]
171020
170952
  - **Sizing & review level:** [Size and review level appropriate for the work?]
171021
- - **Subtask breakdown:** [Were complex tasks appropriately split into 2-5 child tasks?]
171022
170953
  - **User comment coverage:** [Were all user comments addressed? Every user comment must be reflected in the spec \u2014 missing coverage is a blocking REVISE]
171023
170954
  - **Security considerations:** [Are security-sensitive areas identified and addressed?]
171024
170955
  - **Edge case coverage:** [Does the spec account for failure modes and boundary conditions?]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/whatsapp-chat",
3
- "version": "0.1.55-beta.4",
3
+ "version": "0.1.55-beta.5",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runfusion/fusion",
3
- "version": "0.77.0-beta.4",
3
+ "version": "0.77.0-beta.5",
4
4
  "license": "MIT",
5
5
  "description": "Fusion CLI: HTTP API server, daemon, dashboard launcher, and task tooling for the Fusion AI coding agent.",
6
6
  "homepage": "https://github.com/Runfusion/Fusion#readme",
@@ -143,13 +143,14 @@ Unarchive an archived task (move from archived → its restore column). Restores
143
143
 
144
144
  ### fn_task_delete
145
145
 
146
- Soft-delete a task from active Fusion board views. The task row and artifacts are preserved; optional allowResurrection marks the ID for intentional recreation. If the task is still referenced as a lineage parent by another task, deletion is rejected unless removeLineageReferences:true is passed.
146
+ Soft-delete a task from active Fusion board views. The task row and artifacts are preserved; optional allowResurrection marks the ID for intentional recreation. If live lineage children or dependents still reference the task, deletion is rejected unless the matching explicit reference-removal option is passed.
147
147
 
148
148
  | Parameter | Type | Required | Description |
149
149
  |-----------|------|----------|-------------|
150
150
  | `id` | string | ✓ | Task ID to delete (e.g. FN-001) |
151
151
  | `allowResurrection` | boolean | — | When true, mark this tombstone as explicitly reusable for future recreation. |
152
152
  | `removeLineageReferences` | boolean | — | When true, clear incoming lineage-parent references (child sourceParentTaskId) before deleting, so a task still referenced as a lineage parent can be removed. |
153
+ | `removeDependencyReferences` | boolean | — | When true, remove incoming dependency edges before soft deletion. Omit or pass false to retain the dependent-conflict refusal. |
153
154
 
154
155
  ### fn_task_browse_gitlab_project_issues
155
156
 
@@ -36,7 +36,7 @@ All skill/extension tool invocations in this catalog use the public `fn_*` names
36
36
  | `fn_task_refine` | Request a refinement of a completed or in-review task. Creates a new follow-up task in planning that references the original task as a dependency. Use this when a done or in-review task needs additional work, improvements, or follow-up changes. |
37
37
  | `fn_task_archive` | Archive a task from any live column (move to archived). Archived tasks are preserved for historical reference but moved out of the main board view. If the task is still referenced as a lineage parent by another task, archiving is rejected unless removeLineageReferences:true is passed. |
38
38
  | `fn_task_unarchive` | Unarchive an archived task (move from archived → its restore column). Restores to the pre-archive column when available, with active execution columns downgraded to todo. |
39
- | `fn_task_delete` | Soft-delete a task from active Fusion board views. The task row and artifacts are preserved; optional allowResurrection marks the ID for intentional recreation. If the task is still referenced as a lineage parent by another task, deletion is rejected unless removeLineageReferences:true is passed. |
39
+ | `fn_task_delete` | Soft-delete a task from active Fusion board views. The task row and artifacts are preserved; optional allowResurrection marks the ID for intentional recreation. If live lineage children or dependents still reference the task, deletion is rejected unless the matching explicit reference-removal option is passed. |
40
40
  | `fn_task_import_github` | Import GitHub issues as Fusion tasks. Fetches open issues from a repository and creates tasks in the planning column. Each task includes the issue title and body with a link to the source issue. |
41
41
  | `fn_task_import_github_issue` | Import a specific GitHub issue as a Fusion task. Fetches the issue by number and creates a single task in the planning column with the issue title and body. |
42
42
  | `fn_task_browse_github_issues` | List open GitHub issues from a repository to browse before importing. Returns issue numbers, titles, and URLs for selection. Use with fn_task_import_github_issue to import specific issues by number. |
@@ -134,7 +134,7 @@ What the task should accomplish.
134
134
  }
135
135
  ```
136
136
 
137
- > **Note:** `maxConcurrent` applies to task-lane agents (triage, execution, merge) only. Utility AI workflows—planning mode, subtask breakdown, mission interviews, agent heartbeat/chat wake, and title summarization—run outside this limit on a dedicated control-plane lane.
137
+ > **Note:** `maxConcurrent` applies to task-lane agents (triage, execution, merge) only. Utility AI workflows—planning mode, mission interviews, agent heartbeat/chat wake, and title summarization—run outside this limit on a dedicated control-plane lane.
138
138
 
139
139
  ## Global Settings
140
140
 
@@ -58,8 +58,8 @@ fn_task_plan({ description: "Build a notification system for the app" })
58
58
  The planning mode will:
59
59
  1. Ask clarifying questions about scope, channels (email, push, in-app), users
60
60
  2. Identify technical constraints and dependencies
61
- 3. Suggest breaking the work into multiple tasks if needed
62
- 4. Create a well-specified task (or multiple subtasks)
61
+ 3. Develop one complete plan with concrete, defined steps
62
+ 4. Create one well-specified task that retains the original request
63
63
 
64
64
  **Organizing with Missions:**
65
65
 
@@ -1,13 +0,0 @@
1
- import{r as a,j as t}from"./vendor-react-SZ_qB27O.js";import{c as Ps,S as an,r as St,e as ss,cL as rs,dq as Ar,dr as Tr,ds as Xn,b as q,dt as Er,du as Tt,dv as Nt,dw as sa,dx as Dr,dy as Ir,dz as Lr,dA as Fr,dB as Pr,dC as $r,bj as _r,d0 as ra,ar as ln,dD as zr,dE as Br,bU as Or,K as Ur,aK as Hr,b5 as cn,a2 as Kr,db as Vr,dF as qr,dG as Wr,a_ as Qr,dH as Xr,dI as $s,dJ as _s,dK as Gr,dL as Yr,W as Jr,dM as Zr,dN as eo,dO as ze,dP as os,dQ as is,dR as to,dS as no,dT as cs,G as ao,dU as so,z as ro,B as oo,aI as io,V as co,bW as lo,P as sn,dg as ls,df as uo,X as ds,aJ as mo,dV as ho,dW as us,dX as ms,F as Gn,dY as fo,D as hs,cY as go,dZ as Yn,C as fs,d_ as gs,d$ as ps,e0 as Jn,e1 as vs,e2 as bs,c5 as zs,e3 as ws,e4 as po,dl as Bs,e5 as vo,e6 as bo,cX as xs,cx as wo}from"./index-I32FijPT.js";import{e7 as ri,e8 as oi}from"./index-I32FijPT.js";import{u as Qe}from"./vendor-i18n-Duky4gdQ.js";import{SessionTerminal as ys}from"./SessionTerminal-Bwb8nGmU.js";import{u as xo}from"./useDiscoveredSkillsCache-D6zMSIaS.js";import"./vendor-codemirror-CcrtqoCy.js";import"./vendor-reactflow-BlIeoTu4.js";import"./vendor-xterm-BNq00GSj.js";import"./shield-alert-BBDlP6A5.js";/**
2
- * @license lucide-react v1.7.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const yo=[["line",{x1:"4",x2:"20",y1:"9",y2:"9",key:"4lhtct"}],["line",{x1:"4",x2:"20",y1:"15",y2:"15",key:"vyu0kd"}],["line",{x1:"10",x2:"8",y1:"3",y2:"21",key:"1ggp8o"}],["line",{x1:"16",x2:"14",y1:"3",y2:"21",key:"weycgp"}]],Os=Ps("hash",yo);/**
7
- * @license lucide-react v1.7.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const Co=[["path",{d:"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z",key:"vktsd0"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor",key:"kqv944"}]],ko=Ps("tag",Co);function rn(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Ro(){try{typeof import.meta<"u"}catch{}try{if(typeof localStorage<"u")return localStorage.getItem("kb-debug-room-open")==="1"}catch{}return!1}function Zn(r,o){const u=Ro(),f=o?.warm===!0,d=rn(),m=new Map;let y=!1,k=!1;return{mark(E){y||k||!u||m.has(E)||m.set(E,rn())},complete:E=>{if(!u||y||k){y=!0;return}y=!0,m.set("complete",rn());const I=Array.from(m.entries()).sort((C,j)=>C[1]-j[1]);let M=d;const s={};for(const[C,j]of I)s[C]=Math.max(0,j-M),M=j;const A=Math.max(0,rn()-d);try{console.debug("[room-open]",{roomId:r,warm:f,totalMs:A,phases:s,...E??{}})}catch{}},cancel(){k=!0,y=!0}}}const _e="fusion:chat-active-room";class Us extends Error{roomId;constructor(o,u){super(o),this.name="RoomMessageDeliveredButReplyFailedError",this.roomId=u}}function oa(r){return[...r].sort((o,u)=>new Date(u.updatedAt).getTime()-new Date(o.updatedAt).getTime())}function We(r,o){const u=r.findIndex(d=>d.id===o.id);if(u===-1)return oa([o,...r]);const f=[...r];return f[u]=o,oa(f)}function Ie(r){try{return JSON.parse(r.data)}catch{return null}}function ea(r){return r.slice().reverse()}function Mo(r,o,u){return{id:`temp-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,roomId:r,role:"user",content:o,thinkingOutput:null,metadata:null,senderAgentId:null,mentions:[],...u?.length?{attachments:u}:{},createdAt:new Date().toISOString()}}function Cs(r,o,u){if(r.some(d=>d.id===o.id))return r;const f=u?r.findIndex(d=>d.id===u):-1;if(f>=0){const d=[...r];return d[f]=o,d}if(o.role==="user"){const d=r.findIndex(m=>m.role==="user"&&m.id.startsWith("temp-")&&m.content.trim()===o.content.trim());if(d>=0){const m=[...r];return m[d]=o,m}}return[...r,o]}function So(r,o){const{t:u}=Qe("app"),f=`${an.CHAT_ROOMS}:${r??"global"}`,d=`${an.ACTIVE_CHAT_ROOM_ID}:${r??"global"}`,m=a.useCallback(p=>`${an.CHAT_ROOM_MESSAGES_PREFIX}${r??"global"}:${p}`,[r]),y=a.useCallback(p=>`${an.CHAT_ROOM_MEMBERS_PREFIX}${r??"global"}:${p}`,[r]),[k,b]=a.useState(()=>{const p=St(f,{maxAgeMs:ss});return Array.isArray(p)?p:[]}),[E,I]=a.useState(()=>k.length===0),[M,s]=a.useState(null),[A,C]=a.useState(()=>{const p=St(d,{maxAgeMs:rs});return p?k.find(g=>g.id===p)??null:null}),[j,$]=a.useState([]),[N,c]=a.useState([]),[te,_]=a.useState(!1),J=a.useRef(k),R=a.useRef(A),Z=a.useRef(N),U=a.useRef(0),ae=a.useRef(r);J.current=k,R.current=A,Z.current=N,ae.current!==r&&(ae.current=r,U.current+=1);const D=a.useCallback(async p=>{if(!p){$([]),c([]),_(!1);return}const g=Zn(p.id,{warm:!1});g.mark("select");const x=St(m(p.id),{maxAgeMs:Ar}),h=St(y(p.id),{maxAgeMs:ss}),S=Array.isArray(x)&&x.length>0,F=Array.isArray(h)&&h.length>0,K=R.current?.id===p.id&&Z.current.length>0&&Z.current.every(ue=>ue.roomId===p.id);S||F?(g.mark("cache-hit"),S&&!K&&(c(x),g.mark("hydrate")),F&&$(h)):K||c([]),_(!S&&!K);try{const[ue,ee]=await Promise.all([Tr(p.id,r),Xn(p.id,{limit:100,order:"desc"},r)]);g.mark("members-fetch"),g.mark("messages-fetch"),q(y(p.id),ue.members,{maxBytes:5e5});const re=ea(ee.messages);q(m(p.id),re,{maxBytes:5e5}),R.current?.id===p.id&&($(ue.members),c(re),g.mark("hydrate"))}catch{!S&&!F&&($([]),c([]))}finally{R.current?.id===p.id&&_(!1),g.complete({warm:S||K,membersCached:F})}},[y,m,r]),L=a.useCallback(async()=>{J.current.length===0&&I(!0);try{const p=await Er({},r),g=oa(p.rooms);b(g),q(f,g,{maxBytes:5e5}),s(null);const x=St(d,{maxAgeMs:rs})??Tt(_e,r);if(x){const h=g.find(S=>S.id===x)??null;h?(C(h),D(h)):(Nt(_e,r),q(d,"",{maxBytes:5e5}))}}catch(p){const g=p instanceof Error?p.message:u("chatRooms.error.failedToLoad","Failed to load chat rooms");s(g),o?.(g,"error")}finally{I(!1)}},[d,o,D,r,f]),G=a.useCallback(p=>{if(!p){R.current=null,C(null),Nt(_e,r),q(d,"",{maxBytes:5e5}),D(null);return}const g=J.current.find(x=>x.id===p)??null;R.current=g,C(g),g&&(sa(_e,g.id,r),q(d,g.id,{maxBytes:5e5}),D(g))},[d,D,r]),Q=a.useCallback(async p=>{const x=(await Dr({name:p.name,memberAgentIds:p.memberAgentIds},r)).room;return b(h=>We(h,x)),R.current=x,C(x),sa(_e,x.id,r),q(d,x.id,{maxBytes:5e5}),await D(x),x},[d,D,r]),T=a.useCallback(async(p,g)=>{const h=(await Ir(p,g,r)).room;return b(S=>We(S,h)),R.current?.id===h.id&&(R.current=h,C(h)),h},[r]),B=a.useCallback(async p=>{await Lr(p,r),b(g=>g.filter(x=>x.id!==p)),q(m(p),[],{maxBytes:5e5}),q(y(p),[],{maxBytes:5e5}),R.current?.id===p&&(R.current=null,C(null),$([]),c([]),Nt(_e,r),q(d,"",{maxBytes:5e5}))},[d,y,m,r]),se=a.useCallback(async(p,g)=>{const x=R.current,h=x?.id;if(!h)throw new Error(u("chatRooms.error.selectRoomFirst","Select a room before sending a message"));const S=Zn(h,{warm:!1}),F=g?.files?.map(ee=>({id:`upload-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,filename:ee.name,originalName:ee.name,mimeType:ee.type||"application/octet-stream",size:ee.size,createdAt:new Date().toISOString()})),K=Mo(h,p,F?.length?F:g?.attachments);R.current?.id===h&&c(ee=>{const re=[...ee,K];return q(m(h),re,{maxBytes:5e5}),re});let ue=!1;try{const ee=[];if(g?.files?.length)for(const he of g.files)try{const Xe=await Fr(h,he,r);ee.push(Xe.attachment)}catch{throw new Error(u("chatRooms.error.failedToUpload","Failed to upload attachment: {{filename}}",{filename:he.name}))}const re=[...g?.attachments??[],...ee],Re=await Pr(h,{content:p,...re.length?{attachments:re}:{}},r);ue=!0;try{g?.onDelivered?.()}catch{}Re.message?.createdAt&&x&&b(he=>We(he,{...x,updatedAt:Re.message.createdAt})),R.current?.id===h&&c(he=>{const Xe=Cs(he,Re.message,K.id);return q(m(h),Xe,{maxBytes:5e5}),Xe});const oe=await Xn(h,{limit:100,order:"desc"},r),Le=ea(oe.messages);if(q(m(h),Le,{maxBytes:5e5}),R.current?.id!==h)return;c(Le),S.mark("hydrate")}catch(ee){let re=null;try{const oe=await Xn(h,{limit:100,order:"desc"},r);re=ea(oe.messages),q(m(h),re,{maxBytes:5e5}),R.current?.id===h&&(c(re),S.mark("hydrate"))}catch{!ue&&R.current?.id===h&&c(oe=>{const Le=oe.filter(he=>he.id!==K.id);return q(m(h),Le,{maxBytes:5e5}),Le})}const Re=re?.some(oe=>oe.role==="user"&&oe.content.trim()===K.content.trim());if(ue||Re){const oe=ee instanceof Error&&ee.message.trim()?ee.message:u("chatRooms.error.deliveredButRefreshFailed","Message delivered, but failed to refresh room replies");throw new Us(oe,h)}throw ee}finally{S.complete({source:"send-room-message"})}},[m,r]),ke=a.useCallback(async p=>{!p||!J.current.some(g=>g.id===p)||(await $r(p,r),q(m(p),[],{maxBytes:5e5}),R.current?.id===p&&c([]))},[m,r]);return a.useEffect(()=>{L()},[L]),a.useEffect(()=>{const p=U.current,g=r?`/api/events?projectId=${encodeURIComponent(r)}`:"/api/events";return _r(g,{onReconnect:()=>{ra({view:"useChatRooms",trigger:"sse-reconnect",projectId:r,replayAttempted:!1});const x=R.current?.id;if(x){const h=Zn(x,{warm:!0});h.mark("sse-reconnect-refresh"),L().finally(()=>h.complete({source:"sse-reconnect"}));return}L()},events:{"chat:room:created":x=>{if(U.current!==p)return;const h=Ie(x);h&&b(S=>We(S,h))},"chat:room:updated":x=>{if(U.current!==p)return;const h=Ie(x);h&&(b(S=>We(S,h)),R.current?.id===h.id&&(R.current=h,C(h)))},"chat:room:deleted":x=>{if(U.current!==p)return;const h=Ie(x);h?.id&&(b(S=>S.filter(F=>F.id!==h.id)),q(m(h.id),[],{maxBytes:5e5}),q(y(h.id),[],{maxBytes:5e5}),R.current?.id===h.id&&(R.current=null,C(null),$([]),c([]),Nt(_e,r),q(d,"",{maxBytes:5e5})))},"chat:room:member:added":x=>{if(U.current!==p)return;const h=Ie(x);!h||R.current?.id!==h.roomId||$(S=>{if(S.some(K=>K.agentId===h.agentId))return S;const F=[...S,h];return q(y(h.roomId),F,{maxBytes:5e5}),F})},"chat:room:member:removed":x=>{if(U.current!==p)return;const h=Ie(x);!h||R.current?.id!==h.roomId||$(S=>{const F=S.filter(K=>K.agentId!==h.agentId);return q(y(h.roomId),F,{maxBytes:5e5}),F})},"chat:room:message:added":x=>{if(U.current!==p)return;const h=Ie(x);h&&(b(S=>{const F=S.find(K=>K.id===h.roomId);return F?We(S,{...F,updatedAt:h.createdAt}):S}),R.current?.id===h.roomId&&c(S=>{const F=Cs(S,h);return F===S?S:(q(m(h.roomId),F,{maxBytes:5e5}),F)}))},"chat:room:message:updated":x=>{if(U.current!==p)return;const h=Ie(x);!h||R.current?.id!==h.roomId||c(S=>{const F=S.map(K=>K.id===h.id?h:K);return q(m(h.roomId),F,{maxBytes:5e5}),F})},"chat:room:message:deleted":x=>{if(U.current!==p)return;const h=Ie(x);h?.id&&c(S=>{const F=S.filter(ue=>ue.id!==h.id),K=R.current?.id;return K&&q(m(K),F,{maxBytes:5e5}),F})},"chat:room:messages:cleared":x=>{if(U.current!==p)return;const h=Ie(x);h?.roomId&&(q(m(h.roomId),[],{maxBytes:5e5}),R.current?.id===h.roomId&&c([]),b(S=>{const F=S.find(K=>K.id===h.roomId);return F?We(S,{...F,updatedAt:new Date().toISOString()}):S}))}}})},[d,y,m,r,L]),a.useEffect(()=>{A&&(k.some(p=>p.id===A.id)||(R.current=null,C(null),$([]),c([]),Nt(_e,r),q(d,"",{maxBytes:5e5})))},[A,d,r,k]),{rooms:k,roomsLoading:E,roomsError:M,activeRoom:A,activeRoomMembers:j,messages:N,messagesLoading:te,selectRoom:G,createRoom:Q,updateRoomSettings:T,deleteRoom:B,sendRoomMessage:se,clearRoom:ke,refreshRooms:L}}const jt={direct:"fusion:chat-unread:direct",room:"fusion:chat-unread:rooms"},ks=200;function ia(r){if(!r)return null;const o=new Date(r).getTime();return Number.isFinite(o)?o:null}function Hs(r){const o=Object.entries(r);if(o.length<=ks)return r;const u=o.map(([f,d])=>({id:f,timestamp:d,value:ia(d)??0})).sort((f,d)=>d.value-f.value).slice(0,ks);return Object.fromEntries(u.map(({id:f,timestamp:d})=>[f,d]))}function on(r){if(!r)return{};try{const o=JSON.parse(r);if(!o||typeof o!="object")return{};const u={};for(const[f,d]of Object.entries(o))typeof f=="string"&&typeof d=="string"&&(u[f]=d);return Hs(u)}catch{return{}}}function No(r){const[o,u]=a.useState(()=>{try{return on(Tt(jt.direct,r))}catch{return{}}}),[f,d]=a.useState(()=>{try{return on(Tt(jt.room,r))}catch{return{}}});a.useEffect(()=>{try{u(on(Tt(jt.direct,r)))}catch{u({})}try{d(on(Tt(jt.room,r)))}catch{d({})}},[r]);const m=a.useMemo(()=>({direct:o,room:f}),[o,f]),y=a.useCallback((M,s)=>{const A=Hs(s);try{sa(jt[M],JSON.stringify(A),r)}catch{}return A},[r]),k=a.useCallback((M,s)=>{if(M==="direct"){u(A=>y(M,s(A)));return}d(A=>y(M,s(A)))},[y]),b=a.useCallback((M,s,A)=>{const C=ia(A);if(C===null)return!1;const j=m[M][s],$=ia(j);return $===null?!0:C>$},[m]),E=a.useCallback((M,s,A)=>{if(!s)return;const C=A??new Date().toISOString();k(M,j=>({...j,[s]:C}))},[k]),I=a.useCallback((M,s)=>{s.length!==0&&k(M,A=>{const C={...A};for(const j of s)j.id&&(C[j.id]=j.lastActivityAt??new Date().toISOString());return C})},[k]);return{isUnread:b,markRead:E,markAllRead:I}}function Rs(r){return r.trim().toLowerCase().replace(/[\s-]+/g,"_").replace(/_+/g,"_")}function Ks(r,o){const u=o.trim();if(!u)return!0;const f=Rs(u);return Rs(r).includes(f)||r.toLowerCase().includes(u.toLowerCase())}function Ms({agents:r,filter:o,highlightedIndex:u,visible:f,onSelect:d,position:m="below",roomMemberIds:y,roomName:k}){const{t:b}=Qe("app"),E=a.useMemo(()=>r.filter(j=>Ks(j.name,o)),[r,o]),I=!!y,M=I&&o.trim().length>0,s=a.useMemo(()=>I?E.filter(j=>y?.has(j.id)):E,[E,y,I]),A=a.useMemo(()=>I?E.filter(j=>!y?.has(j.id)):[],[E,y,I]),C=M?[...s,...A]:s;return f?t.jsx("div",{className:`agent-mention-popup agent-mention-popup--${m}`,"data-testid":"agent-mention-popup",role:"listbox","aria-label":b("agentMention.suggestionsLabel","Agent mention suggestions"),children:C.length===0?t.jsx("div",{className:"agent-mention-empty",children:b("agentMention.noAgentsFound","No agents found")}):t.jsxs(t.Fragment,{children:[I&&t.jsx("div",{className:"agent-mention-section-header","data-testid":"agent-mention-members-header",children:k?b("agentMention.membersOf","Members of #{{roomName}}",{roomName:k}):b("agentMention.roomMembers","Room members")}),s.map((j,$)=>t.jsxs("button",{type:"button",className:`agent-mention-item${$===u?" agent-mention-item--highlighted":""}`,"data-testid":`agent-mention-item-${j.id}`,onMouseDown:N=>N.preventDefault(),onClick:()=>d(j),role:"option","aria-selected":$===u,children:[t.jsx(ln,{agent:j,size:20}),I&&t.jsx("span",{className:"status-dot agent-mention-member-dot","aria-label":b("agentMention.roomMemberBadge","Room member")}),t.jsx("span",{className:"agent-mention-name",children:j.name}),t.jsx("span",{className:"agent-mention-role",children:j.role})]},j.id)),I&&!M&&A.length>0&&t.jsx("div",{className:"agent-mention-hint","data-testid":"agent-mention-other-hint",children:b("agentMention.typeToSearch","Type to search other agents")}),I&&M&&A.length>0&&t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"agent-mention-section-header","data-testid":"agent-mention-others-header",children:b("agentMention.otherAgents","Other agents")}),A.map((j,$)=>{const N=s.length+$;return t.jsxs("button",{type:"button",className:`agent-mention-item${N===u?" agent-mention-item--highlighted":""}`,"data-testid":`agent-mention-item-${j.id}`,onMouseDown:c=>c.preventDefault(),onClick:()=>d(j),role:"option","aria-selected":N===u,children:[t.jsx(ln,{agent:j,size:20}),t.jsx("span",{className:"agent-mention-name",children:j.name}),t.jsx("span",{className:"agent-mention-role",children:j.role})]},j.id)})]})]})}):null}function jo(r,o){return r+o}function Ao({visible:r,position:o,tasks:u,files:f,selectedIndex:d,onSelectTask:m,onSelectFile:y,loading:k}){const{t:b}=Qe("app");if(!r)return null;const E=u.length>0,I=f.length>0;return t.jsxs("div",{className:"file-mention-popup",style:{top:o.top,left:o.left},"data-testid":"file-mention-popup",onMouseDown:M=>{M.preventDefault()},children:[k&&t.jsx("div",{className:"file-mention-popup-loading","data-testid":"file-mention-loading",children:t.jsx("span",{className:"spinner"})}),!k&&!E&&!I&&t.jsx("div",{className:"file-mention-popup-empty","data-testid":"file-mention-empty",children:b("fileMention.empty","No tasks or files found")}),!k&&(E||I)&&t.jsxs("div",{className:"file-mention-popup-groups",children:[E&&t.jsxs("div",{className:"file-mention-popup-group",children:[t.jsx("div",{className:"file-mention-popup-group-header",children:b("fileMention.taskHeader","Tasks")}),t.jsx("ul",{className:"file-mention-popup-list",role:"listbox","aria-label":b("fileMention.taskMatches","Task matches"),children:u.map((M,s)=>{const A=s;return t.jsxs("li",{className:`file-mention-popup-item${A===d?" file-mention-popup-item--selected":""}`,onClick:()=>m(M),role:"option","aria-selected":A===d,"data-testid":`task-mention-item-${A}`,children:[t.jsx("span",{className:"file-mention-popup-icon",children:t.jsx(Os,{})}),t.jsxs("div",{className:"file-mention-popup-info",children:[t.jsxs("div",{className:"file-mention-popup-task-row",children:[t.jsx("span",{className:"file-mention-popup-task-id",children:M.id}),t.jsx("span",{className:`file-mention-popup-column-badge file-mention-popup-column-badge--${M.column}`,children:M.column})]}),t.jsx("span",{className:"file-mention-popup-item-path",children:M.title})]})]},M.id)})})]}),I&&t.jsxs("div",{className:"file-mention-popup-group",children:[t.jsx("div",{className:"file-mention-popup-group-header",children:b("fileMention.fileHeader","Files")}),t.jsx("ul",{className:"file-mention-popup-list",role:"listbox","aria-label":b("fileMention.fileMatches","File matches"),children:f.map((M,s)=>{const A=jo(u.length,s),C=zr(M.path);return t.jsxs("li",{className:`file-mention-popup-item${A===d?" file-mention-popup-item--selected":""}`,onClick:()=>y(M),role:"option","aria-selected":A===d,"data-testid":`file-mention-item-${A}`,children:[t.jsx("span",{className:"file-mention-popup-icon",children:t.jsx(Br,{})}),t.jsxs("div",{className:"file-mention-popup-info",children:[t.jsx("span",{className:"file-mention-popup-item-name",children:M.name}),C&&t.jsx("span",{className:"file-mention-popup-item-path",children:C})]})]},M.path)})})]})]})]})}function To(r,o=[],u){const f=r.trim().replace(/^#/,""),d=(y,k)=>u?u(y,k):k;if(!f)return{ok:!1,error:d("createRoom.nameRequired","Room name is required.")};if(/[A-Z]/.test(f))return{ok:!1,error:d("createRoom.lowercase","Use lowercase letters only.")};const m=f.toLowerCase();return m.length>80?{ok:!1,error:d("createRoom.maxLength","Room names can be at most 80 characters.")}:/^[a-z0-9_-]+$/.test(m)?/^[-_]|[-_]$/.test(m)?{ok:!1,error:d("createRoom.noEdgeChars","Room names cannot start or end with a hyphen or underscore.")}:o.some(y=>y.toLowerCase()===m)?{ok:!1,error:d("createRoom.duplicate","A room with this name already exists.")}:{ok:!0,name:m}:{ok:!1,error:d("createRoom.validChars","Use lowercase letters, numbers, hyphens, or underscores only.")}}function Eo({isOpen:r,onClose:o,onCreate:u,projectId:f,existingRoomNames:d=[]}){const{t:m}=Qe("app"),[y,k]=a.useState(""),[b,E]=a.useState([]),[I,M]=a.useState(""),[s,A]=a.useState([]),[C,j]=a.useState("idle"),[$,N]=a.useState(null),[c,te]=a.useState(!1),_=a.useRef(null),J=a.useRef(null),R=a.useRef(null),Z=a.useRef(0);a.useEffect(()=>{const T=++Z.current;if(!r)return;R.current=document.activeElement instanceof HTMLElement?document.activeElement:null,E([]),j("loading"),N(null);let B=!1;const se=()=>!B&&Z.current===T;return Or(void 0,f).then(ke=>{se()&&(E(ke),A(p=>p.filter(g=>ke.some(x=>x.id===g))),j("loaded"))}).catch(()=>{se()&&(E([]),j("failed"))}),()=>{B=!0,++Z.current}},[r,f]),a.useEffect(()=>{if(!r){k(""),M(""),A([]),E([]),j("idle"),N(null),te(!1);return}const T=window.requestAnimationFrame(()=>{const B=document.activeElement;B instanceof HTMLElement&&J.current?.contains(B)||_.current?.focus()});return()=>window.cancelAnimationFrame(T)},[r]),a.useEffect(()=>{if(!r)return;const T=B=>{B.key==="Escape"&&o()};return document.addEventListener("keydown",T),()=>document.removeEventListener("keydown",T)},[r,o]),a.useEffect(()=>{r||R.current?.focus()},[r]);const U=a.useMemo(()=>To(y,d,m),[y,d,m]),ae=a.useMemo(()=>{const T=I.trim().toLowerCase();return T?b.filter(B=>B.name.toLowerCase().includes(T)):b},[b,I]),D=a.useMemo(()=>b.filter(T=>s.includes(T.id)),[b,s]),L=U.ok&&s.length>0&&!c&&C==="loaded";if(!r)return null;const G=T=>{c||A(B=>B.includes(T)?B.filter(se=>se!==T):[...B,T])},Q=async()=>{if(!U.ok){N(U.error);return}if(s.length===0){N(m("createRoom.selectMember","Select at least one member."));return}N(null),te(!0);try{await u({name:U.name,displayName:`#${U.name}`,memberAgentIds:s}),o()}catch(T){N(T instanceof Error?T.message:m("createRoom.failedCreate","Failed to create room."))}finally{te(!1)}};return t.jsx(Ur,{windowKey:"create-room",title:m("createRoom.title","Create room"),ariaLabel:m("createRoom.title","Create room"),onClose:o,modal:!0,hideHeader:!0,dragHandleSelector:".modal-header",className:"floating-window--create-room",defaultSize:{width:640,height:640},minSize:{width:360,height:400},persistGeometryKey:"floating-window:create-room",suspendGeometryPersistenceOnMobile:!0,suspendGeometryPersistenceOnShortViewport:!0,closeOnOutsidePointerDown:!0,layer:"utility",children:t.jsxs("div",{ref:J,className:"modal create-room-modal",children:[t.jsxs("div",{className:"modal-header",children:[t.jsx("h3",{children:m("createRoom.title","Create room")}),t.jsx("button",{type:"button",className:"modal-close","aria-label":m("actions.close","Close"),onClick:o,children:"×"})]}),t.jsxs("div",{className:"form-group create-room-modal-name-group",children:[t.jsx("label",{htmlFor:"create-room-name",children:m("createRoom.nameLabel","Room name")}),t.jsxs("div",{className:"create-room-modal-name-field",children:[t.jsx("span",{"aria-hidden":"true",className:"create-room-modal-name-hash",children:"#"}),t.jsx("input",{ref:_,id:"create-room-name",className:"input",value:y,disabled:c,onChange:T=>{const B=T.target.value.replace(/^#/,"").replace(/\s+/g,"-").toLowerCase();k(B)}})]}),!U.ok&&t.jsx("div",{className:"form-error",children:U.error})]}),t.jsxs("div",{className:"form-group",children:[t.jsx("label",{htmlFor:"create-room-member-search",children:m("createRoom.members","Members")}),t.jsx("input",{id:"create-room-member-search",className:"input",placeholder:m("createRoom.searchAgents","Search agents"),value:I,disabled:c,onChange:T=>M(T.target.value)})]}),D.length>0&&t.jsx("div",{className:"create-room-modal-selected","data-testid":"create-room-selected-chips",children:D.map(T=>t.jsxs("button",{type:"button",className:"btn btn-sm create-room-modal-chip",onClick:()=>G(T.id),disabled:c,children:[T.name," ×"]},T.id))}),t.jsx("div",{className:"create-room-modal-member-list","data-testid":"create-room-member-list",children:C==="idle"||C==="loading"?t.jsx("div",{className:"create-room-modal-empty",children:t.jsx(Hr,{label:m("createRoom.loadingAgents","Loading agents...")})}):C==="failed"?t.jsx("div",{className:"create-room-modal-empty",children:m("createRoom.failedLoadAgents","Failed to load agents.")}):ae.length===0?t.jsx("div",{className:"create-room-modal-empty",children:b.length===0?m("createRoom.noAgents","No agents in this project yet."):m("createRoom.noMatch","No agents match your search.")}):ae.map(T=>{const B=s.includes(T.id);return t.jsxs("button",{type:"button",className:`create-room-modal-member-row${B?" create-room-modal-member-row--selected":""}`,onClick:()=>G(T.id),disabled:c,children:[t.jsx(ln,{agent:T,size:20}),t.jsx("span",{children:T.name}),t.jsx("span",{className:"create-room-modal-member-role",children:T.role})]},T.id)})}),$&&t.jsx("div",{className:"form-group",children:t.jsx("div",{className:"form-error",children:$})}),t.jsxs("div",{className:"modal-actions",children:[t.jsx("button",{type:"button",className:"btn",onClick:o,disabled:c,children:m("actions.cancel","Cancel")}),t.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void Q(),disabled:!L,children:c?m("createRoom.creating","Creating..."):m("createRoom.create","Create room")})]})]})})}function Do({cliSessionId:r,tier:o,projectId:u,renderTranscript:f,renderComposer:d,queuedCount:m=0,terminalProps:y}){const{t:k}=Qe("app"),b=o==="generic",[E,I]=a.useState(b?"terminal":"transcript");if(b)return t.jsx("div",{className:"cli-chat-surface cli-chat-surface--generic","data-tier":"generic",children:t.jsx(ys,{sessionId:r,projectId:u,...y})});const M=E==="terminal";return t.jsxs("div",{className:"cli-chat-surface","data-tier":o,"data-view":E,children:[t.jsxs("div",{className:"cli-chat-surface__toolbar",role:"tablist","aria-label":k("cliChat.viewToggleLabel","Chat view"),children:[t.jsxs("button",{type:"button",role:"tab","aria-selected":!M,className:`cli-chat-surface__tab${M?"":" is-active"}`,onClick:()=>I("transcript"),children:[t.jsx(cn,{size:14,"aria-hidden":"true"}),t.jsx("span",{children:k("cliChat.transcriptTab","Transcript")})]}),t.jsxs("button",{type:"button",role:"tab","aria-selected":M,className:`cli-chat-surface__tab${M?" is-active":""}`,onClick:()=>I("terminal"),children:[t.jsx(Kr,{size:14,"aria-hidden":"true"}),t.jsx("span",{children:k("cliChat.terminalTab","Terminal")})]})]}),t.jsx("div",{className:"cli-chat-surface__body",children:M?t.jsx(ys,{sessionId:r,projectId:u,...y}):f()}),!M&&t.jsxs("div",{className:"cli-chat-surface__composer",children:[m>0&&t.jsx("div",{className:"cli-chat-surface__queued",role:"status","aria-live":"polite",children:k("cliChat.queued","{{count}} message queued — will send when the agent is ready",{count:m})}),d()]})]})}const Io=200,Lo=8,Fo=8;function Ss(){return new DOMException("The operation was aborted.","AbortError")}function Ns(r,o){return o.aborted?Promise.reject(Ss()):new Promise((u,f)=>{const d=()=>f(Ss());o.addEventListener("abort",d,{once:!0}),r.then(m=>{o.removeEventListener("abort",d),u(m)},m=>{o.removeEventListener("abort",d),f(m)})})}function js(r,o,u){const f=r.slice(0,o),d=r.slice(o+1),m=d.match(/[\s]|$/),y=m?m.index??d.length:d.length,k=d.slice(y);return`${f}${u}${k}`}function Po(r={}){const{projectId:o,workspace:u="project"}=r,[f,d]=a.useState(!1),[m,y]=a.useState(""),[k,b]=a.useState(-1),[E,I]=a.useState([]),[M,s]=a.useState([]),[A,C]=a.useState(!1),[j,$]=a.useState(0),N=a.useRef(null),c=a.useRef(null),te=[...E.map(D=>({kind:"task",task:D})),...M.map(D=>({kind:"file",file:D}))];a.useEffect(()=>()=>{N.current&&clearTimeout(N.current),c.current?.abort()},[]);const _=a.useCallback((D,L)=>{if(L<0||L>D.length){d(!1);return}const G=Q=>/[a-zA-Z0-9/_.-]/.test(Q);for(let Q=L-1;Q>=0;Q--){if(D[Q]==="#"){if(Q===0){const B=D.slice(Q+1,L);b(Q),y(B),$(0),d(!0);return}const T=D[Q-1];if(/[\s,.;:!?'"()[\]{}]/.test(T)){const B=D.slice(Q+1,L);b(Q),y(B),$(0),d(!0);return}d(!1);return}if(!G(D[Q])){d(!1);return}}d(!1)},[]),J=a.useCallback(()=>{c.current?.abort(),d(!1),y(""),b(-1),I([]),s([]),$(0),C(!1)},[]),R=a.useCallback(async D=>{if(!D.trim()){I([]),s([]),C(!1);return}c.current?.abort();const L=new AbortController;c.current=L;try{C(!0);const[G,Q]=await Promise.allSettled([Ns(Vr(20,0,o,D),L.signal),Ns(qr(D,u,o),L.signal)]);if(L.signal.aborted)return;const T=G.status==="fulfilled"?G.value.slice(0,Lo).map(se=>({id:se.id,title:se.title??"",column:se.column})):[],B=Q.status==="fulfilled"?Q.value.files.slice(0,Fo):[];I(T),s(B),$(0)}catch(G){G.name!=="AbortError"&&(I([]),s([]))}finally{L.signal.aborted||C(!1)}},[u,o]);a.useEffect(()=>{if(f)return N.current&&clearTimeout(N.current),N.current=setTimeout(()=>{R(m)},Io),()=>{N.current&&clearTimeout(N.current)}},[m,f,R]);const Z=a.useCallback((D,L)=>!f||k<0?L:js(L,k,`#${D.id}`),[f,k]),U=a.useCallback((D,L)=>!f||k<0?L:js(L,k,`#${D.path}`),[f,k]),ae=a.useCallback((D,L)=>{if(!f||te.length===0)return!1;switch(D.key){case"ArrowDown":return D.preventDefault(),$(G=>Math.min(G+1,te.length-1)),!0;case"ArrowUp":return D.preventDefault(),$(G=>Math.max(G-1,0)),!0;case"Enter":case"Tab":return te[j]?(D.preventDefault(),!0):!1;case"Escape":return D.preventDefault(),J(),!0;default:return!1}},[f,te,j,J]);return{mentionActive:f,tasks:E,files:M,combinedItems:te,loading:A,mentionQuery:m,selectedIndex:j,setSelectedIndex:$,detectMention:_,selectTask:Z,selectFile:U,dismissMention:J,handleKeyDown:ae}}function $o(r,o){const u=r.reduce((f,d)=>f+(d.content?.length??0),0)+(o?.length??0);return Math.ceil(u/4)}function As(r){if(!Number.isFinite(r)||r<=0)return"0";if(r<1e3)return String(Math.round(r));const o=r/1e3;return o<10?`~${Number(o.toFixed(1))}k`:`${Math.round(o)}k`}const _o=200,gt=8;function ti(r){const o=r.trim();return o?`${o}
12
-
13
- `:""}function zo(r,o,u,f,d,m,y){const k=Math.max(gt,m-f-gt),b=Math.max(gt,y-d-gt),E=u?r-f:r;return{x:Math.min(Math.max(gt,E),k),y:Math.min(Math.max(gt,o),b)}}const Ts="__SKIP__";let ta=!1;function Bo(r,o){const u=new Date(r),d=new Date().getTime()-u.getTime(),m=Math.floor(d/1e3),y=Math.floor(m/60),k=Math.floor(y/60),b=Math.floor(k/24);return m<60?o("chat.relativeTimeJustNow","just now"):y<60?o("chat.relativeTimeMinutes","{{count}}m ago",{count:y}):k<24?o("chat.relativeTimeHours","{{count}}h ago",{count:k}):b<7?o("chat.relativeTimeDays","{{count}}d ago",{count:b}):u.toLocaleDateString()}const na="fusion:chat-scope",Oo="fusion:chat-draft:";function Es(r,o){return r.slice(o+1).find(u=>u.role==="user")?.content}function Ds(r,o){return o?`${Oo}${r}:${o}`:null}function Is(r){if(!r)return"";try{return localStorage.getItem(r)??""}catch{return""}}const Uo=["image/png","image/jpeg","image/gif","image/webp","video/mp4","video/webm","video/quicktime","text/plain","text/markdown","application/json","text/yaml","text/x-toml","text/csv","application/xml"],Ls="image/png,image/jpeg,image/gif,image/webp,video/mp4,video/webm,video/quicktime,.txt,.md,.json,.yaml,.yml,.toml,.csv,.xml",aa=po;function Ho(r,o){const u=r.slice(0,o),f=/(^|[\s\n])@([\w-]*)$/.exec(u);if(!f)return null;const d=f[2]??"",m=u.length-d.length-1;return{filter:d,start:m,end:o}}function Ko(r){const o=r?.runtimeConfig;if(!o||typeof o!="object")return null;const u=Reflect.get(o,"modelProvider"),f=Reflect.get(o,"modelId");return typeof u!="string"||u.trim().length===0||typeof f!="string"||f.trim().length===0?null:{provider:u,modelId:f}}function Fs(r,o,u){if(r?.modelProvider&&r?.modelId)return{provider:r.modelProvider,modelId:r.modelId};const f=Ko(o??void 0);return f||(u.provider&&u.modelId?{provider:u.provider,modelId:u.modelId}:null)}function Vo({projectId:r,defaultModel:o,defaultKind:u,defaultAgentId:f,defaultThinkingLevel:d,defaultSelectedThinkingLevel:m,onClose:y,onCreate:k}){const{t:b}=Qe("app"),[E,I]=a.useState(u??"agent"),{agents:M,loading:s}=$s(r),[A,C]=a.useState(f??""),{models:j,favoriteProviders:$,favoriteModels:N,loading:c,refresh:te}=_s(),_=o.provider&&o.modelId?`${o.provider}/${o.modelId}`:"",[J,R]=a.useState(_),[Z,U]=a.useState(m??""),[ae,D]=a.useState($),[L,G]=a.useState(N);a.useEffect(()=>{D($)},[$]),a.useEffect(()=>{G(N)},[N]),a.useEffect(()=>{u&&I(u)},[u]),a.useEffect(()=>{f&&C(g=>g||f)},[f]),a.useEffect(()=>{_&&R(g=>g||_)},[_]),a.useEffect(()=>{m&&U(g=>g||m)},[m]);const Q=a.useCallback(async g=>{const x=ae,S=x.includes(g)?x.filter(F=>F!==g):[g,...x];D(S);try{await xs({favoriteProviders:S,favoriteModels:L}),await te()}catch{D(x)}},[ae,L,te]),T=a.useCallback(async g=>{const x=L,S=x.includes(g)?x.filter(F=>F!==g):[g,...x];G(S);try{await xs({favoriteProviders:ae,favoriteModels:S}),await te()}catch{G(x)}},[L,ae,te]),B=J||_,se=g=>{if(g.preventDefault(),E==="agent"){if(!A)return;k({agentId:A});return}if(!B)return;const x=B.indexOf("/");if(x<=0)return;const h=B.slice(0,x),S=B.slice(x+1);k({agentId:ze,modelProvider:h,modelId:S,thinkingLevel:Z||void 0})},ke=E==="agent"?!A:!B,p=Bs(y,{enabled:!0});return t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",...p,role:"dialog","aria-modal":"true",children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:g=>g.stopPropagation(),children:[t.jsx("h3",{children:b("chat.newChatTitle","New Chat")}),t.jsxs("div",{className:"chat-new-dialog-mode-toggle","data-testid":"chat-new-dialog-mode-toggle",children:[t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${E==="agent"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-agent",onClick:()=>{I("agent")},children:b("chat.newChatModeAgent","Agent")}),t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${E==="model"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-model",onClick:()=>{I("model"),C(""),R(g=>g||_)},children:b("chat.newChatModeModel","Model")})]}),t.jsxs("form",{onSubmit:se,children:[E==="agent"&&t.jsxs("label",{className:"chat-new-dialog-model-label",children:[b("chat.newChatModeAgent","Agent"),s?t.jsx("div",{className:"chat-new-dialog-loading",children:b("chat.loadingAgents","Loading agents...")}):M.length===0?t.jsx("div",{className:"chat-new-dialog-empty",children:b("chat.noAgentsAvailable","No agents available")}):t.jsx("div",{className:"chat-new-dialog-agent-list",children:M.map(g=>t.jsxs("button",{type:"button",className:`chat-new-dialog-agent-item${A===g.id?" chat-new-dialog-agent-item--selected":""}`,onClick:()=>C(g.id),"data-testid":`agent-option-${g.id}`,children:[t.jsx(zs,{size:16}),t.jsx("span",{className:"chat-new-dialog-agent-name",children:g.name}),t.jsx("span",{className:"chat-new-dialog-agent-role",children:g.role})]},g.id))})]}),E==="model"&&t.jsx("div",{className:"chat-new-dialog-model-dropdown","data-testid":"chat-new-dialog-model-section",children:c?t.jsx("div",{className:"chat-new-dialog-loading",children:b("chat.loadingModels","Loading models...")}):t.jsx(wo,{models:j,value:J,onChange:R,label:b("chat.newChatModeModel","Model"),placeholder:b("chat.selectModel","Select a model"),favoriteProviders:ae,onToggleFavorite:Q,favoriteModels:L,onToggleModelFavorite:T,showThinkingLevel:!0,thinkingLevel:Z,onThinkingLevelChange:U,defaultThinkingLevel:d??"off"})}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{type:"button",className:"btn btn-sm",onClick:y,children:b("chat.cancel","Cancel")}),t.jsx("button",{type:"submit",className:"btn btn-sm btn-primary",disabled:ke,children:b("chat.create","Create")})]})]})]})})}function At({children:r,onClose:o}){const u=Bs(o,{enabled:!0});return t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",...u,children:r})}function ni({projectId:r,addToast:o,floating:u=!1,compactLayout:f=!1,onPopOut:d,onMaximize:m,onMinimize:y,onClose:k,chatCommandContext:b,initialComposerDraft:E,initialComposerDraftNonce:I,onSendAsReport:M}){const{t:s}=Qe("app"),A=Wr();a.useEffect(()=>(ra({view:"ChatView",trigger:ta?"route-active":"remount",projectId:r,replayAttempted:!1}),ta=!1,()=>{ta=!0,ra({view:"ChatView",trigger:"route-inactive",projectId:r,replayAttempted:!1})}),[r]);const[C,j]=a.useState(null);a.useEffect(()=>{let e=!1;return j(null),Qr(r).then(n=>{e||j(n)}).catch(()=>{e||j(null)}),()=>{e=!0}},[r]);const $=C?.defaultThinkingLevel??"off",N=a.useMemo(()=>C?.chatDefaultKind==="agent"&&C.chatDefaultAgentId?{kind:"agent",agentId:C.chatDefaultAgentId}:C?.chatDefaultKind==="model"&&C.chatDefaultModelProvider&&C.chatDefaultModelId?{kind:"model",modelProvider:C.chatDefaultModelProvider,modelId:C.chatDefaultModelId,thinkingLevel:C.chatDefaultThinkingLevel}:null,[C]),{activeSession:c,sessionsLoading:te,messages:_,messagesLoading:J,isStreaming:R,streamingText:Z,streamingThinking:U,streamingToolCalls:ae,selectSession:D,createSession:L,archiveSession:G,archivedSessions:Q,refreshArchivedSessions:T,unarchiveSession:B,renameSession:se,pinSession:ke,pinnedCount:p,setSessionModel:g,setSessionThinkingLevel:x,deleteSession:h,tags:S=[],selectedTagId:F,setSelectedTagId:K,createTag:ue,renameTag:ee,deleteTag:re,setSessionTags:Re,sendMessage:oe,editMessageAndResend:Le,stopStreaming:he,pendingMessages:Xe,pendingQueueAction:Ge,clearPendingMessage:dn,updatePendingMessage:Vs,movePendingMessage:qs,forceSendPendingMessage:Ws,loadMoreMessages:ca,hasMoreMessages:un,searchQuery:Qs,setSearchQuery:Xs,filteredSessions:Be,agentsMap:mn}=Xr(r,o),[Gs,hn]=a.useState(!1),Fe=!0,[P,Ye]=a.useState(()=>{try{if(localStorage.getItem(na)==="rooms"&&Fe)return"rooms"}catch{}return"direct"}),w=So(r,o),{isUnread:la,markRead:fe}=No(r),[H,ie]=a.useState(()=>{const e=Ds(P,P==="rooms"?w.activeRoom?.id:c?.id);return Is(e)}),[V,Me]=a.useState(null),[Je,Ys]=a.useState(!1),fn=a.useRef(null),da=(e,n,i,l)=>{typeof window>"u"||Me({sessionId:e,anchorX:n,anchorY:i,anchorRight:l?.anchorRight??!1,x:n,y:i})};a.useLayoutEffect(()=>{if(!V||!fn.current||typeof window>"u")return;const e=fn.current,n=e.getBoundingClientRect(),i=n.width||e.offsetWidth||_o,l=n.height||e.offsetHeight,v=zo(V.anchorX,V.anchorY,V.anchorRight,i,l,window.innerWidth,window.innerHeight);(v.x!==V.x||v.y!==V.y)&&Me({...V,...v})},[V]);const[Et,Dt]=a.useState(null),[gn,pn]=a.useState(""),[ua,It]=a.useState(null),[ma,Lt]=a.useState(null),[vn,ha]=a.useState(""),[bn,pt]=a.useState(null),[wn,fa]=a.useState(""),[ga,Ft]=a.useState(null),[Js,Oe]=a.useState(!1),[Zs,Pt]=a.useState(!1),{agentsMap:pa}=$s(r),ve=a.useMemo(()=>mn.size>0?mn:pa,[pa,mn]),{models:xn,favoriteProviders:er,favoriteModels:tr,defaultProvider:va,defaultModelId:ba}=_s(),$t=a.useMemo(()=>({provider:va,modelId:ba}),[ba,va]),nr=a.useMemo(()=>N?.kind==="model"?{provider:N.modelProvider,modelId:N.modelId}:$t,[N,$t]),{skills:yn,loading:ar}=xo(r),[Ze,Ue]=a.useState(!1),[vt,bt]=a.useState(""),[et,He]=a.useState(0),[tt,nt]=a.useState(""),[Se,at]=a.useState(!1),[_t,zt]=a.useState(0),[Cn,st]=a.useState(-1),[ge,Bt]=a.useState([]),[wa,rt]=a.useState(!1),[xa,Ot]=a.useState(!1),[ot,ya]=a.useState({}),{pushNav:Ca,removeNav:ka}=Gr(),[,Ut]=a.useState(!1),[sr,rr]=a.useState({top:0,left:0}),O=Po({projectId:r}),kn=a.useCallback(e=>{if(!e||!O.mentionActive)return;const n=e.getBoundingClientRect();rr({top:n.top-260,left:n.left+8})},[O.mentionActive]),Ra=a.useRef(null),Ma=a.useRef(null),de=a.useRef(!1),Ht=a.useRef(null),Sa=a.useRef(null),Pe=a.useRef(null),Kt=a.useRef(0),Rn=a.useRef(null),wt=a.useRef(null),Ne=a.useRef(null),ce=a.useRef(null),Mn=a.useRef(null),it=a.useRef(null),[Sn,or]=a.useState(()=>new Set),Vt=a.useRef(!1),je=a.useRef(null),Ae=a.useRef(null),Y=a.useRef(null),xt=a.useRef(null),yt=a.useRef(null),Ct=a.useRef(null),Na=a.useRef(void 0),Nn=a.useRef(!1),qt=a.useRef(null),ja=a.useRef([]),ct=a.useRef(0),kt=a.useRef(new Map),jn=a.useRef(!1),Aa=Yr(),Ke=Aa==="mobile",Ta=Aa==="tablet",Ea=a.useRef(null),[ir,Da]=a.useState(!1);a.useLayoutEffect(()=>{if(!u){Da(!1);return}const e=Ea.current;if(!e||typeof ResizeObserver>"u")return;const n=()=>{Da(e.getBoundingClientRect().width<=768)};n();const i=new ResizeObserver(n);return i.observe(e),()=>i.disconnect()},[u]);const pe=Ke||ir||f;a.useEffect(()=>{c?.id&&fe("direct",c.id,c.lastMessageAt??c.updatedAt)},[c?.id,c?.lastMessageAt,c?.updatedAt,fe]),a.useEffect(()=>{w.activeRoom?.id&&fe("room",w.activeRoom.id,w.activeRoom.updatedAt)},[w.activeRoom?.id,w.activeRoom?.updatedAt,fe]),a.useEffect(()=>{if(!c?.id||_.length===0)return;const e=_[_.length-1];fe("direct",c.id,e?.createdAt??c.lastMessageAt??c.updatedAt)},[c?.id,c?.lastMessageAt,c?.updatedAt,fe,_]),a.useEffect(()=>{if(!w.activeRoom?.id||w.messages.length===0)return;const e=w.messages[w.messages.length-1];fe("room",w.activeRoom.id,e?.createdAt??w.activeRoom.updatedAt)},[fe,w.activeRoom?.id,w.activeRoom?.updatedAt,w.messages]),a.useEffect(()=>{try{const e=localStorage.getItem(na);if(e==="direct"){Ye("direct");return}e==="rooms"&&Fe&&Ye("rooms")}catch{}},[Fe]),a.useEffect(()=>{try{localStorage.setItem(na,P)}catch{}},[Fe,P]);const me=Ds(P,P==="rooms"?w.activeRoom?.id:c?.id),An=a.useRef(me),Tn=a.useRef(!1);a.useEffect(()=>{if(me!==An.current){if(An.current=me,Tn.current){Tn.current=!1;return}ie(Is(me))}},[me]),a.useEffect(()=>{if(!(!me||An.current!==me))try{if(H){localStorage.setItem(me,H);return}localStorage.removeItem(me)}catch{}},[me,H]);const ne=P==="rooms"&&!!w.activeRoom,{keyboardOverlap:Ia,keyboardOpen:En}=Jr({enabled:(pe||Ta)&&(!!c||ne),allowNonMobileViewport:Ta}),Wt=a.useMemo(()=>{const e=vt.trim().toLowerCase();return(e?yn.filter(i=>i.name.toLowerCase().includes(e)):yn).slice(0,10)},[yn,vt]),Dn=a.useMemo(()=>b?Zr(vt,ws):[],[b,vt]),be=a.useMemo(()=>{const e=Dn.map(i=>({kind:"command",command:i,disabled:!b?.agentRunning})),n=Wt.map(i=>({kind:"skill",skill:i}));return[...e,...n]},[Dn,Wt,b]),lt=a.useMemo(()=>Array.from(ve.values()),[ve]),Te=a.useMemo(()=>P!=="rooms"||!w.activeRoom?null:{roomId:w.activeRoom.id,roomName:w.activeRoom.name,memberIds:new Set(w.activeRoomMembers.map(e=>e.agentId))},[Fe,P,w.activeRoom,w.activeRoomMembers]),Ve=a.useMemo(()=>{const e=lt.filter(l=>Ks(l.name,tt));if(!Te)return e;const n=e.filter(l=>Te.memberIds.has(l.id));if(tt.trim().length===0)return n;const i=e.filter(l=>!Te.memberIds.has(l.id));return[...n,...i]},[lt,tt,Te]),In=a.useMemo(()=>{const e=new Map;for(const n of lt)e.set(n.name.toLowerCase(),n);return e},[lt]),cr=a.useMemo(()=>Wt.map(e=>e.id).join("\0"),[Wt]);a.useEffect(()=>{He(0)},[cr]),a.useEffect(()=>{zt(0)},[tt,Se]),a.useEffect(()=>()=>{Ne.current!==null&&window.clearTimeout(Ne.current)},[]),a.useEffect(()=>{const e=Ma.current;if(!e||!un||J)return;const n=new IntersectionObserver(i=>{i[0].isIntersecting&&ca()},{threshold:.1});return n.observe(e),()=>n.disconnect()},[un,J,ca]);const dt=a.useCallback(()=>ne?w.activeRoom?.id??null:c?.id??null,[ne,w.activeRoom?.id,c?.id]),La=a.useCallback((e,n)=>typeof CSS<"u"&&typeof CSS.escape=="function"?e.querySelector(`.chat-message[data-message-id="${CSS.escape(n)}"]`):e.querySelector(`.chat-message[data-message-id="${n.replace(/"/g,'\\"')}"]`),[]),Fa=a.useCallback(()=>{const e=ce.current;if(!e)return;const n=e.getBoundingClientRect().top,i=new Set;e.querySelectorAll(".chat-message--assistant:not(.chat-message--failure)[data-message-id]").forEach(l=>{const v=l.getAttribute("data-message-id");v&&l.getBoundingClientRect().top<n&&i.add(v)}),or(l=>l.size===i.size&&Array.from(l).every(v=>i.has(v))?l:i)},[]),Qt=a.useCallback(()=>{!ce.current||it.current!==null||(it.current=window.requestAnimationFrame(()=>{it.current=null,Fa()}))},[Fa]),Xt=a.useCallback(()=>{const e=ce.current,n=dt();if(!e||!n)return;const i=e.scrollTop,l=e.querySelectorAll(".chat-message[data-message-id]"),v=Array.from(l).find(W=>W.offsetTop+W.offsetHeight>=i)??l[0]??null,z=v?.getAttribute("data-message-id")??null,X=v?v.offsetTop-i:0;wt.current={threadId:n,scrollTop:i,scrollHeight:e.scrollHeight,clientHeight:e.clientHeight,anchorMessageId:z,anchorOffset:X,wasPinnedBefore:!de.current,capturedAtMs:typeof performance<"u"?performance.now():Date.now()}},[dt]),Pa=a.useCallback(()=>{const e=ce.current;if(!e)return;const i=e.scrollTop+e.clientHeight>=e.scrollHeight-50;Ot(!i),de.current=!i,Xt(),Qt()},[Xt,Qt]),Ee=a.useCallback((e,n)=>{if(!e.isConnected||!n?.force&&de.current)return;let i=0,l=0,v=-1;const z=6,X=()=>{if(e.isConnected&&!(!n?.force&&de.current)){if(e.scrollTop=e.scrollHeight,e.scrollHeight===v?l+=1:(l=0,v=e.scrollHeight),i+=1,i>=z||l>=2){Ot(!1),de.current=!1;return}window.requestAnimationFrame(X)}};X()},[]),ut=ne?w.messages:_;a.useLayoutEffect(()=>(Qt(),()=>{it.current!==null&&(window.cancelAnimationFrame(it.current),it.current=null)}),[ut,Qt]),a.useLayoutEffect(()=>{const e=ce.current,n=dt(),i=wt.current;if(!e||!n||!i||i.threadId!==n||i.wasPinnedBefore)return;const l=(typeof performance<"u"?performance.now():Date.now())-i.capturedAtMs,v=e.scrollHeight>e.clientHeight,z=l>3e3,X=i.scrollTop<=0&&i.anchorOffset<=0&&v;if(!de.current||z||X){wt.current=null;return}let W=i.scrollTop;if(i.anchorMessageId){const Ce=La(e,i.anchorMessageId);Ce?W=Ce.offsetTop-i.anchorOffset:W=i.scrollTop+(e.scrollHeight-i.scrollHeight)}else W=i.scrollTop+(e.scrollHeight-i.scrollHeight);e.scrollTop=Math.max(0,W),de.current=!0,Ot(!0),wt.current=null},[ut,dt,La]);const Ln=a.useCallback(e=>{},[ut.length,ne]),we=a.useCallback(e=>{Ln(e);const n=ce.current;n&&(wt.current=null,de.current=!1,Ee(n))},[Ee,Ln]);a.useLayoutEffect(()=>{Pe.current!==null&&(window.clearTimeout(Pe.current),Pe.current=null);const e=ne?w.activeRoom?.id??null:c?.id??null;if(!e){Ht.current=null;return}const n={threadId:e,loaded:ne?!w.messagesLoading:!J,hasMessages:ne?w.messages.length>0:_.length>0},i=Ht.current,l=i?.threadId!==e,v=i?.threadId===e&&!i.loaded&&n.loaded,z=i?.threadId===e&&!i.hasMessages&&n.hasMessages;if(!(i===null||l||v||z))return;const W=ce.current;if(W)return Ln(l?"thread-change":v?"finished-loading":z?"first-messages":"mount"),Ee(W,{force:!0}),ne||(Pe.current=window.setTimeout(()=>{if(Pe.current=null,de.current)return;const Ce=ce.current;Ce&&Ee(Ce)},250)),Ht.current=n,()=>{Pe.current!==null&&(window.clearTimeout(Pe.current),Pe.current=null)}},[ne,w.activeRoom?.id,w.messages.length,w.messagesLoading,c?.id,_.length,J,Ee]),a.useEffect(()=>{!R||de.current||we("streaming")},[R,Z,U,we]),a.useEffect(()=>{const e=dt();if(!e){Kt.current=0,Rn.current=null;return}if(Rn.current!==e){Rn.current=e,Kt.current=ut.length;return}const n=Kt.current,i=ut.length,l=i>n,v=!de.current;Kt.current=i,l&&v&&we("new-message")},[ut,dt,we]),a.useEffect(()=>{Ia<=0||!ce.current||we("keyboard")},[Ia,we]),eo(Ke&&En),a.useLayoutEffect(()=>{if(!Ke||!c&&!ne||typeof window>"u")return;const e=Mn.current,n=window.visualViewport;if(!e||!n)return;const i=v=>{if(!(v instanceof HTMLElement))return!1;if(v.tagName==="TEXTAREA")return!0;if(v.tagName!=="INPUT")return!1;const z=v.type.toLowerCase();return["","text","search","email","url","tel","password","number"].includes(z)},l=()=>{if(Vt.current){e.classList.remove("chat-thread--keyboard-active"),e.style.setProperty("--chat-keyboard-accessory-clearance","0px"),e.style.transform="",e.style.willChange="";return}const v=Math.max(0,window.innerHeight-n.offsetTop-n.height),z=n.offsetTop||0;e.style.setProperty("--vv-height",`${n.height}px`),e.style.setProperty("--vv-offset-top",`${z}px`),e.style.setProperty("--keyboard-overlap",`${v}px`);const X=(v>0||z>0)&&i(document.activeElement);e.classList.toggle("chat-thread--keyboard-active",X),e.style.setProperty("--chat-keyboard-accessory-clearance",X&&Jn()?"calc(var(--space-2xl) + var(--space-md))":"0px"),X&&z>0?(e.style.transform=`translateY(${z}px)`,e.style.willChange="transform"):(e.style.transform="",e.style.willChange="")};return l(),n.addEventListener("resize",l),n.addEventListener("scroll",l),document.addEventListener("focusin",l),document.addEventListener("focusout",l),window.addEventListener("pageshow",l),document.addEventListener("visibilitychange",l),()=>{n.removeEventListener("resize",l),n.removeEventListener("scroll",l),document.removeEventListener("focusin",l),document.removeEventListener("focusout",l),window.removeEventListener("pageshow",l),document.removeEventListener("visibilitychange",l),e.classList.remove("chat-thread--keyboard-active"),e.style.setProperty("--chat-keyboard-accessory-clearance","0px"),e.style.transform="",e.style.willChange=""}},[c,Ke,ne]),a.useEffect(()=>{const e=()=>Me(null);if(V)return document.addEventListener("click",e),()=>document.removeEventListener("click",e)},[V]),a.useEffect(()=>{if(!Ke||!En)return;const e=n=>{n.target?.closest(".chat-messages")||n.preventDefault()};return document.addEventListener("touchmove",e,{passive:!1}),()=>{document.removeEventListener("touchmove",e)}},[Ke,En]),a.useEffect(()=>{const e=Sa.current;if(Sa.current=P,P==="rooms"&&!w.activeRoom){Ht.current=null;return}if(!(P==="direct"&&(e===null||e==="rooms"))&&!(P==="rooms"&&(e===null||e==="direct")))return;const l=ce.current;l&&(Ee(l,{force:!0}),de.current=!1,Ot(!1))},[P,w.activeRoom,Ee]),a.useEffect(()=>{if(!c&&!ne||ne&&!pe)return;const e=()=>{const i=!de.current;Xt(),i&&pe&&ce.current&&we("visibility-restore")},n=()=>{document.visibilityState==="visible"&&e()};return document.addEventListener("visibilitychange",n),window.addEventListener("pageshow",e),()=>{document.removeEventListener("visibilitychange",n),window.removeEventListener("pageshow",e)}},[pe,Ke,c,ne,Xt,we]),a.useEffect(()=>{if(ne||typeof ResizeObserver>"u")return;const e=ce.current;if(!e)return;const n=new ResizeObserver(()=>{de.current||Ee(e)});return n.observe(e),()=>{n.disconnect()}},[ne,Ee,c?.id,P]),a.useEffect(()=>{ja.current=ge},[ge]),a.useEffect(()=>()=>{for(const e of ja.current)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);for(const e of kt.current.values())window.clearTimeout(e);kt.current.clear()},[]);const mt=a.useCallback(e=>{if(!e||e.length===0)return;const n=[];for(const i of Array.from(e)){if(!Uo.includes(i.type))continue;const l=i.type.startsWith("image/");n.push({file:i,previewUrl:l?URL.createObjectURL(i):""})}n.length>0&&Bt(i=>[...i,...n])},[]),$a=a.useCallback(e=>{Bt(n=>{const i=n[e];return i?.previewUrl&&URL.revokeObjectURL(i.previewUrl),n.filter((l,v)=>v!==e)})},[]),_a=a.useCallback(e=>{mt(e.clipboardData?.files)},[mt]),ht=a.useCallback(async e=>{try{return await L(e),hn(!1),Oe(!0),!0}catch{return o(s("chat.failedToCreateSession","Failed to create chat session"),"error"),!1}},[L,o,pe,s]),za=a.useCallback(()=>{if(C?.chatNewSessionMode==="always-default"&&N){if(N.kind==="agent"){ht({agentId:N.agentId});return}ht({agentId:ze,modelProvider:N.modelProvider,modelId:N.modelId,thinkingLevel:N.thinkingLevel});return}hn(!0)},[N,C?.chatNewSessionMode,ht]),le=a.useCallback((e,n)=>{if(!e||e===Y.current){yt.current?.resize(n);return}e===xt.current&&Ct.current?.resize(n)},[]),lr=os({textareaRef:Y,value:H,onChange:ie,onResize:()=>le(Y.current),projectId:r}),dr=os({textareaRef:xt,value:H,onChange:ie,onResize:()=>le(xt.current),projectId:r}),ur=a.useCallback(e=>{yt.current?.destroy(),yt.current=null,Y.current=e,e&&(yt.current=is(e))},[]),mr=a.useCallback(e=>{Ct.current?.destroy(),Ct.current=null,xt.current=e,e&&(Ct.current=is(e))},[]);a.useLayoutEffect(()=>{le(P==="rooms"?xt.current:Y.current,{resetManual:H.length===0}),Nn.current&&(Nn.current=!1,Y.current?.focus())},[P,H,c?.id,w.activeRoom?.id,le]),a.useLayoutEffect(()=>{yt.current?.reset(),Ct.current?.reset()},[P,c?.id,w.activeRoom?.id]),a.useEffect(()=>{if(I===void 0||I===Na.current||!E?.trim())return;Na.current=I;const e=n=>{n&&(Tn.current=!0),Ye("direct"),Nn.current=!0,ie(E)};if(!R&&C?.chatNewSessionMode==="always-default"&&N){const n=N.kind==="agent"?{agentId:N.agentId}:{agentId:ze,modelProvider:N.modelProvider,modelId:N.modelId,thinkingLevel:N.thinkingLevel};ht(n).then(i=>e(i||P!=="direct"));return}e(P!=="direct")},[N,P,C?.chatNewSessionMode,ht,E,I,R,le]);const ft=a.useCallback(()=>{if(ie(""),me)try{localStorage.removeItem(me)}catch{}Ue(!1),bt(""),at(!1),nt(""),st(-1),Bt(e=>{for(const n of e)n.previewUrl&&URL.revokeObjectURL(n.previewUrl);return[]})},[me]),qe=a.useCallback(e=>{Bt(n=>{const i=n.filter(l=>e.has(l.file));for(const l of i)l.previewUrl&&URL.revokeObjectURL(l.previewUrl);return n.filter(l=>!e.has(l.file))})},[]),Fn=a.useCallback(()=>{const e=H.trim(),n=ge.map(l=>l.file);if(!e&&n.length===0||!c)return;if(b){const l=to(e,ws);if(l){if(!b.agentRunning){o(s("chat.commandNoRunningAgent","No running agent to steer"),"warning");return}if(n.length>0){o(s("chat.commandNoAttachments","Attachments aren't supported with commands — remove them before sending"),"warning");return}ft(),l.command.run({taskId:b.taskId,projectId:b.projectId,remainder:l.remainder}).then(()=>{o(s("chat.commandSteerSuccess","Sent to the running agent"),"success")}).catch(v=>{const z=v instanceof Error&&v.message.trim()?v.message:s("chat.commandSteerFailed","Failed to send to the running agent");o(z,"error")});return}}if(e==="/clear"||e==="/new"){if(n.length>0){o(s("chat.clearNoAttachments","Remove the attachments before running /clear or /new — they would be discarded unsent"),"warning");return}if(c.agentId.startsWith(no)){ft(),o(s("chat.newNotAllowedForTaskChat","This chat is tied to a task — /new and /clear can't clear it"),"warning");return}ft(),dn(),he(),L({agentId:c.agentId,modelProvider:c.modelProvider??void 0,modelId:c.modelId??void 0,thinkingLevel:c.thinkingLevel??void 0}).catch(()=>{o(s("chat.failedToClearConversation","Failed to clear conversation"),"error")});return}if(R&&n.length>0){o(s("chat.attachmentsNotQueued","Attachments can't be queued while a reply is streaming — wait for it to finish"),"warning");return}const i=new Set(n);ie("");try{oe(e,n,{onAccepted:()=>qe(i),onDelivered:()=>qe(i),onFailed:()=>{ie(l=>l||e)}})}catch{ie(e)}},[H,ge,c,ft,he,dn,L,o,oe,b,R,qe,s]),Pn=a.useCallback(async()=>{const e=H.trim(),n=ge.map(i=>i.file);if(!(!e&&n.length===0)){if(P==="rooms"){if(!w.activeRoom)return;if(e==="/clear"||e==="/new"){if(n.length>0){o(s("chat.clearNoAttachments","Remove the attachments before running /clear or /new — they would be discarded unsent"),"warning");return}ft();try{await w.clearRoom(w.activeRoom.id)}catch{o(s("chat.failedToClearRoomConversation","Failed to clear room conversation"),"error")}return}if(jn.current)return;jn.current=!0;const i=H,l=new Set(n);ie("");try{await w.sendRoomMessage(e,{files:n,onDelivered:()=>qe(l)}),qe(l)}catch(v){if(v instanceof Us){qe(l);const X=v.message.trim()?v.message:s("chat.messageSentButReplyFailed","Message sent, but assistant reply failed");o(s("chat.messageSentButReplyFailedDetail","Message sent, but assistant reply failed: {{detail}}",{detail:X}),"error");return}ie(i);const z=v instanceof Error&&v.message.trim()?v.message:s("chat.failedToSendRoomMessage","Failed to send room message");o(z,"error")}finally{jn.current=!1}return}Fn()}},[H,ge,Fe,P,w,w.clearRoom,ft,o,Fn,qe]),Gt=a.useCallback(async e=>{if(P==="rooms"){if(!w.activeRoom)return;try{await w.sendRoomMessage(e)}catch(n){const i=n instanceof Error&&n.message.trim()?n.message:s("chat.failedToSendRoomMessage","Failed to send room message");o(i,"error")}return}c&&oe(e)},[c,o,Fe,P,w,oe,s]),$n=a.useCallback(e=>{ie(n=>{const i=aa(n);if(!i)return n;const l=`/skill:${e.name} `,v=n.slice(0,i.start)+l+n.slice(i.end);return window.requestAnimationFrame(()=>{Y.current&&(le(Y.current),Y.current.focus())}),v}),Ue(!1),bt(""),He(0)},[le]),_n=a.useCallback((e,n)=>{if(n){o(s("chat.commandNoRunningAgent","No running agent to steer"),"warning");return}ie(i=>{const l=aa(i);if(!l)return i;const v=`${e.trigger} `,z=i.slice(0,l.start)+v+i.slice(l.end);return window.requestAnimationFrame(()=>{Y.current&&(le(Y.current),Y.current.focus())}),z}),Ue(!1),bt(""),He(0)},[le,o,s]),Yt=a.useCallback(e=>{const n=Y.current;if(!n||Cn<0)return;const i=n.selectionStart??ct.current,l=n.selectionEnd??i,v=Math.max(i,l),z=Math.min(Cn,v),W=`${`@${e.name.replace(/\s+/g,"_")}`} `,Ce=H.slice(0,z)+W+H.slice(v),as=z+W.length;ie(Ce),at(!1),nt(""),zt(0),st(-1),window.requestAnimationFrame(()=>{Y.current&&(le(Y.current),Y.current.focus(),Y.current.setSelectionRange(as,as))})},[Cn,H,le]),Rt=a.useCallback((e,n)=>{const l=Y.current?.selectionStart??ct.current,v=H.lastIndexOf("#",l),z=v>=0?v+n.length:e.length;ie(e),O.dismissMention(),Ut(!1),window.requestAnimationFrame(()=>{Y.current&&(le(Y.current),Y.current.focus(),Y.current.setSelectionRange(z,z))})},[O,H,le]),Ba=a.useCallback(e=>{if(ct.current=e.currentTarget.selectionStart??ct.current,O.mentionActive&&O.combinedItems.length>0){if(O.handleKeyDown(e,H),e.key==="Enter"||e.key==="Tab"){const n=O.combinedItems[O.selectedIndex];n?.kind==="task"?Rt(O.selectTask(n.task,H),`#${n.task.id}`):n?.kind==="file"&&Rt(O.selectFile(n.file,H),`#${n.file.path}`)}return}if(Se&&e.key==="ArrowDown"){e.preventDefault(),Ve.length>0&&zt(n=>(n+1)%Ve.length);return}if(Se&&e.key==="ArrowUp"){e.preventDefault(),Ve.length>0&&zt(n=>n===0?Ve.length-1:n-1);return}if(Se&&e.key==="Enter"){e.preventDefault();const n=Ve[_t]??Ve[0];n&&Yt(n);return}if(Se&&e.key==="Escape"){e.preventDefault(),at(!1),nt(""),st(-1);return}if(Ze&&e.key==="ArrowDown"){e.preventDefault(),be.length>0&&He(n=>(n+1)%be.length);return}if(Ze&&e.key==="ArrowUp"){e.preventDefault(),be.length>0&&He(n=>n===0?be.length-1:n-1);return}if(Ze&&(e.key==="Enter"||e.key==="Tab")&&be.length>0){e.preventDefault();const n=be[et]??be[0];n?.kind==="skill"?$n(n.skill):n?.kind==="command"&&_n(n.command,n.disabled);return}if(Ze&&e.key==="Escape"){e.preventDefault(),Ue(!1);return}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),Pn())},[Se,Ve,_t,Yt,Ze,be,et,$n,_n,Pn,O,Rt,H]),Jt=a.useCallback((e,n)=>{const i=Ho(e,n);if(i){at(!0),nt(i.filter),st(i.start);return}at(!1),nt(""),st(-1)},[]),Oa=a.useCallback(e=>{const n=e.target,i=n.value,l=n.selectionStart??i.length;le(n),ct.current=l,ie(i);const v=aa(i);v?(Ue(!0),bt(v.filter)):(Ue(!1),bt("")),Jt(i,l),O.detectMention(i,l),Ut(O.mentionActive),O.mentionActive&&kn(n)},[Jt,le]),Zt=a.useCallback(e=>{const n=e.currentTarget,i=n.selectionStart??n.value.length;ct.current=i,Jt(n.value,i),O.detectMention(n.value,i),Ut(O.mentionActive),O.mentionActive&&kn(n)},[Jt,O,kn]),Ua=a.useCallback(e=>{e.key!=="Escape"&&Zt(e)},[Zt]),Ha=a.useCallback(()=>{typeof window<"u"&&window.innerWidth<=768&&(Vt.current=!0,je.current!==null&&window.clearTimeout(je.current),je.current=window.setTimeout(()=>{Vt.current=!1,je.current=null},450),(window.scrollY!==0||window.scrollX!==0)&&window.scrollTo(0,0),Ae.current!==null&&window.clearTimeout(Ae.current),Ae.current=window.setTimeout(()=>{Ae.current=null,document.activeElement?.tagName!=="TEXTAREA"&&(window.scrollY!==0||window.scrollX!==0)&&window.scrollTo(0,0)},350)),Ne.current!==null&&window.clearTimeout(Ne.current),Ne.current=window.setTimeout(()=>{Ue(!1),at(!1),nt(""),st(-1),Ut(!1),O.dismissMention(),Ne.current=null},120)},[O]),Ka=a.useCallback(()=>{Vt.current=!1,je.current!==null&&(window.clearTimeout(je.current),je.current=null),Ne.current!==null&&(window.clearTimeout(Ne.current),Ne.current=null),Ae.current!==null&&(window.clearTimeout(Ae.current),Ae.current=null)},[]);a.useEffect(()=>()=>{je.current!==null&&window.clearTimeout(je.current),Ae.current!==null&&window.clearTimeout(Ae.current)},[]);const hr=a.useCallback(async e=>{Me(null);try{await G(e),o(s("chat.conversationArchived","Conversation archived"),"success")}catch{o(s("chat.failedToArchiveConversation","Failed to archive conversation"),"error")}},[G,o]),fr=a.useCallback(async e=>{try{await B(e),o(s("chat.conversationRestored","Conversation restored"),"success")}catch{o(s("chat.failedToRestoreConversation","Failed to restore conversation"),"error")}},[B,o,s]),gr=a.useCallback(e=>{const n=Be.find(i=>i.id===e)??(c?.id===e?c:null);Me(null),pn(n?.title??""),Dt({sessionId:e,title:n?.title??""})},[c,Be]),Va=a.useCallback(async()=>{if(Et)try{await se(Et.sessionId,gn),Dt(null),pn(""),o(s("chat.conversationRenamed","Conversation renamed"),"success")}catch{}},[o,Et,se,gn,s]),pr=a.useCallback(async(e,n)=>{Me(null);try{await ke(e,n),o(n?s("chat.conversationPinned","Conversation pinned"):s("chat.conversationUnpinned","Conversation unpinned"),"success")}catch{}},[o,ke,s]),vr=a.useCallback(async e=>{It(null),Me(null);try{await h(e),o(s("chat.conversationDeleted","Conversation deleted"),"success")}catch{o(s("chat.failedToDeleteConversation","Failed to delete conversation"),"error")}},[h,o]),br=a.useCallback(e=>{const n=Be.find(i=>i.id===e);fe("direct",e,n?.lastMessageAt??n?.updatedAt),D(e),Oe(!0)},[Be,fe,D]),en=a.useCallback(()=>{Oe(!1)},[]),tn=a.useCallback(()=>{Oe(!1)},[]),wr=a.useCallback(()=>{const e=P==="rooms"?tn:en;e(),ka?.(e)},[P,en,tn,ka]),xr=()=>t.jsxs("div",{className:"chat-empty-state",children:[t.jsx(cn,{size:48,strokeWidth:1.5}),t.jsx("h2",{children:s("chat.startNewConversation","Start a new conversation")}),t.jsxs("button",{className:"btn btn-primary",onClick:za,children:[t.jsx(sn,{size:16}),s("chat.newChat","New Chat")]})]}),De=Fs(c,c?.agentId?ve.get(c.agentId)??null:null,$t),zn=a.useMemo(()=>{if(!De?.provider||!De.modelId)return null;const e=xn.find(n=>n.provider===De.provider&&n.id===De.modelId);return e?.contextWindow?e.contextWindow:null},[De?.modelId,De?.provider,xn]),yr=a.useMemo(()=>$o(_,R?Z:void 0),[R,_,Z]),$e=cs(De?.provider,De?.modelId),Mt=De?.provider??null,Bn=!!(c||R||_.length>0),xe=Js&&(P==="rooms"?ne:Bn),qa=a.useRef(xe);a.useEffect(()=>{const e=qa.current;qa.current=xe,!(e||!xe)&&Ca({type:"view",revert:P==="rooms"?tn:en})},[P,en,tn,xe,Ca]);const Wa=c?.agentId===ze?$e??"Fusion":c?.title||ve.get(c?.agentId??"")?.name||c?.agentId||"Chat",Cr=!!($e&&$e!==Wa),kr=!pe&&Bn&&zn!==null,Qa=As(yr),nn=zn!==null?As(zn):null,On=nn?s("chat.contextWindowAria","Estimated {{used}} of {{total}} context tokens",{used:Qa,total:nn}):null,Un=ve.get(c?.agentId??"")?.name||(c?.agentId===ze?$e??"Fusion":c?.agentId?.slice(0,30)??"Fusion"),Hn=!1,Kn=c?.agentId===ze,Xa=a.useCallback((e,n)=>{const i=kt.current.get(e);i&&window.clearTimeout(i),ya(v=>({...v,[e]:n}));const l=window.setTimeout(()=>{ya(v=>{const{[e]:z,...X}=v;return X}),kt.current.delete(e)},2e3);kt.current.set(e,l)},[]),Ga=a.useCallback(async(e,n)=>{const i=await ao(n);Xa(e,i?"success":"error")},[Xa]),Vn=c?.agentId===ze,qn=a.useCallback((e,n,i,l,v=!0)=>{const z=Vn&&i==="assistant",X=v&&i==="assistant"&&M?so(n,s("chat.reportFallbackTitle","Chat report")):null;if(!(!z&&!X?.handoff))return t.jsxs(t.Fragment,{children:[z&&t.jsx("button",{type:"button",className:`btn-icon chat-message-copy-action${ot[e]==="success"?" chat-message-copy-action--success":""}${ot[e]==="error"?" chat-message-copy-action--error":""}`,"data-testid":l??`chat-copy-response-${e}`,"aria-label":ot[e]==="success"?s("chat.responseCopied","Response copied"):ot[e]==="error"?s("chat.copyFailed","Copy failed"):s("chat.copyResponse","Copy response"),onClick:()=>{Ga(e,n)},children:ot[e]==="success"?t.jsx(ro,{size:14}):t.jsx(oo,{size:14})}),X?.handoff&&t.jsx("button",{type:"button",className:"btn-icon","data-testid":`chat-send-as-report-${e}`,"aria-label":s("chat.sendAsReport","Send as report"),onClick:()=>{X.truncated&&o(s("chat.reportTrimmed","Message trimmed to 2000 characters for mail"),"warning"),M?.(X.handoff)},children:t.jsx(io,{size:14})})]})},[o,ot,Ga,M,Vn,s]),Wn=a.useCallback(e=>{const n=ce.current;if(!n)return;const i=`[data-testid="chat-message-${e}"]`,l=n.querySelector(i);if(!l)return;const v=l.getBoundingClientRect().top-n.getBoundingClientRect().top+n.scrollTop,z=typeof window<"u"&&window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;n.scrollTo({top:v,behavior:z?"auto":"smooth"})},[]),Ya=c?.cliExecutorAdapterId??null,Qn=!!Ya,Rr=Ya==="generic"?"generic":"hybrid",Mr=c?.cliSessionFile||c?.id||"",Ja=!Qn&&!R,Za=()=>t.jsxs("div",{className:"chat-messages",ref:ce,onScroll:Pa,children:[t.jsx("div",{ref:Ma,className:"chat-load-more-sentinel",children:un&&J&&t.jsx("div",{className:"chat-loading-older",children:s("chat.loadingOlderMessages","Loading older messages…")})}),R?t.jsxs(t.Fragment,{children:[_.map((e,n)=>t.jsx(Yn,{message:e,forcePlain:!1,agentName:Un,hideAssistantIdentity:Kn,showAssistantModelTag:Hn,activeModelTag:$e,activeModelProvider:Mt,activeSessionId:c?.id??null,projectId:r,mentionAgentsByName:In,roomContext:null,copyAction:qn(e.id,e.content,e.role),onScrollToTop:Wn,isTopClipped:Sn.has(e.id),isAwaitingQuestionAnswer:e.role==="assistant"&&n===_.length-1&&!R,submittedQuestionAnswer:Es(_,n),onQuestionSubmit:Gt,canEdit:Ja,onEditMessage:Le},e.id)),t.jsx(vo,{streamingText:Z,streamingThinking:U,streamingToolCalls:ae,forcePlain:!1,agentName:Un,hideAssistantIdentity:Kn,showAssistantModelTag:Hn,activeModelTag:$e,activeModelProvider:Mt,copyAction:Vn&&Z?qn("__streaming__",Z,"assistant","chat-copy-response-streaming",!1):void 0,onQuestionSubmit:Gt})]}):J&&_.length===0?t.jsx("div",{className:"chat-empty-state",children:s("chat.loadingMessages","Loading messages...")}):_.length===0&&!c?xr():_.length===0&&c?t.jsx("div",{className:"chat-empty-state",children:s("chat.noMessagesYet","No messages yet. Start the conversation!")}):t.jsx(t.Fragment,{children:_.map((e,n)=>t.jsx(Yn,{message:e,forcePlain:!1,agentName:Un,hideAssistantIdentity:Kn,showAssistantModelTag:Hn,activeModelTag:$e,activeModelProvider:Mt,activeSessionId:c?.id??null,projectId:r,mentionAgentsByName:In,roomContext:null,copyAction:qn(e.id,e.content,e.role),onScrollToTop:Wn,isTopClipped:Sn.has(e.id),isAwaitingQuestionAnswer:e.role==="assistant"&&n===_.length-1&&!R,submittedQuestionAnswer:Es(_,n),onQuestionSubmit:Gt,canEdit:Ja,onEditMessage:Le},e.id))}),t.jsx("div",{ref:Ra})]}),es=()=>t.jsxs("div",{className:"chat-input-area",children:[t.jsx("input",{ref:qt,type:"file","data-testid":"chat-file-input",accept:Ls,multiple:!0,style:{display:"none"},onChange:e=>{mt(e.target.files),e.target.value=""}}),Ze&&t.jsx("div",{className:"chat-skill-menu","data-testid":"chat-skill-menu",role:"listbox","aria-label":s("chat.skillSuggestions","Skill suggestions"),children:ar&&Dn.length===0?t.jsx("div",{className:"chat-skill-menu-empty",children:s("chat.loadingSkills","Loading skills…")}):be.length===0?t.jsx("div",{className:"chat-skill-menu-empty",children:vt?s("chat.noSkillsFound","No skills found"):s("chat.noSkillsAvailable","No skills available")}):be.map((e,n)=>e.kind==="command"?t.jsxs("button",{type:"button",role:"option","aria-selected":n===et,"aria-disabled":e.disabled,className:`chat-skill-menu-item chat-command-menu-item${n===et?" chat-skill-menu-item--highlighted":""}${e.disabled?" chat-command-menu-item--disabled":""}`,onMouseDown:i=>i.preventDefault(),onMouseEnter:()=>He(n),onClick:()=>_n(e.command,e.disabled),children:[t.jsx("span",{className:"chat-skill-menu-item-name",children:e.command.trigger}),t.jsx("span",{className:"chat-skill-menu-item-description",children:e.disabled?s("chat.commandNoRunningAgentHint","No running agent to steer"):e.command.description})]},`command-${e.command.trigger}`):t.jsxs("button",{type:"button",role:"option","aria-selected":n===et,className:`chat-skill-menu-item${n===et?" chat-skill-menu-item--highlighted":""}`,onMouseDown:i=>i.preventDefault(),onMouseEnter:()=>He(n),onClick:()=>$n(e.skill),children:[t.jsx("span",{className:"chat-skill-menu-item-name",children:e.skill.name}),t.jsx("span",{className:"chat-skill-menu-item-description",title:e.skill.relativePath,children:e.skill.relativePath})]},e.skill.id))}),ge.length>0&&t.jsx("div",{className:"chat-attachment-previews","data-testid":"chat-attachment-previews",children:ge.map((e,n)=>t.jsxs("div",{className:"chat-attachment-preview","data-testid":`chat-attachment-preview-${n}`,children:[e.previewUrl?t.jsx("img",{src:e.previewUrl,alt:e.file.name}):t.jsx("span",{className:"chat-attachment-preview-name",children:e.file.name}),t.jsx("button",{type:"button",className:"chat-attachment-remove",onClick:()=>$a(n),"data-testid":`chat-attachment-remove-${n}`,"aria-label":`Remove ${e.file.name}`,children:"×"})]},e.previewUrl||`${e.file.name}-${n}`))}),t.jsx(bo,{messages:Xe,disabled:Ge,onEdit:Vs??(()=>{}),onMove:qs??(()=>{}),onDelete:dn,onForceSend:Ws??(()=>{}),testIdPrefix:"chat-pending"}),t.jsxs("div",{className:"chat-input-row",children:[t.jsx("button",{type:"button",className:"btn-icon chat-attach-btn","data-testid":"chat-attach-btn","aria-label":s("chat.attachFiles","Attach files"),onClick:()=>qt.current?.click(),disabled:Ge,children:t.jsx(gs,{size:16})}),!Qn&&t.jsx(ps,{level:c?.thinkingLevel,defaultThinkingLevel:$,models:xn,favoriteProviders:er,favoriteModels:tr,agents:Array.from(ve.values()),agentId:c?.agentId,modelProvider:c?.modelProvider,modelId:c?.modelId,onChange:e=>{c&&x(c.id,e)},onChangeModel:e=>{c&&g(c.id,e)},disabled:!c||Ge}),t.jsxs("div",{className:`chat-input-wrapper${wa?" chat-input-wrapper--dragover":""}`,onDragOver:e=>{e.preventDefault(),rt(!0)},onDragLeave:()=>rt(!1),onDrop:e=>{e.preventDefault(),rt(!1),mt(e.dataTransfer.files)},children:[t.jsx("textarea",{ref:ur,className:"chat-input-textarea",placeholder:s("chat.typeMessage","Type a message..."),value:H,onChange:Oa,onKeyDown:Ba,onKeyUp:Ua,onClick:Zt,onBlur:Ha,onFocus:Ka,onPaste:_a,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||Jn()&&(document.activeElement,e.currentTarget)},rows:1,disabled:Ge,"data-testid":"chat-input"}),t.jsx(Ms,{agents:lt,filter:tt,highlightedIndex:_t,visible:Se,onSelect:Yt,position:"below",roomMemberIds:Te?.memberIds,roomName:Te?.roomName}),t.jsx(Ao,{visible:O.mentionActive&&!Se,position:sr,tasks:O.tasks,files:O.files,selectedIndex:O.selectedIndex,onSelectTask:e=>{Rt(O.selectTask(e,H),`#${e.id}`)},onSelectFile:e=>{Rt(O.selectFile(e,H),`#${e.path}`)},loading:O.loading})]}),t.jsx(vs,{...lr.micProps,disabled:Ge}),t.jsx(bs,{isStreaming:R,canSend:!Ge&&!!(H.trim()||ge.length>0),onSend:Fn,onStop:he})]})]}),ts=Je?Q:Be,Sr=ts.filter(e=>e.pinnedAt!=null),Nr=ts.filter(e=>e.pinnedAt==null),ye=V?Be.find(e=>e.id===V.sessionId)??(c?.id===V.sessionId?c:void 0):void 0,ns=a.useCallback(async()=>{const e=vn.trim();if(!e)return;let n;try{n=await ue(e)}catch{o(s("chat.failedToCreateTag","Failed to create tag"),"error");return}if(V?.sessionId){const i=(ye?.tags??[]).map(l=>l.id);if(!i.includes(n.id))try{await Re(V.sessionId,[...i,n.id])}catch{o(s("chat.failedToUpdateTags","Failed to update tags"),"error");return}}ha("")},[o,V,ye,ue,vn,Re,s]),jr=t.jsxs("div",{className:"chat-sidebar-scope-toggle chat-view-header-scope-toggle",role:"tablist","data-testid":"chat-sidebar-scope-toggle",children:[t.jsxs("button",{type:"button",role:"tab",className:`chat-sidebar-scope-btn${P==="direct"?" chat-sidebar-scope-btn--active":""}`,"aria-selected":P==="direct","data-testid":"chat-sidebar-scope-direct",onClick:()=>Ye("direct"),children:[t.jsx(cn,{size:14,"aria-hidden":"true"}),t.jsx("span",{children:s("chat.scopeDirect","Direct")})]}),t.jsxs("button",{type:"button",role:"tab",className:`chat-sidebar-scope-btn${P==="rooms"?" chat-sidebar-scope-btn--active":""}`,"aria-selected":P==="rooms","data-testid":"chat-sidebar-scope-rooms",onClick:()=>Ye("rooms"),children:[t.jsx(Os,{size:14,"aria-hidden":"true"}),t.jsx("span",{children:s("chat.scopeRooms","Rooms")})]})]});return t.jsxs("div",{ref:Ea,className:`chat-view${u?" chat-view--floating":""}${pe?" chat-view--narrow":""}${xe?" chat-view--detail":""}${A==="full-width"?" chat-view--full-width":""}`,children:[t.jsx(co,{icon:cn,title:s("chat.title","Chat"),actions:t.jsxs(t.Fragment,{children:[xe?t.jsx("button",{className:"btn-icon chat-back-btn",onClick:wr,"data-testid":"chat-back-btn","aria-label":s("chat.backToConversations","Back to conversations"),children:t.jsx(lo,{size:16})}):jr,xe?null:t.jsxs("button",{className:"btn btn-sm btn-primary chat-view-header-new-chat",onClick:za,"data-testid":"chat-new-btn",children:[t.jsx(sn,{size:14}),s("chat.newChat","New Chat")]}),!u&&d?t.jsx("button",{type:"button",className:"btn-icon chat-view-header-icon",onClick:d,"aria-label":s("chat.popOut","Pop out chat"),title:s("chat.popOut","Pop out chat"),"data-testid":"chat-pop-out",children:t.jsx(ls,{size:16})}):null,u&&m?t.jsx("button",{type:"button",className:"btn-icon chat-view-header-icon",onClick:m,"aria-label":s("chat.maximizeToChatView","Open in Chat view"),title:s("chat.maximizeToChatView","Open in Chat view"),"data-testid":"chat-modal-maximize",children:t.jsx(ls,{size:16})}):null,u&&y?t.jsx("button",{type:"button",className:"btn-icon chat-view-header-icon",onClick:y,"aria-label":s("chat.minimizeToQuickChat","Minimize to quick chat"),title:s("chat.minimizeToQuickChat","Minimize to quick chat"),"data-testid":"chat-modal-minimize",children:t.jsx(uo,{size:16})}):null,u&&k?t.jsx("button",{type:"button",className:"btn-icon chat-view-header-icon",onClick:k,"aria-label":s("chat.closeChat","Close chat"),title:s("chat.closeChat","Close chat"),"data-testid":"chat-modal-close",children:t.jsx(ds,{size:16})}):null]})}),t.jsxs("div",{className:"chat-view__body",children:[t.jsxs("div",{className:`chat-sidebar${xe?" chat-sidebar--hidden":""}`,children:[P==="direct"?t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"chat-sidebar-search-container",children:[t.jsxs("div",{className:"chat-sidebar-search-wrapper",children:[t.jsx(mo,{size:14,className:"chat-sidebar-search-icon"}),t.jsx("input",{type:"text",className:"chat-sidebar-search",placeholder:s("chat.searchConversations","Search conversations..."),value:Qs,onChange:e=>Xs(e.target.value),"data-testid":"chat-search-input"})]}),t.jsxs("label",{className:"chat-tag-filter",htmlFor:"chat-tag-filter",children:[t.jsx(ko,{size:14,"aria-hidden":"true"}),t.jsxs("select",{id:"chat-tag-filter",value:F??"",onChange:e=>K(e.target.value||null),"data-testid":"chat-tag-filter","aria-label":s("chat.filterByTag","Filter conversations by tag"),children:[t.jsx("option",{value:"",children:s("chat.allTags","All tags")}),S.map(e=>t.jsx("option",{value:e.id,children:e.name},e.id))]}),F?t.jsx("button",{type:"button",className:"btn-icon","aria-label":s("chat.clearTagFilter","Clear tag filter"),onClick:()=>K(null),children:t.jsx(ds,{size:14})}):null]})]}),t.jsx("div",{className:"chat-archived-toggle",children:t.jsx("button",{type:"button",className:"btn btn-sm btn-secondary","data-testid":"chat-archived-toggle",onClick:()=>{const e=!Je;Ys(e),e&&T()},children:Je?"Active conversations":"Archived conversations"})}),t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:te?t.jsx("div",{className:"chat-empty-state chat-empty-state--padded",children:s("chat.loadingConversations","Loading...")}):(Je?Q:Be).length===0?t.jsx("div",{className:"chat-empty-state chat-empty-state--padded",children:s("chat.noConversationsYet","No conversations yet")}):t.jsx(t.Fragment,{children:[{id:"pinned",label:s("chat.pinned","Pinned"),testId:"chat-pinned-divider",sessions:Sr},{id:"recent",label:s("chat.recent","Recent"),testId:"chat-recent-divider",sessions:Nr}].filter(e=>e.sessions.length>0).map(e=>t.jsxs("section",{className:"chat-session-section","data-testid":`chat-session-section-${e.id}`,children:[t.jsx("div",{className:"chat-pinned-divider","data-testid":e.testId,children:e.label}),e.sessions.map(n=>{const i=c?.id===n.id,l=!i&&la("direct",n.id,n.lastMessageAt??n.updatedAt),v=Fs(n,ve.get(n.agentId)??null,$t),z=cs(v?.provider,v?.modelId)??"Fusion",X=n.title||s("chat.untitledSession","Untitled");return t.jsxs("div",{className:`chat-session-item${i?" chat-session-item--active":""}`,onClick:()=>br(n.id),onContextMenu:W=>{W.preventDefault(),da(n.id,W.clientX,W.clientY)},"data-testid":Je?`chat-archived-session-${n.id}`:`chat-session-${n.id}`,children:[t.jsx("button",{type:"button",className:"btn-icon chat-session-menu-btn","data-testid":"chat-session-menu-btn","aria-label":s("chat.conversationActionsAria","Conversation actions for {{title}}",{title:X}),"aria-haspopup":"menu","aria-expanded":V?.sessionId===n.id,onClick:W=>{if(W.stopPropagation(),V?.sessionId===n.id){Me(null);return}const Ce=W.currentTarget.getBoundingClientRect();da(n.id,Ce.right,Ce.bottom,{anchorRight:!0})},children:t.jsx(ho,{size:14})}),t.jsxs("div",{className:"chat-session-title",children:[X,n.pinnedAt?t.jsx(us,{className:"chat-session-pinned-indicator",size:14,"data-testid":`chat-session-pinned-indicator-${n.id}`,"aria-label":s("chat.pinned","Pinned")}):null,l?t.jsx("span",{className:"chat-unread-dot","data-testid":`chat-unread-dot-${n.id}`,"aria-label":s("chat.unreadMessages","Unread messages")}):null]}),t.jsx("div",{className:"chat-session-preview",children:n.lastMessagePreview||s("chat.noMessages","No messages")}),(n.tags??[]).length>0?t.jsx("div",{className:"chat-session-tags","data-testid":`chat-session-tags-${n.id}`,children:(n.tags??[]).map(W=>t.jsx("span",{className:"chat-session-tag",children:W.name},W.id))}):null,n.matchedMessagePreview?t.jsx("div",{className:"chat-session-preview chat-session-preview--matched","data-testid":`chat-session-matched-preview-${n.id}`,children:s("chat.matchedInMessage",'Matched: "{{preview}}"',{preview:n.matchedMessagePreview})}):null,Je?t.jsx("button",{type:"button",className:"btn btn-sm btn-secondary","data-testid":`chat-archived-restore-${n.id}`,onClick:W=>{W.stopPropagation(),fr(n.id)},children:s("chat.restore","Restore")}):null,t.jsxs("div",{className:"chat-session-meta",children:[t.jsxs("span",{className:"chat-session-meta-model",children:[v?.provider?t.jsx(ms,{provider:v.provider,size:"sm"}):null,t.jsx("span",{children:ve.get(n.agentId)?.name||(n.agentId===ze?z:n.agentId.slice(0,30))})]}),t.jsx("span",{children:n.updatedAt?Bo(n.updatedAt,s):""})]})]},n.id)})]},e.id))})})]}):t.jsxs("div",{className:"chat-sidebar-rooms","data-testid":"chat-sidebar-rooms",children:[!pe&&t.jsx("div",{className:"chat-sidebar-rooms-header","data-testid":"chat-sidebar-rooms-header",children:t.jsxs("button",{type:"button",className:"btn btn-sm btn-primary","data-testid":"chat-create-room-btn",onClick:()=>Pt(!0),children:[t.jsx(sn,{size:14}),s("chat.createRoom","Create room")]})}),w.rooms.length===0?t.jsx("div",{className:"chat-sidebar-rooms-empty","data-testid":"chat-sidebar-rooms-empty",children:s("chat.noRoomsYet","No rooms yet.")}):t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:w.rooms.map(e=>{const n=w.activeRoom?.id===e.id,i=!n&&la("room",e.id,e.updatedAt);return t.jsxs("div",{role:"button",tabIndex:0,className:`chat-room-item${n?" chat-room-item--active":""}`,"data-testid":`chat-room-item-${e.slug}`,onClick:()=>{fe("room",e.id,e.updatedAt),w.selectRoom(e.id),Oe(!0)},onKeyDown:l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),fe("room",e.id,e.updatedAt),w.selectRoom(e.id),Oe(!0))},children:[t.jsxs("span",{className:"chat-room-item-details",children:[t.jsxs("span",{className:"chat-room-item-name-row",children:[t.jsxs("span",{className:"chat-room-item-name",children:["#",e.name]}),i?t.jsx("span",{className:"chat-unread-dot","data-testid":`chat-unread-dot-${e.id}`,"aria-label":s("chat.unreadMessages","Unread messages")}):null]}),n?t.jsx("span",{className:"chat-room-item-meta",children:s("chat.roomMemberCount","{{count}} member",{count:w.activeRoomMembers.length,defaultValue_one:"{{count}} member",defaultValue_other:"{{count}} members"})}):null]}),t.jsx("button",{type:"button",className:"btn-icon chat-room-item-delete","data-testid":`chat-room-delete-${e.slug}`,"aria-label":s("chat.deleteRoom","Delete room {{name}}",{name:e.name}),onClick:l=>{l.stopPropagation(),Lt(e.id)},children:t.jsx(Gn,{size:14})})]},e.id)})})]}),P==="rooms"&&pe?t.jsx("div",{className:"chat-sidebar-footer",children:t.jsxs("button",{type:"button",className:"btn btn-sm btn-primary chat-sidebar-footer-btn","data-testid":"chat-create-room-btn",onClick:()=>Pt(!0),children:[t.jsx(sn,{size:14}),s("chat.createRoom","Create room")]})}):null]}),V&&t.jsxs("div",{className:"chat-session-context-menu",ref:fn,role:"menu",style:{top:V.y,left:V.x},onClick:e=>e.stopPropagation(),children:[t.jsxs("button",{onClick:()=>pr(V.sessionId,!ye?.pinnedAt),"data-testid":"chat-context-pin",title:p>=3&&!ye?.pinnedAt?s("chat.pinLimit","You can pin up to 3 conversations"):void 0,disabled:p>=3&&!ye?.pinnedAt,children:[ye?.pinnedAt?t.jsx(fo,{size:14}):t.jsx(us,{size:14}),ye?.pinnedAt?s("chat.unpin","Unpin"):s("chat.pin","Pin")]}),t.jsxs("button",{onClick:()=>gr(V.sessionId),"data-testid":"chat-context-rename",children:[t.jsx(hs,{size:14}),s("chat.rename","Rename")]}),t.jsxs("div",{className:"chat-session-tag-menu",role:"group","aria-label":s("chat.conversationTags","Conversation tags"),children:[S.map(e=>{const n=(ye?.tags??[]).some(i=>i.id===e.id);return t.jsxs("div",{className:"chat-tag-menu-item",children:[t.jsxs("button",{type:"button",role:"menuitemcheckbox","aria-checked":n,"data-testid":`chat-context-tag-${e.id}`,onClick:()=>void Re(V.sessionId,n?(ye?.tags??[]).filter(i=>i.id!==e.id).map(i=>i.id):[...(ye?.tags??[]).map(i=>i.id),e.id]).catch(()=>o(s("chat.failedToUpdateTags","Failed to update tags"),"error")),children:[n?"✓ ":"",e.name]}),t.jsx("button",{type:"button",className:"btn-icon","aria-label":s("chat.renameTag","Rename tag {{name}}",{name:e.name}),"data-testid":`chat-context-rename-tag-${e.id}`,onClick:i=>{i.stopPropagation(),fa(e.name),pt(e)},children:t.jsx(hs,{size:14})}),t.jsx("button",{type:"button",className:"btn-icon","aria-label":s("chat.deleteTag","Delete tag {{name}}",{name:e.name}),"data-testid":`chat-context-delete-tag-${e.id}`,onClick:i=>{i.stopPropagation(),Ft(e)},children:t.jsx(Gn,{size:14})})]},e.id)}),t.jsxs("div",{className:"chat-tag-create-row",children:[t.jsx("input",{className:"input",value:vn,placeholder:s("chat.newTag","New tag"),"aria-label":s("chat.newTag","New tag"),onChange:e=>ha(e.target.value),onKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),ns())}}),t.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void ns(),children:s("chat.addTag","Add")})]})]}),t.jsxs("button",{onClick:()=>hr(V.sessionId),"data-testid":"chat-context-archive",children:[t.jsx(go,{size:14}),s("chat.archive","Archive")]}),t.jsxs("button",{onClick:()=>{Me(null),It(V.sessionId)},"data-testid":"chat-context-delete",children:[t.jsx(Gn,{size:14}),s("chat.delete","Delete")]})]}),Et&&t.jsx(At,{onClose:()=>Dt(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"chat-rename-dialog-title",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{id:"chat-rename-dialog-title",children:s("chat.renameConversationTitle","Rename Conversation")}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:s("chat.renameConversationBody","Choose a new name for this conversation. Leave it blank to show Untitled.")}),t.jsx("label",{className:"chat-rename-label",htmlFor:"chat-rename-input",children:s("chat.conversationName","Conversation name")}),t.jsx("input",{id:"chat-rename-input",className:"input chat-rename-input",type:"text",value:gn,placeholder:s("chat.renamePlaceholder","Untitled"),"data-testid":"chat-rename-input",onChange:e=>pn(e.target.value),onKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),Va())},autoFocus:!0}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>Dt(null),children:s("chat.cancel","Cancel")}),t.jsx("button",{className:"btn btn-sm btn-primary",onClick:()=>void Va(),"data-testid":"chat-rename-save",children:s("chat.save","Save")})]})]})}),bn&&t.jsx(At,{onClose:()=>pt(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"chat-rename-tag-dialog-title",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{id:"chat-rename-tag-dialog-title",children:s("chat.renameTagTitle","Rename tag")}),t.jsx("label",{className:"chat-rename-label",htmlFor:"chat-rename-tag-input",children:s("chat.tagName","Tag name")}),t.jsx("input",{id:"chat-rename-tag-input",className:"input chat-rename-input",value:wn,"data-testid":"chat-rename-tag-input",onChange:e=>fa(e.target.value),onKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),ee(bn.id,wn).then(()=>pt(null)).catch(()=>o(s("chat.failedToRenameTag","Failed to rename tag"),"error")))},autoFocus:!0}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>pt(null),children:s("chat.cancel","Cancel")}),t.jsx("button",{className:"btn btn-sm btn-primary","data-testid":"chat-rename-tag-save",onClick:()=>void ee(bn.id,wn).then(()=>pt(null)).catch(()=>o(s("chat.failedToRenameTag","Failed to rename tag"),"error")),children:s("chat.save","Save")})]})]})}),ga&&t.jsx(At,{onClose:()=>Ft(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"chat-delete-tag-dialog-title",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{id:"chat-delete-tag-dialog-title",children:s("chat.deleteTagTitle","Delete tag?")}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:s("chat.deleteTagBody","This removes the tag from all conversations, but does not delete conversations.")}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>Ft(null),children:s("chat.cancel","Cancel")}),t.jsx("button",{className:"btn btn-sm btn-danger","data-testid":"chat-delete-tag-confirm",onClick:()=>void re(ga.id).then(()=>Ft(null)).catch(()=>o(s("chat.failedToDeleteTag","Failed to delete tag"),"error")),children:s("chat.delete","Delete")})]})]})}),ua&&t.jsx(At,{onClose:()=>It(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:s("chat.deleteConversationTitle","Delete Conversation?")}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:s("chat.deleteConversationBody","This action cannot be undone. All messages in this conversation will be permanently deleted.")}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>It(null),children:s("chat.cancel","Cancel")}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void vr(ua),children:s("chat.delete","Delete")})]})]})}),ma&&t.jsx(At,{onClose:()=>Lt(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:s("chat.deleteRoomTitle","Delete Room?")}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:s("chat.deleteRoomBody","This action cannot be undone. This room and all its messages will be permanently deleted.")}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>Lt(null),children:s("chat.cancel","Cancel")}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>{(async()=>{try{await w.deleteRoom(ma),Lt(null)}catch{o(s("chat.failedToDeleteRoom","Failed to delete room"),"error")}})()},children:s("chat.delete","Delete")})]})]})}),xe&&Fe&&P==="rooms"?t.jsxs("div",{ref:Mn,className:"chat-thread",children:[w.activeRoom?t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"chat-room-thread-header",children:[t.jsxs("span",{className:"chat-thread-header-title",children:["#",w.activeRoom.name]}),t.jsx("div",{className:"chat-room-thread-members",children:w.activeRoomMembers.map(e=>t.jsx(ln,{agent:ve.get(e.agentId)??{id:e.agentId,name:e.agentId.slice(0,30)}},e.agentId))})]}),t.jsxs("div",{className:"chat-messages",ref:ce,onScroll:Pa,children:[w.messagesLoading&&w.messages.length===0?t.jsx("div",{className:"chat-empty-state",children:s("chat.loadingMessages","Loading messages...")}):w.messages.filter(e=>e.content.trim()!==Ts).length===0?t.jsx("div",{className:"chat-empty-state",children:s("chat.noMessagesYet","No messages yet. Start the conversation!")}):w.messages.filter(e=>e.content.trim()!==Ts).map(e=>{const n=e.senderAgentId?ve.get(e.senderAgentId)?.name??e.senderAgentId.slice(0,30):s("chat.you","You"),i={id:e.id,sessionId:e.roomId,role:e.role,content:e.content,thinkingOutput:e.thinkingOutput??void 0,toolCalls:void 0,fallbackInfo:void 0,attachments:e.attachments,createdAt:e.createdAt};return t.jsx(Yn,{message:i,forcePlain:!1,agentName:n,hideAssistantIdentity:!1,showAssistantModelTag:!1,activeModelTag:null,activeModelProvider:null,activeSessionId:w.activeRoom?.id??null,projectId:r,mentionAgentsByName:In,roomContext:Te,onScrollToTop:Wn,isTopClipped:Sn.has(e.id),isAwaitingQuestionAnswer:!1,onQuestionSubmit:Gt},e.id)}),t.jsx("div",{ref:Ra})]}),w.activeRoom&&xa&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:()=>we("fab-click"),children:[t.jsx(fs,{size:14}),s("chat.latest","Latest")]})]}):t.jsx("div",{className:"chat-room-empty-pane","data-testid":"chat-rooms-empty-pane",children:s("chat.selectRoomOrCreate","Select a room or create one")}),w.activeRoom&&t.jsxs("div",{className:"chat-input-area",children:[t.jsx("input",{ref:qt,type:"file",accept:Ls,multiple:!0,style:{display:"none"},onChange:e=>{mt(e.target.files),e.target.value=""}}),ge.length>0&&t.jsx("div",{className:"chat-attachment-previews","data-testid":"chat-attachment-previews",children:ge.map((e,n)=>t.jsxs("div",{className:"chat-attachment-preview","data-testid":`chat-attachment-preview-${n}`,children:[e.previewUrl?t.jsx("img",{src:e.previewUrl,alt:e.file.name}):t.jsx("span",{className:"chat-attachment-preview-name",children:e.file.name}),t.jsx("button",{type:"button",className:"chat-attachment-remove",onClick:()=>$a(n),"data-testid":`chat-attachment-remove-${n}`,"aria-label":`Remove ${e.file.name}`,children:"×"})]},e.previewUrl||`${e.file.name}-${n}`))}),t.jsxs("div",{className:"chat-input-row",children:[t.jsx("button",{type:"button",className:"btn-icon chat-attach-btn","data-testid":"chat-attach-btn","aria-label":s("chat.attachFiles","Attach files"),onClick:()=>qt.current?.click(),children:t.jsx(gs,{size:16})}),t.jsx(ps,{level:w.activeRoom.thinkingLevel,defaultThinkingLevel:$,showTargetSection:!1,onChange:e=>{w.updateRoomSettings(w.activeRoom.id,{thinkingLevel:e||null}).catch(()=>{o(s("chat.failedToUpdateRoomThinkingLevel","Failed to update room thinking effort"),"error")})}}),t.jsxs("div",{className:`chat-input-wrapper${wa?" chat-input-wrapper--dragover":""}`,onDragOver:e=>{e.preventDefault(),rt(!0)},onDragLeave:()=>rt(!1),onDrop:e=>{e.preventDefault(),rt(!1),mt(e.dataTransfer.files)},children:[t.jsx("textarea",{ref:mr,className:"chat-input-textarea",placeholder:s("chat.typeMessage","Type a message..."),value:H,onChange:Oa,onKeyDown:Ba,onKeyUp:Ua,onClick:Zt,onBlur:Ha,onFocus:Ka,onPaste:_a,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||Jn()&&(document.activeElement,e.currentTarget)},rows:1,"data-testid":"chat-input"}),t.jsx(Ms,{agents:lt,filter:tt,highlightedIndex:_t,visible:Se,onSelect:Yt,position:"below",roomMemberIds:Te?.memberIds,roomName:Te?.roomName})]}),t.jsx(vs,{...dr.micProps}),t.jsx(bs,{isStreaming:!1,canSend:!!(H.trim()||ge.length>0),onSend:Pn})]})]})]}):xe?t.jsxs("div",{ref:Mn,className:"chat-thread",children:[!pe&&(Bn||!pe)&&t.jsx("div",{className:"chat-thread-header",children:t.jsxs("div",{className:"chat-thread-header-identity","data-testid":"chat-thread-header-identity",children:[Mt?t.jsx(ms,{provider:Mt,size:"md"}):t.jsx(zs,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:Wa}),Cr&&t.jsx("span",{className:"chat-model-tag",children:$e}),kr&&nn&&On?t.jsxs("span",{className:"chat-thread-header-context","data-testid":"chat-thread-context-window",title:On,"aria-label":On,children:[Qa," / ",nn]}):null]})}),Qn?t.jsx(Do,{cliSessionId:Mr,tier:Rr,projectId:r,renderTranscript:Za,renderComposer:()=>c?es():null}):t.jsxs(t.Fragment,{children:[Za(),xa&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:()=>we("fab-click"),children:[t.jsx(fs,{size:14}),s("chat.latest","Latest")]}),c&&es()]})]}):null,t.jsx(Eo,{isOpen:Zs,onClose:()=>Pt(!1),projectId:r,existingRoomNames:w.rooms.map(e=>e.name),onCreate:async e=>{await w.createRoom({name:e.name,memberAgentIds:e.memberAgentIds}),P!=="rooms"&&Ye("rooms"),Pt(!1),Oe(!0)}})]}),Gs&&t.jsx(Vo,{projectId:r,defaultModel:nr,defaultKind:N?.kind,defaultAgentId:N?.kind==="agent"?N.agentId:void 0,defaultThinkingLevel:$,defaultSelectedThinkingLevel:N?.kind==="model"?N.thinkingLevel:void 0,onClose:()=>hn(!1),onCreate:ht})]})}export{ni as ChatView,ti as buildIssueChatPrefill,ri as clampChatInputHeight,zo as resolveChatContextMenuPosition,oi as resolveChatInputOverflowY,Fs as resolveSessionProvider};