@blade-hq/agent-kit 0.4.5 → 0.4.7

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 (52) hide show
  1. package/README.md +39 -1
  2. package/dist/{SkillStatusBar-DItrW2vv.d.ts → SkillStatusBar-DQyipdzn.d.ts} +112 -8
  3. package/dist/chunk-2UP7MG3J.js +66 -0
  4. package/dist/chunk-2UP7MG3J.js.map +1 -0
  5. package/dist/chunk-4VWLTG5L.js +2984 -0
  6. package/dist/chunk-4VWLTG5L.js.map +1 -0
  7. package/dist/chunk-7LEKQI47.js +32 -0
  8. package/dist/chunk-7LEKQI47.js.map +1 -0
  9. package/dist/chunk-CGOQI7ZL.js +8124 -0
  10. package/dist/chunk-CGOQI7ZL.js.map +1 -0
  11. package/dist/chunk-DQCXSPHP.js +33 -0
  12. package/dist/chunk-DQCXSPHP.js.map +1 -0
  13. package/dist/chunk-I3FFV63W.js +30 -0
  14. package/dist/chunk-I3FFV63W.js.map +1 -0
  15. package/dist/chunk-J3XVFPOV.js +58 -0
  16. package/dist/chunk-J3XVFPOV.js.map +1 -0
  17. package/dist/chunk-JCJFFJ42.js +39 -0
  18. package/dist/chunk-JCJFFJ42.js.map +1 -0
  19. package/dist/chunk-OKQWPNE3.js +1077 -0
  20. package/dist/chunk-OKQWPNE3.js.map +1 -0
  21. package/dist/chunk-PZ5AY32C.js +10 -0
  22. package/dist/chunk-PZ5AY32C.js.map +1 -0
  23. package/dist/chunk-TC5BBLWO.js +29 -0
  24. package/dist/chunk-TC5BBLWO.js.map +1 -0
  25. package/dist/chunk-VD4CKRMT.js +127 -0
  26. package/dist/chunk-VD4CKRMT.js.map +1 -0
  27. package/dist/chunk-X6MEYCU7.js +1401 -0
  28. package/dist/chunk-X6MEYCU7.js.map +1 -0
  29. package/dist/client/index.js +24 -1052
  30. package/dist/client/index.js.map +1 -1
  31. package/dist/react/api/licenses.js +11 -1470
  32. package/dist/react/api/licenses.js.map +1 -1
  33. package/dist/react/api/vibe-coding.js +25 -1481
  34. package/dist/react/api/vibe-coding.js.map +1 -1
  35. package/dist/react/cards/register.js +45 -138
  36. package/dist/react/cards/register.js.map +1 -1
  37. package/dist/react/components/chat/index.d.ts +7 -21
  38. package/dist/react/components/chat/index.js +28 -11366
  39. package/dist/react/components/chat/index.js.map +1 -1
  40. package/dist/react/components/plan/index.js +135 -3054
  41. package/dist/react/components/plan/index.js.map +1 -1
  42. package/dist/react/components/session/index.js +21 -1499
  43. package/dist/react/components/session/index.js.map +1 -1
  44. package/dist/react/components/workspace/index.js +116 -1715
  45. package/dist/react/components/workspace/index.js.map +1 -1
  46. package/dist/react/devtools/bridge-devtools/index.js +8 -51
  47. package/dist/react/devtools/bridge-devtools/index.js.map +1 -1
  48. package/dist/react/index.d.ts +2 -2
  49. package/dist/react/index.js +625 -14035
  50. package/dist/react/index.js.map +1 -1
  51. package/dist/style.css +1 -1
  52. package/package.json +1 -1
@@ -1,1521 +1,36 @@
1
+ import {
2
+ Collapsible,
3
+ CollapsibleContent,
4
+ CollapsibleTrigger,
5
+ resolveSessionFilePreviewTarget
6
+ } from "../../../chunk-VD4CKRMT.js";
7
+ import {
8
+ apiFetchText,
9
+ copyFile,
10
+ deleteFile,
11
+ getAuthedUrl,
12
+ getDownloadDirUrl,
13
+ isUiMeta,
14
+ listDir,
15
+ renameFile,
16
+ uploadFiles,
17
+ useChatStore,
18
+ useSessionStore,
19
+ useUiStore
20
+ } from "../../../chunk-4VWLTG5L.js";
21
+ import "../../../chunk-J3XVFPOV.js";
22
+ import "../../../chunk-OKQWPNE3.js";
23
+ import {
24
+ cn
25
+ } from "../../../chunk-7LEKQI47.js";
26
+ import "../../../chunk-JCJFFJ42.js";
27
+ import "../../../chunk-PZ5AY32C.js";
28
+
1
29
  // src/react/components/workspace/WorkspaceFilesPanel.tsx
2
30
  import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
3
31
  import { FileText, FolderTree, FolderUp, Loader2 as Loader22, PanelRightOpen, RefreshCw, Upload } from "lucide-react";
4
32
  import { useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
5
33
 
6
- // src/client/resources/models.ts
7
- import { type } from "arktype";
8
- var ModelOption = type({
9
- id: "string",
10
- label: "string"
11
- });
12
- var ModelsConfig = type({
13
- default: "string",
14
- models: ModelOption.array()
15
- });
16
-
17
- // src/client/socket.ts
18
- import { io } from "socket.io-client";
19
-
20
- // src/react/schemas/partner-skill.ts
21
- import { type as type2 } from "arktype";
22
- var PartnerSkillName = type2("/^[a-z0-9-]+\\/[a-z0-9-]+$/");
23
- var PartnerSkillFile = type2({
24
- path: "string > 0",
25
- content: "string"
26
- });
27
- var PartnerSkillInstallPayload = type2({
28
- name: PartnerSkillName,
29
- files: PartnerSkillFile.array().atLeastLength(1)
30
- });
31
- var PartnerSkillInstallResult = type2({
32
- name: PartnerSkillName,
33
- skill_dir: "string",
34
- file_count: "number.integer >= 0",
35
- overwritten: "boolean"
36
- });
37
-
38
- // src/react/stores/ui-bridge-store.ts
39
- import { create } from "zustand";
40
-
41
- // src/react/stores/client-aware.ts
42
- function createClientActions(set) {
43
- return {
44
- _client: null,
45
- setClient: (client) => set({ _client: client })
46
- };
47
- }
48
-
49
- // src/react/stores/ui-bridge-store.ts
50
- function buildSignalId() {
51
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
52
- return crypto.randomUUID();
53
- }
54
- return `bridge-${Date.now()}-${Math.random().toString(36).slice(2)}`;
55
- }
56
- function clearSignalRecord(record, sessionId) {
57
- if (!(sessionId in record)) {
58
- return record;
59
- }
60
- const next = { ...record };
61
- delete next[sessionId];
62
- return next;
63
- }
64
- var useUiBridgeStore = create()((set, get) => ({
65
- ...createClientActions(set),
66
- pendingContexts: {},
67
- draftAppends: {},
68
- sendRequests: {},
69
- addPendingContext: (sessionId, context) => set((state) => ({
70
- pendingContexts: {
71
- ...state.pendingContexts,
72
- [sessionId]: [
73
- ...state.pendingContexts[sessionId] ?? [],
74
- {
75
- id: buildSignalId(),
76
- label: context.label,
77
- content: context.content
78
- }
79
- ]
80
- }
81
- })),
82
- removePendingContext: (sessionId, contextId) => set((state) => {
83
- const contexts = state.pendingContexts[sessionId];
84
- if (!contexts?.length) {
85
- return state;
86
- }
87
- const nextContexts = contexts.filter((context) => context.id !== contextId);
88
- if (nextContexts.length === contexts.length) {
89
- return state;
90
- }
91
- return {
92
- pendingContexts: nextContexts.length > 0 ? {
93
- ...state.pendingContexts,
94
- [sessionId]: nextContexts
95
- } : clearSignalRecord(state.pendingContexts, sessionId)
96
- };
97
- }),
98
- consumePendingContexts: (sessionId) => {
99
- const signals = get().pendingContexts[sessionId] ?? [];
100
- if (signals.length === 0) return [];
101
- set((state) => ({
102
- pendingContexts: clearSignalRecord(state.pendingContexts, sessionId)
103
- }));
104
- return signals;
105
- },
106
- clearPendingContexts: (sessionId) => set((state) => ({
107
- pendingContexts: clearSignalRecord(state.pendingContexts, sessionId)
108
- })),
109
- addDraftAppend: (sessionId, text) => set((state) => ({
110
- draftAppends: {
111
- ...state.draftAppends,
112
- [sessionId]: [
113
- ...state.draftAppends[sessionId] ?? [],
114
- {
115
- id: buildSignalId(),
116
- text
117
- }
118
- ]
119
- }
120
- })),
121
- consumeDraftAppends: (sessionId) => {
122
- const signals = get().draftAppends[sessionId] ?? [];
123
- if (signals.length === 0) return [];
124
- set((state) => ({
125
- draftAppends: clearSignalRecord(state.draftAppends, sessionId)
126
- }));
127
- return signals;
128
- },
129
- clearDraftAppends: (sessionId) => set((state) => ({
130
- draftAppends: clearSignalRecord(state.draftAppends, sessionId)
131
- })),
132
- addSendRequest: (sessionId) => set((state) => ({
133
- sendRequests: {
134
- ...state.sendRequests,
135
- [sessionId]: [
136
- ...state.sendRequests[sessionId] ?? [],
137
- {
138
- id: buildSignalId()
139
- }
140
- ]
141
- }
142
- })),
143
- consumeSendRequests: (sessionId) => {
144
- const signals = get().sendRequests[sessionId] ?? [];
145
- if (signals.length === 0) return [];
146
- set((state) => ({
147
- sendRequests: clearSignalRecord(state.sendRequests, sessionId)
148
- }));
149
- return signals;
150
- },
151
- clearSendRequests: (sessionId) => set((state) => ({
152
- sendRequests: clearSignalRecord(state.sendRequests, sessionId)
153
- })),
154
- clearSession: (sessionId) => set((state) => ({
155
- pendingContexts: clearSignalRecord(state.pendingContexts, sessionId),
156
- draftAppends: clearSignalRecord(state.draftAppends, sessionId),
157
- sendRequests: clearSignalRecord(state.sendRequests, sessionId)
158
- }))
159
- }));
160
-
161
- // src/react/lib/chat.ts
162
- function normalizeMessageContent(content) {
163
- if (typeof content === "string") return content;
164
- if (Array.isArray(content)) return content;
165
- return String(content ?? "");
166
- }
167
-
168
- // src/react/lib/ui-meta.ts
169
- function isNonEmptyString(value) {
170
- return typeof value === "string" && value.trim().length > 0;
171
- }
172
- function isPositiveNumber(value) {
173
- return typeof value === "number" && Number.isFinite(value) && value > 0;
174
- }
175
- function isUiMeta(value) {
176
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
177
- return false;
178
- }
179
- const raw = value;
180
- if (raw.target !== "inline" && raw.target !== "preview") {
181
- return false;
182
- }
183
- if (!isPositiveNumber(raw.height)) {
184
- return false;
185
- }
186
- if (!isNonEmptyString(raw.resourceHTML) && !isNonEmptyString(raw.resourceUri) && !isNonEmptyString(raw.resourceURI)) {
187
- return false;
188
- }
189
- if (raw.title != null && !isNonEmptyString(raw.title)) {
190
- return false;
191
- }
192
- return true;
193
- }
194
-
195
- // src/react/stores/auth-store.ts
196
- import { create as create6 } from "zustand";
197
- import { createJSONStorage, persist } from "zustand/middleware";
198
-
199
- // src/react/api/auth.ts
200
- var r = () => getClient().auth;
201
- var getMe = (...args) => r().getMe(...args);
202
- var logout = (...args) => r().logout(...args);
203
-
204
- // src/react/sockets/socket-state.ts
205
- var agentSocket = null;
206
-
207
- // src/react/stores/session-store.ts
208
- import { create as create5 } from "zustand";
209
-
210
- // src/react/stores/chat-store.ts
211
- import { create as create3 } from "zustand";
212
-
213
- // src/react/components/chat/display-utils.ts
214
- var TOOL_NAME_ALIASES = {
215
- agent: "Agent",
216
- ask_user_question: "AskUserQuestion",
217
- bash: "Bash",
218
- bg_bash: "BgBash",
219
- edit: "Edit",
220
- exit_plan_mode: "ExitPlanMode",
221
- file_edit: "Edit",
222
- file_read: "Read",
223
- file_write: "Write",
224
- finish_task: "FinishTask",
225
- get_skill_content: "GetSkillContent",
226
- glob: "Glob",
227
- grep: "Grep",
228
- list_skill_tools: "ListSkillTools",
229
- load_skill_tools: "LoadSkillTools",
230
- ls: "Ls",
231
- read: "Read",
232
- run_skill_tool: "RunSkillTool",
233
- search_skills: "SearchSkills",
234
- web_fetch: "WebFetch",
235
- web_search: "WebSearch",
236
- write: "Write"
237
- };
238
- var TOOL_DISPLAY_LABELS = {
239
- Bash: "\u6267\u884C\u547D\u4EE4",
240
- BgBash: "\u540E\u53F0\u6267\u884C\u547D\u4EE4",
241
- Read: "\u8BFB\u53D6\u6587\u4EF6",
242
- Write: "\u5199\u5165\u6587\u4EF6",
243
- Edit: "\u7F16\u8F91\u6587\u4EF6",
244
- Ls: "\u5217\u51FA\u76EE\u5F55",
245
- Glob: "\u5339\u914D\u6587\u4EF6",
246
- Grep: "\u641C\u7D22\u6587\u672C",
247
- WebSearch: "\u641C\u7D22\u7F51\u9875",
248
- WebFetch: "\u6574\u7406\u7F51\u9875\u5185\u5BB9",
249
- Agent: "\u6D3E\u751F\u5B50\u667A\u80FD\u4F53",
250
- AskUserQuestion: "\u5411\u7528\u6237\u63D0\u95EE",
251
- SearchSkills: "\u641C\u7D22\u6280\u80FD",
252
- GetSkillContent: "\u8BFB\u53D6\u6280\u80FD",
253
- ListSkillTools: "\u67E5\u770B\u5DE5\u5177\u5217\u8868",
254
- LoadSkillTools: "\u52A0\u8F7D\u6280\u80FD",
255
- RunSkillTool: "\u6267\u884C\u6280\u80FD\u5DE5\u5177",
256
- FinishTask: "\u4EFB\u52A1\u5B8C\u6210",
257
- ExitPlanMode: "\u63D0\u4EA4\u8BA1\u5212",
258
- ListSessions: "\u5217\u51FA\u5386\u53F2\u4F1A\u8BDD",
259
- GetSessionHistory: "\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2"
260
- };
261
- var GENERIC_DISPLAY_NAMES = new Set(Object.values(TOOL_DISPLAY_LABELS));
262
- function formatToolName(name) {
263
- const trimmed = name.trim();
264
- if (!trimmed) return name;
265
- const stripped = trimmed.split(":").pop()?.split("/").pop()?.split(".").pop()?.trim() || trimmed;
266
- const normalized = stripped.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
267
- return TOOL_NAME_ALIASES[normalized] ?? stripped;
268
- }
269
-
270
- // src/react/stores/ui-store.ts
271
- import { create as create2 } from "zustand";
272
- var isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
273
- function resolveEffectiveTheme(theme) {
274
- if (theme !== "system") return theme;
275
- return isBrowser && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
276
- }
277
- function applyTheme(theme) {
278
- if (!isBrowser) return;
279
- const effective = resolveEffectiveTheme(theme);
280
- document.documentElement.setAttribute("data-theme", effective);
281
- }
282
- var storedTheme = isBrowser ? localStorage.getItem("blade-theme") ?? "light" : "light";
283
- applyTheme(storedTheme);
284
- if (isBrowser) {
285
- window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
286
- const current = useUiStore?.getState?.()?.theme;
287
- if (current === "system") applyTheme("system");
288
- });
289
- }
290
- function removeArtifactAtIndex(state, index) {
291
- const next = state.artifacts.filter((_, i) => i !== index);
292
- let nextActive = state.activeArtifactIndex;
293
- if (next.length === 0) {
294
- return { artifacts: [], activeArtifactIndex: -1, rightPanelCollapsed: true };
295
- }
296
- if (index < nextActive) {
297
- nextActive -= 1;
298
- } else if (index === nextActive) {
299
- nextActive = Math.min(index, next.length - 1);
300
- }
301
- return { artifacts: next, activeArtifactIndex: nextActive };
302
- }
303
- function upsertArtifactState(state, target, options) {
304
- const reveal = options?.reveal ?? true;
305
- const activate = options?.activate ?? true;
306
- const targetKey = target.key ?? target.title;
307
- const applyUiState = (partial) => ({
308
- ...partial,
309
- ...reveal ? { rightPanelCollapsed: false, activeRightTab: "preview" } : {}
310
- });
311
- const existing = state.artifacts.findIndex((artifact) => targetKey && (artifact.key ?? artifact.title) === targetKey);
312
- if (existing >= 0) {
313
- const updated = [...state.artifacts];
314
- updated[existing] = target;
315
- return applyUiState({
316
- artifacts: updated,
317
- activeArtifactIndex: activate ? existing : state.activeArtifactIndex
318
- });
319
- }
320
- const next = [...state.artifacts, target];
321
- return applyUiState({
322
- artifacts: next,
323
- activeArtifactIndex: activate ? next.length - 1 : state.activeArtifactIndex >= 0 ? state.activeArtifactIndex : 0
324
- });
325
- }
326
- var useUiStore = create2()((set) => ({
327
- ...createClientActions(set),
328
- leftPanelSize: 20,
329
- rightPanelSize: 25,
330
- leftPanelCollapsed: false,
331
- rightPanelCollapsed: false,
332
- activeRightTab: "situation",
333
- artifacts: [],
334
- activeArtifactIndex: -1,
335
- theme: storedTheme,
336
- setLeftPanelSize: (size) => set({ leftPanelSize: size }),
337
- setRightPanelSize: (size) => set({ rightPanelSize: size }),
338
- setLeftPanelCollapsed: (collapsed) => set({ leftPanelCollapsed: collapsed }),
339
- setRightPanelCollapsed: (collapsed) => set({ rightPanelCollapsed: collapsed }),
340
- toggleLeftPanel: () => set((s) => ({ leftPanelCollapsed: !s.leftPanelCollapsed })),
341
- toggleRightPanel: () => set((s) => ({ rightPanelCollapsed: !s.rightPanelCollapsed })),
342
- setActiveRightTab: (tab) => set({ activeRightTab: tab }),
343
- pushArtifact: (target) => set((state) => upsertArtifactState(state, target)),
344
- upsertArtifact: (target, options) => set((state) => upsertArtifactState(state, target, options)),
345
- setActiveArtifact: (index) => set({ activeArtifactIndex: index }),
346
- closeArtifact: (index) => set((state) => removeArtifactAtIndex(state, index)),
347
- removeArtifactByKey: (key) => set((state) => {
348
- const index = state.artifacts.findIndex((artifact) => (artifact.key ?? artifact.title) === key);
349
- if (index < 0) return state;
350
- return removeArtifactAtIndex(state, index);
351
- }),
352
- clearArtifacts: () => set({ artifacts: [], activeArtifactIndex: -1 }),
353
- setPreviewTarget: (target) => set(() => {
354
- if (target === null) {
355
- return { artifacts: [], activeArtifactIndex: -1 };
356
- }
357
- return {
358
- artifacts: [target],
359
- activeArtifactIndex: 0,
360
- rightPanelCollapsed: false,
361
- activeRightTab: "preview"
362
- };
363
- }),
364
- setTheme: (theme) => {
365
- localStorage.setItem("blade-theme", theme);
366
- applyTheme(theme);
367
- set({ theme });
368
- }
369
- }));
370
-
371
- // src/react/stores/chat-store.ts
372
- var _getActiveSessionId = null;
373
- function setChatStoreSessionAccessor(fn) {
374
- _getActiveSessionId = fn;
375
- }
376
- function parseAgentDescription(argumentsJson) {
377
- try {
378
- return JSON.parse(argumentsJson)?.description ?? "\u5B50\u667A\u80FD\u4F53";
379
- } catch {
380
- return "\u5B50\u667A\u80FD\u4F53";
381
- }
382
- }
383
- function inferLoopStatusFromMessages(messages) {
384
- const toolCalls = messages.flatMap((message) => message.tool_calls ?? []);
385
- if (messages.some((message) => message.status === "streaming")) return "running";
386
- if (toolCalls.some((toolCall) => toolCall.status === "awaiting_answer")) return "awaiting_answer";
387
- if (toolCalls.some((toolCall) => toolCall.status === "error")) return "error";
388
- if (toolCalls.some((toolCall) => toolCall.status === "cancelled")) return "cancelled";
389
- if (toolCalls.some((toolCall) => toolCall.status === "pending")) return "running";
390
- return "done";
391
- }
392
- function inferLoopStatusFromTurns(turns, messages) {
393
- const latestAgentNotification = [...turns].reverse().flatMap((turn) => turn.blocks).find((block) => {
394
- if (block.type !== "system_notification" || !isRecord(block.content)) return false;
395
- return block.content.notification_type === "agent:start" || block.content.notification_type === "agent:end";
396
- });
397
- if (latestAgentNotification?.type === "system_notification" && isRecord(latestAgentNotification.content)) {
398
- const notificationType = latestAgentNotification.content.notification_type;
399
- const status = latestAgentNotification.content.status;
400
- if (notificationType === "agent:start" || status === "running") return "running";
401
- if (status === "error") return "error";
402
- if (status === "cancelled") return "cancelled";
403
- }
404
- return inferLoopStatusFromMessages(messages);
405
- }
406
- function isRecord(value) {
407
- return typeof value === "object" && value !== null && !Array.isArray(value);
408
- }
409
- function parentForkToolCallIdFromTurn(turn) {
410
- if (typeof turn.parent_fork_tool_call_id === "string" && turn.parent_fork_tool_call_id.length > 0) {
411
- return turn.parent_fork_tool_call_id;
412
- }
413
- for (const block of turn.blocks) {
414
- if (block.type !== "system_notification" || !isRecord(block.content)) continue;
415
- const metadata = block.content.metadata;
416
- if (!isRecord(metadata)) continue;
417
- const parentId = metadata.parent_fork_tool_call_id;
418
- if (typeof parentId === "string" && parentId.length > 0) return parentId;
419
- }
420
- return null;
421
- }
422
- function buildMessageContent(turn) {
423
- const textBlocks = turn.blocks.filter((block) => block.type === "text");
424
- if (textBlocks.length === 0) return "";
425
- if (textBlocks.length === 1) return normalizeMessageContent(textBlocks[0].content);
426
- return textBlocks.map((block) => {
427
- if (typeof block.content === "string") return block.content;
428
- return JSON.stringify(block.content);
429
- }).join("");
430
- }
431
- function buildReasoning(turn) {
432
- const thinking = turn.blocks.filter((block) => block.type === "thinking").map((block) => typeof block.content === "string" ? block.content : JSON.stringify(block.content)).filter(Boolean);
433
- if (thinking.length === 0) return void 0;
434
- return thinking.join("\n\n");
435
- }
436
- function isModeChangeContent(value) {
437
- return typeof value === "object" && value !== null && typeof value.from === "string" && typeof value.to === "string";
438
- }
439
- function extractModeFromBlocks(blocks) {
440
- const modeBlock = blocks.find((block) => block.type === "mode_change");
441
- if (modeBlock && isModeChangeContent(modeBlock.content)) {
442
- return modeBlock.content.to === "planning" || modeBlock.content.to === "executing" ? modeBlock.content.to : null;
443
- }
444
- if (blocks.some((block) => block.type === "planning_enter")) return "planning";
445
- if (blocks.some((block) => block.type === "planning_exit")) return "executing";
446
- return null;
447
- }
448
- function projectionToMessage(turn) {
449
- if (turn.kind === "compaction" && turn.compaction_id) {
450
- return {
451
- role: "assistant",
452
- content: turn.summary_preview ?? "",
453
- kind: "compaction",
454
- loop_name: turn.loop_id,
455
- entry_id: turn.turn_id,
456
- status: turn.status,
457
- compaction: {
458
- compaction_id: turn.compaction_id,
459
- summary_preview: turn.summary_preview,
460
- summary_full: turn.summary_full,
461
- archived_count: turn.archived_count,
462
- archived_files: turn.archived_files,
463
- archived_tool_calls: turn.archived_tool_calls,
464
- tokens_before: turn.tokens_before,
465
- tokens_after: turn.tokens_after,
466
- saved_ratio: turn.saved_ratio,
467
- trigger: turn.trigger,
468
- failure_reason: turn.failure_reason,
469
- fallback_applied: turn.fallback_applied
470
- }
471
- };
472
- }
473
- const planningBlock = turn.blocks.find(
474
- (block) => block.type === "mode_change" || block.type === "planning_enter" || block.type === "planning_exit" || block.type === "plan_status"
475
- );
476
- if (planningBlock) {
477
- if (planningBlock.type === "plan_status") {
478
- return {
479
- role: "tool",
480
- content: typeof planningBlock.content === "string" ? planningBlock.content : JSON.stringify(planningBlock.content ?? {}, null, 2),
481
- kind: "plan_status",
482
- loop_name: turn.loop_id,
483
- entry_id: turn.turn_id,
484
- status: turn.status
485
- };
486
- }
487
- return {
488
- role: "assistant",
489
- content: planningBlock.type === "mode_change" ? typeof planningBlock.content === "string" ? planningBlock.content : JSON.stringify(planningBlock.content ?? {}) : "",
490
- kind: planningBlock.type,
491
- loop_name: turn.loop_id,
492
- entry_id: turn.turn_id,
493
- status: turn.status
494
- };
495
- }
496
- if (turn.blocks.some((block) => block.type === "ask_user_answer")) {
497
- return null;
498
- }
499
- const content = buildMessageContent(turn);
500
- const reasoning = buildReasoning(turn);
501
- const toolCalls = turn.tool_calls.length > 0 ? turn.tool_calls.map((toolCall) => ({
502
- id: toolCall.id,
503
- name: toolCall.tool_name,
504
- display_name: toolCall.display_name,
505
- arguments: toolCall.arguments,
506
- result: toolCall.result ?? void 0,
507
- pending_question_ref: toolCall.pending_question_ref ?? void 0,
508
- status: toolCall.status === "pending" || toolCall.status === "awaiting_answer" || toolCall.status === "done" || toolCall.status === "error" || toolCall.status === "cancelled" ? toolCall.status : "pending",
509
- ...typeof toolCall.duration_ms === "number" ? { duration_ms: toolCall.duration_ms } : {}
510
- })) : void 0;
511
- if (turn.role === "system" && !content && !toolCalls?.length) {
512
- return null;
513
- }
514
- return {
515
- role: turn.role === "system" ? "assistant" : turn.role,
516
- content,
517
- blocks: turn.blocks,
518
- ...reasoning ? { reasoning } : {},
519
- ...toolCalls ? { tool_calls: toolCalls } : {},
520
- loop_name: turn.loop_id,
521
- entry_id: turn.turn_id,
522
- status: turn.status,
523
- ...typeof turn.duration_ms === "number" ? { duration_ms: turn.duration_ms } : {},
524
- ...turn.started_at ? { timestamp: turn.started_at } : {},
525
- ...turn.memory_refs?.length ? { memory_refs: turn.memory_refs } : {}
526
- };
527
- }
528
- function rebuildAgentLoops(turns) {
529
- const messages = turns.map(projectionToMessage).filter(Boolean);
530
- const childLoopNames = [...new Set(turns.map((turn) => turn.loop_id).filter((name) => name !== "root"))];
531
- if (childLoopNames.length === 0) return {};
532
- const agentToolCalls = messages.filter((message) => message.role === "assistant" && (message.loop_name ?? "root") === "root").flatMap((message) => message.tool_calls ?? []).filter((toolCall) => formatToolName(toolCall.name) === "Agent");
533
- const loops = {};
534
- const agentToolCallsById = new Map(agentToolCalls.map((toolCall) => [toolCall.id, toolCall]));
535
- const explicitParentToolCallIds = new Set(
536
- turns.map(parentForkToolCallIdFromTurn).filter((id) => id !== null)
537
- );
538
- const usedToolCallIds = /* @__PURE__ */ new Set();
539
- for (const loopName of childLoopNames) {
540
- const loopMessages = messages.filter((message) => (message.loop_name ?? "root") === loopName);
541
- const loopTurns = turns.filter((turn) => turn.loop_id === loopName);
542
- const parentToolCallId = loopTurns.map(parentForkToolCallIdFromTurn).find(Boolean);
543
- const explicitToolCall = parentToolCallId && !usedToolCallIds.has(parentToolCallId) ? agentToolCallsById.get(parentToolCallId) ?? null : null;
544
- const fallbackToolCall = explicitToolCall === null ? agentToolCalls.find(
545
- (toolCall2) => !usedToolCallIds.has(toolCall2.id) && !explicitParentToolCallIds.has(toolCall2.id)
546
- ) : null;
547
- const toolCall = explicitToolCall ?? fallbackToolCall;
548
- if (!toolCall) continue;
549
- usedToolCallIds.add(toolCall.id);
550
- loops[loopName] = {
551
- toolCallId: toolCall.id,
552
- description: parseAgentDescription(toolCall.arguments),
553
- status: inferLoopStatusFromTurns(loopTurns, loopMessages)
554
- };
555
- }
556
- return loops;
557
- }
558
- function applyPlanningSideEffects(sessionId, turns) {
559
- const latestMode = [...turns].reverse().map((turn) => extractModeFromBlocks(turn.blocks)).find((mode) => mode !== null);
560
- if (latestMode !== "planning") return;
561
- if (_getActiveSessionId?.() !== sessionId) return;
562
- const ui = useUiStore.getState();
563
- ui.setActiveRightTab("situation");
564
- if (ui.rightPanelCollapsed) {
565
- ui.toggleRightPanel();
566
- }
567
- }
568
- function materialize(turns) {
569
- const messages = turns.map(projectionToMessage).filter((message) => message !== null);
570
- const activeCompaction = [...turns].reverse().find(
571
- (turn) => turn.kind === "compaction" && turn.status === "streaming" && typeof turn.compaction_id === "string"
572
- );
573
- return {
574
- messages,
575
- agentLoops: rebuildAgentLoops(turns),
576
- activeCompaction: activeCompaction ? {
577
- turn_id: activeCompaction.turn_id,
578
- status: activeCompaction.status,
579
- compaction_id: activeCompaction.compaction_id,
580
- summary_preview: activeCompaction.summary_preview,
581
- summary_full: activeCompaction.summary_full,
582
- archived_count: activeCompaction.archived_count,
583
- archived_files: activeCompaction.archived_files,
584
- archived_tool_calls: activeCompaction.archived_tool_calls,
585
- tokens_before: activeCompaction.tokens_before,
586
- tokens_after: activeCompaction.tokens_after,
587
- saved_ratio: activeCompaction.saved_ratio,
588
- trigger: activeCompaction.trigger,
589
- failure_reason: activeCompaction.failure_reason,
590
- fallback_applied: activeCompaction.fallback_applied
591
- } : null
592
- };
593
- }
594
- var ERROR_ANCHOR_PREFIX = "error-anchor:";
595
- function updateSessionState(state, sessionId, turns) {
596
- const orderedTurns = [...turns].sort((left, right) => left.sequence - right.sequence);
597
- const { messages, agentLoops, activeCompaction } = materialize(orderedTurns);
598
- applyPlanningSideEffects(sessionId, orderedTurns);
599
- const lastTurnId = orderedTurns[orderedTurns.length - 1]?.turn_id ?? null;
600
- const preservedErrors = lastTurnId ? (state.messages[sessionId] ?? []).filter(
601
- (m) => m.role === "error" && typeof m.entry_id === "string" && m.entry_id.startsWith(`${ERROR_ANCHOR_PREFIX}${lastTurnId}:`)
602
- ) : [];
603
- const mergedMessages = preservedErrors.length > 0 ? [...messages, ...preservedErrors] : messages;
604
- return {
605
- turns: { ...state.turns, [sessionId]: orderedTurns },
606
- messages: { ...state.messages, [sessionId]: mergedMessages },
607
- agentLoops: { ...state.agentLoops, [sessionId]: agentLoops },
608
- activeCompactions: { ...state.activeCompactions, [sessionId]: activeCompaction }
609
- };
610
- }
611
- var useChatStore = create3()((set) => ({
612
- ...createClientActions(set),
613
- turns: {},
614
- messages: {},
615
- askAnswers: {},
616
- isStreaming: {},
617
- agentLoops: {},
618
- activeCompactions: {},
619
- addUserMessage: (sessionId, content) => {
620
- set((state) => {
621
- const existing = state.turns[sessionId] ?? [];
622
- const turnId = `local-user-${Date.now()}`;
623
- const optimisticTurn = {
624
- id: turnId,
625
- sequence: Math.max(0, ...existing.map((turn) => turn.sequence)) + 1,
626
- turn_id: turnId,
627
- loop_id: "root",
628
- role: "user",
629
- status: "completed",
630
- blocks: [{ type: "text", content }],
631
- tool_calls: [],
632
- model: null,
633
- usage: null,
634
- duration_ms: 0
635
- };
636
- return updateSessionState(state, sessionId, [...existing, optimisticTurn]);
637
- });
638
- },
639
- setTurns: (sessionId, turns) => {
640
- set((state) => updateSessionState(state, sessionId, [...turns]));
641
- },
642
- upsertTurn: (sessionId, turn) => {
643
- set((state) => {
644
- const existing = [...state.turns[sessionId] ?? []];
645
- const index = existing.findIndex((item) => item.turn_id === turn.turn_id);
646
- if (index >= 0) {
647
- existing[index] = turn;
648
- } else {
649
- existing.push(turn);
650
- }
651
- return {
652
- ...updateSessionState(state, sessionId, existing)
653
- };
654
- });
655
- },
656
- applyTurnPatch: (sessionId, patch) => {
657
- set((state) => {
658
- const turn = patch.data.turn;
659
- if (!turn) return state;
660
- const existing = [...state.turns[sessionId] ?? []];
661
- const index = existing.findIndex((item) => item.turn_id === turn.turn_id);
662
- const lastSequence = index >= 0 ? existing[index].sequence : null;
663
- if (lastSequence !== null && patch.sequence <= lastSequence) {
664
- return state;
665
- }
666
- const nextTurn = {
667
- ...turn,
668
- sequence: patch.sequence
669
- };
670
- if (index >= 0) {
671
- existing[index] = nextTurn;
672
- } else {
673
- existing.push(nextTurn);
674
- }
675
- return {
676
- ...updateSessionState(state, sessionId, existing)
677
- };
678
- });
679
- },
680
- addErrorMessage: (sessionId, content) => {
681
- set((state) => {
682
- const turns = state.turns[sessionId] ?? [];
683
- const anchorTurnId = turns[turns.length - 1]?.turn_id ?? null;
684
- const entry_id = anchorTurnId ? `${ERROR_ANCHOR_PREFIX}${anchorTurnId}:${Date.now()}` : void 0;
685
- return {
686
- messages: {
687
- ...state.messages,
688
- [sessionId]: [
689
- ...state.messages[sessionId] ?? [],
690
- { role: "error", content, loop_name: "root", entry_id }
691
- ]
692
- }
693
- };
694
- });
695
- },
696
- markInterrupted: (sessionId) => {
697
- set((state) => {
698
- const turns = (state.turns[sessionId] ?? []).map((turn) => {
699
- if (turn.status !== "streaming") return turn;
700
- return {
701
- ...turn,
702
- status: "interrupted",
703
- tool_calls: turn.tool_calls.map(
704
- (toolCall) => toolCall.status === "pending" || toolCall.status === "awaiting_answer" ? { ...toolCall, status: "cancelled" } : toolCall
705
- )
706
- };
707
- });
708
- return {
709
- ...updateSessionState(state, sessionId, turns)
710
- };
711
- });
712
- },
713
- markFailed: (sessionId) => {
714
- set((state) => {
715
- const turns = (state.turns[sessionId] ?? []).map((turn) => {
716
- if (turn.status !== "streaming") return turn;
717
- return {
718
- ...turn,
719
- status: "failed",
720
- tool_calls: turn.tool_calls.map(
721
- (toolCall) => toolCall.status === "pending" || toolCall.status === "awaiting_answer" ? { ...toolCall, status: "error" } : toolCall
722
- )
723
- };
724
- });
725
- return {
726
- ...updateSessionState(state, sessionId, turns)
727
- };
728
- });
729
- },
730
- setStreaming: (sessionId, streaming) => {
731
- set((state) => ({
732
- isStreaming: { ...state.isStreaming, [sessionId]: streaming }
733
- }));
734
- },
735
- setAskAnswers: (sessionId, answers) => {
736
- set((state) => ({
737
- askAnswers: {
738
- ...state.askAnswers,
739
- [sessionId]: answers
740
- }
741
- }));
742
- },
743
- clearMessages: (sessionId) => {
744
- set((state) => {
745
- const { [sessionId]: _turns, ...restTurns } = state.turns;
746
- const { [sessionId]: _messages, ...restMessages } = state.messages;
747
- const { [sessionId]: _answers, ...restAnswers } = state.askAnswers;
748
- const { [sessionId]: _loops, ...restLoops } = state.agentLoops;
749
- const { [sessionId]: _compaction, ...restCompactions } = state.activeCompactions;
750
- return {
751
- turns: restTurns,
752
- messages: restMessages,
753
- askAnswers: restAnswers,
754
- agentLoops: restLoops,
755
- activeCompactions: restCompactions
756
- };
757
- });
758
- }
759
- }));
760
-
761
- // src/react/stores/task-store.ts
762
- import { create as create4 } from "zustand";
763
- var EMPTY_TASKS = [];
764
- var useTaskStore = create4()((set, get) => ({
765
- ...createClientActions(set),
766
- tasks: {},
767
- setTasks: (sessionId, tasks) => {
768
- set((state) => ({
769
- tasks: { ...state.tasks, [sessionId]: tasks }
770
- }));
771
- },
772
- getTasks: (sessionId) => {
773
- return get().tasks[sessionId] ?? EMPTY_TASKS;
774
- }
775
- }));
776
-
777
- // src/react/stores/session-store.ts
778
- var DEFAULT_SESSION_MODE = "executing";
779
- var onSessionChange = null;
780
- function invalidateHomeSidebarSessions() {
781
- const queryClient = globalThis.__agentQueryClient;
782
- if (!queryClient) return;
783
- void queryClient.invalidateQueries({ queryKey: ["sessions", "home-sidebar"] });
784
- }
785
- function isSessionAccessRevoked(error) {
786
- if (error instanceof Error) {
787
- const msg = error.message;
788
- return msg.includes("API 403") || msg.includes("API 404");
789
- }
790
- return false;
791
- }
792
- function removeSessionArtifacts(sessionId) {
793
- useChatStore.getState().clearMessages(sessionId);
794
- useTaskStore.getState().setTasks(sessionId, []);
795
- }
796
- function pruneSessionState(state, sessionId) {
797
- const nextFresh = new Set(state._freshSessions);
798
- nextFresh.delete(sessionId);
799
- const { [sessionId]: _mode, ...modes } = state.modes;
800
- const { [sessionId]: _rewindDraft, ...rewindDrafts } = state.rewindDrafts;
801
- return {
802
- sessions: state.sessions.filter((session) => session.id !== sessionId),
803
- activeSessionId: state.activeSessionId === sessionId ? null : state.activeSessionId,
804
- modes,
805
- rewindDrafts,
806
- _freshSessions: nextFresh
807
- };
808
- }
809
- function navigateAwayFromSession(sessionId) {
810
- if (typeof window === "undefined") return;
811
- if (window.location.pathname !== `/chat/${sessionId}`) return;
812
- window.history.replaceState(window.history.state, "", "/chat");
813
- window.dispatchEvent(new PopStateEvent("popstate"));
814
- }
815
- function handleUnreadableSession(set, get, sessionId) {
816
- const wasActive = get().activeSessionId === sessionId;
817
- removeSessionArtifacts(sessionId);
818
- set((state) => pruneSessionState(state, sessionId));
819
- if (wasActive) {
820
- onSessionChange?.(null);
821
- navigateAwayFromSession(sessionId);
822
- }
823
- invalidateHomeSidebarSessions();
824
- }
825
- function isPlainRecord(value) {
826
- return typeof value === "object" && value !== null && !Array.isArray(value);
827
- }
828
- function extractModeFromBlocks2(blocks) {
829
- const modeBlock = blocks.find((block) => block.type === "mode_change");
830
- if (modeBlock && isPlainRecord(modeBlock.content) && (modeBlock.content.to === "planning" || modeBlock.content.to === "executing")) {
831
- return modeBlock.content.to;
832
- }
833
- if (blocks.some((block) => block.type === "planning_enter")) return "planning";
834
- if (blocks.some((block) => block.type === "planning_exit")) return "executing";
835
- return null;
836
- }
837
- function toSelectionMap(value) {
838
- if (!isPlainRecord(value)) return {};
839
- const entries = Object.entries(value).map(([questionKey, optionIndexes]) => {
840
- if (!Array.isArray(optionIndexes)) return null;
841
- const parsedIndexes = optionIndexes.map((item) => typeof item === "number" ? item : Number(item)).filter((item) => Number.isInteger(item));
842
- return [Number(questionKey), parsedIndexes];
843
- }).filter((entry) => entry !== null);
844
- return Object.fromEntries(entries);
845
- }
846
- function toCustomMap(value) {
847
- if (!isPlainRecord(value)) return {};
848
- const entries = Object.entries(value).filter(([, text]) => typeof text === "string").map(([questionKey, text]) => [Number(questionKey), text]);
849
- return Object.fromEntries(entries);
850
- }
851
- function extractAskAnswers(turns) {
852
- const answers = {};
853
- for (const turn of turns) {
854
- for (const block of turn.blocks) {
855
- if (block.type !== "ask_user_answer" || typeof block.tool_call_id !== "string") continue;
856
- answers[block.tool_call_id] = {
857
- selections: toSelectionMap(isPlainRecord(block.content) ? block.content.selections : void 0),
858
- custom: toCustomMap(isPlainRecord(block.content) ? block.content.custom : void 0)
859
- };
860
- }
861
- }
862
- return answers;
863
- }
864
- function registerCreatedSessionState(set, session, mode = DEFAULT_SESSION_MODE) {
865
- useChatStore.getState().setTurns(session.id, []);
866
- useTaskStore.getState().setTasks(session.id, []);
867
- set((state) => ({
868
- sessions: [session, ...state.sessions.filter((item) => item.id !== session.id)],
869
- modes: { ...state.modes, [session.id]: state.modes[session.id] ?? mode },
870
- _freshSessions: new Set(state._freshSessions).add(session.id)
871
- }));
872
- }
873
- async function revalidateViewerSessions(existingSessions) {
874
- const viewerSessions = existingSessions.filter((session) => session.viewer_role === "viewer");
875
- if (viewerSessions.length === 0) {
876
- return [];
877
- }
878
- const refreshed = await Promise.all(
879
- viewerSessions.map(async (session) => {
880
- try {
881
- return await getSession(session.id);
882
- } catch (error) {
883
- if (isSessionAccessRevoked(error)) {
884
- return null;
885
- }
886
- return session;
887
- }
888
- })
889
- );
890
- return refreshed.filter((session) => session !== null);
891
- }
892
- var useSessionStore = create5()((set, get) => ({
893
- ...createClientActions(set),
894
- sessions: [],
895
- activeSessionId: null,
896
- loading: false,
897
- modes: {},
898
- rewindDrafts: {},
899
- _freshSessions: /* @__PURE__ */ new Set(),
900
- fetchSessions: async () => {
901
- set({ loading: true });
902
- try {
903
- const currentState = get();
904
- const [sessions, viewerSessions] = await Promise.all([
905
- listSessions(),
906
- revalidateViewerSessions(currentState.sessions)
907
- ]);
908
- const knownSessionIds = new Set(sessions.map((session) => session.id));
909
- const mergedSessions = [
910
- ...sessions,
911
- ...viewerSessions.filter((session) => !knownSessionIds.has(session.id))
912
- ];
913
- const removedSessionIds = currentState.sessions.filter(
914
- (session) => session.viewer_role === "viewer" && !mergedSessions.some((candidate) => candidate.id === session.id)
915
- ).map((session) => session.id);
916
- const activeSessionId = currentState.activeSessionId;
917
- for (const sessionId of removedSessionIds) {
918
- removeSessionArtifacts(sessionId);
919
- }
920
- let nextState = {
921
- sessions: mergedSessions,
922
- activeSessionId: currentState.activeSessionId,
923
- loading: false,
924
- modes: currentState.modes,
925
- rewindDrafts: currentState.rewindDrafts,
926
- _freshSessions: currentState._freshSessions
927
- };
928
- for (const sessionId of removedSessionIds) {
929
- nextState = {
930
- ...nextState,
931
- ...pruneSessionState(
932
- {
933
- ...currentState,
934
- sessions: nextState.sessions ?? currentState.sessions,
935
- activeSessionId: nextState.activeSessionId ?? currentState.activeSessionId,
936
- loading: nextState.loading ?? currentState.loading,
937
- modes: nextState.modes ?? currentState.modes,
938
- rewindDrafts: nextState.rewindDrafts ?? currentState.rewindDrafts,
939
- _freshSessions: nextState._freshSessions ?? currentState._freshSessions
940
- },
941
- sessionId
942
- )
943
- };
944
- }
945
- set(nextState);
946
- if (activeSessionId && removedSessionIds.includes(activeSessionId)) {
947
- onSessionChange?.(null);
948
- navigateAwayFromSession(activeSessionId);
949
- }
950
- invalidateHomeSidebarSessions();
951
- } catch (error) {
952
- set({ loading: false });
953
- throw error;
954
- }
955
- },
956
- createSession: async (intent) => {
957
- const { session_id } = await createSession(intent);
958
- const now = (/* @__PURE__ */ new Date()).toISOString();
959
- get().registerCreatedSession({
960
- id: session_id,
961
- intent: intent ?? "",
962
- status: "created",
963
- created_at: now,
964
- updated_at: now
965
- });
966
- get().setActiveSession(session_id);
967
- invalidateHomeSidebarSessions();
968
- get().fetchSessions().catch(() => {
969
- });
970
- return session_id;
971
- },
972
- registerCreatedSession: (session, mode = DEFAULT_SESSION_MODE) => {
973
- registerCreatedSessionState(set, session, mode);
974
- },
975
- upsertSession: (session) => {
976
- set((state) => ({
977
- sessions: state.sessions.some((item) => item.id === session.id) ? state.sessions.map((item) => item.id === session.id ? { ...item, ...session } : item) : [session, ...state.sessions]
978
- }));
979
- },
980
- isFreshSession: (sessionId) => get()._freshSessions.has(sessionId),
981
- setActiveSession: (id) => {
982
- set({ activeSessionId: id });
983
- onSessionChange?.(id);
984
- getSession(id).then((detail) => {
985
- set((state) => ({
986
- sessions: state.sessions.some((s) => s.id === id) ? state.sessions.map(
987
- (s) => s.id === id ? { ...s, status: detail.status, updated_at: detail.updated_at } : s
988
- ) : [detail, ...state.sessions]
989
- }));
990
- }).catch(() => {
991
- });
992
- const tasksPromise = getSessionTasks(id).catch(() => null);
993
- Promise.all([getSessionTurns(id), tasksPromise]).then(([turns, tasks]) => {
994
- if (tasks) useTaskStore.getState().setTasks(id, tasks);
995
- useChatStore.getState().setAskAnswers(id, extractAskAnswers(turns));
996
- let inferredMode = DEFAULT_SESSION_MODE;
997
- for (const turn of turns) {
998
- const nextMode = extractModeFromBlocks2(turn.blocks);
999
- if (nextMode) {
1000
- inferredMode = nextMode;
1001
- }
1002
- }
1003
- set((state) => {
1004
- if (state.modes[id] == null) {
1005
- return { modes: { ...state.modes, [id]: inferredMode } };
1006
- }
1007
- return state;
1008
- });
1009
- const isFresh = get()._freshSessions.has(id);
1010
- if (isFresh) {
1011
- set((state) => {
1012
- const next = new Set(state._freshSessions);
1013
- next.delete(id);
1014
- return { _freshSessions: next };
1015
- });
1016
- if (turns.length > 0) {
1017
- useChatStore.getState().setTurns(id, turns);
1018
- }
1019
- } else {
1020
- useChatStore.getState().setTurns(id, turns);
1021
- }
1022
- }).catch((error) => {
1023
- if (isSessionAccessRevoked(error)) {
1024
- handleUnreadableSession(set, get, id);
1025
- return;
1026
- }
1027
- console.error("Failed to load session data", error);
1028
- });
1029
- },
1030
- clearActiveSession: () => {
1031
- set({ activeSessionId: null });
1032
- onSessionChange?.(null);
1033
- },
1034
- deleteSession: async (id) => {
1035
- await deleteSession(id);
1036
- invalidateHomeSidebarSessions();
1037
- const wasActive = get().activeSessionId === id;
1038
- await get().fetchSessions();
1039
- if (!wasActive) {
1040
- return;
1041
- }
1042
- const nextId = get().sessions[0]?.id ?? null;
1043
- if (nextId) {
1044
- get().setActiveSession(nextId);
1045
- return;
1046
- }
1047
- get().clearActiveSession();
1048
- },
1049
- updateSessionStatus: (sessionId, status) => {
1050
- set((state) => ({
1051
- sessions: state.sessions.map((s) => s.id === sessionId ? { ...s, status } : s)
1052
- }));
1053
- if (status === "failed" || status === "interrupted") {
1054
- useChatStore.getState().setStreaming(sessionId, false);
1055
- if (status === "interrupted") {
1056
- useChatStore.getState().markInterrupted(sessionId);
1057
- } else {
1058
- useChatStore.getState().markFailed(sessionId);
1059
- }
1060
- }
1061
- },
1062
- updateSessionIntent: (sessionId, intent) => {
1063
- set((state) => ({
1064
- sessions: state.sessions.map((s) => s.id === sessionId ? { ...s, intent } : s)
1065
- }));
1066
- },
1067
- patchSession: (sessionId, patch) => {
1068
- set((state) => ({
1069
- sessions: state.sessions.map(
1070
- (s) => s.id === sessionId ? { ...s, ...patch } : s
1071
- )
1072
- }));
1073
- },
1074
- pinSession: async (sessionId, pinned) => {
1075
- const updated = await pinSession(sessionId, pinned);
1076
- set((state) => ({
1077
- sessions: state.sessions.map(
1078
- (s) => s.id === sessionId ? { ...s, is_pinned: updated.is_pinned, pinned_at: updated.pinned_at } : s
1079
- )
1080
- }));
1081
- invalidateHomeSidebarSessions();
1082
- },
1083
- setRewindDraft: (sessionId, text) => {
1084
- set((state) => {
1085
- if (text == null) {
1086
- const { [sessionId]: _, ...rest } = state.rewindDrafts;
1087
- return { rewindDrafts: rest };
1088
- }
1089
- return {
1090
- rewindDrafts: {
1091
- ...state.rewindDrafts,
1092
- [sessionId]: text
1093
- }
1094
- };
1095
- });
1096
- },
1097
- setMode: (sessionId, mode) => {
1098
- set((state) => ({ modes: { ...state.modes, [sessionId]: mode } }));
1099
- },
1100
- togglePlanningMode: (sessionId) => {
1101
- const current = get().modes[sessionId] ?? DEFAULT_SESSION_MODE;
1102
- const next = current === "executing" ? "planning" : "executing";
1103
- set((state) => ({ modes: { ...state.modes, [sessionId]: next } }));
1104
- },
1105
- toggleSharing: async (sessionId) => {
1106
- const session = get().sessions.find((s) => s.id === sessionId);
1107
- if (!session) return;
1108
- const newShared = !session.shared;
1109
- const result = await updateSharing(sessionId, newShared);
1110
- set((state) => ({
1111
- sessions: state.sessions.map(
1112
- (s) => s.id === sessionId ? { ...s, shared: result.shared } : s
1113
- )
1114
- }));
1115
- },
1116
- reset: () => {
1117
- set({
1118
- sessions: [],
1119
- activeSessionId: null,
1120
- loading: false,
1121
- modes: {},
1122
- rewindDrafts: {},
1123
- _freshSessions: /* @__PURE__ */ new Set()
1124
- });
1125
- invalidateHomeSidebarSessions();
1126
- }
1127
- }));
1128
- setChatStoreSessionAccessor(() => useSessionStore.getState().activeSessionId);
1129
-
1130
- // src/react/stores/auth-store.ts
1131
- var noopStorage = {
1132
- getItem: () => null,
1133
- setItem: () => {
1134
- },
1135
- removeItem: () => {
1136
- }
1137
- };
1138
- function shouldClearPersistedAuthState(value) {
1139
- try {
1140
- const parsed = JSON.parse(value);
1141
- return parsed.state?.token == null && parsed.state?.user == null;
1142
- } catch {
1143
- return false;
1144
- }
1145
- }
1146
- var authStorage = createJSONStorage(() => {
1147
- if (typeof localStorage === "undefined") {
1148
- return noopStorage;
1149
- }
1150
- return {
1151
- getItem: (name) => localStorage.getItem(name),
1152
- setItem: (name, value) => {
1153
- if (shouldClearPersistedAuthState(value)) {
1154
- localStorage.removeItem(name);
1155
- return;
1156
- }
1157
- localStorage.setItem(name, value);
1158
- },
1159
- removeItem: (name) => localStorage.removeItem(name)
1160
- };
1161
- });
1162
- function finishAuth(set, payload) {
1163
- set({
1164
- token: payload.token,
1165
- socketAuthToken: null,
1166
- user: payload.user,
1167
- loading: false,
1168
- error: null
1169
- });
1170
- agentSocket?.reconnect();
1171
- useSessionStore.getState().fetchSessions().catch(() => {
1172
- });
1173
- }
1174
- function finishCookieHydration(set, payload) {
1175
- set({
1176
- token: null,
1177
- socketAuthToken: payload.token,
1178
- user: payload.user,
1179
- loading: false,
1180
- error: null
1181
- });
1182
- agentSocket?.reconnect();
1183
- useSessionStore.getState().fetchSessions().catch(() => {
1184
- });
1185
- }
1186
- function toUser(info) {
1187
- return {
1188
- id: info.id,
1189
- username: info.username,
1190
- display_name: info.display_name,
1191
- avatar_url: info.avatar_url,
1192
- is_admin: info.is_admin
1193
- };
1194
- }
1195
- var useAuthStore = create6()(
1196
- persist(
1197
- (set, get) => ({
1198
- ...createClientActions(set),
1199
- token: null,
1200
- socketAuthToken: null,
1201
- user: null,
1202
- loading: false,
1203
- error: null,
1204
- logout: () => {
1205
- void logout().catch(() => {
1206
- });
1207
- set({ token: null, socketAuthToken: null, user: null, error: null });
1208
- agentSocket?.disconnect();
1209
- useSessionStore.getState().reset();
1210
- },
1211
- checkAuth: async () => {
1212
- const token = get().token;
1213
- if (!token) return;
1214
- try {
1215
- const auth = await getMe();
1216
- finishAuth(set, { token: auth.token, user: toUser(auth) });
1217
- } catch {
1218
- set({ token: null, socketAuthToken: null, user: null, error: null });
1219
- useSessionStore.getState().reset();
1220
- }
1221
- },
1222
- hydrateFromCookie: async () => {
1223
- set({ loading: true, error: null });
1224
- const previousToken = get().token;
1225
- if (previousToken) {
1226
- try {
1227
- const auth = await getMe();
1228
- finishAuth(set, { token: auth.token, user: toUser(auth) });
1229
- return;
1230
- } catch {
1231
- set({ token: null, socketAuthToken: null, user: null, error: null });
1232
- useSessionStore.getState().reset();
1233
- }
1234
- }
1235
- try {
1236
- const auth = await getMe();
1237
- finishCookieHydration(set, { token: auth.token, user: toUser(auth) });
1238
- } catch {
1239
- set({
1240
- token: null,
1241
- socketAuthToken: null,
1242
- user: null,
1243
- loading: false,
1244
- error: null
1245
- });
1246
- useSessionStore.getState().reset();
1247
- }
1248
- }
1249
- }),
1250
- {
1251
- name: "agent-auth",
1252
- storage: authStorage,
1253
- partialize: (state) => {
1254
- if (state.socketAuthToken) {
1255
- return { token: null, user: null };
1256
- }
1257
- return { token: state.token, user: state.user };
1258
- }
1259
- }
1260
- )
1261
- );
1262
-
1263
- // src/react/stores/background-store.ts
1264
- import { create as create7 } from "zustand";
1265
- var useBackgroundStore = create7()((set) => ({
1266
- ...createClientActions(set),
1267
- tasks: {},
1268
- selectedTaskId: {},
1269
- setTasks: (sessionId, tasks) => set((state) => ({
1270
- tasks: { ...state.tasks, [sessionId]: tasks },
1271
- selectedTaskId: {
1272
- ...state.selectedTaskId,
1273
- [sessionId]: state.selectedTaskId[sessionId] ?? tasks[0]?.id ?? null
1274
- }
1275
- })),
1276
- upsertTask: (sessionId, task) => set((state) => {
1277
- const existing = state.tasks[sessionId] ?? [];
1278
- const index = existing.findIndex((item) => item.id === task.id);
1279
- const next = [...existing];
1280
- if (index >= 0) {
1281
- next[index] = { ...next[index], ...task };
1282
- } else {
1283
- next.unshift(task);
1284
- }
1285
- return {
1286
- tasks: { ...state.tasks, [sessionId]: next },
1287
- selectedTaskId: {
1288
- ...state.selectedTaskId,
1289
- [sessionId]: state.selectedTaskId[sessionId] ?? task.id
1290
- }
1291
- };
1292
- }),
1293
- selectTask: (sessionId, taskId) => set((state) => ({
1294
- selectedTaskId: { ...state.selectedTaskId, [sessionId]: taskId }
1295
- }))
1296
- }));
1297
-
1298
- // src/react/stores/card-state-store.ts
1299
- import { create as create8 } from "zustand";
1300
- var useCardStateStore = create8((set, get) => ({
1301
- ...createClientActions(set),
1302
- states: {},
1303
- getCardState: (cardId) => {
1304
- return get().states[cardId];
1305
- },
1306
- setCardState: (cardId, state) => {
1307
- set((prev) => ({
1308
- states: { ...prev.states, [cardId]: state }
1309
- }));
1310
- },
1311
- removeCardState: (cardId) => {
1312
- set((prev) => {
1313
- const { [cardId]: _, ...rest } = prev.states;
1314
- return { states: rest };
1315
- });
1316
- },
1317
- clearAllStates: () => {
1318
- set({ states: {} });
1319
- }
1320
- }));
1321
-
1322
- // src/react/stores/connection-store.ts
1323
- import { create as create9 } from "zustand";
1324
- var initialConnectionState = {
1325
- status: "disconnected",
1326
- reconnectAttempt: 0,
1327
- lastConnectedAt: null,
1328
- lastDisconnectedAt: null,
1329
- hasEverConnected: false
1330
- };
1331
- var useConnectionStore = create9()((set) => ({
1332
- ...createClientActions(set),
1333
- ...initialConnectionState,
1334
- markConnecting: (attempt = 0) => set({
1335
- status: "connecting",
1336
- reconnectAttempt: attempt
1337
- }),
1338
- markConnected: () => set({
1339
- status: "connected",
1340
- reconnectAttempt: 0,
1341
- lastConnectedAt: Date.now(),
1342
- hasEverConnected: true
1343
- }),
1344
- markDisconnected: () => set({
1345
- status: "disconnected",
1346
- reconnectAttempt: 0,
1347
- lastDisconnectedAt: Date.now()
1348
- }),
1349
- reset: () => set(initialConnectionState)
1350
- }));
1351
-
1352
- // src/react/stores/runtime-store.ts
1353
- import { create as create10 } from "zustand";
1354
- var useRuntimeStore = create10()((set) => ({
1355
- ...createClientActions(set),
1356
- events: {},
1357
- addEvent: (sessionId, event) => set((state) => {
1358
- const current = state.events[sessionId] ?? [];
1359
- const nextEvent = {
1360
- ...event,
1361
- id: `${Date.now()}-${current.length}`,
1362
- sessionId,
1363
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1364
- };
1365
- return {
1366
- events: {
1367
- ...state.events,
1368
- [sessionId]: [...current.slice(-59), nextEvent]
1369
- }
1370
- };
1371
- }),
1372
- clearSession: (sessionId) => set((state) => ({
1373
- events: { ...state.events, [sessionId]: [] }
1374
- }))
1375
- }));
1376
-
1377
- // src/react/stores/gis-store.ts
1378
- import { create as create11 } from "zustand";
1379
- var EMPTY_GOALS = [];
1380
- var EMPTY_RESOURCES = [];
1381
- var EMPTY_TARGETS = [];
1382
- var EMPTY_COMMANDS = [];
1383
- function newCommandId() {
1384
- if (typeof globalThis !== "undefined" && "crypto" in globalThis) {
1385
- return globalThis.crypto?.randomUUID?.() ?? `gis-map-${Date.now()}-${Math.random()}`;
1386
- }
1387
- return `gis-map-${Date.now()}-${Math.random()}`;
1388
- }
1389
- var useGisStore = create11()((set, get) => ({
1390
- ...createClientActions(set),
1391
- goalsBySession: {},
1392
- resourcesBySession: {},
1393
- targetsBySession: {},
1394
- pendingMapCommandsBySession: {},
1395
- setGoals: (sessionId, goals) => {
1396
- set((state) => ({
1397
- goalsBySession: { ...state.goalsBySession, [sessionId]: goals }
1398
- }));
1399
- },
1400
- setResources: (sessionId, resources) => {
1401
- set((state) => ({
1402
- resourcesBySession: { ...state.resourcesBySession, [sessionId]: resources }
1403
- }));
1404
- },
1405
- setTargets: (sessionId, targets) => {
1406
- set((state) => ({
1407
- targetsBySession: { ...state.targetsBySession, [sessionId]: targets }
1408
- }));
1409
- },
1410
- pushMapCommand: (sessionId, command) => {
1411
- set((state) => ({
1412
- pendingMapCommandsBySession: {
1413
- ...state.pendingMapCommandsBySession,
1414
- [sessionId]: [
1415
- ...state.pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS,
1416
- {
1417
- ...command,
1418
- id: newCommandId(),
1419
- createdAt: Date.now()
1420
- }
1421
- ]
1422
- }
1423
- }));
1424
- },
1425
- consumeMapCommand: (sessionId, commandId) => {
1426
- set((state) => ({
1427
- pendingMapCommandsBySession: {
1428
- ...state.pendingMapCommandsBySession,
1429
- [sessionId]: (state.pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS).filter(
1430
- (command) => command.id !== commandId
1431
- )
1432
- }
1433
- }));
1434
- },
1435
- getGoals: (sessionId) => get().goalsBySession[sessionId] ?? EMPTY_GOALS,
1436
- getResources: (sessionId) => get().resourcesBySession[sessionId] ?? EMPTY_RESOURCES,
1437
- getTargets: (sessionId) => get().targetsBySession[sessionId] ?? EMPTY_TARGETS,
1438
- getPendingMapCommands: (sessionId) => get().pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS
1439
- }));
1440
-
1441
- // src/react/stores/answer-callback-store.ts
1442
- import { create as create12 } from "zustand";
1443
- var useAnswerCallbackStore = create12()((set) => ({
1444
- ...createClientActions(set),
1445
- callbacks: {},
1446
- setAnswerCallback: (sessionId, callback) => {
1447
- set((state) => ({
1448
- callbacks: {
1449
- ...state.callbacks,
1450
- [sessionId]: callback
1451
- }
1452
- }));
1453
- }
1454
- }));
1455
-
1456
- // src/react/stores/runtime-features-store.ts
1457
- import { create as create13 } from "zustand";
1458
- var useRuntimeFeaturesStore = create13((set) => ({
1459
- ...createClientActions(set),
1460
- asrEnabled: false,
1461
- asrProvider: "volcengine",
1462
- publicSharingEnabled: false,
1463
- memoryEnabled: false,
1464
- setFeatures: (features) => set((prev) => ({
1465
- asrEnabled: features.asrEnabled ?? prev.asrEnabled,
1466
- asrProvider: features.asrProvider ?? prev.asrProvider,
1467
- publicSharingEnabled: features.publicSharingEnabled ?? prev.publicSharingEnabled,
1468
- memoryEnabled: features.memoryEnabled ?? prev.memoryEnabled
1469
- }))
1470
- }));
1471
-
1472
- // src/react/bootstrap.ts
1473
- var bootstrappedClient = null;
1474
- function getBootstrappedClient() {
1475
- if (!bootstrappedClient) {
1476
- throw new Error("bootstrapBladeClient() must be called before any SDK usage");
1477
- }
1478
- return bootstrappedClient;
1479
- }
1480
-
1481
- // src/react/api/client.ts
1482
- function getAuthedUrl(path) {
1483
- return getClient().buildAuthedUrl(path);
1484
- }
1485
- async function apiFetchText(path, init) {
1486
- return getClient().textFromInit(path, init);
1487
- }
1488
- async function apiFetchResponse(path, init) {
1489
- return getClient().responseFromInit(path, init);
1490
- }
1491
- function getClient() {
1492
- return getBootstrappedClient();
1493
- }
1494
-
1495
- // src/react/api/sessions.ts
1496
- var r2 = () => getClient().sessions;
1497
- var listSessions = (...args) => r2().listSessions(...args);
1498
- var createSession = (...args) => r2().createSession(...args);
1499
- var getSession = (...args) => r2().getSession(...args);
1500
- var pinSession = (...args) => r2().pinSession(...args);
1501
- var updateSharing = (...args) => r2().updateSharing(...args);
1502
- var getSessionTasks = (...args) => r2().getSessionTasks(...args);
1503
- var getSessionTurns = (...args) => r2().getSessionTurns(...args);
1504
- var deleteSession = (...args) => r2().deleteSession(...args);
1505
- var listDir = (...args) => r2().listDir(...args);
1506
- var uploadFiles = (...args) => r2().uploadFiles(...args);
1507
- var deleteFile = (...args) => r2().deleteFile(...args);
1508
- var renameFile = (...args) => r2().renameFile(...args);
1509
- var copyFile = (...args) => r2().copyFile(...args);
1510
- var getDownloadDirUrl = (...args) => r2().getDownloadDirUrl(...args);
1511
-
1512
- // src/react/lib/utils.ts
1513
- import { clsx } from "clsx";
1514
- import { twMerge } from "tailwind-merge";
1515
- function cn(...inputs) {
1516
- return twMerge(clsx(inputs));
1517
- }
1518
-
1519
34
  // src/react/components/workspace/FileTree.tsx
1520
35
  import { useQuery, useQueryClient } from "@tanstack/react-query";
1521
36
  import {
@@ -1529,89 +44,6 @@ import {
1529
44
  } from "lucide-react";
1530
45
  import { useEffect, useEffectEvent, useRef, useState as useState2 } from "react";
1531
46
 
1532
- // src/react/lib/session-file-preview.ts
1533
- var IMAGE_EXTS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "svg", "webp", "ico", "bmp"]);
1534
- var DOCX_EXTS = /* @__PURE__ */ new Set(["docx", "doc"]);
1535
- var EXCEL_EXTS = /* @__PURE__ */ new Set(["xlsx", "xls", "xlsm", "xlsb"]);
1536
- var PPT_EXTS = /* @__PURE__ */ new Set(["pptx", "ppt"]);
1537
- var CSV_EXTS = /* @__PURE__ */ new Set(["csv"]);
1538
- var MARKDOWN_EXTS = /* @__PURE__ */ new Set(["md", "markdown"]);
1539
- var HTML_EXTS = /* @__PURE__ */ new Set(["html", "htm"]);
1540
- function getExt(fileName) {
1541
- return fileName.split(".").pop()?.toLowerCase() ?? "";
1542
- }
1543
- function getDisplayFileName(filePath, fileName) {
1544
- return fileName?.trim() || filePath.split("/").pop() || filePath;
1545
- }
1546
- function getSessionFilePath(sessionId, filePath) {
1547
- return `/api/sessions/${sessionId}/files/${encodeURIComponent(filePath)}`;
1548
- }
1549
- function getSessionFileDownloadUrl(sessionId, filePath) {
1550
- return getAuthedUrl(getSessionFilePath(sessionId, filePath));
1551
- }
1552
- function isTextualContentType(contentType) {
1553
- return contentType.startsWith("text/") || contentType.includes("json") || contentType.includes("xml") || contentType.includes("yaml") || contentType.includes("javascript");
1554
- }
1555
- function buildSessionBinaryPreviewTarget(sessionId, filePath, fileName) {
1556
- const resolvedFileName = getDisplayFileName(filePath, fileName);
1557
- const ext = getExt(resolvedFileName);
1558
- const filePathUrl = getSessionFilePath(sessionId, filePath);
1559
- const downloadUrl = getSessionFileDownloadUrl(sessionId, filePath);
1560
- if (IMAGE_EXTS.has(ext)) {
1561
- return { type: "image", content: downloadUrl, title: resolvedFileName, key: filePath };
1562
- }
1563
- if (ext === "pdf") {
1564
- return { type: "pdf", content: downloadUrl, title: resolvedFileName, key: filePath };
1565
- }
1566
- if (DOCX_EXTS.has(ext)) {
1567
- return { type: "docx", content: downloadUrl, title: resolvedFileName, key: filePath };
1568
- }
1569
- if (EXCEL_EXTS.has(ext)) {
1570
- return { type: "excel", content: downloadUrl, title: resolvedFileName, key: filePath };
1571
- }
1572
- if (PPT_EXTS.has(ext)) {
1573
- return {
1574
- type: "ppt",
1575
- content: filePathUrl,
1576
- sourceUrl: downloadUrl,
1577
- title: resolvedFileName,
1578
- key: filePath
1579
- };
1580
- }
1581
- return null;
1582
- }
1583
- async function resolveSessionFilePreviewTarget(sessionId, filePath, fileName) {
1584
- const resolvedFileName = getDisplayFileName(filePath, fileName);
1585
- const binaryTarget = buildSessionBinaryPreviewTarget(sessionId, filePath, resolvedFileName);
1586
- if (binaryTarget) {
1587
- return binaryTarget;
1588
- }
1589
- const downloadUrl = getSessionFileDownloadUrl(sessionId, filePath);
1590
- const res = await apiFetchResponse(getSessionFilePath(sessionId, filePath));
1591
- const contentType = (res.headers.get("content-type") ?? "").toLowerCase();
1592
- if (contentType.startsWith("video/")) {
1593
- void res.body?.cancel();
1594
- return { type: "video", content: downloadUrl, title: resolvedFileName, key: filePath };
1595
- }
1596
- if (contentType.startsWith("audio/")) {
1597
- void res.body?.cancel();
1598
- return { type: "audio", content: downloadUrl, title: resolvedFileName, key: filePath };
1599
- }
1600
- if (!isTextualContentType(contentType)) {
1601
- void res.body?.cancel();
1602
- return { type: "download", content: downloadUrl, title: resolvedFileName, key: filePath };
1603
- }
1604
- const content = await res.text();
1605
- const ext = getExt(resolvedFileName);
1606
- const type3 = MARKDOWN_EXTS.has(ext) ? "markdown" : CSV_EXTS.has(ext) ? "csv" : HTML_EXTS.has(ext) ? "html" : "file";
1607
- return {
1608
- type: type3,
1609
- content,
1610
- title: resolvedFileName,
1611
- key: filePath
1612
- };
1613
- }
1614
-
1615
47
  // src/react/lib/open-session-file.ts
1616
48
  async function openSessionFileInPreview(sessionId, filePath, fileName, pushArtifact, shouldOpen = () => true) {
1617
49
  try {
@@ -1624,37 +56,6 @@ async function openSessionFileInPreview(sessionId, filePath, fileName, pushArtif
1624
56
  }
1625
57
  }
1626
58
 
1627
- // src/react/components/ui/collapsible.tsx
1628
- import { Collapsible as CollapsiblePrimitive } from "radix-ui";
1629
- import { jsx } from "react/jsx-runtime";
1630
- function Collapsible({
1631
- ...props
1632
- }) {
1633
- return /* @__PURE__ */ jsx(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
1634
- }
1635
- function CollapsibleTrigger({
1636
- ...props
1637
- }) {
1638
- return /* @__PURE__ */ jsx(
1639
- CollapsiblePrimitive.CollapsibleTrigger,
1640
- {
1641
- "data-slot": "collapsible-trigger",
1642
- ...props
1643
- }
1644
- );
1645
- }
1646
- function CollapsibleContent({
1647
- ...props
1648
- }) {
1649
- return /* @__PURE__ */ jsx(
1650
- CollapsiblePrimitive.CollapsibleContent,
1651
- {
1652
- "data-slot": "collapsible-content",
1653
- ...props
1654
- }
1655
- );
1656
- }
1657
-
1658
59
  // src/react/components/ai-elements/file-tree.tsx
1659
60
  import {
1660
61
  ChevronRightIcon,
@@ -1669,7 +70,7 @@ import {
1669
70
  useMemo,
1670
71
  useState
1671
72
  } from "react";
1672
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
73
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1673
74
  var noop = () => {
1674
75
  };
1675
76
  var FileTreeContext = createContext({
@@ -1706,7 +107,7 @@ var FileTree = ({
1706
107
  () => ({ expandedPaths, onSelect, selectedPath, togglePath }),
1707
108
  [expandedPaths, onSelect, selectedPath, togglePath]
1708
109
  );
1709
- return /* @__PURE__ */ jsx2(FileTreeContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx2(
110
+ return /* @__PURE__ */ jsx(FileTreeContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
1710
111
  "div",
1711
112
  {
1712
113
  className: cn(
@@ -1715,7 +116,7 @@ var FileTree = ({
1715
116
  ),
1716
117
  role: "tree",
1717
118
  ...props,
1718
- children: /* @__PURE__ */ jsx2("div", { className: "p-2", children })
119
+ children: /* @__PURE__ */ jsx("div", { className: "p-2", children })
1719
120
  }
1720
121
  ) });
1721
122
  };
@@ -1723,12 +124,12 @@ var FileTreeIcon = ({
1723
124
  className,
1724
125
  children,
1725
126
  ...props
1726
- }) => /* @__PURE__ */ jsx2("span", { className: cn("shrink-0", className), ...props, children });
127
+ }) => /* @__PURE__ */ jsx("span", { className: cn("shrink-0", className), ...props, children });
1727
128
  var FileTreeName = ({
1728
129
  className,
1729
130
  children,
1730
131
  ...props
1731
- }) => /* @__PURE__ */ jsx2("span", { className: cn("truncate", className), ...props, children });
132
+ }) => /* @__PURE__ */ jsx("span", { className: cn("truncate", className), ...props, children });
1732
133
  var FileTreeFolderContext = createContext({
1733
134
  isExpanded: false,
1734
135
  name: "",
@@ -1743,7 +144,7 @@ var FileTreeActions = ({
1743
144
  className,
1744
145
  children,
1745
146
  ...props
1746
- }) => /* @__PURE__ */ jsx2(
147
+ }) => /* @__PURE__ */ jsx(
1747
148
  "div",
1748
149
  {
1749
150
  className: cn("ml-auto flex items-center gap-1", className),
@@ -1755,7 +156,7 @@ var FileTreeActions = ({
1755
156
  );
1756
157
 
1757
158
  // src/react/components/workspace/FileTree.tsx
1758
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
159
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1759
160
  var ROOT_PATH = ".";
1760
161
  var TREE_ROW_CLASS = "group flex w-full items-center gap-1 rounded px-2 py-1 text-left transition-colors hover:bg-muted/50";
1761
162
  var FILE_ICON_GROUPS = {
@@ -1983,16 +384,16 @@ function FileTree2({
1983
384
  setSelectedPath(path);
1984
385
  };
1985
386
  if (!sessionId) {
1986
- return /* @__PURE__ */ jsx3(EmptyState, { title: "\u6682\u65E0\u6D3B\u8DC3\u4F1A\u8BDD", description: "\u9009\u62E9\u6216\u521B\u5EFA\u4F1A\u8BDD\u540E\u67E5\u770B\u5DE5\u4F5C\u533A\u6587\u4EF6" });
387
+ return /* @__PURE__ */ jsx2(EmptyState, { title: "\u6682\u65E0\u6D3B\u8DC3\u4F1A\u8BDD", description: "\u9009\u62E9\u6216\u521B\u5EFA\u4F1A\u8BDD\u540E\u67E5\u770B\u5DE5\u4F5C\u533A\u6587\u4EF6" });
1987
388
  }
1988
389
  if (rootLoading) {
1989
390
  return /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 px-3 py-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
1990
- /* @__PURE__ */ jsx3(Loader2, { size: 14, className: "animate-spin" }),
1991
- /* @__PURE__ */ jsx3("span", { children: "\u52A0\u8F7D\u4E2D..." })
391
+ /* @__PURE__ */ jsx2(Loader2, { size: 14, className: "animate-spin" }),
392
+ /* @__PURE__ */ jsx2("span", { children: "\u52A0\u8F7D\u4E2D..." })
1992
393
  ] });
1993
394
  }
1994
395
  if (rootError) {
1995
- return /* @__PURE__ */ jsx3(
396
+ return /* @__PURE__ */ jsx2(
1996
397
  EmptyState,
1997
398
  {
1998
399
  title: "\u6587\u4EF6\u6811\u52A0\u8F7D\u5931\u8D25",
@@ -2001,9 +402,9 @@ function FileTree2({
2001
402
  );
2002
403
  }
2003
404
  if (!rootEntries || rootEntries.length === 0) {
2004
- return /* @__PURE__ */ jsx3(EmptyState, { title: "\u5F53\u524D\u5DE5\u4F5C\u533A\u4E3A\u7A7A", description: "\u4F1A\u8BDD\u4EA7\u751F\u6587\u4EF6\u540E\u4F1A\u663E\u793A\u5728\u8FD9\u91CC" });
405
+ return /* @__PURE__ */ jsx2(EmptyState, { title: "\u5F53\u524D\u5DE5\u4F5C\u533A\u4E3A\u7A7A", description: "\u4F1A\u8BDD\u4EA7\u751F\u6587\u4EF6\u540E\u4F1A\u663E\u793A\u5728\u8FD9\u91CC" });
2005
406
  }
2006
- return /* @__PURE__ */ jsx3(
407
+ return /* @__PURE__ */ jsx2(
2007
408
  FileTree,
2008
409
  {
2009
410
  expanded: expandedDirs,
@@ -2012,7 +413,7 @@ function FileTree2({
2012
413
  onSelect: handleSelect,
2013
414
  className: "border-none bg-transparent",
2014
415
  children: rootEntries.map(
2015
- (entry) => entry.is_dir ? /* @__PURE__ */ jsx3(
416
+ (entry) => entry.is_dir ? /* @__PURE__ */ jsx2(
2016
417
  FolderNode,
2017
418
  {
2018
419
  entry,
@@ -2030,7 +431,7 @@ function FileTree2({
2030
431
  allowDelete
2031
432
  },
2032
433
  entry.path
2033
- ) : /* @__PURE__ */ jsx3(
434
+ ) : /* @__PURE__ */ jsx2(
2034
435
  FileNode,
2035
436
  {
2036
437
  entry,
@@ -2132,15 +533,15 @@ function FolderNode({
2132
533
  setActiveAction(null);
2133
534
  }
2134
535
  };
2135
- return /* @__PURE__ */ jsx3(Collapsible, { open: isExpanded, onOpenChange: () => onToggleDir(entry.path), children: /* @__PURE__ */ jsxs2("div", { children: [
536
+ return /* @__PURE__ */ jsx2(Collapsible, { open: isExpanded, onOpenChange: () => onToggleDir(entry.path), children: /* @__PURE__ */ jsxs2("div", { children: [
2136
537
  /* @__PURE__ */ jsxs2("div", { className: cn(TREE_ROW_CLASS, isSelected && "bg-muted"), children: [
2137
- /* @__PURE__ */ jsx3(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsx3(
538
+ /* @__PURE__ */ jsx2(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
2138
539
  "button",
2139
540
  {
2140
541
  type: "button",
2141
542
  className: "flex shrink-0 cursor-pointer items-center rounded border-none bg-transparent p-0",
2142
543
  title: isExpanded ? "\u6536\u8D77\u76EE\u5F55" : "\u5C55\u5F00\u76EE\u5F55",
2143
- children: /* @__PURE__ */ jsx3(
544
+ children: /* @__PURE__ */ jsx2(
2144
545
  ChevronRight,
2145
546
  {
2146
547
  className: cn(
@@ -2152,8 +553,8 @@ function FolderNode({
2152
553
  }
2153
554
  ) }),
2154
555
  isRenaming ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
2155
- /* @__PURE__ */ jsx3(FileTreeIcon, { children: getFolderIcon() }),
2156
- /* @__PURE__ */ jsx3(
556
+ /* @__PURE__ */ jsx2(FileTreeIcon, { children: getFolderIcon() }),
557
+ /* @__PURE__ */ jsx2(
2157
558
  "input",
2158
559
  {
2159
560
  ref: renameInputRef,
@@ -2185,13 +586,13 @@ function FolderNode({
2185
586
  onSelectPath(entry.path);
2186
587
  },
2187
588
  children: [
2188
- /* @__PURE__ */ jsx3(FileTreeIcon, { children: getFolderIcon() }),
2189
- /* @__PURE__ */ jsx3(FileTreeName, { className: "min-w-0 flex-1", children: entry.name })
589
+ /* @__PURE__ */ jsx2(FileTreeIcon, { children: getFolderIcon() }),
590
+ /* @__PURE__ */ jsx2(FileTreeName, { className: "min-w-0 flex-1", children: entry.name })
2190
591
  ]
2191
592
  }
2192
593
  ),
2193
594
  !readOnly ? /* @__PURE__ */ jsxs2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: [
2194
- /* @__PURE__ */ jsx3(
595
+ /* @__PURE__ */ jsx2(
2195
596
  TreeActionButton,
2196
597
  {
2197
598
  onClick: () => {
@@ -2201,10 +602,10 @@ function FolderNode({
2201
602
  anchor.click();
2202
603
  },
2203
604
  title: "\u4E0B\u8F7D\u76EE\u5F55",
2204
- children: /* @__PURE__ */ jsx3(Download, { size: 12 })
605
+ children: /* @__PURE__ */ jsx2(Download, { size: 12 })
2205
606
  }
2206
607
  ),
2207
- /* @__PURE__ */ jsx3(
608
+ /* @__PURE__ */ jsx2(
2208
609
  TreeActionButton,
2209
610
  {
2210
611
  disabled: activeAction !== null,
@@ -2214,19 +615,19 @@ function FolderNode({
2214
615
  setIsRenaming(true);
2215
616
  },
2216
617
  title: "\u91CD\u547D\u540D",
2217
- children: activeAction === "rename" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Pencil, { size: 12 })
618
+ children: activeAction === "rename" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Pencil, { size: 12 })
2218
619
  }
2219
620
  ),
2220
- /* @__PURE__ */ jsx3(
621
+ /* @__PURE__ */ jsx2(
2221
622
  TreeActionButton,
2222
623
  {
2223
624
  disabled: activeAction !== null,
2224
625
  onClick: () => void handleCopy(),
2225
626
  title: "\u590D\u5236\u76EE\u5F55",
2226
- children: activeAction === "copy" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Copy, { size: 12 })
627
+ children: activeAction === "copy" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Copy, { size: 12 })
2227
628
  }
2228
629
  ),
2229
- /* @__PURE__ */ jsx3(
630
+ /* @__PURE__ */ jsx2(
2230
631
  TreeActionButton,
2231
632
  {
2232
633
  disabled: activeAction !== null || !onShareFile,
@@ -2243,29 +644,29 @@ function FolderNode({
2243
644
  }
2244
645
  },
2245
646
  title: "\u5171\u4EAB\u5230 .share",
2246
- children: activeAction === "share" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Link2, { size: 12 })
647
+ children: activeAction === "share" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Link2, { size: 12 })
2247
648
  }
2248
649
  ),
2249
- /* @__PURE__ */ jsx3(
650
+ /* @__PURE__ */ jsx2(
2250
651
  TreeActionButton,
2251
652
  {
2252
653
  disabled: activeAction !== null,
2253
654
  onClick: () => void handleDelete(),
2254
655
  title: "\u5220\u9664\u76EE\u5F55",
2255
- children: activeAction === "delete" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Trash2, { size: 12 })
656
+ children: activeAction === "delete" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Trash2, { size: 12 })
2256
657
  }
2257
658
  )
2258
- ] }) : allowDelete ? /* @__PURE__ */ jsx3(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: /* @__PURE__ */ jsx3(
659
+ ] }) : allowDelete ? /* @__PURE__ */ jsx2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: /* @__PURE__ */ jsx2(
2259
660
  TreeActionButton,
2260
661
  {
2261
662
  disabled: activeAction !== null,
2262
663
  onClick: () => void handleDelete(),
2263
664
  title: "\u5220\u9664\u76EE\u5F55",
2264
- children: activeAction === "delete" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Trash2, { size: 12 })
665
+ children: activeAction === "delete" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Trash2, { size: 12 })
2265
666
  }
2266
667
  ) }) : null
2267
668
  ] }),
2268
- /* @__PURE__ */ jsx3(CollapsibleContent, { children: /* @__PURE__ */ jsx3("div", { className: "ml-4 border-l pl-2", children: /* @__PURE__ */ jsx3(
669
+ /* @__PURE__ */ jsx2(CollapsibleContent, { children: /* @__PURE__ */ jsx2("div", { className: "ml-4 border-l pl-2", children: /* @__PURE__ */ jsx2(
2269
670
  LazyDirChildren,
2270
671
  {
2271
672
  dirPath: entry.path,
@@ -2369,9 +770,9 @@ function FileNode({
2369
770
  }
2370
771
  };
2371
772
  return /* @__PURE__ */ jsxs2("div", { className: cn(TREE_ROW_CLASS, isSelected && "bg-muted"), children: [
2372
- /* @__PURE__ */ jsx3("span", { className: "size-4 shrink-0" }),
2373
- /* @__PURE__ */ jsx3(FileTreeIcon, { children: getFileIcon(entry.name) }),
2374
- isRenaming ? /* @__PURE__ */ jsx3(
773
+ /* @__PURE__ */ jsx2("span", { className: "size-4 shrink-0" }),
774
+ /* @__PURE__ */ jsx2(FileTreeIcon, { children: getFileIcon(entry.name) }),
775
+ isRenaming ? /* @__PURE__ */ jsx2(
2375
776
  "input",
2376
777
  {
2377
778
  ref: renameInputRef,
@@ -2402,13 +803,13 @@ function FileNode({
2402
803
  void onOpenFile(entry.path, entry.name);
2403
804
  },
2404
805
  children: [
2405
- /* @__PURE__ */ jsx3(FileTreeName, { className: "min-w-0 flex-1", children: entry.name }),
2406
- /* @__PURE__ */ jsx3(FileTagList, { tags: entry.tags })
806
+ /* @__PURE__ */ jsx2(FileTreeName, { className: "min-w-0 flex-1", children: entry.name }),
807
+ /* @__PURE__ */ jsx2(FileTagList, { tags: entry.tags })
2407
808
  ]
2408
809
  }
2409
810
  ),
2410
- isOpening ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "ml-auto shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : !readOnly ? /* @__PURE__ */ jsxs2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: [
2411
- /* @__PURE__ */ jsx3(
811
+ isOpening ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "ml-auto shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : !readOnly ? /* @__PURE__ */ jsxs2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: [
812
+ /* @__PURE__ */ jsx2(
2412
813
  TreeActionButton,
2413
814
  {
2414
815
  onClick: () => {
@@ -2418,10 +819,10 @@ function FileNode({
2418
819
  anchor.click();
2419
820
  },
2420
821
  title: "\u4E0B\u8F7D\u6587\u4EF6",
2421
- children: /* @__PURE__ */ jsx3(Download, { size: 12 })
822
+ children: /* @__PURE__ */ jsx2(Download, { size: 12 })
2422
823
  }
2423
824
  ),
2424
- /* @__PURE__ */ jsx3(
825
+ /* @__PURE__ */ jsx2(
2425
826
  TreeActionButton,
2426
827
  {
2427
828
  disabled: activeAction !== null,
@@ -2431,19 +832,19 @@ function FileNode({
2431
832
  setIsRenaming(true);
2432
833
  },
2433
834
  title: "\u91CD\u547D\u540D",
2434
- children: activeAction === "rename" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Pencil, { size: 12 })
835
+ children: activeAction === "rename" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Pencil, { size: 12 })
2435
836
  }
2436
837
  ),
2437
- /* @__PURE__ */ jsx3(
838
+ /* @__PURE__ */ jsx2(
2438
839
  TreeActionButton,
2439
840
  {
2440
841
  disabled: activeAction !== null,
2441
842
  onClick: () => void handleCopy(),
2442
843
  title: "\u590D\u5236\u6587\u4EF6",
2443
- children: activeAction === "copy" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Copy, { size: 12 })
844
+ children: activeAction === "copy" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Copy, { size: 12 })
2444
845
  }
2445
846
  ),
2446
- /* @__PURE__ */ jsx3(
847
+ /* @__PURE__ */ jsx2(
2447
848
  TreeActionButton,
2448
849
  {
2449
850
  disabled: activeAction !== null || !onShareFile,
@@ -2460,25 +861,25 @@ function FileNode({
2460
861
  }
2461
862
  },
2462
863
  title: "\u5171\u4EAB\u5230 .share",
2463
- children: activeAction === "share" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Link2, { size: 12 })
864
+ children: activeAction === "share" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Link2, { size: 12 })
2464
865
  }
2465
866
  ),
2466
- /* @__PURE__ */ jsx3(
867
+ /* @__PURE__ */ jsx2(
2467
868
  TreeActionButton,
2468
869
  {
2469
870
  disabled: activeAction !== null,
2470
871
  onClick: () => void handleDelete(),
2471
872
  title: "\u5220\u9664\u6587\u4EF6",
2472
- children: activeAction === "delete" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Trash2, { size: 12 })
873
+ children: activeAction === "delete" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Trash2, { size: 12 })
2473
874
  }
2474
875
  )
2475
- ] }) : allowDelete ? /* @__PURE__ */ jsx3(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: /* @__PURE__ */ jsx3(
876
+ ] }) : allowDelete ? /* @__PURE__ */ jsx2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: /* @__PURE__ */ jsx2(
2476
877
  TreeActionButton,
2477
878
  {
2478
879
  disabled: activeAction !== null,
2479
880
  onClick: () => void handleDelete(),
2480
881
  title: "\u5220\u9664\u6587\u4EF6",
2481
- children: activeAction === "delete" ? /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Trash2, { size: 12 })
882
+ children: activeAction === "delete" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Trash2, { size: 12 })
2482
883
  }
2483
884
  ) }) : null
2484
885
  ] });
@@ -2509,18 +910,18 @@ function LazyDirChildren({
2509
910
  });
2510
911
  if (isLoading) {
2511
912
  return /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 px-2 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
2512
- /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "animate-spin" }),
2513
- /* @__PURE__ */ jsx3("span", { children: "\u52A0\u8F7D\u4E2D..." })
913
+ /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }),
914
+ /* @__PURE__ */ jsx2("span", { children: "\u52A0\u8F7D\u4E2D..." })
2514
915
  ] });
2515
916
  }
2516
917
  if (error) {
2517
- return /* @__PURE__ */ jsx3("div", { className: "px-2 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: error instanceof Error ? error.message : "\u52A0\u8F7D\u5931\u8D25" });
918
+ return /* @__PURE__ */ jsx2("div", { className: "px-2 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: error instanceof Error ? error.message : "\u52A0\u8F7D\u5931\u8D25" });
2518
919
  }
2519
920
  if (!entries || entries.length === 0) {
2520
- return /* @__PURE__ */ jsx3("div", { className: "px-2 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u7A7A\u76EE\u5F55" });
921
+ return /* @__PURE__ */ jsx2("div", { className: "px-2 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u7A7A\u76EE\u5F55" });
2521
922
  }
2522
- return /* @__PURE__ */ jsx3(Fragment2, { children: entries.map(
2523
- (child) => child.is_dir ? /* @__PURE__ */ jsx3(
923
+ return /* @__PURE__ */ jsx2(Fragment2, { children: entries.map(
924
+ (child) => child.is_dir ? /* @__PURE__ */ jsx2(
2524
925
  FolderNode,
2525
926
  {
2526
927
  entry: child,
@@ -2538,7 +939,7 @@ function LazyDirChildren({
2538
939
  allowDelete
2539
940
  },
2540
941
  child.path
2541
- ) : /* @__PURE__ */ jsx3(
942
+ ) : /* @__PURE__ */ jsx2(
2542
943
  FileNode,
2543
944
  {
2544
945
  entry: child,
@@ -2558,7 +959,7 @@ function LazyDirChildren({
2558
959
  }
2559
960
  function FileTagList({ tags }) {
2560
961
  if (!tags || tags.length === 0) return null;
2561
- return /* @__PURE__ */ jsx3("span", { className: "ml-2 flex min-w-0 shrink-0 items-center gap-1", children: tags.map((tag) => /* @__PURE__ */ jsx3(
962
+ return /* @__PURE__ */ jsx2("span", { className: "ml-2 flex min-w-0 shrink-0 items-center gap-1", children: tags.map((tag) => /* @__PURE__ */ jsx2(
2562
963
  "span",
2563
964
  {
2564
965
  className: "max-w-20 truncate rounded border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-1.5 py-0.5 text-[10px] leading-none text-[hsl(var(--muted-foreground))]",
@@ -2574,7 +975,7 @@ function TreeActionButton({
2574
975
  onClick,
2575
976
  title
2576
977
  }) {
2577
- return /* @__PURE__ */ jsx3(
978
+ return /* @__PURE__ */ jsx2(
2578
979
  "button",
2579
980
  {
2580
981
  type: "button",
@@ -2588,10 +989,10 @@ function TreeActionButton({
2588
989
  }
2589
990
  function EmptyState({ title, description }) {
2590
991
  return /* @__PURE__ */ jsxs2("div", { className: "flex h-full min-h-[12rem] flex-col items-center justify-center gap-3 px-6 text-center", children: [
2591
- /* @__PURE__ */ jsx3("div", { className: "flex h-10 w-10 items-center justify-center text-[hsl(var(--muted-foreground))]", children: getFolderIcon() }),
992
+ /* @__PURE__ */ jsx2("div", { className: "flex h-10 w-10 items-center justify-center text-[hsl(var(--muted-foreground))]", children: getFolderIcon() }),
2592
993
  /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
2593
- /* @__PURE__ */ jsx3("div", { className: "text-sm font-medium text-[hsl(var(--foreground))]", children: title }),
2594
- /* @__PURE__ */ jsx3("div", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: description })
994
+ /* @__PURE__ */ jsx2("div", { className: "text-sm font-medium text-[hsl(var(--foreground))]", children: title }),
995
+ /* @__PURE__ */ jsx2("div", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: description })
2595
996
  ] })
2596
997
  ] });
2597
998
  }
@@ -2599,13 +1000,13 @@ function getFileIcon(fileName) {
2599
1000
  const ext = fileName.split(".").pop()?.toLowerCase() ?? "";
2600
1001
  const group = FILE_ICON_GROUPS[ext];
2601
1002
  const src = group ? `/file-icons/${group}/${ext}.png` : "/file-icons/generic-file.png";
2602
- return /* @__PURE__ */ jsx3(FileTypeIcon, { src, alt: `${ext || "file"} \u6587\u4EF6` });
1003
+ return /* @__PURE__ */ jsx2(FileTypeIcon, { src, alt: `${ext || "file"} \u6587\u4EF6` });
2603
1004
  }
2604
1005
  function getFolderIcon() {
2605
- return /* @__PURE__ */ jsx3(FileTypeIcon, { src: "/file-icons/folder.png", alt: "\u6587\u4EF6\u5939" });
1006
+ return /* @__PURE__ */ jsx2(FileTypeIcon, { src: "/file-icons/folder.png", alt: "\u6587\u4EF6\u5939" });
2606
1007
  }
2607
1008
  function FileTypeIcon({ src, alt }) {
2608
- return /* @__PURE__ */ jsx3(
1009
+ return /* @__PURE__ */ jsx2(
2609
1010
  "img",
2610
1011
  {
2611
1012
  src,
@@ -2624,7 +1025,7 @@ function getErrorMessage(error, fallback) {
2624
1025
  }
2625
1026
 
2626
1027
  // src/react/components/workspace/WorkspaceFilesPanel.tsx
2627
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1028
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
2628
1029
  var EMPTY_MESSAGES = [];
2629
1030
  function WorkspaceFilesPanel({
2630
1031
  sessionId,
@@ -2659,7 +1060,7 @@ function WorkspaceFilesPanel({
2659
1060
  return [];
2660
1061
  }
2661
1062
  const ui = block.content;
2662
- const type3 = ui.resourceHTML ? "resource-html" : "resource-uri";
1063
+ const type = ui.resourceHTML ? "resource-html" : "resource-uri";
2663
1064
  const content = ui.resourceHTML ?? ui.resourceUri ?? ui.resourceURI ?? "";
2664
1065
  if (!content) return [];
2665
1066
  const title2 = ui.title ?? (typeof block.display_name === "string" && block.display_name.trim().length > 0 ? block.display_name : "\u53EF\u89C6\u5316\u4EA7\u7269");
@@ -2669,7 +1070,7 @@ function WorkspaceFilesPanel({
2669
1070
  key,
2670
1071
  title: title2,
2671
1072
  target: {
2672
- type: type3,
1073
+ type,
2673
1074
  content,
2674
1075
  title: title2,
2675
1076
  key,
@@ -2746,7 +1147,7 @@ function WorkspaceFilesPanel({
2746
1147
  folderInputRef.current?.click();
2747
1148
  };
2748
1149
  return /* @__PURE__ */ jsxs3("div", { className: cn("flex flex-col", className), children: [
2749
- topSlot ? /* @__PURE__ */ jsx4("div", { className: "mb-3", children: topSlot }) : null,
1150
+ topSlot ? /* @__PURE__ */ jsx3("div", { className: "mb-3", children: topSlot }) : null,
2750
1151
  /* @__PURE__ */ jsxs3("div", { className: "mb-2 flex shrink-0 items-center justify-between gap-2", children: [
2751
1152
  /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-1 rounded-lg bg-[hsl(var(--muted))]/60 p-0.5 text-[11px] font-medium", children: [
2752
1153
  /* @__PURE__ */ jsxs3(
@@ -2759,7 +1160,7 @@ function WorkspaceFilesPanel({
2759
1160
  activeTab === "files" ? "bg-[hsl(var(--background))] text-[hsl(var(--foreground))] shadow-sm" : "text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
2760
1161
  ),
2761
1162
  children: [
2762
- /* @__PURE__ */ jsx4(FolderTree, { size: 12 }),
1163
+ /* @__PURE__ */ jsx3(FolderTree, { size: 12 }),
2763
1164
  title
2764
1165
  ]
2765
1166
  }
@@ -2774,14 +1175,14 @@ function WorkspaceFilesPanel({
2774
1175
  activeTab === "resources" ? "bg-[hsl(var(--background))] text-[hsl(var(--foreground))] shadow-sm" : "text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
2775
1176
  ),
2776
1177
  children: [
2777
- /* @__PURE__ */ jsx4(PanelRightOpen, { size: 12 }),
1178
+ /* @__PURE__ */ jsx3(PanelRightOpen, { size: 12 }),
2778
1179
  "\u53EF\u89C6\u5316\u4EA7\u7269",
2779
- /* @__PURE__ */ jsx4("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: inlineResources.length })
1180
+ /* @__PURE__ */ jsx3("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: inlineResources.length })
2780
1181
  ]
2781
1182
  }
2782
1183
  ) : null
2783
1184
  ] }),
2784
- onSync ? /* @__PURE__ */ jsx4("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx4(
1185
+ onSync ? /* @__PURE__ */ jsx3("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx3(
2785
1186
  "button",
2786
1187
  {
2787
1188
  type: "button",
@@ -2800,11 +1201,11 @@ function WorkspaceFilesPanel({
2800
1201
  },
2801
1202
  className: "rounded p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted-foreground))/10] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50",
2802
1203
  title: "\u540C\u6B65\u5171\u4EAB\u533A",
2803
- children: isSyncing ? /* @__PURE__ */ jsx4(Loader22, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx4(RefreshCw, { size: 12 })
1204
+ children: isSyncing ? /* @__PURE__ */ jsx3(Loader22, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(RefreshCw, { size: 12 })
2804
1205
  }
2805
1206
  ) }) : null,
2806
1207
  !readOnly && activeTab === "files" ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
2807
- /* @__PURE__ */ jsx4(
1208
+ /* @__PURE__ */ jsx3(
2808
1209
  "button",
2809
1210
  {
2810
1211
  type: "button",
@@ -2812,10 +1213,10 @@ function WorkspaceFilesPanel({
2812
1213
  onClick: handleUploadClick,
2813
1214
  className: "rounded p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted-foreground))/10] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50",
2814
1215
  title: "\u4E0A\u4F20\u6587\u4EF6",
2815
- children: isUploading ? /* @__PURE__ */ jsx4(Loader22, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx4(Upload, { size: 12 })
1216
+ children: isUploading ? /* @__PURE__ */ jsx3(Loader22, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(Upload, { size: 12 })
2816
1217
  }
2817
1218
  ),
2818
- /* @__PURE__ */ jsx4(
1219
+ /* @__PURE__ */ jsx3(
2819
1220
  "button",
2820
1221
  {
2821
1222
  type: "button",
@@ -2823,12 +1224,12 @@ function WorkspaceFilesPanel({
2823
1224
  onClick: handleFolderUploadClick,
2824
1225
  className: "rounded p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted-foreground))/10] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50",
2825
1226
  title: "\u4E0A\u4F20\u6587\u4EF6\u5939",
2826
- children: isUploading ? /* @__PURE__ */ jsx4(Loader22, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx4(FolderUp, { size: 12 })
1227
+ children: isUploading ? /* @__PURE__ */ jsx3(Loader22, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx3(FolderUp, { size: 12 })
2827
1228
  }
2828
1229
  )
2829
1230
  ] }) : null
2830
1231
  ] }),
2831
- activeTab === "resources" && inlineResources.length > 0 ? /* @__PURE__ */ jsx4("div", { className: cn("min-h-0 overflow-auto", treeContainerClassName), children: /* @__PURE__ */ jsx4("div", { className: "flex flex-col gap-1.5", children: inlineResources.map((item, index) => /* @__PURE__ */ jsxs3(
1232
+ activeTab === "resources" && inlineResources.length > 0 ? /* @__PURE__ */ jsx3("div", { className: cn("min-h-0 overflow-auto", treeContainerClassName), children: /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-1.5", children: inlineResources.map((item, index) => /* @__PURE__ */ jsxs3(
2832
1233
  "button",
2833
1234
  {
2834
1235
  type: "button",
@@ -2836,13 +1237,13 @@ function WorkspaceFilesPanel({
2836
1237
  className: "group flex min-w-0 items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors hover:bg-[hsl(var(--muted))]",
2837
1238
  title: item.title,
2838
1239
  children: [
2839
- /* @__PURE__ */ jsx4(FileText, { size: 14, className: "shrink-0 text-[hsl(var(--primary))]" }),
2840
- /* @__PURE__ */ jsx4("span", { className: "min-w-0 flex-1 truncate text-[hsl(var(--foreground))]", children: item.title }),
2841
- /* @__PURE__ */ jsx4("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: index + 1 })
1240
+ /* @__PURE__ */ jsx3(FileText, { size: 14, className: "shrink-0 text-[hsl(var(--primary))]" }),
1241
+ /* @__PURE__ */ jsx3("span", { className: "min-w-0 flex-1 truncate text-[hsl(var(--foreground))]", children: item.title }),
1242
+ /* @__PURE__ */ jsx3("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: index + 1 })
2842
1243
  ]
2843
1244
  },
2844
1245
  item.key
2845
- )) }) }) : /* @__PURE__ */ jsx4("div", { className: treeContainerClassName, children: /* @__PURE__ */ jsx4(
1246
+ )) }) }) : /* @__PURE__ */ jsx3("div", { className: treeContainerClassName, children: /* @__PURE__ */ jsx3(
2846
1247
  FileTree2,
2847
1248
  {
2848
1249
  sessionId,
@@ -2856,7 +1257,7 @@ function WorkspaceFilesPanel({
2856
1257
  },
2857
1258
  sessionId ?? "workspace-empty"
2858
1259
  ) }),
2859
- /* @__PURE__ */ jsx4(
1260
+ /* @__PURE__ */ jsx3(
2860
1261
  "input",
2861
1262
  {
2862
1263
  ref: fileInputRef,
@@ -2866,7 +1267,7 @@ function WorkspaceFilesPanel({
2866
1267
  onChange: handleUploadChange
2867
1268
  }
2868
1269
  ),
2869
- /* @__PURE__ */ jsx4(
1270
+ /* @__PURE__ */ jsx3(
2870
1271
  "input",
2871
1272
  {
2872
1273
  ref: folderInputRef,