@runfusion/fusion 0.38.1 → 0.39.0

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 (58) hide show
  1. package/dist/bin.js +3325 -858
  2. package/dist/client/.vite/manifest.json +58 -58
  3. package/dist/client/assets/{AgentDetailView-DuRYmHK3.js → AgentDetailView-nS4sABBv.js} +1 -1
  4. package/dist/client/assets/{AgentPermissionPolicyEditor-ClY32kYN.js → AgentPermissionPolicyEditor-DiYAo51R.js} +1 -1
  5. package/dist/client/assets/{AgentsView-UbCAHs_i.js → AgentsView-VbUsJLma.js} +3 -3
  6. package/dist/client/assets/ChatView-B1AMky9x.js +6 -0
  7. package/dist/client/assets/{DevServerView-DY5GlJcD.js → DevServerView-CyFdAcCd.js} +1 -1
  8. package/dist/client/assets/{DirectoryPicker-B4VRL2BH.js → DirectoryPicker-C7v2Esic.js} +1 -1
  9. package/dist/client/assets/{DocumentsView-tqpIZ9t9.js → DocumentsView-P_YIsnO0.js} +1 -1
  10. package/dist/client/assets/{EvalsView-C_Br3ry8.js → EvalsView-2zyH0dWG.js} +1 -1
  11. package/dist/client/assets/{ExperimentalAgentOnboardingModal-lXM--LV-.js → ExperimentalAgentOnboardingModal-DoRPGkfN.js} +1 -1
  12. package/dist/client/assets/{GoalsView-B65urz9k.css → GoalsView-Dky8vDoG.css} +1 -1
  13. package/dist/client/assets/GoalsView-l0PVSxK4.js +2 -0
  14. package/dist/client/assets/{InsightsView-BYfsVobi.js → InsightsView-BZKu5-C3.js} +1 -1
  15. package/dist/client/assets/{MemoryView-DT4vIhaW.js → MemoryView-CYBNC_h8.js} +1 -1
  16. package/dist/client/assets/{NodesView-Dx6HFqjI.js → NodesView-CQ63uWC8.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-BcGBnNiC.js → PiExtensionsManager-BNXxlpb6.js} +1 -1
  18. package/dist/client/assets/{PluginManager-T_XZ7iNI.js → PluginManager-DejpEyl7.js} +1 -1
  19. package/dist/client/assets/{ResearchView-Bv4igpnv.js → ResearchView-B4u2YieX.js} +1 -1
  20. package/dist/client/assets/{SecretsView-C4VX2ZTa.js → SecretsView-DvMMG_rf.js} +1 -1
  21. package/dist/client/assets/SettingsModal-986SEzVN.css +1 -0
  22. package/dist/client/assets/SettingsModal-C2mfeKp1.js +31 -0
  23. package/dist/client/assets/{SettingsModal-Cy42vswI.js → SettingsModal-Dmz2aH3c.js} +1 -1
  24. package/dist/client/assets/{SetupWizardModal-LqloAL4J.js → SetupWizardModal-BiIFP3De.js} +1 -1
  25. package/dist/client/assets/{SkillsView-I1SDKaRz.js → SkillsView-CRARYL_G.js} +1 -1
  26. package/dist/client/assets/{StashRecoveryView-DMUUR3cy.js → StashRecoveryView-DHj0O6sE.js} +1 -1
  27. package/dist/client/assets/{TodoView-PKvJKjtV.js → TodoView-CjyU1h-B.js} +1 -1
  28. package/dist/client/assets/{dashboard-view-D4XVI1XP.js → dashboard-view-BVckVLAO.js} +1 -1
  29. package/dist/client/assets/{folder-open-Doam5g-y.js → folder-open-CJgBSqdA.js} +1 -1
  30. package/dist/client/assets/index-BonLYFW-.js +742 -0
  31. package/dist/client/assets/{index-ktpD_W3I.css → index-nzIVQsA_.css} +1 -1
  32. package/dist/client/assets/{upload-BUfrZl69.js → upload-hsiV4Ixv.js} +1 -1
  33. package/dist/client/assets/{users-XNGnYBJb.js → users-D63HpHlZ.js} +1 -1
  34. package/dist/client/index.html +2 -2
  35. package/dist/client/version.json +1 -1
  36. package/dist/droid-cli/package.json +1 -1
  37. package/dist/extension.js +3073 -785
  38. package/dist/pi-claude-cli/package.json +1 -1
  39. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  40. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  41. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  42. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +38 -4
  43. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  44. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  45. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  46. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  47. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  48. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  49. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  50. package/package.json +1 -1
  51. package/skill/fusion/SKILL.md +1 -1
  52. package/skill/fusion/references/extension-tools.md +47 -1
  53. package/skill/fusion/references/fusion-capabilities.md +6 -1
  54. package/dist/client/assets/ChatView-DDDjYRKc.js +0 -6
  55. package/dist/client/assets/GoalsView-CI3Bzs1b.js +0 -1
  56. package/dist/client/assets/SettingsModal-CLEkhLK_.js +0 -31
  57. package/dist/client/assets/SettingsModal-D_uIvf6n.css +0 -1
  58. package/dist/client/assets/index-BS-jSWPW.js +0 -742
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion/pi-claude-cli",
3
- "version": "0.38.1",
3
+ "version": "0.39.0",
4
4
  "description": "Fusion vendored fork: pi coding-agent extension that routes LLM calls through the Claude Code CLI. Forked from rchern/pi-claude-cli (MIT). See UPSTREAM.md.",
5
5
  "license": "MIT",
6
6
  "private": true,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/cli-printing-press",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "description": "CLI Printing Press plugin package for Fusion",
6
6
  "private": true,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/cursor-runtime",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/dependency-graph",
3
- "version": "0.1.30",
3
+ "version": "0.1.31",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -137081,6 +137081,20 @@ function mapStopReason5(reason) {
137081
137081
  return "stop";
137082
137082
  }
137083
137083
  }
137084
+ function normalizeStreamingDelta(previousText, nextDelta) {
137085
+ if (!previousText || !nextDelta) {
137086
+ return nextDelta;
137087
+ }
137088
+ const previousChar = previousText.slice(-1);
137089
+ const nextChar = nextDelta[0] ?? "";
137090
+ if (/\s/.test(previousChar) || /\s/.test(nextChar)) {
137091
+ return nextDelta;
137092
+ }
137093
+ if (/[.!?]/.test(previousChar) && /[A-Z0-9"'([]/.test(nextChar)) {
137094
+ return ` ${nextDelta}`;
137095
+ }
137096
+ return nextDelta;
137097
+ }
137084
137098
  function createEventBridge(stream2, model) {
137085
137099
  const blocks = [];
137086
137100
  const output = {
@@ -137101,6 +137115,18 @@ function createEventBridge(stream2, model) {
137101
137115
  timestamp: Date.now()
137102
137116
  };
137103
137117
  let started = false;
137118
+ function getPreviousContentText(contentIndex, type) {
137119
+ for (let i2 = contentIndex - 1; i2 >= 0; i2--) {
137120
+ const contentBlock = output.content[i2];
137121
+ if (type === "text" && contentBlock?.type === "text") {
137122
+ return contentBlock.text;
137123
+ }
137124
+ if (type === "thinking" && contentBlock?.type === "thinking") {
137125
+ return contentBlock.thinking;
137126
+ }
137127
+ }
137128
+ return "";
137129
+ }
137104
137130
  function handleEvent(event) {
137105
137131
  if (!started) {
137106
137132
  stream2.push({ type: "start", partial: output });
@@ -137207,13 +137233,17 @@ function createEventBridge(stream2, model) {
137207
137233
  if (idx === -1) return;
137208
137234
  const block = blocks[idx];
137209
137235
  if (block.type === "text") {
137210
- block.text += event.delta.text;
137236
+ const delta = normalizeStreamingDelta(
137237
+ block.text || getPreviousContentText(idx, "text"),
137238
+ event.delta.text
137239
+ );
137240
+ block.text += delta;
137211
137241
  const contentBlock = output.content[idx];
137212
137242
  contentBlock.text = block.text;
137213
137243
  stream2.push({
137214
137244
  type: "text_delta",
137215
137245
  contentIndex: idx,
137216
- delta: event.delta.text,
137246
+ delta,
137217
137247
  partial: output
137218
137248
  });
137219
137249
  }
@@ -137222,13 +137252,17 @@ function createEventBridge(stream2, model) {
137222
137252
  if (idx === -1) return;
137223
137253
  const block = blocks[idx];
137224
137254
  if (block.type === "thinking") {
137225
- block.text += event.delta.thinking;
137255
+ const delta = normalizeStreamingDelta(
137256
+ block.text || getPreviousContentText(idx, "thinking"),
137257
+ event.delta.thinking
137258
+ );
137259
+ block.text += delta;
137226
137260
  const contentBlock = output.content[idx];
137227
137261
  contentBlock.thinking = block.text;
137228
137262
  stream2.push({
137229
137263
  type: "thinking_delta",
137230
137264
  contentIndex: idx,
137231
- delta: event.delta.thinking,
137265
+ delta,
137232
137266
  partial: output
137233
137267
  });
137234
137268
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/droid-runtime",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/hermes-runtime",
3
- "version": "0.2.49",
3
+ "version": "0.2.50",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/openclaw-runtime",
3
- "version": "0.2.49",
3
+ "version": "0.2.50",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/paperclip-runtime",
3
- "version": "0.2.49",
3
+ "version": "0.2.50",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/reports",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "description": "Reports plugin for Fusion",
6
6
  "private": true,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/roadmap",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/whatsapp-chat",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "description": "WhatsApp Web (Baileys) chat bridge for Fusion agents",
6
6
  "keywords": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runfusion/fusion",
3
- "version": "0.38.1",
3
+ "version": "0.39.0",
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",
@@ -29,7 +29,7 @@ Mission → Milestone → Slice → Feature → Task
29
29
  <!-- BEGIN: tool-categories (auto-generated by scripts/sync-fusion-skill-tools.mjs — do not edit by hand) -->
30
30
  - **Task tools** — `fn_task_create`, `fn_task_update`, `fn_task_list`, `fn_task_show`, `fn_task_attach`, `fn_task_pause`, `fn_task_unpause`, `fn_task_retry`, `fn_task_duplicate`, `fn_task_refine`, `fn_task_archive`, `fn_task_unarchive`, `fn_task_delete`, `fn_task_plan`
31
31
  - **GitHub tools** — `fn_task_import_github`, `fn_task_import_github_issue`, `fn_task_browse_github_issues`
32
- - **Mission tools** — `fn_mission_create`, `fn_mission_list`, `fn_mission_show`, `fn_mission_delete`, `fn_milestone_add`, `fn_slice_add`, `fn_feature_add`, `fn_slice_activate`, `fn_feature_link_task`, `fn_feature_update`, `fn_milestone_update`
32
+ - **Mission tools** — `fn_mission_create`, `fn_mission_list`, `fn_mission_show`, `fn_mission_backfill_assertions`, `fn_mission_delete`, `fn_mission_update`, `fn_milestone_add`, `fn_slice_add`, `fn_feature_add`, `fn_feature_delete`, `fn_slice_delete`, `fn_milestone_delete`, `fn_slice_activate`, `fn_feature_link_task`, `fn_feature_update`, `fn_milestone_update`
33
33
  - **Goal tools** — `fn_goal_list`, `fn_goal_create`, `fn_goal_archive`, `fn_goal_show`
34
34
  - **Agent tools** — `fn_agent_stop`, `fn_agent_start`, `fn_agent_create`, `fn_agent_delete`, `fn_list_agents`, `fn_delegate_task`, `fn_agent_show`, `fn_agent_org_chart`
35
35
  - **Skills tools** — `fn_skills_search`, `fn_skills_install`
@@ -196,6 +196,15 @@ Show mission details with full hierarchy: milestones → slices → features.
196
196
  |-----------|------|----------|-------------|
197
197
  | `id` | string | ✓ | Mission ID (e.g., M-001) |
198
198
 
199
+ ### fn_mission_backfill_assertions
200
+
201
+ Backfill mission assertions by deriving and linking one store-managed assertion for each feature without linked assertions. Supports dry-run mode.
202
+
203
+ | Parameter | Type | Required | Description |
204
+ |-----------|------|----------|-------------|
205
+ | `missionId` | string | — | Mission ID to scope backfill to (e.g., M-001) |
206
+ | `dryRun` | boolean | — | When true, preview repairs without writing changes (default: true) |
207
+
199
208
  ### fn_mission_delete
200
209
 
201
210
  Delete a mission and all its milestones, slices, and features. Cannot be undone.
@@ -204,6 +213,16 @@ Delete a mission and all its milestones, slices, and features. Cannot be undone.
204
213
  |-----------|------|----------|-------------|
205
214
  | `id` | string | ✓ | Mission ID to delete (e.g., M-001) |
206
215
 
216
+ ### fn_mission_update
217
+
218
+ Update an existing mission's title or description. Partial patches leave untouched fields intact.
219
+
220
+ | Parameter | Type | Required | Description |
221
+ |-----------|------|----------|-------------|
222
+ | `id` | string | ✓ | Mission ID to update (e.g., M-001) |
223
+ | `title` | string | — | Updated mission title |
224
+ | `description` | string | — | Updated mission description |
225
+
207
226
  ### fn_milestone_add
208
227
 
209
228
  Add a milestone to a mission. Milestones represent phases of work.
@@ -235,6 +254,33 @@ Add a feature to a slice. Features are deliverables that can be linked to tasks.
235
254
  | `description` | string | — | Feature description |
236
255
  | `acceptanceCriteria` | string | — | Acceptance criteria for completing the feature |
237
256
 
257
+ ### fn_feature_delete
258
+
259
+ Delete a feature. Rejects deletion when linked to a live task unless force=true.
260
+
261
+ | Parameter | Type | Required | Description |
262
+ |-----------|------|----------|-------------|
263
+ | `featureId` | string | ✓ | Feature ID to delete (e.g., F-001) |
264
+ | `force` | boolean | — | Override linked-task guard |
265
+
266
+ ### fn_slice_delete
267
+
268
+ Delete a slice and its features. Rejects deletion when child features link to live tasks unless force=true.
269
+
270
+ | Parameter | Type | Required | Description |
271
+ |-----------|------|----------|-------------|
272
+ | `sliceId` | string | ✓ | Slice ID to delete (e.g., SL-001) |
273
+ | `force` | boolean | — | Override linked-task guard |
274
+
275
+ ### fn_milestone_delete
276
+
277
+ Delete a milestone and all descendant slices/features. Rejects deletion when child features link to live tasks unless force=true.
278
+
279
+ | Parameter | Type | Required | Description |
280
+ |-----------|------|----------|-------------|
281
+ | `milestoneId` | string | ✓ | Milestone ID to delete (e.g., MS-001) |
282
+ | `force` | boolean | — | Override linked-task guard |
283
+
238
284
  ### fn_slice_activate
239
285
 
240
286
  Activate a pending slice for implementation. Sets status to 'active' and enables task linking for its features.
@@ -245,7 +291,7 @@ Activate a pending slice for implementation. Sets status to 'active' and enables
245
291
 
246
292
  ### fn_feature_link_task
247
293
 
248
- Link a feature to a fn task for implementation. Updates the feature status to 'triaged' and associates it with the task.
294
+ Link a feature to a fn task for implementation. Updates the feature status to 'triaged' and associates it with the task. If the target task is not on the active board (for example archived, deleted, or never created), the tool returns a clear validation error indicating that only active tasks can be linked.
249
295
 
250
296
  | Parameter | Type | Required | Description |
251
297
  |-----------|------|----------|-------------|
@@ -48,12 +48,17 @@ All skill/extension tool invocations in this catalog use the public `fn_*` names
48
48
  | `fn_goal_archive` | Archive a goal by ID. |
49
49
  | `fn_goal_show` | Show full details for a single goal by ID. |
50
50
  | `fn_mission_show` | Show mission details with full hierarchy: milestones → slices → features. |
51
+ | `fn_mission_backfill_assertions` | Backfill mission assertions by deriving and linking one store-managed assertion for each feature without linked assertions. Supports dry-run mode. |
51
52
  | `fn_mission_delete` | Delete a mission and all its milestones, slices, and features. Cannot be undone. |
53
+ | `fn_mission_update` | Update an existing mission's title or description. Partial patches leave untouched fields intact. |
52
54
  | `fn_milestone_add` | Add a milestone to a mission. Milestones represent phases of work. |
53
55
  | `fn_slice_add` | Add a slice to a milestone. Slices are work units that can be activated for implementation. |
54
56
  | `fn_feature_add` | Add a feature to a slice. Features are deliverables that can be linked to tasks. |
57
+ | `fn_feature_delete` | Delete a feature. Rejects deletion when linked to a live task unless force=true. |
58
+ | `fn_slice_delete` | Delete a slice and its features. Rejects deletion when child features link to live tasks unless force=true. |
59
+ | `fn_milestone_delete` | Delete a milestone and all descendant slices/features. Rejects deletion when child features link to live tasks unless force=true. |
55
60
  | `fn_slice_activate` | Activate a pending slice for implementation. Sets status to 'active' and enables task linking for its features. |
56
- | `fn_feature_link_task` | Link a feature to a fn task for implementation. Updates the feature status to 'triaged' and associates it with the task. |
61
+ | `fn_feature_link_task` | Link a feature to a fn task for implementation. Updates the feature status to 'triaged' and associates it with the task. If the target task is not on the active board (for example archived, deleted, or never created), the tool returns a clear validation error indicating that only active tasks can be linked. |
57
62
  | `fn_feature_update` | Update an existing feature's title, description, or acceptance criteria. Partial patches leave untouched fields intact. |
58
63
  | `fn_milestone_update` | Update an existing milestone's title, description, or acceptance criteria (the structured pass/fail bar, distinct from verification's free-form how-to-confirm notes). Partial patches leave untouched fields intact. |
59
64
  | `fn_agent_stop` | Stop a running agent — pauses its execution. Transitions the agent from running/active to paused state. |
@@ -1,6 +0,0 @@
1
- import{r as s,a as wn,j as t,R as Sn}from"./vendor-react-K0fH_qHe.js";import{c as Cn,a9 as Ts,a7 as Is,bd as $s,be as ls,aG as At,bf as Ds,ac as Ps,bg as ts,t as kn,bh as Nn,bi as Ls,bj as jn,bk as ss,w as Mn,bl as Rn,bm as An,bn as En,bo as Tn,bp as In,bq as $n,br as Dn,s as Pn,bs as Ln,j as Fn,k as Qs,bt as _n,bu as zn,bv as Zs,bw as Hn,bx as Un,by as On,p as Bn,bz as Kn,bA as Gn,u as Wn,bB as Vn,ah as en,ai as tn,bC as qn,bD as Xn,S as Yn,_ as ns,P as dt,J as lt,aw as Jn,bE as Fs,a as Nt,bF as _s,bG as zs,bH as Hs,B as ut,ae as Qn,af as Zn,b2 as Et,bI as ea,bJ as ta,a$ as sa,bK as Us,bL as na,T as aa,bM as Os,bN as ra,au as Bs,m as ia}from"./index-BS-jSWPW.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.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 oa=[["path",{d:"M5 3h14",key:"7usisc"}],["path",{d:"m18 13-6-6-6 6",key:"1kf1n9"}],["path",{d:"M12 7v14",key:"1akyts"}]],ca=Cn("arrow-up-to-line",oa),as="kb-chat-active-session";function Ks(n){const r=typeof n=="string"?n.trim():"",d=r.indexOf("/");return!r||d<=0||d>=r.length-1?{}:{modelProvider:r.slice(0,d),modelId:r.slice(d+1)}}function la(n){const r=n?.toolCalls;if(!Array.isArray(r))return;const d=r.map(i=>{if(!i||typeof i!="object")return null;const g=i,b=typeof g.toolName=="string"?g.toolName:"";if(!b)return null;const y=g.args;return{toolName:b,...y&&typeof y=="object"?{args:y}:{},isError:!!g.isError,result:g.result,status:"completed"}}).filter(i=>i!==null);return d.length>0?d:void 0}function da(n){const r=n?.fallback;if(!r||typeof r!="object")return;const d=r,i=typeof d.primaryModel=="string"?d.primaryModel:"",g=typeof d.fallbackModel=="string"?d.fallbackModel:"",b=d.triggerPoint;if(!(!i||!g||b!=="session-creation"&&b!=="prompt-time"))return{primaryModel:i,fallbackModel:g,triggerPoint:b}}function ua(n){const r=n?.failureInfo;if(!r||typeof r!="object")return;const d=r,i=typeof d.summary=="string"?d.summary.trim():"";if(!i)return;const g=(()=>{const b=d.reference;if(!b||typeof b!="object")return;const y=b,f=typeof y.kind=="string"?y.kind.trim():"",I=typeof y.id=="string"?y.id.trim():"";if(!(!f||!I))return{kind:f,id:I,...typeof y.label=="string"&&y.label.trim()?{label:y.label.trim()}:{}}})();return{summary:i,...typeof d.errorClass=="string"&&d.errorClass.trim()?{errorClass:d.errorClass.trim()}:{},...typeof d.code=="string"&&d.code.trim()?{code:d.code.trim()}:{},...typeof d.detail=="string"&&d.detail.trim()?{detail:d.detail.trim()}:{},...g?{reference:g}:{}}}function Gs(n){return typeof n=="string"?{summary:n.trim()||"Failed to get response"}:{summary:typeof n.summary=="string"&&n.summary.trim()?n.summary.trim():"Failed to get response",...typeof n.errorClass=="string"&&n.errorClass.trim()?{errorClass:n.errorClass.trim()}:{},...typeof n.code=="string"&&n.code.trim()?{code:n.code.trim()}:{},...typeof n.detail=="string"&&n.detail.trim()?{detail:n.detail.trim()}:{},...n.reference?{reference:n.reference}:{}}}function rs(n){return{id:n.id,sessionId:n.sessionId,role:n.role,content:n.content,thinkingOutput:n.thinkingOutput,toolCalls:la(n.metadata),fallbackInfo:da(n.metadata),failureInfo:ua(n.metadata),attachments:n.attachments,createdAt:n.createdAt}}function ma(n,r){const d=s.useCallback(l=>l?`${Ts.CHAT_SESSIONS_PREFIX}${l}`:null,[]),i=s.useCallback((l,u)=>l&&u?`${Ts.CHAT_MESSAGES_PREFIX}${l}:${u}`:null,[]),g=s.useCallback(l=>{const u=d(l);return u?Is(u,{maxAgeMs:$s})??[]:[]},[d]),[b,y]=s.useState(()=>g(n)),[f,I]=s.useState(null),[J,Q]=s.useState(()=>g(n).length===0),[w,j]=s.useState([]),[z,S]=s.useState(!1),[Z,C]=s.useState(!1),[O,N]=s.useState(""),[X,E]=s.useState(""),[_,T]=s.useState([]),[Y,k]=s.useState(""),[B,te]=s.useState(""),[h,p]=s.useState(!1),{agentsMap:he}=ls(n),c=s.useRef(null),re=s.useRef(null),se=s.useRef(!1),$=s.useRef(""),ue=s.useRef(null),be=s.useRef(b),G=s.useRef(f),Ge=s.useRef(w),K=s.useRef(Z);be.current=b,G.current=f,Ge.current=w,K.current=Z,s.useEffect(()=>{$.current=Y},[Y]);const We=s.useRef(new Set),ye=s.useRef(0),Ie=s.useRef(n);Ie.current!==n&&(At({view:"useChat",trigger:"project-context-change",projectId:n,replayAttempted:!1,detail:{previousProjectId:Ie.current??null}}),Ie.current=n,ye.current++);const oe=s.useCallback(async()=>{be.current.length===0&&Q(!0);try{const u=[...(await Ds(n)).sessions].sort((D,H)=>new Date(H.updatedAt).getTime()-new Date(D.updatedAt).getTime());y(u);const v=d(n);v&&Ps(v,u,{maxBytes:5e5})}catch{const l=g(n);if(be.current.length===0&&l.length===0){const u=d(n);u&&ts(u)}}finally{Q(!1)}},[d,n]);s.useEffect(()=>{const l=g(n);y(l),Q(l.length===0)},[n,g]),s.useEffect(()=>{oe()},[oe,n]);const Se=s.useRef(()=>{}),Ce=s.useRef(!1);s.useEffect(()=>{Ce.current=!1,re.current=null},[n]),s.useEffect(()=>{if(J||Ce.current||G.current)return;const l=kn(as,n);if(!l){Ce.current=!0;return}const u=b.find(v=>v.id===l);if(u){Ce.current=!0,Se.current(l,u);return}Ce.current=!0},[J,b,n]);const Ve=s.useCallback((l,u)=>{const v=i(l,u);return v?Is(v,{maxAgeMs:$s})??[]:[]},[i]),Oe=s.useCallback(l=>{const u=Ve(n,l);return u.length>0?(j(u),S(!1),!0):(j([]),!1)},[n,Ve]),ce=s.useCallback(async(l,u)=>{const v=typeof u?.offset=="number"&&u.offset>0||typeof u?.before=="string",D=i(n,l),H=v?[]:Ve(n,l),A=H.length>0;!v&&A?(j(H),S(!1)):S(!0);try{const ee=await Nn(l,{limit:50,order:"desc",...u},n),M=ee.messages.slice().reverse().map(rs);v?G.current?.id===l&&(j(U=>[...M,...U]),p(ee.messages.length>=50)):G.current?.id===l&&(j(M),p(ee.messages.length>=50),D&&Ps(D,M,{maxBytes:5e5}))}catch{!v&&Ge.current.length===0&&A&&(j(H),S(!1))}finally{S(!1)}},[i,n,Ve]),me=s.useCallback(()=>{ue.current?.(),ue.current=null,$.current="",k(""),N(""),E(""),T([]),C(!1)},[]),mt=s.useCallback(()=>{$.current="",k("")},[]),ie=s.useCallback(()=>{const l=$.current.trim();l&&($.current="",k(""),Be.current(l))},[]),le=s.useCallback((l,u,v)=>{if(c.current||!l)return!0;se.current=!1,u&&(N(u.streamingText),E(u.streamingThinking),T(u.toolCalls)),C(!0);const{handlers:D}=Ls({sessionId:l,tempUserMessageId:"",setStreamingText:N,setStreamingThinking:E,setStreamingToolCalls:T,cancelStreamingFlushesRef:ue,addToast:v?.silent?void 0:r,onFallbackSession:(A,ee)=>{const M=Ks(A.fallbackModel);y(U=>U.map(W=>W.id===ee?{...W,...M}:W)),I(U=>U&&U.id===ee?{...U,...M}:U)},onDone:()=>{N(""),E(""),T([]),C(!1),K.current=!1,c.current=null,re.current=null,ce(l),ie()},onError:A=>{N(""),E(""),T([]),C(!1),K.current=!1,c.current=null,re.current=null;const ee=Gs(A);v?.silent||r?.(ee.summary,"error"),ce(l),ie()}});At({view:"useChat",trigger:"sse-open",projectId:n,replayAttempted:typeof u?.replayFromEventId=="number",replayFromEventId:u?.replayFromEventId??null,lastEventId:u?.replayFromEventId??null});const H=jn(l,D,n,{...typeof u?.replayFromEventId=="number"?{lastEventId:u.replayFromEventId}:{}});return c.current=H,re.current={sessionId:l,replayFromEventId:typeof u?.replayFromEventId=="number"?u.replayFromEventId:null},!0},[r,ce,n,ie]),$e=s.useCallback((l,u)=>{const v=G.current?.id??null;if(l&&v===l&&!u)return;c.current&&(c.current.close(),c.current=null),re.current=null;const D=u??b.find(H=>H.id===l);I(D||null),l&&ss(l,n).then(({session:H})=>{!H.isGenerating||!H.inFlightGeneration||I(A=>!A||A.id!==l?A:{...A,...H})}).catch(()=>{}),me(),p(!1),l?(Oe(l),ce(l)):j([]),D?.isGenerating&&le(D.id,D.inFlightGeneration),l?Mn(as,l,n):Rn(as,n)},[le,Oe,b,ce,n,me]);Se.current=$e;const Tt=s.useCallback(async l=>{const u=await An(l,n);c.current&&(c.current.close(),c.current=null),re.current=null;const v={id:u.session.id,title:u.session.title,agentId:u.session.agentId,status:u.session.status,modelProvider:u.session.modelProvider,modelId:u.session.modelId,createdAt:u.session.createdAt,updatedAt:u.session.updatedAt};return y(D=>D.some(H=>H.id===v.id)?D:[v,...D]),me(),$e(v.id,v),v},[n,me,$e]),De=s.useCallback(async l=>{await En(l,{status:"archived"},n),y(u=>u.filter(v=>v.id!==l)),f?.id===l&&(re.current=null,I(null),j([]))},[f,n]),Pe=s.useCallback(async l=>{f?.id===l&&c.current&&(c.current.close(),c.current=null),f?.id===l&&(re.current=null),await Tn(l,n);const u=i(n,l);u&&ts(u),y(v=>v.filter(D=>D.id!==l)),f?.id===l&&(I(null),j([]))},[f,i,n]),nt=s.useCallback(async()=>{if(!f||!h)return;const l=Ge.current[0]?.createdAt;l&&await ce(f.id,{before:l})},[f,h,ce]),qe=s.useCallback(()=>{f&&(se.current=!0,ue.current?.(),ue.current=null,c.current?.close(),c.current=null,re.current=null,In(f.id,n).catch(()=>{}),C(!1),K.current=!1,N(""),E(""),T([]),ie())},[f,n,ie]),Be=s.useRef(()=>{}),Le=$n(),ke=s.useCallback(async l=>{try{await oe();const u=await ss(l,n);G.current?.id===l&&I(v=>!v||v.id!==l?v:{...v,...u.session}),u.session.isGenerating?(N(""),E(""),T([]),C(!0),K.current=!0,le(l,u.session.inFlightGeneration,{silent:!0})):(N(""),E(""),T([]),C(!1),K.current=!1,await ce(l))}catch{}},[le,ce,n,oe]),Ne=s.useCallback((l,u)=>{if(!f)return;if(K.current){$.current=l,k(l);return}se.current=!1,c.current&&(c.current.close(),c.current=null),re.current=null;const v=`temp-${Date.now()}`,D={id:v,sessionId:f.id,role:"user",content:l,createdAt:new Date().toISOString()};j(A=>[...A,D]),N(""),E(""),T([]),C(!0);const{handlers:H}=Ls({sessionId:f.id,tempUserMessageId:v,setStreamingText:N,setStreamingThinking:E,setStreamingToolCalls:T,cancelStreamingFlushesRef:ue,addToast:r,onFallbackSession:(A,ee)=>{const M=Ks(A.fallbackModel);y(U=>U.map(W=>W.id===ee?{...W,...M}:W)),I(U=>U&&U.id===ee?{...U,...M}:U)},onDone:({messageId:A,message:ee,accumulated:M})=>{const U=ee?{...rs(ee),...M.text.length>0?{content:M.text}:{}}:{id:A||`msg-${Date.now()}`,sessionId:f.id,role:"assistant",content:M.text,thinkingOutput:M.thinking,toolCalls:M.toolCalls.length>0?M.toolCalls:void 0,fallbackInfo:M.fallbackInfo,createdAt:new Date().toISOString()};We.current.add(U.id),j(W=>[...W,U]),N(""),E(""),T([]),C(!1),K.current=!1,c.current=null,re.current=null,setTimeout(()=>{We.current.delete(U.id)},1e3),oe(),ie()},onError:(A,ee)=>{const M=Gs(A),U=typeof A=="string"?A:M.summary,W=Ln(U);j(V=>{const P=V.filter(q=>q.id!==ee);return W?P:[...P,{id:`error-${Date.now()}`,sessionId:f.id,role:"assistant",content:M.summary,failureInfo:M,createdAt:new Date().toISOString()}]}),N(""),E(""),T([]),C(!1),K.current=!1,c.current=null,re.current=null,console.error("[useChat] Stream error:",A),W?(console.info("[useChat] Suppressed tab-suspension stream error:",A),f?.id&&(N(""),E(""),T([]),C(!0),K.current=!0,ke(f.id))):(r?.(M.summary,"error"),oe()),se.current||ie()}});c.current=Dn(f.id,l,H,u,n)},[f,n,oe,r,le,ke,ie]);Be.current=Ne;const ve=B?b.filter(l=>l.title?.toLowerCase().includes(B.toLowerCase())||l.agentId.toLowerCase().includes(B.toLowerCase())):b;return s.useEffect(()=>{if(!f?.id||f.isGenerating!==!0||c.current)return;const l=typeof f.inFlightGeneration?.replayFromEventId=="number"?f.inFlightGeneration.replayFromEventId:null,u=re.current;u?.sessionId===f.id&&u.replayFromEventId===l||le(f.id,f.inFlightGeneration,{silent:!0})},[f?.id,f?.isGenerating,f?.inFlightGeneration,le]),s.useEffect(()=>{if(!G.current?.isGenerating||(c.current||le(G.current.id,G.current.inFlightGeneration),!K.current||c.current||!G.current))return;const l=setInterval(async()=>{if(!K.current||c.current||!G.current){clearInterval(l);return}try{(await Ds(n)).sessions.find(D=>D.id===G.current?.id)?.isGenerating||(clearInterval(l),await ce(G.current.id),N(""),E(""),T([]),C(!1),K.current=!1,ie())}catch{}},3e3);return()=>clearInterval(l)},[le,ce,n,f,ie]),s.useEffect(()=>Le.onBecameVisible(()=>{const u=G.current;if(!u||c.current)return;const v=ye.current;ss(u.id,n).then(D=>{if(!(ye.current!==v||c.current)){if(D.session.isGenerating){N(""),E(""),T([]),C(!0),K.current=!0,le(u.id,D.session.inFlightGeneration,{silent:!0});return}K.current&&(N(""),E(""),T([]),C(!1),K.current=!1,ie(),ce(u.id))}}).catch(()=>{})}),[le,ce,n,Le,ie]),s.useEffect(()=>{const l=ye.current,u=n?`?projectId=${encodeURIComponent(n)}`:"",v=()=>ye.current!==l,D=W=>{if(v())return;const V=JSON.parse(W.data);y(P=>P.some(q=>q.id===V.id)?P:[V,...P])},H=W=>{if(v())return;const V=JSON.parse(W.data);y(P=>[...P.map(ne=>ne.id===V.id?V:ne)]),G.current?.id===V.id&&(I(V),V.isGenerating&&!c.current&&le(V.id,V.inFlightGeneration))},A=W=>{if(v())return;const{id:V}=JSON.parse(W.data);y(q=>q.filter(ne=>ne.id!==V));const P=i(n,V);P&&ts(P),G.current?.id===V&&(I(null),j([]))},ee=W=>{if(v())return;const V=JSON.parse(W.data),P=rs(V);if(!We.current.has(P.id)){if(G.current?.id===P.sessionId&&K.current&&!c.current&&P.role==="assistant"){j(q=>q.some(ne=>ne.id===P.id)?q:[...q,P]),N(""),E(""),T([]),C(!1),K.current=!1,ie();return}G.current?.id===P.sessionId&&!K.current&&j(q=>{if(q.some(ne=>ne.id===P.id))return q;if(P.role==="user"){const ne=q.findIndex(je=>je.role==="user"&&je.id.startsWith("temp-")&&je.content.trim()===P.content.trim());if(ne>=0){const je=[...q];return je[ne]=P,je}}return[...q,P]})}},M=W=>{if(v())return;const{id:V}=JSON.parse(W.data);j(P=>P.filter(q=>q.id!==V))};return Pn(`/api/events${u}`,{events:{"chat:session:created":D,"chat:session:updated":H,"chat:session:deleted":A,"chat:message:added":ee,"chat:message:deleted":M}})},[le,i,n,ie]),s.useEffect(()=>()=>{c.current&&(c.current.close(),c.current=null),re.current=null},[]),{sessions:b,activeSession:f,sessionsLoading:J,messages:w,messagesLoading:z,isStreaming:Z,streamingText:O,streamingThinking:X,streamingToolCalls:_,pendingMessage:Y,selectSession:$e,createSession:Tt,archiveSession:De,deleteSession:Pe,sendMessage:Ne,stopStreaming:qe,clearPendingMessage:mt,loadMoreMessages:nt,hasMoreMessages:h,searchQuery:B,setSearchQuery:te,filteredSessions:ve,refreshSessions:oe,agentsMap:he}}function ha(n,r=[]){const d=n.trim().replace(/^#/,"");if(!d)return{ok:!1,error:"Room name is required."};if(/[A-Z]/.test(d))return{ok:!1,error:"Use lowercase letters only."};const i=d.toLowerCase();return i.length>80?{ok:!1,error:"Room names can be at most 80 characters."}:/^[a-z0-9_-]+$/.test(i)?/^[-_]|[-_]$/.test(i)?{ok:!1,error:"Room names cannot start or end with a hyphen or underscore."}:r.some(g=>g.toLowerCase()===i)?{ok:!1,error:"A room with this name already exists."}:{ok:!0,name:i}:{ok:!1,error:"Use lowercase letters, numbers, hyphens, or underscores only."}}function fa({isOpen:n,onClose:r,onCreate:d,projectId:i,existingRoomNames:g=[]}){const[b,y]=s.useState(""),[f,I]=s.useState([]),[J,Q]=s.useState(""),[w,j]=s.useState([]),[z,S]=s.useState(!1),[Z,C]=s.useState(null),[O,N]=s.useState(!1),X=s.useRef(null),E=s.useRef(null);s.useEffect(()=>{n&&(E.current=document.activeElement instanceof HTMLElement?document.activeElement:null,S(!0),C(null),Fn(void 0,i).then(h=>I(h)).catch(()=>{I([]),C("Failed to load agents.")}).finally(()=>S(!1)))},[n,i]),s.useEffect(()=>{if(!n){y(""),Q(""),j([]),C(null),N(!1);return}const h=window.requestAnimationFrame(()=>X.current?.focus());return()=>window.cancelAnimationFrame(h)},[n]),s.useEffect(()=>{if(!n)return;const h=p=>{p.key==="Escape"&&r()};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[n,r]),s.useEffect(()=>{n||E.current?.focus()},[n]);const _=s.useMemo(()=>ha(b,g),[b,g]),T=s.useMemo(()=>{const h=J.trim().toLowerCase();return h?f.filter(p=>p.name.toLowerCase().includes(h)):f},[f,J]),Y=s.useMemo(()=>f.filter(h=>w.includes(h.id)),[f,w]),k=_.ok&&w.length>0&&!O&&!z;if(!n)return null;const B=h=>{O||j(p=>p.includes(h)?p.filter(he=>he!==h):[...p,h])},te=async()=>{if(!_.ok){C(_.error);return}if(w.length===0){C("Select at least one member.");return}C(null),N(!0);try{await d({name:_.name,displayName:`#${_.name}`,memberAgentIds:w}),r()}catch(h){C(h instanceof Error?h.message:"Failed to create room.")}finally{N(!1)}};return wn.createPortal(t.jsx("div",{className:"modal-overlay open",onClick:h=>h.target===h.currentTarget&&r(),children:t.jsxs("div",{className:"modal modal-lg create-room-modal",role:"dialog","aria-modal":"true","aria-label":"Create room",onClick:h=>h.stopPropagation(),children:[t.jsxs("div",{className:"modal-header",children:[t.jsx("h3",{children:"Create room"}),t.jsx("button",{type:"button",className:"modal-close","aria-label":"Close",onClick:r,children:"×"})]}),t.jsxs("div",{className:"form-group create-room-modal-name-group",children:[t.jsx("label",{htmlFor:"create-room-name",children:"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:X,id:"create-room-name",className:"input",value:b,disabled:O,onChange:h=>{const p=h.target.value.replace(/^#/,"").replace(/\s+/g,"-").toLowerCase();y(p)}})]}),!_.ok&&t.jsx("div",{className:"form-error",children:_.error})]}),t.jsxs("div",{className:"form-group",children:[t.jsx("label",{htmlFor:"create-room-member-search",children:"Members"}),t.jsx("input",{id:"create-room-member-search",className:"input",placeholder:"Search agents",value:J,disabled:O,onChange:h=>Q(h.target.value)})]}),Y.length>0&&t.jsx("div",{className:"create-room-modal-selected","data-testid":"create-room-selected-chips",children:Y.map(h=>t.jsxs("button",{type:"button",className:"btn btn-sm create-room-modal-chip",onClick:()=>B(h.id),disabled:O,children:[h.name," ×"]},h.id))}),t.jsx("div",{className:"create-room-modal-member-list","data-testid":"create-room-member-list",children:z?t.jsx("div",{className:"create-room-modal-empty",children:"Loading agents..."}):T.length===0?t.jsx("div",{className:"create-room-modal-empty",children:f.length===0?"No agents in this project yet.":"No agents match your search."}):T.map(h=>{const p=w.includes(h.id);return t.jsxs("button",{type:"button",className:`create-room-modal-member-row${p?" create-room-modal-member-row--selected":""}`,onClick:()=>B(h.id),disabled:O,children:[t.jsx(Qs,{agent:h,size:20}),t.jsx("span",{children:h.name}),t.jsx("span",{className:"create-room-modal-member-role",children:h.role})]},h.id)})}),Z&&t.jsx("div",{className:"form-group",children:t.jsx("div",{className:"form-error",children:Z})}),t.jsxs("div",{className:"modal-actions",children:[t.jsx("button",{type:"button",className:"btn",onClick:r,disabled:O,children:"Cancel"}),t.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void te(),disabled:!k,children:O?"Creating...":"Create room"})]})]})}),document.body)}const sn=640;let is=!1;function ga(n){return n>sn?"auto":"hidden"}function pa(n){return Math.max(40,Math.min(n,sn))}function nn(n){const r=new Date(n),i=new Date().getTime()-r.getTime(),g=Math.floor(i/1e3),b=Math.floor(g/60),y=Math.floor(b/60),f=Math.floor(y/24);return g<60?"just now":b<60?`${b}m ago`:y<24?`${y}h ago`:f<7?`${f}d ago`:r.toLocaleDateString()}function Ws(n,r){if(!n||!r)return null;const d=r.toLowerCase();if(d.includes("claude")){let g=r.replace(/^claude[- ]/i,"Claude ").replace(/sonnet[- ](\d+)[- ](\d+)/i,"Sonnet $1.$2").replace(/sonnet[- ](\d+)/i,"Sonnet $1").replace(/haiku[- ](\d+)/i,"Haiku $1").replace(/opus[- ](\d+)/i,"Opus $1").replace(/sonnet/i,"Sonnet").replace(/haiku/i,"Haiku").replace(/opus/i,"Opus").replace(/-/g," ").trim();return g=g.replace(/\s+/g," "),g.length>30?g.slice(0,30)+"…":g}if(d.includes("gpt")||d.includes("openai")){const g=r.replace(/^gpt-4-turbo$/i,"GPT-4 Turbo").replace(/^gpt-4o-mini$/i,"GPT-4o Mini").replace(/^gpt-4o$/i,"GPT-4o").replace(/^gpt-4$/i,"GPT-4").replace(/^gpt-o1-preview$/i,"GPT-o1 Preview").replace(/^gpt-o1-mini$/i,"GPT-o1 Mini").replace(/^gpt-o1$/i,"GPT-o1").replace(/^gpt/i,"GPT").trim();return g.length>30?g.slice(0,30)+"…":g}if(d.includes("gemini")){const g=r.replace(/^gemini[- ]/i,"Gemini ").replace(/pro[- ](\d+)[- ](\d+)/i,"Pro $1.$2").replace(/pro[- ](\d+)/i,"Pro $1").replace(/-/g," ").replace(/\s+/g," ").trim();return g.length>30?g.slice(0,30)+"…":g}const i=r.replace(/-/g," ").replace(/^\w/,g=>g.toUpperCase()).replace(/\s+/g," ").trim();return i.length>30?i.slice(0,30)+"…":i}function Rt(n,r){return n.length<=r?n:`${n.slice(0,r)}…`}function ba(n){if(!n)return null;const r=Object.entries(n);return r.length===0?null:r.map(([d,i])=>{const g=typeof i=="string"?i:(()=>{try{return JSON.stringify(i)}catch{return String(i)}})();return`${d}=${Rt(g,50)}`}).join(", ")}function va(n){if(n===void 0)return null;if(typeof n=="string")return Rt(n,200);try{return Rt(JSON.stringify(n),200)}catch{return Rt(String(n),200)}}function xa(n){if(!n)return null;if(n.kind==="mailbox"||n.kind==="mailbox-message"){const r=typeof window>"u"?"/":window.location.pathname||"/",d=new URLSearchParams(typeof window>"u"?"":window.location.search);return d.set("view","mailbox"),d.set("mailbox-message",n.id),`${r}?${d.toString()}#message-${encodeURIComponent(n.id)}`}return null}function ya(n){if(!n)return null;const r=n.label??`${n.kind} ${n.id}`,d=xa(n),i=`chat-failure-reference-${n.kind}-${n.id}`.replace(/[^a-zA-Z0-9_-]+/g,"-").toLowerCase();return t.jsxs("div",{className:"chat-message-failure-reference",children:[t.jsx("span",{className:"chat-message-failure-reference-label",children:"Reference"}),t.jsx("span",{className:"chat-message-failure-reference-value",children:r}),d?t.jsx("a",{className:"btn btn-sm chat-message-failure-reference-link",href:d,children:"Open mailbox message"}):t.jsxs("details",{className:"chat-message-failure-reference-details",children:[t.jsx("summary",{className:"btn btn-sm chat-message-failure-reference-link",children:"View failure details"}),t.jsxs("dl",{className:"chat-message-failure-reference-meta",id:i,children:[t.jsxs("div",{children:[t.jsx("dt",{children:"Kind"}),t.jsx("dd",{children:n.kind})]}),t.jsxs("div",{children:[t.jsx("dt",{children:"ID"}),t.jsx("dd",{children:n.id})]}),n.label&&t.jsxs("div",{children:[t.jsx("dt",{children:"Label"}),t.jsx("dd",{children:n.label})]})]})]})]})}function an(n){if(!n||n.length===0)return null;const r=(w,j)=>{const z=w.status==="running",S=w.status==="completed"&&w.isError,Z=ba(w.args),C=va(w.result),O=z?Z:C?`result: ${C}`:Z?`args: ${Z}`:null,N=z?"running":S?"error":"completed";return t.jsxs("details",{className:`chat-tool-call${z?" chat-tool-call--running":""}${S?" chat-tool-call--error":""}`,open:z,children:[t.jsxs("summary",{children:[t.jsx("span",{className:"chat-tool-call-status-dot","aria-hidden":"true"}),t.jsx("span",{className:"chat-tool-call-name",title:w.toolName,children:w.toolName}),O&&t.jsx("span",{className:"chat-tool-call-preview",title:O,children:O}),t.jsx("span",{className:"chat-tool-call-status-text",children:N})]}),t.jsxs("div",{className:"chat-tool-call-content",children:[Z&&t.jsxs("div",{className:"chat-tool-call-row",children:[t.jsx("span",{className:"chat-tool-call-label",children:"args"}),t.jsx("span",{className:"chat-tool-call-value",children:Z})]}),C&&t.jsxs("div",{className:`chat-tool-call-row${S?" chat-tool-call-row--error":""}`,children:[t.jsx("span",{className:"chat-tool-call-label",children:"result"}),t.jsx("span",{className:"chat-tool-call-value",children:C})]})]})]},`${w.toolName}-${j}`)},d="chat-tool-calls";if(n.length===1)return t.jsxs("div",{className:d,"data-testid":"chat-tool-calls",children:[t.jsxs("div",{className:"chat-tool-calls-header",children:[t.jsx(Os,{size:12,"aria-hidden":"true"}),t.jsx("span",{children:"Tool calls"})]}),r(n[0],0)]});const i=n.filter(w=>w.status==="running").length,g=n.filter(w=>w.status==="completed"&&w.isError).length,b=i>0,y=Array.from(new Set(n.map(w=>w.toolName))),f=y.slice(0,5),I=Math.max(0,y.length-f.length),J=I>0?`${f.join(", ")}, +${I} more`:f.join(", "),Q=b?`(${i} running)`:g>0?`(${g} ${g===1?"error":"errors"})`:null;return t.jsx("div",{className:d,"data-testid":"chat-tool-calls",children:t.jsxs("details",{className:"chat-tool-calls-group","data-testid":"chat-tool-calls-group",open:b,children:[t.jsxs("summary",{className:"chat-tool-calls-group-summary",children:[t.jsx(Os,{size:12,"aria-hidden":"true"}),t.jsxs("span",{className:"chat-tool-calls-count",children:[n.length," tool calls"]}),t.jsx("span",{className:"chat-tool-calls-names",title:J,children:J}),Q&&t.jsx("span",{className:"chat-tool-calls-group-status",children:Q})]}),n.map((w,j)=>r(w,j))]})})}const rn={p:({children:n,...r})=>t.jsx("p",{...r,children:Us(n)}),li:({children:n,...r})=>t.jsx("li",{...r,children:Us(n)}),pre:({children:n,...r})=>t.jsx("pre",{...r,className:"chat-markdown-pre",children:n}),code:({children:n,...r})=>{const d=typeof n=="string"?n:Sn.Children.toArray(n).join(""),i=Et(d);return i.length===1&&typeof i[0]=="string"?t.jsx("code",{...r,children:n}):t.jsx("code",{...r,children:i})},table:({children:n,...r})=>t.jsx("table",{...r,className:"chat-markdown-table",children:n})},st="__fn_agent__",wa=280,jt=180,Mt=500,Vs="fusion:chat-sidebar-width",os="fusion:chat-scope",Sa="fusion:chat-draft:";function qs(n,r){return r?`${Sa}${n}:${r}`:null}function Xs(n){if(!n)return"";try{return localStorage.getItem(n)??""}catch{return""}}const Ca=["image/png","image/jpeg","image/gif","image/webp","text/plain","application/json","text/yaml","text/markdown","text/csv","application/xml","text/x-log"];function Ys(n){const r=/(^|[\s])\/([^\s]*)$/.exec(n);if(!r)return null;const d=r[1]??"",i=r[2]??"",g=r.index+d.length;return{filter:i,start:g,end:n.length}}function ka(n,r){const d=n.slice(0,r),i=/(^|[\s\n])@([\w-]*)$/.exec(d);if(!i)return null;const g=i[2]??"",b=d.length-g.length-1;return{filter:g,start:b,end:r}}function Na(n){const r=n?.runtimeConfig;if(!r||typeof r!="object")return null;const d=Reflect.get(r,"modelProvider"),i=Reflect.get(r,"modelId");return typeof d!="string"||d.trim().length===0||typeof i!="string"||i.trim().length===0?null:{provider:d,modelId:i}}function Js(n,r,d){if(n?.modelProvider&&n?.modelId)return{provider:n.modelProvider,modelId:n.modelId};const i=Na(r??void 0);return i||(d.provider&&d.modelId?{provider:d.provider,modelId:d.modelId}:null)}function ja({projectId:n,onClose:r,onCreate:d}){const[i,g]=s.useState("agent"),{agents:b,loading:y}=ls(n),[f,I]=s.useState(""),{models:J,favoriteProviders:Q,favoriteModels:w,loading:j,refresh:z}=Zs(),[S,Z]=s.useState(""),[C,O]=s.useState(Q),[N,X]=s.useState(w);s.useEffect(()=>{O(Q)},[Q]),s.useEffect(()=>{X(w)},[w]);const E=s.useCallback(async k=>{const B=C,h=B.includes(k)?B.filter(p=>p!==k):[k,...B];O(h);try{await Bs({favoriteProviders:h,favoriteModels:N}),await z()}catch{O(B)}},[C,N,z]),_=s.useCallback(async k=>{const B=N,h=B.includes(k)?B.filter(p=>p!==k):[k,...B];X(h);try{await Bs({favoriteProviders:C,favoriteModels:h}),await z()}catch{X(B)}},[N,C,z]),T=k=>{if(k.preventDefault(),i==="agent"){if(!f)return;d({agentId:f});return}if(!S)return;const B=S.indexOf("/");if(B<=0)return;const te=S.slice(0,B),h=S.slice(B+1);d({agentId:st,modelProvider:te,modelId:h})},Y=i==="agent"?!f:!S;return t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:r,role:"dialog","aria-modal":"true",children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:k=>k.stopPropagation(),children:[t.jsx("h3",{children:"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${i==="agent"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-agent",onClick:()=>{g("agent"),Z("")},children:"Agent"}),t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${i==="model"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-model",onClick:()=>{g("model"),I("")},children:"Model"})]}),t.jsxs("form",{onSubmit:T,children:[i==="agent"&&t.jsxs("label",{className:"chat-new-dialog-model-label",children:["Agent",y?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading agents..."}):b.length===0?t.jsx("div",{className:"chat-new-dialog-empty",children:"No agents available"}):t.jsx("div",{className:"chat-new-dialog-agent-list",children:b.map(k=>t.jsxs("button",{type:"button",className:`chat-new-dialog-agent-item${f===k.id?" chat-new-dialog-agent-item--selected":""}`,onClick:()=>I(k.id),"data-testid":`agent-option-${k.id}`,children:[t.jsx(ut,{size:16}),t.jsx("span",{className:"chat-new-dialog-agent-name",children:k.name}),t.jsx("span",{className:"chat-new-dialog-agent-role",children:k.role})]},k.id))})]}),i==="model"&&t.jsx("div",{className:"chat-new-dialog-model-dropdown","data-testid":"chat-new-dialog-model-section",children:j?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading models..."}):t.jsx(ia,{models:J,value:S,onChange:Z,label:"Model",placeholder:"Select a model",favoriteProviders:C,onToggleFavorite:E,favoriteModels:N,onToggleModelFavorite:_})}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{type:"button",className:"btn btn-sm",onClick:r,children:"Cancel"}),t.jsx("button",{type:"submit",className:"btn btn-sm btn-primary",disabled:Y,children:"Create"})]})]})]})})}const cs=s.memo(function({message:r,forcePlain:d,agentName:i,hideAssistantIdentity:g,showAssistantModelTag:b,activeModelTag:y,activeModelProvider:f,activeSessionId:I,mentionAgentsByName:J,roomContext:Q,copyAction:w,onScrollToTop:j}){const z=r.role==="assistant",S=z?r.failureInfo:void 0,Z=z&&(!g||!!S),C=s.useMemo(()=>{if(z)return null;const X=r.content,E=/@([\w-]+)/g,_=[];let T=0,Y=E.exec(X);for(;Y;){const[k,B=""]=Y,te=Y.index;te>T&&_.push(X.slice(T,te));const h=B.replace(/_/g," ").toLowerCase(),p=J.get(h);if(p){const he=!!(Q&&!Q.memberIds.has(p.id)),c=he?`Not a member of ${Q?.roomName}`:void 0;_.push(t.jsxs("span",{className:`chat-mention-chip${he?" chat-mention-chip--non-member":""}`,title:c,"aria-label":c,children:["@",p.name.replace(/\s+/g,"_")]},`${p.id}-${te}`))}else _.push(k);T=te+k.length,Y=E.exec(X)}return T<X.length&&_.push(X.slice(T)),_.length===0?X:_},[z,r.content,J,Q]),O=s.useMemo(()=>{const X=r.attachments;if(!X||X.length===0)return null;const E=r.roomId?`/api/chat/rooms/${encodeURIComponent(r.roomId)}/attachments/`:I?`/api/chat/sessions/${encodeURIComponent(I)}/attachments/`:null;return E?t.jsx("div",{className:"chat-message-attachments",children:X.map(_=>{const T=_.mimeType.startsWith("image/"),Y=_.id||_.filename,k=`${E}${encodeURIComponent(_.filename)}`;return T?t.jsx("a",{className:"chat-message-attachment-link","data-testid":"chat-message-attachment",href:k,target:"_blank",rel:"noopener noreferrer",children:t.jsx("img",{className:"chat-message-attachment",src:k,alt:_.originalName})},Y):t.jsxs("a",{className:"chat-message-attachment-file","data-testid":"chat-message-attachment",href:k,target:"_blank",rel:"noopener noreferrer",children:[t.jsx(na,{size:14}),t.jsx("span",{children:_.originalName})]},Y)})}):null},[r.attachments,r.roomId,I]),N=s.useMemo(()=>z?S?t.jsxs("div",{className:"chat-message-content chat-message-content--failure",children:[t.jsxs("div",{className:"chat-message-failure-summary-row",children:[t.jsx("span",{className:"status-dot status-dot--error","aria-hidden":"true"}),t.jsx("span",{className:"chat-message-failure-label",children:"Response failed"})]}),t.jsx("div",{className:"chat-message-failure-summary",children:S.summary}),(S.errorClass||S.code)&&t.jsxs("div",{className:"chat-message-failure-badges",children:[S.errorClass&&t.jsx("span",{className:"chat-message-failure-badge",children:S.errorClass}),S.code&&t.jsx("span",{className:"chat-message-failure-badge",children:S.code})]}),(S.detail||S.reference)&&t.jsxs("details",{className:"chat-message-failure-details",children:[t.jsxs("summary",{children:[t.jsx(aa,{size:14,"aria-hidden":"true"}),t.jsx("span",{children:"Failure details"})]}),S.detail&&t.jsx("pre",{className:"chat-message-failure-detail",children:Et(S.detail)}),ya(S.reference)]})]}):d?t.jsx("div",{className:"chat-message-content chat-message-content--plain",children:r.content}):t.jsx("div",{className:"chat-message-content chat-message-content--markdown",children:t.jsx(en,{remarkPlugins:[tn],components:rn,children:r.content})}):null,[S,d,z,r.content]);return t.jsxs("div",{className:`chat-message chat-message--${r.role}${S?" chat-message--failure":""}`,"data-testid":`chat-message-${r.id}`,"data-message-id":r.id,children:[Z&&t.jsxs("div",{className:"chat-message-avatar",children:[f?t.jsx(dt,{provider:f,size:"sm"}):t.jsx(ut,{size:14}),t.jsx("span",{children:i}),b&&y&&t.jsx("span",{className:"chat-model-tag",children:y})]}),z?N:t.jsx("div",{className:"chat-message-content",children:C}),z&&!S&&(w||j)&&t.jsxs("div",{className:"chat-message-actions",children:[w,j&&t.jsx("button",{type:"button",className:"btn-icon chat-message-scroll-to-top-action","aria-label":"Scroll message to top","data-testid":`chat-message-scroll-to-top-${r.id}`,onClick:()=>j(r.id),children:t.jsx(ca,{size:14})})]}),an(r.toolCalls),r.thinkingOutput&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:Et(r.thinkingOutput)})]}),O,t.jsx("div",{className:"chat-message-time",children:nn(r.createdAt)})]})});function Ia({projectId:n,addToast:r,experimentalFeatures:d}){s.useEffect(()=>(At({view:"ChatView",trigger:is?"route-active":"remount",projectId:n,replayAttempted:!1}),is=!1,()=>{is=!0,At({view:"ChatView",trigger:"route-inactive",projectId:n,replayAttempted:!1})}),[n]);const{activeSession:i,sessionsLoading:g,messages:b,messagesLoading:y,isStreaming:f,streamingText:I,streamingThinking:J,streamingToolCalls:Q,selectSession:w,createSession:j,archiveSession:z,deleteSession:S,sendMessage:Z,stopStreaming:C,pendingMessage:O,clearPendingMessage:N,loadMoreMessages:X,hasMoreMessages:E,searchQuery:_,setSearchQuery:T,filteredSessions:Y,agentsMap:k}=ma(n,r),[B,te]=s.useState(!1),h=d?.chatRooms===!0,[p,he]=s.useState(()=>{try{if(localStorage.getItem(os)==="rooms"&&h)return"rooms"}catch{}return"direct"}),c=_n(n,r),{isUnread:re,markRead:se}=zn(n),[$,ue]=s.useState(()=>{const e=qs(p,p==="rooms"?c.activeRoom?.id:i?.id);return Xs(e)}),[be,G]=s.useState(null),[Ge,K]=s.useState(null),[We,ye]=s.useState(null),[Ie,oe]=s.useState(!0),[Se,Ce]=s.useState(wa),[Ve,Oe]=s.useState(!1),{agentsMap:ce}=ls(n),me=s.useMemo(()=>k.size>0?k:ce,[ce,k]),{defaultProvider:mt,defaultModelId:ie}=Zs(),le=s.useMemo(()=>({provider:mt,modelId:ie}),[ie,mt]),{skills:$e,loading:Tt}=Hn(n),[De,Pe]=s.useState(!1),[nt,qe]=s.useState(""),[Be,Le]=s.useState(0),[ke,Ne]=s.useState(""),[ve,l]=s.useState(!1),[u,v]=s.useState(0),[D,H]=s.useState(-1),[A,ee]=s.useState(!1),[M,U]=s.useState([]),[W,V]=s.useState(!1),[P,q]=s.useState(!1),[ne,je]=s.useState({}),[ht,Xe]=s.useState(!1),[ft,at]=s.useState(!1),{pushNav:ds}=Un(),[,gt]=s.useState(!1),[on,cn]=s.useState({top:0,left:0}),L=On({projectId:n}),It=s.useCallback(e=>{if(!e||!L.mentionActive)return;const a=e.getBoundingClientRect();cn({top:a.top-260,left:a.left+8})},[L.mentionActive]),us=s.useRef(null),ms=s.useRef(null),hs=s.useRef(null),fs=s.useRef(null),we=s.useRef(!1),$t=s.useRef(null),gs=s.useRef(null),Fe=s.useRef(null),pt=s.useRef(0),Dt=s.useRef(null),bt=s.useRef(null),Me=s.useRef(null),ge=s.useRef(null),Pt=s.useRef(null),vt=s.useRef(!1),Re=s.useRef(null),de=s.useRef(null),ps=s.useRef(null),bs=s.useRef([]),Ye=s.useRef(0),rt=s.useRef(new Map),R=Bn()==="mobile";s.useEffect(()=>{i?.id&&se("direct",i.id,i.lastMessageAt??i.updatedAt)},[i?.id,i?.lastMessageAt,i?.updatedAt,se]),s.useEffect(()=>{c.activeRoom?.id&&se("room",c.activeRoom.id,c.activeRoom.updatedAt)},[c.activeRoom?.id,c.activeRoom?.updatedAt,se]),s.useEffect(()=>{if(!i?.id||b.length===0)return;const e=b[b.length-1];se("direct",i.id,e?.createdAt??i.lastMessageAt??i.updatedAt)},[i?.id,i?.lastMessageAt,i?.updatedAt,se,b]),s.useEffect(()=>{if(!c.activeRoom?.id||c.messages.length===0)return;const e=c.messages[c.messages.length-1];se("room",c.activeRoom.id,e?.createdAt??c.activeRoom.updatedAt)},[se,c.activeRoom?.id,c.activeRoom?.updatedAt,c.messages]),s.useEffect(()=>{try{const e=localStorage.getItem(Vs);if(!e)return;const a=Number.parseInt(e,10);if(Number.isNaN(a))return;const o=Math.max(jt,Math.min(Mt,a));Ce(o)}catch{}},[]),s.useEffect(()=>{try{const e=localStorage.getItem(os);if(e==="direct"){he("direct");return}e==="rooms"&&h&&he("rooms")}catch{}},[h]),s.useEffect(()=>{if(!h&&p==="rooms"){he("direct");return}try{localStorage.setItem(os,p)}catch{}},[h,p]);const fe=qs(p,p==="rooms"?c.activeRoom?.id:i?.id),Lt=s.useRef(fe);s.useEffect(()=>{fe!==Lt.current&&(Lt.current=fe,ue(Xs(fe)))},[fe]),s.useEffect(()=>{if(!(!fe||Lt.current!==fe))try{if($){localStorage.setItem(fe,$);return}localStorage.removeItem(fe)}catch{}},[fe,$]);const ae=h&&p==="rooms"&&!!c.activeRoom,{keyboardOverlap:vs,keyboardOpen:Ft}=Kn({enabled:R&&(!!i||ae)}),xe=s.useMemo(()=>{const e=nt.trim().toLowerCase();return(e?$e.filter(o=>o.name.toLowerCase().includes(e)):$e).slice(0,10)},[$e,nt]),Je=s.useMemo(()=>Array.from(me.values()),[me]),Ae=s.useMemo(()=>!h||p!=="rooms"||!c.activeRoom?null:{roomId:c.activeRoom.id,roomName:c.activeRoom.name,memberIds:new Set(c.activeRoomMembers.map(e=>e.agentId))},[h,p,c.activeRoom,c.activeRoomMembers]),Ke=s.useMemo(()=>{const e=Je.filter(m=>Gn(m.name,ke));if(!Ae)return e;const a=e.filter(m=>Ae.memberIds.has(m.id));if(ke.trim().length===0)return a;const o=e.filter(m=>!Ae.memberIds.has(m.id));return[...a,...o]},[Je,ke,Ae]),_t=s.useMemo(()=>{const e=new Map;for(const a of Je)e.set(a.name.toLowerCase(),a);return e},[Je]);s.useEffect(()=>{Le(0)},[xe]),s.useEffect(()=>{v(0)},[ke,ve]),s.useEffect(()=>()=>{Me.current!==null&&window.clearTimeout(Me.current)},[]),s.useEffect(()=>{const e=ms.current;if(!e||!E||y)return;const a=new IntersectionObserver(o=>{o[0].isIntersecting&&X()},{threshold:.1});return a.observe(e),()=>a.disconnect()},[E,y,X]);const Qe=s.useCallback(()=>ae?c.activeRoom?.id??null:i?.id??null,[ae,c.activeRoom?.id,i?.id]),xs=s.useCallback((e,a)=>typeof CSS<"u"&&typeof CSS.escape=="function"?e.querySelector(`.chat-message[data-message-id="${CSS.escape(a)}"]`):e.querySelector(`.chat-message[data-message-id="${a.replace(/"/g,'\\"')}"]`),[]),xt=s.useCallback(()=>{const e=ge.current,a=Qe();if(!e||!a)return;const o=e.querySelector(".chat-message[data-message-id]"),m=o?.getAttribute("data-message-id")??null,x=o?o.offsetTop-e.scrollTop:0;bt.current={threadId:a,scrollTop:e.scrollTop,scrollHeight:e.scrollHeight,clientHeight:e.clientHeight,anchorMessageId:m,anchorOffset:x,wasPinnedBefore:!we.current}},[Qe]),ys=s.useCallback(()=>{const e=ge.current;if(!e)return;const o=e.scrollTop+e.clientHeight>=e.scrollHeight-50;q(!o),we.current=!o,xt()},[xt]),Ee=s.useCallback(e=>{if(!e.isConnected)return;let a=0,o=0,m=-1;const x=6,F=()=>{if(e.isConnected){if(e.scrollTop=e.scrollHeight,e.scrollHeight===m?o+=1:(o=0,m=e.scrollHeight),a+=1,a>=x||o>=2){q(!1),we.current=!1;return}window.requestAnimationFrame(F)}};F()},[]),it=ae?c.messages:b;s.useLayoutEffect(()=>{const e=ge.current,a=Qe(),o=bt.current;if(!e||!a||!o||o.threadId!==a||o.wasPinnedBefore)return;let m=o.scrollTop;if(o.anchorMessageId){const x=xs(e,o.anchorMessageId);x?m=x.offsetTop-o.anchorOffset:m=o.scrollTop+(e.scrollHeight-o.scrollHeight)}else m=o.scrollTop+(e.scrollHeight-o.scrollHeight);e.scrollTop=Math.max(0,m),we.current=!0,q(!0),bt.current=null},[it,Qe,xs]);const zt=s.useCallback(e=>{},[it.length,ae]),_e=s.useCallback(e=>{zt(e);const a=ge.current;a&&(bt.current=null,we.current=!1,Ee(a))},[Ee,zt]);s.useLayoutEffect(()=>{Fe.current!==null&&(window.clearTimeout(Fe.current),Fe.current=null);const e=ae?c.activeRoom?.id??null:i?.id??null;if(!e){$t.current=null;return}const a={threadId:e,loaded:ae?!c.messagesLoading:!y,hasMessages:ae?c.messages.length>0:b.length>0},o=$t.current,m=o?.threadId!==e,x=o?.threadId===e&&!o.loaded&&a.loaded,F=o?.threadId===e&&!o.hasMessages&&a.hasMessages;if(!(o===null||m||x||F))return;const Te=ge.current;if(Te)return zt(m?"thread-change":x?"finished-loading":F?"first-messages":"mount"),Ee(Te),ae||(Fe.current=window.setTimeout(()=>{if(Fe.current=null,we.current)return;const et=ge.current;et&&Ee(et)},250)),$t.current=a,()=>{Fe.current!==null&&(window.clearTimeout(Fe.current),Fe.current=null)}},[ae,c.activeRoom?.id,c.messages.length,c.messagesLoading,i?.id,b.length,y,Ee]),s.useEffect(()=>{!f||we.current||_e("streaming")},[f,I,J,_e]),s.useEffect(()=>{const e=Qe();if(!e){pt.current=0,Dt.current=null;return}if(Dt.current!==e){Dt.current=e,pt.current=it.length;return}const a=pt.current,o=it.length,m=o>a,x=!we.current;pt.current=o,m&&x&&_e("new-message")},[it,Qe,_e]),s.useEffect(()=>{vs<=0||!ge.current||_e("keyboard")},[vs,_e]),Wn(R&&Ft),s.useLayoutEffect(()=>{if(!R||!i&&!ae||typeof window>"u")return;const e=Pt.current,a=window.visualViewport;if(!e||!a)return;const o=x=>{if(!(x instanceof HTMLElement))return!1;if(x.tagName==="TEXTAREA")return!0;if(x.tagName!=="INPUT")return!1;const F=x.type.toLowerCase();return["","text","search","email","url","tel","password","number"].includes(F)},m=()=>{if(vt.current){e.classList.remove("chat-thread--keyboard-active");return}const x=Math.max(0,window.innerHeight-a.offsetTop-a.height),F=a.offsetTop||0;e.style.setProperty("--vv-height",`${a.height}px`),e.style.setProperty("--vv-offset-top",`${F}px`),e.style.setProperty("--keyboard-overlap",`${x}px`);const Ue=(x>0||F>0)&&o(document.activeElement);e.classList.toggle("chat-thread--keyboard-active",Ue)};return m(),a.addEventListener("resize",m),a.addEventListener("scroll",m),document.addEventListener("focusin",m),document.addEventListener("focusout",m),window.addEventListener("pageshow",m),document.addEventListener("visibilitychange",m),()=>{a.removeEventListener("resize",m),a.removeEventListener("scroll",m),document.removeEventListener("focusin",m),document.removeEventListener("focusout",m),window.removeEventListener("pageshow",m),document.removeEventListener("visibilitychange",m),e.classList.remove("chat-thread--keyboard-active")}},[i,R,ae]),s.useEffect(()=>{const e=()=>G(null);if(be)return document.addEventListener("click",e),()=>document.removeEventListener("click",e)},[be]),s.useEffect(()=>{if(!R||!Ft)return;const e=a=>{a.target?.closest(".chat-messages")||a.preventDefault()};return document.addEventListener("touchmove",e,{passive:!1}),()=>{document.removeEventListener("touchmove",e)}},[R,Ft]),s.useEffect(()=>{if(!R||!i)return;const e=()=>{const a=de.current;a&&document.activeElement===a&&(a.blur(),window.setTimeout(()=>{a.focus({preventScroll:!0})},0))};return document.addEventListener("visibilitychange",e),window.addEventListener("pageshow",e),()=>{document.removeEventListener("visibilitychange",e),window.removeEventListener("pageshow",e)}},[R,i]),s.useEffect(()=>{const e=gs.current;if(gs.current=p,p!=="direct"||e!==null&&e!=="rooms")return;const a=ge.current;a&&(Ee(a),we.current=!1,q(!1))},[p,Ee]),s.useEffect(()=>{if(!i&&!ae||ae&&!R)return;const e=()=>{xt()},a=()=>{document.visibilityState==="visible"&&e()};return document.addEventListener("visibilitychange",a),window.addEventListener("pageshow",e),()=>{document.removeEventListener("visibilitychange",a),window.removeEventListener("pageshow",e)}},[R,i,ae,xt]),s.useEffect(()=>{if(ae||typeof ResizeObserver>"u")return;const e=ge.current;if(!e)return;const a=new ResizeObserver(()=>{we.current||Ee(e)});return a.observe(e),()=>{a.disconnect()}},[ae,Ee,i?.id,p]),s.useEffect(()=>{bs.current=M},[M]),s.useEffect(()=>()=>{for(const e of bs.current)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);for(const e of rt.current.values())window.clearTimeout(e);rt.current.clear()},[]);const yt=s.useCallback(e=>{if(!e||e.length===0)return;const a=[];for(const o of Array.from(e)){if(!Ca.includes(o.type))continue;const m=o.type.startsWith("image/");a.push({file:o,previewUrl:m?URL.createObjectURL(o):""})}a.length>0&&U(o=>[...o,...a])},[]),ln=s.useCallback(e=>{U(a=>{const o=a[e];return o?.previewUrl&&URL.revokeObjectURL(o.previewUrl),a.filter((m,x)=>x!==e)})},[]),dn=s.useCallback(e=>{const a=e.clipboardData?.files;if(!a||a.length===0)return;const o=Array.from(a).filter(m=>m.type.startsWith("image/"));o.length!==0&&yt(o)},[yt]),un=s.useCallback(async e=>{try{await j(e),te(!1),R&&oe(!1)}catch{r("Failed to create chat session","error")}},[j,r,R]),pe=s.useCallback(e=>{const a=e??de.current;a&&(a.style.height="auto",a.style.height=`${pa(a.scrollHeight)}px`,a.style.overflowY=ga(a.scrollHeight))},[]),ws=s.useCallback(e=>{de.current=e,e&&pe(e)},[pe]);s.useLayoutEffect(()=>{pe()},[p,$,i?.id,c.activeRoom?.id,pe]);const Ze=s.useCallback(()=>{if(ue(""),fe)try{localStorage.removeItem(fe)}catch{}Pe(!1),qe(""),l(!1),Ne(""),H(-1),U(e=>{for(const a of e)a.previewUrl&&URL.revokeObjectURL(a.previewUrl);return[]})},[fe]),Ht=s.useCallback(()=>{const e=$.trim(),a=M.map(o=>o.file);if(!(!e&&a.length===0||!i)){if(e==="/clear"||e==="/new"){Ze(),N(),C(),j({agentId:i.agentId,modelProvider:i.modelProvider??void 0,modelId:i.modelId??void 0}).catch(()=>{r("Failed to clear conversation","error")});return}Ze(),Z(e,a)}},[$,M,i,Ze,C,N,j,r,Z]),Ut=s.useCallback(async()=>{const e=$.trim();if(e){if(h&&p==="rooms"){if(!c.activeRoom)return;if(e==="/clear"||e==="/new"){Ze();try{await c.clearRoom(c.activeRoom.id)}catch{r("Failed to clear room conversation","error")}return}const a=$;Ze();try{await c.sendRoomMessage(e,{files:M.map(o=>o.file)})}catch(o){if(o instanceof Vn){const x=o.message.trim()?o.message:"Message sent, but assistant reply failed";r(`Message sent, but assistant reply failed: ${x}`,"error");return}ue(a);const m=o instanceof Error&&o.message.trim()?o.message:"Failed to send room message";r(m,"error")}return}Ht()}},[$,M,h,p,c,c.clearRoom,Ze,r,Ht]),Ot=s.useCallback(e=>{ue(a=>{const o=Ys(a);if(!o)return a;const m=`/skill:${e.name} `,x=a.slice(0,o.start)+m+a.slice(o.end);return window.requestAnimationFrame(()=>{de.current&&(pe(de.current),de.current.focus())}),x}),Pe(!1),qe(""),Le(0)},[pe]),wt=s.useCallback(e=>{const a=de.current;if(!a||D<0)return;const o=a.selectionStart??Ye.current,m=a.selectionEnd??o,x=Math.max(o,m),F=Math.min(D,x),Te=`${`@${e.name.replace(/\s+/g,"_")}`} `,et=$.slice(0,F)+Te+$.slice(x),tt=F+Te.length;ue(et),l(!1),Ne(""),v(0),H(-1),window.requestAnimationFrame(()=>{de.current&&(pe(de.current),de.current.focus(),de.current.setSelectionRange(tt,tt))})},[D,$,pe]),ot=s.useCallback((e,a)=>{const m=de.current?.selectionStart??Ye.current,x=$.lastIndexOf("#",m),F=x>=0?x+a.length:e.length;ue(e),L.dismissMention(),gt(!1),window.requestAnimationFrame(()=>{de.current&&(pe(de.current),de.current.focus(),de.current.setSelectionRange(F,F))})},[L,$,pe]),Ss=s.useCallback(e=>{if(Ye.current=e.currentTarget.selectionStart??Ye.current,L.mentionActive&&L.combinedItems.length>0){if(L.handleKeyDown(e,$),e.key==="Enter"||e.key==="Tab"){const a=L.combinedItems[L.selectedIndex];a?.kind==="task"?ot(L.selectTask(a.task,$),`#${a.task.id}`):a?.kind==="file"&&ot(L.selectFile(a.file,$),`#${a.file.path}`)}return}if(ve&&e.key==="ArrowDown"){e.preventDefault(),Ke.length>0&&v(a=>(a+1)%Ke.length);return}if(ve&&e.key==="ArrowUp"){e.preventDefault(),Ke.length>0&&v(a=>a===0?Ke.length-1:a-1);return}if(ve&&e.key==="Enter"){e.preventDefault();const a=Ke[u]??Ke[0];a&&wt(a);return}if(ve&&e.key==="Escape"){e.preventDefault(),l(!1),Ne(""),H(-1);return}if(De&&e.key==="ArrowDown"){e.preventDefault(),xe.length>0&&Le(a=>(a+1)%xe.length);return}if(De&&e.key==="ArrowUp"){e.preventDefault(),xe.length>0&&Le(a=>a===0?xe.length-1:a-1);return}if(De&&(e.key==="Enter"||e.key==="Tab")&&xe.length>0){e.preventDefault();const a=xe[Be]??xe[0];a&&Ot(a);return}if(De&&e.key==="Escape"){e.preventDefault(),Pe(!1);return}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),Ut())},[ve,Ke,u,wt,De,xe,Be,Ot,Ut,L,ot,$]),St=s.useCallback((e,a)=>{const o=ka(e,a);if(o){l(!0),Ne(o.filter),H(o.start);return}l(!1),Ne(""),H(-1)},[]),Cs=s.useCallback(e=>{const a=e.target,o=a.value,m=a.selectionStart??o.length;pe(a),Ye.current=m,ue(o);const x=Ys(o);x?(Pe(!0),qe(x.filter)):(Pe(!1),qe("")),St(o,m),L.detectMention(o,m),gt(L.mentionActive),L.mentionActive&&It(a)},[St,pe]),Ct=s.useCallback(e=>{const a=e.currentTarget,o=a.selectionStart??a.value.length;Ye.current=o,St(a.value,o),L.detectMention(a.value,o),gt(L.mentionActive),L.mentionActive&&It(a)},[St,L,It]),ks=s.useCallback(e=>{e.key!=="Escape"&&Ct(e)},[Ct]),Ns=s.useCallback(()=>{typeof window<"u"&&window.innerWidth<=768&&(vt.current=!0,Re.current!==null&&window.clearTimeout(Re.current),Re.current=window.setTimeout(()=>{vt.current=!1,Re.current=null},450)),Me.current!==null&&window.clearTimeout(Me.current),Me.current=window.setTimeout(()=>{Pe(!1),l(!1),Ne(""),H(-1),gt(!1),L.dismissMention(),Me.current=null},120)},[L]),js=s.useCallback(()=>{vt.current=!1,Re.current!==null&&(window.clearTimeout(Re.current),Re.current=null),Me.current!==null&&(window.clearTimeout(Me.current),Me.current=null),typeof window<"u"&&window.innerWidth<=768&&queueMicrotask(()=>{(window.scrollY!==0||window.scrollX!==0)&&window.scrollTo(0,0)})},[]);s.useEffect(()=>()=>{Re.current!==null&&window.clearTimeout(Re.current)},[]);const mn=s.useCallback(async e=>{G(null);try{await z(e),r("Conversation archived","success")}catch{r("Failed to archive conversation","error")}},[z,r]),hn=s.useCallback(async e=>{K(null),G(null);try{await S(e),r("Conversation deleted","success")}catch{r("Failed to delete conversation","error")}},[S,r]),ct=s.useCallback(e=>{try{localStorage.setItem(Vs,String(e))}catch{}},[]),fn=s.useCallback(e=>{if(R)return;e.preventDefault(),e.stopPropagation();const a=e.currentTarget;typeof a.setPointerCapture=="function"&&a.setPointerCapture(e.pointerId);const o=e.clientX,m=Se;let x=m;document.body.style.userSelect="none";const F=Te=>{const et=Te.clientX-o,tt=Math.max(jt,Math.min(Mt,m+et));x=tt,Ce(tt),ct(tt)},Ue=Te=>{typeof a.releasePointerCapture=="function"&&a.releasePointerCapture(Te.pointerId),document.body.style.userSelect="",document.removeEventListener("pointermove",F),document.removeEventListener("pointerup",Ue),ct(x)};document.addEventListener("pointermove",F),document.addEventListener("pointerup",Ue)},[R,ct,Se]),gn=s.useCallback(e=>{if(R||e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;e.preventDefault();const a=e.shiftKey?50:10,o=e.key==="ArrowLeft"?-a:a,m=Math.max(jt,Math.min(Mt,Se+o));Ce(m),ct(m)},[R,ct,Se]),Ms=s.useCallback(e=>{const a=Y.find(o=>o.id===e);se("direct",e,a?.lastMessageAt??a?.updatedAt),w(e),Xe(!1),R&&oe(!1)},[Y,R,se,w]),Bt=s.useCallback(()=>{w(""),oe(!0),Xe(!1)},[w]),Kt=s.useCallback(()=>{c.selectRoom(null),oe(!0),Xe(!1)},[c]),pn=()=>t.jsxs("div",{className:"chat-empty-state",children:[t.jsx(ra,{size:48,strokeWidth:1.5}),t.jsx("h2",{children:"Start a new conversation"}),t.jsxs("button",{className:"btn btn-primary",onClick:()=>te(!0),children:[t.jsx(lt,{size:16}),"New Chat"]})]}),Gt=Js(i,i?.agentId?me.get(i.agentId)??null:null,le),ze=Ws(Gt?.provider,Gt?.modelId),He=Gt?.provider??null,Wt=!!(i||f||b.length>0),kt=p==="rooms"?ae:!!i,Rs=s.useRef(kt);s.useEffect(()=>{const e=Rs.current;Rs.current=kt,R&&(e||!kt||ds({type:"view",revert:p==="rooms"?Kt:Bt}))},[p,Bt,Kt,kt,R,ds]);const Vt=i?.agentId===st?ze??"Fusion":i?.title||me.get(i?.agentId??"")?.name||i?.agentId||"Chat",As=!!(ze&&ze!==Vt),bn=R&&p==="direct"&&!!i,qt=me.get(i?.agentId??"")?.name||(i?.agentId===st?ze??"Fusion":i?.agentId?.slice(0,30)??"Fusion"),Xt=!1,Yt=i?.agentId===st,vn=O.length>50?`${O.slice(0,50)}…`:O,xn=s.useCallback(()=>{ee(e=>!e)},[]);s.useEffect(()=>{if(!ht)return;const e=a=>{hs.current?.contains(a.target)||Xe(!1)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[ht]),s.useEffect(()=>{if(!ft)return;const e=o=>{fs.current?.contains(o.target)||at(!1)},a=o=>{o.key==="Escape"&&at(!1)};return document.addEventListener("mousedown",e),document.addEventListener("keydown",a),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("keydown",a)}},[ft]),s.useEffect(()=>{(!R||p!=="direct"||Ie)&&Xe(!1)},[R,p,Ie]),s.useEffect(()=>{at(!1)},[c.activeRoom?.id]);const Jt=s.useCallback((e,a)=>{const o=rt.current.get(e);o&&window.clearTimeout(o),je(x=>({...x,[e]:a}));const m=window.setTimeout(()=>{je(x=>{const{[e]:F,...Ue}=x;return Ue}),rt.current.delete(e)},2e3);rt.current.set(e,m)},[]),Es=s.useCallback(async(e,a)=>{try{if(!navigator.clipboard?.writeText)throw new Error("Clipboard API unavailable");await navigator.clipboard.writeText(a),Jt(e,"success")}catch{Jt(e,"error")}},[Jt]),yn=s.useCallback((e,a=!1)=>a?t.jsx("div",{className:"chat-message-content chat-message-content--plain",children:e}):t.jsx("div",{className:"chat-message-content chat-message-content--markdown",children:t.jsx(en,{remarkPlugins:[tn],components:rn,children:e})}),[]),Qt=i?.agentId===st,Zt=s.useCallback((e,a,o)=>t.jsx("button",{type:"button",className:`btn-icon chat-message-copy-action${ne[e]==="success"?" chat-message-copy-action--success":""}${ne[e]==="error"?" chat-message-copy-action--error":""}`,"data-testid":o??`chat-copy-response-${e}`,"aria-label":ne[e]==="success"?"Response copied":ne[e]==="error"?"Copy failed":"Copy response",onClick:()=>{Es(e,a)},children:ne[e]==="success"?t.jsx(qn,{size:14}):t.jsx(Xn,{size:14})}),[ne,Es]),es=s.useCallback(e=>{const a=ge.current;if(!a)return;const o=`[data-testid="chat-message-${e}"]`,m=a.querySelector(o);if(!m)return;const x=m.getBoundingClientRect().top-a.getBoundingClientRect().top+a.scrollTop,F=typeof window<"u"&&window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;a.scrollTo({top:x,behavior:F?"auto":"smooth"})},[]);return t.jsxs("div",{className:"chat-view",children:[t.jsxs("div",{className:`chat-sidebar${Ie?"":" chat-sidebar--hidden"}`,style:R?void 0:{width:`${Se}px`},children:[h&&t.jsxs("div",{className:"chat-sidebar-scope-toggle",role:"tablist","data-testid":"chat-sidebar-scope-toggle",children:[t.jsx("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:()=>he("direct"),children:"Direct"}),t.jsx("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:()=>he("rooms"),children:"Rooms"})]}),!h||p==="direct"?t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"chat-sidebar-search-container",children:t.jsxs("div",{className:"chat-sidebar-search-wrapper",children:[t.jsx(Yn,{size:14,className:"chat-sidebar-search-icon"}),t.jsx("input",{type:"text",className:"chat-sidebar-search",placeholder:"Search conversations...",value:_,onChange:e=>T(e.target.value),"data-testid":"chat-search-input"})]})}),t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:g?t.jsx("div",{className:"chat-empty-state chat-empty-state--padded",children:"Loading..."}):Y.length===0?t.jsx("div",{className:"chat-empty-state chat-empty-state--padded",children:"No conversations yet"}):Y.map(e=>{const a=i?.id===e.id,o=!a&&re("direct",e.id,e.lastMessageAt??e.updatedAt),m=Js(e,me.get(e.agentId)??null,le),x=Ws(m?.provider,m?.modelId)??"Fusion";return t.jsxs("div",{className:`chat-session-item${a?" chat-session-item--active":""}`,onClick:()=>Ms(e.id),onContextMenu:F=>{F.preventDefault(),G({sessionId:e.id,x:F.clientX,y:F.clientY})},"data-testid":`chat-session-${e.id}`,children:[t.jsx("button",{className:"chat-session-delete-btn",onClick:F=>{F.stopPropagation(),K(e.id)},"data-testid":"chat-session-delete-btn","aria-label":"Delete conversation",children:t.jsx(ns,{size:14})}),t.jsxs("div",{className:"chat-session-title",children:[e.title||"Untitled",o?t.jsx("span",{className:"chat-unread-dot","data-testid":`chat-unread-dot-${e.id}`,"aria-label":"Unread messages"}):null]}),t.jsx("div",{className:"chat-session-preview",children:e.lastMessagePreview||"No messages"}),t.jsxs("div",{className:"chat-session-meta",children:[t.jsxs("span",{className:"chat-session-meta-model",children:[m?.provider?t.jsx(dt,{provider:m.provider,size:"sm"}):null,t.jsx("span",{children:me.get(e.agentId)?.name||(e.agentId===st?x:e.agentId.slice(0,30))})]}),t.jsx("span",{children:e.updatedAt?nn(e.updatedAt):""})]})]},e.id)})})]}):t.jsxs("div",{className:"chat-sidebar-rooms","data-testid":"chat-sidebar-rooms",children:[!R&&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:()=>Oe(!0),children:[t.jsx(lt,{size:14}),"Create room"]})}),c.rooms.length===0?t.jsx("div",{className:"chat-sidebar-rooms-empty","data-testid":"chat-sidebar-rooms-empty",children:"No rooms yet."}):t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:c.rooms.map(e=>{const a=c.activeRoom?.id===e.id,o=!a&&re("room",e.id,e.updatedAt);return t.jsxs("div",{role:"button",tabIndex:0,className:`chat-room-item${a?" chat-room-item--active":""}`,"data-testid":`chat-room-item-${e.slug}`,onClick:()=>{se("room",e.id,e.updatedAt),c.selectRoom(e.id),R&&oe(!1)},onKeyDown:m=>{(m.key==="Enter"||m.key===" ")&&(m.preventDefault(),se("room",e.id,e.updatedAt),c.selectRoom(e.id),R&&oe(!1))},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]}),o?t.jsx("span",{className:"chat-unread-dot","data-testid":`chat-unread-dot-${e.id}`,"aria-label":"Unread messages"}):null]}),a?t.jsxs("span",{className:"chat-room-item-meta",children:[c.activeRoomMembers.length," ",c.activeRoomMembers.length===1?"member":"members"]}):null]}),t.jsx("button",{type:"button",className:"btn-icon chat-room-item-delete","data-testid":`chat-room-delete-${e.slug}`,"aria-label":`Delete room ${e.name}`,onClick:m=>{m.stopPropagation(),ye(e.id)},children:t.jsx(ns,{size:14})})]},e.id)})})]}),p==="rooms"?R?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:()=>Oe(!0),children:[t.jsx(lt,{size:14}),"Create room"]})}):null:t.jsx("div",{className:"chat-sidebar-footer",children:t.jsxs("button",{className:"btn btn-sm btn-primary chat-sidebar-footer-btn",onClick:()=>te(!0),"data-testid":"chat-new-btn",children:[t.jsx(lt,{size:14}),"New Chat"]})})]}),!R&&Ie&&t.jsx("div",{className:"chat-sidebar-resize-handle",role:"separator","aria-orientation":"vertical","aria-valuemin":jt,"aria-valuemax":Mt,"aria-valuenow":Se,"aria-label":"Resize chat sidebar",tabIndex:0,onPointerDown:fn,onKeyDown:gn}),be&&t.jsxs("div",{className:"chat-session-context-menu",style:{top:be.y,left:be.x},onClick:e=>e.stopPropagation(),children:[t.jsxs("button",{onClick:()=>mn(be.sessionId),"data-testid":"chat-context-archive",children:[t.jsx(Jn,{size:14}),"Archive"]}),t.jsxs("button",{onClick:()=>{G(null),K(be.sessionId)},"data-testid":"chat-context-delete",children:[t.jsx(ns,{size:14}),"Delete"]})]}),Ge&&t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:()=>K(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:"Delete Conversation?"}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:"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:()=>K(null),children:"Cancel"}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void hn(Ge),children:"Delete"})]})]})}),h&&We&&t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:()=>ye(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:"Delete Room?"}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:"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:()=>ye(null),children:"Cancel"}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>{(async()=>{try{await c.deleteRoom(We),ye(null)}catch{r("Failed to delete room","error")}})()},children:"Delete"})]})]})}),h&&p==="rooms"?t.jsxs("div",{ref:Pt,className:"chat-thread",children:[c.activeRoom?t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"chat-room-thread-header",children:[R&&t.jsx("button",{className:"btn-icon",onClick:Kt,"data-testid":"chat-back-btn",children:t.jsx(Fs,{size:16})}),t.jsxs("div",{className:"chat-room-switcher-menu",ref:fs,children:[t.jsxs("button",{type:"button",className:"chat-room-switcher-trigger","data-testid":"chat-room-switcher-trigger","aria-haspopup":"menu","aria-expanded":ft,onClick:()=>at(e=>!e),children:[t.jsxs("span",{className:"chat-thread-header-title",children:["#",c.activeRoom.name]}),t.jsx(Nt,{size:16,"aria-hidden":"true"})]}),ft&&t.jsx("div",{role:"menu",className:"chat-room-switcher-dropdown","data-testid":"chat-room-switcher-dropdown",children:c.rooms.map(e=>t.jsxs("button",{type:"button",role:"menuitem",className:`chat-room-switcher-option${e.id===c.activeRoom?.id?" chat-room-switcher-option--active":""}`,"data-testid":`chat-room-switcher-option-${e.id}`,onClick:()=>{se("room",e.id,e.updatedAt),c.selectRoom(e.id),at(!1)},children:["#",e.name]},e.id))})]}),t.jsx("div",{className:"chat-room-thread-members",children:c.activeRoomMembers.map(e=>t.jsx(Qs,{agent:me.get(e.agentId)??{id:e.agentId,name:e.agentId.slice(0,30)}},e.agentId))})]}),t.jsxs("div",{className:"chat-messages",ref:ge,onScroll:ys,children:[c.messagesLoading?t.jsx("div",{className:"chat-empty-state",children:"Loading messages..."}):c.messages.length===0?t.jsx("div",{className:"chat-empty-state",children:"No messages yet. Start the conversation!"}):c.messages.map(e=>{const a=e.senderAgentId?me.get(e.senderAgentId)?.name??e.senderAgentId.slice(0,30):"You",o={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(cs,{message:o,forcePlain:A,agentName:a,hideAssistantIdentity:!1,showAssistantModelTag:!1,activeModelTag:null,activeModelProvider:null,activeSessionId:c.activeRoom?.id??null,mentionAgentsByName:_t,roomContext:Ae,onScrollToTop:es},e.id)}),t.jsx("div",{ref:us})]}),c.activeRoom&&P&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:()=>_e("fab-click"),children:[t.jsx(Nt,{size:14}),"Latest"]})]}):t.jsx("div",{className:"chat-room-empty-pane","data-testid":"chat-rooms-empty-pane",children:"Select a room or create one"}),c.activeRoom&&t.jsx("div",{className:"chat-input-area",children:t.jsxs("div",{className:"chat-input-row",children:[t.jsxs("div",{className:"chat-input-wrapper",children:[t.jsx("textarea",{ref:ws,className:"chat-input-textarea",placeholder:"Type a message...",value:$,onChange:Cs,onKeyDown:Ss,onKeyUp:ks,onClick:Ct,onBlur:Ns,onFocus:js,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||_s()&&document.activeElement!==e.currentTarget&&(e.preventDefault(),e.currentTarget.focus({preventScroll:!0}))},rows:1,"data-testid":"chat-input"}),t.jsx(zs,{agents:Je,filter:ke,highlightedIndex:u,visible:ve,onSelect:wt,position:"below",roomMemberIds:Ae?.memberIds,roomName:Ae?.roomName})]}),t.jsx("button",{type:"button",className:"chat-input-send",onPointerDown:e=>{e.pointerType&&e.pointerType!=="mouse"&&e.preventDefault()},onMouseDown:e=>{e.preventDefault()},onClick:()=>{Ut()},disabled:!$.trim(),"data-testid":"chat-send-btn",style:{touchAction:"manipulation"},children:t.jsx(Hs,{size:16})})]})})]}):t.jsxs("div",{ref:Pt,className:"chat-thread",children:[(Wt||!R)&&t.jsxs("div",{className:"chat-thread-header",children:[R&&Wt&&t.jsx("button",{className:"btn-icon",onClick:Bt,"data-testid":"chat-back-btn",children:t.jsx(Fs,{size:16})}),t.jsx("div",{className:"chat-thread-header-identity","data-testid":"chat-thread-header-identity",children:bn?t.jsxs("div",{className:"chat-mobile-session-menu",ref:hs,children:[t.jsxs("button",{type:"button",className:"btn chat-mobile-session-trigger","data-testid":"chat-mobile-session-trigger","aria-haspopup":"menu","aria-expanded":ht,onClick:()=>Xe(e=>!e),children:[He?t.jsx(dt,{provider:He,size:"md"}):t.jsx(ut,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:Vt}),As&&t.jsx("span",{className:"chat-model-tag",children:ze}),t.jsx(Nt,{size:16,"aria-hidden":"true"})]}),ht&&t.jsx("div",{className:"chat-mobile-session-dropdown",role:"menu","data-testid":"chat-mobile-session-dropdown",children:Y.map(e=>t.jsx("button",{type:"button",role:"menuitem",className:`chat-mobile-session-option${i?.id===e.id?" chat-mobile-session-option--active":""}`,"data-testid":`chat-mobile-session-option-${e.id}`,onClick:()=>Ms(e.id),children:t.jsx("span",{className:"chat-mobile-session-option-title",children:e.title||"Untitled"})},e.id))})]}):t.jsxs(t.Fragment,{children:[He?t.jsx(dt,{provider:He,size:"md"}):t.jsx(ut,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:Vt}),As&&t.jsx("span",{className:"chat-model-tag",children:ze})]})}),Wt&&t.jsx("button",{type:"button",className:`chat-thread-header-render-toggle${A?" chat-thread-header-render-toggle--plain":""}`,"data-testid":"chat-thread-render-toggle","aria-label":A?"Show all messages as rendered Markdown":"Show all messages as plain text",onClick:xn,children:A?t.jsx(Qn,{size:14}):t.jsx(Zn,{size:14})}),!R&&t.jsxs("button",{className:"btn btn-sm btn-primary chat-thread-header-new-chat",onClick:()=>te(!0),"data-testid":"chat-thread-new-chat-btn",children:[t.jsx(lt,{size:14}),"New Chat"]})]}),t.jsxs("div",{className:"chat-messages",ref:ge,onScroll:ys,children:[t.jsx("div",{ref:ms,className:"chat-load-more-sentinel",children:E&&y&&t.jsx("div",{className:"chat-loading-older",children:"Loading older messages…"})}),f?t.jsxs(t.Fragment,{children:[b.map(e=>t.jsx(cs,{message:e,forcePlain:A,agentName:qt,hideAssistantIdentity:Yt,showAssistantModelTag:Xt,activeModelTag:ze,activeModelProvider:He,activeSessionId:i?.id??null,mentionAgentsByName:_t,roomContext:null,copyAction:Qt&&e.role==="assistant"?Zt(e.id,e.content):void 0,onScrollToTop:es},e.id)),t.jsxs("div",{className:"chat-message chat-message--assistant chat-message--streaming",children:[!Yt&&t.jsxs("div",{className:"chat-message-avatar",children:[He?t.jsx(dt,{provider:He,size:"sm"}):t.jsx(ut,{size:14}),t.jsx("span",{children:qt}),Xt]}),I?yn(I,A):t.jsx("div",{className:"chat-message-content chat-message-content--waiting",children:J?"Thinking…":"Connecting…"}),Qt&&I&&Zt("__streaming__",I,"chat-copy-response-streaming"),an(Q),J&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:Et(J)})]}),t.jsxs("div",{className:"chat-typing-indicator",children:[t.jsx("span",{}),t.jsx("span",{}),t.jsx("span",{})]})]})]}):y?t.jsx("div",{className:"chat-empty-state",children:"Loading messages..."}):b.length===0&&!i?pn():b.length===0&&i?t.jsx("div",{className:"chat-empty-state",children:"No messages yet. Start the conversation!"}):t.jsx(t.Fragment,{children:b.map(e=>t.jsx(cs,{message:e,forcePlain:A,agentName:qt,hideAssistantIdentity:Yt,showAssistantModelTag:Xt,activeModelTag:ze,activeModelProvider:He,activeSessionId:i?.id??null,mentionAgentsByName:_t,roomContext:null,copyAction:Qt&&e.role==="assistant"?Zt(e.id,e.content):void 0,onScrollToTop:es},e.id))}),t.jsx("div",{ref:us})]}),P&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:()=>_e("fab-click"),children:[t.jsx(Nt,{size:14}),"Latest"]}),i&&t.jsxs("div",{className:"chat-input-area",children:[t.jsx("input",{ref:ps,type:"file",accept:"image/*,.txt,.json,.yaml,.yml,.log,.csv,.xml,.md",multiple:!0,style:{display:"none"},onChange:e=>{yt(e.target.files),e.target.value=""}}),De&&t.jsx("div",{className:"chat-skill-menu","data-testid":"chat-skill-menu",role:"listbox","aria-label":"Skill suggestions",children:Tt?t.jsx("div",{className:"chat-skill-menu-empty",children:"Loading skills…"}):xe.length===0?t.jsx("div",{className:"chat-skill-menu-empty",children:nt?"No skills found":"No skills available"}):xe.map((e,a)=>t.jsxs("button",{type:"button",role:"option","aria-selected":a===Be,className:`chat-skill-menu-item${a===Be?" chat-skill-menu-item--highlighted":""}`,onMouseDown:o=>o.preventDefault(),onMouseEnter:()=>Le(a),onClick:()=>Ot(e),children:[t.jsx("span",{className:"chat-skill-menu-item-name",children:e.name}),t.jsx("span",{className:"chat-skill-menu-item-description",title:e.relativePath,children:e.relativePath})]},e.id))}),M.length>0&&t.jsx("div",{className:"chat-attachment-previews","data-testid":"chat-attachment-previews",children:M.map((e,a)=>t.jsxs("div",{className:"chat-attachment-preview","data-testid":`chat-attachment-preview-${a}`,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:()=>ln(a),"data-testid":`chat-attachment-remove-${a}`,"aria-label":`Remove ${e.file.name}`,children:"×"})]},e.previewUrl||`${e.file.name}-${a}`))}),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":"Attach files",onClick:()=>ps.current?.click(),children:t.jsx(ea,{size:16})}),t.jsxs("div",{className:`chat-input-wrapper${W?" chat-input-wrapper--dragover":""}`,onDragOver:e=>{e.preventDefault(),V(!0)},onDragLeave:()=>V(!1),onDrop:e=>{e.preventDefault(),V(!1),yt(e.dataTransfer.files)},children:[t.jsx("textarea",{ref:ws,className:"chat-input-textarea",placeholder:"Type a message...",value:$,onChange:Cs,onKeyDown:Ss,onKeyUp:ks,onClick:Ct,onBlur:Ns,onFocus:js,onPaste:dn,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||_s()&&document.activeElement!==e.currentTarget&&(e.preventDefault(),e.currentTarget.focus({preventScroll:!0}))},rows:1,"data-testid":"chat-input"}),t.jsx(zs,{agents:Je,filter:ke,highlightedIndex:u,visible:ve,onSelect:wt,position:"below",roomMemberIds:Ae?.memberIds,roomName:Ae?.roomName}),t.jsx(ta,{visible:L.mentionActive&&!ve,position:on,tasks:L.tasks,files:L.files,selectedIndex:L.selectedIndex,onSelectTask:e=>{ot(L.selectTask(e,$),`#${e.id}`)},onSelectFile:e=>{ot(L.selectFile(e,$),`#${e.path}`)},loading:L.loading}),O&&t.jsxs("div",{className:"chat-pending-message","data-testid":"chat-pending-indicator",children:[t.jsx("span",{children:`Queued: ${vn}`}),t.jsx("button",{type:"button",className:"chat-pending-message-dismiss","aria-label":"Dismiss queued message","data-testid":"chat-pending-dismiss",onClick:N,children:"×"})]})]}),f?t.jsx("button",{className:"chat-input-stop",onClick:C,"aria-label":"Stop generation","data-testid":"chat-stop-btn",children:t.jsx(sa,{size:14})}):t.jsx("button",{type:"button",className:"chat-input-send",onPointerDown:e=>{e.pointerType&&e.pointerType!=="mouse"&&e.preventDefault()},onMouseDown:e=>{e.preventDefault()},onClick:()=>{Ht()},disabled:!$.trim()&&M.length===0,"data-testid":"chat-send-btn",style:{touchAction:"manipulation"},children:t.jsx(Hs,{size:16})})]})]})]}),h&&t.jsx(fa,{isOpen:Ve,onClose:()=>Oe(!1),projectId:n,existingRoomNames:c.rooms.map(e=>e.name),onCreate:async e=>{await c.createRoom({name:e.name,memberAgentIds:e.memberAgentIds}),p!=="rooms"&&he("rooms"),Oe(!1),R&&oe(!1)}}),B&&t.jsx(ja,{projectId:n,onClose:()=>te(!1),onCreate:un})]})}export{Ia as ChatView,pa as clampChatInputHeight,ga as resolveChatInputOverflowY,Js as resolveSessionProvider};
@@ -1 +0,0 @@
1
- import{r as i,j as a}from"./vendor-react-K0fH_qHe.js";import{J as X}from"./index-BS-jSWPW.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const B=5,K=3,_="Cannot activate more than 5 goals. Resolve an active goal before activating another.";function R(o){return!!(o&&typeof o=="object"&&"code"in o&&o.code==="ACTIVE_GOAL_LIMIT_EXCEEDED")}function tt({initialGoals:o}){const[c,g]=i.useState(()=>o??[]),[m,b]=i.useState(o===void 0),[x,n]=i.useState(null),[U,j]=i.useState(!1),[y,N]=i.useState(""),[E,S]=i.useState(""),[w,d]=i.useState(null),[A,C]=i.useState(!1),[h,$]=i.useState(null),[G,p]=i.useState(""),[T,f]=i.useState(""),[k,u]=i.useState(null),[F,P]=i.useState(!1);i.useEffect(()=>{if(o!==void 0)return;let t=!0;return(async()=>{try{b(!0),n(null);const s=await fetch("/api/goals");if(!s.ok)throw new Error(`Failed to load goals (${s.status})`);const l=await s.json();if(!t)return;g(Array.isArray(l.goals)?l.goals:[])}catch{if(!t)return;n("Unable to load goals right now. Please try again.")}finally{t&&b(!1)}})(),()=>{t=!1}},[o]);const v=i.useMemo(()=>c.filter(t=>t.status==="active").length,[c]),M=v>=K&&v<=B;function H(){n(null),d(null),j(!0)}function J(t){$(t.id),p(t.title),f(t.description??""),u(null)}function I(){$(null),p(""),f(""),u(null)}function L(){j(!1),N(""),S(""),d(null)}async function V(){const t=y.trim();if(!t){d("Title is required.");return}try{C(!0),d(null),n(null);const e=await fetch("/api/goals",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({title:t,description:E})});if(e.ok){const l=await e.json();g(r=>[...r,l]),L();return}let s=null;try{s=await e.json()}catch{s=null}if(e.status===409&&R(s)){n(_);return}d("Unable to create goal right now. Please try again.")}catch{d("Unable to create goal right now. Please try again.")}finally{C(!1)}}async function q(){if(!h)return;const t=G.trim();if(!t){u("Title is required.");return}try{P(!0),u(null);const e=await fetch(`/api/goals/${h}`,{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({title:t,description:T})});if(!e.ok)throw new Error(`Failed to update goal (${e.status})`);const s=await e.json();g(l=>l.map(r=>r.id===s.id?s:r)),I()}catch{u("Unable to save goal right now. Please try again.")}finally{P(!1)}}async function O(t){const e=t.status==="active"?`/api/goals/${t.id}/archive`:`/api/goals/${t.id}/unarchive`;try{n(null);const s=await fetch(e,{method:"POST"});if(s.ok){const r=await s.json();g(W=>W.map(D=>D.id===r.id?r:D));return}let l=null;try{l=await s.json()}catch{l=null}if(s.status===409&&R(l)){n(_);return}n("Unable to update goal status right now. Please try again.")}catch{n("Unable to update goal status right now. Please try again.")}}return a.jsxs("section",{className:"goals-view","data-testid":"goals-view",children:[a.jsxs("header",{className:"goals-header",children:[a.jsxs("div",{children:[a.jsx("h2",{className:"goals-title",children:"Goals"}),a.jsxs("p",{className:"goals-count","data-testid":"goals-active-count",children:[v," active goals"]})]}),a.jsxs("button",{type:"button",className:"btn btn-primary goals-add-button",onClick:H,"data-testid":"goals-add-button",children:[a.jsx(X,{"aria-hidden":"true"}),"Add Goal"]})]}),U?a.jsxs("div",{className:"card goals-form","data-testid":"goals-form",children:[a.jsx("label",{className:"goals-form-label",htmlFor:"goals-form-title",children:"Title"}),a.jsx("input",{id:"goals-form-title",className:"input",type:"text",value:y,maxLength:200,onChange:t=>N(t.target.value),"data-testid":"goals-form-title"}),a.jsx("label",{className:"goals-form-label",htmlFor:"goals-form-description",children:"Description"}),a.jsx("textarea",{id:"goals-form-description",className:"input",value:E,maxLength:5e3,onChange:t=>S(t.target.value),"data-testid":"goals-form-description"}),w?a.jsx("p",{className:"form-error goals-error",role:"alert",children:w}):null,a.jsxs("div",{className:"goals-form-actions",children:[a.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void V(),disabled:A,"data-testid":"goals-form-submit",children:"Save"}),a.jsx("button",{type:"button",className:"btn",onClick:L,disabled:A,"data-testid":"goals-form-cancel",children:"Cancel"})]})]}):null,M?a.jsx("p",{className:"goals-warning",role:"status",children:"Approaching the 5-active goal cap. Keep active goals focused."}):null,x?a.jsx("p",{className:"form-error goals-error",role:"alert","data-testid":"goals-error",children:x}):null,m?a.jsx("p",{className:"goals-loading",role:"status","data-testid":"goals-loading",children:"Loading goals…"}):null,!m&&c.length===0?a.jsx("div",{className:"goals-empty card","data-testid":"goals-empty-state",children:"No goals yet. Add one to begin tracking strategic outcomes."}):null,!m&&c.length>0?a.jsx("div",{className:"goals-list","data-testid":"goals-list",children:c.map(t=>a.jsx("article",{className:`card goals-card ${t.status==="archived"?"goals-card-archived":""}`.trim(),"data-testid":`goal-card-${t.id}`,children:h===t.id?a.jsxs("div",{className:"goals-card-main goals-card-edit",children:[a.jsx("label",{className:"goals-form-label",htmlFor:`goal-edit-title-${t.id}`,children:"Title"}),a.jsx("input",{id:`goal-edit-title-${t.id}`,className:"input",type:"text",value:G,maxLength:200,onChange:e=>p(e.target.value),"data-testid":`goal-edit-title-${t.id}`}),a.jsx("label",{className:"goals-form-label",htmlFor:`goal-edit-description-${t.id}`,children:"Description"}),a.jsx("textarea",{id:`goal-edit-description-${t.id}`,className:"input",value:T,maxLength:5e3,onChange:e=>f(e.target.value),"data-testid":`goal-edit-description-${t.id}`}),k?a.jsx("p",{className:"form-error goals-error",role:"alert",children:k}):null,a.jsxs("div",{className:"goals-card-actions",children:[a.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void q(),disabled:F,"data-testid":`goal-edit-save-${t.id}`,children:"Save"}),a.jsx("button",{type:"button",className:"btn",onClick:I,disabled:F,"data-testid":`goal-edit-cancel-${t.id}`,children:"Cancel"})]})]}):a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"goals-card-main",children:[a.jsx("h3",{className:"goals-card-title",children:t.title}),t.description?a.jsx("p",{className:"goals-card-description",children:t.description}):null,a.jsxs("p",{className:"goals-card-status",children:["Status: ",t.status]})]}),a.jsxs("div",{className:"goals-card-actions",children:[a.jsx("button",{type:"button",className:"btn",onClick:()=>J(t),"data-testid":`goal-edit-${t.id}`,children:"Edit"}),t.status==="active"?a.jsx("button",{type:"button",className:"btn goals-activate-button",onClick:()=>void O(t),"data-testid":`goal-archive-${t.id}`,children:"Archive"}):a.jsx("button",{type:"button",className:"btn goals-activate-button",onClick:()=>void O(t),"data-testid":`goal-unarchive-${t.id}`,children:"Unarchive"})]})]})},t.id))}):null]})}export{tt as GoalsView};