@runfusion/fusion 0.24.0 → 0.26.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.
- package/README.md +6 -0
- package/dist/bin.js +18646 -15669
- package/dist/client/assets/AgentDetailView-Cv-vgOj3.js +18 -0
- package/dist/client/assets/{AgentsView-BkB9FiMT.js → AgentsView-D6Zi5zfP.js} +4 -4
- package/dist/client/assets/ChatView-CAHjY9uO.js +1 -0
- package/dist/client/assets/{DevServerView-BkvtjZBa.js → DevServerView--_WBvIDQ.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-BK-KbnhP.js → DirectoryPicker-xedtR-Rd.js} +1 -1
- package/dist/client/assets/{DocumentsView-BEg1CQAk.js → DocumentsView-Bg2oaZks.js} +1 -1
- package/dist/client/assets/{EvalsView-Berf9bQm.js → EvalsView-B3uOCXfr.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-jcInE50G.js → ExperimentalAgentOnboardingModal-Bx6yXVS5.js} +1 -1
- package/dist/client/assets/{InsightsView-BX5bSF1J.js → InsightsView-Q1zvtF4F.js} +1 -1
- package/dist/client/assets/MemoryView-xcN_eouf.js +2 -0
- package/dist/client/assets/MemoryView-zaXewZzi.css +1 -0
- package/dist/client/assets/{NodesView-DLUOBLf6.js → NodesView-RxXg58_Q.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-COlJf0Kx.js → PiExtensionsManager-Cc8aAZXg.js} +2 -2
- package/dist/client/assets/PluginManager-BEkyBajl.js +1 -0
- package/dist/client/assets/{ResearchView-BzCcDAS4.css → ResearchView-BEI4ZSGs.css} +1 -1
- package/dist/client/assets/ResearchView-CERNf7sJ.js +1 -0
- package/dist/client/assets/{SettingsModal-yRqM4DV8.js → SettingsModal-B1r0yASu.js} +1 -1
- package/dist/client/assets/SettingsModal-BLsac7CJ.js +31 -0
- package/dist/client/assets/SettingsModal-Cis-4Lot.css +1 -0
- package/dist/client/assets/{SetupWizardModal-uUZk3TKT.js → SetupWizardModal-D1q548_L.js} +1 -1
- package/dist/client/assets/{SkillsView-CP8JX0P_.js → SkillsView-ClLM6u6p.js} +1 -1
- package/dist/client/assets/StashRecoveryView-B_8WIQEo.css +1 -0
- package/dist/client/assets/StashRecoveryView-ze0pEZ5U.js +1 -0
- package/dist/client/assets/{TodoView-DCRIkDZ-.js → TodoView-CTmIfy2M.js} +1 -1
- package/dist/client/assets/{dashboard-view-lR7YYmSC.js → dashboard-view-4xAN3yO5.js} +2 -2
- package/dist/client/assets/{folder-open-DHjELt8-.js → folder-open-BZuKESeq.js} +1 -1
- package/dist/client/assets/index-Bdw6llW6.js +692 -0
- package/dist/client/assets/index-CZGlyJuS.css +1 -0
- package/dist/client/assets/{star-DYesq1AV.js → star-D75YKEq-.js} +1 -1
- package/dist/client/assets/{upload-DTWF3Db5.js → upload-BYYTgWFj.js} +1 -1
- package/dist/client/assets/{users--syrel4l.js → users-RS90Aii3.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +5640 -3618
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/manifest.json +6 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +26 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/src/__tests__/manifest.test.ts +20 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/src/index.ts +14 -0
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +9 -11
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +30 -0
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +3 -28
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +899 -895
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +68 -71
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +47 -50
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +155 -109
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/src/index.ts +49 -3
- package/dist/plugins/fusion-plugin-reports/src/report-schema.ts +38 -0
- package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-schema.test.ts +66 -0
- package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-store.test.ts +177 -0
- package/dist/plugins/fusion-plugin-reports/src/store/report-store.ts +341 -0
- package/dist/plugins/fusion-plugin-reports/src/store/report-types.ts +77 -0
- package/dist/plugins/fusion-plugin-roadmap/{src/dashboard/RoadmapsView.css → bundled.css} +13 -219
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +29535 -0
- package/dist/plugins/fusion-plugin-roadmap/package.json +4 -41
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +2 -3
- package/dist/client/assets/AgentDetailView-gy_5SUj2.js +0 -18
- package/dist/client/assets/ChatView-B_-B8fqu.js +0 -1
- package/dist/client/assets/MemoryView-CKElJY_3.js +0 -2
- package/dist/client/assets/MemoryView-DiajLXby.css +0 -1
- package/dist/client/assets/PluginManager-CfW55BF4.js +0 -1
- package/dist/client/assets/ResearchView-B256Lr8I.js +0 -1
- package/dist/client/assets/SettingsModal-BeA_nQtW.js +0 -31
- package/dist/client/assets/SettingsModal-DzsLquBu.css +0 -1
- package/dist/client/assets/index-CQyVRLOb.js +0 -692
- package/dist/client/assets/index-CxA2Nn0_.css +0 -1
- package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.css +0 -58
- package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.tsx +0 -301
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphHighlight.css +0 -27
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.css +0 -157
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.tsx +0 -126
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.css +0 -35
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.tsx +0 -36
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.highlighting.test.tsx +0 -112
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.persistence.test.tsx +0 -115
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.test.tsx +0 -128
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.drag.test.tsx +0 -82
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.test.tsx +0 -307
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphToolbar.test.tsx +0 -60
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/edges.test.tsx +0 -75
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filtering.test.tsx +0 -62
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filters.test.ts +0 -78
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/graphPositionStorage.test.ts +0 -95
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/host-integration.test.ts +0 -74
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/index.test.ts +0 -58
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/interactions.test.tsx +0 -121
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/layout.test.ts +0 -70
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/persistence.test.tsx +0 -89
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphData.test.ts +0 -86
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphInteraction.test.ts +0 -167
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphPositions.test.ts +0 -66
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useNodeDrag.test.ts +0 -81
- package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-interop.d.ts +0 -35
- package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-view.tsx +0 -19
- package/dist/plugins/fusion-plugin-dependency-graph/src/edges.tsx +0 -70
- package/dist/plugins/fusion-plugin-dependency-graph/src/filters.ts +0 -8
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/__tests__/useDependencyChain.test.ts +0 -53
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useDependencyChain.ts +0 -60
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useGraphPositions.ts +0 -45
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useNodeDrag.ts +0 -114
- package/dist/plugins/fusion-plugin-dependency-graph/src/index.ts +0 -24
- package/dist/plugins/fusion-plugin-dependency-graph/src/layout.ts +0 -91
- package/dist/plugins/fusion-plugin-dependency-graph/src/styles/drag.css +0 -15
- package/dist/plugins/fusion-plugin-dependency-graph/src/types.ts +0 -21
- package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphData.ts +0 -17
- package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphInteraction.ts +0 -292
- package/dist/plugins/fusion-plugin-dependency-graph/src/utils/graphPositionStorage.ts +0 -65
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/api-client.test.ts +0 -101
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/index.test.ts +0 -92
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-routes.test.ts +0 -48
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-suggestions.test.ts +0 -31
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/RoadmapsView.tsx +0 -2559
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/RoadmapsView.test.tsx +0 -1144
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/useRoadmaps.test.ts +0 -1756
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/api.ts +0 -70
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/test-setup.ts +0 -7
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/types.ts +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useConfirm.ts +0 -8
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useRoadmaps.ts +0 -1188
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useViewportMode.ts +0 -20
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard-view.tsx +0 -6
- package/dist/plugins/fusion-plugin-roadmap/src/index.ts +0 -74
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-routes.ts +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-schema.ts +0 -41
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.d.ts +0 -15
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.ts +0 -15
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts +0 -283
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js +0 -21
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.ts +0 -310
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts +0 -5
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js +0 -361
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.ts +0 -408
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts +0 -68
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js +0 -300
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.ts +0 -381
- package/dist/plugins/fusion-plugin-roadmap/src/server/index.d.ts +0 -3
- package/dist/plugins/fusion-plugin-roadmap/src/server/index.ts +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-handoff.test.ts +0 -445
- package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-ordering.test.ts +0 -334
- package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-store.test.ts +0 -1318
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-handoff.ts +0 -163
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts +0 -37
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js +0 -188
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.ts +0 -311
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts +0 -299
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js +0 -765
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.ts +0 -1001
|
@@ -1,48 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion-plugin-examples/roadmap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Roadmap plugin package for Fusion",
|
|
6
|
-
"private": true,
|
|
7
5
|
"exports": {
|
|
8
6
|
".": {
|
|
9
|
-
"
|
|
10
|
-
"import": "./src/index.ts"
|
|
11
|
-
},
|
|
12
|
-
"./server": {
|
|
13
|
-
"types": "./src/server/index.d.ts",
|
|
14
|
-
"import": "./src/server/index.ts"
|
|
15
|
-
},
|
|
16
|
-
"./dashboard-view": {
|
|
17
|
-
"types": "./src/dashboard-view.tsx",
|
|
18
|
-
"import": "./src/dashboard-view.tsx"
|
|
19
|
-
},
|
|
20
|
-
"./roadmap-suggestions": {
|
|
21
|
-
"types": "./src/roadmap-suggestions.d.ts",
|
|
22
|
-
"import": "./src/roadmap-suggestions.ts"
|
|
7
|
+
"import": "./bundled.js"
|
|
23
8
|
}
|
|
24
9
|
},
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
"test": "vitest run --silent=passed-only --reporter=dot"
|
|
28
|
-
},
|
|
29
|
-
"dependencies": {
|
|
30
|
-
"@fusion/core": "workspace:*",
|
|
31
|
-
"@fusion/dashboard": "workspace:*",
|
|
32
|
-
"@fusion/plugin-sdk": "workspace:*",
|
|
33
|
-
"express": "^5.1.0",
|
|
34
|
-
"lucide-react": "^0.542.0",
|
|
35
|
-
"react": "^19.0.0",
|
|
36
|
-
"react-dom": "^19.2.4"
|
|
37
|
-
},
|
|
38
|
-
"devDependencies": {
|
|
39
|
-
"@testing-library/jest-dom": "^6.6.3",
|
|
40
|
-
"@testing-library/react": "^16.3.2",
|
|
41
|
-
"@testing-library/user-event": "^14.6.1",
|
|
42
|
-
"@types/express": "^5.0.5",
|
|
43
|
-
"@types/node": "^25.5.2",
|
|
44
|
-
"@types/react": "^19.0.0",
|
|
45
|
-
"typescript": "^5.7.0",
|
|
46
|
-
"vitest": "^3.2.4"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
10
|
+
"private": true
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runfusion/fusion",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.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",
|
|
@@ -80,8 +80,7 @@
|
|
|
80
80
|
"typebox": "^1.0.0",
|
|
81
81
|
"typescript": "^5.7.0",
|
|
82
82
|
"vitest": "^3.1.0",
|
|
83
|
-
"yaml": "^2.8.3"
|
|
84
|
-
"@fusion/pi-llama-cpp": "0.17.2"
|
|
83
|
+
"yaml": "^2.8.3"
|
|
85
84
|
},
|
|
86
85
|
"repository": {
|
|
87
86
|
"type": "git",
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import{r as t,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Ns,dy as yt,dz as St,dA as kt,dB as Ct,L as B,R as os,ap as Ds,Z as wt,aq as ms,W as rs,a as qs,b as Gs,dC as Rt,dD as Mt,dE as Ft,v as Ys,cH as At,dF as Tt,z as G,dG as Et,dH as Ks,dI as Zs,dJ as Pt,s as as,bp as Qs,k as Xs,U as hs,V as zs,aQ as Le,X as et,F as Ve,dK as Lt,A as ns,cf as st,dL as tt,dM as $t,cB as Dt,an as zt,bo as Ht,ar as at,B as ys,Y as Ot,a2 as Bt,a4 as It,dN as ps,l as nt,dO as Ut,bz as _t,r as Vt,ao as it,a1 as rt,dP as Jt,C as de,dQ as lt,dR as Hs,bq as Os,dS as Wt,dT as qt,dU as Gt,dV as Je,a9 as We,ab as qe,ac as Ge,a7 as ot,dW as Yt,dX as Kt,i as Zt,h as Qt,j as Bs,$ as Xt,dY as ea,dZ as sa,m as ta,d_ as js,d$ as aa,a3 as na,e0 as ia,O as ra,e1 as la,e2 as oa,e3 as ct,e4 as ca,e5 as da,e6 as ua,e7 as ma,e8 as ha}from"./index-CQyVRLOb.js";import{S as dt}from"./star-DYesq1AV.js";import{f as fs,S as fa,E as ga}from"./ExperimentalAgentOnboardingModal-jcInE50G.js";import"./vendor-xterm-DzcZoU0P.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 xa=[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"M18 17V9",key:"2bz60n"}],["path",{d:"M13 17V5",key:"1frdt8"}],["path",{d:"M8 17v-3",key:"17ska0"}]],is=Ns("chart-column",xa);/**
|
|
7
|
-
* @license lucide-react v1.7.0 - ISC
|
|
8
|
-
*
|
|
9
|
-
* This source code is licensed under the ISC license.
|
|
10
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
-
*/const ba=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M17 12h-2l-2 5-2-10-2 5H7",key:"15hlnc"}]],va=Ns("square-activity",ba);/**
|
|
12
|
-
* @license lucide-react v1.7.0 - ISC
|
|
13
|
-
*
|
|
14
|
-
* This source code is licensed under the ISC license.
|
|
15
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
16
|
-
*/const pa=[["path",{d:"M16 17h6v-6",key:"t6n2it"}],["path",{d:"m22 17-8.5-8.5-5 5L2 7",key:"x473p"}]],ja=Ns("trending-down",pa);function Is(s){return s<1e3?`${s}ms`:s<6e4?`${(s/1e3).toFixed(1)}s`:s<36e5?`${Math.floor(s/6e4)}m`:`${(s/36e5).toFixed(1)}h`}function Na(s){return`${Math.round(s*100)}%`}function Us(s){const n=Date.now(),i=new Date(s).getTime(),o=n-i;if(o<0){const u=Math.abs(o);return u<6e4?"in a moment":u<36e5?`in ${Math.floor(u/6e4)}m`:u<864e5?`in ${Math.floor(u/36e5)}h`:`in ${Math.floor(u/864e5)}d`}return o<6e4?"just now":o<36e5?`${Math.floor(o/6e4)}m ago`:o<864e5?`${Math.floor(o/36e5)}h ago`:`${Math.floor(o/864e5)}d ago`}function ya(s){switch(s){case"periodic":return"Periodic";case"post-task":return"Post-Task";case"manual":return"Manual";case"user-requested":return"User Requested";default:return s}}function Ue(s){return s instanceof Error&&s.message?s.message:String(s)}function Sa(s){switch(s){case"improving":return"↑ Improving";case"declining":return"↓ Declining";case"stable":return"→ Stable";default:return"Insufficient data"}}function ka(s){switch(s){case"improving":return"trend-improving";case"declining":return"trend-declining";case"stable":return"trend-stable";default:return"trend-insufficient"}}function _s(s,n=5){return e.jsx("span",{className:"rating-stars",children:Array.from({length:n},(i,o)=>e.jsx(dt,{size:14,className:o<s?"star-filled":"star-empty",fill:o<s?"currentColor":"none"},o))})}function Ca({agentId:s,projectId:n,addToast:i}){const[o,u]=t.useState([]),[g,R]=t.useState(null),[d,M]=t.useState(null),[k,F]=t.useState([]),[c,x]=t.useState(!0),[A,z]=t.useState(!0),[N,y]=t.useState(!1),[J,m]=t.useState(!1),[K,ee]=t.useState(null),[C,T]=t.useState(0),[j,E]=t.useState(""),[V,$]=t.useState(""),q=t.useCallback(async()=>{try{const[r,l]=await Promise.all([yt(s,20,n),St(s,void 0,n)]);u(r),R(l)}catch(r){i(`Failed to load reflections: ${Ue(r)}`,"error")}finally{x(!1)}},[s,n,i]),w=t.useCallback(async()=>{try{const[r,l]=await Promise.all([kt(s,n),Ct(s,{limit:50},n)]);M(r),F(l)}catch(r){i(`Failed to load ratings: ${Ue(r)}`,"error")}finally{z(!1)}},[s,n,i]);t.useEffect(()=>{q(),w()},[q,w]);const Q=async()=>{y(!0);try{if(!await Rt(s,n)){i("Not enough history to generate a reflection yet","error");return}i("Reflection generated successfully","success"),x(!0),await q()}catch(r){const l=Ue(r),p=l.toLowerCase();p.includes("agent not found")||p.includes("not found")?i("This agent is no longer available. It may have been deleted.","error"):p.includes("insufficient history")?i("Not enough history to generate a reflection yet","error"):i(`Failed to generate reflection: ${l}`,"error")}finally{y(!1)}},P=async r=>{if(r.preventDefault(),C!==0){m(!0);try{await Mt(s,{score:C,category:j||void 0,comment:V||void 0,raterType:"user"},n),T(0),E(""),$(""),i("Rating added","success"),await w()}catch(l){i(`Failed to add rating: ${Ue(l)}`,"error")}finally{m(!1)}}},O=async r=>{try{await Ft(s,r,n),i("Rating deleted","success"),await w()}catch(l){i(`Failed to delete rating: ${Ue(l)}`,"error")}},f=r=>{ee(l=>l===r?null:r)};if(c&&A)return e.jsx("div",{className:"reflections-tab",children:e.jsxs("div",{className:"reflections-loading-indicator",children:[e.jsx(B,{size:16,className:"animate-spin"}),e.jsx("span",{className:"text-muted",children:"Loading evaluation..."})]})});const b=g&&g.totalTasksCompleted===0&&g.totalTasksFailed===0&&g.recentReflectionCount===0;return e.jsxs("div",{className:"reflections-tab",children:[e.jsxs("div",{className:"reflections-header",children:[e.jsxs("h3",{children:[e.jsx(is,{size:16}),"Performance, Reflections & Ratings"]}),e.jsx("button",{className:"btn btn-secondary",onClick:Q,disabled:N,title:"Generate a manual reflection",children:N?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:14,className:"animate-spin"}),"Reflecting..."]}):e.jsxs(e.Fragment,{children:[e.jsx(os,{size:14}),"Reflect Now"]})})]}),g&&!b&&e.jsxs("div",{className:"reflections-stats-grid",children:[e.jsxs("div",{className:"reflections-stat-card",children:[e.jsxs("div",{className:"stat-value",children:[e.jsx(Ds,{size:16,style:{color:"var(--color-success)"}}),g.totalTasksCompleted]}),e.jsx("div",{className:"stat-label",children:"Tasks Completed"})]}),e.jsxs("div",{className:"reflections-stat-card",children:[e.jsxs("div",{className:"stat-value",children:[e.jsx(ja,{size:16,style:{color:"var(--color-error)"}}),g.totalTasksFailed]}),e.jsx("div",{className:"stat-label",children:"Tasks Failed"})]}),e.jsxs("div",{className:"reflections-stat-card",children:[e.jsxs("div",{className:"stat-value",children:[e.jsx(wt,{size:16,style:{color:"var(--in-progress)"}}),Is(g.avgDurationMs)]}),e.jsx("div",{className:"stat-label",children:"Avg Duration"})]}),e.jsxs("div",{className:"reflections-stat-card",children:[e.jsxs("div",{className:"stat-value",children:[e.jsx(is,{size:16,style:{color:g.successRate>=.8?"var(--color-success)":g.successRate>=.5?"var(--color-warning)":"var(--color-error)"}}),Na(g.successRate)]}),e.jsx("div",{className:"stat-label",children:"Success Rate"})]}),e.jsxs("div",{className:"reflections-stat-card",children:[e.jsxs("div",{className:"stat-value",children:[e.jsx(ms,{size:16,style:{color:"var(--color-info)"}}),g.recentReflectionCount]}),e.jsx("div",{className:"stat-label",children:"Reflections"})]})]}),b&&e.jsxs("div",{className:"reflections-no-data",children:[e.jsx(is,{size:24,opacity:.3}),e.jsx("p",{children:"No performance data yet"})]}),e.jsxs("div",{className:"reflections-ratings-section",children:[e.jsx("h4",{children:"User Ratings"}),A?e.jsxs("div",{className:"reflections-loading-indicator",children:[e.jsx(B,{size:16,className:"animate-spin"}),e.jsx("span",{className:"text-muted",children:"Loading ratings..."})]}):e.jsxs(e.Fragment,{children:[d&&e.jsxs("div",{className:"rating-summary-card",children:[e.jsxs("div",{className:"rating-score-display",children:[e.jsx("span",{className:"rating-average",children:d.averageScore.toFixed(1)}),_s(Math.round(d.averageScore))]}),e.jsxs("div",{className:"rating-stats",children:[e.jsxs("span",{className:"rating-count",children:[d.totalRatings," ratings"]}),e.jsx("span",{className:`rating-trend-badge ${ka(d.trend)}`,children:Sa(d.trend)})]})]}),d&&Object.keys(d.categoryAverages).length>0&&e.jsxs("div",{className:"category-breakdown",children:[e.jsx("h4",{children:"Category Averages"}),Object.entries(d.categoryAverages).map(([r,l])=>e.jsxs("div",{className:"category-item",children:[e.jsx("span",{className:"category-name",children:r}),e.jsx("span",{className:"category-score",children:l.toFixed(1)})]},r))]}),e.jsxs("form",{className:"add-rating-form",onSubmit:P,children:[e.jsx("h4",{children:"Add Rating"}),e.jsx("div",{className:"star-selector",children:[1,2,3,4,5].map(r=>e.jsx("button",{type:"button",className:"star-btn touch-target",onClick:()=>T(r),title:`${r} star${r>1?"s":""}`,children:e.jsx(dt,{size:24,fill:r<=C?"currentColor":"none",className:r<=C?"star-filled":"star-empty"})},r))}),e.jsxs("select",{value:j,onChange:r=>E(r.target.value),className:"select add-rating-category-select",children:[e.jsx("option",{value:"",children:"Select category..."}),e.jsx("option",{value:"quality",children:"Quality"}),e.jsx("option",{value:"speed",children:"Speed"}),e.jsx("option",{value:"communication",children:"Communication"}),e.jsx("option",{value:"reliability",children:"Reliability"}),e.jsx("option",{value:"other",children:"Other"})]}),e.jsx("textarea",{value:V,onChange:r=>$(r.target.value),placeholder:"Optional comment...",className:"input add-rating-comment-input",rows:3}),e.jsx("button",{type:"submit",className:"btn btn-task-create",disabled:C===0||J,children:J?"Submitting...":"Submit Rating"})]}),e.jsxs("div",{className:"rating-history",children:[e.jsx("h4",{children:"Rating History"}),k.length===0?e.jsx("p",{className:"no-ratings",children:"No ratings yet"}):k.map(r=>e.jsxs("div",{className:"rating-history-item",children:[e.jsxs("div",{className:"rating-item-header",children:[_s(r.score),r.category&&e.jsx("span",{className:"rating-category-badge",children:r.category}),e.jsx("span",{className:"rating-time",children:Us(r.createdAt)}),e.jsx("button",{type:"button",className:"rating-delete-btn touch-target",onClick:()=>void O(r.id),title:"Delete rating",children:e.jsx(rs,{size:14})})]}),r.comment&&e.jsx("p",{className:"rating-comment",children:r.comment})]},r.id))]})]})]}),e.jsxs("div",{className:"reflections-list",children:[e.jsx("h4",{children:"Reflection History"}),c?e.jsxs("div",{className:"reflections-loading-indicator",children:[e.jsx(B,{size:16,className:"animate-spin"}),e.jsx("span",{className:"text-muted",children:"Loading reflections..."})]}):o.length===0?e.jsxs("div",{className:"reflection-empty",children:[e.jsx(ms,{size:32,opacity:.3}),e.jsx("p",{children:"No reflections yet"}),e.jsx("p",{className:"text-secondary",children:"Trigger a reflection to get started"})]}):e.jsx("div",{className:"reflection-cards",children:o.map(r=>{const l=K===r.id;return e.jsxs("div",{className:`reflection-card ${l?"reflection-card--expanded":""}`,onClick:()=>f(r.id),role:"button",tabIndex:0,onKeyDown:p=>p.key==="Enter"&&f(r.id),children:[e.jsxs("div",{className:"reflection-card-header",children:[e.jsx("span",{className:`reflection-trigger-badge reflection-trigger-${r.trigger}`,children:ya(r.trigger)}),e.jsx("span",{className:"reflection-timestamp",children:Us(r.timestamp)}),e.jsx("span",{className:"reflection-chevron",children:l?e.jsx(qs,{size:16}):e.jsx(Gs,{size:16})})]}),e.jsx("div",{className:"reflection-summary",children:r.summary}),l&&e.jsxs("div",{className:"reflection-details",children:[r.insights.length>0&&e.jsxs("div",{className:"reflection-insights",children:[e.jsxs("h5",{children:[e.jsx(ms,{size:14})," Insights"]}),e.jsx("ul",{children:r.insights.map((p,se)=>e.jsx("li",{children:p},se))})]}),r.suggestedImprovements.length>0&&e.jsxs("div",{className:"reflection-suggestions",children:[e.jsxs("h5",{children:[e.jsx(Ds,{size:14})," Suggested Improvements"]}),e.jsx("ul",{children:r.suggestedImprovements.map((p,se)=>e.jsx("li",{children:p},se))})]}),r.metrics&&e.jsxs("div",{className:"reflection-metrics",children:[e.jsx("h5",{children:"Metrics"}),e.jsxs("div",{className:"metrics-grid",children:[r.metrics.tasksCompleted!==void 0&&e.jsxs("div",{className:"metric",children:[e.jsx("span",{className:"metric-label",children:"Tasks:"}),e.jsx("span",{className:"metric-value",children:r.metrics.tasksCompleted})]}),r.metrics.tasksFailed!==void 0&&e.jsxs("div",{className:"metric",children:[e.jsx("span",{className:"metric-label",children:"Failed:"}),e.jsx("span",{className:"metric-value",children:r.metrics.tasksFailed})]}),r.metrics.avgDurationMs!==void 0&&e.jsxs("div",{className:"metric",children:[e.jsx("span",{className:"metric-label",children:"Avg Duration:"}),e.jsx("span",{className:"metric-value",children:Is(r.metrics.avgDurationMs)})]}),r.metrics.errorCount!==void 0&&e.jsxs("div",{className:"metric",children:[e.jsx("span",{className:"metric-label",children:"Errors:"}),e.jsx("span",{className:"metric-value",children:r.metrics.errorCount})]})]})]})]})]},r.id)})})]})]})}function ae(...s){return s.filter(Boolean).join(" ")}function $e(s){const n=Date.now(),i=new Date(s).getTime(),o=n-i;if(o<0){const u=Math.abs(o);return u<6e4?"in a moment":u<36e5?`in ${Math.floor(u/6e4)}m`:u<864e5?`in ${Math.floor(u/36e5)}h`:`in ${Math.floor(u/864e5)}d`}return o<6e4?"just now":o<36e5?`${Math.floor(o/6e4)}m ago`:o<864e5?`${Math.floor(o/36e5)}h ago`:`${Math.floor(o/864e5)}d ago`}const wa=[{id:"dashboard",label:"Dashboard",icon:va},{id:"logs",label:"Logs",icon:Ve},{id:"mail",label:"Mail",icon:Lt},{id:"runs",label:"Runs",icon:ns},{id:"tasks",label:"Tasks",icon:st},{id:"employees",label:"Employees",icon:tt},{id:"soul",label:"Soul",icon:$t},{id:"instructions",label:"Instructions",icon:Dt},{id:"memory",label:"Agent Memory",icon:Ve},{id:"reflections",label:"Evaluation",icon:is},{id:"config",label:"Settings",icon:zt}],Ss={idle:{bg:"var(--state-idle-bg)",text:"var(--state-idle-text)",border:"var(--state-idle-border)"},active:{bg:"var(--state-active-bg)",text:"var(--state-active-text)",border:"var(--state-active-border)"},running:{bg:"var(--state-active-bg)",text:"var(--state-active-text)",border:"var(--state-active-border)"},paused:{bg:"var(--state-paused-bg)",text:"var(--state-paused-text)",border:"var(--state-paused-border)"},error:{bg:"var(--state-error-bg)",text:"var(--state-error-text)",border:"var(--state-error-border)"}},ls={completed:{icon:de,color:"var(--color-success)"},failed:{icon:Jt,color:"var(--color-error)"},active:{icon:B,color:"var(--in-progress)"},terminated:{icon:Le,color:"var(--text-muted)"}},Vs={"long-term":"Long-term",daily:"Daily",dreams:"Dreams"},Ra={"long-term":"Curated durable decisions, conventions, constraints, and pitfalls for this specific agent.",daily:"Raw daily observations and open loops recorded by this agent.",dreams:"Synthesized patterns and emerging themes distilled from this agent's daily memory."},Ma=rt(js),Fa=700;function Aa(s,n){return s.some(i=>i.path===n)?n:s.find(i=>i.layer==="long-term")?.path??s[0]?.path??""}function Qa({agentId:s,projectId:n,onClose:i,addToast:o,onChildClick:u,inline:g=!1,showInlineBackButton:R=!1,initialTab:d,initialRunId:M,preferActiveRun:k=!1,onMutationSuccess:F}){const[c,x]=t.useState(null),{confirm:A}=Ys(),[z,N]=t.useState([]),[y,J]=t.useState(!0),[m,K]=t.useState(d??"dashboard"),[ee,C]=t.useState(!1),[T,j]=t.useState(!1),[E,V]=t.useState(null),[$,q]=t.useState(null),[w,Q]=t.useState(!1),[P,O]=t.useState(null),f=t.useRef(null),b=t.useRef(!1);At(f,!g,"fusion:agent-detail-modal-size");const r=t.useRef(i),l=t.useRef(o),p=t.useRef(null),se=t.useRef(!1),L=t.useRef(null),Y=t.useRef(0),ie=t.useRef(s),xe=t.useRef(n);r.current=i,l.current=o,p.current=c;const W=t.useCallback(async()=>{p.current===null&&J(!0);try{const I=await Tt(s,n);x(I)}catch(I){l.current(`Failed to load agent: ${G(I)}`,"error"),r.current()}finally{J(!1)}},[s,n]),H=t.useCallback(async()=>{const v=Y.current,I=s,X=n,ne=()=>Y.current!==v||s!==I||n!==X;try{if(c?.taskId){V(null),L.current=null;const Se=await Et(c.taskId,X,{limit:100});if(ne())return;N(Se.entries);return}const re=await Ks(I,1,X);if(ne())return;const he=re[0]??null;if(V(he),!he){L.current=null,N([]);return}if(L.current===he.id)return;const ye=await Zs(I,he.id,X);if(ne())return;N(ye),L.current=he.id}catch(re){if(ne())return;console.error("Failed to load agent logs:",re)}},[c?.taskId,s,n]),te=t.useCallback(async()=>{Q(!0),O(null);try{const v=await Pt(s,n);q(v)}catch(v){O(G(v)),q(null)}finally{Q(!1)}},[s,n]),De=t.useCallback(v=>{se.current=v},[]),Ne=t.useCallback(async(v=!1)=>{await F?.({agentId:s,deleted:v})},[s,F]),Re=t.useCallback(async()=>{await W(),await Ne(!1)},[W,Ne]);t.useEffect(()=>{W()},[W]),t.useEffect(()=>{const v=setInterval(()=>{W()},3e4);return()=>{clearInterval(v)}},[W]),t.useEffect(()=>{c&&m==="logs"&&H()},[c,m,H]),t.useEffect(()=>{m!=="logs"&&(L.current=null)},[m]),t.useEffect(()=>{c&&m==="mail"&&te()},[c,m,te]),t.useEffect(()=>{if(m!=="logs"||c?.taskId||!E||E.status!=="active")return;const v=Y.current,I=s,X=E.id,ne=n?`?projectId=${encodeURIComponent(n)}`:"",re=as(`/api/agents/${encodeURIComponent(I)}/runs/${encodeURIComponent(X)}/logs/stream${ne}`,{events:{"agent:log":he=>{if(Y.current===v)try{const ye=JSON.parse(he.data);N(Se=>[...Se,ye])}catch{}}},onOpen:()=>{Y.current===v&&C(!0)},onError:()=>{Y.current===v&&C(!1)}});return()=>{re(),Y.current===v&&C(!1)}},[m,c?.taskId,s,n,E]),t.useEffect(()=>{(ie.current!==s||xe.current!==n)&&(ie.current=s,xe.current=n,Y.current++,N([]),C(!1),V(null),q(null),O(null),L.current=null,se.current=!1)},[s,n]),t.useEffect(()=>{const v=n?`?projectId=${encodeURIComponent(n)}`:"",I=Y.current,X=ne=>{if(Y.current===I)try{const re=JSON.parse(ne.data);if(!re||typeof re!="object"||re.agentId!==s)return;W()}catch{}};return as(`/api/events${v}`,{events:{"agent:updated":ne=>{if(Y.current===I)try{const re=JSON.parse(ne.data);if(!re||typeof re!="object"||re.id!==s||se.current)return;W()}catch{}},"approval:requested":X,"approval:updated":X,"approval:decided":X}})},[s,n,W]),t.useEffect(()=>{if(m!=="logs"||!c?.taskId){C(!1);return}const v=Y.current,I=c.taskId,X=n?`?projectId=${encodeURIComponent(n)}`:"",ne=as(`/api/tasks/${encodeURIComponent(I)}/logs/stream${X}`,{events:{"agent:log":re=>{if(Y.current===v)try{const he=JSON.parse(re.data);N(ye=>[...ye,he])}catch{}}},onOpen:()=>{Y.current===v&&C(!0)},onError:()=>{Y.current===v&&C(!1)}});return()=>{ne(),Y.current===v&&C(!1)}},[c?.taskId,m,n]);const oe=async v=>{if(T||!p.current)return;const I=p.current.state;if(I!==v){j(!0),x(X=>X&&{...X,state:v});try{await Bt(s,v,n),o(`Agent state updated to ${v}`,"success"),await Re()}catch(X){x(ne=>ne&&{...ne,state:I}),o(`Failed to update state: ${G(X)}`,"error")}finally{j(!1)}}},Ee=async()=>{if(!(!c||!await A({title:"Delete Agent",message:`Delete agent "${c.name}"? This cannot be undone.`,danger:!0})))try{await It(s,n),o(`Agent "${c.name}" deleted`,"success"),await Ne(!0),i()}catch(I){o(`Failed to delete agent: ${G(I)}`,"error")}},cs=()=>c?Ot(c):{label:"Unknown",icon:e.jsx(ys,{size:14}),color:"var(--text-muted)",stateDerived:!1},Ye=()=>{c&&(navigator.clipboard.writeText(c.id),o("Agent ID copied to clipboard","success"))};if(y)return g?e.jsx("div",{className:"agent-detail-inline-loading",role:"region","aria-label":"Agent detail loading",children:e.jsxs("div",{className:"agent-detail-loading",children:[e.jsx(B,{className:"animate-spin",size:24}),e.jsx("span",{children:"Loading agent..."})]})}):e.jsx("div",{className:"agent-detail-overlay",onMouseDown:v=>{v.target===v.currentTarget&&(b.current=!0)},onMouseUp:v=>{b.current&&v.target===v.currentTarget&&i(),b.current=!1},role:"dialog","aria-modal":"true",children:e.jsx("div",{className:"agent-detail-modal",ref:f,children:e.jsxs("div",{className:"agent-detail-loading",children:[e.jsx(B,{className:"animate-spin",size:24}),e.jsx("span",{children:"Loading agent..."})]})})});if(!c)return null;const ze=Ss[c.state],be=cs(),Me=g?"agent-detail-inline":"agent-detail-modal";return e.jsx("div",{className:g?"agent-detail-inline-shell":"agent-detail-overlay",onClick:v=>!g&&v.target===v.currentTarget&&i(),role:g?"region":"dialog","aria-label":g?"Agent detail":void 0,"aria-modal":g?void 0:"true",children:e.jsxs("div",{className:Me,ref:f,children:[e.jsxs("div",{className:"agent-detail-header",children:[e.jsxs("div",{className:"agent-detail-identity",children:[g&&R?e.jsxs("button",{type:"button",className:"btn agent-detail-inline-back",onClick:i,"aria-label":"Back to agents",children:[e.jsx(Qs,{size:16}),"Agents"]}):null,e.jsx("div",{className:"agent-detail-icon",children:e.jsx(Xs,{agent:c,size:36})}),e.jsxs("div",{className:"agent-detail-info",children:[e.jsx("h2",{children:c.name}),e.jsxs("div",{className:"agent-detail-badges",children:[e.jsx("span",{className:"badge",style:{background:ze.bg,color:ze.text,border:`1px solid ${ze.border}`},children:c.state}),e.jsxs("span",{className:"badge",style:{color:be.color},title:be.reason??be.label,children:[be.icon,!be.stateDerived&&be.label]})]})]})]}),e.jsxs("div",{className:"agent-detail-header-actions",children:[e.jsxs("div",{className:"agent-detail-controls",children:[c.state==="idle"&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn-task-create btn--compact",onClick:()=>void oe("active"),disabled:T,children:[e.jsx(hs,{size:14}),"Start"]}),e.jsxs("button",{className:"btn btn--danger btn--compact",onClick:Ee,children:[e.jsx(rs,{size:14}),"Delete"]})]}),c.state==="active"&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn--compact agent-detail-mobile-icon-control",onClick:()=>void oe("paused"),disabled:T,"aria-label":"Pause",children:[e.jsx(zs,{size:14}),e.jsx("span",{className:"agent-detail-control-label",children:"Pause"})]}),e.jsxs("button",{className:"btn btn--danger btn--compact",onClick:()=>void oe("paused"),disabled:T,children:[e.jsx(Le,{size:14}),"Stop"]})]}),c.state==="paused"&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn-task-create btn--compact agent-detail-mobile-icon-control",onClick:()=>void oe("active"),disabled:T,"aria-label":"Resume",children:[e.jsx(hs,{size:14}),e.jsx("span",{className:"agent-detail-control-label",children:"Resume"})]}),e.jsxs("button",{className:"btn btn--danger btn--compact",onClick:Ee,children:[e.jsx(rs,{size:14}),"Delete"]})]}),c.state==="running"&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn--compact agent-detail-mobile-icon-control",onClick:()=>void oe("paused"),disabled:T,"aria-label":"Pause",children:[e.jsx(zs,{size:14}),e.jsx("span",{className:"agent-detail-control-label",children:"Pause"})]}),e.jsxs("button",{className:"btn btn--danger btn--compact",onClick:()=>void oe("paused"),disabled:T,children:[e.jsx(Le,{size:14}),"Stop"]})]}),c.state==="error"&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn-task-create btn--compact",onClick:()=>void oe("active"),disabled:T,children:[e.jsx(hs,{size:14}),"Retry"]}),e.jsxs("button",{className:"btn btn--danger btn--compact",onClick:()=>void oe("paused"),disabled:T,children:[e.jsx(Le,{size:14}),"Stop"]})]})]}),e.jsxs("div",{className:"agent-detail-utility-actions",children:[e.jsx("button",{className:"btn-icon",onClick:()=>void W(),title:"Refresh","aria-label":"Refresh",children:e.jsx(os,{size:16})}),!g&&e.jsx("button",{className:"btn-icon",onClick:i,"aria-label":"Close",title:"Close",children:e.jsx(et,{size:20})})]})]})]}),e.jsx("div",{className:"agent-detail-tabs",children:wa.map(v=>e.jsxs("button",{className:ae("agent-detail-tab",m===v.id&&"active"),onClick:()=>K(v.id),children:[e.jsx(v.icon,{size:16}),v.label]},v.id))}),e.jsxs("div",{className:"agent-detail-content",children:[m==="dashboard"&&e.jsx(Ta,{agent:c,health:be,onChildClick:u,projectId:n}),m==="logs"&&e.jsx(Ea,{logs:z,isStreaming:ee,hasTask:!!c.taskId||z.length>0||E!==null,fallbackLabel:!c.taskId&&E?`Latest run · ${E.id.slice(0,8)}`:null}),m==="mail"&&e.jsx(La,{agent:c,mailbox:$,isLoading:w,error:P,projectId:n,addToast:o,onRefresh:()=>void te()}),m==="runs"&&e.jsx($a,{addToast:o,agentId:c.id,projectId:n,agentState:c.state,agentName:c.name,initialRunId:M,preferActiveRun:k}),m==="tasks"&&e.jsx(Oa,{agentId:c.id,projectId:n,addToast:o}),m==="employees"&&e.jsx(Wa,{agentId:c.id,projectId:n,onChildClick:u}),m==="soul"&&e.jsx(Ia,{agent:c,projectId:n,addToast:o,onSaved:Re}),m==="instructions"&&e.jsx(_a,{agent:c,projectId:n,addToast:o,onSaved:Re}),m==="memory"&&e.jsx(Ua,{agent:c,projectId:n,addToast:o,onSaved:Re}),m==="reflections"&&e.jsx(Ca,{agentId:c.id,projectId:n,addToast:o}),m==="config"&&e.jsx(Ja,{agent:c,projectId:n,addToast:o,onSaved:Re,onHasChangesChange:De,onDelete:Ee,onAgentDraftApplied:v=>{x(I=>I&&{...I,...v})}},c.id)]}),!g&&e.jsxs("div",{className:"agent-detail-footer",children:[e.jsx("button",{className:"btn-icon",onClick:Ye,title:"Copy Agent ID",children:e.jsx(Ht,{})}),e.jsx("span",{className:"agent-detail-id",onClick:Ye,children:c.id}),c.taskId&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"divider",children:"|"}),e.jsx("span",{className:"text-muted",children:"Working on:"}),e.jsxs("a",{href:`/tasks/${c.taskId}`,className:"link",children:[c.taskId,e.jsx(at,{size:12})]})]})]})]})})}function Ta({agent:s,health:n,onChildClick:i,projectId:o}){const u=Ss[s.state],[g,R]=t.useState([]),[d,M]=t.useState(!0),[k,F]=t.useState(null),[c,x]=t.useState([]),[A,z]=t.useState(null),[N,y]=t.useState(null),[J,m]=t.useState(!1),[K,ee]=t.useState(null),C=typeof s.runtimeConfig?.runtimeHint=="string"?s.runtimeConfig.runtimeHint:"",T=(()=>{const f=s.runtimeConfig??{};if(C){const b=c.find(r=>r.runtimeId===C);return b?b.name:C}if(f.modelProvider&&f.modelId)return`${f.modelProvider}/${f.modelId}`;if(typeof f.model=="string"&&f.model.includes("/")){const b=f.model.indexOf("/");return f.model.slice(b+1)}return null})();t.useEffect(()=>{ps(s.id,o).then(F).catch(()=>F(null))},[s.id,o]),t.useEffect(()=>{nt(o).then(x).catch(()=>x([]))},[o]),t.useEffect(()=>{let f=!1;return M(!0),Ut(s.id,o).then(b=>{if(f)return;const r=b.length>0&&b[0]?.id===s.id?[...b].reverse():b;R(r)}).catch(()=>{f||R([])}).finally(()=>{f||M(!1)}),()=>{f=!0}},[s.id,o]);const j=t.useMemo(()=>{const f=s.completedRuns||[],b=new Date;b.setHours(0,0,0,0);const r=f.filter(p=>new Date(p.startedAt)>=b),l=f.filter(p=>p.status==="completed");return{totalRuns:f.length,todayRuns:r.length,successfulRuns:l.length,successRate:f.length>0?Math.round(l.length/f.length*100):0}},[s]),E=(s.completedRuns||[]).slice(0,5),V=Array.isArray(s.metadata?.skills)?s.metadata.skills:[],$=A?fs(A):null,q=t.useCallback(async f=>{m(!0),ee(null),y(null);try{const b=await _t(f,o);y(b)}catch(b){ee(G(b))}finally{m(!1)}},[o]),w=t.useCallback(f=>{if(A===f){z(null),y(null),ee(null),m(!1);return}z(f),q(f)},[q,A]),Q=s.state==="active"||s.state==="running",P=Vt(s.runtimeConfig?.heartbeatIntervalMs),O=Q&&s.lastHeartbeatAt?new Date(new Date(s.lastHeartbeatAt).getTime()+P).toISOString():null;return e.jsxs("div",{className:"dashboard-tab dashboard-summary-layout",children:[k?.isOverBudget&&e.jsxs("div",{className:"budget-warning-banner",role:"alert",children:[e.jsx("span",{children:"⚠️"}),e.jsxs("span",{children:[e.jsx("strong",{children:"Budget Exhausted:"})," This agent has exceeded its token budget and may operate with limited functionality."]})]}),e.jsxs("section",{className:"dashboard-summary-card dashboard-summary-hero",children:[e.jsxs("div",{className:"dashboard-summary-hero__heading",children:[e.jsx(ys,{}),e.jsx("h3",{children:"Overview"}),e.jsx("strong",{children:s.name}),e.jsx("span",{className:"inline-badge",style:{background:u.bg,color:u.text},children:s.state})]}),e.jsxs("div",{className:"dashboard-summary-hero__meta",children:[e.jsxs("span",{className:"dashboard-summary-hero__health",title:n.reason??n.label,children:[n.icon," ",n.label]}),(s.pendingApprovalCount??0)>0?e.jsxs("span",{className:"badge agent-detail-approval-badge",title:"Pending approvals",children:[e.jsx("span",{className:"status-dot status-dot--pending"}),s.pendingApprovalCount," pending approvals"]}):null,e.jsxs("span",{children:["Role: ",s.role]}),e.jsxs("span",{children:[e.jsx("span",{className:"dashboard-summary-label",children:C?"Runtime":"Model"}),e.jsxs("span",{children:[" ",T??"Auto"]})]}),V.length>0?e.jsxs("span",{className:"dashboard-summary-skills",children:[e.jsx("span",{className:"dashboard-summary-label",children:"Skills"}),e.jsx("span",{className:"dashboard-summary-skill-badges",role:"list","aria-label":"Assigned skills",children:V.map(f=>{const b=A===f;return e.jsx("button",{type:"button",className:ae("badge","badge-skill","dashboard-summary-skill-badge","dashboard-summary-skill-badge-btn",b&&"dashboard-summary-skill-badge--selected"),title:f,onClick:()=>w(f),"aria-expanded":b,"aria-label":`View details for ${fs(f)}`,children:fs(f)},f)})})]}):e.jsx("span",{children:"Skills: —"})]}),A?e.jsxs("div",{className:"dashboard-summary-skill-detail","data-testid":"agent-skill-detail",children:[e.jsxs("div",{className:"dashboard-summary-skill-detail-header",children:[e.jsx("span",{className:"dashboard-summary-skill-detail-title",children:$}),e.jsxs("button",{type:"button",className:"btn btn-sm",onClick:()=>w(A),children:[e.jsx(et,{size:14}),"Close"]})]}),J?e.jsxs("div",{className:"dashboard-summary-skill-detail-loading",role:"status","aria-live":"polite",children:[e.jsx(B,{size:14,className:"animate-spin"}),"Loading skill content..."]}):K?e.jsxs("div",{className:"dashboard-summary-skill-detail-error",role:"alert",children:[e.jsx(it,{size:14}),e.jsx("span",{children:K}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void q(A),children:"Retry"})]}):N?e.jsx("pre",{className:"dashboard-summary-skill-detail-content",children:N.skillMd||"(No SKILL.md found)"}):e.jsx("div",{className:"dashboard-summary-skill-detail-empty",children:"No skill content available"})]}):null]}),e.jsxs("section",{className:"dashboard-summary-card",children:[e.jsx("h3",{children:"Heartbeat & Health"}),e.jsxs("div",{className:"dashboard-summary-grid",children:[e.jsxs("div",{children:[e.jsx("p",{className:"dashboard-summary-label",children:"Last heartbeat"}),e.jsx("p",{children:s.lastHeartbeatAt?$e(s.lastHeartbeatAt):"Never"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"dashboard-summary-label",children:"Next expected"}),e.jsx("p",{children:O?$e(O):"Not scheduled"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"dashboard-summary-label",children:"Interval"}),e.jsx("p",{children:rt(P)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"dashboard-summary-label",children:"Status"}),e.jsxs("p",{className:"dashboard-summary-health-row",children:[e.jsx("span",{className:ae("status-dot",s.state==="running"&&"status-dot--running")}),n.label,n.reason&&e.jsxs("span",{className:"text-secondary dashboard-summary-health-reason",title:n.reason,children:["(",n.reason,")"]})]})]})]})]}),e.jsxs("section",{className:"dashboard-summary-card",children:[e.jsx("h3",{children:"Current Work"}),s.taskId?e.jsxs("div",{className:"current-task",children:[e.jsx("a",{href:`/tasks/${s.taskId}`,className:"task-badge",children:s.taskId}),e.jsxs("a",{href:`/tasks/${s.taskId}`,className:"btn btn-sm",children:["View Task ",e.jsx(at,{size:14})]})]}):e.jsx("p",{className:"text-muted",children:"No active assignment"})]}),e.jsxs("section",{className:"dashboard-summary-card",children:[e.jsx("h3",{children:"Recent Runs"}),e.jsxs("p",{className:"dashboard-summary-label",children:[j.successfulRuns,"/",j.totalRuns," successful (",j.successRate,"%)"]}),E.length===0?e.jsx("p",{className:"text-muted",children:"No runs yet"}):e.jsx("div",{className:"runs-list",children:E.map(f=>{const b=ls[f.status]||ls.terminated,r=b.icon;return e.jsxs("div",{className:"run-item",children:[e.jsx(r,{size:14,style:{color:b.color}}),e.jsx("span",{children:$e(f.startedAt)}),e.jsxs("span",{className:"text-muted",children:[Math.max(0,Math.round((new Date(f.endedAt||f.startedAt).getTime()-new Date(f.startedAt).getTime())/1e3)),"s"]})]},f.id)})})]}),e.jsxs("section",{className:"dashboard-summary-card",children:[e.jsx("h3",{children:"Throughput"}),e.jsxs("div",{className:"stats-grid",children:[e.jsxs("div",{className:"stat-card",children:[e.jsx("div",{className:"stat-value",children:j.totalRuns}),e.jsx("div",{className:"stat-label",children:"Total Runs"})]}),e.jsxs("div",{className:"stat-card",children:[e.jsx("div",{className:"stat-value",children:j.todayRuns}),e.jsx("div",{className:"stat-label",children:"Runs Today"})]}),e.jsxs("div",{className:"stat-card",children:[e.jsxs("div",{className:"stat-value",children:[j.successRate,"%"]}),e.jsx("div",{className:"stat-label",children:"Success Rate"})]})]})]}),e.jsxs("section",{className:"dashboard-summary-card",children:[e.jsx("h3",{children:"Chain of Command"}),d?e.jsxs("div",{className:"chain-of-command-loading",role:"status","aria-live":"polite",children:[e.jsx(B,{size:14,className:"animate-spin"}),e.jsx("span",{children:"Loading reporting chain..."})]}):g.length<=1?e.jsx("p",{className:"text-muted",children:"No reporting chain"}):e.jsx("div",{className:"chain-of-command-path","aria-label":"Chain of command",children:g.map((f,b)=>{const r=b===g.length-1,l=!r;return e.jsxs("div",{className:"chain-of-command-item",children:[e.jsx("button",{type:"button",className:`chain-of-command-node${r?" chain-of-command-node--current":""}`,onClick:()=>l&&i?.(f.id),disabled:!l||!i,title:r?"Current agent":`View ${f.name}`,children:f.name}),!r&&e.jsx("span",{className:"chain-of-command-separator","aria-hidden":"true",children:"→"})]},f.id)})})]})]})}function Ea({logs:s,isStreaming:n,hasTask:i,fallbackLabel:o}){return i?e.jsxs("div",{className:"logs-tab",children:[e.jsxs("div",{className:"logs-header",children:[e.jsxs("span",{className:"logs-count",children:[s.length," entries"]}),o&&e.jsx("span",{className:"text-muted logs-fallback-label",children:o}),n&&e.jsxs("span",{className:"streaming-indicator",children:[e.jsx("span",{className:"streaming-dot"}),"Live"]})]}),s.length===0?e.jsxs("div",{className:"logs-empty",children:[e.jsx(Ve,{size:48,opacity:.3}),e.jsx("p",{children:"No log entries yet"}),e.jsx("p",{className:"text-muted",children:n?"Waiting for activity...":"Logs will appear here when the agent is active"})]}):e.jsx(lt,{entries:s,loading:!1})]}):e.jsx("div",{className:"logs-tab",children:e.jsxs("div",{className:"logs-empty",children:[e.jsx(Ve,{size:48,opacity:.3}),e.jsx("p",{children:"No activity yet"}),e.jsx("p",{className:"text-muted",children:"Agent logs will appear here from the current task or most recent run"})]})})}function Pa(s){const n=new Date(s),o=new Date().getTime()-n.getTime(),u=Math.floor(o/6e4),g=Math.floor(o/36e5),R=Math.floor(o/864e5);return u<1?"Just now":u<60?`${u}m ago`:g<24?`${g}h ago`:R<7?`${R}d ago`:n.toLocaleDateString(void 0,{month:"short",day:"numeric"})}function ts(s,n){return n==="user"?s==="dashboard"?"You":`User: ${s}`:n==="agent"?`Agent: ${s}`:"System"}function La({agent:s,mailbox:n,isLoading:i,error:o,projectId:u,addToast:g,onRefresh:R}){const[d,M]=t.useState("inbox"),[k,F]=t.useState(null),c=d==="inbox"?n?.inbox??[]:n?.outbox??[],x=k?c.find(y=>y.id===k)??null:null;t.useEffect(()=>{F(null)},[d,s.id]);const A=async y=>{if(F(y.id),!(d!=="inbox"||y.read))try{await ma(y.id,u),R()}catch(J){const m=`Failed to mark message as read: ${G(J)}`;g?g(m,"error"):console.warn(m)}},z=()=>{F(null),R()},N=y=>e.jsxs("button",{type:"button",className:ae("mailbox-item","agent-mail-tab-message",d==="inbox"&&!y.read&&"unread",k===y.id&&"agent-mail-tab-message--selected"),onClick:()=>void A(y),"aria-pressed":k===y.id,children:[e.jsx("div",{className:"mailbox-item-avatar",children:(d==="inbox"?y.fromType:y.toType)==="agent"?e.jsx(ys,{size:16}):e.jsx(aa,{size:16})}),e.jsxs("div",{className:"mailbox-item-content",children:[e.jsxs("div",{className:"mailbox-item-header",children:[d==="inbox"?e.jsx("span",{className:"mailbox-item-from",children:ts(y.fromId,y.fromType)}):e.jsxs("span",{className:"mailbox-item-to",children:["To: ",ts(y.toId,y.toType)]}),e.jsx("span",{className:"mailbox-item-time",children:Pa(y.createdAt)})]}),e.jsxs("div",{className:"mailbox-item-preview",children:[y.content.slice(0,80),y.content.length>80?"…":""]})]}),d==="inbox"&&!y.read?e.jsx("div",{className:"mailbox-item-unread-dot","aria-label":"Unread message"}):null]},y.id);return e.jsxs("div",{className:"agent-mail-tab",children:[e.jsxs("div",{className:"agent-mail-tab-header",children:[e.jsxs("h3",{children:[s.name," Mail"]}),e.jsxs("button",{className:"btn btn-sm",onClick:z,disabled:i,children:[e.jsx(os,{size:14}),"Refresh"]})]}),e.jsxs("div",{className:"mailbox-agent-subtabs","data-testid":"agent-detail-mail-subtabs",children:[e.jsxs("button",{className:ae("btn","btn-sm","btn-secondary","mailbox-agent-subtab",d==="inbox"&&"active"),onClick:()=>M("inbox"),children:[e.jsx(Hs,{size:12}),e.jsx("span",{children:"Inbox"}),(n?.unreadCount??0)>0?e.jsx("span",{className:"mailbox-tab-badge",children:n?.unreadCount}):null]}),e.jsxs("button",{className:ae("btn","btn-sm","btn-secondary","mailbox-agent-subtab",d==="outbox"&&"active"),onClick:()=>M("outbox"),children:[e.jsx(Os,{size:12}),e.jsx("span",{children:"Outbox"})]})]}),i&&!n?e.jsxs("div",{className:"agent-detail-loading agent-detail-loading--inline",role:"status","aria-live":"polite",children:[e.jsx(B,{className:"animate-spin",size:16}),e.jsx("span",{children:"Loading mailbox..."})]}):null,!i&&o?e.jsxs("div",{className:"agent-mail-tab-error",role:"alert",children:[e.jsx(it,{size:16}),e.jsxs("span",{children:["Failed to load mailbox: ",o]})]}):null,!i&&!o?x?e.jsxs("div",{className:"agent-mail-tab-detail","data-testid":"agent-detail-mail-message",children:[e.jsxs("button",{type:"button",className:"btn btn-sm agent-mail-tab-back","data-testid":"agent-detail-mail-back",onClick:()=>F(null),children:[e.jsx(Qs,{size:14}),"Back to ",d==="inbox"?"Inbox":"Outbox"]}),e.jsxs("div",{className:"agent-mail-tab-detail-meta",children:[e.jsxs("div",{className:"agent-mail-tab-detail-row",children:[e.jsx("span",{className:"agent-mail-tab-detail-label",children:"From"}),e.jsx("span",{children:ts(x.fromId,x.fromType)})]}),e.jsxs("div",{className:"agent-mail-tab-detail-row",children:[e.jsx("span",{className:"agent-mail-tab-detail-label",children:"To"}),e.jsx("span",{children:ts(x.toId,x.toType)})]}),e.jsxs("div",{className:"agent-mail-tab-detail-row",children:[e.jsx("span",{className:"agent-mail-tab-detail-label",children:"Type"}),e.jsx("span",{children:x.type})]}),e.jsxs("div",{className:"agent-mail-tab-detail-row",children:[e.jsx("span",{className:"agent-mail-tab-detail-label",children:"Sent"}),e.jsx("span",{children:new Date(x.createdAt).toLocaleString()})]}),x.metadata?.replyTo?.messageId?e.jsxs("div",{className:"agent-mail-tab-reply-context",children:["↪ Replying to message ",x.metadata.replyTo.messageId]}):null]}),e.jsx("div",{className:"agent-mail-tab-detail-body",children:x.content})]}):e.jsx("div",{className:"mailbox-list","data-testid":"agent-detail-mail-list",children:c.length===0?e.jsxs("div",{className:"mailbox-empty","data-testid":"agent-detail-mail-empty",children:[d==="inbox"?e.jsx(Hs,{size:32}):e.jsx(Os,{size:32}),e.jsx("p",{children:d==="inbox"?"No received messages for this agent":"No sent messages for this agent"})]}):c.map(N)}):null]})}function $a({addToast:s,agentId:n,projectId:i,agentState:o,agentName:u,initialRunId:g,preferActiveRun:R}){const[d,M]=t.useState([]),{confirm:k}=Ys(),[F,c]=t.useState(!0),[x,A]=t.useState(null),[z,N]=t.useState([]),[y,J]=t.useState(!1),[m,K]=t.useState(null),[ee,C]=t.useState(!1),T=t.useRef(!1),j=t.useCallback(async()=>{try{const l=await Ks(n,50,i);M(l)}catch(l){s(`Failed to load runs: ${G(l)}`,"error")}finally{c(!1)}},[n,i,s]);t.useEffect(()=>{j()},[j]);const E=d.some(l=>l.status==="active"),V=x?d.find(l=>l.id===x)?.status:void 0;t.useEffect(()=>{if(!E)return;const l=setInterval(()=>{j()},5e3);return()=>clearInterval(l)},[E,j]),t.useEffect(()=>{if(!x||V!=="active")return;const l=i?`?projectId=${encodeURIComponent(i)}`:"";return as(`/api/agents/${encodeURIComponent(n)}/runs/${encodeURIComponent(x)}/logs/stream${l}`,{events:{"agent:log":p=>{try{const se=JSON.parse(p.data);N(L=>[...L,se])}catch{}}}})},[x,V,n,i]);const $=t.useCallback(async l=>{if(x===l){A(null),N([]),K(null);return}A(l),J(!0),C(!0),N([]),K(null);try{const[p,se]=await Promise.all([Zs(n,l,i),Wt(n,l,i)]);N(p),K(se)}catch(p){s(`Failed to load run details: ${G(p)}`,"error"),N([]),K(null)}finally{J(!1),C(!1)}},[x,n,i,s]);t.useEffect(()=>{T.current=!1},[n,g,R]),t.useEffect(()=>{if(d.length===0||F||T.current)return;const l=g?d.find(p=>p.id===g):R?d.find(p=>p.status==="active"):null;T.current=!0,l&&$(l.id)},[g,R,d,F,$]);const q=async()=>{try{await na(n,i,{source:"on_demand",triggerDetail:"Triggered from dashboard"}),s(`Heartbeat run started for ${u??n}`,"success"),c(!0),j()}catch(l){s(`Failed to start heartbeat run: ${G(l)}`,"error")}},w=async()=>{if(await k({title:"Stop Active Run",message:"Stop the active run? The agent's work will be interrupted.",danger:!0}))try{await ia(n,i),s("Run stopped","success"),c(!0),j()}catch(p){s(`Failed to stop run: ${G(p)}`,"error")}},Q=o==="active"||o==="idle";if(F&&d.length===0)return e.jsx("div",{className:"runs-tab",children:e.jsxs("div",{className:"runs-loading-row",children:[e.jsx(B,{size:16,className:"animate-spin"}),e.jsx("span",{className:"text-muted",children:"Loading runs..."})]})});if(d.length===0)return e.jsxs("div",{className:"runs-tab",children:[Q&&e.jsx("div",{className:"runs-toolbar",children:e.jsxs("button",{className:"btn btn--sm btn-task-create",onClick:()=>void q(),"aria-label":`Run now for ${u??n}`,children:[e.jsx(ns,{size:14})," Run Now"]})}),e.jsxs("div",{className:"runs-empty",children:[e.jsx(ns,{size:48,opacity:.3}),e.jsx("p",{children:"No runs yet"}),e.jsx("p",{className:"text-muted",children:"Heartbeat runs will appear here"})]})]});const P=[...d].sort((l,p)=>new Date(p.startedAt).getTime()-new Date(l.startedAt).getTime()),O=P.filter(l=>l.status==="active"),f=P.filter(l=>l.status!=="active"),b=l=>l?e.jsxs("div",{className:"run-usage",children:[e.jsxs("span",{children:["Input: ",l.inputTokens.toLocaleString()]}),e.jsxs("span",{children:["Output: ",l.outputTokens.toLocaleString()]}),l.cachedTokens>0&&e.jsxs("span",{children:["Cached: ",l.cachedTokens.toLocaleString()]})]}):null,r=(l,p,se)=>{const L=ls[l.status]||ls.completed,Y=L.icon,ie=l.endedAt?Da(new Date(l.startedAt),new Date(l.endedAt)):"In progress",xe=x===l.id;return e.jsxs("div",{children:[e.jsxs("div",{className:ae("run-card",se&&"run-card--active",xe&&"run-card--selected","run-card--clickable"),onClick:()=>void $(l.id),role:"button",tabIndex:0,"aria-expanded":xe,"aria-label":`${se?"Active":""} run ${l.id.slice(0,8)}, ${l.status}`,onKeyDown:W=>{(W.key==="Enter"||W.key===" ")&&(W.preventDefault(),$(l.id))},children:[e.jsxs("div",{className:"run-header",children:[e.jsxs("div",{className:"run-header-group",children:[xe?e.jsx(qs,{size:14}):e.jsx(Gs,{size:14}),se?e.jsxs("span",{className:"run-live-indicator",children:[e.jsx("span",{className:"live-dot"}),"Live Run"]}):e.jsxs("span",{className:"run-id",children:["#",p+1," ",l.id.slice(0,8)]})]}),e.jsxs("div",{className:"run-header-group",children:[l.invocationSource&&e.jsx("span",{className:"badge run-badge--compact",children:l.invocationSource}),se&&e.jsxs("button",{className:"btn btn--sm btn--danger",onClick:W=>{W.preventDefault(),W.stopPropagation(),w()},"aria-label":"Stop active run",children:[e.jsx(Le,{size:12})," Stop"]}),e.jsxs("span",{className:ae("run-status",l.status),children:[e.jsx(Y,{size:14,style:{color:L.color}}),l.status]}),l.heartbeatProcedureSource==="custom"&&e.jsx("span",{className:"badge run-badge--compact",children:"Heartbeat: custom"})]})]}),e.jsxs("div",{className:"run-details",children:[e.jsxs("span",{children:["Started ",$e(l.startedAt)]}),e.jsx("span",{children:"•"}),e.jsx("span",{children:ie}),l.triggerDetail&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"•"}),e.jsx("span",{className:"text-muted",children:l.triggerDetail})]})]})]}),xe&&e.jsxs("div",{className:"run-logs-container",children:[ee?e.jsxs("div",{className:"run-details-loading-state",children:[e.jsx(B,{size:14,className:"animate-spin"}),e.jsx("span",{className:"text-muted",children:"Loading details..."})]}):m&&e.jsxs("div",{className:"run-output-sections",children:[e.jsx("div",{className:"run-output-section",children:e.jsxs("details",{children:[e.jsx("summary",{className:"run-output-label run-output-summary",children:"System Prompt"}),m.systemPrompt?e.jsx("pre",{className:"run-output-panel",children:m.systemPrompt}):e.jsx("div",{className:"text-muted run-output-empty",children:"System prompt not captured for this run"})]})}),e.jsx("div",{className:"run-output-section",children:e.jsxs("details",{children:[e.jsx("summary",{className:"run-output-label run-output-summary",children:"Execution Prompt"}),m.executionPrompt?e.jsx("pre",{className:"run-output-panel",children:m.executionPrompt}):e.jsx("div",{className:"text-muted run-output-empty",children:"Execution prompt not captured for this run"})]})}),m.usageJson&&e.jsxs("div",{className:"run-output-section",children:[e.jsx("div",{className:"run-output-label",children:"Token Usage"}),b(m.usageJson)]}),m.stdoutExcerpt&&e.jsxs("div",{className:"run-output-section",children:[e.jsx("div",{className:"run-output-label",children:"Output"}),e.jsx("pre",{className:"run-output-panel",children:m.stdoutExcerpt.length>2e3?`${m.stdoutExcerpt.slice(0,2e3)}
|
|
17
|
-
|
|
18
|
-
... (truncated, ${m.stdoutExcerpt.length} chars total)`:m.stdoutExcerpt})]}),m.stderrExcerpt&&e.jsxs("div",{className:"run-output-section",children:[e.jsx("div",{className:"run-output-label run-output-label--error",children:"Errors"}),e.jsx(ra,{errorText:m.stderrExcerpt,summaryPrefix:"Run error",issueContext:{surface:"AgentDetailView runs",agentId:n,agentName:u,agentState:o,runId:m.id,taskId:void 0,timestamp:m.startedAt}})]}),m.resultJson&&e.jsxs("div",{className:"run-output-section",children:[e.jsx("div",{className:"run-output-label",children:"Result"}),e.jsx("pre",{className:"run-output-panel",children:JSON.stringify(m.resultJson,null,2)})]}),m.contextSnapshot&&Object.keys(m.contextSnapshot).length>0&&e.jsxs("div",{className:"run-output-section",children:[e.jsx("div",{className:"run-output-label",children:"Context"}),e.jsx("div",{className:"run-context-grid",children:Object.entries(m.contextSnapshot).map(([W,H])=>e.jsxs("span",{className:"run-context-item",children:[e.jsxs("span",{className:"text-muted",children:[W,":"]})," ",e.jsx("span",{children:String(H)})]},W))})]}),!m.stdoutExcerpt&&!m.stderrExcerpt&&!m.resultJson&&e.jsx("div",{className:"text-muted run-output-empty",children:"No output captured"})]}),e.jsxs("div",{className:"run-agent-logs-section",children:[e.jsx("div",{className:"run-output-label",children:"Agent Logs"}),y?e.jsxs("div",{className:"run-details-loading-state",children:[e.jsx(B,{size:14,className:"animate-spin"}),e.jsx("span",{className:"text-muted",children:"Loading logs..."})]}):z.length===0?e.jsx("div",{className:"text-muted run-output-empty",children:"No logs available for this run"}):e.jsx(lt,{entries:z,loading:!1})]})]})]},l.id)};return e.jsxs("div",{className:"runs-tab",children:[Q&&e.jsxs("div",{className:"runs-toolbar runs-toolbar--between",children:[e.jsxs("span",{className:"runs-toolbar-meta",children:[d.length," run",d.length!==1?"s":"",E&&e.jsxs("span",{className:"run-live-indicator run-live-indicator--with-margin",children:[e.jsx("span",{className:"live-dot"}),"Live"]})]}),e.jsxs("div",{className:"run-header-group",children:[E&&e.jsxs("button",{className:"btn btn--sm btn--danger",onClick:()=>void w(),"aria-label":`Stop active run for ${u??n}`,children:[e.jsx(Le,{size:14})," Stop Run"]}),e.jsxs("button",{className:"btn btn--sm btn-task-create",onClick:()=>void q(),"aria-label":`Run now for ${u??n}`,children:[e.jsx(ns,{size:14})," Run Now"]})]})]}),O.map((l,p)=>r(l,p,!0)),f.map((l,p)=>r(l,O.length+p,!1))]})}function Da(s,n){const i=Math.floor((n.getTime()-s.getTime())/1e3);return i<60?`${i}s`:i<3600?`${Math.floor(i/60)}m ${i%60}s`:`${Math.floor(i/3600)}h ${Math.floor(i%3600/60)}m`}const za={triage:"Triage",todo:"Todo","in-progress":"In Progress","in-review":"In Review",done:"Done",archived:"Archived"};function Ha(s){const n=s.title?.trim()||s.description?.trim()||s.id;return n.length>80?`${n.slice(0,77)}...`:n}function Oa({agentId:s,projectId:n,addToast:i}){const[o,u]=t.useState([]),[g,R]=t.useState(!0);return t.useEffect(()=>{let d=!1;return R(!0),qt(s,n).then(M=>{d||u(M)}).catch(M=>{d||(u([]),i(`Failed to load assigned tasks: ${G(M)}`,"error"))}).finally(()=>{d||R(!1)}),()=>{d=!0}},[s,n,i]),g?e.jsxs("div",{className:"agent-tasks-empty",children:[e.jsx(B,{size:16,className:"animate-spin"}),e.jsx("p",{children:"Loading assigned tasks..."})]}):o.length===0?e.jsxs("div",{className:"agent-tasks-empty",children:[e.jsx(st,{size:18}),e.jsx("p",{children:"No tasks assigned to this agent"})]}):e.jsx("div",{className:"agent-tasks-list",children:o.map(d=>e.jsxs("a",{className:"agent-task-item",href:`/tasks/${d.id}`,children:[e.jsxs("div",{className:"agent-task-row",children:[e.jsx("span",{className:"agent-task-id",children:d.id}),e.jsx("span",{className:`agent-task-column column-${d.column}`,children:za[d.column]})]}),e.jsx("div",{className:"agent-task-title",title:d.title||d.description||d.id,children:Ha(d)}),e.jsxs("div",{className:"agent-task-status",children:[d.status??"idle"," · Updated ",$e(d.updatedAt)]})]},d.id))})}const _e=[{key:"maxRetries",label:"Max Retries",type:"number",placeholder:"3",hint:"Maximum number of automatic retries on task failure (0–10, default 3)",min:0,max:10},{key:"timeoutMs",label:"Task Timeout (ms)",type:"number",placeholder:"600000",hint:"Maximum time in ms before a task is considered timed out (minimum 60000ms, default 600000ms)",min:6e4,max:864e5},{key:"logLevel",label:"Log Level",type:"select",hint:"Verbosity of agent log output",options:[{value:"debug",label:"Debug"},{value:"info",label:"Info"},{value:"warn",label:"Warning"},{value:"error",label:"Error"}]}];function Ba(s){const n={};for(const i of _e){const o=s[i.key]?.trim();if(o){if(i.type==="number"){const u=Number(o);if(Number.isNaN(u)||!Number.isFinite(u)){n[i.key]=`"${i.label}" must be a valid number`;continue}i.min!==void 0&&u<i.min&&(n[i.key]=`"${i.label}" must be at least ${i.min.toLocaleString()}`),i.max!==void 0&&u>i.max&&(n[i.key]=`"${i.label}" must be at most ${i.max.toLocaleString()}`)}if(i.type==="select"){const u=i.options?.map(g=>g.value)??[];u.length>0&&!u.includes(o)&&(n[i.key]=`"${i.label}" must be one of: ${u.join(", ")}`)}}}return n}function Ia({agent:s,projectId:n,addToast:i,onSaved:o}){const[u,g]=t.useState(s.soul??""),[R,d]=t.useState(!1),[M,k]=t.useState(!1),[F,c]=t.useState(!1),x=t.useRef(null);t.useEffect(()=>{g(s.soul??""),k(!1),c(!1)},[s.id,s.soul]),t.useEffect(()=>()=>{x.current&&clearTimeout(x.current)},[]);const A=u!==(s.soul??""),z=async()=>{if(u.length>1e4){i("Soul must be at most 10,000 characters","error");return}d(!0);try{await la(s.id,u,n),i("Soul saved","success"),k(!0),x.current&&clearTimeout(x.current),x.current=setTimeout(()=>k(!1),3e3),await o()}catch(N){i(`Failed to save soul: ${G(N)}`,"error")}finally{d(!1)}};return e.jsx("div",{className:"config-tab",children:e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Soul"}),e.jsx("p",{className:"config-description",children:"Define this agent's personality and identity."}),e.jsx("div",{className:"config-fields",children:e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-soul",children:"Agent Soul"}),e.jsx("div",{className:"agent-content-toolbar",children:e.jsxs("div",{className:"agent-content-mode-toggle",children:[e.jsxs("button",{className:`btn btn-sm ${F?"":"btn-primary"}`,onClick:()=>c(!1),disabled:!F,"aria-label":"Edit mode",children:[e.jsx(Je,{size:14}),"Edit"]}),e.jsxs("button",{className:`btn btn-sm ${F?"btn-primary":""}`,onClick:()=>c(!0),disabled:F,"aria-label":"Preview mode",children:[e.jsx(We,{size:14}),"Preview"]})]})}),F?u.trim()?e.jsx("div",{className:"agent-content-preview markdown-body",children:e.jsx(qe,{remarkPlugins:[Ge],children:u})}):e.jsx("div",{className:"agent-content-preview agent-content-placeholder",children:"No soul defined yet. Switch to Edit mode to define the agent's personality."}):e.jsx("textarea",{id:"agent-soul",className:"input config-textarea-mono",rows:12,placeholder:"Describe this agent's personality, tone, and behavioral traits...",value:u,onChange:N=>{g(N.target.value),k(!1)}}),!F&&e.jsx("span",{className:"config-hint",children:"Defines the agent's character and identity. Max 10,000 characters."})]})}),!F&&e.jsxs("div",{className:"config-actions",children:[e.jsx("button",{className:"btn btn-task-create",disabled:!A||R,onClick:()=>void z(),children:R?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Saving…"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Save Soul"]})}),!A&&M&&e.jsxs("span",{className:"config-saved-indicator",children:[e.jsx(de,{size:14}),"Soul saved"]})]})]})})}function Ua({agent:s,projectId:n,addToast:i,onSaved:o}){const[u,g]=t.useState(s.memory??""),[R,d]=t.useState(!1),[M,k]=t.useState(!1),[F,c]=t.useState(!1),[x,A]=t.useState(!1),[z,N]=t.useState([]),[y,J]=t.useState(!1),[m,K]=t.useState(""),[ee,C]=t.useState(""),[T,j]=t.useState(!1),[E,V]=t.useState(!1),[$,q]=t.useState(!1),[w,Q]=t.useState(!1),[P,O]=t.useState(""),f=t.useRef(null),b=t.useRef(null),r=s.state==="running",l=u!==(s.memory??""),p=t.useMemo(()=>z.find(H=>H.path===m),[z,m]),se=p?Ra[p.layer]:"Select a memory file to view or edit.",L=t.useCallback(async H=>{V(!0);try{const te=await Yt(s.id,H,n);K(te.path),C(te.content),j(!1),Q(!1)}catch(te){i(`Failed to load agent memory file: ${G(te)}`,"error")}finally{V(!1)}},[s.id,n,i]),Y=t.useCallback(async(H="")=>{J(!0);try{const{files:te}=await Kt(s.id,n);if(N(te),te.length===0){K(""),C(""),j(!1);return}const De=Aa(te,H);await L(De)}catch(te){i(`Failed to load memory files: ${G(te)}`,"error"),N([]),K(""),C(""),j(!1)}finally{J(!1)}},[s.id,n,i,L]);t.useEffect(()=>{g(s.memory??""),k(!1),c(!1),A(!1),O(""),Q(!1),Y()},[s.id,s.memory,Y]),t.useEffect(()=>()=>{f.current&&clearTimeout(f.current),b.current&&clearTimeout(b.current)},[]);const ie=async()=>{if(u.length>5e4){i("Memory must be at most 50,000 characters","error");return}d(!0);try{await ca(s.id,u,n),i("Memory saved","success"),k(!0),f.current&&clearTimeout(f.current),f.current=setTimeout(()=>k(!1),3e3),await o()}catch(H){i(`Failed to save memory: ${G(H)}`,"error")}finally{d(!1)}},xe=async H=>{if(!(!H||H===m)){if(T){O("Save the current file before switching to another file.");return}O(""),await L(H)}},W=async()=>{if(m){q(!0);try{await da(s.id,m,ee,n),j(!1),Q(!0),b.current&&clearTimeout(b.current),b.current=setTimeout(()=>Q(!1),3e3),O(""),await Y(m),i("Agent memory file saved","success"),await o()}catch(H){i(`Failed to save agent memory file: ${G(H)}`,"error")}finally{q(!1)}}};return e.jsx("div",{className:"config-tab",children:e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Agent Memory"}),e.jsx("p",{className:"config-description",children:"Store context that belongs to this agent only. Workspace memory, daily notes, dreams, and qmd search live in project settings under Project Memory."}),r&&e.jsx("p",{className:"config-hint config-hint--block-spacing",children:"Read-only while this agent is running."}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-memory",children:"Inline Memory"}),e.jsx("span",{className:"config-hint config-hint--block",children:"Short-form memory stored directly on the agent record and injected into prompts."}),e.jsx("div",{className:"agent-content-toolbar",children:e.jsxs("div",{className:"agent-content-mode-toggle",children:[!r&&e.jsxs("button",{className:`btn btn-sm ${F?"":"btn-primary"}`,onClick:()=>c(!1),disabled:!F,"aria-label":"Edit mode",children:[e.jsx(Je,{size:14}),"Edit"]}),e.jsxs("button",{className:`btn btn-sm ${F?"btn-primary":""}`,onClick:()=>c(!0),disabled:F,"aria-label":"Preview mode",children:[e.jsx(We,{size:14}),"Preview"]})]})}),F?u.trim()?e.jsx("div",{className:"agent-content-preview markdown-body",children:e.jsx(qe,{remarkPlugins:[Ge],children:u})}):e.jsx("div",{className:"agent-content-preview agent-content-placeholder",children:"No agent memory defined yet. Switch to Edit mode to add memory content."}):e.jsx("textarea",{id:"agent-memory","aria-label":"Agent Memory",className:"input config-textarea-mono",rows:10,placeholder:"Durable preferences, operating habits, and context this agent should carry across tasks...",value:u,readOnly:r,onChange:H=>{g(H.target.value),k(!1)}}),!F&&e.jsx("span",{className:"config-hint",children:"This is the inline memory field on the agent JSON record. Max 50,000 characters."})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-memory-file-select",children:"Memory Files"}),e.jsxs("span",{className:"config-hint config-hint--block",children:["Full OpenClaw memory files at ",e.jsxs("code",{children:["agent/",s.name||s.id,"/memory/"]})," (MEMORY.md, DREAMS.md, and daily notes)."]}),e.jsx("select",{id:"agent-memory-file-select",className:"select",value:m,disabled:y||E||$||z.length===0,onChange:H=>{xe(H.target.value)},children:z.length===0?e.jsx("option",{value:"",children:"No memory files found"}):z.map(H=>e.jsxs("option",{value:H.path,children:[Vs[H.layer]," • ",H.label]},H.path))}),y&&e.jsxs("span",{className:"config-hint config-hint--inline-loader",children:[e.jsx(B,{size:14,className:"animate-spin"}),"Loading memory files…"]}),p&&e.jsxs("div",{className:"config-hint config-hint--top-spacing",children:[e.jsx("strong",{children:Vs[p.layer]})," · ",se,e.jsx("br",{}),p.size.toLocaleString()," bytes · Updated ",$e(p.updatedAt)]}),e.jsx("div",{className:"agent-content-toolbar config-textarea-top-spacing",children:e.jsxs("div",{className:"agent-content-mode-toggle",children:[!r&&e.jsxs("button",{className:`btn btn-sm ${x?"":"btn-primary"}`,onClick:()=>A(!1),disabled:!x,"aria-label":"Memory file edit mode",children:[e.jsx(Je,{size:14}),"Edit"]}),e.jsxs("button",{className:`btn btn-sm ${x?"btn-primary":""}`,onClick:()=>A(!0),disabled:x,"aria-label":"Memory file preview mode",children:[e.jsx(We,{size:14}),"Preview"]})]})}),x?ee.trim()?e.jsx("div",{className:"agent-content-preview markdown-body",children:e.jsx(qe,{remarkPlugins:[Ge],children:ee})}):e.jsx("div",{className:"agent-content-preview agent-content-placeholder",children:"No memory file content yet. Switch to Edit mode to add content."}):e.jsx("textarea",{className:"input config-textarea-mono",rows:14,placeholder:"Select a memory file to view and edit its content...",value:ee,readOnly:r||!m||E,onChange:H=>{C(H.target.value),j(!0),Q(!1),O("")}}),E&&e.jsxs("span",{className:"config-hint config-hint--inline-loader",children:[e.jsx(B,{size:14,className:"animate-spin"}),"Loading file content…"]}),P&&e.jsx("span",{className:"config-hint config-hint--top-spacing config-hint--block",children:P})]})]}),e.jsxs("div",{className:"config-actions",children:[!F&&e.jsx("button",{className:"btn btn-task-create",disabled:!l||R||r,onClick:()=>void ie(),children:R?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Saving…"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Save Memory"]})}),!x&&e.jsx("button",{className:"btn",disabled:!T||$||!m||r,onClick:()=>void W(),children:$?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Saving file…"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Save Memory File"]})}),!l&&M&&e.jsxs("span",{className:"config-saved-indicator",children:[e.jsx(de,{size:14}),"Memory saved"]}),!T&&w&&e.jsxs("span",{className:"config-saved-indicator",children:[e.jsx(de,{size:14}),"Memory file saved"]})]})]})})}function _a({agent:s,projectId:n,addToast:i,onSaved:o}){const[u,g]=t.useState(s.instructionsText??""),[R,d]=t.useState(s.instructionsPath??""),[M,k]=t.useState(!1),[F,c]=t.useState(""),[x,A]=t.useState(!1),[z,N]=t.useState(!1),[y,J]=t.useState(!1),[m,K]=t.useState(!1),[ee,C]=t.useState(!1),[T,j]=t.useState(!1),E=t.useRef(null),V=t.useRef(null);t.useEffect(()=>{const P=R.trim();if(!P){c(""),N(!1);return}A(!0),ot("project",P).then(O=>{c(O.content),N(!1)}).catch(O=>{const f=G(O);f.includes("ENOENT")||f.includes("Not found")||f.includes("not found")?(c(""),N(!1)):(i(`Failed to load instructions file: ${f}`,"error"),c(""))}).finally(()=>{A(!1)})},[R,i]),t.useEffect(()=>{g(s.instructionsText??""),d(s.instructionsPath??""),C(!1),j(!1),k(!1)},[s.id,s.instructionsText,s.instructionsPath]),t.useEffect(()=>()=>{E.current&&clearTimeout(E.current),V.current&&clearTimeout(V.current)},[]);const $=(()=>{const P=u??"",O=s.instructionsText??"",f=R?.trim()??"",b=s.instructionsPath?.trim()??"";return P!==O||f!==b})(),q=async()=>{J(!0);try{await oa(s.id,{instructionsText:u||void 0,instructionsPath:R.trim()||void 0},n),i("Instructions saved","success"),C(!0),E.current&&clearTimeout(E.current),E.current=setTimeout(()=>C(!1),3e3),await o()}catch(P){i(`Failed to save instructions: ${G(P)}`,"error")}finally{J(!1)}},w=async()=>{const P=R.trim();if(!P){i("No instructions file path set","error");return}K(!0);try{await ct("project",P,F),i("Instructions file saved","success"),N(!1),j(!0),V.current&&clearTimeout(V.current),V.current=setTimeout(()=>j(!1),3e3),await o()}catch(O){i(`Failed to save instructions file: ${G(O)}`,"error")}finally{K(!1)}},Q=!!R.trim();return e.jsxs("div",{className:"config-tab",children:[e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Custom Instructions"}),e.jsx("p",{className:"config-description",children:"Append custom instructions to this agent's system prompt at execution time. Use this to customize behavior, coding style, or project conventions without modifying built-in prompts."}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"instructions-text",children:"Inline Instructions"}),e.jsx("div",{className:"agent-content-toolbar",children:e.jsxs("div",{className:"agent-content-mode-toggle",children:[e.jsxs("button",{className:`btn btn-sm ${M?"":"btn-primary"}`,onClick:()=>k(!1),disabled:!M,"aria-label":"Edit mode","data-testid":"instructions-edit-toggle",children:[e.jsx(Je,{size:14}),"Edit"]}),e.jsxs("button",{className:`btn btn-sm ${M?"btn-primary":""}`,onClick:()=>k(!0),disabled:M,"aria-label":"Preview mode","data-testid":"instructions-preview-toggle",children:[e.jsx(We,{size:14}),"Preview"]})]})}),M?u.trim()?e.jsx("div",{className:"agent-content-preview markdown-body",children:e.jsx(qe,{remarkPlugins:[Ge],children:u})}):e.jsx("div",{className:"agent-content-preview agent-content-placeholder",children:"No inline instructions defined yet. Switch to Edit mode to add instructions."}):e.jsx("textarea",{id:"instructions-text",className:"input",rows:10,placeholder:"Enter custom instructions to append to this agent's system prompt...",value:u,onChange:P=>{g(P.target.value),C(!1)}}),!M&&e.jsx("span",{className:"config-hint",children:"Markdown formatting supported. Max 50,000 characters."})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"instructions-path",children:"Instructions File Path"}),e.jsx("input",{id:"instructions-path",type:"text",className:"input",placeholder:"e.g., .fusion/agents/my-agent-instructions.md",value:R,onChange:P=>{d(P.target.value),C(!1)}}),e.jsx("span",{className:"config-hint",children:"Path to a .md file (relative to project root). Contents are read and appended at execution time."})]})]}),!M&&e.jsxs("div",{className:"config-actions",children:[e.jsx("button",{className:"btn btn-task-create",disabled:!$||y,onClick:()=>void q(),children:y?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Saving…"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Save Instructions"]})}),!$&&ee&&e.jsxs("span",{className:"config-saved-indicator",children:[e.jsx(de,{size:14}),"Instructions saved"]})]})]}),Q&&e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Instructions File Editor"}),e.jsx("p",{className:"config-description",children:"Edit the instructions file directly. Changes are saved separately from the path configuration."}),e.jsx("div",{className:"config-fields",children:e.jsxs("div",{className:"config-field",children:[e.jsxs("div",{className:"config-inline-header",children:[e.jsx("label",{htmlFor:"instructions-file-content",children:"File Content"}),x&&e.jsxs("span",{className:"config-hint config-hint--inline-tight",children:[e.jsx(B,{size:12,className:"animate-spin"}),"Loading..."]}),z&&!x&&e.jsx("span",{className:"config-hint config-hint--warning",children:"Unsaved changes"})]}),e.jsx("textarea",{id:"instructions-file-content",className:"input config-textarea-mono",rows:20,placeholder:"File content will appear here when loaded...",value:F,readOnly:x,onChange:P=>{c(P.target.value),N(!0),j(!1)}}),e.jsx("span",{className:"config-hint",children:"Edit the markdown file content directly. Save separately using the button below."})]})}),e.jsxs("div",{className:"config-actions",children:[e.jsx("button",{className:"btn btn-task-create",disabled:!z||m,onClick:()=>void w(),children:m?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Saving…"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Save File"]})}),!z&&T&&e.jsxs("span",{className:"config-saved-indicator",children:[e.jsx(de,{size:14}),"File saved"]})]})]})]})}function Js(s){const n=s??{},i={};return n.heartbeatIntervalMs!==void 0&&n.heartbeatIntervalMs!==null&&(i.heartbeatIntervalMs=String(Number(n.heartbeatIntervalMs)/1e3)),n.heartbeatTimeoutMs!==void 0&&n.heartbeatTimeoutMs!==null&&(i.heartbeatTimeoutMs=String(Number(n.heartbeatTimeoutMs)/1e3)),n.maxConcurrentRuns!==void 0&&n.maxConcurrentRuns!==null&&(i.maxConcurrentRuns=String(n.maxConcurrentRuns)),(n.messageResponseMode==="immediate"||n.messageResponseMode==="on-heartbeat")&&(i.messageResponseMode=n.messageResponseMode),i}function gs(s){return s?.enabled!==!1}function xs(s){return s?.autoClaimRelevantTasks!==!1}function bs(s){return s?.runMissedHeartbeatOnStartup===!0}function vs(s){return s?.allowParallelExecution!==!1}function Ws(s){const n=(s??{}).budgetConfig,i={};return n&&(n.tokenBudget!==void 0&&n.tokenBudget!==null&&(i.tokenBudget=String(n.tokenBudget)),n.usageThreshold!==void 0&&n.usageThreshold!==null&&(i.usageThreshold=String(Number(n.usageThreshold)*100)),n.budgetPeriod!==void 0&&n.budgetPeriod!==null&&(i.budgetPeriod=String(n.budgetPeriod)),n.resetDay!==void 0&&n.resetDay!==null&&(i.resetDay=String(n.resetDay))),i}function Va({agent:s,projectId:n,addToast:i,onSaved:o}){const[u,g]=t.useState(!1),[R,d]=t.useState(!1),[M,k]=t.useState(!1),[F,c]=t.useState(!1),[x,A]=t.useState(!1),[z,N]=t.useState(""),[y,J]=t.useState(!1),[m,K]=t.useState(null),[ee,C]=t.useState(!1),T=t.useRef(null),j=s.heartbeatProcedurePath?.trim(),E=`.fusion/agents/${s.name.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||s.id.toLowerCase().replace(/[^a-z0-9]+/g,"-")||"agent"}-${s.id.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"agent"}/HEARTBEAT.md`,V=`.fusion/agents/${s.id}/HEARTBEAT.md`,$=s.id.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"agent",q=!!(j&&(j===E||j===V||new RegExp(`^\\.fusion/agents/[^/]+-${$}/HEARTBEAT\\.md$`).test(j))),w=!!j,Q=t.useCallback(async b=>{k(!0),K(null);try{const r=await ot("project",b,n);N(r.content),J(!1)}catch(r){const l=G(r);K(l),i(`Failed to load heartbeat procedure file: ${l}`,"error")}finally{k(!1)}},[i,n]);t.useEffect(()=>{d(!1),A(!1),N(""),J(!1),K(null),k(!1),c(!1),C(!1)},[s.id,j]),t.useEffect(()=>()=>{T.current&&clearTimeout(T.current)},[]);const P=async()=>{j&&(d(!0),await Q(j))},O=async()=>{if(j){c(!0);try{await ct("project",j,z,n),J(!1),C(!0),i("Heartbeat procedure file saved","success"),T.current&&clearTimeout(T.current),T.current=setTimeout(()=>C(!1),3e3),await o()}catch(b){i(`Failed to save heartbeat procedure file: ${G(b)}`,"error")}finally{c(!1)}}},f=async()=>{g(!0);try{const b=await ha(s.id,n);i(b.procedureFileSeeded?`Heartbeat procedure file ready at ${b.heartbeatProcedurePath}`:`Heartbeat procedure path set to ${b.heartbeatProcedurePath}`,"success"),await o()}catch(b){i(`Failed to upgrade heartbeat procedure: ${G(b)}`,"error")}finally{g(!1)}};return e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Heartbeat Procedure"}),e.jsxs("p",{className:"config-description",children:["The per-tick procedure this agent runs every wake. Defaults to a per-agent markdown file (for example ",e.jsx("code",{children:".fusion/agents/ceo-agent2736/HEARTBEAT.md"}),") that you can edit. Legacy id-only default paths remain valid. Resets on every tick — no need to restart the agent after editing."]}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsxs("span",{className:"config-hint",children:["Current path: ",e.jsx("code",{children:j||"(none — using built-in default)"})]}),w&&e.jsx("div",{className:"heartbeat-procedure-actions",children:e.jsx("button",{className:"btn btn-sm",onClick:()=>void P(),disabled:M,children:M?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Loading file…"]}):e.jsxs(e.Fragment,{children:[e.jsx(Ve,{size:16}),"View Heartbeat Markdown"]})})})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("button",{className:"btn",disabled:u||q,onClick:()=>void f(),"aria-label":"Upgrade agent to default heartbeat procedure file",children:u?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Upgrading…"]}):q?e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Already on default"]}):"Upgrade to Default Heartbeat Procedure"}),e.jsxs("span",{className:"config-hint",children:["Sets ",e.jsx("code",{children:"heartbeatProcedurePath"})," to"," ",e.jsx("code",{children:E})," ","and seeds the file from the built-in template if it doesn't exist. Each agent gets its own per-agent file, so edits stay scoped to this agent. Operator edits to the file are preserved."]})]})]}),R&&w&&j&&e.jsxs("div",{className:"config-fields heartbeat-procedure-viewer",children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"heartbeat-procedure-file-content",children:"Heartbeat Procedure File"}),e.jsxs("div",{className:"agent-content-toolbar",children:[e.jsxs("div",{className:"agent-content-mode-toggle",children:[e.jsxs("button",{className:`btn btn-sm ${x?"":"btn-primary"}`,onClick:()=>A(!1),disabled:!x,"aria-label":"Heartbeat file edit mode",children:[e.jsx(Je,{size:14}),"Edit"]}),e.jsxs("button",{className:`btn btn-sm ${x?"btn-primary":""}`,onClick:()=>A(!0),disabled:x,"aria-label":"Heartbeat file preview mode",children:[e.jsx(We,{size:14}),"Preview"]})]}),M&&e.jsxs("span",{className:"config-hint heartbeat-procedure-status",children:[e.jsx(B,{size:12,className:"animate-spin"}),"Loading..."]}),y&&!M&&e.jsx("span",{className:"config-hint heartbeat-procedure-status heartbeat-procedure-status--warning",children:"Unsaved changes"})]}),x?z.trim()?e.jsx("div",{className:"agent-content-preview markdown-body",children:e.jsx(qe,{remarkPlugins:[Ge],children:z})}):e.jsx("div",{className:"agent-content-preview agent-content-placeholder",children:"No heartbeat procedure markdown content yet."}):e.jsx("textarea",{id:"heartbeat-procedure-file-content",className:"input",rows:16,value:z,readOnly:M,placeholder:"Heartbeat procedure markdown file content will appear here...",onChange:b=>{N(b.target.value),J(!0),C(!1)}}),m&&e.jsxs("span",{className:"config-error",children:["Failed to load file: ",m]}),e.jsxs("span",{className:"config-hint",children:["This editor writes directly to ",e.jsx("code",{children:j}),"."]})]}),!x&&e.jsxs("div",{className:"config-actions",children:[e.jsx("button",{className:"btn btn-task-create",disabled:!y||F||M,onClick:()=>void O(),children:F?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Saving…"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Save Heartbeat File"]})}),!y&&ee&&e.jsxs("span",{className:"config-saved-indicator",children:[e.jsx(de,{size:14}),"File saved"]})]})]})]})}function Ja({agent:s,projectId:n,addToast:i,onSaved:o,onHasChangesChange:u,onDelete:g,onAgentDraftApplied:R}){const[d,M]=t.useState(s.name),[k,F]=t.useState(s.role),[c,x]=t.useState(s.title??""),[A,z]=t.useState(s.icon??""),[N,y]=t.useState(s.reportsTo??""),[J,m]=t.useState([]),[K,ee]=t.useState(!1),[C,T]=t.useState(!1),[j,E]=t.useState(!1),V=t.useRef(null),[$,q]=t.useState(()=>{const a={};for(const h of _e){const S=s.metadata[h.key];S!=null&&(a[h.key]=String(S))}return a}),[w,Q]=t.useState(()=>Js(s.runtimeConfig)),[P,O]=t.useState(()=>gs(s.runtimeConfig)),[f,b]=t.useState(()=>xs(s.runtimeConfig)),[r,l]=t.useState(()=>bs(s.runtimeConfig)),[p,se]=t.useState(()=>vs(s.runtimeConfig)),[L,Y]=t.useState(()=>Ws(s.runtimeConfig)),[ie,xe]=t.useState(s.bundleConfig?.mode??""),[W,H]=t.useState(s.bundleConfig?.entryFile??"AGENTS.md"),[te,De]=t.useState(s.bundleConfig?.externalPath??""),[Ne,Re]=t.useState(s.bundleConfig?.files??[]),[oe,Ee]=t.useState(Array.isArray(s.metadata?.skills)?s.metadata.skills:[]),[cs,Ye]=t.useState([]),[ze,be]=t.useState(!1),[Me,v]=t.useState([]),[I,X]=t.useState([]),[ne,re]=t.useState([]),[he,ye]=t.useState(!1),Se=(()=>{const a=s.runtimeConfig??{};return a.modelProvider&&a.modelId?`${a.modelProvider}/${a.modelId}`:typeof a.model=="string"&&a.model.includes("/")?a.model:""})(),Fe=typeof s.runtimeConfig?.runtimeHint=="string"?s.runtimeConfig.runtimeHint:"",[fe,He]=t.useState(Fe?"runtime":"model"),[ve,Ke]=t.useState(Se),[Ae,Oe]=t.useState(Fe),Ze=N.trim(),ks=t.useMemo(()=>J.filter(a=>a.id!==s.id),[J,s.id]),ut=!!Ze&&!ks.some(a=>a.id===Ze),mt=t.useMemo(()=>({name:d,role:k,title:c||void 0,instructionsText:s.instructionsText,soul:s.soul,memory:s.memory,reportsTo:N||void 0,skills:oe,model:ve||void 0,runtimeHint:fe==="runtime"&&Ae||void 0,thinkingLevel:$.thinkingLevel??void 0,maxTurns:$.maxTurns?Number($.maxTurns):void 0,heartbeatIntervalMs:w.heartbeatIntervalMs?Number(w.heartbeatIntervalMs)*1e3:void 0,heartbeatTimeoutMs:w.heartbeatTimeoutMs?Number(w.heartbeatTimeoutMs)*1e3:void 0,maxConcurrentRuns:w.maxConcurrentRuns?Number(w.maxConcurrentRuns):void 0,messageResponseMode:w.messageResponseMode}),[s.instructionsText,s.memory,s.soul,$.maxTurns,$.thinkingLevel,w.heartbeatIntervalMs,w.heartbeatTimeoutMs,w.maxConcurrentRuns,w.messageResponseMode,ve,d,N,k,fe,Ae,oe,c]),ht=t.useCallback(a=>{M(a.name),F(a.role),x(a.title??""),z(a.icon??""),y(a.reportsTo??""),a.skills&&Ee(a.skills),a.thinkingLevel&&q(S=>({...S,thinkingLevel:a.thinkingLevel})),a.maxTurns!==void 0&&q(S=>({...S,maxTurns:String(a.maxTurns)})),a.runtimeHint!==void 0?(He("runtime"),Oe(a.runtimeHint??""),a.runtimeHint&&Ke("")):a.model!==void 0&&(He("model"),Ke(a.model??""),Oe(""));const h=Object.fromEntries(Object.entries({name:a.name,role:a.role,title:a.title,icon:a.icon,reportsTo:a.reportsTo,instructionsText:a.instructionsText,soul:a.soul,memory:a.memory}).filter(([,S])=>S!==void 0));R?.(h),E(!1),i("Interview draft applied. Review and save when ready.","success")},[i,R]);t.useEffect(()=>{let a=!1;return ee(!0),Zt(void 0,n).then(h=>{a||m(h)}).catch(()=>{a||m([])}).finally(()=>{a||ee(!1)}),()=>{a=!0}},[n]),t.useEffect(()=>{be(!0),Qt().then(a=>{Ye(a.models),v(a.favoriteProviders),X(a.favoriteModels)}).catch(()=>{}).finally(()=>be(!1))},[]);const ft=t.useCallback(async a=>{const h=Me,_=h.includes(a)?h.filter(ce=>ce!==a):[a,...h];v(_);try{await Bs({favoriteProviders:_,favoriteModels:I})}catch{v(h)}},[Me,I]),gt=t.useCallback(async a=>{const h=I,_=h.includes(a)?h.filter(ce=>ce!==a):[a,...h];X(_);try{await Bs({favoriteProviders:Me,favoriteModels:_})}catch{X(h)}},[Me,I]);t.useEffect(()=>{ye(!0),nt(n).then(re).catch(()=>re([])).finally(()=>ye(!1))},[n]);const[ke,ds]=t.useState(null),[Cs,ws]=t.useState(!1);t.useEffect(()=>{ps(s.id,n).then(ds).catch(()=>ds(null))},[s.id,n]);const xt=async()=>{ws(!0);try{await ua(s.id,n),i("Budget usage reset successfully","success");const a=await ps(s.id,n);ds(a)}catch(a){i(`Failed to reset budget: ${G(a)}`,"error")}finally{ws(!1)}},[Ce,Rs]=t.useState(!1),[U,Te]=t.useState({}),[bt,Pe]=t.useState(!1),[us,Qe]=t.useState(null),Ms=s.state==="idle"||s.state==="paused",Be=t.useRef(null),Fs=t.useRef(null),As=t.useRef(null),Xe=t.useRef(0);t.useEffect(()=>()=>{Be.current&&clearTimeout(Be.current)},[]);const ge=(()=>{if(d!==s.name||k!==s.role||c!==(s.title??"")||A!==(s.icon??"")||N!==(s.reportsTo??"")||ie!==(s.bundleConfig?.mode??"")||W!==(s.bundleConfig?.entryFile??"AGENTS.md")||te!==(s.bundleConfig?.externalPath??"")||JSON.stringify(Ne)!==JSON.stringify(s.bundleConfig?.files??[]))return!0;for(const Z of _e){const me=$[Z.key]?.trim()??"",D=s.metadata[Z.key]!==void 0&&s.metadata[Z.key]!==null?String(s.metadata[Z.key]):"";if(me!==D)return!0}const a=s.runtimeConfig??{};if(P!==gs(s.runtimeConfig)||f!==xs(s.runtimeConfig)||r!==bs(s.runtimeConfig)||p!==vs(s.runtimeConfig))return!0;for(const Z of["heartbeatIntervalMs","heartbeatTimeoutMs","maxConcurrentRuns","messageResponseMode"]){const me=w[Z]?.trim()??"";let D=a[Z]!==void 0&&a[Z]!==null?String(a[Z]):"";if((Z==="heartbeatIntervalMs"||Z==="heartbeatTimeoutMs")&&D&&(D=String(Number(D)/1e3)),me!==D)return!0}const h=a.budgetConfig;for(const Z of["tokenBudget","budgetPeriod","resetDay"]){const me=L[Z]?.trim()??"",D=h?.[Z]!==void 0&&h?.[Z]!==null?String(h[Z]):"";if(me!==D)return!0}const S=L.usageThreshold?.trim()??"",_=h?.usageThreshold!==void 0&&h?.usageThreshold!==null?String(Number(h.usageThreshold)*100):"";if(S!==_)return!0;const ce=Array.isArray(s.metadata?.skills)?s.metadata.skills:[];return JSON.stringify(oe)!==JSON.stringify(ce)||fe!==(Fe?"runtime":"model")||ve!==Se||Ae!==Fe})(),Ts=t.useRef(null);t.useEffect(()=>{u&&Ts.current!==ge&&(Ts.current=ge,u(ge))},[ge,u]),t.useEffect(()=>()=>{u?.(!1)},[u]),t.useEffect(()=>{const a={id:s.id,updatedAt:s.updatedAt},h=Fs.current;(!h||h.id!==a.id||h.updatedAt!==a.updatedAt)&&(ge||(Fs.current=a,Q(Js(s.runtimeConfig)),O(gs(s.runtimeConfig)),b(xs(s.runtimeConfig)),l(bs(s.runtimeConfig)),se(vs(s.runtimeConfig)),Y(Ws(s.runtimeConfig)),Ke(Se),Oe(Fe),He(Fe?"runtime":"model")))},[s,ge,Se,Fe]);const Es=(a,h)=>{q(S=>({...S,[a]:h})),Pe(!1),U[a]&&Te(S=>{const _={...S};return delete _[a],_})},es=(a,h)=>{Q(S=>({...S,[a]:h})),Pe(!1),U[a]&&Te(S=>{const _={...S};return delete _[a],_})},vt=a=>{O(a),Pe(!1)},ss=(a,h)=>{Y(S=>({...S,[a]:h})),Pe(!1),U[a]&&Te(S=>{const _={...S};return delete _[a],_})},pe=t.useMemo(()=>{const a=Ba($);for(const[D,we]of Object.entries({heartbeatIntervalMs:{label:"Heartbeat Interval",min:1},heartbeatTimeoutMs:{label:"Heartbeat Timeout",min:5},maxConcurrentRuns:{label:"Max Concurrent Runs",min:1}})){const le=w[D]?.trim();if(!le)continue;const je=Number(le);Number.isNaN(je)||!Number.isFinite(je)?a[D]=`"${we.label}" must be a valid number`:je<we.min&&(a[D]=`"${we.label}" must be at least ${we.min.toLocaleString()}`)}const h=w.messageResponseMode?.trim();h&&!["immediate","on-heartbeat"].includes(h)&&(a.messageResponseMode='"Message Response Mode" must be either immediate or on-heartbeat');const S=L.tokenBudget?.trim();if(S){const D=Number(S);Number.isNaN(D)||!Number.isFinite(D)?a.tokenBudget='"Token Budget" must be a valid number':D<=0&&(a.tokenBudget='"Token Budget" must be greater than 0')}const _=L.usageThreshold?.trim();if(_){const D=Number(_);Number.isNaN(D)||!Number.isFinite(D)?a.usageThreshold='"Usage Threshold" must be a valid number':(D<1||D>100)&&(a.usageThreshold='"Usage Threshold" must be between 1 and 100')}const ce=L.budgetPeriod?.trim();ce&&!["daily","weekly","monthly","lifetime"].includes(ce)&&(a.budgetPeriod='"Budget Period" must be one of: daily, weekly, monthly, lifetime');const Z=L.resetDay?.trim(),me=ce||"lifetime";if(Z){const D=Number(Z);Number.isNaN(D)||!Number.isFinite(D)?a.resetDay='"Reset Day" must be a valid number':me==="weekly"?(D<0||D>6||!Number.isInteger(D))&&(a.resetDay='"Reset Day" must be between 0 (Sunday) and 6 (Saturday) for weekly period'):me==="monthly"&&(D<1||D>31||!Number.isInteger(D))&&(a.resetDay='"Reset Day" must be between 1 and 31 for monthly period')}return a},[$,w,L]),Ps=t.useCallback(()=>{if(Object.keys(pe).length>0)return null;const a={...s.metadata};for(const le of _e){const je=$[le.key]?.trim();je?le.type==="number"?a[le.key]=Number(je):a[le.key]=je:delete a[le.key]}oe.length>0?a.skills=oe:delete a.skills;const h={...s.runtimeConfig};h.enabled=P,h.autoClaimRelevantTasks=f,h.runMissedHeartbeatOnStartup=r,h.allowParallelExecution=p;for(const le of["heartbeatIntervalMs","heartbeatTimeoutMs","maxConcurrentRuns"]){const je=w[le]?.trim();if(!je)delete h[le];else{const $s=Number(je);h[le]=le==="maxConcurrentRuns"?$s:$s*1e3}}const S=w.messageResponseMode?.trim();if(S?h.messageResponseMode=S:delete h.messageResponseMode,fe==="runtime")Ae.trim()?h.runtimeHint=Ae.trim():delete h.runtimeHint,delete h.modelProvider,delete h.modelId,delete h.model;else if(delete h.runtimeHint,ve.trim()){const le=ve.indexOf("/");le!==-1&&(h.modelProvider=ve.slice(0,le),h.modelId=ve.slice(le+1),h.model=ve.trim())}else delete h.modelProvider,delete h.modelId,delete h.model;const _={},ce=L.tokenBudget?.trim(),Z=L.usageThreshold?.trim(),me=L.budgetPeriod?.trim(),D=L.resetDay?.trim();ce&&(_.tokenBudget=Number(ce)),Z&&(_.usageThreshold=Number(Z)/100),me&&(_.budgetPeriod=me),D&&(_.resetDay=Number(D)),Object.keys(_).length>0?h.budgetConfig=_:delete h.budgetConfig;let we;return ie&&(we={mode:ie,entryFile:W||"AGENTS.md",files:Ne.length>0?Ne:["AGENTS.md"]},ie==="external"&&te.trim()&&(we.externalPath=te.trim())),{name:d.trim()||void 0,role:k,title:c.trim()||void 0,icon:A.trim()||void 0,reportsTo:N.trim()||void 0,metadata:a,runtimeConfig:h,bundleConfig:we}},[s.metadata,s.runtimeConfig,p,f,L,W,te,Ne,ie,$,P,w,A,ve,d,N,k,r,fe,Ae,oe,c,pe]),Ie=t.useCallback(async(a,h)=>{const S=Ps();if(!S)return Te(pe),a&&i("Please fix validation errors before saving","error"),h==="auto"&&Qe("Fix validation errors to save changes"),!1;const _=JSON.stringify(S);if(_===As.current)return!1;const ce=++Xe.current;Te({}),Qe(null),Rs(!0);try{return await Xt(s.id,S,n),ce!==Xe.current?!1:(As.current=_,h==="manual"&&i("Settings saved","success"),Qe(null),Pe(!0),Be.current&&clearTimeout(Be.current),Be.current=setTimeout(()=>Pe(!1),3e3),await o(),!0)}catch(Z){if(ce===Xe.current){const me=G(Z);Qe(me),i(`Failed to save settings: ${me}`,"error")}return!1}finally{ce===Xe.current&&Rs(!1)}},[i,s.id,Ps,o,n,pe]),pt=async()=>{await Ie(!0,"manual")},ue=t.useCallback(()=>{if(!(!ge||Ce)){if(Object.keys(pe).length>0){Te(pe);return}Ie(!1,"auto")}},[ge,Ce,Ie,pe]);t.useEffect(()=>{if(!ge||Ce)return;if(Object.keys(pe).length>0){Te(pe);return}const a=setTimeout(()=>{Ie(!1,"auto")},Fa);return()=>clearTimeout(a)},[ge,Ce,Ie,pe]);const jt=t.useCallback(async a=>{T(!0);try{await ea(s.id,a,n),await o(),i("Avatar uploaded","success")}catch(h){i(G(h),"error")}finally{T(!1),V.current&&(V.current.value="")}},[i,s.id,o,n]),Nt=t.useCallback(async()=>{T(!0);try{await sa(s.id,n),await o(),i("Avatar removed","success")}catch(a){i(G(a),"error")}finally{T(!1)}},[i,s.id,o,n]),Ls=Ce?"Saving changes…":us?`Save failed: ${us}`:!ge&&bt?"All changes saved":null;return e.jsxs("div",{className:"config-tab",children:[e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Agent Configuration"}),e.jsx("p",{className:"config-description",children:"Configure agent settings and behavior."}),e.jsx("div",{className:"config-actions-row",children:e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>E(!0),children:"AI Interview"})}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-name",children:"Name"}),e.jsx("input",{id:"agent-name",type:"text",className:"input",value:d,onChange:a=>M(a.target.value),onBlur:()=>{ue()}})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-role",children:"Role"}),e.jsxs("select",{id:"agent-role",className:"select",value:k,onChange:a=>{F(a.target.value),ue()},children:[e.jsx("option",{value:"triage",children:"Triage"}),e.jsx("option",{value:"executor",children:"Executor"}),e.jsx("option",{value:"reviewer",children:"Reviewer"}),e.jsx("option",{value:"merger",children:"Merger"}),e.jsx("option",{value:"scheduler",children:"Scheduler"}),e.jsx("option",{value:"custom",children:"Custom"})]})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-title",children:"Title"}),e.jsx("input",{id:"agent-title",type:"text",className:"input",placeholder:"e.g. Senior Code Reviewer",value:c,onChange:a=>x(a.target.value),onBlur:()=>{ue()}})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{children:"Avatar"}),e.jsxs("div",{className:"agent-avatar-editor",children:[e.jsx(Xs,{agent:s,size:64,className:"agent-avatar-editor-preview"}),e.jsxs("div",{className:"agent-avatar-editor-actions",children:[e.jsx("input",{ref:V,id:"agent-avatar-upload",type:"file",accept:"image/png,image/jpeg,image/gif,image/webp",className:"visually-hidden",disabled:C,onChange:a=>{const h=a.target.files?.[0];h&&jt(h)}}),e.jsx("button",{type:"button",className:"btn btn-sm",disabled:C,onClick:()=>V.current?.click(),children:"Upload Avatar"}),s.imageUrl?e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void Nt(),disabled:C,children:"Remove Avatar"}):null]})]})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-icon",children:"Icon"}),e.jsx("input",{id:"agent-icon",type:"text",className:"input",placeholder:"e.g. 🤖",value:A,onChange:a=>z(a.target.value),onBlur:()=>{ue()}})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-reports-to",children:"Reports To"}),e.jsxs("select",{id:"agent-reports-to",className:"select",value:N,onChange:a=>{y(a.target.value),ue()},disabled:K,children:[e.jsx("option",{value:"",children:"No manager"}),ut&&e.jsxs("option",{value:Ze,children:["Unknown manager (",Ze,")"]}),ks.map(a=>e.jsxs("option",{value:a.id,children:[a.name," (",a.id,")"]},a.id))]})]})]})]}),e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Skills"}),e.jsx("p",{className:"config-description",children:"Assign skills to this agent for specialized behavior."}),e.jsx("div",{className:"config-fields",children:e.jsx("div",{className:"config-field",children:e.jsx(fa,{id:"agent-skills",label:"Skills",value:oe,onChange:a=>{Ee(a),ue()},projectId:n})})})]}),e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Model"}),e.jsx("p",{className:"config-description",children:"Choose either a built-in model or a plugin runtime for this agent. These options are mutually exclusive."}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{children:"Runtime Source"}),e.jsxs("div",{className:"config-runtime-tabs",role:"tablist","aria-label":"Runtime source",children:[e.jsx("button",{type:"button",className:`config-runtime-tab${fe==="model"?" active":""}`,role:"tab","aria-selected":fe==="model",tabIndex:fe==="model"?0:-1,onClick:()=>{He("model"),Oe(""),ue()},children:"Built-in Model"}),e.jsx("button",{type:"button",className:`config-runtime-tab${fe==="runtime"?" active":""}`,role:"tab","aria-selected":fe==="runtime",tabIndex:fe==="runtime"?0:-1,onClick:()=>{He("runtime"),ue()},children:"Plugin Runtime"})]})]}),fe==="model"?e.jsx("div",{className:"config-field",children:e.jsx(ta,{models:cs,value:ve,onChange:a=>{Ke(a),ue()},placeholder:"Use global default",label:"Agent Model",disabled:ze,favoriteProviders:Me,onToggleFavorite:ft,favoriteModels:I,onToggleModelFavorite:gt})}):e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"agent-runtime-hint",children:"Runtime"}),he?e.jsx("span",{className:"config-hint",children:"Loading runtimes…"}):e.jsxs("select",{id:"agent-runtime-hint",className:"select",value:Ae,onChange:a=>{Oe(a.target.value),ue()},children:[e.jsx("option",{value:"",children:ne.length>0?"Select a plugin runtime…":"No plugin runtimes available"}),ne.map(a=>e.jsx("option",{value:a.runtimeId,children:a.description?`${a.name} — ${a.description}`:a.name},`${a.pluginId}:${a.runtimeId}`))]})]})]})]}),e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Heartbeat Settings"}),e.jsx("p",{className:"config-description",children:"Configure how this agent's heartbeat is monitored. Leave a field empty to use system defaults."}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsxs("label",{className:"checkbox-label",htmlFor:"hb-enabled",children:[e.jsx("input",{id:"hb-enabled",type:"checkbox",checked:P,onChange:a=>{vt(a.target.checked),ue()}}),"Heartbeat Enabled"]}),e.jsx("span",{className:"config-hint",children:"When enabled, this agent receives scheduled heartbeat runs based on its interval."})]}),e.jsxs("div",{className:"config-field",children:[e.jsxs("label",{className:"checkbox-label",htmlFor:"hb-autoClaimRelevantTasks",children:[e.jsx("input",{id:"hb-autoClaimRelevantTasks",type:"checkbox",checked:f,onChange:a=>{b(a.target.checked),ue()}}),"Auto-Claim Relevant Tasks"]}),e.jsx("span",{className:"config-hint",children:"When enabled (default), no-task heartbeats scan open unowned work and auto-claim tasks aligned with this agent's role and soul."})]}),e.jsxs("div",{className:"config-field",children:[e.jsxs("label",{className:"checkbox-label",htmlFor:"hb-runMissedHeartbeatOnStartup",children:[e.jsx("input",{id:"hb-runMissedHeartbeatOnStartup",type:"checkbox",checked:r,onChange:a=>{l(a.target.checked),ue()}}),"Run Missed Heartbeat On Startup"]}),e.jsx("span",{className:"config-hint",children:"When enabled, if the server was down across this agent's scheduled heartbeat tick, fire a single catch-up heartbeat at startup. Default: off."})]}),e.jsxs("div",{className:"config-field",children:[e.jsxs("label",{className:"checkbox-label",htmlFor:"hb-allowParallelExecution",children:[e.jsx("input",{id:"hb-allowParallelExecution",type:"checkbox",checked:p,onChange:a=>{se(a.target.checked),ue()}}),"Allow Parallel Execution"]}),e.jsx("span",{className:"config-hint",children:"When disabled, the heartbeat and task execution paths serialize for this agent (heartbeat will not start while the agent's task is executing, and vice versa). Permanent agents only."})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"hb-heartbeatIntervalMs",children:"Heartbeat Interval (s)"}),e.jsx("input",{id:"hb-heartbeatIntervalMs",type:"text",inputMode:"numeric",className:ae("input",!!U.heartbeatIntervalMs&&"input--error"),placeholder:String(js/1e3),value:w.heartbeatIntervalMs??"",onChange:a=>es("heartbeatIntervalMs",a.target.value)}),U.heartbeatIntervalMs?e.jsx("span",{className:"config-error",children:U.heartbeatIntervalMs}):e.jsxs("span",{className:"config-hint",children:["How often heartbeats are checked. Leave empty for system default (",js/1e3,"s / ",Ma,")."]})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"hb-heartbeatTimeoutMs",children:"Heartbeat Timeout (s)"}),e.jsx("input",{id:"hb-heartbeatTimeoutMs",type:"text",inputMode:"numeric",className:ae("input",!!U.heartbeatTimeoutMs&&"input--error"),placeholder:"60",value:w.heartbeatTimeoutMs??"",onChange:a=>es("heartbeatTimeoutMs",a.target.value)}),U.heartbeatTimeoutMs?e.jsx("span",{className:"config-error",children:U.heartbeatTimeoutMs}):e.jsx("span",{className:"config-hint",children:"Time without heartbeat before agent is considered unresponsive. Leave empty for system default (60s)"})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"hb-maxConcurrentRuns",children:"Max Concurrent Runs"}),e.jsx("input",{id:"hb-maxConcurrentRuns",type:"text",inputMode:"numeric",className:ae("input",!!U.maxConcurrentRuns&&"input--error"),placeholder:"1",value:w.maxConcurrentRuns??"",onChange:a=>es("maxConcurrentRuns",a.target.value)}),U.maxConcurrentRuns?e.jsx("span",{className:"config-error",children:U.maxConcurrentRuns}):e.jsx("span",{className:"config-hint",children:"Maximum simultaneous heartbeat runs for this agent. Leave empty for system default (1)."})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"hb-messageResponseMode",children:"Message Response Mode"}),e.jsxs("select",{id:"hb-messageResponseMode",className:ae("select",!!U.messageResponseMode&&"input--error"),value:w.messageResponseMode??"",onChange:a=>es("messageResponseMode",a.target.value),children:[e.jsx("option",{value:"",children:"System Default (On Heartbeat)"}),e.jsx("option",{value:"on-heartbeat",children:"On Heartbeat"}),e.jsx("option",{value:"immediate",children:"Immediate"})]}),U.messageResponseMode?e.jsx("span",{className:"config-error",children:U.messageResponseMode}):e.jsx("span",{className:"config-hint",children:"How this agent responds to incoming messages. 'Immediate' wakes the agent as soon as a message arrives. 'On Heartbeat' defers processing to the next scheduled heartbeat."})]})]})]}),e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Budget Settings"}),e.jsx("p",{className:"config-description",children:"Configure token budget limits for this agent. Leave all fields empty to disable budget tracking."}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"budget-tokenBudget",children:"Token Budget"}),e.jsx("input",{id:"budget-tokenBudget",type:"text",inputMode:"numeric",className:ae("input",!!U.tokenBudget&&"input--error"),placeholder:"No limit",value:L.tokenBudget??"",onChange:a=>ss("tokenBudget",a.target.value)}),U.tokenBudget?e.jsx("span",{className:"config-error",children:U.tokenBudget}):e.jsx("span",{className:"config-hint",children:"Total token cap (input + output) for this agent. Leave empty for no limit."})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"budget-usageThreshold",children:"Usage Threshold (%)"}),e.jsx("input",{id:"budget-usageThreshold",type:"text",inputMode:"numeric",className:ae("input",!!U.usageThreshold&&"input--error"),placeholder:"80",value:L.usageThreshold??"",onChange:a=>ss("usageThreshold",a.target.value)}),U.usageThreshold?e.jsx("span",{className:"config-error",children:U.usageThreshold}):e.jsx("span",{className:"config-hint",children:"Warning threshold as a percentage. Agent warns when usage reaches this level. Default: 80%."})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"budget-budgetPeriod",children:"Budget Period"}),e.jsxs("select",{id:"budget-budgetPeriod",className:ae("select",!!U.budgetPeriod&&"input--error"),value:L.budgetPeriod??"",onChange:a=>ss("budgetPeriod",a.target.value),children:[e.jsx("option",{value:"",children:"No reset (lifetime)"}),e.jsx("option",{value:"daily",children:"Daily"}),e.jsx("option",{value:"weekly",children:"Weekly"}),e.jsx("option",{value:"monthly",children:"Monthly"})]}),U.budgetPeriod?e.jsx("span",{className:"config-error",children:U.budgetPeriod}):e.jsx("span",{className:"config-hint",children:"How often the budget counter resets. Leave empty for lifetime budget."})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"budget-resetDay",children:"Reset Day"}),e.jsx("input",{id:"budget-resetDay",type:"text",inputMode:"numeric",className:ae("input",!!U.resetDay&&"input--error"),placeholder:"Auto",value:L.resetDay??"",onChange:a=>ss("resetDay",a.target.value)}),U.resetDay?e.jsx("span",{className:"config-error",children:U.resetDay}):e.jsx("span",{className:"config-hint",children:L.budgetPeriod==="weekly"?"Day of week (0=Sunday to 6=Saturday) for reset.":L.budgetPeriod==="monthly"?"Day of month (1-31) for reset.":"Day for reset (weekly: 0-6, monthly: 1-31). Leave empty for automatic."})]}),ke?.budgetLimit!=null&&e.jsxs("div",{className:"config-field",children:[e.jsx("label",{children:"Current Usage"}),e.jsxs("div",{className:"budget-progress-container",children:[e.jsx("div",{className:"budget-progress-bar",children:e.jsx("div",{className:ae("budget-progress-bar__fill",(ke.usagePercent??0)>=100?"budget-progress-bar__fill--red":(ke.usagePercent??0)>=80?"budget-progress-bar__fill--amber":"budget-progress-bar__fill--green"),style:{width:`${Math.min(ke.usagePercent??0,100)}%`}})}),e.jsxs("span",{className:"budget-progress-label",children:[(ke.currentUsage??0).toLocaleString()," / ",(ke.budgetLimit??0).toLocaleString()," tokens (",Math.round(ke.usagePercent??0),"% used)"]})]})]}),ke?.budgetLimit!=null&&e.jsx("div",{className:"config-field",children:e.jsx("button",{className:"btn btn-reset-budget",onClick:()=>void xt(),disabled:Cs,children:Cs?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:14,className:"animate-spin"}),"Resetting…"]}):e.jsxs(e.Fragment,{children:[e.jsx(os,{size:14}),"Reset Budget Usage"]})})})]})]}),e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Instruction Bundle"}),e.jsx("p",{className:"config-description",children:"Configure the agent's instruction bundle. Leave empty to use inline instructions only."}),e.jsxs("div",{className:"config-fields",children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"bundle-mode",children:"Bundle Mode"}),e.jsxs("select",{id:"bundle-mode",className:"select",value:ie,onChange:a=>xe(a.target.value),children:[e.jsx("option",{value:"",children:"None (use inline instructions)"}),e.jsx("option",{value:"managed",children:"Managed (system-managed directory)"}),e.jsx("option",{value:"external",children:"External (user-specified path)"})]}),e.jsxs("span",{className:"config-hint",children:[ie==="managed"&&"Files will be stored in a system-managed directory within .fusion/agents/",ie==="external"&&"Specify an external directory path for the instruction files",!ie&&"Select a mode to enable instruction bundling"]})]}),ie&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"bundle-entry-file",children:"Entry File"}),e.jsx("input",{id:"bundle-entry-file",type:"text",className:"input",placeholder:"AGENTS.md",value:W,onChange:a=>H(a.target.value)}),e.jsx("span",{className:"config-hint",children:"Primary instructions file name (default: AGENTS.md)"})]}),ie==="external"&&e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"bundle-external-path",children:"External Path"}),e.jsx("input",{id:"bundle-external-path",type:"text",className:"input",placeholder:"e.g. .fusion/agents/my-agent",value:te,onChange:a=>De(a.target.value)}),e.jsx("span",{className:"config-hint",children:"Absolute or relative path to the external directory"})]}),e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:"bundle-files",children:"Files (comma-separated)"}),e.jsx("input",{id:"bundle-files",type:"text",className:"input",placeholder:"AGENTS.md, PROMPTS.md",value:Ne.join(", "),onChange:a=>Re(a.target.value.split(",").map(h=>h.trim()).filter(Boolean))}),e.jsx("span",{className:"config-hint",children:"List of file names in the bundle directory"})]})]})]})]}),e.jsxs("div",{className:"config-section",children:[e.jsx("h3",{children:"Advanced Settings"}),e.jsx("p",{className:"config-description",children:"Advanced configuration options for this agent. Leave a field empty to use system defaults."}),e.jsx("div",{className:"config-fields",children:_e.map(a=>{const h=!!U[a.key];return e.jsxs("div",{className:"config-field",children:[e.jsx("label",{htmlFor:`adv-${a.key}`,children:a.label}),a.type==="select"?e.jsxs("select",{id:`adv-${a.key}`,className:ae("select",h&&"input--error"),value:$[a.key]??"",onChange:S=>Es(a.key,S.target.value),children:[e.jsx("option",{value:"",children:"System Default"}),a.options?.map(S=>e.jsx("option",{value:S.value,children:S.label},S.value))]}):e.jsx("input",{id:`adv-${a.key}`,type:"text",inputMode:a.type==="number"?"numeric":void 0,className:ae("input",h&&"input--error"),placeholder:a.placeholder,value:$[a.key]??"",onChange:S=>Es(a.key,S.target.value)}),h&&e.jsx("span",{className:"config-error",children:U[a.key]}),!h&&a.hint&&e.jsx("span",{className:"config-hint",children:a.hint})]},a.key)})}),e.jsxs("div",{className:"config-actions",children:[e.jsx("button",{className:"btn btn-task-create",disabled:!ge||Ce,onClick:()=>void pt(),children:Ce?e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,className:"animate-spin"}),"Saving…"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{size:16}),"Save Settings"]})}),Ls&&e.jsxs("span",{className:ae("config-saved-indicator",us&&"config-saved-indicator--error"),children:[Ce?e.jsx(B,{size:14,className:"animate-spin"}):e.jsx(de,{size:14}),Ls]})]})]}),e.jsx(Va,{agent:s,projectId:n,addToast:i,onSaved:o}),e.jsxs("div",{className:"config-section config-section--danger",children:[e.jsx("h3",{children:"Danger Zone"}),e.jsx("p",{className:"config-description",children:"Permanently delete this agent from the project."}),e.jsx("div",{className:"config-fields",children:e.jsxs("div",{className:"config-field",children:[e.jsxs("button",{className:"btn btn--danger",disabled:!Ms||!g,onClick:()=>void g?.(),children:[e.jsx(rs,{size:16}),"Delete Agent"]}),e.jsx("span",{className:"config-danger-note",children:Ms?"Deletion is permanent and cannot be undone.":`Agent deletion is only available when state is idle or paused (current state: ${s.state}).`})]})})]}),e.jsx(ga,{isOpen:j,onClose:()=>E(!1),onUseDraft:ht,projectId:n,existingAgents:J,mode:"edit",existingAgentConfig:mt})]})}function Wa({agentId:s,projectId:n,onChildClick:i}){const[o,u]=t.useState([]),[g,R]=t.useState(!0);return t.useEffect(()=>{R(!0),Gt(s,n).then(u).finally(()=>R(!1))},[s,n]),g?e.jsxs("div",{className:"detail-section",children:[e.jsx("div",{className:"detail-section-header",children:e.jsx("h3",{children:"Employees"})}),e.jsxs("div",{className:"detail-section-body detail-section-body--loading",children:[e.jsx(B,{size:16,className:"spin"}),e.jsx("span",{className:"text-muted",children:"Loading employees..."})]})]}):e.jsxs("div",{className:"detail-section",children:[e.jsxs("div",{className:"detail-section-header",children:[e.jsx("h3",{children:"Employees"}),e.jsxs("span",{className:"text-muted",children:["(",o.length,")"]})]}),e.jsx("div",{className:"detail-section-body",children:o.length===0?e.jsxs("div",{className:"agent-empty agent-empty--padded",children:[e.jsx(tt,{size:32,opacity:.3}),e.jsx("p",{children:"No employees"}),e.jsx("p",{className:"text-muted",children:"This agent has no employees"})]}):e.jsx("div",{className:"agent-tree__children",children:o.map(d=>{const M=Ss[d.state];return e.jsxs("div",{className:"agent-tree__node agent-is-child",onClick:()=>i?.(d.id),role:"button",tabIndex:0,onKeyDown:k=>{(k.key==="Enter"||k.key===" ")&&(k.key===" "&&k.preventDefault(),i?.(d.id))},style:{cursor:i?"pointer":"default"},children:[e.jsx("span",{className:"agent-tree__icon",children:d.icon??"🤖"}),e.jsx("span",{className:"agent-tree__name",children:d.name}),e.jsx("span",{className:"agent-tree__badge",style:{background:M?.bg??"var(--state-idle-bg)",color:M?.text??"var(--state-idle-text)",border:`1px solid ${M?.border??"var(--state-idle-border)"}`},children:d.state})]},d.id)})})})]})}export{Qa as AgentDetailView,$e as relativeTime};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as s,a as ys,j as t}from"./vendor-react-K0fH_qHe.js";import{i as nt,b1 as It,t as Jt,b2 as ks,b3 as zt,b4 as Cs,w as Ct,b5 as $e,b6 as Ns,b7 as js,b8 as Ms,b9 as Rs,ba as As,bb as Es,s as Yt,bc as Ts,bd as Ps,be as Ds,bf as $s,bg as Ls,bh as Fs,bi as Is,k as Xt,bj as zs,p as _s,bk as Us,bl as Os,u as Hs,bm as Bs,ab as Qt,ac as Zt,bn as Ws,bo as Gs,S as Vs,W as _t,P as et,I as Ye,am as Ks,bp as Ut,bq as Ot,B as st,a8 as qs,a9 as Js,a as Ys,br as Xs,bs as Qs,bt as Zs,aQ as en,bu as tn,bv as Ht,bw as sn,h as nn,j as Bt,m as an}from"./index-CQyVRLOb.js";import"./vendor-xterm-DzcZoU0P.js";const St="kb-chat-active-session";function Wt(n){const r=typeof n=="string"?n.trim():"",o=r.indexOf("/");return!r||o<=0||o>=r.length-1?{}:{modelProvider:r.slice(0,o),modelId:r.slice(o+1)}}function rn(n){const r=n?.toolCalls;if(!Array.isArray(r))return;const o=r.map(d=>{if(!d||typeof d!="object")return null;const c=d,S=typeof c.toolName=="string"?c.toolName:"";if(!S)return null;const R=c.args;return{toolName:S,...R&&typeof R=="object"?{args:R}:{},isError:!!c.isError,result:c.result,status:"completed"}}).filter(d=>d!==null);return o.length>0?o:void 0}function on(n){const r=n?.fallback;if(!r||typeof r!="object")return;const o=r,d=typeof o.primaryModel=="string"?o.primaryModel:"",c=typeof o.fallbackModel=="string"?o.fallbackModel:"",S=o.triggerPoint;if(!(!d||!c||S!=="session-creation"&&S!=="prompt-time"))return{primaryModel:d,fallbackModel:c,triggerPoint:S}}function yt(n){return{id:n.id,sessionId:n.sessionId,role:n.role,content:n.content,thinkingOutput:n.thinkingOutput,toolCalls:rn(n.metadata),fallbackInfo:on(n.metadata),attachments:n.attachments,createdAt:n.createdAt}}function cn(n,r){const[o,d]=s.useState([]),[c,S]=s.useState(null),[R,A]=s.useState(!0),[D,y]=s.useState([]),[Y,p]=s.useState(!1),[K,C]=s.useState(!1),[Q,b]=s.useState(""),[E,m]=s.useState(""),[j,M]=s.useState([]),[T,I]=s.useState(""),[B,z]=s.useState(""),[G,v]=s.useState(!0),[h,u]=s.useState(new Map),i=s.useRef(null),f=s.useRef(!1),x=s.useRef(""),P=s.useRef(null),ye=s.useRef(o),W=s.useRef(c),ae=s.useRef(K);ye.current=o,W.current=c,ae.current=K,s.useEffect(()=>{x.current=T},[T]);const Fe=s.useRef(new Set),me=s.useRef(0),q=s.useRef(n);q.current!==n&&(q.current=n,me.current++),s.useEffect(()=>{const g=me.current;nt(void 0,n).then(k=>{if(me.current!==g)return;const w=new Map;for(const N of k)w.set(N.id,N);u(w)}).catch(()=>{})},[n]);const oe=s.useCallback(async()=>{A(!0);try{const k=[...(await It(n)).sessions].sort((w,N)=>new Date(N.updatedAt).getTime()-new Date(w.updatedAt).getTime());d(k)}catch{}finally{A(!1)}},[n]);s.useEffect(()=>{oe()},[oe]);const Ge=s.useRef(()=>{}),he=s.useRef(!1);s.useEffect(()=>{he.current=!1},[n]),s.useEffect(()=>{if(R||he.current||W.current)return;const g=Jt(St,n);if(!g){he.current=!0;return}const k=o.find(w=>w.id===g);if(k){he.current=!0,Ge.current(g,k);return}he.current=!0},[R,o,n]);const re=s.useCallback(async(g,k)=>{p(!0);try{const w=await ks(g,{limit:50,...k},n),N=w.messages.map(yt);k?.offset&&k.offset>0?y(ee=>[...N,...ee]):y(N),v(w.messages.length>=50)}catch{}finally{p(!1)}},[n]),je=s.useCallback(()=>{P.current?.(),P.current=null,x.current="",I(""),b(""),m(""),M([]),C(!1)},[]),fe=s.useCallback(g=>{if(i.current||!g)return!0;f.current=!1,C(!0);const{handlers:k}=zt({sessionId:g,tempUserMessageId:"",setStreamingText:b,setStreamingThinking:m,setStreamingToolCalls:M,cancelStreamingFlushesRef:P,addToast:r,onFallbackSession:(N,ee)=>{const F=Wt(N.fallbackModel);d(J=>J.map(Z=>Z.id===ee?{...Z,...F}:Z)),S(J=>J&&J.id===ee?{...J,...F}:J)},onDone:()=>{b(""),m(""),M([]),C(!1),ae.current=!1,i.current=null,re(g)},onError:N=>{b(""),m(""),M([]),C(!1),ae.current=!1,i.current=null;const ee=typeof N=="string"&&N.trim()?N:"Failed to get response";r?.(ee,"error"),re(g)}}),w=Cs(g,k,n);return i.current=w,!0},[r,re,n]),ce=s.useCallback((g,k)=>{const w=W.current?.id??null;if(g&&w===g&&!k)return;i.current&&(i.current.close(),i.current=null);const N=k??o.find(ee=>ee.id===g);S(N||null),je(),v(!0),g?re(g):y([]),N?.isGenerating&&(b(""),fe(N.id)),g?Ct(St,g,n):$e(St,n)},[fe,o,re,n,je]);Ge.current=ce;const ve=s.useCallback(async g=>{const k=await Ns(g,n);i.current&&(i.current.close(),i.current=null);const w={id:k.session.id,title:k.session.title,agentId:k.session.agentId,status:k.session.status,modelProvider:k.session.modelProvider,modelId:k.session.modelId,createdAt:k.session.createdAt,updatedAt:k.session.updatedAt};return d(N=>N.some(ee=>ee.id===w.id)?N:[w,...N]),je(),ce(w.id,w),y([]),w},[n,je,ce]),Ie=s.useCallback(async g=>{await js(g,{status:"archived"},n),d(k=>k.filter(w=>w.id!==g)),c?.id===g&&(S(null),y([]))},[c,n]),Me=s.useCallback(async g=>{c?.id===g&&i.current&&(i.current.close(),i.current=null),await Ms(g,n),d(k=>k.filter(w=>w.id!==g)),c?.id===g&&(S(null),y([]))},[c,n]),Re=s.useCallback(async()=>{!c||!G||await re(c.id,{offset:D.length})},[c,G,re,D.length]),ke=s.useCallback(()=>{c&&(f.current=!0,P.current?.(),P.current=null,i.current?.close(),i.current=null,Rs(c.id,n).catch(()=>{}),C(!1),b(""),m(""),M([]))},[c,n]),Ae=s.useCallback(()=>{x.current="",I("")},[]),ue=s.useRef(()=>{}),ie=As(),ge=s.useCallback((g,k)=>{if(!c)return;if(ae.current){x.current=g,I(g),r?.("Still waiting for previous response — message queued","warning");return}f.current=!1,i.current&&(i.current.close(),i.current=null);const w=`temp-${Date.now()}`,N={id:w,sessionId:c.id,role:"user",content:g,createdAt:new Date().toISOString()};y(F=>[...F,N]),b(""),m(""),M([]),C(!0);const{handlers:ee}=zt({sessionId:c.id,tempUserMessageId:w,setStreamingText:b,setStreamingThinking:m,setStreamingToolCalls:M,cancelStreamingFlushesRef:P,addToast:r,onFallbackSession:(F,J)=>{const Z=Wt(F.fallbackModel);d(te=>te.map(U=>U.id===J?{...U,...Z}:U)),S(te=>te&&te.id===J?{...te,...Z}:te)},onDone:({messageId:F,message:J,accumulated:Z})=>{const te=J?yt(J):{id:F||`msg-${Date.now()}`,sessionId:c.id,role:"assistant",content:Z.text,thinkingOutput:Z.thinking,toolCalls:Z.toolCalls.length>0?Z.toolCalls:void 0,fallbackInfo:Z.fallbackInfo,createdAt:new Date().toISOString()};Fe.current.add(te.id),y(O=>[...O,te]),b(""),m(""),M([]),C(!1),ae.current=!1,i.current=null,setTimeout(()=>{Fe.current.delete(te.id)},1e3),oe();const U=x.current.trim();U&&(x.current="",I(""),ue.current(U))},onError:(F,J)=>{y(U=>U.filter(O=>O.id!==J)),b(""),m(""),M([]),C(!1),ae.current=!1,i.current=null,console.error("[useChat] Stream error:",F);const Z=typeof F=="string"&&F.trim()?F:"Failed to get response";if(typeof F=="string"&&Ts(F)&&(ie.isHiddenNow()||ie.wasRecentlyHidden(5e3))?(console.info("[useChat] Suppressed tab-suspension stream error:",F),c?.id&&re(c.id)):r?.(Z,"error"),!f.current){const U=x.current.trim();U&&(x.current="",I(""),ue.current(U))}}});i.current=Es(c.id,g,ee,k,n)},[c,n,oe,r,re,ie]);ue.current=ge;const ze=B?o.filter(g=>g.title?.toLowerCase().includes(B.toLowerCase())||g.agentId.toLowerCase().includes(B.toLowerCase())):o;return s.useEffect(()=>{if(!W.current?.isGenerating||(i.current||fe(W.current.id),!ae.current||i.current||!W.current))return;const g=setInterval(async()=>{if(!ae.current||i.current||!W.current){clearInterval(g);return}try{(await It(n)).sessions.find(N=>N.id===W.current?.id)?.isGenerating||(clearInterval(g),await re(W.current.id),b(""),m(""),M([]),C(!1))}catch{}},3e3);return()=>clearInterval(g)},[fe,re,n,c]),s.useEffect(()=>{const g=me.current,k=n?`?projectId=${encodeURIComponent(n)}`:"",w=()=>me.current!==g,N=U=>{if(w())return;const O=JSON.parse(U.data);d($=>$.some(X=>X.id===O.id)?$:[O,...$])},ee=U=>{if(w())return;const O=JSON.parse(U.data);d($=>[...$.map(ne=>ne.id===O.id?O:ne)]),W.current?.id===O.id&&(S(O),O.isGenerating&&!i.current&&(b(""),fe(O.id)))},F=U=>{if(w())return;const{id:O}=JSON.parse(U.data);d($=>$.filter(X=>X.id!==O)),W.current?.id===O&&(S(null),y([]))},J=U=>{if(w())return;const O=JSON.parse(U.data),$=yt(O);if(!Fe.current.has($.id)){if(W.current?.id===$.sessionId&&ae.current&&!i.current&&$.role==="assistant"){y(X=>X.some(ne=>ne.id===$.id)?X:[...X,$]),b(""),m(""),M([]),C(!1);return}W.current?.id===$.sessionId&&!ae.current&&y(X=>{if(X.some(ne=>ne.id===$.id))return X;if($.role==="user"){const ne=X.findIndex(xe=>xe.role==="user"&&xe.id.startsWith("temp-")&&xe.content.trim()===$.content.trim());if(ne>=0){const xe=[...X];return xe[ne]=$,xe}}return[...X,$]})}},Z=U=>{if(w())return;const{id:O}=JSON.parse(U.data);y($=>$.filter(X=>X.id!==O))};return Yt(`/api/events${k}`,{events:{"chat:session:created":N,"chat:session:updated":ee,"chat:session:deleted":F,"chat:message:added":J,"chat:message:deleted":Z}})},[fe,n]),s.useEffect(()=>()=>{i.current&&(i.current.close(),i.current=null)},[]),{sessions:o,activeSession:c,sessionsLoading:R,messages:D,messagesLoading:Y,isStreaming:K,streamingText:Q,streamingThinking:E,streamingToolCalls:j,pendingMessage:T,selectSession:ce,createSession:ve,archiveSession:Ie,deleteSession:Me,sendMessage:ge,stopStreaming:ke,clearPendingMessage:Ae,loadMoreMessages:Re,hasMoreMessages:G,searchQuery:B,setSearchQuery:z,filteredSessions:ze,refreshSessions:oe,agentsMap:h}}const we="fusion:chat-active-room";function Nt(n){return[...n].sort((r,o)=>new Date(o.updatedAt).getTime()-new Date(r.updatedAt).getTime())}function Xe(n,r){const o=n.findIndex(c=>c.id===r.id);if(o===-1)return Nt([r,...n]);const d=[...n];return d[o]=r,Nt(d)}function Se(n){try{return JSON.parse(n.data)}catch{return null}}function ln(n,r){const[o,d]=s.useState([]),[c,S]=s.useState(!0),[R,A]=s.useState(null),[D,y]=s.useState(null),[Y,p]=s.useState([]),[K,C]=s.useState([]),[Q,b]=s.useState(!1),E=s.useRef(o),m=s.useRef(D),j=s.useRef(0),M=s.useRef(n);E.current=o,m.current=D,M.current!==n&&(M.current=n,j.current+=1);const T=s.useCallback(async(h,u=!0)=>{if(!h){p([]),C([]),b(!1);return}u&&C([]),b(!0);try{const[i,f]=await Promise.all([Ps(h.id,n),Ds(h.id,{limit:100},n)]);p(i.members),C(f.messages)}catch{p([]),C([])}finally{b(!1)}},[n]),I=s.useCallback(async()=>{S(!0);try{const h=await $s({},n),u=Nt(h.rooms);d(u),A(null);const i=Jt(we,n);if(i){const f=u.find(x=>x.id===i)??null;f?(y(f),T(f,!0)):$e(we,n)}}catch(h){const u=h instanceof Error?h.message:"Failed to load chat rooms";A(u),r?.(u,"error")}finally{S(!1)}},[r,T,n]),B=s.useCallback(h=>{if(!h){y(null),$e(we,n),T(null,!0);return}const u=E.current.find(i=>i.id===h)??null;y(u),u&&(Ct(we,u.id,n),T(u,!0))},[T,n]),z=s.useCallback(async h=>{const i=(await Ls({name:h.name,memberAgentIds:h.memberAgentIds},n)).room;return d(f=>Xe(f,i)),y(i),Ct(we,i.id,n),await T(i,!0),i},[T,n]),G=s.useCallback(async h=>{await Fs(h,n),d(u=>u.filter(i=>i.id!==h)),m.current?.id===h&&(y(null),p([]),C([]),$e(we,n))},[n]),v=s.useCallback(async(h,u)=>{const i=m.current?.id;if(!i)throw new Error("Select a room before sending a message");await Is(i,{content:h,...u?.attachments?{attachments:u.attachments}:{}},n)},[n]);return s.useEffect(()=>{I()},[I]),s.useEffect(()=>{const h=j.current,u=n?`/api/events?projectId=${encodeURIComponent(n)}`:"/api/events";return Yt(u,{onReconnect:()=>{I()},events:{"chat:room:created":i=>{if(j.current!==h)return;const f=Se(i);f&&d(x=>Xe(x,f))},"chat:room:updated":i=>{if(j.current!==h)return;const f=Se(i);f&&(d(x=>Xe(x,f)),m.current?.id===f.id&&y(f))},"chat:room:deleted":i=>{if(j.current!==h)return;const f=Se(i);f?.id&&(d(x=>x.filter(P=>P.id!==f.id)),m.current?.id===f.id&&(y(null),p([]),C([]),$e(we,n)))},"chat:room:member:added":i=>{if(j.current!==h)return;const f=Se(i);!f||m.current?.id!==f.roomId||p(x=>x.some(P=>P.agentId===f.agentId)?x:[...x,f])},"chat:room:member:removed":i=>{if(j.current!==h)return;const f=Se(i);!f||m.current?.id!==f.roomId||p(x=>x.filter(P=>P.agentId!==f.agentId))},"chat:room:message:added":i=>{if(j.current!==h)return;const f=Se(i);f&&(d(x=>{const P=x.find(ye=>ye.id===f.roomId);return P?Xe(x,{...P,updatedAt:f.createdAt}):x}),m.current?.id===f.roomId&&C(x=>x.some(P=>P.id===f.id)?x:[...x,f]))},"chat:room:message:updated":i=>{if(j.current!==h)return;const f=Se(i);!f||m.current?.id!==f.roomId||C(x=>x.map(P=>P.id===f.id?f:P))},"chat:room:message:deleted":i=>{if(j.current!==h)return;const f=Se(i);f?.id&&C(x=>x.filter(P=>P.id!==f.id))}}})},[n,I]),s.useEffect(()=>{D&&(o.some(h=>h.id===D.id)||(y(null),p([]),C([]),$e(we,n)))},[D,n,o]),{rooms:o,roomsLoading:c,roomsError:R,activeRoom:D,activeRoomMembers:Y,messages:K,messagesLoading:Q,selectRoom:B,createRoom:z,deleteRoom:G,sendRoomMessage:v,refreshRooms:I}}function dn(n,r=[]){const o=n.trim().replace(/^#/,"");if(!o)return{ok:!1,error:"Room name is required."};if(/[A-Z]/.test(o))return{ok:!1,error:"Use lowercase letters only."};const d=o.toLowerCase();return d.length>80?{ok:!1,error:"Room names can be at most 80 characters."}:/^[a-z0-9_-]+$/.test(d)?/^[-_]|[-_]$/.test(d)?{ok:!1,error:"Room names cannot start or end with a hyphen or underscore."}:r.some(c=>c.toLowerCase()===d)?{ok:!1,error:"A room with this name already exists."}:{ok:!0,name:d}:{ok:!1,error:"Use lowercase letters, numbers, hyphens, or underscores only."}}function un({isOpen:n,onClose:r,onCreate:o,projectId:d,existingRoomNames:c=[]}){const[S,R]=s.useState(""),[A,D]=s.useState([]),[y,Y]=s.useState(""),[p,K]=s.useState([]),[C,Q]=s.useState(!1),[b,E]=s.useState(null),[m,j]=s.useState(!1),M=s.useRef(null),T=s.useRef(null);s.useEffect(()=>{n&&(T.current=document.activeElement instanceof HTMLElement?document.activeElement:null,Q(!0),E(null),nt(void 0,d).then(u=>D(u)).catch(()=>{D([]),E("Failed to load agents.")}).finally(()=>Q(!1)))},[n,d]),s.useEffect(()=>{if(!n){R(""),Y(""),K([]),E(null),j(!1);return}const u=window.requestAnimationFrame(()=>M.current?.focus());return()=>window.cancelAnimationFrame(u)},[n]),s.useEffect(()=>{if(!n)return;const u=i=>{i.key==="Escape"&&r()};return document.addEventListener("keydown",u),()=>document.removeEventListener("keydown",u)},[n,r]),s.useEffect(()=>{n||T.current?.focus()},[n]);const I=s.useMemo(()=>dn(S,c),[S,c]),B=s.useMemo(()=>{const u=y.trim().toLowerCase();return u?A.filter(i=>i.name.toLowerCase().includes(u)):A},[A,y]),z=s.useMemo(()=>A.filter(u=>p.includes(u.id)),[A,p]),G=I.ok&&p.length>0&&!m&&!C;if(!n)return null;const v=u=>{m||K(i=>i.includes(u)?i.filter(f=>f!==u):[...i,u])},h=async()=>{if(!I.ok){E(I.error);return}if(p.length===0){E("Select at least one member.");return}E(null),j(!0);try{await o({name:I.name,displayName:`#${I.name}`,memberAgentIds:p}),r()}catch(u){E(u instanceof Error?u.message:"Failed to create room.")}finally{j(!1)}};return ys.createPortal(t.jsx("div",{className:"modal-overlay open",onClick:u=>u.target===u.currentTarget&&r(),children:t.jsxs("div",{className:"modal modal-lg create-room-modal",role:"dialog","aria-modal":"true","aria-label":"Create room",onClick:u=>u.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:M,id:"create-room-name",className:"input",value:S,disabled:m,onChange:u=>{const i=u.target.value.replace(/^#/,"").replace(/\s+/g,"-").toLowerCase();R(i)}})]}),!I.ok&&t.jsx("div",{className:"form-error",children:I.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:y,disabled:m,onChange:u=>Y(u.target.value)})]}),z.length>0&&t.jsx("div",{className:"create-room-modal-selected","data-testid":"create-room-selected-chips",children:z.map(u=>t.jsxs("button",{type:"button",className:"btn btn-sm create-room-modal-chip",onClick:()=>v(u.id),disabled:m,children:[u.name," ×"]},u.id))}),t.jsx("div",{className:"create-room-modal-member-list","data-testid":"create-room-member-list",children:C?t.jsx("div",{className:"create-room-modal-empty",children:"Loading agents..."}):B.length===0?t.jsx("div",{className:"create-room-modal-empty",children:A.length===0?"No agents in this project yet.":"No agents match your search."}):B.map(u=>{const i=p.includes(u.id);return t.jsxs("button",{type:"button",className:`create-room-modal-member-row${i?" create-room-modal-member-row--selected":""}`,onClick:()=>v(u.id),disabled:m,children:[t.jsx(Xt,{agent:u,size:20}),t.jsx("span",{children:u.name}),t.jsx("span",{className:"create-room-modal-member-role",children:u.role})]},u.id)})}),b&&t.jsx("div",{className:"form-group",children:t.jsx("div",{className:"form-error",children:b})}),t.jsxs("div",{className:"modal-actions",children:[t.jsx("button",{type:"button",className:"btn",onClick:r,disabled:m,children:"Cancel"}),t.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void h(),disabled:!G,children:m?"Creating...":"Create room"})]})]})}),document.body)}function es(n){const r=new Date(n),d=new Date().getTime()-r.getTime(),c=Math.floor(d/1e3),S=Math.floor(c/60),R=Math.floor(S/60),A=Math.floor(R/24);return c<60?"just now":S<60?`${S}m ago`:R<24?`${R}h ago`:A<7?`${A}d ago`:r.toLocaleDateString()}function Gt(n,r){if(!n||!r)return null;const o=r.toLowerCase();if(o.includes("claude")){let c=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 c=c.replace(/\s+/g," "),c.length>30?c.slice(0,30)+"…":c}if(o.includes("gpt")||o.includes("openai")){const c=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 c.length>30?c.slice(0,30)+"…":c}if(o.includes("gemini")){const c=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 c.length>30?c.slice(0,30)+"…":c}const d=r.replace(/-/g," ").replace(/^\w/,c=>c.toUpperCase()).replace(/\s+/g," ").trim();return d.length>30?d.slice(0,30)+"…":d}function tt(n,r){return n.length<=r?n:`${n.slice(0,r)}…`}function mn(n){if(!n)return null;const r=Object.entries(n);return r.length===0?null:r.map(([o,d])=>{const c=typeof d=="string"?d:(()=>{try{return JSON.stringify(d)}catch{return String(d)}})();return`${o}=${tt(c,50)}`}).join(", ")}function hn(n){if(n===void 0)return null;if(typeof n=="string")return tt(n,200);try{return tt(JSON.stringify(n),200)}catch{return tt(String(n),200)}}function ts(n){if(!n||n.length===0)return null;const r=(p,K)=>{const C=p.status==="running",Q=p.status==="completed"&&p.isError,b=mn(p.args),E=hn(p.result),m=C?b:E?`result: ${E}`:b?`args: ${b}`:null,j=C?"running":Q?"error":"completed";return t.jsxs("details",{className:`chat-tool-call${C?" chat-tool-call--running":""}${Q?" chat-tool-call--error":""}`,open:C,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:p.toolName,children:p.toolName}),m&&t.jsx("span",{className:"chat-tool-call-preview",title:m,children:m}),t.jsx("span",{className:"chat-tool-call-status-text",children:j})]}),t.jsxs("div",{className:"chat-tool-call-content",children:[b&&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:b})]}),E&&t.jsxs("div",{className:`chat-tool-call-row${Q?" 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:E})]})]})]},`${p.toolName}-${K}`)},o="chat-tool-calls";if(n.length===1)return t.jsxs("div",{className:o,"data-testid":"chat-tool-calls",children:[t.jsxs("div",{className:"chat-tool-calls-header",children:[t.jsx(Ht,{size:12,"aria-hidden":"true"}),t.jsx("span",{children:"Tool calls"})]}),r(n[0],0)]});const d=n.filter(p=>p.status==="running").length,c=n.filter(p=>p.status==="completed"&&p.isError).length,S=d>0,R=Array.from(new Set(n.map(p=>p.toolName))),A=R.slice(0,5),D=Math.max(0,R.length-A.length),y=D>0?`${A.join(", ")}, +${D} more`:A.join(", "),Y=S?`(${d} running)`:c>0?`(${c} ${c===1?"error":"errors"})`:null;return t.jsx("div",{className:o,"data-testid":"chat-tool-calls",children:t.jsxs("details",{className:"chat-tool-calls-group","data-testid":"chat-tool-calls-group",open:S,children:[t.jsxs("summary",{className:"chat-tool-calls-group-summary",children:[t.jsx(Ht,{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:y,children:y}),Y&&t.jsx("span",{className:"chat-tool-calls-group-status",children:Y})]}),n.map((p,K)=>r(p,K))]})})}const ss={pre:({children:n,...r})=>t.jsx("pre",{...r,className:"chat-markdown-pre",children:n}),table:({children:n,...r})=>t.jsx("table",{...r,className:"chat-markdown-table",children:n})},Le="__fn_agent__",fn=280,Qe=180,Ze=500,Vt="fusion:chat-sidebar-width",Kt="fusion:chat-scope",gn=["image/png","image/jpeg","image/gif","image/webp","text/plain","application/json","text/yaml","text/markdown","text/csv","application/xml","text/x-log"];function qt(n){const r=/(^|[\s])\/([^\s]*)$/.exec(n);if(!r)return null;const o=r[1]??"",d=r[2]??"",c=r.index+o.length;return{filter:d,start:c,end:n.length}}function pn(n,r){const o=n.slice(0,r),d=/(^|[\s\n])@([\w-]*)$/.exec(o);if(!d)return null;const c=d[2]??"",S=o.length-c.length-1;return{filter:c,start:S,end:r}}function bn({projectId:n,onClose:r,onCreate:o}){const[d,c]=s.useState("agent"),[S,R]=s.useState([]),[A,D]=s.useState(!0),[y,Y]=s.useState(""),[p,K]=s.useState([]),[C,Q]=s.useState(!0),[b,E]=s.useState(""),[m,j]=s.useState([]),[M,T]=s.useState([]);s.useEffect(()=>{let v=!1;return D(!0),nt(void 0,n).then(h=>{v||R(h)}).catch(()=>{v||R([])}).finally(()=>{v||D(!1)}),()=>{v=!0}},[n]),s.useEffect(()=>{Q(!0),nn().then(v=>{K(v.models),j(v.favoriteProviders),T(v.favoriteModels)}).catch(()=>{K([]),j([]),T([])}).finally(()=>{Q(!1)})},[]);const I=s.useCallback(async v=>{const h=m,i=h.includes(v)?h.filter(f=>f!==v):[v,...h];j(i);try{await Bt({favoriteProviders:i,favoriteModels:M})}catch{j(h)}},[m,M]),B=s.useCallback(async v=>{const h=M,i=h.includes(v)?h.filter(f=>f!==v):[v,...h];T(i);try{await Bt({favoriteProviders:m,favoriteModels:i})}catch{T(h)}},[M,m]),z=v=>{if(v.preventDefault(),d==="agent"){if(!y)return;o({agentId:y});return}if(!b)return;const h=b.indexOf("/");if(h<=0)return;const u=b.slice(0,h),i=b.slice(h+1);o({agentId:Le,modelProvider:u,modelId:i})},G=d==="agent"?!y:!b;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:v=>v.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${d==="agent"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-agent",onClick:()=>{c("agent"),E("")},children:"Agent"}),t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${d==="model"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-model",onClick:()=>{c("model"),Y("")},children:"Model"})]}),t.jsxs("form",{onSubmit:z,children:[d==="agent"&&t.jsxs("label",{className:"chat-new-dialog-model-label",children:["Agent",A?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading agents..."}):S.length===0?t.jsx("div",{className:"chat-new-dialog-empty",children:"No agents available"}):t.jsx("div",{className:"chat-new-dialog-agent-list",children:S.map(v=>t.jsxs("button",{type:"button",className:`chat-new-dialog-agent-item${y===v.id?" chat-new-dialog-agent-item--selected":""}`,onClick:()=>Y(v.id),"data-testid":`agent-option-${v.id}`,children:[t.jsx(st,{size:16}),t.jsx("span",{className:"chat-new-dialog-agent-name",children:v.name}),t.jsx("span",{className:"chat-new-dialog-agent-role",children:v.role})]},v.id))})]}),d==="model"&&t.jsx("div",{className:"chat-new-dialog-model-dropdown","data-testid":"chat-new-dialog-model-section",children:C?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading models..."}):t.jsx(an,{models:p,value:b,onChange:E,label:"Model",placeholder:"Select a model",favoriteProviders:m,onToggleFavorite:I,favoriteModels:M,onToggleModelFavorite:B})}),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:G,children:"Create"})]})]})]})})}const kt=s.memo(function({message:r,forcePlain:o,agentName:d,hideAssistantIdentity:c,showAssistantModelTag:S,activeModelTag:R,activeModelProvider:A,activeSessionId:D,mentionAgentsByName:y,copyAction:Y}){const p=r.role==="assistant",K=s.useMemo(()=>{if(p)return null;const b=r.content,E=/@([\w-]+)/g,m=[];let j=0,M=E.exec(b);for(;M;){const[T,I=""]=M,B=M.index;B>j&&m.push(b.slice(j,B));const z=I.replace(/_/g," ").toLowerCase(),G=y.get(z);G?m.push(t.jsxs("span",{className:"chat-mention-chip",children:["@",G.name.replace(/\s+/g,"_")]},`${G.id}-${B}`)):m.push(T),j=B+T.length,M=E.exec(b)}return j<b.length&&m.push(b.slice(j)),m.length===0?b:m},[p,r.content,y]),C=s.useMemo(()=>{const b=r.attachments;if(!b||b.length===0||!D)return null;const E=`/api/chat/sessions/${encodeURIComponent(D)}/attachments/`;return t.jsx("div",{className:"chat-message-attachments",children:b.map(m=>{const j=m.mimeType.startsWith("image/"),M=m.id||m.filename,T=`${E}${encodeURIComponent(m.filename)}`;return j?t.jsx("a",{className:"chat-message-attachment-link","data-testid":"chat-message-attachment",href:T,target:"_blank",rel:"noopener noreferrer",children:t.jsx("img",{className:"chat-message-attachment",src:T,alt:m.originalName})},M):t.jsxs("a",{className:"chat-message-attachment-file","data-testid":"chat-message-attachment",href:T,target:"_blank",rel:"noopener noreferrer",children:[t.jsx(tn,{size:14}),t.jsx("span",{children:m.originalName})]},M)})})},[r.attachments,D]),Q=s.useMemo(()=>p?o?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(Qt,{remarkPlugins:[Zt],components:ss,children:r.content})}):null,[p,o,r.content]);return t.jsxs("div",{className:`chat-message chat-message--${r.role}`,"data-testid":`chat-message-${r.id}`,children:[p&&!c&&t.jsxs("div",{className:"chat-message-avatar",children:[A?t.jsx(et,{provider:A,size:"sm"}):t.jsx(st,{size:14}),t.jsx("span",{children:d}),S&&R&&t.jsx("span",{className:"chat-model-tag",children:R})]}),p?Q:t.jsx("div",{className:"chat-message-content",children:K}),Y,ts(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:r.thinkingOutput})]}),C,t.jsx("div",{className:"chat-message-time",children:es(r.createdAt)})]})});function yn({projectId:n,addToast:r}){const{activeSession:o,sessionsLoading:d,messages:c,messagesLoading:S,isStreaming:R,streamingText:A,streamingThinking:D,streamingToolCalls:y,selectSession:Y,createSession:p,archiveSession:K,deleteSession:C,sendMessage:Q,stopStreaming:b,pendingMessage:E,clearPendingMessage:m,searchQuery:j,setSearchQuery:M,filteredSessions:T}=cn(n,r),[I,B]=s.useState(!1),[z,G]=s.useState(""),[v,h]=s.useState(null),[u,i]=s.useState(null),[f,x]=s.useState(!0),[P,ye]=s.useState(fn),[W,ae]=s.useState("direct"),[Fe,me]=s.useState(!1),q=ln(n,r),[oe,Ge]=s.useState(new Map),[he,re]=s.useState([]),[je,fe]=s.useState(!0),[ce,ve]=s.useState(!1),[Ie,Me]=s.useState(""),[Re,ke]=s.useState(0),[Ae,ue]=s.useState(""),[ie,ge]=s.useState(!1),[ze,g]=s.useState(0),[k,w]=s.useState(-1),[N,ee]=s.useState(!1),[F,J]=s.useState([]),[Z,te]=s.useState(!1),[U,O]=s.useState(!1),[$,X]=s.useState({}),[,ne]=s.useState(!1),[xe,ns]=s.useState({top:0,left:0}),_=zs({projectId:n}),at=s.useCallback(e=>{if(!e||!_.mentionActive)return;const a=e.getBoundingClientRect();ns({top:a.top-260,left:a.left+8})},[_.mentionActive]),jt=s.useRef(null),rt=s.useRef(!1),ot=s.useRef(null),pe=s.useRef(null),Ee=s.useRef(null),se=s.useRef(null),Mt=s.useRef(null),Rt=s.useRef([]),_e=s.useRef(0),Ue=s.useRef(new Map),V=_s()==="mobile";s.useEffect(()=>{try{const e=localStorage.getItem(Vt);if(!e)return;const a=Number.parseInt(e,10);if(Number.isNaN(a))return;const l=Math.max(Qe,Math.min(Ze,a));ye(l)}catch{}},[]),s.useEffect(()=>{try{const e=localStorage.getItem(Kt);(e==="direct"||e==="rooms")&&ae(e)}catch{}},[]),s.useEffect(()=>{try{localStorage.setItem(Kt,W)}catch{}},[W]);const{keyboardOverlap:Ve,viewportHeight:At,viewportOffsetTop:Et,keyboardOpen:Oe}=Us({enabled:V&&!!o}),Tt=Ve>0||Et>0,as=Oe&&Tt?{"--keyboard-overlap":`${Ve}px`,"--vv-offset-top":`${Et}px`,...At!==null?{"--vv-height":`${At}px`}:{}}:{},le=s.useMemo(()=>{const e=Ie.trim().toLowerCase();return(e?he.filter(l=>l.name.toLowerCase().includes(e)):he).slice(0,10)},[he,Ie]),He=s.useMemo(()=>Array.from(oe.values()),[oe]),Ce=s.useMemo(()=>He.filter(e=>Os(e.name,Ae)),[He,Ae]),it=s.useMemo(()=>{const e=new Map;for(const a of He)e.set(a.name.toLowerCase(),a);return e},[He]);s.useEffect(()=>{ke(0)},[le]),s.useEffect(()=>{g(0)},[Ae,ie]),s.useEffect(()=>()=>{pe.current!==null&&window.clearTimeout(pe.current)},[]);const Pt=s.useCallback(()=>{const e=Ee.current;if(!e)return;const l=e.scrollTop+e.clientHeight>=e.scrollHeight-50;O(!l),rt.current=!l},[]),Ke=s.useCallback(e=>{if(!e.isConnected)return;let a=0,l=0,L=-1;const H=6,de=()=>{if(e.isConnected){if(e.scrollTop=e.scrollHeight,e.scrollHeight===L?l+=1:(l=0,L=e.scrollHeight),a+=1,a>=H||l>=2){O(!1),rt.current=!1;return}window.requestAnimationFrame(de)}};de()},[]),Be=s.useCallback(()=>{const e=Ee.current;e&&Ke(e)},[Ke]);s.useLayoutEffect(()=>{const e=o?.id??null;if(!e){ot.current=null;return}const a={sessionId:e,loaded:!S,hasMessages:c.length>0},l=ot.current,L=l?.sessionId!==e,H=l?.sessionId===e&&!l.loaded&&a.loaded,de=l?.sessionId===e&&!l.hasMessages&&a.hasMessages;if(!(l===null||L||H||de))return;const be=Ee.current;be&&(Ke(be),ot.current=a)},[o?.id,c.length,S,Ke]),s.useEffect(()=>{rt.current||Be()},[c,A,D,R,Be]),s.useEffect(()=>{Ve<=0||!Ee.current||Be()},[Ve,Be]),Hs(V&&Oe),s.useEffect(()=>{const e=()=>h(null);if(v)return document.addEventListener("click",e),()=>document.removeEventListener("click",e)},[v]),s.useEffect(()=>{if(!V||!Oe)return;const e=a=>{a.target?.closest(".chat-messages")||a.preventDefault()};return document.addEventListener("touchmove",e,{passive:!1}),()=>{document.removeEventListener("touchmove",e)}},[V,Oe]),s.useEffect(()=>{if(!V||!o)return;const e=()=>{const a=se.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)}},[V,o]),s.useEffect(()=>{let e=!1;const a=n;return nt(void 0,n).then(l=>{if(e||a!==n)return;const L=new Map;for(const H of l)L.set(H.id,H);Ge(L)}).catch(()=>{}),()=>{e=!0}},[n]),s.useEffect(()=>{let e=!1;return fe(!0),Bs(n).then(a=>{e||re(a)}).catch(()=>{e||re([])}).finally(()=>{e||fe(!1)}),()=>{e=!0}},[n]),s.useEffect(()=>{Rt.current=F},[F]),s.useEffect(()=>()=>{for(const e of Rt.current)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);for(const e of Ue.current.values())window.clearTimeout(e);Ue.current.clear()},[]);const qe=s.useCallback(e=>{if(!e||e.length===0)return;const a=[];for(const l of Array.from(e)){if(!gn.includes(l.type))continue;const L=l.type.startsWith("image/");a.push({file:l,previewUrl:L?URL.createObjectURL(l):""})}a.length>0&&J(l=>[...l,...a])},[]),rs=s.useCallback(e=>{J(a=>{const l=a[e];return l?.previewUrl&&URL.revokeObjectURL(l.previewUrl),a.filter((L,H)=>H!==e)})},[]),os=s.useCallback(e=>{const a=e.clipboardData?.files;if(!a||a.length===0)return;const l=Array.from(a).filter(L=>L.type.startsWith("image/"));l.length!==0&&qe(l)},[qe]),is=s.useCallback(async e=>{try{await p(e),B(!1),V&&x(!1)}catch{r("Failed to create chat session","error")}},[p,r,V]),ct=s.useCallback(()=>{G(""),ve(!1),Me(""),ge(!1),ue(""),w(-1),J(e=>{for(const a of e)a.previewUrl&&URL.revokeObjectURL(a.previewUrl);return[]})},[]),lt=s.useCallback(()=>{const e=z.trim(),a=F.map(l=>l.file);if(!(!e&&a.length===0||!o)){if(e==="/clear"){ct(),b(),m(),p({agentId:o.agentId,modelProvider:o.modelProvider??void 0,modelId:o.modelId??void 0}).catch(()=>{r("Failed to clear conversation","error")});return}ct(),Q(e,a)}},[z,F,o,ct,b,m,p,r,Q]),dt=s.useCallback(e=>{G(a=>{const l=qt(a);if(!l)return a;const L=`/skill:${e.name} `,H=a.slice(0,l.start)+L+a.slice(l.end);return window.requestAnimationFrame(()=>{se.current&&(se.current.style.height="auto",se.current.style.height=`${Math.min(se.current.scrollHeight,120)}px`,se.current.focus())}),H}),ve(!1),Me(""),ke(0)},[]),ut=s.useCallback(e=>{const a=se.current;if(!a||k<0)return;const l=a.selectionStart??_e.current,L=a.selectionEnd??l,H=Math.max(l,L),de=Math.min(k,H),be=`${`@${e.name.replace(/\s+/g,"_")}`} `,wt=z.slice(0,de)+be+z.slice(H),De=de+be.length;G(wt),ge(!1),ue(""),g(0),w(-1),window.requestAnimationFrame(()=>{se.current&&(se.current.style.height="auto",se.current.style.height=`${Math.min(se.current.scrollHeight,120)}px`,se.current.focus(),se.current.setSelectionRange(De,De))})},[k,z]),Dt=s.useCallback(e=>{if(_e.current=e.currentTarget.selectionStart??_e.current,_.mentionActive&&_.files.length>0){if(_.handleKeyDown(e,z),e.key==="Enter"||e.key==="Tab"){const a=_.files[_.selectedIndex];if(a){const l=_.selectFile(a,z);G(l),_.dismissMention(),ne(!1)}}return}if(ie&&e.key==="ArrowDown"){e.preventDefault(),Ce.length>0&&g(a=>(a+1)%Ce.length);return}if(ie&&e.key==="ArrowUp"){e.preventDefault(),Ce.length>0&&g(a=>a===0?Ce.length-1:a-1);return}if(ie&&e.key==="Enter"){e.preventDefault();const a=Ce[ze]??Ce[0];a&&ut(a);return}if(ie&&e.key==="Escape"){e.preventDefault(),ge(!1),ue(""),w(-1);return}if(ce&&e.key==="ArrowDown"){e.preventDefault(),le.length>0&&ke(a=>(a+1)%le.length);return}if(ce&&e.key==="ArrowUp"){e.preventDefault(),le.length>0&&ke(a=>a===0?le.length-1:a-1);return}if(ce&&(e.key==="Enter"||e.key==="Tab")&&le.length>0){e.preventDefault();const a=le[Re]??le[0];a&&dt(a);return}if(ce&&e.key==="Escape"){e.preventDefault(),ve(!1);return}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),lt())},[ie,Ce,ze,ut,ce,le,Re,dt,lt,_,z]),Je=s.useCallback((e,a)=>{const l=pn(e,a);if(l){ge(!0),ue(l.filter),w(l.start);return}ge(!1),ue(""),w(-1)},[]),$t=s.useCallback(e=>{const a=e.target,l=a.value,L=a.selectionStart??l.length;_e.current=L,G(l);const H=qt(l);H?(ve(!0),Me(H.filter)):(ve(!1),Me("")),Je(l,L),_.detectMention(l,L),ne(_.mentionActive),_.mentionActive&&at(a),a.style.height="auto",a.style.height=`${Math.min(a.scrollHeight,120)}px`},[Je]),mt=s.useCallback(e=>{const a=e.currentTarget,l=a.selectionStart??a.value.length;_e.current=l,Je(a.value,l),_.detectMention(a.value,l),ne(_.mentionActive),_.mentionActive&&at(a)},[Je,_,at]),cs=s.useCallback(e=>{e.key!=="Escape"&&mt(e)},[mt]),ls=s.useCallback(()=>{pe.current!==null&&window.clearTimeout(pe.current),pe.current=window.setTimeout(()=>{ve(!1),ge(!1),ue(""),w(-1),ne(!1),_.dismissMention(),pe.current=null},120)},[_]),ds=s.useCallback(()=>{pe.current!==null&&(window.clearTimeout(pe.current),pe.current=null),typeof window<"u"&&window.innerWidth<=768&&window.setTimeout(()=>{(window.scrollY!==0||window.scrollX!==0)&&window.scrollTo(0,0)},0)},[]),us=s.useCallback(async e=>{h(null);try{await K(e),r("Conversation archived","success")}catch{r("Failed to archive conversation","error")}},[K,r]),ms=s.useCallback(async e=>{i(null),h(null);try{await C(e),r("Conversation deleted","success")}catch{r("Failed to delete conversation","error")}},[C,r]),We=s.useCallback(e=>{try{localStorage.setItem(Vt,String(e))}catch{}},[]),hs=s.useCallback(e=>{if(V)return;e.preventDefault(),e.stopPropagation();const a=e.currentTarget;typeof a.setPointerCapture=="function"&&a.setPointerCapture(e.pointerId);const l=e.clientX,L=P;let H=L;document.body.style.userSelect="none";const de=be=>{const wt=be.clientX-l,De=Math.max(Qe,Math.min(Ze,L+wt));H=De,ye(De),We(De)},Pe=be=>{typeof a.releasePointerCapture=="function"&&a.releasePointerCapture(be.pointerId),document.body.style.userSelect="",document.removeEventListener("pointermove",de),document.removeEventListener("pointerup",Pe),We(H)};document.addEventListener("pointermove",de),document.addEventListener("pointerup",Pe)},[V,We,P]),fs=s.useCallback(e=>{if(V||e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;e.preventDefault();const a=e.shiftKey?50:10,l=e.key==="ArrowLeft"?-a:a,L=Math.max(Qe,Math.min(Ze,P+l));ye(L),We(L)},[V,We,P]),gs=s.useCallback(e=>{Y(e),V&&x(!1)},[Y,V]),ps=s.useCallback(()=>{Y(""),x(!0)},[Y]),bs=()=>t.jsxs("div",{className:"chat-empty-state",children:[t.jsx(sn,{size:48,strokeWidth:1.5}),t.jsx("h2",{children:"Start a new conversation"}),t.jsxs("button",{className:"btn btn-primary",onClick:()=>B(!0),children:[t.jsx(Ye,{size:16}),"New Chat"]})]}),Ne=Gt(o?.modelProvider,o?.modelId),Te=o?.modelProvider??null,ht=!!(o||R||c.length>0),Lt=o?.agentId===Le?Ne??"Fusion":o?.title||oe.get(o?.agentId??"")?.name||o?.agentId||"Chat",vs=!!(Ne&&Ne!==Lt),ft=oe.get(o?.agentId??"")?.name||(o?.agentId===Le?Ne??"Fusion":o?.agentId?.slice(0,30)??"Fusion"),gt=!1,pt=o?.agentId===Le,xs=E.length>50?`${E.slice(0,50)}…`:E,ws=s.useCallback(()=>{ee(e=>!e)},[]),bt=s.useCallback((e,a)=>{const l=Ue.current.get(e);l&&window.clearTimeout(l),X(H=>({...H,[e]:a}));const L=window.setTimeout(()=>{X(H=>{const{[e]:de,...Pe}=H;return Pe}),Ue.current.delete(e)},2e3);Ue.current.set(e,L)},[]),Ft=s.useCallback(async(e,a)=>{try{if(!navigator.clipboard?.writeText)throw new Error("Clipboard API unavailable");await navigator.clipboard.writeText(a),bt(e,"success")}catch{bt(e,"error")}},[bt]),Ss=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(Qt,{remarkPlugins:[Zt],components:ss,children:e})}),[]),vt=o?.agentId===Le,xt=s.useCallback((e,a,l)=>t.jsx("button",{type:"button",className:`btn-icon chat-message-copy-action${$[e]==="success"?" chat-message-copy-action--success":""}${$[e]==="error"?" chat-message-copy-action--error":""}`,"data-testid":l??`chat-copy-response-${e}`,"aria-label":$[e]==="success"?"Response copied":$[e]==="error"?"Copy failed":"Copy response",onClick:()=>{Ft(e,a)},children:$[e]==="success"?t.jsx(Ws,{size:14}):t.jsx(Gs,{size:14})}),[$,Ft]);return t.jsxs("div",{className:"chat-view",children:[t.jsxs("div",{className:`chat-sidebar${f?"":" chat-sidebar--hidden"}`,style:V?void 0:{width:`${P}px`},children:[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${W==="direct"?" chat-sidebar-scope-btn--active":""}`,"aria-selected":W==="direct","data-testid":"chat-sidebar-scope-direct",onClick:()=>ae("direct"),children:"Direct"}),t.jsx("button",{type:"button",role:"tab",className:`chat-sidebar-scope-btn${W==="rooms"?" chat-sidebar-scope-btn--active":""}`,"aria-selected":W==="rooms","data-testid":"chat-sidebar-scope-rooms",onClick:()=>ae("rooms"),children:"Rooms"})]}),W==="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(Vs,{size:14,className:"chat-sidebar-search-icon"}),t.jsx("input",{type:"text",className:"chat-sidebar-search",placeholder:"Search conversations...",value:j,onChange:e=>M(e.target.value),"data-testid":"chat-search-input"})]})}),t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:d?t.jsx("div",{style:{padding:"12px",color:"var(--text-secondary)",fontSize:"13px"},children:"Loading..."}):T.length===0?t.jsx("div",{style:{padding:"12px",color:"var(--text-secondary)",fontSize:"13px"},children:"No conversations yet"}):T.map(e=>t.jsxs("div",{className:`chat-session-item${o?.id===e.id?" chat-session-item--active":""}`,onClick:()=>gs(e.id),onContextMenu:a=>{a.preventDefault(),h({sessionId:e.id,x:a.clientX,y:a.clientY})},"data-testid":`chat-session-${e.id}`,children:[t.jsx("button",{className:"chat-session-delete-btn",onClick:a=>{a.stopPropagation(),i(e.id)},"data-testid":"chat-session-delete-btn","aria-label":"Delete conversation",children:t.jsx(_t,{size:14})}),t.jsx("div",{className:"chat-session-title",children:e.title||"Untitled"}),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:[e.modelProvider&&t.jsx(et,{provider:e.modelProvider,size:"sm"}),t.jsx("span",{children:oe.get(e.agentId)?.name||(e.agentId===Le?Gt(e.modelProvider,e.modelId)??"Fusion":e.agentId.slice(0,30))})]}),t.jsx("span",{children:e.updatedAt?es(e.updatedAt):""})]})]},e.id))})]}):t.jsxs("div",{className:"chat-sidebar-rooms","data-testid":"chat-sidebar-rooms",children:[t.jsx("div",{className:"chat-sidebar-rooms-header",children:t.jsxs("button",{type:"button",className:"btn btn-sm btn-primary","data-testid":"chat-create-room-btn",onClick:()=>me(!0),children:[t.jsx(Ye,{size:14}),"Create room"]})}),q.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:q.rooms.map(e=>{const a=q.activeRoom?.id===e.id,l=a?q.activeRoomMembers.length:"—";return t.jsxs("button",{type:"button",className:`chat-room-item${a?" chat-room-item--active":""}`,"data-testid":`chat-room-item-${e.slug}`,onClick:()=>{q.selectRoom(e.id),V&&x(!1)},children:[t.jsxs("span",{className:"chat-room-item-name",children:["#",e.name]}),t.jsxs("span",{className:"chat-room-item-meta",children:[l," ",l===1?"member":"members"]})]},e.id)})})]}),t.jsx("div",{className:"chat-sidebar-footer",children:t.jsxs("button",{className:"btn btn-sm btn-primary chat-sidebar-footer-btn",onClick:()=>B(!0),"data-testid":"chat-new-btn",children:[t.jsx(Ye,{size:14}),"New Chat"]})})]}),!V&&f&&t.jsx("div",{className:"chat-sidebar-resize-handle",role:"separator","aria-orientation":"vertical","aria-valuemin":Qe,"aria-valuemax":Ze,"aria-valuenow":P,"aria-label":"Resize chat sidebar",tabIndex:0,onPointerDown:hs,onKeyDown:fs}),v&&t.jsxs("div",{className:"chat-session-context-menu",style:{top:v.y,left:v.x},onClick:e=>e.stopPropagation(),children:[t.jsxs("button",{onClick:()=>us(v.sessionId),"data-testid":"chat-context-archive",children:[t.jsx(Ks,{size:14}),"Archive"]}),t.jsxs("button",{onClick:()=>{h(null),i(v.sessionId)},"data-testid":"chat-context-delete",children:[t.jsx(_t,{size:14}),"Delete"]})]}),u&&t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:()=>i(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:()=>i(null),children:"Cancel"}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void ms(u),children:"Delete"})]})]})}),W==="rooms"?t.jsxs("div",{className:"chat-thread",children:[q.activeRoom?t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"chat-room-thread-header",children:[V&&t.jsx("button",{className:"btn-icon",onClick:()=>{q.selectRoom(null),x(!0)},"data-testid":"chat-back-btn",children:t.jsx(Ut,{size:16})}),t.jsxs("div",{className:"chat-thread-header-title",children:["#",q.activeRoom.name]}),t.jsx("div",{className:"chat-room-thread-members",children:q.activeRoomMembers.map(e=>t.jsx(Xt,{agent:oe.get(e.agentId)??null},e.agentId))})]}),t.jsxs("div",{className:"chat-messages",ref:Ee,onScroll:Pt,children:[q.messagesLoading?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"Loading messages..."}):q.messages.length===0?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"No messages yet. Start the conversation!"}):q.messages.map(e=>{const a=e.senderAgentId?oe.get(e.senderAgentId)?.name??e.senderAgentId.slice(0,30):"You",l={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(kt,{message:l,forcePlain:N,agentName:a,hideAssistantIdentity:!1,showAssistantModelTag:!1,activeModelTag:null,activeModelProvider:null,activeSessionId:q.activeRoom?.id??null,mentionAgentsByName:it},e.id)}),t.jsx("div",{ref:jt})]})]}):t.jsx("div",{className:"chat-room-empty-pane","data-testid":"chat-rooms-empty-pane",children:"Select a room or create one"}),q.activeRoom&&t.jsx("div",{className:"chat-input-area",children:t.jsxs("div",{className:"chat-input-row",children:[t.jsx("div",{className:"chat-input-wrapper",children:t.jsx("textarea",{ref:se,className:"chat-input-textarea",placeholder:"Type a message...",value:z,onChange:$t,onKeyDown:Dt,rows:1,"data-testid":"chat-input"})}),t.jsx("button",{type:"button",className:"chat-input-send",onClick:()=>{const e=z.trim();e&&q.sendRoomMessage(e).then(()=>{G("")})},disabled:!z.trim(),"data-testid":"chat-send-btn",style:{touchAction:"manipulation"},children:t.jsx(Ot,{size:16})})]})})]}):t.jsxs("div",{className:`chat-thread${Oe&&Tt?" chat-thread--keyboard-active":""}`,style:as,children:[(ht||!V)&&t.jsxs("div",{className:"chat-thread-header",children:[V&&ht&&t.jsx("button",{className:"btn-icon",onClick:ps,"data-testid":"chat-back-btn",children:t.jsx(Ut,{size:16})}),t.jsxs("div",{className:"chat-thread-header-identity","data-testid":"chat-thread-header-identity",children:[Te?t.jsx(et,{provider:Te,size:"md"}):t.jsx(st,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:Lt}),vs&&t.jsx("span",{className:"chat-model-tag",children:Ne})]}),ht&&t.jsx("button",{type:"button",className:`chat-thread-header-render-toggle${N?" chat-thread-header-render-toggle--plain":""}`,"data-testid":"chat-thread-render-toggle","aria-label":N?"Show all messages as rendered Markdown":"Show all messages as plain text",onClick:ws,children:N?t.jsx(qs,{size:14}):t.jsx(Js,{size:14})}),!V&&t.jsxs("button",{className:"btn btn-sm btn-primary chat-thread-header-new-chat",onClick:()=>B(!0),"data-testid":"chat-thread-new-chat-btn",children:[t.jsx(Ye,{size:14}),"New Chat"]})]}),t.jsxs("div",{className:"chat-messages",ref:Ee,onScroll:Pt,children:[R?t.jsxs(t.Fragment,{children:[c.map(e=>t.jsx(kt,{message:e,forcePlain:N,agentName:ft,hideAssistantIdentity:pt,showAssistantModelTag:gt,activeModelTag:Ne,activeModelProvider:Te,activeSessionId:o?.id??null,mentionAgentsByName:it,copyAction:vt&&e.role==="assistant"?xt(e.id,e.content):void 0},e.id)),t.jsxs("div",{className:"chat-message chat-message--assistant chat-message--streaming",children:[!pt&&t.jsxs("div",{className:"chat-message-avatar",children:[Te?t.jsx(et,{provider:Te,size:"sm"}):t.jsx(st,{size:14}),t.jsx("span",{children:ft}),gt]}),A?Ss(A,N):t.jsx("div",{className:"chat-message-content chat-message-content--waiting",children:D?"Thinking…":"Connecting…"}),vt&&A&&xt("__streaming__",A,"chat-copy-response-streaming"),ts(y),D&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:D})]}),t.jsxs("div",{className:"chat-typing-indicator",children:[t.jsx("span",{}),t.jsx("span",{}),t.jsx("span",{})]})]})]}):S?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"Loading messages..."}):c.length===0&&!o?bs():c.length===0&&o?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"No messages yet. Start the conversation!"}):t.jsx(t.Fragment,{children:c.map(e=>t.jsx(kt,{message:e,forcePlain:N,agentName:ft,hideAssistantIdentity:pt,showAssistantModelTag:gt,activeModelTag:Ne,activeModelProvider:Te,activeSessionId:o?.id??null,mentionAgentsByName:it,copyAction:vt&&e.role==="assistant"?xt(e.id,e.content):void 0},e.id))}),t.jsx("div",{ref:jt})]}),U&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:Be,children:[t.jsx(Ys,{size:14}),"Latest"]}),o&&t.jsxs("div",{className:"chat-input-area",children:[t.jsx("input",{ref:Mt,type:"file",accept:"image/*,.txt,.json,.yaml,.yml,.log,.csv,.xml,.md",multiple:!0,style:{display:"none"},onChange:e=>{qe(e.target.files),e.target.value=""}}),ce&&t.jsx("div",{className:"chat-skill-menu","data-testid":"chat-skill-menu",role:"listbox","aria-label":"Skill suggestions",children:je?t.jsx("div",{className:"chat-skill-menu-empty",children:"Loading skills…"}):le.length===0?t.jsx("div",{className:"chat-skill-menu-empty",children:Ie?"No skills found":"No skills available"}):le.map((e,a)=>t.jsxs("button",{type:"button",role:"option","aria-selected":a===Re,className:`chat-skill-menu-item${a===Re?" chat-skill-menu-item--highlighted":""}`,onMouseDown:l=>l.preventDefault(),onMouseEnter:()=>ke(a),onClick:()=>dt(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))}),F.length>0&&t.jsx("div",{className:"chat-attachment-previews","data-testid":"chat-attachment-previews",children:F.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:()=>rs(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:()=>Mt.current?.click(),children:t.jsx(Xs,{size:16})}),t.jsxs("div",{className:`chat-input-wrapper${Z?" chat-input-wrapper--dragover":""}`,onDragOver:e=>{e.preventDefault(),te(!0)},onDragLeave:()=>te(!1),onDrop:e=>{e.preventDefault(),te(!1),qe(e.dataTransfer.files)},children:[t.jsx("textarea",{ref:se,className:"chat-input-textarea",placeholder:"Type a message...",value:z,onChange:$t,onKeyDown:Dt,onKeyUp:cs,onClick:mt,onBlur:ls,onFocus:ds,onPaste:os,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||document.activeElement!==e.currentTarget&&(e.preventDefault(),e.currentTarget.focus({preventScroll:!0}))},rows:1,"data-testid":"chat-input"}),t.jsx(Qs,{agents:He,filter:Ae,highlightedIndex:ze,visible:ie,onSelect:ut,position:"below"}),t.jsx(Zs,{visible:_.mentionActive&&!ie,position:xe,files:_.files,selectedIndex:_.selectedIndex,onSelect:e=>{const a=_.selectFile(e,z);G(a),_.dismissMention(),ne(!1),se.current?.focus()},loading:_.loading}),E&&t.jsxs("div",{className:"chat-pending-message","data-testid":"chat-pending-indicator",children:[t.jsx("span",{children:`Queued: ${xs}`}),t.jsx("button",{type:"button",className:"chat-pending-message-dismiss","aria-label":"Dismiss queued message","data-testid":"chat-pending-dismiss",onClick:m,children:"×"})]})]}),R?t.jsx("button",{className:"chat-input-stop",onClick:b,"aria-label":"Stop generation","data-testid":"chat-stop-btn",children:t.jsx(en,{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:()=>{lt()},disabled:!z.trim()&&F.length===0,"data-testid":"chat-send-btn",style:{touchAction:"manipulation"},children:t.jsx(Ot,{size:16})})]})]})]}),t.jsx(un,{isOpen:Fe,onClose:()=>me(!1),projectId:n,existingRoomNames:q.rooms.map(e=>e.name),onCreate:async e=>{await q.createRoom({name:e.name,memberAgentIds:e.memberAgentIds}),me(!1)}}),I&&t.jsx(bn,{projectId:n,onClose:()=>B(!1),onCreate:is})]})}export{yn as ChatView};
|