@blade-hq/agent-kit 0.4.4 → 0.4.6

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 (51) hide show
  1. package/README.md +8 -1
  2. package/dist/chunk-2UP7MG3J.js +66 -0
  3. package/dist/chunk-2UP7MG3J.js.map +1 -0
  4. package/dist/chunk-4VWLTG5L.js +2984 -0
  5. package/dist/chunk-4VWLTG5L.js.map +1 -0
  6. package/dist/chunk-7LEKQI47.js +32 -0
  7. package/dist/chunk-7LEKQI47.js.map +1 -0
  8. package/dist/chunk-DQCXSPHP.js +33 -0
  9. package/dist/chunk-DQCXSPHP.js.map +1 -0
  10. package/dist/chunk-I3FFV63W.js +30 -0
  11. package/dist/chunk-I3FFV63W.js.map +1 -0
  12. package/dist/chunk-J3XVFPOV.js +58 -0
  13. package/dist/chunk-J3XVFPOV.js.map +1 -0
  14. package/dist/chunk-JCJFFJ42.js +39 -0
  15. package/dist/chunk-JCJFFJ42.js.map +1 -0
  16. package/dist/chunk-LIL4FIZP.js +7992 -0
  17. package/dist/chunk-LIL4FIZP.js.map +1 -0
  18. package/dist/chunk-OKQWPNE3.js +1077 -0
  19. package/dist/chunk-OKQWPNE3.js.map +1 -0
  20. package/dist/chunk-PZ5AY32C.js +10 -0
  21. package/dist/chunk-PZ5AY32C.js.map +1 -0
  22. package/dist/chunk-TC5BBLWO.js +29 -0
  23. package/dist/chunk-TC5BBLWO.js.map +1 -0
  24. package/dist/chunk-VD4CKRMT.js +127 -0
  25. package/dist/chunk-VD4CKRMT.js.map +1 -0
  26. package/dist/chunk-X6MEYCU7.js +1401 -0
  27. package/dist/chunk-X6MEYCU7.js.map +1 -0
  28. package/dist/client/index.d.ts +529 -40
  29. package/dist/client/index.js +24 -1033
  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.js +28 -11366
  38. package/dist/react/components/chat/index.js.map +1 -1
  39. package/dist/react/components/plan/index.js +135 -3054
  40. package/dist/react/components/plan/index.js.map +1 -1
  41. package/dist/react/components/session/index.js +21 -1499
  42. package/dist/react/components/session/index.js.map +1 -1
  43. package/dist/react/components/workspace/index.js +116 -1715
  44. package/dist/react/components/workspace/index.js.map +1 -1
  45. package/dist/react/devtools/bridge-devtools/index.js +8 -51
  46. package/dist/react/devtools/bridge-devtools/index.js.map +1 -1
  47. package/dist/react/index.d.ts +74 -2
  48. package/dist/react/index.js +656 -13958
  49. package/dist/react/index.js.map +1 -1
  50. package/dist/style.css +2 -0
  51. package/package.json +5 -2
@@ -1,1486 +1,30 @@
1
- // src/client/resources/models.ts
2
- import { type } from "arktype";
3
- var ModelOption = type({
4
- id: "string",
5
- label: "string"
6
- });
7
- var ModelsConfig = type({
8
- default: "string",
9
- models: ModelOption.array()
10
- });
11
-
12
- // src/client/socket.ts
13
- import { io } from "socket.io-client";
14
-
15
- // src/react/schemas/partner-skill.ts
16
- import { type as type2 } from "arktype";
17
- var PartnerSkillName = type2("/^[a-z0-9-]+\\/[a-z0-9-]+$/");
18
- var PartnerSkillFile = type2({
19
- path: "string > 0",
20
- content: "string"
21
- });
22
- var PartnerSkillInstallPayload = type2({
23
- name: PartnerSkillName,
24
- files: PartnerSkillFile.array().atLeastLength(1)
25
- });
26
- var PartnerSkillInstallResult = type2({
27
- name: PartnerSkillName,
28
- skill_dir: "string",
29
- file_count: "number.integer >= 0",
30
- overwritten: "boolean"
31
- });
32
-
33
- // src/react/stores/ui-bridge-store.ts
34
- import { create } from "zustand";
35
-
36
- // src/react/stores/client-aware.ts
37
- function createClientActions(set) {
38
- return {
39
- _client: null,
40
- setClient: (client) => set({ _client: client })
41
- };
42
- }
43
-
44
- // src/react/stores/ui-bridge-store.ts
45
- function buildSignalId() {
46
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
47
- return crypto.randomUUID();
48
- }
49
- return `bridge-${Date.now()}-${Math.random().toString(36).slice(2)}`;
50
- }
51
- function clearSignalRecord(record, sessionId) {
52
- if (!(sessionId in record)) {
53
- return record;
54
- }
55
- const next = { ...record };
56
- delete next[sessionId];
57
- return next;
58
- }
59
- var useUiBridgeStore = create()((set, get) => ({
60
- ...createClientActions(set),
61
- pendingContexts: {},
62
- draftAppends: {},
63
- sendRequests: {},
64
- addPendingContext: (sessionId, context) => set((state) => ({
65
- pendingContexts: {
66
- ...state.pendingContexts,
67
- [sessionId]: [
68
- ...state.pendingContexts[sessionId] ?? [],
69
- {
70
- id: buildSignalId(),
71
- label: context.label,
72
- content: context.content
73
- }
74
- ]
75
- }
76
- })),
77
- removePendingContext: (sessionId, contextId) => set((state) => {
78
- const contexts = state.pendingContexts[sessionId];
79
- if (!contexts?.length) {
80
- return state;
81
- }
82
- const nextContexts = contexts.filter((context) => context.id !== contextId);
83
- if (nextContexts.length === contexts.length) {
84
- return state;
85
- }
86
- return {
87
- pendingContexts: nextContexts.length > 0 ? {
88
- ...state.pendingContexts,
89
- [sessionId]: nextContexts
90
- } : clearSignalRecord(state.pendingContexts, sessionId)
91
- };
92
- }),
93
- consumePendingContexts: (sessionId) => {
94
- const signals = get().pendingContexts[sessionId] ?? [];
95
- if (signals.length === 0) return [];
96
- set((state) => ({
97
- pendingContexts: clearSignalRecord(state.pendingContexts, sessionId)
98
- }));
99
- return signals;
100
- },
101
- clearPendingContexts: (sessionId) => set((state) => ({
102
- pendingContexts: clearSignalRecord(state.pendingContexts, sessionId)
103
- })),
104
- addDraftAppend: (sessionId, text) => set((state) => ({
105
- draftAppends: {
106
- ...state.draftAppends,
107
- [sessionId]: [
108
- ...state.draftAppends[sessionId] ?? [],
109
- {
110
- id: buildSignalId(),
111
- text
112
- }
113
- ]
114
- }
115
- })),
116
- consumeDraftAppends: (sessionId) => {
117
- const signals = get().draftAppends[sessionId] ?? [];
118
- if (signals.length === 0) return [];
119
- set((state) => ({
120
- draftAppends: clearSignalRecord(state.draftAppends, sessionId)
121
- }));
122
- return signals;
123
- },
124
- clearDraftAppends: (sessionId) => set((state) => ({
125
- draftAppends: clearSignalRecord(state.draftAppends, sessionId)
126
- })),
127
- addSendRequest: (sessionId) => set((state) => ({
128
- sendRequests: {
129
- ...state.sendRequests,
130
- [sessionId]: [
131
- ...state.sendRequests[sessionId] ?? [],
132
- {
133
- id: buildSignalId()
134
- }
135
- ]
136
- }
137
- })),
138
- consumeSendRequests: (sessionId) => {
139
- const signals = get().sendRequests[sessionId] ?? [];
140
- if (signals.length === 0) return [];
141
- set((state) => ({
142
- sendRequests: clearSignalRecord(state.sendRequests, sessionId)
143
- }));
144
- return signals;
145
- },
146
- clearSendRequests: (sessionId) => set((state) => ({
147
- sendRequests: clearSignalRecord(state.sendRequests, sessionId)
148
- })),
149
- clearSession: (sessionId) => set((state) => ({
150
- pendingContexts: clearSignalRecord(state.pendingContexts, sessionId),
151
- draftAppends: clearSignalRecord(state.draftAppends, sessionId),
152
- sendRequests: clearSignalRecord(state.sendRequests, sessionId)
153
- }))
154
- }));
155
-
156
- // src/react/lib/chat.ts
157
- function normalizeMessageContent(content) {
158
- if (typeof content === "string") return content;
159
- if (Array.isArray(content)) return content;
160
- return String(content ?? "");
161
- }
162
-
163
- // src/react/stores/auth-store.ts
164
- import { create as create6 } from "zustand";
165
- import { createJSONStorage, persist } from "zustand/middleware";
166
-
167
- // src/react/api/auth.ts
168
- var r = () => getClient().auth;
169
- var getMe = (...args) => r().getMe(...args);
170
- var logout = (...args) => r().logout(...args);
171
-
172
- // src/react/sockets/socket-state.ts
173
- var agentSocket = null;
174
-
175
- // src/react/stores/session-store.ts
176
- import { create as create5 } from "zustand";
177
-
178
- // src/react/api/sessions.ts
179
- var r2 = () => getClient().sessions;
180
- var listSessions = (...args) => r2().listSessions(...args);
181
- var createSession = (...args) => r2().createSession(...args);
182
- var getSession = (...args) => r2().getSession(...args);
183
- var pinSession = (...args) => r2().pinSession(...args);
184
- var updateSharing = (...args) => r2().updateSharing(...args);
185
- var getSessionTasks = (...args) => r2().getSessionTasks(...args);
186
- var getSessionTurns = (...args) => r2().getSessionTurns(...args);
187
- var deleteSession = (...args) => r2().deleteSession(...args);
188
-
189
- // src/react/stores/chat-store.ts
190
- import { create as create3 } from "zustand";
191
-
192
- // src/react/components/chat/display-utils.ts
193
- var TOOL_NAME_ALIASES = {
194
- agent: "Agent",
195
- ask_user_question: "AskUserQuestion",
196
- bash: "Bash",
197
- bg_bash: "BgBash",
198
- edit: "Edit",
199
- exit_plan_mode: "ExitPlanMode",
200
- file_edit: "Edit",
201
- file_read: "Read",
202
- file_write: "Write",
203
- finish_task: "FinishTask",
204
- get_skill_content: "GetSkillContent",
205
- glob: "Glob",
206
- grep: "Grep",
207
- list_skill_tools: "ListSkillTools",
208
- load_skill_tools: "LoadSkillTools",
209
- ls: "Ls",
210
- read: "Read",
211
- run_skill_tool: "RunSkillTool",
212
- search_skills: "SearchSkills",
213
- web_fetch: "WebFetch",
214
- web_search: "WebSearch",
215
- write: "Write"
216
- };
217
- var TOOL_DISPLAY_LABELS = {
218
- Bash: "\u6267\u884C\u547D\u4EE4",
219
- BgBash: "\u540E\u53F0\u6267\u884C\u547D\u4EE4",
220
- Read: "\u8BFB\u53D6\u6587\u4EF6",
221
- Write: "\u5199\u5165\u6587\u4EF6",
222
- Edit: "\u7F16\u8F91\u6587\u4EF6",
223
- Ls: "\u5217\u51FA\u76EE\u5F55",
224
- Glob: "\u5339\u914D\u6587\u4EF6",
225
- Grep: "\u641C\u7D22\u6587\u672C",
226
- WebSearch: "\u641C\u7D22\u7F51\u9875",
227
- WebFetch: "\u6574\u7406\u7F51\u9875\u5185\u5BB9",
228
- Agent: "\u6D3E\u751F\u5B50\u667A\u80FD\u4F53",
229
- AskUserQuestion: "\u5411\u7528\u6237\u63D0\u95EE",
230
- SearchSkills: "\u641C\u7D22\u6280\u80FD",
231
- GetSkillContent: "\u8BFB\u53D6\u6280\u80FD",
232
- ListSkillTools: "\u67E5\u770B\u5DE5\u5177\u5217\u8868",
233
- LoadSkillTools: "\u52A0\u8F7D\u6280\u80FD",
234
- RunSkillTool: "\u6267\u884C\u6280\u80FD\u5DE5\u5177",
235
- FinishTask: "\u4EFB\u52A1\u5B8C\u6210",
236
- ExitPlanMode: "\u63D0\u4EA4\u8BA1\u5212",
237
- ListSessions: "\u5217\u51FA\u5386\u53F2\u4F1A\u8BDD",
238
- GetSessionHistory: "\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2"
239
- };
240
- var GENERIC_DISPLAY_NAMES = new Set(Object.values(TOOL_DISPLAY_LABELS));
241
- function formatToolName(name) {
242
- const trimmed = name.trim();
243
- if (!trimmed) return name;
244
- const stripped = trimmed.split(":").pop()?.split("/").pop()?.split(".").pop()?.trim() || trimmed;
245
- const normalized = stripped.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
246
- return TOOL_NAME_ALIASES[normalized] ?? stripped;
247
- }
248
-
249
- // src/react/stores/ui-store.ts
250
- import { create as create2 } from "zustand";
251
- var isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
252
- function resolveEffectiveTheme(theme) {
253
- if (theme !== "system") return theme;
254
- return isBrowser && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
255
- }
256
- function applyTheme(theme) {
257
- if (!isBrowser) return;
258
- const effective = resolveEffectiveTheme(theme);
259
- document.documentElement.setAttribute("data-theme", effective);
260
- }
261
- var storedTheme = isBrowser ? localStorage.getItem("blade-theme") ?? "light" : "light";
262
- applyTheme(storedTheme);
263
- if (isBrowser) {
264
- window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
265
- const current = useUiStore?.getState?.()?.theme;
266
- if (current === "system") applyTheme("system");
267
- });
268
- }
269
- function removeArtifactAtIndex(state, index) {
270
- const next = state.artifacts.filter((_, i) => i !== index);
271
- let nextActive = state.activeArtifactIndex;
272
- if (next.length === 0) {
273
- return { artifacts: [], activeArtifactIndex: -1, rightPanelCollapsed: true };
274
- }
275
- if (index < nextActive) {
276
- nextActive -= 1;
277
- } else if (index === nextActive) {
278
- nextActive = Math.min(index, next.length - 1);
279
- }
280
- return { artifacts: next, activeArtifactIndex: nextActive };
281
- }
282
- function upsertArtifactState(state, target, options) {
283
- const reveal = options?.reveal ?? true;
284
- const activate = options?.activate ?? true;
285
- const targetKey = target.key ?? target.title;
286
- const applyUiState = (partial) => ({
287
- ...partial,
288
- ...reveal ? { rightPanelCollapsed: false, activeRightTab: "preview" } : {}
289
- });
290
- const existing = state.artifacts.findIndex((artifact) => targetKey && (artifact.key ?? artifact.title) === targetKey);
291
- if (existing >= 0) {
292
- const updated = [...state.artifacts];
293
- updated[existing] = target;
294
- return applyUiState({
295
- artifacts: updated,
296
- activeArtifactIndex: activate ? existing : state.activeArtifactIndex
297
- });
298
- }
299
- const next = [...state.artifacts, target];
300
- return applyUiState({
301
- artifacts: next,
302
- activeArtifactIndex: activate ? next.length - 1 : state.activeArtifactIndex >= 0 ? state.activeArtifactIndex : 0
303
- });
304
- }
305
- var useUiStore = create2()((set) => ({
306
- ...createClientActions(set),
307
- leftPanelSize: 20,
308
- rightPanelSize: 25,
309
- leftPanelCollapsed: false,
310
- rightPanelCollapsed: false,
311
- activeRightTab: "situation",
312
- artifacts: [],
313
- activeArtifactIndex: -1,
314
- theme: storedTheme,
315
- setLeftPanelSize: (size) => set({ leftPanelSize: size }),
316
- setRightPanelSize: (size) => set({ rightPanelSize: size }),
317
- setLeftPanelCollapsed: (collapsed) => set({ leftPanelCollapsed: collapsed }),
318
- setRightPanelCollapsed: (collapsed) => set({ rightPanelCollapsed: collapsed }),
319
- toggleLeftPanel: () => set((s) => ({ leftPanelCollapsed: !s.leftPanelCollapsed })),
320
- toggleRightPanel: () => set((s) => ({ rightPanelCollapsed: !s.rightPanelCollapsed })),
321
- setActiveRightTab: (tab) => set({ activeRightTab: tab }),
322
- pushArtifact: (target) => set((state) => upsertArtifactState(state, target)),
323
- upsertArtifact: (target, options) => set((state) => upsertArtifactState(state, target, options)),
324
- setActiveArtifact: (index) => set({ activeArtifactIndex: index }),
325
- closeArtifact: (index) => set((state) => removeArtifactAtIndex(state, index)),
326
- removeArtifactByKey: (key) => set((state) => {
327
- const index = state.artifacts.findIndex((artifact) => (artifact.key ?? artifact.title) === key);
328
- if (index < 0) return state;
329
- return removeArtifactAtIndex(state, index);
330
- }),
331
- clearArtifacts: () => set({ artifacts: [], activeArtifactIndex: -1 }),
332
- setPreviewTarget: (target) => set(() => {
333
- if (target === null) {
334
- return { artifacts: [], activeArtifactIndex: -1 };
335
- }
336
- return {
337
- artifacts: [target],
338
- activeArtifactIndex: 0,
339
- rightPanelCollapsed: false,
340
- activeRightTab: "preview"
341
- };
342
- }),
343
- setTheme: (theme) => {
344
- localStorage.setItem("blade-theme", theme);
345
- applyTheme(theme);
346
- set({ theme });
347
- }
348
- }));
349
-
350
- // src/react/stores/chat-store.ts
351
- var _getActiveSessionId = null;
352
- function setChatStoreSessionAccessor(fn) {
353
- _getActiveSessionId = fn;
354
- }
355
- function parseAgentDescription(argumentsJson) {
356
- try {
357
- return JSON.parse(argumentsJson)?.description ?? "\u5B50\u667A\u80FD\u4F53";
358
- } catch {
359
- return "\u5B50\u667A\u80FD\u4F53";
360
- }
361
- }
362
- function inferLoopStatusFromMessages(messages) {
363
- const toolCalls = messages.flatMap((message) => message.tool_calls ?? []);
364
- if (messages.some((message) => message.status === "streaming")) return "running";
365
- if (toolCalls.some((toolCall) => toolCall.status === "awaiting_answer")) return "awaiting_answer";
366
- if (toolCalls.some((toolCall) => toolCall.status === "error")) return "error";
367
- if (toolCalls.some((toolCall) => toolCall.status === "cancelled")) return "cancelled";
368
- if (toolCalls.some((toolCall) => toolCall.status === "pending")) return "running";
369
- return "done";
370
- }
371
- function inferLoopStatusFromTurns(turns, messages) {
372
- const latestAgentNotification = [...turns].reverse().flatMap((turn) => turn.blocks).find((block) => {
373
- if (block.type !== "system_notification" || !isRecord(block.content)) return false;
374
- return block.content.notification_type === "agent:start" || block.content.notification_type === "agent:end";
375
- });
376
- if (latestAgentNotification?.type === "system_notification" && isRecord(latestAgentNotification.content)) {
377
- const notificationType = latestAgentNotification.content.notification_type;
378
- const status = latestAgentNotification.content.status;
379
- if (notificationType === "agent:start" || status === "running") return "running";
380
- if (status === "error") return "error";
381
- if (status === "cancelled") return "cancelled";
382
- }
383
- return inferLoopStatusFromMessages(messages);
384
- }
385
- function isRecord(value) {
386
- return typeof value === "object" && value !== null && !Array.isArray(value);
387
- }
388
- function parentForkToolCallIdFromTurn(turn) {
389
- if (typeof turn.parent_fork_tool_call_id === "string" && turn.parent_fork_tool_call_id.length > 0) {
390
- return turn.parent_fork_tool_call_id;
391
- }
392
- for (const block of turn.blocks) {
393
- if (block.type !== "system_notification" || !isRecord(block.content)) continue;
394
- const metadata = block.content.metadata;
395
- if (!isRecord(metadata)) continue;
396
- const parentId = metadata.parent_fork_tool_call_id;
397
- if (typeof parentId === "string" && parentId.length > 0) return parentId;
398
- }
399
- return null;
400
- }
401
- function buildMessageContent(turn) {
402
- const textBlocks = turn.blocks.filter((block) => block.type === "text");
403
- if (textBlocks.length === 0) return "";
404
- if (textBlocks.length === 1) return normalizeMessageContent(textBlocks[0].content);
405
- return textBlocks.map((block) => {
406
- if (typeof block.content === "string") return block.content;
407
- return JSON.stringify(block.content);
408
- }).join("");
409
- }
410
- function buildReasoning(turn) {
411
- const thinking = turn.blocks.filter((block) => block.type === "thinking").map((block) => typeof block.content === "string" ? block.content : JSON.stringify(block.content)).filter(Boolean);
412
- if (thinking.length === 0) return void 0;
413
- return thinking.join("\n\n");
414
- }
415
- function isModeChangeContent(value) {
416
- return typeof value === "object" && value !== null && typeof value.from === "string" && typeof value.to === "string";
417
- }
418
- function extractModeFromBlocks(blocks) {
419
- const modeBlock = blocks.find((block) => block.type === "mode_change");
420
- if (modeBlock && isModeChangeContent(modeBlock.content)) {
421
- return modeBlock.content.to === "planning" || modeBlock.content.to === "executing" ? modeBlock.content.to : null;
422
- }
423
- if (blocks.some((block) => block.type === "planning_enter")) return "planning";
424
- if (blocks.some((block) => block.type === "planning_exit")) return "executing";
425
- return null;
426
- }
427
- function projectionToMessage(turn) {
428
- if (turn.kind === "compaction" && turn.compaction_id) {
429
- return {
430
- role: "assistant",
431
- content: turn.summary_preview ?? "",
432
- kind: "compaction",
433
- loop_name: turn.loop_id,
434
- entry_id: turn.turn_id,
435
- status: turn.status,
436
- compaction: {
437
- compaction_id: turn.compaction_id,
438
- summary_preview: turn.summary_preview,
439
- summary_full: turn.summary_full,
440
- archived_count: turn.archived_count,
441
- archived_files: turn.archived_files,
442
- archived_tool_calls: turn.archived_tool_calls,
443
- tokens_before: turn.tokens_before,
444
- tokens_after: turn.tokens_after,
445
- saved_ratio: turn.saved_ratio,
446
- trigger: turn.trigger,
447
- failure_reason: turn.failure_reason,
448
- fallback_applied: turn.fallback_applied
449
- }
450
- };
451
- }
452
- const planningBlock = turn.blocks.find(
453
- (block) => block.type === "mode_change" || block.type === "planning_enter" || block.type === "planning_exit" || block.type === "plan_status"
454
- );
455
- if (planningBlock) {
456
- if (planningBlock.type === "plan_status") {
457
- return {
458
- role: "tool",
459
- content: typeof planningBlock.content === "string" ? planningBlock.content : JSON.stringify(planningBlock.content ?? {}, null, 2),
460
- kind: "plan_status",
461
- loop_name: turn.loop_id,
462
- entry_id: turn.turn_id,
463
- status: turn.status
464
- };
465
- }
466
- return {
467
- role: "assistant",
468
- content: planningBlock.type === "mode_change" ? typeof planningBlock.content === "string" ? planningBlock.content : JSON.stringify(planningBlock.content ?? {}) : "",
469
- kind: planningBlock.type,
470
- loop_name: turn.loop_id,
471
- entry_id: turn.turn_id,
472
- status: turn.status
473
- };
474
- }
475
- if (turn.blocks.some((block) => block.type === "ask_user_answer")) {
476
- return null;
477
- }
478
- const content = buildMessageContent(turn);
479
- const reasoning = buildReasoning(turn);
480
- const toolCalls = turn.tool_calls.length > 0 ? turn.tool_calls.map((toolCall) => ({
481
- id: toolCall.id,
482
- name: toolCall.tool_name,
483
- display_name: toolCall.display_name,
484
- arguments: toolCall.arguments,
485
- result: toolCall.result ?? void 0,
486
- pending_question_ref: toolCall.pending_question_ref ?? void 0,
487
- status: toolCall.status === "pending" || toolCall.status === "awaiting_answer" || toolCall.status === "done" || toolCall.status === "error" || toolCall.status === "cancelled" ? toolCall.status : "pending",
488
- ...typeof toolCall.duration_ms === "number" ? { duration_ms: toolCall.duration_ms } : {}
489
- })) : void 0;
490
- if (turn.role === "system" && !content && !toolCalls?.length) {
491
- return null;
492
- }
493
- return {
494
- role: turn.role === "system" ? "assistant" : turn.role,
495
- content,
496
- blocks: turn.blocks,
497
- ...reasoning ? { reasoning } : {},
498
- ...toolCalls ? { tool_calls: toolCalls } : {},
499
- loop_name: turn.loop_id,
500
- entry_id: turn.turn_id,
501
- status: turn.status,
502
- ...typeof turn.duration_ms === "number" ? { duration_ms: turn.duration_ms } : {},
503
- ...turn.started_at ? { timestamp: turn.started_at } : {},
504
- ...turn.memory_refs?.length ? { memory_refs: turn.memory_refs } : {}
505
- };
506
- }
507
- function rebuildAgentLoops(turns) {
508
- const messages = turns.map(projectionToMessage).filter(Boolean);
509
- const childLoopNames = [...new Set(turns.map((turn) => turn.loop_id).filter((name) => name !== "root"))];
510
- if (childLoopNames.length === 0) return {};
511
- const agentToolCalls = messages.filter((message) => message.role === "assistant" && (message.loop_name ?? "root") === "root").flatMap((message) => message.tool_calls ?? []).filter((toolCall) => formatToolName(toolCall.name) === "Agent");
512
- const loops = {};
513
- const agentToolCallsById = new Map(agentToolCalls.map((toolCall) => [toolCall.id, toolCall]));
514
- const explicitParentToolCallIds = new Set(
515
- turns.map(parentForkToolCallIdFromTurn).filter((id) => id !== null)
516
- );
517
- const usedToolCallIds = /* @__PURE__ */ new Set();
518
- for (const loopName of childLoopNames) {
519
- const loopMessages = messages.filter((message) => (message.loop_name ?? "root") === loopName);
520
- const loopTurns = turns.filter((turn) => turn.loop_id === loopName);
521
- const parentToolCallId = loopTurns.map(parentForkToolCallIdFromTurn).find(Boolean);
522
- const explicitToolCall = parentToolCallId && !usedToolCallIds.has(parentToolCallId) ? agentToolCallsById.get(parentToolCallId) ?? null : null;
523
- const fallbackToolCall = explicitToolCall === null ? agentToolCalls.find(
524
- (toolCall2) => !usedToolCallIds.has(toolCall2.id) && !explicitParentToolCallIds.has(toolCall2.id)
525
- ) : null;
526
- const toolCall = explicitToolCall ?? fallbackToolCall;
527
- if (!toolCall) continue;
528
- usedToolCallIds.add(toolCall.id);
529
- loops[loopName] = {
530
- toolCallId: toolCall.id,
531
- description: parseAgentDescription(toolCall.arguments),
532
- status: inferLoopStatusFromTurns(loopTurns, loopMessages)
533
- };
534
- }
535
- return loops;
536
- }
537
- function applyPlanningSideEffects(sessionId, turns) {
538
- const latestMode = [...turns].reverse().map((turn) => extractModeFromBlocks(turn.blocks)).find((mode) => mode !== null);
539
- if (latestMode !== "planning") return;
540
- if (_getActiveSessionId?.() !== sessionId) return;
541
- const ui = useUiStore.getState();
542
- ui.setActiveRightTab("situation");
543
- if (ui.rightPanelCollapsed) {
544
- ui.toggleRightPanel();
545
- }
546
- }
547
- function materialize(turns) {
548
- const messages = turns.map(projectionToMessage).filter((message) => message !== null);
549
- const activeCompaction = [...turns].reverse().find(
550
- (turn) => turn.kind === "compaction" && turn.status === "streaming" && typeof turn.compaction_id === "string"
551
- );
552
- return {
553
- messages,
554
- agentLoops: rebuildAgentLoops(turns),
555
- activeCompaction: activeCompaction ? {
556
- turn_id: activeCompaction.turn_id,
557
- status: activeCompaction.status,
558
- compaction_id: activeCompaction.compaction_id,
559
- summary_preview: activeCompaction.summary_preview,
560
- summary_full: activeCompaction.summary_full,
561
- archived_count: activeCompaction.archived_count,
562
- archived_files: activeCompaction.archived_files,
563
- archived_tool_calls: activeCompaction.archived_tool_calls,
564
- tokens_before: activeCompaction.tokens_before,
565
- tokens_after: activeCompaction.tokens_after,
566
- saved_ratio: activeCompaction.saved_ratio,
567
- trigger: activeCompaction.trigger,
568
- failure_reason: activeCompaction.failure_reason,
569
- fallback_applied: activeCompaction.fallback_applied
570
- } : null
571
- };
572
- }
573
- var ERROR_ANCHOR_PREFIX = "error-anchor:";
574
- function updateSessionState(state, sessionId, turns) {
575
- const orderedTurns = [...turns].sort((left, right) => left.sequence - right.sequence);
576
- const { messages, agentLoops, activeCompaction } = materialize(orderedTurns);
577
- applyPlanningSideEffects(sessionId, orderedTurns);
578
- const lastTurnId = orderedTurns[orderedTurns.length - 1]?.turn_id ?? null;
579
- const preservedErrors = lastTurnId ? (state.messages[sessionId] ?? []).filter(
580
- (m) => m.role === "error" && typeof m.entry_id === "string" && m.entry_id.startsWith(`${ERROR_ANCHOR_PREFIX}${lastTurnId}:`)
581
- ) : [];
582
- const mergedMessages = preservedErrors.length > 0 ? [...messages, ...preservedErrors] : messages;
583
- return {
584
- turns: { ...state.turns, [sessionId]: orderedTurns },
585
- messages: { ...state.messages, [sessionId]: mergedMessages },
586
- agentLoops: { ...state.agentLoops, [sessionId]: agentLoops },
587
- activeCompactions: { ...state.activeCompactions, [sessionId]: activeCompaction }
588
- };
589
- }
590
- var useChatStore = create3()((set) => ({
591
- ...createClientActions(set),
592
- turns: {},
593
- messages: {},
594
- askAnswers: {},
595
- isStreaming: {},
596
- agentLoops: {},
597
- activeCompactions: {},
598
- addUserMessage: (sessionId, content) => {
599
- set((state) => {
600
- const existing = state.turns[sessionId] ?? [];
601
- const turnId = `local-user-${Date.now()}`;
602
- const optimisticTurn = {
603
- id: turnId,
604
- sequence: Math.max(0, ...existing.map((turn) => turn.sequence)) + 1,
605
- turn_id: turnId,
606
- loop_id: "root",
607
- role: "user",
608
- status: "completed",
609
- blocks: [{ type: "text", content }],
610
- tool_calls: [],
611
- model: null,
612
- usage: null,
613
- duration_ms: 0
614
- };
615
- return updateSessionState(state, sessionId, [...existing, optimisticTurn]);
616
- });
617
- },
618
- setTurns: (sessionId, turns) => {
619
- set((state) => updateSessionState(state, sessionId, [...turns]));
620
- },
621
- upsertTurn: (sessionId, turn) => {
622
- set((state) => {
623
- const existing = [...state.turns[sessionId] ?? []];
624
- const index = existing.findIndex((item) => item.turn_id === turn.turn_id);
625
- if (index >= 0) {
626
- existing[index] = turn;
627
- } else {
628
- existing.push(turn);
629
- }
630
- return {
631
- ...updateSessionState(state, sessionId, existing)
632
- };
633
- });
634
- },
635
- applyTurnPatch: (sessionId, patch) => {
636
- set((state) => {
637
- const turn = patch.data.turn;
638
- if (!turn) return state;
639
- const existing = [...state.turns[sessionId] ?? []];
640
- const index = existing.findIndex((item) => item.turn_id === turn.turn_id);
641
- const lastSequence = index >= 0 ? existing[index].sequence : null;
642
- if (lastSequence !== null && patch.sequence <= lastSequence) {
643
- return state;
644
- }
645
- const nextTurn = {
646
- ...turn,
647
- sequence: patch.sequence
648
- };
649
- if (index >= 0) {
650
- existing[index] = nextTurn;
651
- } else {
652
- existing.push(nextTurn);
653
- }
654
- return {
655
- ...updateSessionState(state, sessionId, existing)
656
- };
657
- });
658
- },
659
- addErrorMessage: (sessionId, content) => {
660
- set((state) => {
661
- const turns = state.turns[sessionId] ?? [];
662
- const anchorTurnId = turns[turns.length - 1]?.turn_id ?? null;
663
- const entry_id = anchorTurnId ? `${ERROR_ANCHOR_PREFIX}${anchorTurnId}:${Date.now()}` : void 0;
664
- return {
665
- messages: {
666
- ...state.messages,
667
- [sessionId]: [
668
- ...state.messages[sessionId] ?? [],
669
- { role: "error", content, loop_name: "root", entry_id }
670
- ]
671
- }
672
- };
673
- });
674
- },
675
- markInterrupted: (sessionId) => {
676
- set((state) => {
677
- const turns = (state.turns[sessionId] ?? []).map((turn) => {
678
- if (turn.status !== "streaming") return turn;
679
- return {
680
- ...turn,
681
- status: "interrupted",
682
- tool_calls: turn.tool_calls.map(
683
- (toolCall) => toolCall.status === "pending" || toolCall.status === "awaiting_answer" ? { ...toolCall, status: "cancelled" } : toolCall
684
- )
685
- };
686
- });
687
- return {
688
- ...updateSessionState(state, sessionId, turns)
689
- };
690
- });
691
- },
692
- markFailed: (sessionId) => {
693
- set((state) => {
694
- const turns = (state.turns[sessionId] ?? []).map((turn) => {
695
- if (turn.status !== "streaming") return turn;
696
- return {
697
- ...turn,
698
- status: "failed",
699
- tool_calls: turn.tool_calls.map(
700
- (toolCall) => toolCall.status === "pending" || toolCall.status === "awaiting_answer" ? { ...toolCall, status: "error" } : toolCall
701
- )
702
- };
703
- });
704
- return {
705
- ...updateSessionState(state, sessionId, turns)
706
- };
707
- });
708
- },
709
- setStreaming: (sessionId, streaming) => {
710
- set((state) => ({
711
- isStreaming: { ...state.isStreaming, [sessionId]: streaming }
712
- }));
713
- },
714
- setAskAnswers: (sessionId, answers) => {
715
- set((state) => ({
716
- askAnswers: {
717
- ...state.askAnswers,
718
- [sessionId]: answers
719
- }
720
- }));
721
- },
722
- clearMessages: (sessionId) => {
723
- set((state) => {
724
- const { [sessionId]: _turns, ...restTurns } = state.turns;
725
- const { [sessionId]: _messages, ...restMessages } = state.messages;
726
- const { [sessionId]: _answers, ...restAnswers } = state.askAnswers;
727
- const { [sessionId]: _loops, ...restLoops } = state.agentLoops;
728
- const { [sessionId]: _compaction, ...restCompactions } = state.activeCompactions;
729
- return {
730
- turns: restTurns,
731
- messages: restMessages,
732
- askAnswers: restAnswers,
733
- agentLoops: restLoops,
734
- activeCompactions: restCompactions
735
- };
736
- });
737
- }
738
- }));
739
-
740
- // src/react/stores/task-store.ts
741
- import { create as create4 } from "zustand";
742
- var EMPTY_TASKS = [];
743
- var useTaskStore = create4()((set, get) => ({
744
- ...createClientActions(set),
745
- tasks: {},
746
- setTasks: (sessionId, tasks) => {
747
- set((state) => ({
748
- tasks: { ...state.tasks, [sessionId]: tasks }
749
- }));
750
- },
751
- getTasks: (sessionId) => {
752
- return get().tasks[sessionId] ?? EMPTY_TASKS;
753
- }
754
- }));
755
-
756
- // src/react/stores/session-store.ts
757
- var DEFAULT_SESSION_MODE = "executing";
758
- var onSessionChange = null;
759
- function invalidateHomeSidebarSessions() {
760
- const queryClient = globalThis.__agentQueryClient;
761
- if (!queryClient) return;
762
- void queryClient.invalidateQueries({ queryKey: ["sessions", "home-sidebar"] });
763
- }
764
- function isSessionAccessRevoked(error) {
765
- if (error instanceof Error) {
766
- const msg = error.message;
767
- return msg.includes("API 403") || msg.includes("API 404");
768
- }
769
- return false;
770
- }
771
- function removeSessionArtifacts(sessionId) {
772
- useChatStore.getState().clearMessages(sessionId);
773
- useTaskStore.getState().setTasks(sessionId, []);
774
- }
775
- function pruneSessionState(state, sessionId) {
776
- const nextFresh = new Set(state._freshSessions);
777
- nextFresh.delete(sessionId);
778
- const { [sessionId]: _mode, ...modes } = state.modes;
779
- const { [sessionId]: _rewindDraft, ...rewindDrafts } = state.rewindDrafts;
780
- return {
781
- sessions: state.sessions.filter((session) => session.id !== sessionId),
782
- activeSessionId: state.activeSessionId === sessionId ? null : state.activeSessionId,
783
- modes,
784
- rewindDrafts,
785
- _freshSessions: nextFresh
786
- };
787
- }
788
- function navigateAwayFromSession(sessionId) {
789
- if (typeof window === "undefined") return;
790
- if (window.location.pathname !== `/chat/${sessionId}`) return;
791
- window.history.replaceState(window.history.state, "", "/chat");
792
- window.dispatchEvent(new PopStateEvent("popstate"));
793
- }
794
- function handleUnreadableSession(set, get, sessionId) {
795
- const wasActive = get().activeSessionId === sessionId;
796
- removeSessionArtifacts(sessionId);
797
- set((state) => pruneSessionState(state, sessionId));
798
- if (wasActive) {
799
- onSessionChange?.(null);
800
- navigateAwayFromSession(sessionId);
801
- }
802
- invalidateHomeSidebarSessions();
803
- }
804
- function isPlainRecord(value) {
805
- return typeof value === "object" && value !== null && !Array.isArray(value);
806
- }
807
- function extractModeFromBlocks2(blocks) {
808
- const modeBlock = blocks.find((block) => block.type === "mode_change");
809
- if (modeBlock && isPlainRecord(modeBlock.content) && (modeBlock.content.to === "planning" || modeBlock.content.to === "executing")) {
810
- return modeBlock.content.to;
811
- }
812
- if (blocks.some((block) => block.type === "planning_enter")) return "planning";
813
- if (blocks.some((block) => block.type === "planning_exit")) return "executing";
814
- return null;
815
- }
816
- function toSelectionMap(value) {
817
- if (!isPlainRecord(value)) return {};
818
- const entries = Object.entries(value).map(([questionKey, optionIndexes]) => {
819
- if (!Array.isArray(optionIndexes)) return null;
820
- const parsedIndexes = optionIndexes.map((item) => typeof item === "number" ? item : Number(item)).filter((item) => Number.isInteger(item));
821
- return [Number(questionKey), parsedIndexes];
822
- }).filter((entry) => entry !== null);
823
- return Object.fromEntries(entries);
824
- }
825
- function toCustomMap(value) {
826
- if (!isPlainRecord(value)) return {};
827
- const entries = Object.entries(value).filter(([, text]) => typeof text === "string").map(([questionKey, text]) => [Number(questionKey), text]);
828
- return Object.fromEntries(entries);
829
- }
830
- function extractAskAnswers(turns) {
831
- const answers = {};
832
- for (const turn of turns) {
833
- for (const block of turn.blocks) {
834
- if (block.type !== "ask_user_answer" || typeof block.tool_call_id !== "string") continue;
835
- answers[block.tool_call_id] = {
836
- selections: toSelectionMap(isPlainRecord(block.content) ? block.content.selections : void 0),
837
- custom: toCustomMap(isPlainRecord(block.content) ? block.content.custom : void 0)
838
- };
839
- }
840
- }
841
- return answers;
842
- }
843
- function registerCreatedSessionState(set, session, mode = DEFAULT_SESSION_MODE) {
844
- useChatStore.getState().setTurns(session.id, []);
845
- useTaskStore.getState().setTasks(session.id, []);
846
- set((state) => ({
847
- sessions: [session, ...state.sessions.filter((item) => item.id !== session.id)],
848
- modes: { ...state.modes, [session.id]: state.modes[session.id] ?? mode },
849
- _freshSessions: new Set(state._freshSessions).add(session.id)
850
- }));
851
- }
852
- async function revalidateViewerSessions(existingSessions) {
853
- const viewerSessions = existingSessions.filter((session) => session.viewer_role === "viewer");
854
- if (viewerSessions.length === 0) {
855
- return [];
856
- }
857
- const refreshed = await Promise.all(
858
- viewerSessions.map(async (session) => {
859
- try {
860
- return await getSession(session.id);
861
- } catch (error) {
862
- if (isSessionAccessRevoked(error)) {
863
- return null;
864
- }
865
- return session;
866
- }
867
- })
868
- );
869
- return refreshed.filter((session) => session !== null);
870
- }
871
- var useSessionStore = create5()((set, get) => ({
872
- ...createClientActions(set),
873
- sessions: [],
874
- activeSessionId: null,
875
- loading: false,
876
- modes: {},
877
- rewindDrafts: {},
878
- _freshSessions: /* @__PURE__ */ new Set(),
879
- fetchSessions: async () => {
880
- set({ loading: true });
881
- try {
882
- const currentState = get();
883
- const [sessions, viewerSessions] = await Promise.all([
884
- listSessions(),
885
- revalidateViewerSessions(currentState.sessions)
886
- ]);
887
- const knownSessionIds = new Set(sessions.map((session) => session.id));
888
- const mergedSessions = [
889
- ...sessions,
890
- ...viewerSessions.filter((session) => !knownSessionIds.has(session.id))
891
- ];
892
- const removedSessionIds = currentState.sessions.filter(
893
- (session) => session.viewer_role === "viewer" && !mergedSessions.some((candidate) => candidate.id === session.id)
894
- ).map((session) => session.id);
895
- const activeSessionId = currentState.activeSessionId;
896
- for (const sessionId of removedSessionIds) {
897
- removeSessionArtifacts(sessionId);
898
- }
899
- let nextState = {
900
- sessions: mergedSessions,
901
- activeSessionId: currentState.activeSessionId,
902
- loading: false,
903
- modes: currentState.modes,
904
- rewindDrafts: currentState.rewindDrafts,
905
- _freshSessions: currentState._freshSessions
906
- };
907
- for (const sessionId of removedSessionIds) {
908
- nextState = {
909
- ...nextState,
910
- ...pruneSessionState(
911
- {
912
- ...currentState,
913
- sessions: nextState.sessions ?? currentState.sessions,
914
- activeSessionId: nextState.activeSessionId ?? currentState.activeSessionId,
915
- loading: nextState.loading ?? currentState.loading,
916
- modes: nextState.modes ?? currentState.modes,
917
- rewindDrafts: nextState.rewindDrafts ?? currentState.rewindDrafts,
918
- _freshSessions: nextState._freshSessions ?? currentState._freshSessions
919
- },
920
- sessionId
921
- )
922
- };
923
- }
924
- set(nextState);
925
- if (activeSessionId && removedSessionIds.includes(activeSessionId)) {
926
- onSessionChange?.(null);
927
- navigateAwayFromSession(activeSessionId);
928
- }
929
- invalidateHomeSidebarSessions();
930
- } catch (error) {
931
- set({ loading: false });
932
- throw error;
933
- }
934
- },
935
- createSession: async (intent) => {
936
- const { session_id } = await createSession(intent);
937
- const now = (/* @__PURE__ */ new Date()).toISOString();
938
- get().registerCreatedSession({
939
- id: session_id,
940
- intent: intent ?? "",
941
- status: "created",
942
- created_at: now,
943
- updated_at: now
944
- });
945
- get().setActiveSession(session_id);
946
- invalidateHomeSidebarSessions();
947
- get().fetchSessions().catch(() => {
948
- });
949
- return session_id;
950
- },
951
- registerCreatedSession: (session, mode = DEFAULT_SESSION_MODE) => {
952
- registerCreatedSessionState(set, session, mode);
953
- },
954
- upsertSession: (session) => {
955
- set((state) => ({
956
- sessions: state.sessions.some((item) => item.id === session.id) ? state.sessions.map((item) => item.id === session.id ? { ...item, ...session } : item) : [session, ...state.sessions]
957
- }));
958
- },
959
- isFreshSession: (sessionId) => get()._freshSessions.has(sessionId),
960
- setActiveSession: (id) => {
961
- set({ activeSessionId: id });
962
- onSessionChange?.(id);
963
- getSession(id).then((detail) => {
964
- set((state) => ({
965
- sessions: state.sessions.some((s) => s.id === id) ? state.sessions.map(
966
- (s) => s.id === id ? { ...s, status: detail.status, updated_at: detail.updated_at } : s
967
- ) : [detail, ...state.sessions]
968
- }));
969
- }).catch(() => {
970
- });
971
- const tasksPromise = getSessionTasks(id).catch(() => null);
972
- Promise.all([getSessionTurns(id), tasksPromise]).then(([turns, tasks]) => {
973
- if (tasks) useTaskStore.getState().setTasks(id, tasks);
974
- useChatStore.getState().setAskAnswers(id, extractAskAnswers(turns));
975
- let inferredMode = DEFAULT_SESSION_MODE;
976
- for (const turn of turns) {
977
- const nextMode = extractModeFromBlocks2(turn.blocks);
978
- if (nextMode) {
979
- inferredMode = nextMode;
980
- }
981
- }
982
- set((state) => {
983
- if (state.modes[id] == null) {
984
- return { modes: { ...state.modes, [id]: inferredMode } };
985
- }
986
- return state;
987
- });
988
- const isFresh = get()._freshSessions.has(id);
989
- if (isFresh) {
990
- set((state) => {
991
- const next = new Set(state._freshSessions);
992
- next.delete(id);
993
- return { _freshSessions: next };
994
- });
995
- if (turns.length > 0) {
996
- useChatStore.getState().setTurns(id, turns);
997
- }
998
- } else {
999
- useChatStore.getState().setTurns(id, turns);
1000
- }
1001
- }).catch((error) => {
1002
- if (isSessionAccessRevoked(error)) {
1003
- handleUnreadableSession(set, get, id);
1004
- return;
1005
- }
1006
- console.error("Failed to load session data", error);
1007
- });
1008
- },
1009
- clearActiveSession: () => {
1010
- set({ activeSessionId: null });
1011
- onSessionChange?.(null);
1012
- },
1013
- deleteSession: async (id) => {
1014
- await deleteSession(id);
1015
- invalidateHomeSidebarSessions();
1016
- const wasActive = get().activeSessionId === id;
1017
- await get().fetchSessions();
1018
- if (!wasActive) {
1019
- return;
1020
- }
1021
- const nextId = get().sessions[0]?.id ?? null;
1022
- if (nextId) {
1023
- get().setActiveSession(nextId);
1024
- return;
1025
- }
1026
- get().clearActiveSession();
1027
- },
1028
- updateSessionStatus: (sessionId, status) => {
1029
- set((state) => ({
1030
- sessions: state.sessions.map((s) => s.id === sessionId ? { ...s, status } : s)
1031
- }));
1032
- if (status === "failed" || status === "interrupted") {
1033
- useChatStore.getState().setStreaming(sessionId, false);
1034
- if (status === "interrupted") {
1035
- useChatStore.getState().markInterrupted(sessionId);
1036
- } else {
1037
- useChatStore.getState().markFailed(sessionId);
1038
- }
1039
- }
1040
- },
1041
- updateSessionIntent: (sessionId, intent) => {
1042
- set((state) => ({
1043
- sessions: state.sessions.map((s) => s.id === sessionId ? { ...s, intent } : s)
1044
- }));
1045
- },
1046
- patchSession: (sessionId, patch) => {
1047
- set((state) => ({
1048
- sessions: state.sessions.map(
1049
- (s) => s.id === sessionId ? { ...s, ...patch } : s
1050
- )
1051
- }));
1052
- },
1053
- pinSession: async (sessionId, pinned) => {
1054
- const updated = await pinSession(sessionId, pinned);
1055
- set((state) => ({
1056
- sessions: state.sessions.map(
1057
- (s) => s.id === sessionId ? { ...s, is_pinned: updated.is_pinned, pinned_at: updated.pinned_at } : s
1058
- )
1059
- }));
1060
- invalidateHomeSidebarSessions();
1061
- },
1062
- setRewindDraft: (sessionId, text) => {
1063
- set((state) => {
1064
- if (text == null) {
1065
- const { [sessionId]: _, ...rest } = state.rewindDrafts;
1066
- return { rewindDrafts: rest };
1067
- }
1068
- return {
1069
- rewindDrafts: {
1070
- ...state.rewindDrafts,
1071
- [sessionId]: text
1072
- }
1073
- };
1074
- });
1075
- },
1076
- setMode: (sessionId, mode) => {
1077
- set((state) => ({ modes: { ...state.modes, [sessionId]: mode } }));
1078
- },
1079
- togglePlanningMode: (sessionId) => {
1080
- const current = get().modes[sessionId] ?? DEFAULT_SESSION_MODE;
1081
- const next = current === "executing" ? "planning" : "executing";
1082
- set((state) => ({ modes: { ...state.modes, [sessionId]: next } }));
1083
- },
1084
- toggleSharing: async (sessionId) => {
1085
- const session = get().sessions.find((s) => s.id === sessionId);
1086
- if (!session) return;
1087
- const newShared = !session.shared;
1088
- const result = await updateSharing(sessionId, newShared);
1089
- set((state) => ({
1090
- sessions: state.sessions.map(
1091
- (s) => s.id === sessionId ? { ...s, shared: result.shared } : s
1092
- )
1093
- }));
1094
- },
1095
- reset: () => {
1096
- set({
1097
- sessions: [],
1098
- activeSessionId: null,
1099
- loading: false,
1100
- modes: {},
1101
- rewindDrafts: {},
1102
- _freshSessions: /* @__PURE__ */ new Set()
1103
- });
1104
- invalidateHomeSidebarSessions();
1105
- }
1106
- }));
1107
- setChatStoreSessionAccessor(() => useSessionStore.getState().activeSessionId);
1108
-
1109
- // src/react/stores/auth-store.ts
1110
- var noopStorage = {
1111
- getItem: () => null,
1112
- setItem: () => {
1113
- },
1114
- removeItem: () => {
1115
- }
1116
- };
1117
- function shouldClearPersistedAuthState(value) {
1118
- try {
1119
- const parsed = JSON.parse(value);
1120
- return parsed.state?.token == null && parsed.state?.user == null;
1121
- } catch {
1122
- return false;
1123
- }
1124
- }
1125
- var authStorage = createJSONStorage(() => {
1126
- if (typeof localStorage === "undefined") {
1127
- return noopStorage;
1128
- }
1129
- return {
1130
- getItem: (name) => localStorage.getItem(name),
1131
- setItem: (name, value) => {
1132
- if (shouldClearPersistedAuthState(value)) {
1133
- localStorage.removeItem(name);
1134
- return;
1135
- }
1136
- localStorage.setItem(name, value);
1137
- },
1138
- removeItem: (name) => localStorage.removeItem(name)
1139
- };
1140
- });
1141
- function finishAuth(set, payload) {
1142
- set({
1143
- token: payload.token,
1144
- socketAuthToken: null,
1145
- user: payload.user,
1146
- loading: false,
1147
- error: null
1148
- });
1149
- agentSocket?.reconnect();
1150
- useSessionStore.getState().fetchSessions().catch(() => {
1151
- });
1152
- }
1153
- function finishCookieHydration(set, payload) {
1154
- set({
1155
- token: null,
1156
- socketAuthToken: payload.token,
1157
- user: payload.user,
1158
- loading: false,
1159
- error: null
1160
- });
1161
- agentSocket?.reconnect();
1162
- useSessionStore.getState().fetchSessions().catch(() => {
1163
- });
1164
- }
1165
- function toUser(info) {
1166
- return {
1167
- id: info.id,
1168
- username: info.username,
1169
- display_name: info.display_name,
1170
- avatar_url: info.avatar_url,
1171
- is_admin: info.is_admin
1172
- };
1173
- }
1174
- var useAuthStore = create6()(
1175
- persist(
1176
- (set, get) => ({
1177
- ...createClientActions(set),
1178
- token: null,
1179
- socketAuthToken: null,
1180
- user: null,
1181
- loading: false,
1182
- error: null,
1183
- logout: () => {
1184
- void logout().catch(() => {
1185
- });
1186
- set({ token: null, socketAuthToken: null, user: null, error: null });
1187
- agentSocket?.disconnect();
1188
- useSessionStore.getState().reset();
1189
- },
1190
- checkAuth: async () => {
1191
- const token = get().token;
1192
- if (!token) return;
1193
- try {
1194
- const auth = await getMe();
1195
- finishAuth(set, { token: auth.token, user: toUser(auth) });
1196
- } catch {
1197
- set({ token: null, socketAuthToken: null, user: null, error: null });
1198
- useSessionStore.getState().reset();
1199
- }
1200
- },
1201
- hydrateFromCookie: async () => {
1202
- set({ loading: true, error: null });
1203
- const previousToken = get().token;
1204
- if (previousToken) {
1205
- try {
1206
- const auth = await getMe();
1207
- finishAuth(set, { token: auth.token, user: toUser(auth) });
1208
- return;
1209
- } catch {
1210
- set({ token: null, socketAuthToken: null, user: null, error: null });
1211
- useSessionStore.getState().reset();
1212
- }
1213
- }
1214
- try {
1215
- const auth = await getMe();
1216
- finishCookieHydration(set, { token: auth.token, user: toUser(auth) });
1217
- } catch {
1218
- set({
1219
- token: null,
1220
- socketAuthToken: null,
1221
- user: null,
1222
- loading: false,
1223
- error: null
1224
- });
1225
- useSessionStore.getState().reset();
1226
- }
1227
- }
1228
- }),
1229
- {
1230
- name: "agent-auth",
1231
- storage: authStorage,
1232
- partialize: (state) => {
1233
- if (state.socketAuthToken) {
1234
- return { token: null, user: null };
1235
- }
1236
- return { token: state.token, user: state.user };
1237
- }
1238
- }
1239
- )
1240
- );
1241
-
1242
- // src/react/stores/background-store.ts
1243
- import { create as create7 } from "zustand";
1244
- var useBackgroundStore = create7()((set) => ({
1245
- ...createClientActions(set),
1246
- tasks: {},
1247
- selectedTaskId: {},
1248
- setTasks: (sessionId, tasks) => set((state) => ({
1249
- tasks: { ...state.tasks, [sessionId]: tasks },
1250
- selectedTaskId: {
1251
- ...state.selectedTaskId,
1252
- [sessionId]: state.selectedTaskId[sessionId] ?? tasks[0]?.id ?? null
1253
- }
1254
- })),
1255
- upsertTask: (sessionId, task) => set((state) => {
1256
- const existing = state.tasks[sessionId] ?? [];
1257
- const index = existing.findIndex((item) => item.id === task.id);
1258
- const next = [...existing];
1259
- if (index >= 0) {
1260
- next[index] = { ...next[index], ...task };
1261
- } else {
1262
- next.unshift(task);
1263
- }
1264
- return {
1265
- tasks: { ...state.tasks, [sessionId]: next },
1266
- selectedTaskId: {
1267
- ...state.selectedTaskId,
1268
- [sessionId]: state.selectedTaskId[sessionId] ?? task.id
1269
- }
1270
- };
1271
- }),
1272
- selectTask: (sessionId, taskId) => set((state) => ({
1273
- selectedTaskId: { ...state.selectedTaskId, [sessionId]: taskId }
1274
- }))
1275
- }));
1276
-
1277
- // src/react/stores/card-state-store.ts
1278
- import { create as create8 } from "zustand";
1279
- var useCardStateStore = create8((set, get) => ({
1280
- ...createClientActions(set),
1281
- states: {},
1282
- getCardState: (cardId) => {
1283
- return get().states[cardId];
1284
- },
1285
- setCardState: (cardId, state) => {
1286
- set((prev) => ({
1287
- states: { ...prev.states, [cardId]: state }
1288
- }));
1289
- },
1290
- removeCardState: (cardId) => {
1291
- set((prev) => {
1292
- const { [cardId]: _, ...rest } = prev.states;
1293
- return { states: rest };
1294
- });
1295
- },
1296
- clearAllStates: () => {
1297
- set({ states: {} });
1298
- }
1299
- }));
1300
-
1301
- // src/react/stores/connection-store.ts
1302
- import { create as create9 } from "zustand";
1303
- var initialConnectionState = {
1304
- status: "disconnected",
1305
- reconnectAttempt: 0,
1306
- lastConnectedAt: null,
1307
- lastDisconnectedAt: null,
1308
- hasEverConnected: false
1309
- };
1310
- var useConnectionStore = create9()((set) => ({
1311
- ...createClientActions(set),
1312
- ...initialConnectionState,
1313
- markConnecting: (attempt = 0) => set({
1314
- status: "connecting",
1315
- reconnectAttempt: attempt
1316
- }),
1317
- markConnected: () => set({
1318
- status: "connected",
1319
- reconnectAttempt: 0,
1320
- lastConnectedAt: Date.now(),
1321
- hasEverConnected: true
1322
- }),
1323
- markDisconnected: () => set({
1324
- status: "disconnected",
1325
- reconnectAttempt: 0,
1326
- lastDisconnectedAt: Date.now()
1327
- }),
1328
- reset: () => set(initialConnectionState)
1329
- }));
1330
-
1331
- // src/react/stores/runtime-store.ts
1332
- import { create as create10 } from "zustand";
1333
- var useRuntimeStore = create10()((set) => ({
1334
- ...createClientActions(set),
1335
- events: {},
1336
- addEvent: (sessionId, event) => set((state) => {
1337
- const current = state.events[sessionId] ?? [];
1338
- const nextEvent = {
1339
- ...event,
1340
- id: `${Date.now()}-${current.length}`,
1341
- sessionId,
1342
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1343
- };
1344
- return {
1345
- events: {
1346
- ...state.events,
1347
- [sessionId]: [...current.slice(-59), nextEvent]
1348
- }
1349
- };
1350
- }),
1351
- clearSession: (sessionId) => set((state) => ({
1352
- events: { ...state.events, [sessionId]: [] }
1353
- }))
1354
- }));
1355
-
1356
- // src/react/stores/gis-store.ts
1357
- import { create as create11 } from "zustand";
1358
- var EMPTY_GOALS = [];
1359
- var EMPTY_RESOURCES = [];
1360
- var EMPTY_TARGETS = [];
1361
- var EMPTY_COMMANDS = [];
1362
- function newCommandId() {
1363
- if (typeof globalThis !== "undefined" && "crypto" in globalThis) {
1364
- return globalThis.crypto?.randomUUID?.() ?? `gis-map-${Date.now()}-${Math.random()}`;
1365
- }
1366
- return `gis-map-${Date.now()}-${Math.random()}`;
1367
- }
1368
- var useGisStore = create11()((set, get) => ({
1369
- ...createClientActions(set),
1370
- goalsBySession: {},
1371
- resourcesBySession: {},
1372
- targetsBySession: {},
1373
- pendingMapCommandsBySession: {},
1374
- setGoals: (sessionId, goals) => {
1375
- set((state) => ({
1376
- goalsBySession: { ...state.goalsBySession, [sessionId]: goals }
1377
- }));
1378
- },
1379
- setResources: (sessionId, resources) => {
1380
- set((state) => ({
1381
- resourcesBySession: { ...state.resourcesBySession, [sessionId]: resources }
1382
- }));
1383
- },
1384
- setTargets: (sessionId, targets) => {
1385
- set((state) => ({
1386
- targetsBySession: { ...state.targetsBySession, [sessionId]: targets }
1387
- }));
1388
- },
1389
- pushMapCommand: (sessionId, command) => {
1390
- set((state) => ({
1391
- pendingMapCommandsBySession: {
1392
- ...state.pendingMapCommandsBySession,
1393
- [sessionId]: [
1394
- ...state.pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS,
1395
- {
1396
- ...command,
1397
- id: newCommandId(),
1398
- createdAt: Date.now()
1399
- }
1400
- ]
1401
- }
1402
- }));
1403
- },
1404
- consumeMapCommand: (sessionId, commandId) => {
1405
- set((state) => ({
1406
- pendingMapCommandsBySession: {
1407
- ...state.pendingMapCommandsBySession,
1408
- [sessionId]: (state.pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS).filter(
1409
- (command) => command.id !== commandId
1410
- )
1411
- }
1412
- }));
1413
- },
1414
- getGoals: (sessionId) => get().goalsBySession[sessionId] ?? EMPTY_GOALS,
1415
- getResources: (sessionId) => get().resourcesBySession[sessionId] ?? EMPTY_RESOURCES,
1416
- getTargets: (sessionId) => get().targetsBySession[sessionId] ?? EMPTY_TARGETS,
1417
- getPendingMapCommands: (sessionId) => get().pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS
1418
- }));
1419
-
1420
- // src/react/stores/answer-callback-store.ts
1421
- import { create as create12 } from "zustand";
1422
- var useAnswerCallbackStore = create12()((set) => ({
1423
- ...createClientActions(set),
1424
- callbacks: {},
1425
- setAnswerCallback: (sessionId, callback) => {
1426
- set((state) => ({
1427
- callbacks: {
1428
- ...state.callbacks,
1429
- [sessionId]: callback
1430
- }
1431
- }));
1432
- }
1433
- }));
1434
-
1435
- // src/react/stores/runtime-features-store.ts
1436
- import { create as create13 } from "zustand";
1437
- var useRuntimeFeaturesStore = create13((set) => ({
1438
- ...createClientActions(set),
1439
- asrEnabled: false,
1440
- asrProvider: "volcengine",
1441
- publicSharingEnabled: false,
1442
- memoryEnabled: false,
1443
- setFeatures: (features) => set((prev) => ({
1444
- asrEnabled: features.asrEnabled ?? prev.asrEnabled,
1445
- asrProvider: features.asrProvider ?? prev.asrProvider,
1446
- publicSharingEnabled: features.publicSharingEnabled ?? prev.publicSharingEnabled,
1447
- memoryEnabled: features.memoryEnabled ?? prev.memoryEnabled
1448
- }))
1449
- }));
1450
-
1451
- // src/react/bootstrap.ts
1452
- var bootstrappedClient = null;
1453
- function getBootstrappedClient() {
1454
- if (!bootstrappedClient) {
1455
- throw new Error("bootstrapBladeClient() must be called before any SDK usage");
1456
- }
1457
- return bootstrappedClient;
1458
- }
1459
-
1460
- // src/react/api/client.ts
1461
- function getClient() {
1462
- return getBootstrappedClient();
1463
- }
1
+ import {
2
+ getClient
3
+ } from "../../chunk-4VWLTG5L.js";
4
+ import "../../chunk-J3XVFPOV.js";
5
+ import "../../chunk-OKQWPNE3.js";
6
+ import "../../chunk-JCJFFJ42.js";
7
+ import "../../chunk-PZ5AY32C.js";
1464
8
 
1465
9
  // src/react/api/vibe-coding.ts
1466
- var r3 = () => getClient().vibeCoding;
1467
- var createVibeCodingSession = (...args) => r3().createVibeCodingSession(...args);
1468
- var listVibeCodingSessionInfos = (...args) => r3().listVibeCodingSessionInfos(...args);
1469
- var getVibeCodingSessionDebugStatus = (...args) => r3().getVibeCodingSessionDebugStatus(...args);
1470
- var getVibeCodingSessionStatus = (...args) => r3().getVibeCodingSessionStatus(...args);
1471
- var getVibeCodingDeployStatus = (...args) => r3().getVibeCodingDeployStatus(...args);
1472
- var startVibeCodingService = (...args) => r3().startVibeCodingService(...args);
1473
- var stopVibeCodingService = (...args) => r3().stopVibeCodingService(...args);
1474
- var updateVibeCodingDebugService = (...args) => r3().updateVibeCodingDebugService(...args);
1475
- var deployVibeCodingSession = (...args) => r3().deployVibeCodingSession(...args);
1476
- var listVibeCodingDeployVersions = (...args) => r3().listVibeCodingDeployVersions(...args);
1477
- var startVibeCodingDeployService = (...args) => r3().startVibeCodingDeployService(...args);
1478
- var stopVibeCodingDeployService = (...args) => r3().stopVibeCodingDeployService(...args);
1479
- var deleteVibeCodingDeployVersion = (...args) => r3().deleteVibeCodingDeployVersion(...args);
1480
- var deleteVibeCodingSession = (...args) => r3().deleteVibeCodingSession(...args);
1481
- var probeVibeCodingService = (...args) => r3().probeVibeCodingService(...args);
1482
- var exportVibeCodingSession = (...args) => r3().exportVibeCodingSession(...args);
1483
- var importVibeCodingSession = (...args) => r3().importVibeCodingSession(...args);
10
+ var r = () => getClient().vibeCoding;
11
+ var createVibeCodingSession = (...args) => r().createVibeCodingSession(...args);
12
+ var listVibeCodingSessionInfos = (...args) => r().listVibeCodingSessionInfos(...args);
13
+ var getVibeCodingSessionDebugStatus = (...args) => r().getVibeCodingSessionDebugStatus(...args);
14
+ var getVibeCodingSessionStatus = (...args) => r().getVibeCodingSessionStatus(...args);
15
+ var getVibeCodingDeployStatus = (...args) => r().getVibeCodingDeployStatus(...args);
16
+ var startVibeCodingService = (...args) => r().startVibeCodingService(...args);
17
+ var stopVibeCodingService = (...args) => r().stopVibeCodingService(...args);
18
+ var updateVibeCodingDebugService = (...args) => r().updateVibeCodingDebugService(...args);
19
+ var deployVibeCodingSession = (...args) => r().deployVibeCodingSession(...args);
20
+ var listVibeCodingDeployVersions = (...args) => r().listVibeCodingDeployVersions(...args);
21
+ var startVibeCodingDeployService = (...args) => r().startVibeCodingDeployService(...args);
22
+ var stopVibeCodingDeployService = (...args) => r().stopVibeCodingDeployService(...args);
23
+ var deleteVibeCodingDeployVersion = (...args) => r().deleteVibeCodingDeployVersion(...args);
24
+ var deleteVibeCodingSession = (...args) => r().deleteVibeCodingSession(...args);
25
+ var probeVibeCodingService = (...args) => r().probeVibeCodingService(...args);
26
+ var exportVibeCodingSession = (...args) => r().exportVibeCodingSession(...args);
27
+ var importVibeCodingSession = (...args) => r().importVibeCodingSession(...args);
1484
28
  export {
1485
29
  createVibeCodingSession,
1486
30
  deleteVibeCodingDeployVersion,