@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.
- package/CHANGELOG.md +68 -0
- package/dist/assets/{channels-list-page-FJDuPwU6.js → channels-list-page-HgLgrEg4.js} +1 -1
- package/dist/assets/chat-page-DAKMFDrS.js +1 -0
- package/dist/assets/{desktop-kk7qvZ-v.js → desktop-DVUbOWbR.js} +1 -1
- package/dist/assets/{index-D-AAMKCt.js → index-Cuwst6cc.js} +34 -37
- package/dist/assets/index-dlcqieQ0.css +1 -0
- package/dist/assets/{marketplace-page-BrCLRIc4.js → marketplace-page-BeFbwxR-.js} +2 -2
- package/dist/assets/marketplace-page-CR4xq-TM.js +1 -0
- package/dist/assets/mcp-marketplace-page-DlRrSCj3.js +1 -0
- package/dist/assets/{mcp-marketplace-page-DIq_SpMe.js → mcp-marketplace-page-DwnaLNTx.js} +1 -1
- package/dist/assets/{model-config-Bc6VVnxy.js → model-config-L2l6YAlQ.js} +1 -1
- package/dist/assets/{providers-list-DN0tvISH.js → providers-list-DYAEunOp.js} +1 -1
- package/dist/assets/{runtime-config-page-CRWOwBbl.js → runtime-config-page-BdeU8PEK.js} +1 -1
- package/dist/assets/{search-config-C4c1yZSP.js → search-config-CQUhd5RU.js} +1 -1
- package/dist/assets/{secrets-config-zAF30YfO.js → secrets-config-D-NWlW9q.js} +1 -1
- package/dist/assets/{use-infinite-scroll-loader-Cvz8ZteY.js → use-infinite-scroll-loader-CFVdPpNv.js} +1 -1
- package/dist/index.html +3 -3
- package/package.json +9 -9
- package/src/features/agents/components/agents-page.test.tsx +1 -1
- package/src/features/agents/components/agents-page.tsx +1 -1
- package/src/features/chat/components/chat-session-workspace-panel.tsx +31 -45
- package/src/features/chat/components/chat-sidebar-session-item.tsx +7 -9
- package/src/features/chat/components/conversation/chat-conversation-header.test.tsx +5 -2
- package/src/features/chat/components/conversation/chat-conversation-header.tsx +2 -2
- package/src/features/chat/components/conversation/chat-conversation-panel.test.tsx +106 -78
- package/src/features/chat/components/conversation/chat-conversation-panel.tsx +172 -167
- package/src/features/chat/components/conversation/chat-input-bar.container.tsx +11 -1
- package/src/features/chat/components/conversation/session-header/chat-session-header-actions.tsx +2 -2
- package/src/features/chat/components/providers/chat-presenter.provider.tsx +2 -0
- package/src/features/chat/hooks/use-ncp-agent-runtime.test.tsx +147 -88
- package/src/features/chat/managers/ncp-chat-input.manager.test.ts +20 -0
- package/src/features/chat/managers/ncp-chat-input.manager.ts +18 -0
- package/src/features/chat/managers/ncp-chat-presenter.manager.ts +1 -0
- package/src/features/chat/pages/ncp-chat-page.tsx +4 -1
- package/src/features/chat/stores/chat-input.store.ts +3 -1
- package/src/features/chat/utils/ncp-chat-input-availability.utils.test.ts +1 -0
- package/src/platforms/desktop/components/desktop-app-shell.test.tsx +1 -0
- package/src/platforms/desktop/components/desktop-app-shell.tsx +1 -1
- package/dist/assets/chat-page-D1fMNBrT.js +0 -1
- package/dist/assets/index-DnBeV2Xm.css +0 -1
- package/dist/assets/marketplace-page-odDpPYEs.js +0 -1
- 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
|
-
|
|
35
|
-
|
|
36
|
-
this.
|
|
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 (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
117
|
+
{
|
|
118
|
+
type: NcpEventType.MessageTextDelta,
|
|
119
|
+
payload: {
|
|
120
|
+
sessionId: "session-existing",
|
|
121
|
+
messageId: "assistant-1",
|
|
122
|
+
delta: "done",
|
|
123
|
+
},
|
|
94
124
|
},
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
132
|
+
{
|
|
133
|
+
type: NcpEventType.RunFinished,
|
|
134
|
+
payload: {
|
|
135
|
+
sessionId: "session-existing",
|
|
136
|
+
runId: "run-1",
|
|
137
|
+
},
|
|
115
138
|
},
|
|
116
|
-
|
|
117
|
-
});
|
|
139
|
+
];
|
|
118
140
|
|
|
119
|
-
|
|
120
|
-
|
|
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("
|
|
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
|
|
154
|
-
act(() => {
|
|
155
|
-
|
|
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
|
-
|
|
159
|
-
|
|
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
|
-
|
|
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);
|
|
@@ -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) => ({
|
|
@@ -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": "
|
|
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};
|