@runfusion/fusion 0.14.0 → 0.14.2
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/dist/bin.js +277 -105
- package/dist/client/assets/{AgentDetailView-CBFUveyO.js → AgentDetailView-C2Iik3Qf.js} +1 -1
- package/dist/client/assets/{AgentsView-DPezXQ-U.js → AgentsView-DkX0tzrN.js} +3 -3
- package/dist/client/assets/ChatView-CEm2Hw6m.js +1 -0
- package/dist/client/assets/{DevServerView-Daft4YFc.js → DevServerView-Bumvo_ge.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-rew1y6qO.js → DirectoryPicker-CXN11cBp.js} +1 -1
- package/dist/client/assets/{DocumentsView-i72qJzwd.js → DocumentsView-B71IqAxA.js} +1 -1
- package/dist/client/assets/{InsightsView-BL5eZJ0a.js → InsightsView-Bs4Rldu6.js} +1 -1
- package/dist/client/assets/{MemoryView-pl8Cdg_p.js → MemoryView-Bs7b_L2Q.js} +1 -1
- package/dist/client/assets/{NodesView-D6eJ15zc.js → NodesView-BvAGTXbO.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-ExInwXWP.js → PiExtensionsManager-3Kcc4uhA.js} +2 -2
- package/dist/client/assets/PluginManager-Ch-Xynlm.js +1 -0
- package/dist/client/assets/PluginManager-DA_T0GHn.css +1 -0
- package/dist/client/assets/{ResearchView-B_QPUEjB.js → ResearchView-Bj6Saqf6.js} +1 -1
- package/dist/client/assets/{RoadmapsView-DBNLaEsK.js → RoadmapsView-9qT8Vwd0.js} +1 -1
- package/dist/client/assets/{SettingsModal-CL_gWmOj.js → SettingsModal-D4ERGQNQ.js} +1 -1
- package/dist/client/assets/SettingsModal-Zo5qDGOq.js +31 -0
- package/dist/client/assets/{SetupWizardModal-CLkY9HFL.js → SetupWizardModal-Dv0rX2_o.js} +1 -1
- package/dist/client/assets/{SkillMultiselect-B0qi32SQ.js → SkillMultiselect-CSkXQzdv.js} +1 -1
- package/dist/client/assets/{SkillsView-umVjRq6o.js → SkillsView-2srXMOzj.js} +1 -1
- package/dist/client/assets/TodoView-CxPPIvw2.js +6 -0
- package/dist/client/assets/{folder-open-nYPrL1W3.js → folder-open-FA1PwpXV.js} +1 -1
- package/dist/client/assets/{index-Bc8nfKeH.js → index-CEavim6l.js} +150 -149
- package/dist/client/assets/index-D1gTSlYB.css +1 -0
- package/dist/client/assets/{list-checks-sK8xJeH_.js → list-checks-6EktkUso.js} +1 -1
- package/dist/client/assets/{star-BRtXbYkB.js → star-B6Th07jw.js} +1 -1
- package/dist/client/assets/{upload-BP60eBwN.js → upload-BJwuErhV.js} +1 -1
- package/dist/client/assets/{users-qSGAX2Pf.js → users-BrnPTF8H.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +273 -101
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/pi-claude-cli/src/__tests__/event-bridge.test.ts +107 -0
- package/dist/pi-claude-cli/src/event-bridge.ts +48 -4
- package/package.json +1 -1
- package/skill/fusion/references/engine-tools.md +0 -1
- package/dist/client/assets/ChatView-5N4-EuhD.js +0 -1
- package/dist/client/assets/PluginManager-CYhtxHun.js +0 -1
- package/dist/client/assets/PluginManager-jyNkJZSz.css +0 -1
- package/dist/client/assets/SettingsModal-1ET586M3.js +0 -31
- package/dist/client/assets/TodoView-CFifSvrD.js +0 -6
- package/dist/client/assets/index-C1prPuSl.css +0 -1
|
@@ -178,6 +178,89 @@ describe("createEventBridge", () => {
|
|
|
178
178
|
expect(textEnd1.contentIndex).toBe(1);
|
|
179
179
|
expect(textEnd1.content).toBe("Second");
|
|
180
180
|
});
|
|
181
|
+
|
|
182
|
+
it("repairs a missing sentence boundary between consecutive text blocks", () => {
|
|
183
|
+
const bridge = createBridgeWithStart();
|
|
184
|
+
|
|
185
|
+
bridge.handleEvent({
|
|
186
|
+
type: "content_block_start",
|
|
187
|
+
index: 0,
|
|
188
|
+
content_block: { type: "text", text: "" },
|
|
189
|
+
});
|
|
190
|
+
bridge.handleEvent({
|
|
191
|
+
type: "content_block_delta",
|
|
192
|
+
index: 0,
|
|
193
|
+
delta: { type: "text_delta", text: "compare them." },
|
|
194
|
+
});
|
|
195
|
+
bridge.handleEvent({
|
|
196
|
+
type: "content_block_stop",
|
|
197
|
+
index: 0,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
bridge.handleEvent({
|
|
201
|
+
type: "content_block_start",
|
|
202
|
+
index: 1,
|
|
203
|
+
content_block: { type: "text", text: "" },
|
|
204
|
+
});
|
|
205
|
+
bridge.handleEvent({
|
|
206
|
+
type: "content_block_delta",
|
|
207
|
+
index: 1,
|
|
208
|
+
delta: { type: "text_delta", text: "Good overview." },
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const output = bridge.getOutput();
|
|
212
|
+
const combinedText = output.content
|
|
213
|
+
.filter((content): content is any => content.type === "text")
|
|
214
|
+
.map((content: any) => content.text)
|
|
215
|
+
.join("");
|
|
216
|
+
|
|
217
|
+
expect(combinedText).toBe("compare them. Good overview.");
|
|
218
|
+
expect(stream.events[4]).toEqual(
|
|
219
|
+
expect.objectContaining({
|
|
220
|
+
type: "text_delta",
|
|
221
|
+
contentIndex: 1,
|
|
222
|
+
delta: " Good overview.",
|
|
223
|
+
}),
|
|
224
|
+
);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("does not insert spaces into lowercase continuations like property access", () => {
|
|
228
|
+
const bridge = createBridgeWithStart();
|
|
229
|
+
|
|
230
|
+
bridge.handleEvent({
|
|
231
|
+
type: "content_block_start",
|
|
232
|
+
index: 0,
|
|
233
|
+
content_block: { type: "text", text: "" },
|
|
234
|
+
});
|
|
235
|
+
bridge.handleEvent({
|
|
236
|
+
type: "content_block_delta",
|
|
237
|
+
index: 0,
|
|
238
|
+
delta: { type: "text_delta", text: "console." },
|
|
239
|
+
});
|
|
240
|
+
bridge.handleEvent({
|
|
241
|
+
type: "content_block_stop",
|
|
242
|
+
index: 0,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
bridge.handleEvent({
|
|
246
|
+
type: "content_block_start",
|
|
247
|
+
index: 1,
|
|
248
|
+
content_block: { type: "text", text: "" },
|
|
249
|
+
});
|
|
250
|
+
bridge.handleEvent({
|
|
251
|
+
type: "content_block_delta",
|
|
252
|
+
index: 1,
|
|
253
|
+
delta: { type: "text_delta", text: "log('hi')" },
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const output = bridge.getOutput();
|
|
257
|
+
const combinedText = output.content
|
|
258
|
+
.filter((content): content is any => content.type === "text")
|
|
259
|
+
.map((content: any) => content.text)
|
|
260
|
+
.join("");
|
|
261
|
+
|
|
262
|
+
expect(combinedText).toBe("console.log('hi')");
|
|
263
|
+
});
|
|
181
264
|
});
|
|
182
265
|
|
|
183
266
|
describe("message_start usage tracking", () => {
|
|
@@ -795,6 +878,30 @@ describe("createEventBridge", () => {
|
|
|
795
878
|
expect(thinkingBlock.thinking).toBe("First thought. Second thought.");
|
|
796
879
|
});
|
|
797
880
|
|
|
881
|
+
it("repairs a missing sentence boundary between thinking deltas", () => {
|
|
882
|
+
const bridge = createBridgeWithStart();
|
|
883
|
+
|
|
884
|
+
bridge.handleEvent({
|
|
885
|
+
type: "content_block_start",
|
|
886
|
+
index: 0,
|
|
887
|
+
content_block: { type: "thinking" },
|
|
888
|
+
});
|
|
889
|
+
bridge.handleEvent({
|
|
890
|
+
type: "content_block_delta",
|
|
891
|
+
index: 0,
|
|
892
|
+
delta: { type: "thinking_delta", thinking: "I will inspect the hook." },
|
|
893
|
+
});
|
|
894
|
+
bridge.handleEvent({
|
|
895
|
+
type: "content_block_delta",
|
|
896
|
+
index: 0,
|
|
897
|
+
delta: { type: "thinking_delta", thinking: "Good, now the component." },
|
|
898
|
+
});
|
|
899
|
+
|
|
900
|
+
const output = bridge.getOutput();
|
|
901
|
+
const thinkingBlock = output.content[0] as any;
|
|
902
|
+
expect(thinkingBlock.thinking).toBe("I will inspect the hook. Good, now the component.");
|
|
903
|
+
});
|
|
904
|
+
|
|
798
905
|
it("emits thinking_end for thinking block stop", () => {
|
|
799
906
|
const bridge = createBridgeWithStart();
|
|
800
907
|
|
|
@@ -60,6 +60,29 @@ function mapStopReason(
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
function normalizeStreamingDelta(previousText: string, nextDelta: string): string {
|
|
64
|
+
if (!previousText || !nextDelta) {
|
|
65
|
+
return nextDelta;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const previousChar = previousText.slice(-1);
|
|
69
|
+
const nextChar = nextDelta[0] ?? "";
|
|
70
|
+
|
|
71
|
+
if (/\s/.test(previousChar) || /\s/.test(nextChar)) {
|
|
72
|
+
return nextDelta;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Claude sometimes splits adjacent sentences across separate deltas or text
|
|
76
|
+
// blocks without preserving the separating space. Only repair the specific
|
|
77
|
+
// "sentence punctuation + uppercase/quoted sentence start" case so code,
|
|
78
|
+
// domains, and lowercase continuations remain untouched.
|
|
79
|
+
if (/[.!?]/.test(previousChar) && /[A-Z0-9"'([]/.test(nextChar)) {
|
|
80
|
+
return ` ${nextDelta}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return nextDelta;
|
|
84
|
+
}
|
|
85
|
+
|
|
63
86
|
/**
|
|
64
87
|
* Create an event bridge that translates Claude API streaming events
|
|
65
88
|
* into pi's AssistantMessageEventStream events.
|
|
@@ -98,6 +121,19 @@ export function createEventBridge(
|
|
|
98
121
|
|
|
99
122
|
let started = false;
|
|
100
123
|
|
|
124
|
+
function getPreviousContentText(contentIndex: number, type: "text" | "thinking"): string {
|
|
125
|
+
for (let i = contentIndex - 1; i >= 0; i--) {
|
|
126
|
+
const contentBlock = output.content[i];
|
|
127
|
+
if (type === "text" && contentBlock?.type === "text") {
|
|
128
|
+
return contentBlock.text;
|
|
129
|
+
}
|
|
130
|
+
if (type === "thinking" && contentBlock?.type === "thinking") {
|
|
131
|
+
return contentBlock.thinking;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return "";
|
|
135
|
+
}
|
|
136
|
+
|
|
101
137
|
function handleEvent(event: ClaudeApiEvent): void {
|
|
102
138
|
// Emit start event on first message — tells pi to begin incremental rendering
|
|
103
139
|
if (!started) {
|
|
@@ -226,14 +262,18 @@ export function createEventBridge(
|
|
|
226
262
|
|
|
227
263
|
const block = blocks[idx];
|
|
228
264
|
if (block.type === "text") {
|
|
229
|
-
|
|
265
|
+
const delta = normalizeStreamingDelta(
|
|
266
|
+
block.text || getPreviousContentText(idx, "text"),
|
|
267
|
+
event.delta!.text,
|
|
268
|
+
);
|
|
269
|
+
block.text += delta;
|
|
230
270
|
const contentBlock = output.content[idx] as TextContent;
|
|
231
271
|
contentBlock.text = block.text;
|
|
232
272
|
|
|
233
273
|
stream.push({
|
|
234
274
|
type: "text_delta",
|
|
235
275
|
contentIndex: idx,
|
|
236
|
-
delta
|
|
276
|
+
delta,
|
|
237
277
|
partial: output,
|
|
238
278
|
});
|
|
239
279
|
}
|
|
@@ -246,14 +286,18 @@ export function createEventBridge(
|
|
|
246
286
|
|
|
247
287
|
const block = blocks[idx];
|
|
248
288
|
if (block.type === "thinking") {
|
|
249
|
-
|
|
289
|
+
const delta = normalizeStreamingDelta(
|
|
290
|
+
block.text || getPreviousContentText(idx, "thinking"),
|
|
291
|
+
event.delta!.thinking,
|
|
292
|
+
);
|
|
293
|
+
block.text += delta;
|
|
250
294
|
const contentBlock = output.content[idx] as ThinkingContent;
|
|
251
295
|
contentBlock.thinking = block.text;
|
|
252
296
|
|
|
253
297
|
stream.push({
|
|
254
298
|
type: "thinking_delta",
|
|
255
299
|
contentIndex: idx,
|
|
256
|
-
delta
|
|
300
|
+
delta,
|
|
257
301
|
partial: output,
|
|
258
302
|
});
|
|
259
303
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runfusion/fusion",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.2",
|
|
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",
|
|
@@ -55,5 +55,4 @@ These tools are **not** part of the pi extension's user-invokable `extension.ts`
|
|
|
55
55
|
|
|
56
56
|
| Tool | Purpose | Parameters |
|
|
57
57
|
|---|---|---|
|
|
58
|
-
| `fn_identity` | Return loaded soul/instructions/memory summary for this heartbeat tick (must be called first) | none |
|
|
59
58
|
| `fn_heartbeat_done` | Signal end of heartbeat run with optional summary | `summary?` (string) |
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as s,j as t}from"./vendor-react-K0fH_qHe.js";import{i as He,aL as Pt,g as Et,aM as Ft,a as Lt,aN as _t,aO as It,aP as Ot,aQ as Ut,aR as zt,aS as Ht,s as Vt,aT as Bt,aU as qt,aV as Gt,aW as Wt,ab as rt,ac as lt,S as Kt,V as Ze,J as et,ao as Jt,aX as Yt,B as Pe,a8 as ot,a9 as ct,aY as Qt,aZ as Xt,a_ as Zt,a$ as es,b0 as ts,b1 as ss,b2 as ns,b3 as tt,h as as,u as st,k as is}from"./index-Bc8nfKeH.js";import"./vendor-xterm-DzcZoU0P.js";const ze="kb-chat-active-session";function rs(a){const i=a?.toolCalls;if(!Array.isArray(i))return;const r=i.map(l=>{if(!l||typeof l!="object")return null;const c=l,N=typeof c.toolName=="string"?c.toolName:"";if(!N)return null;const j=c.args;return{toolName:N,...j&&typeof j=="object"?{args:j}:{},isError:!!c.isError,result:c.result,status:"completed"}}).filter(l=>l!==null);return r.length>0?r:void 0}function nt(a){return{id:a.id,sessionId:a.sessionId,role:a.role,content:a.content,thinkingOutput:a.thinkingOutput,toolCalls:rs(a.metadata),attachments:a.attachments,createdAt:a.createdAt}}function ls(a){const[i,r]=s.useState([]),[l,c]=s.useState(null),[N,j]=s.useState(!0),[R,k]=s.useState([]),[P,I]=s.useState(!1),[x,F]=s.useState(!1),[T,$]=s.useState(""),[g,v]=s.useState(""),[C,y]=s.useState([]),[B,E]=s.useState(""),[X,W]=s.useState(""),[L,Y]=s.useState(!0),[h,M]=s.useState(new Map),w=s.useRef(null),_=s.useRef(!1),z=s.useRef(""),te=s.useRef(null),he=s.useRef(i),xe=s.useRef(l),ve=s.useRef(x);he.current=i,xe.current=l,ve.current=x,s.useEffect(()=>{z.current=B},[B]);const we=s.useRef(new Set),me=s.useRef(0),ke=s.useRef(a);ke.current!==a&&(ke.current=a,me.current++),s.useEffect(()=>{const d=me.current;He(void 0,a).then(f=>{if(me.current!==d)return;const p=new Map;for(const S of f)p.set(S.id,S);M(p)}).catch(()=>{})},[a]);const K=s.useCallback(async()=>{j(!0);try{const f=[...(await Pt(a)).sessions].sort((p,S)=>new Date(S.updatedAt).getTime()-new Date(p.updatedAt).getTime());r(f)}catch{}finally{j(!1)}},[a]);s.useEffect(()=>{K()},[K]);const se=s.useRef(()=>{});s.useEffect(()=>{if(N)return;const d=Et(ze,a);d&&i.find(p=>p.id===d)&&se.current(d)},[N,i,a]);const oe=s.useCallback(async(d,f)=>{I(!0);try{const p=await Ft(d,{limit:50,...f},a),S=p.messages.map(nt);f?.offset&&f.offset>0?k(q=>[...S,...q]):k(S),Y(p.messages.length>=50)}catch{}finally{I(!1)}},[a]),ne=s.useCallback(()=>{te.current?.(),te.current=null,z.current="",E(""),$(""),v(""),y([]),F(!1)},[]),ae=s.useCallback((d,f)=>{w.current&&(w.current.close(),w.current=null);const p=f??i.find(S=>S.id===d);c(p||null),ne(),Y(!0),d?oe(d):k([]),d?Lt(ze,d,a):_t(ze,a)},[i,oe,a,ne]);se.current=ae;const fe=s.useCallback(async d=>{const f=await It(d,a);w.current&&(w.current.close(),w.current=null);const p={id:f.session.id,title:f.session.title,agentId:f.session.agentId,status:f.session.status,modelProvider:f.session.modelProvider,modelId:f.session.modelId,createdAt:f.session.createdAt,updatedAt:f.session.updatedAt};return r(S=>S.some(q=>q.id===p.id)?S:[p,...S]),ne(),ae(p.id,p),k([]),p},[a,ne,ae]),Se=s.useCallback(async d=>{await Ot(d,{status:"archived"},a),r(f=>f.filter(p=>p.id!==d)),l?.id===d&&(c(null),k([]))},[l,a]),ce=s.useCallback(async d=>{l?.id===d&&w.current&&(w.current.close(),w.current=null),await Ut(d,a),r(f=>f.filter(p=>p.id!==d)),l?.id===d&&(c(null),k([]))},[l,a]),Z=s.useCallback(async()=>{!l||!L||await oe(l.id,{offset:R.length})},[l,L,oe,R.length]),de=s.useCallback(()=>{l&&(_.current=!0,te.current?.(),te.current=null,w.current?.close(),w.current=null,zt(l.id,a).catch(()=>{}),F(!1),$(""),v(""),y([]))},[l,a]),ye=s.useCallback(()=>{z.current="",E("")},[]),ue=s.useCallback((d,f)=>{if(!l)return;if(x){z.current=d,E(d);return}_.current=!1,w.current&&(w.current.close(),w.current=null);const p=`temp-${Date.now()}`,S={id:p,sessionId:l.id,role:"user",content:d,createdAt:new Date().toISOString()};k(m=>[...m,S]),$(""),v(""),y([]),F(!0);let q="",ge="",O=[],H=null,ie=null;const G=()=>{H=null,$(q)},u=()=>{ie=null,v(ge)},A=()=>{H!==null&&(cancelAnimationFrame(H),H=null),ie!==null&&(cancelAnimationFrame(ie),ie=null)};te.current=A;const V={onThinking:m=>{ge+=m,ie===null&&(ie=requestAnimationFrame(u))},onText:m=>{q+=m,H===null&&(H=requestAnimationFrame(G))},onToolStart:m=>{O=[...O,{toolName:m.toolName,args:m.args,isError:!1,status:"running"}],y(O)},onToolEnd:m=>{const D=[...O];for(let b=D.length-1;b>=0;b--){const ee=D[b];if(ee?.toolName===m.toolName&&ee.status==="running"){D[b]={...ee,status:"completed",isError:m.isError,result:m.result},O=D,y(D);return}}O=[...D,{toolName:m.toolName,isError:m.isError,result:m.result,status:"completed"}],y(O)},onDone:m=>{A();const D={id:m.messageId||`msg-${Date.now()}`,sessionId:l.id,role:"assistant",content:q,thinkingOutput:ge,toolCalls:O.length>0?O:void 0,createdAt:new Date().toISOString()};we.current.add(D.id),k(ee=>[...ee,D]),$(""),v(""),y([]),F(!1),w.current=null,setTimeout(()=>{we.current.delete(D.id)},1e3),K();const b=z.current.trim();b&&(z.current="",E(""),ue(b))},onError:m=>{if(A(),k(D=>D.filter(b=>b.id!==p)),$(""),v(""),y([]),F(!1),w.current=null,console.error("[useChat] Stream error:",m),!_.current){const D=z.current.trim();D&&(z.current="",E(""),ue(D))}}};w.current=Ht(l.id,d,V,f,a)},[l,x,a,K]),Ne=X?i.filter(d=>d.title?.toLowerCase().includes(X.toLowerCase())||d.agentId.toLowerCase().includes(X.toLowerCase())):i;return s.useEffect(()=>{const d=me.current,f=a?`?projectId=${encodeURIComponent(a)}`:"",p=()=>me.current!==d,S=G=>{if(p())return;const u=JSON.parse(G.data);r(A=>A.some(V=>V.id===u.id)?A:[u,...A])},q=G=>{if(p())return;const u=JSON.parse(G.data);r(A=>[...A.map(m=>m.id===u.id?u:m)]),xe.current?.id===u.id&&c(u)},ge=G=>{if(p())return;const{id:u}=JSON.parse(G.data);r(A=>A.filter(V=>V.id!==u)),xe.current?.id===u&&(c(null),k([]))},O=G=>{if(p())return;const u=JSON.parse(G.data),A=nt(u);we.current.has(A.id)||xe.current?.id===A.sessionId&&!ve.current&&k(V=>V.some(m=>m.id===A.id)?V:[...V,A])},H=G=>{if(p())return;const{id:u}=JSON.parse(G.data);k(A=>A.filter(V=>V.id!==u))};return Vt(`/api/events${f}`,{events:{"chat:session:created":S,"chat:session:updated":q,"chat:session:deleted":ge,"chat:message:added":O,"chat:message:deleted":H}})},[a]),s.useEffect(()=>()=>{w.current&&(w.current.close(),w.current=null)},[]),{sessions:i,activeSession:l,sessionsLoading:N,messages:R,messagesLoading:P,isStreaming:x,streamingText:T,streamingThinking:g,streamingToolCalls:C,pendingMessage:B,selectSession:ae,createSession:fe,archiveSession:Se,deleteSession:ce,sendMessage:ue,stopStreaming:de,clearPendingMessage:ye,loadMoreMessages:Z,hasMoreMessages:L,searchQuery:X,setSearchQuery:W,filteredSessions:Ne,refreshSessions:K,agentsMap:h}}function dt(a){const i=new Date(a),l=new Date().getTime()-i.getTime(),c=Math.floor(l/1e3),N=Math.floor(c/60),j=Math.floor(N/60),R=Math.floor(j/24);return c<60?"just now":N<60?`${N}m ago`:j<24?`${j}h ago`:R<7?`${R}d ago`:i.toLocaleDateString()}function at(a,i){if(!a||!i)return null;const r=i.toLowerCase();if(r.includes("claude")){let c=i.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(r.includes("gpt")||r.includes("openai")){const c=i.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(r.includes("gemini")){const c=i.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 l=i.replace(/-/g," ").replace(/^\w/,c=>c.toUpperCase()).replace(/\s+/g," ").trim();return l.length>30?l.slice(0,30)+"…":l}function Re(a,i){return a.length<=i?a:`${a.slice(0,i)}…`}function os(a){if(!a)return null;const i=Object.entries(a);return i.length===0?null:i.map(([r,l])=>{const c=typeof l=="string"?l:(()=>{try{return JSON.stringify(l)}catch{return String(l)}})();return`${r}=${Re(c,50)}`}).join(", ")}function cs(a){if(a===void 0)return null;if(typeof a=="string")return Re(a,200);try{return Re(JSON.stringify(a),200)}catch{return Re(String(a),200)}}function ut(a){if(!a||a.length===0)return null;const i=(x,F)=>{const T=x.status==="running",$=x.status==="completed"&&x.isError,g=os(x.args),v=cs(x.result),C=T?g:v?`result: ${v}`:g?`args: ${g}`:null,y=T?"running":$?"error":"completed";return t.jsxs("details",{className:`chat-tool-call${T?" chat-tool-call--running":""}${$?" chat-tool-call--error":""}`,open:T,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",children:x.toolName}),C&&t.jsx("span",{className:"chat-tool-call-preview",title:C,children:C}),t.jsx("span",{className:"chat-tool-call-status-text",children:y})]}),t.jsxs("div",{className:"chat-tool-call-content",children:[g&&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:g})]}),v&&t.jsxs("div",{className:`chat-tool-call-row${$?" 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:v})]})]})]},`${x.toolName}-${F}`)},r="chat-tool-calls";if(a.length===1)return t.jsxs("div",{className:r,"data-testid":"chat-tool-calls",children:[t.jsxs("div",{className:"chat-tool-calls-header",children:[t.jsx(tt,{size:12,"aria-hidden":"true"}),t.jsx("span",{children:"Tool calls"})]}),i(a[0],0)]});const l=a.filter(x=>x.status==="running").length,c=a.filter(x=>x.status==="completed"&&x.isError).length,N=l>0,j=Array.from(new Set(a.map(x=>x.toolName))),R=j.slice(0,5),k=Math.max(0,j.length-R.length),P=k>0?`${R.join(", ")}, +${k} more`:R.join(", "),I=N?`(${l} running)`:c>0?`(${c} ${c===1?"error":"errors"})`:null;return t.jsx("div",{className:r,"data-testid":"chat-tool-calls",children:t.jsxs("details",{className:"chat-tool-calls-group","data-testid":"chat-tool-calls-group",open:N,children:[t.jsxs("summary",{className:"chat-tool-calls-group-summary",children:[t.jsx(tt,{size:12,"aria-hidden":"true"}),t.jsxs("span",{children:[a.length," tool calls"]}),t.jsx("span",{className:"chat-tool-calls-names",title:P,children:P}),I&&t.jsx("span",{className:"chat-tool-calls-group-status",children:I})]}),a.map((x,F)=>i(x,F))]})})}const ht={pre:({children:a,...i})=>t.jsx("pre",{...i,className:"chat-markdown-pre",children:a}),table:({children:a,...i})=>t.jsx("table",{...i,className:"chat-markdown-table",children:a})},De="__fn_agent__",ds=["image/png","image/jpeg","image/gif","image/webp","text/plain","application/json","text/yaml","text/markdown","text/csv","application/xml","text/x-log"];function it(a){const i=/(^|[\s])\/([^\s]*)$/.exec(a);if(!i)return null;const r=i[1]??"",l=i[2]??"",c=i.index+r.length;return{filter:l,start:c,end:a.length}}function us(a,i){const r=a.slice(0,i),l=/(^|[\s\n])@([\w-]*)$/.exec(r);if(!l)return null;const c=l[2]??"",N=r.length-c.length-1;return{filter:c,start:N,end:i}}function hs({projectId:a,onClose:i,onCreate:r}){const[l,c]=s.useState("agent"),[N,j]=s.useState([]),[R,k]=s.useState(!0),[P,I]=s.useState(""),[x,F]=s.useState([]),[T,$]=s.useState(!0),[g,v]=s.useState(""),[C,y]=s.useState([]),[B,E]=s.useState([]);s.useEffect(()=>{let h=!1;return k(!0),He(void 0,a).then(M=>{h||j(M)}).catch(()=>{h||j([])}).finally(()=>{h||k(!1)}),()=>{h=!0}},[a]),s.useEffect(()=>{$(!0),as().then(h=>{F(h.models),y(h.favoriteProviders),E(h.favoriteModels)}).catch(()=>{F([]),y([]),E([])}).finally(()=>{$(!1)})},[]);const X=s.useCallback(async h=>{const M=C,_=M.includes(h)?M.filter(z=>z!==h):[h,...M];y(_);try{await st({favoriteProviders:_,favoriteModels:B})}catch{y(M)}},[C,B]),W=s.useCallback(async h=>{const M=B,_=M.includes(h)?M.filter(z=>z!==h):[h,...M];E(_);try{await st({favoriteProviders:C,favoriteModels:_})}catch{E(M)}},[B,C]),L=h=>{if(h.preventDefault(),l==="agent"){if(!P)return;r({agentId:P});return}if(!g)return;const M=g.indexOf("/");if(M<=0)return;const w=g.slice(0,M),_=g.slice(M+1);r({agentId:De,modelProvider:w,modelId:_})},Y=l==="agent"?!P:!g;return t.jsx("div",{className:"chat-new-dialog-backdrop",onClick:i,role:"dialog","aria-modal":"true",children:t.jsxs("div",{className:"chat-new-dialog",onClick:h=>h.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${l==="agent"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-agent",onClick:()=>{c("agent"),v("")},children:"Agent"}),t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${l==="model"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-model",onClick:()=>{c("model"),I("")},children:"Model"})]}),t.jsxs("form",{onSubmit:L,children:[l==="agent"&&t.jsxs("label",{className:"chat-new-dialog-model-label",children:["Agent",R?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading agents..."}):N.length===0?t.jsx("div",{className:"chat-new-dialog-empty",children:"No agents available"}):t.jsx("div",{className:"chat-new-dialog-agent-list",children:N.map(h=>t.jsxs("button",{type:"button",className:`chat-new-dialog-agent-item${P===h.id?" chat-new-dialog-agent-item--selected":""}`,onClick:()=>I(h.id),"data-testid":`agent-option-${h.id}`,children:[t.jsx(Pe,{size:16}),t.jsx("span",{className:"chat-new-dialog-agent-name",children:h.name}),t.jsx("span",{className:"chat-new-dialog-agent-role",children:h.role})]},h.id))})]}),l==="model"&&t.jsx("div",{className:"chat-new-dialog-model-dropdown","data-testid":"chat-new-dialog-model-section",children:T?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading models..."}):t.jsx(is,{models:x,value:g,onChange:v,label:"Model",placeholder:"Select a model",favoriteProviders:C,onToggleFavorite:X,favoriteModels:B,onToggleModelFavorite:W})}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{type:"button",className:"btn btn-sm",onClick:i,children:"Cancel"}),t.jsx("button",{type:"submit",className:"btn btn-sm btn-primary",disabled:Y,children:"Create"})]})]})]})})}const ms=s.memo(function({message:i,forcePlain:r,agentName:l,showAssistantModelTag:c,activeModelTag:N,activeSessionId:j,mentionAgentsByName:R,onToggleRender:k}){const P=i.role==="assistant",I=s.useMemo(()=>{if(P)return null;const T=i.content,$=/@([\w-]+)/g,g=[];let v=0,C=$.exec(T);for(;C;){const[y,B=""]=C,E=C.index;E>v&&g.push(T.slice(v,E));const X=B.replace(/_/g," ").toLowerCase(),W=R.get(X);W?g.push(t.jsxs("span",{className:"chat-mention-chip",children:["@",W.name.replace(/\s+/g,"_")]},`${W.id}-${E}`)):g.push(y),v=E+y.length,C=$.exec(T)}return v<T.length&&g.push(T.slice(v)),g.length===0?T:g},[P,i.content,R]),x=s.useMemo(()=>{const T=i.attachments;if(!T||T.length===0||!j)return null;const $=`/api/chat/sessions/${encodeURIComponent(j)}/attachments/`;return t.jsx("div",{className:"chat-message-attachments",children:T.map(g=>{const v=g.mimeType.startsWith("image/"),C=g.id||g.filename,y=`${$}${encodeURIComponent(g.filename)}`;return v?t.jsx("a",{className:"chat-message-attachment-link","data-testid":"chat-message-attachment",href:y,target:"_blank",rel:"noopener noreferrer",children:t.jsx("img",{className:"chat-message-attachment",src:y,alt:g.originalName})},C):t.jsxs("a",{className:"chat-message-attachment-file","data-testid":"chat-message-attachment",href:y,target:"_blank",rel:"noopener noreferrer",children:[t.jsx(ns,{size:14}),t.jsx("span",{children:g.originalName})]},C)})})},[i.attachments,j]),F=s.useMemo(()=>P?r?t.jsx("div",{className:"chat-message-content chat-message-content--plain",children:i.content}):t.jsx("div",{className:"chat-message-content chat-message-content--markdown",children:t.jsx(rt,{remarkPlugins:[lt],components:ht,children:i.content})}):null,[P,r,i.content]);return t.jsxs("div",{className:`chat-message chat-message--${i.role}`,"data-testid":`chat-message-${i.id}`,children:[P&&t.jsxs("div",{className:"chat-message-avatar",children:[t.jsx(Pe,{size:14}),t.jsx("span",{children:l}),c&&N&&t.jsx("span",{className:"chat-model-tag",children:N}),t.jsx("button",{type:"button",className:`chat-message-render-toggle${r?" chat-message-render-toggle--plain":""}`,"data-testid":"chat-message-render-toggle","aria-label":r?"Show rendered markdown":"Show plain text",onClick:()=>k(i.id),children:r?t.jsx(ot,{size:14}):t.jsx(ct,{size:14})})]}),P?F:t.jsx("div",{className:"chat-message-content",children:I}),ut(i.toolCalls),i.thinkingOutput&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:i.thinkingOutput})]}),x,t.jsx("div",{className:"chat-message-time",children:dt(i.createdAt)})]})});function ws({projectId:a,addToast:i}){const{activeSession:r,sessionsLoading:l,messages:c,messagesLoading:N,isStreaming:j,streamingText:R,streamingThinking:k,streamingToolCalls:P,selectSession:I,createSession:x,archiveSession:F,deleteSession:T,sendMessage:$,stopStreaming:g,pendingMessage:v,clearPendingMessage:C,searchQuery:y,setSearchQuery:B,filteredSessions:E}=ls(a),[X,W]=s.useState(!1),[L,Y]=s.useState(""),[h,M]=s.useState(null),[w,_]=s.useState(null),[z,te]=s.useState(!0),[he,xe]=s.useState(new Map),[ve,we]=s.useState([]),[me,ke]=s.useState(!0),[K,se]=s.useState(!1),[oe,ne]=s.useState(""),[ae,fe]=s.useState(0),[Se,ce]=s.useState(""),[Z,de]=s.useState(!1),[ye,ue]=s.useState(0),[Ne,d]=s.useState(-1),[f,p]=s.useState(()=>new Set),[S,q]=s.useState([]),[ge,O]=s.useState(!1),[,H]=s.useState(!1),[ie,G]=s.useState({top:0,left:0}),u=Bt({projectId:a}),A=s.useCallback(e=>{if(!e||!u.mentionActive)return;const n=e.getBoundingClientRect();G({top:n.top-260,left:n.left+8})},[u.mentionActive]),V=s.useRef(null),m=s.useRef(null),D=s.useRef(null),b=s.useRef(null),ee=s.useRef(!1),Me=s.useRef(!1),Ve=s.useRef(null),Be=s.useRef([]),je=s.useRef(0),re=qt()==="mobile",{keyboardOverlap:Ee,viewportHeight:qe,viewportOffsetTop:mt,keyboardOpen:Fe}=Gt({enabled:re&&!!r}),ft=Fe?{"--keyboard-overlap":`${Ee}px`,"--vv-offset-top":`${mt}px`,...qe!==null?{"--vv-height":`${qe}px`}:{}}:{},Q=s.useMemo(()=>{const e=oe.trim().toLowerCase();return(e?ve.filter(o=>o.name.toLowerCase().includes(e)):ve).slice(0,10)},[ve,oe]),be=s.useMemo(()=>Array.from(he.values()),[he]),pe=s.useMemo(()=>{const e=Se.trim().toLowerCase();return e?be.filter(n=>n.name.toLowerCase().includes(e)):be},[be,Se]),gt=s.useMemo(()=>{const e=new Map;for(const n of be)e.set(n.name.toLowerCase(),n);return e},[be]);s.useEffect(()=>{fe(0)},[Q]),s.useEffect(()=>{ue(0)},[Se,Z]),s.useEffect(()=>()=>{m.current!==null&&window.clearTimeout(m.current)},[]),s.useEffect(()=>{const e=D.current;e&&(e.scrollTop=e.scrollHeight)},[c,R]),s.useEffect(()=>{if(Ee<=0)return;const e=D.current;e&&(e.scrollTop=e.scrollHeight)},[Ee]),s.useEffect(()=>{if(!re||!Fe)return;const e=document.documentElement,n=document.body,o={htmlOverflow:e.style.overflow,bodyOverflow:n.style.overflow};return e.style.overflow="hidden",n.style.overflow="hidden",()=>{e.style.overflow=o.htmlOverflow,n.style.overflow=o.bodyOverflow}},[re,Fe]),s.useEffect(()=>{const e=()=>M(null);if(h)return document.addEventListener("click",e),()=>document.removeEventListener("click",e)},[h]),s.useEffect(()=>{let e=!1;const n=a;return He(void 0,a).then(o=>{if(e||n!==a)return;const U=new Map;for(const J of o)U.set(J.id,J);xe(U)}).catch(()=>{}),()=>{e=!0}},[a]),s.useEffect(()=>{let e=!1;return ke(!0),Wt(a).then(n=>{e||we(n)}).catch(()=>{e||we([])}).finally(()=>{e||ke(!1)}),()=>{e=!0}},[a]),s.useEffect(()=>{Be.current=S},[S]),s.useEffect(()=>()=>{for(const e of Be.current)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)},[]);const Te=s.useCallback(e=>{if(!e||e.length===0)return;const n=[];for(const o of Array.from(e)){if(!ds.includes(o.type))continue;const U=o.type.startsWith("image/");n.push({file:o,previewUrl:U?URL.createObjectURL(o):""})}n.length>0&&q(o=>[...o,...n])},[]),pt=s.useCallback(e=>{q(n=>{const o=n[e];return o?.previewUrl&&URL.revokeObjectURL(o.previewUrl),n.filter((U,J)=>J!==e)})},[]),xt=s.useCallback(e=>{const n=e.clipboardData?.files;if(!n||n.length===0)return;const o=Array.from(n).filter(U=>U.type.startsWith("image/"));o.length!==0&&Te(o)},[Te]),vt=s.useCallback(async e=>{try{await x(e),W(!1),re&&te(!1)}catch{i("Failed to create chat session","error")}},[x,i,re]),Le=s.useCallback(()=>{Y(""),se(!1),ne(""),de(!1),ce(""),d(-1),q(e=>{for(const n of e)n.previewUrl&&URL.revokeObjectURL(n.previewUrl);return[]})},[]),Ce=s.useCallback(()=>{const e=L.trim(),n=S.map(o=>o.file);if(!(!e&&n.length===0||!r)){if(e==="/clear"){Le(),g(),C(),x({agentId:r.agentId,modelProvider:r.modelProvider??void 0,modelId:r.modelId??void 0}).catch(()=>{i("Failed to clear conversation","error")});return}Le(),$(e,n)}},[L,S,r,Le,g,C,x,i,$]),Ae=s.useCallback(()=>{if(typeof window>"u"||window.innerWidth>768)return;const e=b.current;if(!e||e.disabled)return;const n=window.scrollX,o=window.scrollY;e.focus({preventScroll:!0}),window.requestAnimationFrame(()=>{(window.scrollX!==n||window.scrollY!==o)&&window.scrollTo(n,o)})},[]),Ge=s.useCallback(()=>{typeof window>"u"||window.innerWidth>768||(ee.current=!0)},[]),_e=s.useCallback(e=>{Y(n=>{const o=it(n);if(!o)return n;const U=`/skill:${e.name} `,J=n.slice(0,o.start)+U+n.slice(o.end);return window.requestAnimationFrame(()=>{b.current&&(b.current.style.height="auto",b.current.style.height=`${Math.min(b.current.scrollHeight,120)}px`,b.current.focus())}),J}),se(!1),ne(""),fe(0)},[]),Ie=s.useCallback(e=>{const n=b.current;if(!n||Ne<0)return;const o=n.selectionStart??je.current,U=n.selectionEnd??o,J=Math.max(o,U),Ye=Math.min(Ne,J),Qe=`${`@${e.name.replace(/\s+/g,"_")}`} `,Dt=L.slice(0,Ye)+Qe+L.slice(J),Xe=Ye+Qe.length;Y(Dt),de(!1),ce(""),ue(0),d(-1),window.requestAnimationFrame(()=>{b.current&&(b.current.style.height="auto",b.current.style.height=`${Math.min(b.current.scrollHeight,120)}px`,b.current.focus(),b.current.setSelectionRange(Xe,Xe))})},[Ne,L]),wt=s.useCallback(e=>{if(je.current=e.currentTarget.selectionStart??je.current,u.mentionActive&&u.files.length>0){if(u.handleKeyDown(e,L),e.key==="Enter"||e.key==="Tab"){const n=u.files[u.selectedIndex];if(n){const o=u.selectFile(n,L);Y(o),u.dismissMention(),H(!1)}}return}if(Z&&e.key==="ArrowDown"){e.preventDefault(),pe.length>0&&ue(n=>(n+1)%pe.length);return}if(Z&&e.key==="ArrowUp"){e.preventDefault(),pe.length>0&&ue(n=>n===0?pe.length-1:n-1);return}if(Z&&e.key==="Enter"){e.preventDefault();const n=pe[ye]??pe[0];n&&Ie(n);return}if(Z&&e.key==="Escape"){e.preventDefault(),de(!1),ce(""),d(-1);return}if(K&&e.key==="ArrowDown"){e.preventDefault(),Q.length>0&&fe(n=>(n+1)%Q.length);return}if(K&&e.key==="ArrowUp"){e.preventDefault(),Q.length>0&&fe(n=>n===0?Q.length-1:n-1);return}if(K&&(e.key==="Enter"||e.key==="Tab")&&Q.length>0){e.preventDefault();const n=Q[ae]??Q[0];n&&_e(n);return}if(K&&e.key==="Escape"){e.preventDefault(),se(!1);return}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),Ce())},[Z,pe,ye,Ie,K,Q,ae,_e,Ce,u,L]),$e=s.useCallback((e,n)=>{const o=us(e,n);if(o){de(!0),ce(o.filter),d(o.start);return}de(!1),ce(""),d(-1)},[]),St=s.useCallback(e=>{const n=e.target,o=n.value,U=n.selectionStart??o.length;je.current=U,Y(o);const J=it(o);J?(se(!0),ne(J.filter)):(se(!1),ne("")),$e(o,U),u.detectMention(o,U),H(u.mentionActive),u.mentionActive&&A(n),n.style.height="auto",n.style.height=`${Math.min(n.scrollHeight,120)}px`},[$e]),Oe=s.useCallback(e=>{const n=e.currentTarget,o=n.selectionStart??n.value.length;je.current=o,$e(n.value,o),u.detectMention(n.value,o),H(u.mentionActive),u.mentionActive&&A(n)},[$e,u,A]),bt=s.useCallback(e=>{e.key!=="Escape"&&Oe(e)},[Oe]),kt=s.useCallback(()=>{if(ee.current){window.requestAnimationFrame(()=>{Ae()});return}m.current!==null&&window.clearTimeout(m.current),m.current=window.setTimeout(()=>{se(!1),de(!1),ce(""),d(-1),H(!1),u.dismissMention(),m.current=null},120)},[u,Ae]),yt=s.useCallback(()=>{m.current!==null&&(window.clearTimeout(m.current),m.current=null)},[]),Nt=s.useCallback(async e=>{M(null);try{await F(e),i("Conversation archived","success")}catch{i("Failed to archive conversation","error")}},[F,i]),jt=s.useCallback(async e=>{_(null),M(null);try{await T(e),i("Conversation deleted","success")}catch{i("Failed to delete conversation","error")}},[T,i]),Ct=s.useCallback(e=>{I(e),re&&te(!1)},[I,re]),Mt=s.useCallback(()=>{I(""),te(!0)},[I]),Tt=()=>t.jsxs("div",{className:"chat-empty-state",children:[t.jsx(ss,{size:48,strokeWidth:1.5}),t.jsx("h2",{children:"Start a new conversation"}),t.jsxs("button",{className:"btn btn-primary",onClick:()=>W(!0),children:[t.jsx(et,{size:16}),"New Chat"]})]}),le=at(r?.modelProvider,r?.modelId),We=r?.agentId===De?le??"Fusion":r?.title||he.get(r?.agentId??"")?.name||r?.agentId||"Chat",At=!!(le&&le!==We),Ue=he.get(r?.agentId??"")?.name||(r?.agentId===De?le??"Fusion":r?.agentId?.slice(0,30)??"Fusion"),Ke=!!(le&&le!==Ue),$t=v.length>50?`${v.slice(0,50)}…`:v,Je=s.useCallback(e=>{p(n=>{const o=new Set(n);return o.has(e)?o.delete(e):o.add(e),o})},[]),Rt=s.useCallback((e,n=!1)=>n?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(rt,{remarkPlugins:[lt],components:ht,children:e})}),[]);return t.jsxs("div",{className:"chat-view",children:[t.jsxs("div",{className:`chat-sidebar${z?"":" chat-sidebar--hidden"}`,children:[t.jsx("div",{className:"chat-sidebar-search",children:t.jsxs("div",{className:"chat-sidebar-search-wrapper",children:[t.jsx(Kt,{size:14,className:"chat-sidebar-search-icon"}),t.jsx("input",{type:"text",className:"chat-sidebar-search",placeholder:"Search conversations...",value:y,onChange:e=>B(e.target.value),"data-testid":"chat-search-input"})]})}),t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:l?t.jsx("div",{style:{padding:"12px",color:"var(--text-secondary)",fontSize:"13px"},children:"Loading..."}):E.length===0?t.jsx("div",{style:{padding:"12px",color:"var(--text-secondary)",fontSize:"13px"},children:"No conversations yet"}):E.map(e=>t.jsxs("div",{className:`chat-session-item${r?.id===e.id?" chat-session-item--active":""}`,onClick:()=>Ct(e.id),onContextMenu:n=>{n.preventDefault(),M({sessionId:e.id,x:n.clientX,y:n.clientY})},"data-testid":`chat-session-${e.id}`,children:[t.jsx("button",{className:"chat-session-delete-btn",onClick:n=>{n.stopPropagation(),_(e.id)},"data-testid":"chat-session-delete-btn","aria-label":"Delete conversation",children:t.jsx(Ze,{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.jsx("span",{children:he.get(e.agentId)?.name||(e.agentId===De?at(e.modelProvider,e.modelId)??"Fusion":e.agentId.slice(0,30))}),t.jsx("span",{children:e.updatedAt?dt(e.updatedAt):""})]})]},e.id))}),t.jsx("div",{className:"chat-sidebar-footer",children:t.jsxs("button",{className:"btn btn-sm btn-primary chat-sidebar-footer-btn",onClick:()=>W(!0),"data-testid":"chat-new-btn",children:[t.jsx(et,{size:14}),"New Chat"]})})]}),h&&t.jsxs("div",{className:"chat-session-context-menu",style:{top:h.y,left:h.x},onClick:e=>e.stopPropagation(),children:[t.jsxs("button",{onClick:()=>Nt(h.sessionId),"data-testid":"chat-context-archive",children:[t.jsx(Jt,{size:14}),"Archive"]}),t.jsxs("button",{onClick:()=>{M(null),_(h.sessionId)},"data-testid":"chat-context-delete",children:[t.jsx(Ze,{size:14}),"Delete"]})]}),w&&t.jsx("div",{className:"chat-new-dialog-backdrop",onClick:()=>_(null),children:t.jsxs("div",{className:"chat-new-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:"Delete Conversation?"}),t.jsx("p",{style:{fontSize:"14px",color:"var(--text-secondary)",marginBottom:"16px"},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:()=>_(null),children:"Cancel"}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void jt(w),children:"Delete"})]})]})}),t.jsxs("div",{className:"chat-thread",style:ft,children:[(r||!re)&&t.jsxs("div",{className:"chat-thread-header",children:[re&&r&&t.jsx("button",{className:"btn-icon",onClick:Mt,"data-testid":"chat-back-btn",children:t.jsx(Yt,{size:16})}),t.jsx(Pe,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:We}),At&&t.jsx("span",{className:"chat-model-tag",children:le})]}),t.jsxs("div",{className:"chat-messages",ref:D,children:[N?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"Loading messages..."}):c.length===0&&!r?Tt():c.length===0&&r?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"No messages yet. Start the conversation!"}):t.jsxs(t.Fragment,{children:[c.map(e=>t.jsx(ms,{message:e,forcePlain:f.has(e.id),agentName:Ue,showAssistantModelTag:Ke,activeModelTag:le,activeSessionId:r?.id??null,mentionAgentsByName:gt,onToggleRender:Je},e.id)),j&&t.jsxs("div",{className:"chat-message chat-message--assistant chat-message--streaming",children:[t.jsxs("div",{className:"chat-message-avatar",children:[t.jsx(Pe,{size:14}),t.jsx("span",{children:Ue}),Ke&&t.jsx("span",{className:"chat-model-tag",children:le}),t.jsx("button",{type:"button",className:`chat-message-render-toggle${f.has("__streaming__")?" chat-message-render-toggle--plain":""}`,"data-testid":"chat-message-render-toggle","aria-label":f.has("__streaming__")?"Show rendered markdown":"Show plain text",onClick:()=>Je("__streaming__"),children:f.has("__streaming__")?t.jsx(ot,{size:14}):t.jsx(ct,{size:14})})]}),R?Rt(R,f.has("__streaming__")):t.jsx("div",{className:"chat-message-content chat-message-content--waiting",children:k?"Thinking…":"Connecting…"}),ut(P),k&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:k})]}),t.jsxs("div",{className:"chat-typing-indicator",children:[t.jsx("span",{}),t.jsx("span",{}),t.jsx("span",{})]})]})]}),t.jsx("div",{ref:V})]}),r&&t.jsxs("div",{className:"chat-input-area",children:[t.jsx("input",{ref:Ve,type:"file",accept:"image/*,.txt,.json,.yaml,.yml,.log,.csv,.xml,.md",multiple:!0,style:{display:"none"},onChange:e=>{Te(e.target.files),e.target.value=""}}),K&&t.jsx("div",{className:"chat-skill-menu","data-testid":"chat-skill-menu",role:"listbox","aria-label":"Skill suggestions",children:me?t.jsx("div",{className:"chat-skill-menu-empty",children:"Loading skills…"}):Q.length===0?t.jsx("div",{className:"chat-skill-menu-empty",children:oe?"No skills found":"No skills available"}):Q.map((e,n)=>t.jsxs("button",{type:"button",role:"option","aria-selected":n===ae,className:`chat-skill-menu-item${n===ae?" chat-skill-menu-item--highlighted":""}`,onMouseDown:o=>o.preventDefault(),onMouseEnter:()=>fe(n),onClick:()=>_e(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))}),S.length>0&&t.jsx("div",{className:"chat-attachment-previews","data-testid":"chat-attachment-previews",children:S.map((e,n)=>t.jsxs("div",{className:"chat-attachment-preview","data-testid":`chat-attachment-preview-${n}`,children:[e.previewUrl?t.jsx("img",{src:e.previewUrl,alt:e.file.name}):t.jsx("span",{className:"chat-attachment-preview-name",children:e.file.name}),t.jsx("button",{type:"button",className:"chat-attachment-remove",onClick:()=>pt(n),"data-testid":`chat-attachment-remove-${n}`,"aria-label":`Remove ${e.file.name}`,children:"×"})]},e.previewUrl||`${e.file.name}-${n}`))}),t.jsxs("div",{className:"chat-input-row",children:[t.jsx("button",{type:"button",className:"btn-icon chat-attach-btn","data-testid":"chat-attach-btn","aria-label":"Attach files",onClick:()=>Ve.current?.click(),children:t.jsx(Qt,{size:16})}),t.jsxs("div",{className:`chat-input-wrapper${ge?" chat-input-wrapper--dragover":""}`,onDragOver:e=>{e.preventDefault(),O(!0)},onDragLeave:()=>O(!1),onDrop:e=>{e.preventDefault(),O(!1),Te(e.dataTransfer.files)},children:[t.jsx("textarea",{ref:b,className:"chat-input-textarea",placeholder:"Type a message...",value:L,onChange:St,onKeyDown:wt,onKeyUp:bt,onClick:Oe,onBlur:kt,onFocus:yt,onPaste:xt,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(Xt,{agents:be,filter:Se,highlightedIndex:ye,visible:Z,onSelect:Ie,position:"below"}),t.jsx(Zt,{visible:u.mentionActive&&!Z,position:ie,files:u.files,selectedIndex:u.selectedIndex,onSelect:e=>{const n=u.selectFile(e,L);Y(n),u.dismissMention(),H(!1),b.current?.focus()},loading:u.loading}),v&&t.jsxs("div",{className:"chat-pending-message","data-testid":"chat-pending-indicator",children:[t.jsx("span",{children:`Queued: ${$t}`}),t.jsx("button",{type:"button",className:"chat-pending-message-dismiss","aria-label":"Dismiss queued message","data-testid":"chat-pending-dismiss",onClick:C,children:"×"})]})]}),j?t.jsx("button",{className:"chat-input-stop",onClick:g,"aria-label":"Stop generation","data-testid":"chat-stop-btn",children:t.jsx(es,{size:14})}):t.jsx("button",{type:"button",className:"chat-input-send",onPointerDown:e=>{typeof window>"u"||window.innerWidth>768||(e.preventDefault(),e.pointerType&&e.pointerType!=="mouse"&&(Me.current=!0,Ge(),Ae(),Ce(),window.setTimeout(()=>{ee.current=!1},1500)))},onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||(e.preventDefault(),Me.current=!0,Ge(),Ae(),Ce(),window.setTimeout(()=>{ee.current=!1},1500))},onMouseDown:e=>{typeof window>"u"||window.innerWidth>768||e.preventDefault()},onClick:()=>{if(Me.current){Me.current=!1;return}Ce()},disabled:!L.trim()&&S.length===0,"data-testid":"chat-send-btn",children:t.jsx(ts,{size:16})})]})]})]}),X&&t.jsx(hs,{projectId:a,onClose:()=>W(!1),onCreate:vt})]})}export{ws as ChatView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as u,j as s}from"./vendor-react-K0fH_qHe.js";import{w as ee,dP as se,s as ne,X as k,an as te,J as O,dQ as A,V,R as ie,dR as ae,aF as le,ch as re,dS as ce,dT as de,dU as ue,dV as oe,dW as _,ce as ge}from"./index-Bc8nfKeH.js";import{D as me}from"./DirectoryPicker-rew1y6qO.js";import"./vendor-xterm-DzcZoU0P.js";import"./folder-open-nYPrL1W3.js";const H=[{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0}],j={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function fe({addToast:l,projectId:c}){const[N,x]=u.useState([]),[S,w]=u.useState(!0),[J,f]=u.useState(!1),[b,v]=u.useState(""),[C,P]=u.useState(!1),[h,I]=u.useState(null),[i,y]=u.useState(null),[a,p]=u.useState({}),[M,R]=u.useState(!1),[$,E]=u.useState(null),{confirm:G}=ee(),o=u.useCallback(async()=>{try{w(!0);const e=await se(c);x(e)}catch(e){l(`Failed to load plugins: ${e instanceof Error?e.message:String(e)}`,"error")}finally{w(!1)}},[c,l]);u.useEffect(()=>{o()},[o]);const K=u.useRef([]);K.current=N,u.useEffect(()=>{const e=c?`?projectId=${encodeURIComponent(c)}`:"",n=g=>{try{const t=JSON.parse(g.data);if(c&&t.projectId&&t.projectId!==c)return;switch(t.transition){case"installing":case"enabled":case"disabled":case"settings-updated":x(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],enabled:t.enabled,state:t.state,settings:t.settings,error:t.error},r}else return o(),d});break;case"uninstalled":x(d=>d.filter(m=>m.id!==t.pluginId));break;case"error":x(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],state:t.state,error:t.error},r}return d});break}}catch{}};return ne(`/api/events${e}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{o()}})},[c,o]);const z=async()=>{if(!b.trim()){l("Please enter a plugin path","error");return}try{P(!0),await _({path:b},c),l("Plugin installed successfully","success"),f(!1),v(""),await o()}catch(e){l(`Failed to install plugin: ${e instanceof Error?e.message:String(e)}`,"error")}finally{P(!1)}},Q=async e=>{try{E(e.id),await _({path:e.path},c),l(`${e.name} installed successfully`,"success"),await o()}catch(n){l(`Failed to install ${e.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{E(null)}},F=async e=>{try{await ue(e.id,c),l(`${e.name} enabled`,"success"),await o()}catch(n){l(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},U=async e=>{try{await de(e.id,c),l(`${e.name} disabled`,"success"),await o()}catch(n){l(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},B=async e=>{try{I(e.id),await ce(e.id,c),l(`${e.name} reloaded`,"success"),await o()}catch(n){l(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{I(null)}},L=async e=>{if(await G({title:"Uninstall Plugin",message:`Are you sure you want to uninstall "${e.name}"?`,danger:!0}))try{await oe(e.id,c),l(`${e.name} uninstalled`,"success"),await o(),y(null)}catch(g){l(`Failed to uninstall plugin: ${g instanceof Error?g.message:String(g)}`,"error")}},W=async e=>{y(e);try{R(!0);const n=await ge(e.id,c);p(n)}catch{p({})}finally{R(!1)}},X=async()=>{if(i)try{await re(i.id,a,c),l("Settings saved","success")}catch(e){l(`Failed to save settings: ${e instanceof Error?e.message:String(e)}`,"error")}};if(i)return s.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[s.jsxs("div",{className:"plugin-manager-detail-header",children:[s.jsx("button",{className:"btn-icon",onClick:()=>y(null),"aria-label":"Back to plugin list",children:s.jsx(k,{size:16})}),s.jsxs("div",{className:"plugin-detail-title",children:[s.jsx("h4",{className:"plugin-detail-name",children:i.name}),s.jsx("span",{className:"plugin-state-badge",style:{color:j[i.state]||j.installed},children:i.state})]})]}),s.jsxs("div",{className:"plugin-detail-content",children:[s.jsxs("div",{className:"plugin-detail-card",children:[i.description&&s.jsx("p",{className:"plugin-description",children:i.description}),i.author&&s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Author:"}),i.author]}),i.homepage&&s.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[s.jsx("span",{className:"text-muted",children:"Homepage:"}),s.jsxs("a",{href:i.homepage,target:"_blank",rel:"noopener noreferrer",children:[i.homepage,s.jsx(te,{size:12})]})]}),s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Version:"}),i.version]})]}),s.jsxs("div",{className:"plugin-detail-card",children:[s.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),M?s.jsx("p",{className:"text-muted",children:"Loading..."}):i.settingsSchema&&Object.keys(i.settingsSchema).length>0?s.jsxs("div",{className:"plugin-settings-form",children:[Object.entries(i.settingsSchema).map(([e,n])=>{const g=`setting-${e}-help`;return s.jsxs("div",{className:"form-group",children:[s.jsxs("label",{htmlFor:`setting-${e}`,children:[n.label||e,n.required&&" *"]}),n.type==="string"&&!n.multiline&&s.jsx("input",{type:"text",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="string"&&n.multiline&&s.jsx("textarea",{id:`setting-${e}`,rows:4,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="password"&&s.jsx("input",{type:"password",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="number"&&s.jsx("input",{type:"number",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:Number(t.target.value)}),"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="boolean"&&s.jsxs("label",{className:"checkbox-label",children:[s.jsx("input",{type:"checkbox",checked:a[e]??!1,onChange:t=>p({...a,[e]:t.target.checked})}),n.description]}),n.type==="enum"&&s.jsxs("select",{id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),"aria-describedby":n.description&&!n.required?g:void 0,children:[s.jsx("option",{value:"",children:"Select..."}),n.enumValues?.map(t=>s.jsx("option",{value:t,children:t},t))]}),n.type==="array"&&s.jsxs("div",{className:"plugin-settings-array",children:[a[e]?.map((t,d)=>s.jsxs("div",{className:"plugin-settings-array-item",children:[s.jsx("input",{type:n.itemType==="number"?"number":"text",value:t??"",onChange:m=>{const r=m.target.value,D=[...a[e]||[]];D[d]=n.itemType==="number"?Number(r):r,p({...a,[e]:D})}}),s.jsx("button",{className:"btn-icon",onClick:()=>{const r=[...a[e]||[]];r.splice(d,1),p({...a,[e]:r})},"aria-label":"Remove item",children:s.jsx(k,{size:14})})]},d)),s.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const t=a[e]||[],d=n.itemType==="number"?0:"";p({...a,[e]:[...t,d]})},children:[s.jsx(O,{size:14})," Add Item"]})]}),n.description&&!n.required&&!n.multiline&&s.jsx("span",{id:g,className:"form-help",children:n.description})]},e)}),s.jsx("button",{className:"btn btn-primary",onClick:X,children:"Save Settings"})]}):s.jsx("p",{className:"text-muted",children:"No configurable settings."})]}),s.jsxs("div",{className:"plugin-detail-actions",children:[i.state==="started"&&s.jsxs("button",{className:"btn btn-secondary",onClick:()=>B(i),disabled:h===i.id,children:[s.jsx(A,{size:14,className:h===i.id?"spin":""}),h===i.id?"Reloading...":"Reload"]}),i.enabled?s.jsx("button",{className:"btn btn-secondary",onClick:()=>U(i),children:"Disable"}):s.jsx("button",{className:"btn btn-primary",onClick:()=>F(i),children:"Enable"}),s.jsxs("button",{className:"btn btn-danger",onClick:()=>L(i),children:[s.jsx(V,{size:14})," Uninstall"]})]})]})]});const Y=new Set(N.map(e=>e.id)),Z=new Set(H.map(e=>e.id)),q=N.filter(e=>!Z.has(e.id)),T=()=>s.jsxs("section",{className:"plugin-bundled-runtime-section","aria-label":"Bundled Runtime Plugins",children:[s.jsxs("div",{className:"plugin-bundled-runtime-header",children:[s.jsx("h4",{className:"plugin-bundled-runtime-heading",children:"Bundled Runtime Plugins"}),s.jsx("p",{className:"plugin-bundled-runtime-description",children:"Install Fusion's bundled runtimes directly from this screen."})]}),s.jsx("div",{className:"plugin-bundled-runtime-list","aria-label":"Bundled runtime plugin recommendations",children:H.map(e=>{const n=Y.has(e.id);return s.jsxs("div",{className:"plugin-bundled-runtime-item",children:[s.jsxs("div",{className:"plugin-bundled-runtime-meta",children:[s.jsx("span",{className:"plugin-bundled-runtime-name",children:e.name}),e.experimental&&s.jsx("span",{className:"plugin-bundled-runtime-badge",children:"Experimental"}),s.jsx("span",{className:`plugin-bundled-runtime-status ${n?"plugin-bundled-runtime-status--installed":"plugin-bundled-runtime-status--available"}`,children:n?"Installed":"Not installed"})]}),s.jsx("button",{className:`btn ${n?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>Q(e),disabled:n||$===e.id,children:n?"Installed":$===e.id?"Installing...":`Install ${e.name}`})]},e.id)})})]});return s.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[s.jsxs("div",{className:"plugin-manager-header",children:[s.jsx("span",{className:"plugin-manager-header-title",children:"Installed Plugins"}),s.jsxs("div",{className:"plugin-manager-actions",children:[s.jsxs("button",{className:"btn btn-sm btn-ghost",onClick:o,title:"Refresh","aria-label":"Refresh plugin list",children:[s.jsx(ie,{size:14,className:S?"spin":""}),"Refresh"]}),s.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>f(!0),children:[s.jsx(O,{size:14})," Install"]})]})]}),J&&s.jsxs("div",{className:"plugin-install-form",children:[s.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",s.jsx("code",{children:"manifest.json"}),") or a built ",s.jsx("code",{children:"dist"})," directory."]}),s.jsx(me,{value:b,onChange:v,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),z())}}),s.jsxs("div",{className:"plugin-install-actions",children:[s.jsx("button",{className:"btn btn-primary",onClick:z,disabled:C||!b.trim(),children:C?"Installing...":"Install Plugin"}),s.jsx("button",{className:"btn btn-secondary",onClick:()=>{f(!1),v("")},children:"Cancel"})]})]}),S?s.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):s.jsxs(s.Fragment,{children:[q.length===0?s.jsxs("div",{className:"settings-empty-state",children:[s.jsx(ae,{size:32,className:"text-muted"}),s.jsx("p",{children:"No plugins installed."}),s.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use a bundled runtime below."})]}):s.jsx("div",{className:"plugin-list",children:q.map(e=>s.jsxs("div",{className:"plugin-item",children:[s.jsxs("div",{className:"plugin-info",children:[s.jsx("span",{className:"plugin-name",children:e.name}),s.jsxs("span",{className:"plugin-version text-muted",children:["v",e.version]}),s.jsx("span",{className:"plugin-state-badge",style:{color:j[e.state]||j.installed},children:e.state})]}),s.jsxs("div",{className:"plugin-actions",children:[e.state==="started"&&s.jsx("button",{className:"btn-icon",onClick:()=>B(e),disabled:h===e.id,title:"Reload",children:s.jsx(A,{size:14,className:h===e.id?"spin":""})}),s.jsxs("label",{className:"toggle-switch",children:[s.jsx("input",{type:"checkbox",checked:e.enabled,onChange:()=>e.enabled?U(e):F(e)}),s.jsx("span",{className:"toggle-slider"})]}),s.jsx("button",{className:"btn-icon",onClick:()=>W(e),title:"Settings",children:s.jsx(le,{size:14})}),s.jsx("button",{className:"btn-icon",onClick:()=>L(e),title:"Uninstall",children:s.jsx(V,{size:14})})]})]},e.id))}),T()]})]})}export{fe as PluginManager,j as STATE_COLORS};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.plugin-manager,.plugin-manager-detail{display:flex;flex-direction:column;gap:var(--space-lg);padding-inline:var(--space-xl);padding-block:var(--space-md)}.plugin-manager-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--space-sm);border-bottom:var(--btn-border-width) solid var(--border);gap:var(--space-sm)}.plugin-manager-header-title{font-size:13px;font-weight:600;color:var(--text);flex:1}.plugin-manager-actions{display:flex;gap:var(--space-sm);align-items:center}.plugin-install-form{display:flex;flex-direction:column;gap:var(--space-sm);padding:var(--space-lg);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.plugin-install-hint{margin:0;font-size:.85rem;color:var(--text-secondary, var(--text-muted));line-height:1.45}.plugin-install-hint code{padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-sm);background:color-mix(in srgb,var(--text-muted) 12%,transparent);font-size:.85em}.plugin-install-actions{display:flex;gap:var(--space-sm);justify-content:flex-end}.plugin-list{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-item{display:flex;align-items:center;justify-content:space-between;padding:var(--space-md) var(--space-lg);background:var(--surface);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);transition:border-color var(--transition-fast)}.plugin-item:hover{border-color:var(--text-dim)}.plugin-info{display:flex;align-items:center;gap:var(--space-sm);min-width:0}.plugin-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.plugin-version{font-size:.85rem}.plugin-state-badge{display:inline-flex;align-items:center;padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;background:color-mix(in srgb,currentColor 12%,transparent)}.plugin-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.plugin-manager-detail-header,.plugin-detail-title{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap}.plugin-detail-name{margin:0}.plugin-detail-content{display:flex;flex-direction:column;gap:var(--space-lg)}.plugin-detail-card{background:var(--surface);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-md)}.plugin-description{font-size:.95rem;color:var(--text-secondary, var(--text-muted));line-height:1.5}.plugin-detail-meta-row{display:flex;align-items:center;gap:var(--space-xs);font-size:.9rem;color:var(--text-muted)}.plugin-homepage a{display:inline-flex;align-items:center;gap:var(--space-xs);color:var(--color-info);font-size:.85rem}.plugin-detail-section-heading{margin:0;padding:0;border:0;font-size:.95rem}.plugin-settings-form{display:flex;flex-direction:column;gap:var(--space-lg);margin-top:var(--space-xs)}.plugin-settings-form .form-group{padding:0;margin:0}.plugin-settings-array{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-settings-array-item{display:flex;align-items:center;gap:var(--space-sm)}.plugin-settings-array-item input{flex:1}.plugin-detail-actions{display:flex;gap:var(--space-sm);padding-top:var(--space-md);border-top:var(--btn-border-width) solid var(--border);justify-content:flex-end}.plugin-manager .empty-state,.plugin-manager .loading-state,.plugin-manager .settings-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-2xl);text-align:center;color:var(--text-muted)}.plugin-bundled-runtime-list{width:100%;display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.plugin-bundled-runtime-item{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.plugin-bundled-runtime-meta{display:flex;align-items:center;gap:var(--space-sm);min-width:0}.plugin-bundled-runtime-name{color:var(--text);font-size:.9rem;font-weight:500}.plugin-bundled-runtime-badge{display:inline-flex;align-items:center;padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-pill);background:var(--status-in-review-bg);color:var(--in-review);font-size:.75rem;font-weight:600;text-transform:uppercase}.plugin-bundled-runtime-section{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-bundled-runtime-header{display:flex;flex-direction:column;gap:var(--space-xs)}.plugin-bundled-runtime-heading{margin:0;font-size:.95rem}.plugin-bundled-runtime-description{margin:0;font-size:.85rem;color:var(--text-muted)}.plugin-bundled-runtime-status{display:inline-flex;align-items:center;padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-pill);font-size:.75rem;font-weight:600;text-transform:uppercase}.plugin-bundled-runtime-status--installed{background:var(--status-done-bg);color:var(--done)}.plugin-bundled-runtime-status--available{background:var(--status-todo-bg);color:var(--todo)}@media(max-width:768px){.plugin-manager-detail-header{gap:var(--space-sm)}.plugin-detail-title{gap:var(--space-xs)}.plugin-detail-card{padding:var(--space-md);gap:var(--space-sm)}.plugin-list{gap:var(--space-xs)}.plugin-item{padding:var(--space-md);flex-direction:column;align-items:stretch;gap:var(--space-sm)}.plugin-info{width:100%;flex-wrap:wrap;row-gap:var(--space-xs)}.plugin-name{flex:1 1 100%;white-space:normal}.plugin-actions{width:100%;justify-content:flex-end;flex-wrap:wrap;gap:var(--space-sm)}.plugin-actions .btn-icon,.plugin-actions .toggle-switch{min-width:36px;min-height:36px}.plugin-actions .toggle-switch{display:inline-flex;align-items:center;justify-content:center}.plugin-detail-actions{flex-wrap:wrap;justify-content:flex-start}.plugin-detail-actions button{flex:1 1 auto;min-height:36px}.plugin-bundled-runtime-item{flex-direction:column;align-items:stretch}.plugin-bundled-runtime-item .btn{min-height:36px}}
|