@nextclaw/ui 0.12.25 → 0.12.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/assets/{channels-list-page-FJDuPwU6.js → channels-list-page-HgLgrEg4.js} +1 -1
  3. package/dist/assets/chat-page-DAKMFDrS.js +1 -0
  4. package/dist/assets/{desktop-kk7qvZ-v.js → desktop-DVUbOWbR.js} +1 -1
  5. package/dist/assets/{index-D-AAMKCt.js → index-Cuwst6cc.js} +34 -37
  6. package/dist/assets/index-dlcqieQ0.css +1 -0
  7. package/dist/assets/{marketplace-page-BrCLRIc4.js → marketplace-page-BeFbwxR-.js} +2 -2
  8. package/dist/assets/marketplace-page-CR4xq-TM.js +1 -0
  9. package/dist/assets/mcp-marketplace-page-DlRrSCj3.js +1 -0
  10. package/dist/assets/{mcp-marketplace-page-DIq_SpMe.js → mcp-marketplace-page-DwnaLNTx.js} +1 -1
  11. package/dist/assets/{model-config-Bc6VVnxy.js → model-config-L2l6YAlQ.js} +1 -1
  12. package/dist/assets/{providers-list-DN0tvISH.js → providers-list-DYAEunOp.js} +1 -1
  13. package/dist/assets/{runtime-config-page-CRWOwBbl.js → runtime-config-page-BdeU8PEK.js} +1 -1
  14. package/dist/assets/{search-config-C4c1yZSP.js → search-config-CQUhd5RU.js} +1 -1
  15. package/dist/assets/{secrets-config-zAF30YfO.js → secrets-config-D-NWlW9q.js} +1 -1
  16. package/dist/assets/{use-infinite-scroll-loader-Cvz8ZteY.js → use-infinite-scroll-loader-CFVdPpNv.js} +1 -1
  17. package/dist/index.html +3 -3
  18. package/package.json +9 -9
  19. package/src/features/agents/components/agents-page.test.tsx +1 -1
  20. package/src/features/agents/components/agents-page.tsx +1 -1
  21. package/src/features/chat/components/chat-session-workspace-panel.tsx +31 -45
  22. package/src/features/chat/components/chat-sidebar-session-item.tsx +7 -9
  23. package/src/features/chat/components/conversation/chat-conversation-header.test.tsx +5 -2
  24. package/src/features/chat/components/conversation/chat-conversation-header.tsx +2 -2
  25. package/src/features/chat/components/conversation/chat-conversation-panel.test.tsx +106 -78
  26. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +172 -167
  27. package/src/features/chat/components/conversation/chat-input-bar.container.tsx +11 -1
  28. package/src/features/chat/components/conversation/session-header/chat-session-header-actions.tsx +2 -2
  29. package/src/features/chat/components/providers/chat-presenter.provider.tsx +2 -0
  30. package/src/features/chat/hooks/use-ncp-agent-runtime.test.tsx +147 -88
  31. package/src/features/chat/managers/ncp-chat-input.manager.test.ts +20 -0
  32. package/src/features/chat/managers/ncp-chat-input.manager.ts +18 -0
  33. package/src/features/chat/managers/ncp-chat-presenter.manager.ts +1 -0
  34. package/src/features/chat/pages/ncp-chat-page.tsx +4 -1
  35. package/src/features/chat/stores/chat-input.store.ts +3 -1
  36. package/src/features/chat/utils/ncp-chat-input-availability.utils.test.ts +1 -0
  37. package/src/platforms/desktop/components/desktop-app-shell.test.tsx +1 -0
  38. package/src/platforms/desktop/components/desktop-app-shell.tsx +1 -1
  39. package/dist/assets/chat-page-D1fMNBrT.js +0 -1
  40. package/dist/assets/index-DnBeV2Xm.css +0 -1
  41. package/dist/assets/marketplace-page-odDpPYEs.js +0 -1
  42. package/dist/assets/mcp-marketplace-page-CfbOBgKK.js +0 -1
@@ -5,6 +5,8 @@ import {
5
5
  type NcpEndpointEvent,
6
6
  type NcpEndpointManifest,
7
7
  type NcpEndpointSubscriber,
8
+ type NcpMessage,
9
+ type NcpStreamRequestPayload,
8
10
  NcpEventType,
9
11
  } from "@nextclaw/ncp";
10
12
  import { beforeEach, describe, expect, it, vi } from "vitest";
@@ -31,9 +33,57 @@ class DeferredSendClient implements NcpAgentClientEndpoint {
31
33
  readonly stream = vi.fn(async () => {});
32
34
  readonly abort = vi.fn(async () => {});
33
35
  private listeners = new Set<NcpEndpointSubscriber>();
34
- private releaseCompletion: (() => void) | null = null;
35
- private completionGate = new Promise<void>((resolve) => {
36
- this.releaseCompletion = resolve;
36
+
37
+ emit = async (event: NcpEndpointEvent): Promise<void> => {
38
+ this.publish(event);
39
+ };
40
+
41
+ subscribe = (listener: NcpEndpointSubscriber): (() => void) => {
42
+ this.listeners.add(listener);
43
+ return () => {
44
+ this.listeners.delete(listener);
45
+ };
46
+ };
47
+
48
+ send = vi.fn(async (envelope: NcpAgentSendEnvelope) => ({
49
+ sessionId: "session-created",
50
+ userMessageId: envelope.message.id,
51
+ assistantMessageId: "assistant-1",
52
+ runId: "run-1",
53
+ ...(envelope.correlationId ? { correlationId: envelope.correlationId } : {}),
54
+ }));
55
+
56
+ private publish = (event: NcpEndpointEvent): void => {
57
+ for (const listener of this.listeners) {
58
+ listener(event);
59
+ }
60
+ };
61
+ }
62
+
63
+ class ExistingSessionLiveClient implements NcpAgentClientEndpoint {
64
+ readonly manifest: NcpEndpointManifest = {
65
+ endpointKind: "agent",
66
+ endpointId: "existing-session-live-client",
67
+ version: "0.1.0",
68
+ supportsStreaming: true,
69
+ supportsAbort: true,
70
+ supportsProactiveMessages: false,
71
+ supportsLiveSessionStream: true,
72
+ supportedPartTypes: ["text"],
73
+ expectedLatency: "seconds",
74
+ };
75
+
76
+ readonly start = vi.fn(async () => {});
77
+ readonly abort = vi.fn(async () => {});
78
+ private listeners = new Set<NcpEndpointSubscriber>();
79
+ private liveStreamActive = false;
80
+
81
+ stop = vi.fn(async () => {
82
+ this.liveStreamActive = false;
83
+ });
84
+
85
+ stream = vi.fn(async (_payload: NcpStreamRequestPayload) => {
86
+ this.liveStreamActive = true;
37
87
  });
38
88
 
39
89
  emit = async (event: NcpEndpointEvent): Promise<void> => {
@@ -47,78 +97,59 @@ class DeferredSendClient implements NcpAgentClientEndpoint {
47
97
  };
48
98
  };
49
99
 
50
- send = vi.fn(async (_envelope: NcpAgentSendEnvelope): Promise<void> => {
51
- this.publish({
52
- type: NcpEventType.MessageSent,
53
- payload: {
54
- sessionId: "session-created",
55
- message: {
56
- id: "user-1",
57
- sessionId: "session-created",
58
- role: "user",
59
- status: "final",
60
- parts: [{ type: "text", text: "hello" }],
61
- timestamp: now,
100
+ send = vi.fn(async (envelope: NcpAgentSendEnvelope) => {
101
+ const events: NcpEndpointEvent[] = [
102
+ {
103
+ type: NcpEventType.RunStarted,
104
+ payload: {
105
+ sessionId: "session-existing",
106
+ messageId: "assistant-1",
107
+ runId: "run-1",
62
108
  },
63
109
  },
64
- });
65
- this.publish({
66
- type: NcpEventType.RunStarted,
67
- payload: {
68
- sessionId: "session-created",
69
- messageId: "assistant-1",
70
- runId: "run-1",
71
- },
72
- });
73
- await this.completionGate;
74
- this.publish({
75
- type: NcpEventType.MessageTextStart,
76
- payload: {
77
- sessionId: "session-created",
78
- messageId: "assistant-1",
79
- },
80
- });
81
- this.publish({
82
- type: NcpEventType.MessageTextDelta,
83
- payload: {
84
- sessionId: "session-created",
85
- messageId: "assistant-1",
86
- delta: "done",
110
+ {
111
+ type: NcpEventType.MessageTextStart,
112
+ payload: {
113
+ sessionId: "session-existing",
114
+ messageId: "assistant-1",
115
+ },
87
116
  },
88
- });
89
- this.publish({
90
- type: NcpEventType.MessageTextEnd,
91
- payload: {
92
- sessionId: "session-created",
93
- messageId: "assistant-1",
117
+ {
118
+ type: NcpEventType.MessageTextDelta,
119
+ payload: {
120
+ sessionId: "session-existing",
121
+ messageId: "assistant-1",
122
+ delta: "done",
123
+ },
94
124
  },
95
- });
96
- this.publish({
97
- type: NcpEventType.MessageCompleted,
98
- payload: {
99
- sessionId: "session-created",
100
- message: {
101
- id: "assistant-1",
102
- sessionId: "session-created",
103
- role: "assistant",
104
- status: "final",
105
- parts: [{ type: "text", text: "done" }],
106
- timestamp: now,
125
+ {
126
+ type: NcpEventType.MessageTextEnd,
127
+ payload: {
128
+ sessionId: "session-existing",
129
+ messageId: "assistant-1",
107
130
  },
108
131
  },
109
- });
110
- this.publish({
111
- type: NcpEventType.RunFinished,
112
- payload: {
113
- sessionId: "session-created",
114
- runId: "run-1",
132
+ {
133
+ type: NcpEventType.RunFinished,
134
+ payload: {
135
+ sessionId: "session-existing",
136
+ runId: "run-1",
137
+ },
115
138
  },
116
- });
117
- });
139
+ ];
118
140
 
119
- release = (): void => {
120
- this.releaseCompletion?.();
121
- };
141
+ if (this.liveStreamActive) {
142
+ for (const event of events) {
143
+ this.publish(event);
144
+ }
145
+ }
146
+ return {
147
+ sessionId: "session-existing",
148
+ userMessageId: envelope.message.id,
149
+ assistantMessageId: "assistant-1",
150
+ runId: "run-1",
151
+ };
152
+ });
122
153
 
123
154
  private publish = (event: NcpEndpointEvent): void => {
124
155
  for (const listener of this.listeners) {
@@ -127,12 +158,20 @@ class DeferredSendClient implements NcpAgentClientEndpoint {
127
158
  };
128
159
  }
129
160
 
161
+ function readAssistantText(messages: readonly NcpMessage[]): string {
162
+ const assistant = messages.find((message) => message.role === "assistant");
163
+ return assistant?.parts
164
+ .filter((part) => part.type === "text")
165
+ .map((part) => part.text ?? "")
166
+ .join("") ?? "";
167
+ }
168
+
130
169
  describe("useNcpAgentRuntime", () => {
131
170
  beforeEach(() => {
132
171
  vi.clearAllMocks();
133
172
  });
134
173
 
135
- it("keeps the active send stream alive when a new root chat materializes a session id", async () => {
174
+ it("returns a command handle when a new root chat materializes a session id", async () => {
136
175
  const client = new DeferredSendClient();
137
176
  const manager = new DefaultNcpAgentConversationStateManager();
138
177
  const envelope: NcpAgentSendEnvelope = {
@@ -150,31 +189,21 @@ describe("useNcpAgentRuntime", () => {
150
189
  { initialProps: { sessionId: undefined as string | undefined } },
151
190
  );
152
191
 
153
- let sendPromise: Promise<void>;
154
- act(() => {
155
- sendPromise = result.current.send(envelope);
192
+ let handle: Awaited<ReturnType<typeof result.current.send>> | null = null;
193
+ await act(async () => {
194
+ handle = await result.current.send(envelope);
156
195
  });
157
196
 
158
- await waitFor(() => {
159
- expect(result.current.snapshot.activeRun?.sessionId).toBe("session-created");
197
+ expect(handle).toEqual({
198
+ sessionId: "session-created",
199
+ userMessageId: "user-1",
200
+ assistantMessageId: "assistant-1",
201
+ runId: "run-1",
160
202
  });
161
-
162
- rerender({ sessionId: "session-created" });
163
-
203
+ expect(result.current.visibleMessages).toEqual([]);
164
204
  expect(client.stop).not.toHaveBeenCalled();
165
205
 
166
- await act(async () => {
167
- client.release();
168
- await sendPromise;
169
- });
170
-
171
- await waitFor(() => {
172
- expect(result.current.snapshot.activeRun).toBeNull();
173
- });
174
- expect(result.current.visibleMessages.map((message) => message.id)).toEqual([
175
- "user-1",
176
- "assistant-1",
177
- ]);
206
+ rerender({ sessionId: "session-created" });
178
207
  });
179
208
 
180
209
  it("aborts by session id even before a hydrated active run reaches local state", async () => {
@@ -190,4 +219,34 @@ describe("useNcpAgentRuntime", () => {
190
219
 
191
220
  expect(client.abort).toHaveBeenCalledWith({ sessionId: "session-running" });
192
221
  });
222
+
223
+ it("uses the hydrated live stream as the only event source while sending to an existing session", async () => {
224
+ const client = new ExistingSessionLiveClient();
225
+ const manager = new DefaultNcpAgentConversationStateManager();
226
+ await client.stream({ sessionId: "session-existing" });
227
+ const { result } = renderHook(() =>
228
+ useNcpAgentRuntime({ sessionId: "session-existing", client, manager: manager as never }),
229
+ );
230
+
231
+ await act(async () => {
232
+ await result.current.send({
233
+ sessionId: "session-existing",
234
+ message: {
235
+ id: "user-1",
236
+ sessionId: "session-existing",
237
+ role: "user",
238
+ status: "final",
239
+ parts: [{ type: "text", text: "hello" }],
240
+ timestamp: now,
241
+ },
242
+ });
243
+ });
244
+
245
+ await waitFor(() => {
246
+ expect(result.current.snapshot.activeRun).toBeNull();
247
+ expect(readAssistantText(result.current.visibleMessages)).toBe("done");
248
+ });
249
+ expect(client.stop).not.toHaveBeenCalled();
250
+ expect(client.stream).toHaveBeenCalledTimes(1);
251
+ });
193
252
  });
@@ -15,6 +15,7 @@ describe('NcpChatInputManager', () => {
15
15
  composerNodes: [createChatComposerTextNode('hello from current thread')],
16
16
  attachments: [],
17
17
  selectedSkills: [],
18
+ composerFocusRequest: null,
18
19
  selectedSessionType: 'native',
19
20
  selectedModel: 'gpt-5',
20
21
  selectedThinkingLevel: null,
@@ -209,4 +210,23 @@ describe('NcpChatInputManager', () => {
209
210
  expect(streamActionsManager.sendMessage).toHaveBeenCalledTimes(1);
210
211
  expect(sessionListManager.materializeRootSessionRoute).not.toHaveBeenCalled();
211
212
  });
213
+
214
+ it('creates and consumes one-shot composer focus requests', () => {
215
+ const manager = new NcpChatInputManager(
216
+ {} as ConstructorParameters<typeof NcpChatInputManager>[0],
217
+ {} as ConstructorParameters<typeof NcpChatInputManager>[1],
218
+ {} as ConstructorParameters<typeof NcpChatInputManager>[2],
219
+ );
220
+
221
+ manager.requestComposerFocusAtEnd();
222
+
223
+ const request = useChatInputStore.getState().snapshot.composerFocusRequest;
224
+ expect(request).toEqual({ id: 1, placement: 'end' });
225
+
226
+ manager.consumeComposerFocusRequest(999);
227
+ expect(useChatInputStore.getState().snapshot.composerFocusRequest).toEqual(request);
228
+
229
+ manager.consumeComposerFocusRequest(request!.id);
230
+ expect(useChatInputStore.getState().snapshot.composerFocusRequest).toBeNull();
231
+ });
212
232
  });
@@ -132,6 +132,24 @@ export class NcpChatInputManager {
132
132
  this.syncComposerSnapshot(createChatComposerNodesFromDraft(value));
133
133
  };
134
134
 
135
+ requestComposerFocusAtEnd = () => {
136
+ const currentRequest = useChatInputStore.getState().snapshot.composerFocusRequest;
137
+ useChatInputStore.getState().setSnapshot({
138
+ composerFocusRequest: {
139
+ id: (currentRequest?.id ?? 0) + 1,
140
+ placement: 'end',
141
+ },
142
+ });
143
+ };
144
+
145
+ consumeComposerFocusRequest = (requestId: number) => {
146
+ const currentRequest = useChatInputStore.getState().snapshot.composerFocusRequest;
147
+ if (currentRequest?.id !== requestId) {
148
+ return;
149
+ }
150
+ useChatInputStore.getState().setSnapshot({ composerFocusRequest: null });
151
+ };
152
+
135
153
  setComposerNodes = (next: SetStateAction<ChatComposerNode[]>) => {
136
154
  const prev = useChatInputStore.getState().snapshot.composerNodes;
137
155
  const value = this.resolveUpdateValue(prev, next);
@@ -23,5 +23,6 @@ export class NcpChatPresenter {
23
23
  this.chatSessionListManager.createSession();
24
24
  this.chatSessionListManager.setSelectedAgentId('main');
25
25
  this.chatInputManager.setDraft(prompt);
26
+ this.chatInputManager.requestComposerFocusAtEnd();
26
27
  };
27
28
  }
@@ -281,7 +281,10 @@ function useNcpChatStreamBindings(params: ReturnType<typeof useNcpChatPageState>
281
281
  return;
282
282
  }
283
283
  try {
284
- await agent.send(envelope);
284
+ const handle = await agent.send(envelope);
285
+ if (!payload.sessionKey && handle?.sessionId) {
286
+ presenter.chatSessionListManager.materializeRootSessionRoute(handle.sessionId);
287
+ }
285
288
  } catch (error) {
286
289
  if (payload.restoreDraftOnError) {
287
290
  if (payload.composerNodes && payload.composerNodes.length > 0) {
@@ -44,6 +44,7 @@ export type ChatInputSnapshot = {
44
44
  skillRecords: SessionSkillEntryView[];
45
45
  isSkillsLoading: boolean;
46
46
  selectedSkills: string[];
47
+ composerFocusRequest: { id: number; placement: 'end' } | null;
47
48
  };
48
49
 
49
50
  type ChatInputStore = {
@@ -75,7 +76,8 @@ const initialSnapshot: ChatInputSnapshot = {
75
76
  sessionTypeUnavailable: false,
76
77
  skillRecords: [],
77
78
  isSkillsLoading: false,
78
- selectedSkills: []
79
+ selectedSkills: [],
80
+ composerFocusRequest: null
79
81
  };
80
82
 
81
83
  export const useChatInputStore = create<ChatInputStore>((set) => ({
@@ -36,6 +36,7 @@ function createSnapshot(
36
36
  skillRecords: [],
37
37
  isSkillsLoading: false,
38
38
  selectedSkills: [],
39
+ composerFocusRequest: null,
39
40
  ...overrides,
40
41
  };
41
42
  }
@@ -51,6 +51,7 @@ describe("DesktopAppShell", () => {
51
51
  const mainChrome = screen.getByTestId("desktop-window-chrome-main");
52
52
 
53
53
  expect(chrome).toBeTruthy();
54
+ expect(chrome.parentElement?.style.getPropertyValue("--desktop-titlebar-height")).toBe("40px");
54
55
  expect(sidebarChrome.className).toContain("w-[var(--desktop-sidebar-width)]");
55
56
  expect(sidebarChrome.className).not.toContain("border-b");
56
57
  expect(mainChrome.className).toContain("border-b");
@@ -25,7 +25,7 @@ type DesktopShellStyle = CSSProperties & {
25
25
 
26
26
  function createWindowsDesktopShellStyle(isMainRoute: boolean): DesktopShellStyle {
27
27
  return {
28
- "--desktop-titlebar-height": "34px",
28
+ "--desktop-titlebar-height": "40px",
29
29
  "--desktop-caption-safe-right": "140px",
30
30
  "--desktop-sidebar-width": isMainRoute ? "280px" : "240px",
31
31
  };
@@ -1 +0,0 @@
1
- import{_ as e,m as t,p as n,r,u as i}from"./i18n-D1144VAA.js";import{At as a,Mt as o,Nt as s,Tt as c,_t as l,kt as u,wt as d}from"./api-DGD9_Bg4.js";import{c as f,l as p,u as m}from"./cpu-DPPwMzoC.js";import{n as h,t as g}from"./marketplace-page-BrCLRIc4.js";import{a as _,i as v,n as y,o as b,r as x,t as S}from"./dialog-BKo0RItd.js";import{t as C}from"./createLucideIcon-DzY6wN61.js";import{D as w,O as T,w as E}from"./desktop-kk7qvZ-v.js";import{a as D,i as O,n as k,r as A,t as j}from"./select-BUTwE_lC.js";import{i as ee,n as te,r as ne,t as re}from"./provider-scoped-model-input-BMTp4BEH.js";import"./mcp-marketplace-page-DIq_SpMe.js";import{t as ie}from"./play-AqrNslHI.js";import{t as M}from"./plus-B-YHtTNC.js";import{t as ae}from"./refresh-cw-CrbD8EkT.js";import{t as oe}from"./sparkles-BmgOD4nY.js";import{t as se}from"./notice-card-Dr6xCwva.js";import{_ as ce,d as le,f as ue,m as de,n as N,o as fe,r as P,s as pe}from"./use-config-Cyv5IuSt.js";import{n as me,r as he,t as ge}from"./popover-BDFNiLlg.js";import{$ as _e,A as ve,B as F,C as I,D as L,E as ye,F as be,G as xe,H as Se,I as Ce,K as we,L as Te,M as R,N as z,O as Ee,P as De,R as Oe,S as ke,T as B,U as Ae,V as je,W as V,X as H,Y as Me,Z as U,a as Ne,b as Pe,c as W,d as Fe,g as Ie,i as Le,j as Re,k as ze,l as Be,n as G,nt as Ve,o as He,r as Ue,s as K,t as We,u as Ge,v as Ke,w as qe,x as q,y as Je,z as J}from"./index-D-AAMKCt.js";import{t as Ye}from"./tag-chip-Dm2Lqnpu.js";var Xe=C(`ShieldCheck`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]),Y=e(t(),1),X=n(),Z=Y.forwardRef(({className:e,...t},n)=>(0,X.jsx)(`textarea`,{className:i(`flex min-h-28 w-full rounded-xl border border-gray-200/80 bg-white px-3.5 py-2.5 text-sm text-gray-900 placeholder:text-gray-300 placeholder:font-normal focus:outline-none focus:ring-1 focus:ring-primary/40 focus:border-primary/40 transition-colors disabled:cursor-not-allowed disabled:opacity-50`,e),ref:n,...t}));Z.displayName=`Textarea`;function Ze(e){return{displayName:e.displayName??``,description:e.description??``,avatar:e.avatar??``,model:e.model??``,runtime:e.runtime??e.engine??``}}function Qe(e){let{runtimeOptions:t,currentRuntime:n}=e,r=n.trim();if(!r)return t;let i=I(r);return t.some(e=>e.value===i)?t:[...t,{value:i,label:B(i),icon:null,ready:!1,reason:`unavailable`,reasonMessage:null,supportedModels:void 0,recommendedModel:null,cta:null}].sort((e,t)=>e.value===`native`?-1:t.value===`native`?1:e.value.localeCompare(t.value))}function $e({value:e,disabled:t=!1,runtimeOptions:n,defaultRuntime:i,onChange:a}){let o=e.trim()?I(e):``,s=Qe({runtimeOptions:n,currentRuntime:e}),c=s.find(e=>e.value===o)??null,l=c?.reasonMessage?.trim()||(c?.ready===!1?r(`agentsRuntimeUnavailableHelp`):``);return(0,X.jsxs)(`div`,{className:`space-y-2`,children:[(0,X.jsxs)(j,{value:o||i,onValueChange:e=>a(e===i?``:e),disabled:t,children:[(0,X.jsx)(O,{"aria-label":r(`agentsCardRuntimeLabel`),className:`rounded-xl`,children:(0,X.jsx)(D,{placeholder:r(`agentsRuntimeSelectPlaceholder`)})}),(0,X.jsx)(k,{className:`rounded-xl`,children:s.map(e=>(0,X.jsx)(A,{value:e.value,disabled:e.ready===!1&&e.value!==o,className:`rounded-lg`,children:e.label},e.value))})]}),l?(0,X.jsx)(`p`,{className:`text-xs text-gray-500`,children:l}):null]})}function et({agent:e,pending:t,providerCatalog:n,runtimeOptions:r,defaultRuntime:i,onOpenChange:a,onSubmit:o}){return(0,X.jsx)(S,{open:e!==null,onOpenChange:a,children:e?(0,X.jsx)(tt,{agent:e,pending:t,providerCatalog:n,runtimeOptions:r,defaultRuntime:i,onOpenChange:a,onSubmit:o},e.id):null})}function tt(e){let{agent:t,pending:n,providerCatalog:i,runtimeOptions:a,defaultRuntime:c,onOpenChange:l,onSubmit:u}=e,[d,f]=(0,Y.useState)(Ze(t));return(0,X.jsxs)(y,{className:`flex max-h-[calc(100vh-2rem)] flex-col overflow-hidden border-none bg-[linear-gradient(180deg,#fff9f1_0%,#ffffff_24%)] p-0 sm:max-h-[760px] sm:max-w-xl`,children:[(0,X.jsx)(`div`,{className:`shrink-0 border-b border-[#f0e2c8] px-6 py-6`,children:(0,X.jsxs)(_,{className:`text-left`,children:[(0,X.jsx)(b,{children:r(`agentsEditDialogTitle`)}),(0,X.jsx)(x,{children:r(`agentsEditDialogDescription`)})]})}),(0,X.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-6`,children:(0,X.jsxs)(`div`,{className:`space-y-4`,children:[(0,X.jsx)(se,{tone:`warning`,title:r(`agentsEditHomeReadonly`),description:r(`agentsEditHomeReadonlyHint`),children:(0,X.jsx)(`div`,{className:`break-all text-sm text-amber-950`,children:t.workspace??`-`})}),(0,X.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-2`,children:[(0,X.jsx)(o,{value:d.displayName,onChange:e=>f(t=>({...t,displayName:e.target.value})),placeholder:r(`agentsFormNamePlaceholder`)}),(0,X.jsx)(Z,{value:d.description,onChange:e=>f(t=>({...t,description:e.target.value})),placeholder:r(`agentsFormDescriptionPlaceholder`),rows:4,className:`md:col-span-2`}),(0,X.jsx)(o,{value:d.avatar,onChange:e=>f(t=>({...t,avatar:e.target.value})),placeholder:r(`agentsFormAvatarPlaceholder`)}),(0,X.jsx)(re,{value:d.model,onChange:e=>f(t=>({...t,model:e})),providerCatalog:i,disabled:n,className:`md:col-span-2`}),(0,X.jsx)($e,{value:d.runtime,onChange:e=>f(t=>({...t,runtime:e})),runtimeOptions:a,defaultRuntime:c,disabled:n})]})]})}),(0,X.jsxs)(v,{className:`shrink-0 border-t border-[#f1e7d4] px-6 py-5`,children:[(0,X.jsx)(s,{type:`button`,variant:`ghost`,onClick:()=>l(!1),disabled:n,children:r(`cancel`)}),(0,X.jsxs)(s,{type:`button`,variant:`primary`,className:`rounded-2xl px-5`,onClick:()=>u(t.id,d),disabled:n,children:[(0,X.jsx)(U,{className:`mr-2 h-4 w-4`}),r(`agentsEditSaveAction`)]})]})]})}var Q=`请帮我创建一个新的 Agent。先问我这个 Agent 的用途、名称、工作目录、默认 Runtime / 模型和需要的技能;信息足够后,请用 NextClaw 的 Agent 管理能力完成创建。`;function nt(e){let{agentCount:t,onCreate:n}=e;return(0,X.jsxs)(`section`,{className:`flex flex-col gap-3 border-b border-gray-200 pb-4 sm:flex-row sm:items-end sm:justify-between`,children:[(0,X.jsxs)(`div`,{className:`min-w-0 space-y-1`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,X.jsx)(`h1`,{className:`text-xl font-semibold text-gray-950`,children:r(`agentsHeroEyebrow`)}),(0,X.jsx)(`span`,{className:`rounded-full border border-gray-200 bg-white px-2 py-0.5 text-xs font-medium text-gray-500`,children:t})]}),(0,X.jsx)(`p`,{className:`max-w-2xl text-sm leading-6 text-gray-500`,children:r(`agentsHeroDescription`)})]}),(0,X.jsxs)(s,{type:`button`,variant:`primary`,className:`h-9 shrink-0 rounded-xl px-4 text-sm font-semibold`,onClick:n,children:[(0,X.jsx)(M,{className:`mr-2 h-4 w-4`}),r(`agentsCreateButton`)]})]})}function $(e){let{icon:t,label:n,disabled:r=!1,destructive:a=!1,onClick:o}=e;return(0,X.jsxs)(`button`,{type:`button`,className:i(`flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50`,a?`text-destructive hover:bg-destructive/10`:`text-gray-700 hover:bg-gray-100`),onClick:o,disabled:r,children:[(0,X.jsx)(t,{className:`h-4 w-4 shrink-0`}),(0,X.jsx)(`span`,{children:n})]})}function rt(e){let{agent:t,runtimeOptions:n,defaultRuntimeLabel:i,updatePending:a,deletePending:o,onStartChat:l,onEdit:u,onDelete:f}=e,p=t.runtime?.trim()||t.engine?.trim()||``,m=p?n.find(e=>e.value===I(p))?.label??B(p):i;return(0,X.jsx)(d,{className:`group overflow-hidden border border-gray-200 bg-white shadow-none transition-colors duration-200 hover:border-gray-300`,children:(0,X.jsxs)(c,{className:`relative flex h-full flex-col gap-3 px-3.5 py-3.5`,children:[(0,X.jsxs)(`div`,{className:`flex items-start gap-2.5 pr-16`,children:[(0,X.jsx)(we,{agentId:t.id,displayName:t.displayName,avatarUrl:t.avatarUrl,className:`h-9 w-9 shrink-0`}),(0,X.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-0.5`,children:[(0,X.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,X.jsx)(`div`,{className:`truncate text-sm font-semibold text-gray-950`,children:t.displayName?.trim()||t.id}),t.builtIn?(0,X.jsxs)(Ye,{tone:`warning`,className:`h-5 gap-1 border-amber-200 bg-amber-50 px-1.5 text-[10px] text-amber-700`,children:[(0,X.jsx)(Xe,{className:`h-3 w-3`}),r(`agentsCardBuiltInTag`)]}):null]}),(0,X.jsxs)(`div`,{className:`truncate text-xs text-gray-400`,children:[`@`,t.id]})]})]}),(0,X.jsxs)(`div`,{className:`absolute right-2.5 top-2.5 flex items-center gap-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100`,children:[(0,X.jsx)(s,{type:`button`,variant:`ghost`,size:`icon`,className:`h-8 w-8 rounded-lg text-gray-400 hover:text-gray-800`,"aria-label":r(`agentsCardStartChat`),title:r(`agentsCardStartChat`),onClick:l,children:(0,X.jsx)(E,{className:`h-4 w-4`})}),(0,X.jsxs)(ge,{children:[(0,X.jsx)(he,{asChild:!0,children:(0,X.jsx)(s,{type:`button`,variant:`ghost`,size:`icon`,className:`h-8 w-8 rounded-lg text-gray-400 hover:text-gray-800`,"aria-label":r(`chatSessionMoreActions`),title:r(`chatSessionMoreActions`),children:(0,X.jsx)(Ve,{className:`h-4 w-4`})})}),(0,X.jsxs)(me,{align:`end`,className:`w-44 p-1.5`,children:[(0,X.jsx)($,{icon:U,label:r(`agentsEditAction`),onClick:u,disabled:a}),t.builtIn?null:(0,X.jsx)($,{icon:H,label:r(`agentsRemoveAction`),onClick:f,disabled:o,destructive:!0})]})]})]}),(0,X.jsx)(`p`,{className:`line-clamp-2 min-h-10 text-sm leading-5 text-gray-600`,children:t.description?.trim()||(t.builtIn?r(`agentsCardBuiltInSummary`):r(`agentsCardCustomSummary`))}),(0,X.jsxs)(`div`,{className:`mt-auto grid gap-2 border-t border-gray-100 pt-2 text-xs text-gray-500`,children:[(0,X.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,X.jsx)(oe,{className:`h-3.5 w-3.5 shrink-0 text-gray-300`}),(0,X.jsx)(`span`,{className:`truncate`,children:m})]}),(0,X.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,X.jsx)(_e,{className:`h-3.5 w-3.5 shrink-0 text-gray-300`}),(0,X.jsx)(`span`,{className:`truncate`,children:t.workspace??`-`})]})]})]})})}function it(){let e=Ae(),t=L(),n=N(),i=P(),o=K(),l=ze(),u=Ee(),[f,p]=(0,Y.useState)(null),m=(0,Y.useMemo)(()=>t.data?.agents??[],[t.data?.agents]),h=(0,Y.useMemo)(()=>[...m].sort((e,t)=>Number(!!t.builtIn)-Number(!!e.builtIn)||e.id.localeCompare(t.id)),[m]),g=(0,Y.useMemo)(()=>te({config:n.data,meta:i.data,onlyConfigured:!0}),[i.data,n.data]),_=(0,Y.useMemo)(()=>ke(o.data?.options??[]),[o.data?.options]),v=(0,Y.useMemo)(()=>I(o.data?.defaultType??`native`),[o.data?.defaultType]),y=(0,Y.useMemo)(()=>_.find(e=>e.value===v)?.label??B(v),[v,_]),b=e=>{p(e)},x=async(e,t)=>{await l.mutateAsync({agentId:e,data:{displayName:t.displayName,description:t.description,avatar:t.avatar,model:t.model,...t.runtime.trim()?{runtime:t.runtime.trim()}:{runtime:``}}}),p(null)},S=t=>{e.chatSessionListManager.startAgentDraftChat(t.id,qe(t,v))};return(0,X.jsxs)(a,{className:`space-y-5`,children:[(0,X.jsx)(nt,{agentCount:m.length,onCreate:()=>e.startAgentCreationDraft(Q)}),(0,X.jsx)(`div`,{className:`grid gap-4 md:grid-cols-2 xl:grid-cols-3`,children:t.isLoading?(0,X.jsx)(d,{className:`md:col-span-2 xl:col-span-3 border-dashed border-[#d9dce3] bg-white/70`,children:(0,X.jsx)(c,{className:`py-14 text-center text-sm text-gray-500`,children:r(`agentsLoading`)})}):h.length===0?(0,X.jsx)(d,{className:`md:col-span-2 xl:col-span-3 overflow-hidden border-dashed border-[#d9dce3] bg-[linear-gradient(135deg,#fff7ea_0%,#f4fbff_100%)]`,children:(0,X.jsxs)(c,{className:`flex min-h-[240px] flex-col items-center justify-center px-6 py-14 text-center`,children:[(0,X.jsx)(`div`,{className:`mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-white/80 shadow-[0_18px_44px_rgba(0,0,0,0.08)]`,children:(0,X.jsx)(w,{className:`h-8 w-8 text-[#d39a3b]`})}),(0,X.jsx)(`div`,{className:`text-lg font-semibold text-[#2f2212]`,children:r(`agentsEmpty`)}),(0,X.jsx)(`p`,{className:`mt-2 max-w-md text-sm leading-6 text-[#78644d]`,children:r(`agentsEmptyDescription`)}),(0,X.jsxs)(s,{type:`button`,variant:`primary`,className:`mt-5 rounded-2xl px-5`,onClick:()=>e.startAgentCreationDraft(Q),children:[(0,X.jsx)(M,{className:`mr-2 h-4 w-4`}),r(`agentsCreateButton`)]})]})}):h.map(e=>(0,X.jsx)(rt,{agent:e,runtimeOptions:_,defaultRuntimeLabel:y,updatePending:l.isPending,deletePending:u.isPending,onStartChat:()=>S(e),onEdit:()=>b(e),onDelete:()=>u.mutate({agentId:e.id})},e.id))}),(0,X.jsx)(et,{agent:f,pending:l.isPending,providerCatalog:g,runtimeOptions:_,defaultRuntime:v,onOpenChange:e=>{!e&&!l.isPending&&p(null)},onSubmit:x})]})}function at(e,t){let n=t.trim().toLowerCase();return n?[e.id,e.name,e.payload.message,e.payload.sessionId??``,e.payload.channel??``,e.payload.to??``].join(` `).toLowerCase().includes(n):!0}function ot(e,t){return t===`all`?!0:t===`enabled`?e.enabled:!e.enabled}function st(e){let{job:t,onDelete:n,onRun:a,onToggle:o}=e;return(0,X.jsx)(d,{className:`border border-gray-200`,children:(0,X.jsx)(c,{className:`pt-5 pb-5`,children:(0,X.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-4`,children:[(0,X.jsxs)(`div`,{className:`min-w-[220px] flex-1`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,X.jsx)(`span`,{className:`text-sm font-semibold text-gray-900`,children:t.name||t.id}),(0,X.jsx)(`span`,{className:`rounded-full bg-gray-100 px-2 py-0.5 text-[10px] font-semibold text-gray-500`,children:t.id}),(0,X.jsx)(`span`,{className:i(`rounded-full px-2 py-0.5 text-[10px] font-semibold`,t.enabled?`bg-emerald-50 text-emerald-700`:`bg-gray-100 text-gray-500`),children:t.enabled?r(`enabled`):r(`disabled`)}),t.deleteAfterRun?(0,X.jsx)(`span`,{className:`rounded-full bg-amber-50 px-2 py-0.5 text-[10px] font-semibold text-amber-700`,children:r(`cronOneShot`)}):null]}),(0,X.jsxs)(`div`,{className:`mt-2 text-xs text-gray-500`,children:[r(`cronScheduleLabel`),`: `,Je(t)]}),(0,X.jsx)(`div`,{className:`mt-2 whitespace-pre-wrap break-words text-sm text-gray-700`,children:t.payload.message}),(0,X.jsxs)(`div`,{className:`mt-2 text-xs text-gray-500`,children:[r(`cronSessionLabel`),`: `,Pe(t)]}),(0,X.jsxs)(`div`,{className:`mt-2 text-xs text-gray-500`,children:[r(`cronDeliverTo`),`: `,Ke(t)]})]}),(0,X.jsxs)(`div`,{className:`min-w-[220px] space-y-2 text-xs text-gray-500`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsxs)(`span`,{className:`font-medium text-gray-700`,children:[r(`cronNextRun`),`:`]}),` `,q(t.state.nextRunAt)]}),(0,X.jsxs)(`div`,{children:[(0,X.jsxs)(`span`,{className:`font-medium text-gray-700`,children:[r(`cronLastRun`),`:`]}),` `,q(t.state.lastRunAt)]}),(0,X.jsxs)(`div`,{children:[(0,X.jsxs)(`span`,{className:`font-medium text-gray-700`,children:[r(`cronLastStatus`),`:`]}),` `,t.state.lastStatus??`-`]}),t.state.lastError?(0,X.jsx)(`div`,{className:`break-words text-[11px] text-red-500`,children:t.state.lastError}):null]}),(0,X.jsxs)(`div`,{className:`flex flex-wrap items-start justify-end gap-2`,children:[(0,X.jsxs)(s,{variant:`subtle`,size:`sm`,onClick:()=>a(t),className:`gap-1`,children:[(0,X.jsx)(ie,{className:`h-3.5 w-3.5`}),r(`cronRunNow`)]}),(0,X.jsxs)(s,{variant:t.enabled?`outline`:`primary`,size:`sm`,onClick:()=>o(t),className:`gap-1`,children:[(0,X.jsx)(h,{className:`h-3.5 w-3.5`}),t.enabled?r(`cronDisable`):r(`cronEnable`)]}),(0,X.jsxs)(s,{variant:`destructive`,size:`sm`,onClick:()=>n(t),className:`gap-1`,children:[(0,X.jsx)(H,{className:`h-3.5 w-3.5`}),r(`delete`)]})]})]})})})}function ct(){let[e,t]=(0,Y.useState)(``),[n,c]=(0,Y.useState)(`all`),l=fe({all:!0}),d=pe(),f=ce(),p=de(),{confirm:m,ConfirmDialog:h}=W(),g=(0,Y.useMemo)(()=>(l.data?.jobs??[]).filter(t=>at(t,e)).filter(e=>ot(e,n)),[l.data,e,n]),_=async e=>{await m({title:`${r(`cronDeleteConfirm`)}?`,description:e.name?`${e.name} (${e.id})`:e.id,variant:`destructive`,confirmLabel:r(`delete`)})&&d.mutate({id:e.id})},v=async e=>{let t=!e.enabled;await m({title:t?`${r(`cronEnableConfirm`)}?`:`${r(`cronDisableConfirm`)}?`,description:e.name?`${e.name} (${e.id})`:e.id,variant:t?`default`:`destructive`,confirmLabel:r(t?`cronEnable`:`cronDisable`)})&&f.mutate({id:e.id,enabled:t})},y=async e=>{let t=!e.enabled;await m({title:t?`${r(`cronRunForceConfirm`)}?`:`${r(`cronRunConfirm`)}?`,description:e.name?`${e.name} (${e.id})`:e.id,confirmLabel:r(`cronRunNow`)})&&p.mutate({id:e.id,force:t})};return(0,X.jsxs)(a,{fullHeight:!0,children:[(0,X.jsx)(u,{title:r(`cronPageTitle`),description:r(`cronPageDescription`),actions:(0,X.jsx)(s,{variant:`ghost`,size:`icon`,className:`h-9 w-9 rounded-lg text-gray-400 hover:text-gray-700 hover:bg-gray-100`,onClick:()=>l.refetch(),children:(0,X.jsx)(ae,{className:i(`h-4 w-4`,l.isFetching&&`animate-spin`)})})}),(0,X.jsx)(`div`,{className:`mb-6`,children:(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-3 items-center`,children:[(0,X.jsxs)(`div`,{className:`relative flex-1 min-w-[240px]`,children:[(0,X.jsx)(o,{value:e,onChange:e=>t(e.target.value),placeholder:r(`cronSearchPlaceholder`),className:`pl-9`}),(0,X.jsx)(T,{className:`absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400`})]}),(0,X.jsx)(`div`,{className:`min-w-[180px]`,children:(0,X.jsxs)(j,{value:n,onValueChange:e=>c(e),children:[(0,X.jsx)(O,{className:`w-full`,children:(0,X.jsx)(D,{placeholder:r(`cronStatusLabel`)})}),(0,X.jsxs)(k,{children:[(0,X.jsx)(A,{value:`all`,children:r(`cronStatusAll`)}),(0,X.jsx)(A,{value:`enabled`,children:r(`cronStatusEnabled`)}),(0,X.jsx)(A,{value:`disabled`,children:r(`cronStatusDisabled`)})]})]})}),(0,X.jsxs)(`div`,{className:`text-xs text-gray-500 ml-auto`,children:[r(`cronTotalLabel`),`: `,l.data?.total??0,` / `,g.length]})]})}),(0,X.jsx)(`div`,{className:`flex-1 overflow-auto custom-scrollbar`,children:l.isLoading?(0,X.jsx)(`div`,{className:`text-sm text-gray-400 p-4 text-center`,children:r(`cronLoading`)}):g.length===0?(0,X.jsx)(`div`,{className:`text-sm text-gray-400 p-4 text-center`,children:r(`cronEmpty`)}):(0,X.jsx)(`div`,{className:`space-y-4`,children:g.map(e=>(0,X.jsx)(st,{job:e,onDelete:_,onRun:y,onToggle:v},e.id))})}),(0,X.jsx)(h,{})]})}function lt(e){let{view:t,routeSessionKey:n,selectedSessionKey:r,setSelectedSessionKey:i,selectedSessionKeyRef:a,resetStreamState:o}=e;(0,Y.useEffect)(()=>{if(t===`chat`){if(n){r!==n&&i(n);return}r!==null&&(i(null),o())}},[o,n,r,i,t]),(0,Y.useEffect)(()=>{a.current=r},[r,a])}function ut({view:e,confirmDialog:t}){let{isMobile:n}=Me();return(0,X.jsxs)(`div`,{className:`h-full flex`,children:[n?null:(0,X.jsx)(Fe,{}),e===`chat`?n?(0,X.jsx)(We,{}):(0,X.jsx)(Ie,{}):(0,X.jsx)(`section`,{className:`flex-1 min-h-0 overflow-hidden bg-gradient-to-b from-gray-50/60 to-white`,children:e===`cron`?(0,X.jsx)(`div`,{className:`h-full overflow-auto custom-scrollbar`,children:(0,X.jsx)(`div`,{className:`mx-auto w-full max-w-[min(1120px,100%)] px-4 py-4 sm:px-6 sm:py-5`,children:(0,X.jsx)(ct,{})})}):e===`agents`?(0,X.jsx)(`div`,{className:`h-full overflow-auto custom-scrollbar`,children:(0,X.jsx)(`div`,{className:`mx-auto w-full max-w-[min(1180px,100%)] px-4 py-4 sm:px-6 sm:py-5`,children:(0,X.jsx)(it,{})})}):(0,X.jsx)(`div`,{className:`h-full overflow-hidden`,children:(0,X.jsx)(`div`,{className:`mx-auto flex h-full min-h-0 w-full max-w-[min(1120px,100%)] flex-col px-4 py-4 sm:px-6 sm:py-5`,children:(0,X.jsx)(g,{forcedType:`skills`})})})}),t]})}function dt(e,t){return e.filter(e=>xe(e,t))}function ft(e){let{config:t,meta:n}=e;return(0,Y.useMemo)(()=>{let e=te({meta:n,config:t,onlyConfigured:!0}),r=new Set,i=[];for(let t of e)for(let e of t.models){let n=ne(t.prefix,e);!n||r.has(n)||(r.add(n),i.push({value:n,modelLabel:e,providerLabel:t.displayName,thinkingCapability:ee(t.modelThinking,e,t.aliases)}))}return i.sort((e,t)=>{let n=e.providerLabel.localeCompare(t.providerLabel);return n===0?e.modelLabel.localeCompare(t.modelLabel):n})},[t,n])}function pt(e){let{sessions:t,sessionKey:n,sessionType:r}=e;return{recentSessionPreferredModel:(0,Y.useMemo)(()=>G({sessions:t,selectedSessionKey:n??``,sessionType:r,readPreference:e=>e.preferredModel?.trim()||void 0}),[n,r,t]),recentSessionPreferredThinking:(0,Y.useMemo)(()=>G({sessions:t,selectedSessionKey:n??``,sessionType:r,readPreference:e=>e.preferredThinking??void 0}),[n,r,t])}}function mt(e){let{currentSelectedModel:t,modelOptions:n}=e,r=(0,Y.useMemo)(()=>n.find(e=>e.value===t),[t,n]);return{supportedThinkingLevels:(0,Y.useMemo)(()=>r?.thinkingCapability?.supported??[],[r?.thinkingCapability?.supported]),defaultThinkingLevel:(0,Y.useMemo)(()=>r?.thinkingCapability?.default??null,[r?.thinkingCapability?.default])}}function ht(e){let{modelOptions:t,supportedModels:n}=e;if(!n||n.length===0)return t;let r=new Set(n),i=t.filter(e=>r.has(e.value));return i.length>0?i:t}function gt(e){let{currentSelectedModel:t,pendingSessionType:n,projectRootOverride:r,query:i,sessionKey:a,setPendingSessionType:o,setSelectedModel:s,setSelectedThinkingLevel:c}=e,l=N(),u=P(),d=ue({limit:200}),f=K(),p=le({sessionId:a?.trim()||`draft-session`,...Object.prototype.hasOwnProperty.call(e,`projectRootOverride`)?{projectRoot:r??null}:{}}),m=(l.isFetched||l.isSuccess)&&(u.isFetched||u.isSuccess),h=ft({config:l.data,meta:u.data}),g=(0,Y.useMemo)(()=>d.data?.sessions??[],[d.data?.sessions]),_=(0,Y.useMemo)(()=>Re(g),[g]),v=(0,Y.useMemo)(()=>dt(_,i),[_,i]),y=(0,Y.useMemo)(()=>_.find(e=>e.key===a)??null,[_,a]),b=(0,Y.useMemo)(()=>p.data?.records??[],[p.data?.records]),x=ye({selectedSession:y,pendingSessionType:n,setPendingSessionType:o,sessionTypesData:f.data}),S=(0,Y.useMemo)(()=>ht({modelOptions:h,supportedModels:x.selectedSessionTypeOption?.supportedModels}),[h,x.selectedSessionTypeOption?.supportedModels]),{recentSessionPreferredModel:C,recentSessionPreferredThinking:w}=pt({sessions:_,sessionKey:a,sessionType:x.selectedSessionType}),{supportedThinkingLevels:T,defaultThinkingLevel:E}=mt({currentSelectedModel:t,modelOptions:S});return Ue({modelOptions:S,selectedSessionKey:a??``,selectedSessionExists:!!y,selectedSessionPreferredModel:y?.preferredModel,fallbackPreferredModel:x.selectedSessionTypeOption?.recommendedModel??C,defaultModel:x.selectedSessionTypeOption?.recommendedModel??l.data?.agents.defaults.model,setSelectedModel:s}),Le({supportedThinkingLevels:T,selectedSessionKey:a??``,selectedSessionExists:!!y,selectedSessionPreferredThinking:y?.preferredThinking??null,fallbackPreferredThinking:w??null,defaultThinkingLevel:E,setSelectedThinkingLevel:c}),{configQuery:l,configMetaQuery:u,sessionsQuery:d,sessionTypesQuery:f,sessionSkillsQuery:p,isProviderStateResolved:m,modelOptions:S,sessionSummaries:g,sessions:v,skillRecords:b,selectedSession:y,...x}}function _t(e){return e.parentSessionKey?e.sessionSummaries.map(R).filter(t=>t.parentSessionId===e.parentSessionKey).sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt)).map(e=>({sessionKey:e.key,parentSessionKey:e.parentSessionId??null,label:e.label??null,agentId:e.agentId??null})):[]}function vt(e){let{availableAgents:t,parentSessionId:n,selectedAgentId:r,selectedSession:i,selectedSessionType:a,sessionKey:o,sessionSummaries:s,sessionTypeOptions:c}=e,l=i?V(i):void 0,u=i?.agentId??r,d=t.find(e=>e.id===u)??null,f=(0,Y.useMemo)(()=>{if(!n)return null;let e=s.find(e=>e.sessionId===n)??null;return e?R(e):null},[n,s]),p=c.find(e=>e.value===a)??null;return{currentSessionDisplayName:l,currentAgentId:u,currentAgent:d,parentSession:f,currentSessionTypeLabel:p?.label??B(a),currentSessionTypeIcon:p?.icon??null,currentChildSessionTabs:(0,Y.useMemo)(()=>_t({parentSessionKey:o,sessionSummaries:s}),[o,s])}}function yt(e){(0,Y.useEffect)(()=>{e.presenter.chatInputManager.syncSnapshot({isProviderStateResolved:e.isProviderStateResolved,defaultSessionType:e.defaultSessionType,canStopGeneration:e.canStopCurrentRun,stopDisabledReason:e.stopDisabledReason,stopSupported:!0,stopReason:void 0,sendError:e.lastSendError,isSending:e.isSending,modelOptions:e.modelOptions,sessionTypeOptions:e.sessionTypeOptions,selectedSessionType:e.selectedSessionType,canEditSessionType:e.canEditSessionType,sessionTypeUnavailable:e.sessionTypeUnavailable,skillRecords:e.skillRecords,isSkillsLoading:e.isSkillsLoading}),e.presenter.chatThreadManager.syncSnapshot({isProviderStateResolved:e.isProviderStateResolved,modelOptions:e.modelOptions,sessionTypeUnavailable:e.sessionTypeUnavailable,sessionTypeUnavailableMessage:e.sessionTypeUnavailableMessage,sessionTypeLabel:e.currentSessionTypeLabel,sessionTypeIcon:e.currentSessionTypeIcon,sessionKey:e.sessionKey??null,agentId:e.currentAgentId,agentDisplayName:e.currentAgent?.displayName??null,agentAvatarUrl:e.currentAgent?.avatarUrl??null,availableAgents:e.availableAgents,sessionDisplayName:e.currentSessionDisplayName,sessionProjectRoot:e.effectiveSessionProjectRoot,sessionProjectName:e.effectiveSessionProjectName,canDeleteSession:!!e.selectedSession,threadRef:e.threadRef,isHistoryLoading:e.agent.isHydrating,messages:e.agent.visibleMessages,isSending:e.isSending,isAwaitingAssistantOutput:e.isAwaitingAssistantOutput,contextWindow:ve(e.agent.snapshot.contextWindow),parentSessionKey:e.parentSession?.key??null,parentSessionLabel:e.parentSession?V(e.parentSession):null,childSessionTabs:e.childSessionTabs})},[e])}function bt(e){if(!Array.isArray(e))return[];let t=new Set;for(let n of e){let e=n.trim();e&&t.add(e)}return[...t]}function xt(e){let t={};e.model?.trim()&&(t.model=e.model.trim(),t.preferred_model=e.model.trim()),e.thinkingLevel?.trim()&&(t.thinking=e.thinkingLevel.trim(),t.preferred_thinking=e.thinkingLevel.trim()),e.sessionType?.trim()&&(t.session_type=e.sessionType.trim(),t.runtime=e.sessionType.trim()),e.agentId?.trim()&&(t.agent_id=e.agentId.trim());let n=De(e.projectRoot);n&&(t.project_root=n);let r=bt(e.requestedSkills);r.length>0&&(t.requested_skill_refs=r);let i=e.composerNodes?Ce(e.composerNodes):[];return i.length>0&&(t[be]=i),t}function St(e){let{pendingProjectRoot:t,pendingProjectRootSessionKey:n,sessionKey:r,selectedSessionProjectRoot:i}=e;return t!==null&&n!==null&&r===n&&(i??null)===t}function Ct(e){let t=J(e=>e.snapshot.query),n=J(e=>e.snapshot.selectedSessionKey),r=J(e=>e.snapshot.selectedAgentId),i=F(e=>e.snapshot.pendingSessionType),a=F(e=>e.snapshot.pendingProjectRoot),o=F(e=>e.snapshot.pendingProjectRootSessionKey),s=F(e=>e.snapshot.selectedModel),c=l(),u=Te(c),d=L(),{confirm:h,ConfirmDialog:g}=W(),_=f(),v=p(),{sessionId:y}=m(),b=(0,Y.useRef)(null),x=(0,Y.useRef)(n),S=(0,Y.useMemo)(()=>He(y),[y]),C=S??void 0,w=a!==null&&(!C||o===C),T=gt({query:t,sessionKey:C??null,projectRootOverride:w?a:void 0,currentSelectedModel:s,pendingSessionType:i,setPendingSessionType:e.chatInputManager.setPendingSessionType,setSelectedModel:e.chatInputManager.setSelectedModel,setSelectedThinkingLevel:e.chatInputManager.setSelectedThinkingLevel});return{presenter:e,selectedSessionKey:n,selectedAgentId:r,pendingProjectRoot:a,pendingProjectRootSessionKey:o,systemStatus:c,isRuntimeBlocked:u,agentsQuery:d,confirm:h,ConfirmDialog:g,location:_,navigate:v,threadRef:b,selectedSessionKeyRef:x,routeSessionKey:S,sessionKey:C,hasSessionProjectRootOverride:w,agent:Ge(C),...T}}function wt(e){let t=Ct(e),{agent:n,agentsQuery:r,hasSessionProjectRootOverride:i,pendingProjectRoot:a,isRuntimeBlocked:o,systemStatus:s,selectedAgentId:c,selectedSession:l,selectedSessionType:u,sessionKey:d,sessionSummaries:f,sessionTypeOptions:p}=t,m=i?a:l?.projectRoot??null,h=i?z(m):l?.projectName??z(m),g=n.hydrateError?.message??n.snapshot.error?.message??null,_=s.phase===`ready`&&Be(g)?null:g,v=(r.data?.agents?.length??0)>0?r.data?.agents??[]:[{id:l?.agentId??c}],y=vt({sessionKey:d??null,selectedSession:l,selectedAgentId:c,availableAgents:v,parentSessionId:l?.parentSessionId??null,sessionSummaries:f,selectedSessionType:u,sessionTypeOptions:p}),b=n.isRunning||l?.status===`running`;return{...t,availableAgents:v,effectiveSessionProjectRoot:m,effectiveSessionProjectName:h,isSending:n.isSending||b,isAwaitingAssistantOutput:b,canStopCurrentRun:b,stopDisabledReason:b?null:`__preparing__`,lastSendError:o?null:s.phase===`ready`?_:Oe({message:_,status:s}),...y}}function Tt(e){let{agent:t,pendingProjectRoot:n,pendingProjectRootSessionKey:r,presenter:i,selectedSession:a,selectedSessionKeyRef:o,sessionKey:s}=e;(0,Y.useEffect)(()=>{i.chatStreamActionsManager.bind({sendMessage:async e=>{if((e.sessionKey??null)!==(s??null))return;let o=xt({agentId:e.agentId,model:e.model,thinkingLevel:e.thinkingLevel,sessionType:e.sessionType,projectRoot:!e.sessionKey||e.sessionKey===r?n:a?.projectRoot??null,requestedSkills:e.requestedSkills,composerNodes:e.composerNodes}),c=je({sessionId:e.sessionKey,text:e.message,attachments:e.attachments,parts:e.parts,metadata:o});if(c)try{await t.send(c)}catch(t){throw e.restoreDraftOnError&&(e.composerNodes&&e.composerNodes.length>0?i.chatInputManager.restoreComposerState?.(e.composerNodes,e.attachments??[]):i.chatInputManager.setDraft(t=>t.trim().length===0?e.message:t)),t}},stopCurrentRun:async()=>{await t.abort()},resumeRun:async e=>{e.sessionKey===s&&await t.streamRun()},resetStreamState:()=>{o.current=null},applyHistoryMessages:()=>{}})},[t,n,r,i,a?.projectRoot,o,s])}function Et(e){let{pendingProjectRoot:t,pendingProjectRootSessionKey:n,selectedSession:r}=e;(0,Y.useEffect)(()=>{!r||!St({pendingProjectRoot:t,pendingProjectRootSessionKey:n,sessionKey:r.key,selectedSessionProjectRoot:r.projectRoot??null})||F.getState().setSnapshot({pendingProjectRoot:null,pendingProjectRootSessionKey:null})},[t,n,r])}function Dt(e){let{confirm:t,location:n,navigate:r,presenter:i}=e;(0,Y.useEffect)(()=>{i.chatUiManager.syncState({pathname:n.pathname}),i.chatUiManager.bindActions({navigate:r,confirm:t})},[t,n.pathname,r,i])}function Ot(e){let{presenter:t,selectedAgentId:n,selectedSession:r}=e;(0,Y.useEffect)(()=>{!r?.agentId||n===r.agentId||t.chatSessionListManager.setSelectedAgentId(r.agentId)},[t,n,r?.agentId])}function kt(e){let{agent:t,presenter:n,routeSessionKey:r}=e,i=t.snapshot.activeRun?.sessionId??t.visibleMessages.find(e=>e.sessionId.trim())?.sessionId??null;(0,Y.useEffect)(()=>{r||!i||n.chatSessionListManager.materializeRootSessionRoute(i)},[i,n,r])}function At({view:e}){let[t]=(0,Y.useState)(()=>new Ne),n=wt(t);return Tt(n),Et(n),Dt(n),Ot(n),kt(n),lt({view:e,routeSessionKey:n.routeSessionKey,selectedSessionKey:n.selectedSessionKey,setSelectedSessionKey:t.chatSessionListManager.setSelectedSessionKey,selectedSessionKeyRef:n.selectedSessionKeyRef,resetStreamState:t.chatStreamActionsManager.resetStreamState}),yt({presenter:t,isProviderStateResolved:n.isProviderStateResolved,defaultSessionType:n.defaultSessionType,canStopCurrentRun:n.canStopCurrentRun,stopDisabledReason:n.stopDisabledReason,lastSendError:n.lastSendError,isSending:n.isSending,modelOptions:n.modelOptions,sessionTypeOptions:n.sessionTypeOptions,selectedSessionType:n.selectedSessionType,canEditSessionType:n.canEditSessionType,sessionTypeUnavailable:n.sessionTypeUnavailable,skillRecords:n.skillRecords,isSkillsLoading:n.sessionSkillsQuery.isLoading,sessionTypeUnavailableMessage:n.sessionTypeUnavailableMessage,currentSessionTypeLabel:n.currentSessionTypeLabel,currentSessionTypeIcon:n.currentSessionTypeIcon,sessionKey:n.sessionKey,currentAgentId:n.currentAgentId,currentAgent:n.currentAgent,availableAgents:n.availableAgents,currentSessionDisplayName:n.currentSessionDisplayName,effectiveSessionProjectRoot:n.effectiveSessionProjectRoot,effectiveSessionProjectName:n.effectiveSessionProjectName,selectedSession:n.selectedSession,threadRef:n.threadRef,agent:n.agent,isAwaitingAssistantOutput:n.isAwaitingAssistantOutput,parentSession:n.parentSession,childSessionTabs:n.currentChildSessionTabs}),(0,X.jsx)(Se,{presenter:t,children:(0,X.jsx)(ut,{view:e,confirmDialog:(0,X.jsx)(n.ConfirmDialog,{})})})}function jt({view:e}){return(0,X.jsx)(At,{view:e})}export{jt as ChatPage};