@sumicom/quicksave 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/claudeCodeService.d.ts +89 -0
- package/dist/ai/claudeCodeService.d.ts.map +1 -0
- package/dist/ai/claudeCodeService.js +602 -0
- package/dist/ai/claudeCodeService.js.map +1 -0
- package/dist/ai/sessionStore.d.ts +31 -0
- package/dist/ai/sessionStore.d.ts.map +1 -0
- package/dist/ai/sessionStore.js +72 -0
- package/dist/ai/sessionStore.js.map +1 -0
- package/dist/ai/sessionStore.test.d.ts +2 -0
- package/dist/ai/sessionStore.test.d.ts.map +1 -0
- package/dist/ai/sessionStore.test.js +99 -0
- package/dist/ai/sessionStore.test.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +39 -0
- package/dist/config.js.map +1 -1
- package/dist/connection/connection.d.ts +16 -17
- package/dist/connection/connection.d.ts.map +1 -1
- package/dist/connection/connection.js +72 -57
- package/dist/connection/connection.js.map +1 -1
- package/dist/connection/{signaling.d.ts → relay.d.ts} +3 -5
- package/dist/connection/relay.d.ts.map +1 -0
- package/dist/connection/{signaling.js → relay.js} +18 -19
- package/dist/connection/relay.js.map +1 -0
- package/dist/git/operations.d.ts +27 -1
- package/dist/git/operations.d.ts.map +1 -1
- package/dist/git/operations.js +113 -4
- package/dist/git/operations.js.map +1 -1
- package/dist/git/operations.test.js +69 -1
- package/dist/git/operations.test.js.map +1 -1
- package/dist/handlers/messageHandler.d.ts +31 -4
- package/dist/handlers/messageHandler.d.ts.map +1 -1
- package/dist/handlers/messageHandler.js +491 -62
- package/dist/handlers/messageHandler.js.map +1 -1
- package/dist/handlers/messageHandler.test.js +130 -2
- package/dist/handlers/messageHandler.test.js.map +1 -1
- package/dist/index.js +229 -89
- package/dist/index.js.map +1 -1
- package/dist/service/ensureDaemon.d.ts +23 -0
- package/dist/service/ensureDaemon.d.ts.map +1 -0
- package/dist/service/ensureDaemon.js +138 -0
- package/dist/service/ensureDaemon.js.map +1 -0
- package/dist/service/index.d.ts +8 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +8 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/ipc.test.d.ts +2 -0
- package/dist/service/ipc.test.d.ts.map +1 -0
- package/dist/service/ipc.test.js +140 -0
- package/dist/service/ipc.test.js.map +1 -0
- package/dist/service/ipcClient.d.ts +36 -0
- package/dist/service/ipcClient.d.ts.map +1 -0
- package/dist/service/ipcClient.js +167 -0
- package/dist/service/ipcClient.js.map +1 -0
- package/dist/service/ipcServer.d.ts +53 -0
- package/dist/service/ipcServer.d.ts.map +1 -0
- package/dist/service/ipcServer.js +245 -0
- package/dist/service/ipcServer.js.map +1 -0
- package/dist/service/run.d.ts +13 -0
- package/dist/service/run.d.ts.map +1 -0
- package/dist/service/run.js +292 -0
- package/dist/service/run.js.map +1 -0
- package/dist/service/singleton.d.ts +31 -0
- package/dist/service/singleton.d.ts.map +1 -0
- package/dist/service/singleton.js +96 -0
- package/dist/service/singleton.js.map +1 -0
- package/dist/service/singleton.test.d.ts +2 -0
- package/dist/service/singleton.test.d.ts.map +1 -0
- package/dist/service/singleton.test.js +39 -0
- package/dist/service/singleton.test.js.map +1 -0
- package/dist/service/stateStore.d.ts +11 -0
- package/dist/service/stateStore.d.ts.map +1 -0
- package/dist/service/stateStore.js +35 -0
- package/dist/service/stateStore.js.map +1 -0
- package/dist/service/types.d.ts +111 -0
- package/dist/service/types.d.ts.map +1 -0
- package/dist/service/types.js +76 -0
- package/dist/service/types.js.map +1 -0
- package/package.json +3 -2
- package/dist/connection/signaling.d.ts.map +0 -1
- package/dist/connection/signaling.js.map +0 -1
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { unstable_v2_createSession, unstable_v2_resumeSession, listSessions, getSessionMessages, } from '@anthropic-ai/claude-agent-sdk';
|
|
3
|
+
const TOOL_RESULT_TRUNCATE_LENGTH = 500;
|
|
4
|
+
const DEFAULT_MODEL = 'claude-sonnet-4-6';
|
|
5
|
+
/** Tools auto-approved at each permission level (no user prompt).
|
|
6
|
+
* Read/Glob/Grep are always auto-approved at SDK level (allowedTools).
|
|
7
|
+
* Tools NOT listed here go through canUseTool → permission prompt.
|
|
8
|
+
*
|
|
9
|
+
* Risk tiers:
|
|
10
|
+
* - Safe: Edit, Write, NotebookEdit, TodoWrite, Agent, EnterWorktree, ExitWorktree
|
|
11
|
+
* - Network: WebFetch, WebSearch
|
|
12
|
+
* - Execute: Bash
|
|
13
|
+
* - Code/Control: Skill, ToolSearch, Config
|
|
14
|
+
* - Schedule: CronCreate, CronDelete (arbitrary scheduled execution)
|
|
15
|
+
* - Remote: RemoteTrigger (triggers remote agents)
|
|
16
|
+
* - Workflow: EnterPlanMode, ExitPlanMode (ExitPlanMode has its own interactive UI)
|
|
17
|
+
*/
|
|
18
|
+
const AUTO_APPROVE = {
|
|
19
|
+
bypassPermissions: new Set([
|
|
20
|
+
// Safe
|
|
21
|
+
'Edit', 'Write', 'NotebookEdit', 'TodoWrite', 'Agent', 'EnterWorktree', 'ExitWorktree',
|
|
22
|
+
// Network
|
|
23
|
+
'WebFetch', 'WebSearch',
|
|
24
|
+
// Execute
|
|
25
|
+
'Bash',
|
|
26
|
+
// Code/Control
|
|
27
|
+
'Skill', 'ToolSearch', 'Config',
|
|
28
|
+
// Schedule + Remote
|
|
29
|
+
'CronCreate', 'CronDelete', 'CronList', 'RemoteTrigger',
|
|
30
|
+
// Workflow
|
|
31
|
+
'EnterPlanMode', 'ExitPlanMode',
|
|
32
|
+
// Background tasks
|
|
33
|
+
'TaskOutput', 'TaskStop',
|
|
34
|
+
]),
|
|
35
|
+
acceptEdits: new Set(['Edit', 'Write', 'NotebookEdit', 'TodoWrite', 'Agent', 'EnterWorktree', 'ExitWorktree']),
|
|
36
|
+
default: new Set(['TodoWrite', 'EnterWorktree', 'ExitWorktree', 'Agent']),
|
|
37
|
+
plan: new Set(),
|
|
38
|
+
};
|
|
39
|
+
/** Extract readable text from tool_result content (which may be a string or array of blocks). */
|
|
40
|
+
function extractToolResultText(content) {
|
|
41
|
+
if (typeof content === 'string')
|
|
42
|
+
return content;
|
|
43
|
+
if (Array.isArray(content)) {
|
|
44
|
+
return content
|
|
45
|
+
.filter((b) => b.type === 'text')
|
|
46
|
+
.map((b) => b.text || '')
|
|
47
|
+
.join('\n');
|
|
48
|
+
}
|
|
49
|
+
return JSON.stringify(content);
|
|
50
|
+
}
|
|
51
|
+
export class ClaudeCodeService extends EventEmitter {
|
|
52
|
+
sessions = new Map();
|
|
53
|
+
pendingInputRequests = new Map();
|
|
54
|
+
requestCounter = 0;
|
|
55
|
+
constructor() {
|
|
56
|
+
super();
|
|
57
|
+
}
|
|
58
|
+
/** Build and emit a session-updated event with current state. */
|
|
59
|
+
emitSessionUpdate(sessionId) {
|
|
60
|
+
const ps = this.sessions.get(sessionId);
|
|
61
|
+
const hasPendingInput = Array.from(this.pendingInputRequests.values())
|
|
62
|
+
.some((p) => p.request.sessionId === sessionId);
|
|
63
|
+
this.emit('session-updated', {
|
|
64
|
+
sessionId,
|
|
65
|
+
isActive: !!ps,
|
|
66
|
+
isStreaming: ps?.streaming ?? false,
|
|
67
|
+
hasPendingInput,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async listAvailableSessions(cwd) {
|
|
71
|
+
const sessions = await listSessions({ dir: cwd, limit: 50 });
|
|
72
|
+
// Enrich with live state + detect pending from JSONL
|
|
73
|
+
const pendingSessionIds = new Set(Array.from(this.pendingInputRequests.values()).map((p) => p.request.sessionId));
|
|
74
|
+
// Check JSONL for sessions not in memory (cold pending detection)
|
|
75
|
+
const enriched = await Promise.all(sessions.map(async (s) => {
|
|
76
|
+
const isActive = this.sessions.has(s.sessionId);
|
|
77
|
+
const isStreaming = this.sessions.get(s.sessionId)?.streaming ?? false;
|
|
78
|
+
let hasPendingInput = pendingSessionIds.has(s.sessionId);
|
|
79
|
+
// If not already known as pending from memory, check JSONL tail
|
|
80
|
+
if (!hasPendingInput) {
|
|
81
|
+
hasPendingInput = await this.detectPendingFromJSONL(s.sessionId, cwd);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
sessionId: s.sessionId,
|
|
85
|
+
summary: s.summary,
|
|
86
|
+
lastModified: s.lastModified,
|
|
87
|
+
createdAt: s.createdAt,
|
|
88
|
+
cwd: s.cwd,
|
|
89
|
+
gitBranch: s.gitBranch,
|
|
90
|
+
isActive,
|
|
91
|
+
isStreaming,
|
|
92
|
+
hasPendingInput,
|
|
93
|
+
};
|
|
94
|
+
}));
|
|
95
|
+
// Sort: pending first, then active, then by lastModified
|
|
96
|
+
enriched.sort((a, b) => {
|
|
97
|
+
if (a.hasPendingInput !== b.hasPendingInput)
|
|
98
|
+
return a.hasPendingInput ? -1 : 1;
|
|
99
|
+
if (a.isActive !== b.isActive)
|
|
100
|
+
return a.isActive ? -1 : 1;
|
|
101
|
+
return b.lastModified - a.lastModified;
|
|
102
|
+
});
|
|
103
|
+
return enriched;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if a session's last message in the SDK JSONL is an unanswered tool_use.
|
|
107
|
+
* Reads only the last few messages to keep it fast.
|
|
108
|
+
*/
|
|
109
|
+
async detectPendingFromJSONL(sessionId, cwd) {
|
|
110
|
+
try {
|
|
111
|
+
const allMessages = await getSessionMessages(sessionId, { dir: cwd });
|
|
112
|
+
if (allMessages.length === 0)
|
|
113
|
+
return false;
|
|
114
|
+
const last = allMessages[allMessages.length - 1];
|
|
115
|
+
// Last message is assistant with a tool_use block and no following user/tool_result
|
|
116
|
+
if (last.type !== 'assistant')
|
|
117
|
+
return false;
|
|
118
|
+
const content = last.message?.content;
|
|
119
|
+
if (!Array.isArray(content))
|
|
120
|
+
return false;
|
|
121
|
+
return content.some((block) => block.type === 'tool_use');
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async getMessages(sessionId, cwd, offset = 0, limit = 50) {
|
|
128
|
+
// Read directly from SDK JSONL — the single source of truth.
|
|
129
|
+
// SDK writes messages immediately and retains full, un-truncated data.
|
|
130
|
+
// Messages are chronological (old→new). We paginate from the tail:
|
|
131
|
+
// offset=0 → last `limit` messages (most recent)
|
|
132
|
+
// offset=50 → the `limit` messages before those, etc.
|
|
133
|
+
const allMessages = await getSessionMessages(sessionId, { dir: cwd });
|
|
134
|
+
const total = allMessages.length;
|
|
135
|
+
const tailStart = Math.max(0, total - offset - limit);
|
|
136
|
+
const tailEnd = Math.max(0, total - offset);
|
|
137
|
+
const sliced = allMessages.slice(tailStart, tailEnd);
|
|
138
|
+
const messages = sliced.map((msg, i) => {
|
|
139
|
+
const role = msg.type;
|
|
140
|
+
let content = '';
|
|
141
|
+
let toolName;
|
|
142
|
+
let toolInput;
|
|
143
|
+
let toolResult;
|
|
144
|
+
let truncated = false;
|
|
145
|
+
const rawMessage = msg.message;
|
|
146
|
+
if (rawMessage?.content) {
|
|
147
|
+
if (typeof rawMessage.content === 'string') {
|
|
148
|
+
content = rawMessage.content;
|
|
149
|
+
}
|
|
150
|
+
else if (Array.isArray(rawMessage.content)) {
|
|
151
|
+
const parts = [];
|
|
152
|
+
for (const block of rawMessage.content) {
|
|
153
|
+
if (block.type === 'text') {
|
|
154
|
+
parts.push(block.text);
|
|
155
|
+
}
|
|
156
|
+
else if (block.type === 'tool_use') {
|
|
157
|
+
toolName = block.name;
|
|
158
|
+
toolInput = JSON.stringify(block.input);
|
|
159
|
+
}
|
|
160
|
+
else if (block.type === 'tool_result') {
|
|
161
|
+
const resultStr = extractToolResultText(block.content);
|
|
162
|
+
if (resultStr.length > TOOL_RESULT_TRUNCATE_LENGTH) {
|
|
163
|
+
toolResult = resultStr.slice(0, TOOL_RESULT_TRUNCATE_LENGTH) + ' [truncated]';
|
|
164
|
+
truncated = true;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
toolResult = resultStr;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
content = parts.join('\n');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
index: tailStart + i,
|
|
176
|
+
role,
|
|
177
|
+
content,
|
|
178
|
+
toolName,
|
|
179
|
+
toolInput,
|
|
180
|
+
toolResult,
|
|
181
|
+
truncated,
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
return {
|
|
185
|
+
messages,
|
|
186
|
+
total,
|
|
187
|
+
hasMore: tailStart > 0,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Create a V2 session with the given cwd.
|
|
192
|
+
* V2 SDKSessionOptions doesn't expose `cwd`, so we temporarily change
|
|
193
|
+
* process.cwd() around the synchronous createSession() call.
|
|
194
|
+
*/
|
|
195
|
+
createSessionWithCwd(cwd, sessionId, opts) {
|
|
196
|
+
const originalCwd = process.cwd();
|
|
197
|
+
try {
|
|
198
|
+
process.chdir(cwd);
|
|
199
|
+
// allowedTools = SDK auto-approve list (bypasses canUseTool entirely).
|
|
200
|
+
// Only list tools that should NEVER prompt at ANY permission level.
|
|
201
|
+
// Everything else goes through permissionMode → canUseTool for dynamic control.
|
|
202
|
+
const sessionOpts = {
|
|
203
|
+
model: opts.model ?? DEFAULT_MODEL,
|
|
204
|
+
allowedTools: opts.allowedTools ?? ['Read', 'Glob', 'Grep'],
|
|
205
|
+
permissionMode: 'default',
|
|
206
|
+
settingSources: ['user', 'project', 'local'],
|
|
207
|
+
canUseTool: async (toolName, input, options) => {
|
|
208
|
+
const resolvedSessionId = sessionId ?? 'unknown';
|
|
209
|
+
// Check runtime permission level — auto-approve if tool is in the allow set
|
|
210
|
+
const ps = resolvedSessionId !== 'unknown' ? this.sessions.get(resolvedSessionId) : undefined;
|
|
211
|
+
const level = ps?.permissionLevel ?? 'acceptEdits';
|
|
212
|
+
if (AUTO_APPROVE[level].has(toolName)) {
|
|
213
|
+
return { behavior: 'allow', updatedInput: input };
|
|
214
|
+
}
|
|
215
|
+
const requestId = `perm-${++this.requestCounter}`;
|
|
216
|
+
// AskUserQuestion: forward as question type with options
|
|
217
|
+
const isQuestion = toolName === 'AskUserQuestion';
|
|
218
|
+
const questions = isQuestion ? input.questions : undefined;
|
|
219
|
+
// Forward request to PWA
|
|
220
|
+
const request = {
|
|
221
|
+
sessionId: resolvedSessionId,
|
|
222
|
+
requestId,
|
|
223
|
+
inputType: isQuestion ? 'question' : 'permission',
|
|
224
|
+
title: isQuestion
|
|
225
|
+
? questions?.[0]?.question ?? 'Question from Claude'
|
|
226
|
+
: (options.title ?? `Allow ${toolName}?`),
|
|
227
|
+
message: isQuestion
|
|
228
|
+
? undefined
|
|
229
|
+
: (options.description ?? JSON.stringify(input).slice(0, 500)),
|
|
230
|
+
toolName,
|
|
231
|
+
toolInput: input,
|
|
232
|
+
// Include structured options for question type
|
|
233
|
+
...(isQuestion && questions ? {
|
|
234
|
+
options: questions.flatMap((q) => (q.options ?? []).map((opt) => ({
|
|
235
|
+
key: opt.label,
|
|
236
|
+
label: opt.label,
|
|
237
|
+
description: opt.description,
|
|
238
|
+
}))),
|
|
239
|
+
} : {}),
|
|
240
|
+
};
|
|
241
|
+
this.emit('user-input-request', request);
|
|
242
|
+
this.emitSessionUpdate(resolvedSessionId);
|
|
243
|
+
// Wait for explicit user response (no timeout — user must act)
|
|
244
|
+
const response = await this.waitForUserInput(requestId, request, options.signal);
|
|
245
|
+
if (response.action === 'deny') {
|
|
246
|
+
return { behavior: 'deny', message: 'User denied permission' };
|
|
247
|
+
}
|
|
248
|
+
// For AskUserQuestion, inject user's answer into the tool input
|
|
249
|
+
if (isQuestion && response.response) {
|
|
250
|
+
const answers = {};
|
|
251
|
+
if (questions?.[0]?.question) {
|
|
252
|
+
answers[questions[0].question] = response.response;
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
behavior: 'allow',
|
|
256
|
+
updatedInput: { ...input, answers },
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return { behavior: 'allow', updatedInput: input };
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
if (opts.resumeSessionId) {
|
|
263
|
+
return unstable_v2_resumeSession(opts.resumeSessionId, sessionOpts);
|
|
264
|
+
}
|
|
265
|
+
return unstable_v2_createSession(sessionOpts);
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
process.chdir(originalCwd);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
waitForUserInput(requestId, request, signal) {
|
|
272
|
+
return new Promise((resolve) => {
|
|
273
|
+
this.pendingInputRequests.set(requestId, { resolve, request });
|
|
274
|
+
// Only auto-resolve if the SDK itself aborts (e.g. session closed)
|
|
275
|
+
signal?.addEventListener('abort', () => {
|
|
276
|
+
this.pendingInputRequests.delete(requestId);
|
|
277
|
+
resolve({ sessionId: '', requestId, action: 'allow' });
|
|
278
|
+
}, { once: true });
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Called by message handler when PWA sends a user input response.
|
|
283
|
+
*/
|
|
284
|
+
resolveUserInput(response) {
|
|
285
|
+
const pending = this.pendingInputRequests.get(response.requestId);
|
|
286
|
+
if (!pending)
|
|
287
|
+
return false;
|
|
288
|
+
this.pendingInputRequests.delete(response.requestId);
|
|
289
|
+
pending.resolve(response);
|
|
290
|
+
this.emit('user-input-resolved', { requestId: response.requestId, sessionId: pending.request.sessionId });
|
|
291
|
+
this.emitSessionUpdate(pending.request.sessionId);
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Get all pending user input requests (for re-sending to a reconnected client).
|
|
296
|
+
*/
|
|
297
|
+
getPendingInputRequests() {
|
|
298
|
+
return Array.from(this.pendingInputRequests.values()).map((p) => p.request);
|
|
299
|
+
}
|
|
300
|
+
async startSession(opts) {
|
|
301
|
+
const validModes = ['default', 'acceptEdits', 'bypassPermissions', 'plan'];
|
|
302
|
+
const level = validModes.includes(opts.permissionMode)
|
|
303
|
+
? opts.permissionMode : 'acceptEdits';
|
|
304
|
+
const session = this.createSessionWithCwd(opts.cwd, null, {
|
|
305
|
+
allowedTools: opts.allowedTools,
|
|
306
|
+
model: opts.model,
|
|
307
|
+
permissionMode: opts.permissionMode,
|
|
308
|
+
});
|
|
309
|
+
const prompt = opts.systemPrompt
|
|
310
|
+
? `[System context: ${opts.systemPrompt}]\n\n${opts.prompt}`
|
|
311
|
+
: opts.prompt;
|
|
312
|
+
await session.send(prompt);
|
|
313
|
+
this.emit('stream', {
|
|
314
|
+
sessionId: '', streamId: opts.streamId,
|
|
315
|
+
eventType: 'user_message',
|
|
316
|
+
content: opts.prompt,
|
|
317
|
+
});
|
|
318
|
+
const sessionId = await new Promise((resolve) => {
|
|
319
|
+
this.consumeStream(session, opts.streamId, (id) => {
|
|
320
|
+
this.sessions.set(id, {
|
|
321
|
+
session,
|
|
322
|
+
sessionId: id,
|
|
323
|
+
cwd: opts.cwd,
|
|
324
|
+
streaming: true,
|
|
325
|
+
cancelStreaming: null,
|
|
326
|
+
permissionLevel: level,
|
|
327
|
+
});
|
|
328
|
+
this.emitSessionUpdate(id);
|
|
329
|
+
resolve(id);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
return sessionId;
|
|
333
|
+
}
|
|
334
|
+
async resumeSession(opts) {
|
|
335
|
+
const existing = this.sessions.get(opts.sessionId);
|
|
336
|
+
if (existing) {
|
|
337
|
+
console.log(`[v2] hot resume session=${opts.sessionId}`);
|
|
338
|
+
existing.streaming = true;
|
|
339
|
+
this.emitSessionUpdate(opts.sessionId);
|
|
340
|
+
this.emit('stream', {
|
|
341
|
+
sessionId: opts.sessionId, streamId: opts.streamId,
|
|
342
|
+
eventType: 'user_message',
|
|
343
|
+
content: opts.prompt,
|
|
344
|
+
});
|
|
345
|
+
await existing.session.send(opts.prompt);
|
|
346
|
+
this.consumeStream(existing.session, opts.streamId, () => {
|
|
347
|
+
// Session ID already captured
|
|
348
|
+
});
|
|
349
|
+
return opts.sessionId;
|
|
350
|
+
}
|
|
351
|
+
console.log(`[v2] cold resume session=${opts.sessionId}`);
|
|
352
|
+
const session = this.createSessionWithCwd(opts.cwd, opts.sessionId, {
|
|
353
|
+
resumeSessionId: opts.sessionId,
|
|
354
|
+
});
|
|
355
|
+
this.emit('stream', {
|
|
356
|
+
sessionId: opts.sessionId, streamId: opts.streamId,
|
|
357
|
+
eventType: 'user_message',
|
|
358
|
+
content: opts.prompt,
|
|
359
|
+
});
|
|
360
|
+
await session.send(opts.prompt);
|
|
361
|
+
const actualSessionId = await new Promise((resolve) => {
|
|
362
|
+
this.consumeStream(session, opts.streamId, (id) => {
|
|
363
|
+
if (id !== opts.sessionId) {
|
|
364
|
+
this.emit('stream', {
|
|
365
|
+
sessionId: id, streamId: opts.streamId,
|
|
366
|
+
eventType: 'system',
|
|
367
|
+
content: `Warning: SDK created new session ${id} instead of resuming ${opts.sessionId}`,
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
this.sessions.set(id, {
|
|
371
|
+
session,
|
|
372
|
+
sessionId: id,
|
|
373
|
+
cwd: opts.cwd,
|
|
374
|
+
streaming: true,
|
|
375
|
+
cancelStreaming: null,
|
|
376
|
+
permissionLevel: 'acceptEdits',
|
|
377
|
+
});
|
|
378
|
+
this.emitSessionUpdate(id);
|
|
379
|
+
resolve(id);
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
return actualSessionId;
|
|
383
|
+
}
|
|
384
|
+
cancelSession(sessionId) {
|
|
385
|
+
const ps = this.sessions.get(sessionId);
|
|
386
|
+
if (!ps)
|
|
387
|
+
return false;
|
|
388
|
+
// Stop streaming but keep the session process alive
|
|
389
|
+
if (ps.cancelStreaming) {
|
|
390
|
+
ps.cancelStreaming();
|
|
391
|
+
}
|
|
392
|
+
ps.streaming = false;
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
setPermissionLevel(sessionId, level) {
|
|
396
|
+
const ps = this.sessions.get(sessionId);
|
|
397
|
+
if (!ps)
|
|
398
|
+
return false;
|
|
399
|
+
ps.permissionLevel = level;
|
|
400
|
+
this.emitSessionUpdate(sessionId);
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
getPermissionLevel(sessionId) {
|
|
404
|
+
return this.sessions.get(sessionId)?.permissionLevel ?? 'acceptEdits';
|
|
405
|
+
}
|
|
406
|
+
closeSession(sessionId) {
|
|
407
|
+
const ps = this.sessions.get(sessionId);
|
|
408
|
+
if (!ps)
|
|
409
|
+
return false;
|
|
410
|
+
// Stop streaming if active
|
|
411
|
+
if (ps.cancelStreaming) {
|
|
412
|
+
ps.cancelStreaming();
|
|
413
|
+
}
|
|
414
|
+
// Terminate the subprocess
|
|
415
|
+
ps.session.close();
|
|
416
|
+
this.sessions.delete(sessionId);
|
|
417
|
+
this.emitSessionUpdate(sessionId);
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
isStreaming(sessionId) {
|
|
421
|
+
return this.sessions.get(sessionId)?.streaming ?? false;
|
|
422
|
+
}
|
|
423
|
+
isOpen(sessionId) {
|
|
424
|
+
return this.sessions.has(sessionId);
|
|
425
|
+
}
|
|
426
|
+
getActiveSessionCount() {
|
|
427
|
+
return this.sessions.size;
|
|
428
|
+
}
|
|
429
|
+
cleanup() {
|
|
430
|
+
// Force-resolve any pending inputs on daemon shutdown
|
|
431
|
+
for (const [requestId, pending] of this.pendingInputRequests) {
|
|
432
|
+
pending.resolve({ sessionId: '', requestId, action: 'allow' });
|
|
433
|
+
}
|
|
434
|
+
this.pendingInputRequests.clear();
|
|
435
|
+
for (const [, ps] of this.sessions) {
|
|
436
|
+
try {
|
|
437
|
+
ps.session.close();
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
// Ignore errors during cleanup
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
this.sessions.clear();
|
|
444
|
+
}
|
|
445
|
+
async consumeStream(session, streamId, onSessionId) {
|
|
446
|
+
let textBuffer = '';
|
|
447
|
+
let bufferTimer = null;
|
|
448
|
+
let capturedSessionId = null;
|
|
449
|
+
let cancelled = false;
|
|
450
|
+
const emitStream = (event) => {
|
|
451
|
+
this.emit('stream', { ...event, sessionId: capturedSessionId ?? '', streamId });
|
|
452
|
+
};
|
|
453
|
+
const flushText = () => {
|
|
454
|
+
if (textBuffer) {
|
|
455
|
+
emitStream({ eventType: 'assistant_text', content: textBuffer });
|
|
456
|
+
textBuffer = '';
|
|
457
|
+
}
|
|
458
|
+
if (bufferTimer) {
|
|
459
|
+
clearTimeout(bufferTimer);
|
|
460
|
+
bufferTimer = null;
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
const markStreamingDone = () => {
|
|
464
|
+
if (capturedSessionId) {
|
|
465
|
+
const ps = this.sessions.get(capturedSessionId);
|
|
466
|
+
if (ps) {
|
|
467
|
+
ps.streaming = false;
|
|
468
|
+
ps.cancelStreaming = null;
|
|
469
|
+
}
|
|
470
|
+
this.emitSessionUpdate(capturedSessionId);
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
const bufferText = (text) => {
|
|
474
|
+
textBuffer += text;
|
|
475
|
+
if (!bufferTimer) {
|
|
476
|
+
bufferTimer = setTimeout(flushText, 150);
|
|
477
|
+
}
|
|
478
|
+
if (textBuffer.length > 2048) {
|
|
479
|
+
flushText();
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
// Wire up cancel function for this streaming turn
|
|
483
|
+
const setCancelFn = () => {
|
|
484
|
+
if (capturedSessionId) {
|
|
485
|
+
const ps = this.sessions.get(capturedSessionId);
|
|
486
|
+
if (ps) {
|
|
487
|
+
ps.cancelStreaming = () => { cancelled = true; };
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
try {
|
|
492
|
+
for await (const message of session.stream()) {
|
|
493
|
+
if (cancelled)
|
|
494
|
+
break;
|
|
495
|
+
// Capture session ID from init message
|
|
496
|
+
if (message.type === 'system' && message.subtype === 'init') {
|
|
497
|
+
capturedSessionId = message.session_id;
|
|
498
|
+
console.log(`[stream] init session=${message.session_id}`);
|
|
499
|
+
onSessionId(message.session_id);
|
|
500
|
+
setCancelFn();
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
// Session state changed — 'idle' means turn is over
|
|
504
|
+
if (message.type === 'system' && message.subtype === 'session_state_changed') {
|
|
505
|
+
const state = message.state;
|
|
506
|
+
if (state === 'idle') {
|
|
507
|
+
flushText();
|
|
508
|
+
console.log(`[stream] session_state_changed=idle session=${capturedSessionId}`);
|
|
509
|
+
// Don't call onEnd here — the result message will follow
|
|
510
|
+
}
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
// Streaming partial events
|
|
514
|
+
if (message.type === 'stream_event') {
|
|
515
|
+
const event = message.event;
|
|
516
|
+
if (event?.type === 'content_block_delta') {
|
|
517
|
+
const delta = event.delta;
|
|
518
|
+
if (delta?.type === 'text_delta' && delta.text) {
|
|
519
|
+
bufferText(delta.text);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
// Complete assistant messages
|
|
525
|
+
if (message.type === 'assistant') {
|
|
526
|
+
flushText();
|
|
527
|
+
const betaMessage = message.message;
|
|
528
|
+
if (betaMessage?.content) {
|
|
529
|
+
for (const block of betaMessage.content) {
|
|
530
|
+
if (block.type === 'text' && block.text) {
|
|
531
|
+
emitStream({
|
|
532
|
+
eventType: 'assistant_text',
|
|
533
|
+
content: block.text,
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
else if (block.type === 'tool_use') {
|
|
537
|
+
const toolInput = JSON.stringify(block.input);
|
|
538
|
+
emitStream({
|
|
539
|
+
eventType: 'tool_use',
|
|
540
|
+
content: '',
|
|
541
|
+
toolName: block.name,
|
|
542
|
+
toolInput,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
// User messages contain tool results
|
|
550
|
+
if (message.type === 'user') {
|
|
551
|
+
const userMsg = message.message;
|
|
552
|
+
if (userMsg?.content && Array.isArray(userMsg.content)) {
|
|
553
|
+
for (const block of userMsg.content) {
|
|
554
|
+
if (block.type === 'tool_result') {
|
|
555
|
+
const resultContent = extractToolResultText(block.content);
|
|
556
|
+
const truncated = resultContent.length > TOOL_RESULT_TRUNCATE_LENGTH
|
|
557
|
+
? resultContent.slice(0, TOOL_RESULT_TRUNCATE_LENGTH) + ' [truncated]'
|
|
558
|
+
: resultContent;
|
|
559
|
+
emitStream({
|
|
560
|
+
eventType: 'tool_result',
|
|
561
|
+
content: truncated,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
// Final result — turn is complete but session stays alive
|
|
569
|
+
if (message.type === 'result') {
|
|
570
|
+
flushText();
|
|
571
|
+
const result = message;
|
|
572
|
+
console.log(`[stream] result session=${capturedSessionId} subtype=${result.subtype} cost=$${result.total_cost_usd?.toFixed(4) ?? '?'}`);
|
|
573
|
+
markStreamingDone();
|
|
574
|
+
this.emit('stream:end', {
|
|
575
|
+
sessionId: capturedSessionId ?? '', streamId,
|
|
576
|
+
success: result.subtype === 'success',
|
|
577
|
+
error: result.subtype !== 'success'
|
|
578
|
+
? (result.errors?.join('; ') || `Session ended: ${result.subtype}`)
|
|
579
|
+
: undefined,
|
|
580
|
+
totalCostUsd: result.total_cost_usd,
|
|
581
|
+
tokenUsage: result.usage
|
|
582
|
+
? { input: result.usage.input_tokens, output: result.usage.output_tokens }
|
|
583
|
+
: undefined,
|
|
584
|
+
});
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
flushText();
|
|
589
|
+
console.log(`[stream] ended without result session=${capturedSessionId} (cancel or unexpected)`);
|
|
590
|
+
markStreamingDone();
|
|
591
|
+
this.emit('stream:end', { sessionId: capturedSessionId ?? '', streamId, success: true });
|
|
592
|
+
}
|
|
593
|
+
catch (error) {
|
|
594
|
+
flushText();
|
|
595
|
+
console.error(`[stream] error session=${capturedSessionId}:`, error);
|
|
596
|
+
markStreamingDone();
|
|
597
|
+
const msg = error instanceof Error ? error.message : 'Unknown error';
|
|
598
|
+
this.emit('stream:end', { sessionId: capturedSessionId ?? '', streamId, success: false, error: msg });
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
//# sourceMappingURL=claudeCodeService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeCodeService.js","sourceRoot":"","sources":["../../src/ai/claudeCodeService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,YAAY,EACZ,kBAAkB,GACnB,MAAM,gCAAgC,CAAC;AASxC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AACxC,MAAM,aAAa,GAAG,mBAAmB,CAAC;AA8B1C;;;;;;;;;;;;GAYG;AACH,MAAM,YAAY,GAAyC;IACzD,iBAAiB,EAAE,IAAI,GAAG,CAAC;QACzB,OAAO;QACP,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc;QACtF,UAAU;QACV,UAAU,EAAE,WAAW;QACvB,UAAU;QACV,MAAM;QACN,eAAe;QACf,OAAO,EAAE,YAAY,EAAE,QAAQ;QAC/B,oBAAoB;QACpB,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe;QACvD,WAAW;QACX,eAAe,EAAE,cAAc;QAC/B,mBAAmB;QACnB,YAAY,EAAE,UAAU;KACzB,CAAC;IACF,WAAW,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;IAC9G,OAAO,EAAM,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IAC7E,IAAI,EAAS,IAAI,GAAG,EAAE;CACvB,CAAC;AAWF,iGAAiG;AACjG,SAAS,qBAAqB,CAAC,OAAgB;IAC7C,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;aACrC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;aAC7B,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAOD,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IACzC,QAAQ,GAAmC,IAAI,GAAG,EAAE,CAAC;IACrD,oBAAoB,GAAkC,IAAI,GAAG,EAAE,CAAC;IAChE,cAAc,GAAG,CAAC,CAAC;IAE3B;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iEAAiE;IACzD,iBAAiB,CAAC,SAAiB;QACzC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC;aACnE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;YAC3B,SAAS;YACT,QAAQ,EAAE,CAAC,CAAC,EAAE;YACd,WAAW,EAAE,EAAE,EAAE,SAAS,IAAI,KAAK;YACnC,eAAe;SAChB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,GAAW;QACrC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC7D,qDAAqD;QACrD,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAC/B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAC/E,CAAC;QACF,kEAAkE;QAClE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAChD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,SAAS,IAAI,KAAK,CAAC;YACvE,IAAI,eAAe,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAEzD,gEAAgE;YAChE,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,eAAe,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YACxE,CAAC;YAED,OAAO;gBACL,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,YAAY,EAAE,CAAC,CAAC,YAAY;gBAC5B,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,QAAQ;gBACR,WAAW;gBACX,eAAe;aAChB,CAAC;QACJ,CAAC,CAAC,CAAC,CAAC;QACJ,yDAAyD;QACzD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACrB,IAAI,CAAC,CAAC,eAAe,KAAK,CAAC,CAAC,eAAe;gBAAE,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;gBAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,sBAAsB,CAAC,SAAiB,EAAE,GAAW;QACjE,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACtE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAQ,CAAC;YACxD,oFAAoF;YACpF,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;gBAAE,OAAO,KAAK,CAAC;YAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC1C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CACf,SAAiB,EACjB,GAAW,EACX,MAAM,GAAG,CAAC,EACV,KAAK,GAAG,EAAE;QAEV,6DAA6D;QAC7D,uEAAuE;QACvE,mEAAmE;QACnE,oDAAoD;QACpD,wDAAwD;QACxD,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QACtE,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAErD,MAAM,QAAQ,GAA2B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YAC7D,MAAM,IAAI,GAAG,GAAG,CAAC,IAA4B,CAAC;YAC9C,IAAI,OAAO,GAAG,EAAE,CAAC;YACjB,IAAI,QAA4B,CAAC;YACjC,IAAI,SAA6B,CAAC;YAClC,IAAI,UAA8B,CAAC;YACnC,IAAI,SAAS,GAAG,KAAK,CAAC;YAEtB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAc,CAAC;YACtC,IAAI,UAAU,EAAE,OAAO,EAAE,CAAC;gBACxB,IAAI,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBAC3C,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;gBAC/B,CAAC;qBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;oBAC3B,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;wBACvC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;4BAC1B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBACzB,CAAC;6BAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;4BACrC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC;4BACtB,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;wBAC1C,CAAC;6BAAM,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;4BACxC,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;4BACvD,IAAI,SAAS,CAAC,MAAM,GAAG,2BAA2B,EAAE,CAAC;gCACnD,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,GAAG,cAAc,CAAC;gCAC9E,SAAS,GAAG,IAAI,CAAC;4BACnB,CAAC;iCAAM,CAAC;gCACN,UAAU,GAAG,SAAS,CAAC;4BACzB,CAAC;wBACH,CAAC;oBACH,CAAC;oBACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YAED,OAAO;gBACL,KAAK,EAAE,SAAS,GAAG,CAAC;gBACpB,IAAI;gBACJ,OAAO;gBACP,QAAQ;gBACR,SAAS;gBACT,UAAU;gBACV,SAAS;aACV,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ;YACR,KAAK;YACL,OAAO,EAAE,SAAS,GAAG,CAAC;SACvB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,oBAAoB,CAC1B,GAAW,EACX,SAAwB,EACxB,IAKC;QAED,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,uEAAuE;YACvE,oEAAoE;YACpE,gFAAgF;YAChF,MAAM,WAAW,GAAG;gBAClB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,aAAa;gBAClC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;gBAC3D,cAAc,EAAE,SAAkB;gBAClC,cAAc,EAAE,CAAC,MAAe,EAAE,SAAkB,EAAE,OAAgB,CAAC;gBACvE,UAAU,EAAE,KAAK,EACf,QAAgB,EAChB,KAA8B,EAC9B,OAA+G,EAC/G,EAAE;oBAGF,MAAM,iBAAiB,GAAG,SAAS,IAAI,SAAS,CAAC;oBAEjD,4EAA4E;oBAC5E,MAAM,EAAE,GAAG,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC9F,MAAM,KAAK,GAAG,EAAE,EAAE,eAAe,IAAI,aAAa,CAAC;oBACnD,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAEtC,OAAO,EAAE,QAAQ,EAAE,OAAgB,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;oBAC7D,CAAC;oBACD,MAAM,SAAS,GAAG,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC;oBAElD,yDAAyD;oBACzD,MAAM,UAAU,GAAG,QAAQ,KAAK,iBAAiB,CAAC;oBAClD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAE,KAAa,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;oBAGpE,yBAAyB;oBACzB,MAAM,OAAO,GAAkC;wBAC7C,SAAS,EAAE,iBAAiB;wBAC5B,SAAS;wBACT,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;wBACjD,KAAK,EAAE,UAAU;4BACf,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,sBAAsB;4BACpD,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,SAAS,QAAQ,GAAG,CAAC;wBAC3C,OAAO,EAAE,UAAU;4BACjB,CAAC,CAAC,SAAS;4BACX,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;wBAChE,QAAQ;wBACR,SAAS,EAAE,KAAK;wBAChB,+CAA+C;wBAC/C,GAAG,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC;4BAC5B,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAM,EAAE,EAAE,CACpC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;gCACnC,GAAG,EAAE,GAAG,CAAC,KAAK;gCACd,KAAK,EAAE,GAAG,CAAC,KAAK;gCAChB,WAAW,EAAE,GAAG,CAAC,WAAW;6BAC7B,CAAC,CAAC,CACJ;yBACF,CAAC,CAAC,CAAC,EAAE,CAAC;qBACR,CAAC;oBAEF,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;oBACzC,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;oBAE1C,+DAA+D;oBAC/D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;oBACjF,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;wBAC/B,OAAO,EAAE,QAAQ,EAAE,MAAe,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;oBAC1E,CAAC;oBAED,gEAAgE;oBAChE,IAAI,UAAU,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;wBACpC,MAAM,OAAO,GAA2B,EAAE,CAAC;wBAC3C,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;4BAC7B,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC;wBACrD,CAAC;wBACD,OAAO;4BACL,QAAQ,EAAE,OAAgB;4BAC1B,YAAY,EAAE,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE;yBACpC,CAAC;oBACJ,CAAC;oBAED,OAAO,EAAE,QAAQ,EAAE,OAAgB,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;gBAC7D,CAAC;aACF,CAAC;YACF,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,OAAO,yBAAyB,CAAC,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;YACtE,CAAC;YACD,OAAO,yBAAyB,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAEO,gBAAgB,CACtB,SAAiB,EACjB,OAAsC,EACtC,MAAoB;QAEpB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAE/D,mEAAmE;YACnE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBACrC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBAC5C,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,QAAwC;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAClE,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3B,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,uBAAuB;QACrB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAQlB;QACC,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,CAAU,CAAC;QACpF,MAAM,KAAK,GAAoB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAqB,CAAC;YAC5E,CAAC,CAAE,IAAI,CAAC,cAAkC,CAAC,CAAC,CAAC,aAAa,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE;YACxD,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,cAAc,EAAE,IAAI,CAAC,cAAc;SACpC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY;YAC9B,CAAC,CAAC,oBAAoB,IAAI,CAAC,YAAY,QAAQ,IAAI,CAAC,MAAM,EAAE;YAC5D,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAEhB,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACtC,SAAS,EAAE,cAAuC;YAClD,OAAO,EAAE,IAAI,CAAC,MAAM;SACrB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACtD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE;gBAChD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;oBACpB,OAAO;oBACP,SAAS,EAAE,EAAE;oBACb,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,SAAS,EAAE,IAAI;oBACf,eAAe,EAAE,IAAI;oBACrB,eAAe,EAAE,KAAK;iBACvB,CAAC,CAAC;gBACH,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;gBAC3B,OAAO,CAAC,EAAE,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAKnB;QACC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEnD,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YACzD,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC;YAC1B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAClB,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBAClD,SAAS,EAAE,cAAuC;gBAClD,OAAO,EAAE,IAAI,CAAC,MAAM;aACrB,CAAC,CAAC;YACH,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAEzC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACvD,8BAA8B;YAChC,CAAC,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE;YAClE,eAAe,EAAE,IAAI,CAAC,SAAS;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ;YAClD,SAAS,EAAE,cAAuC;YAClD,OAAO,EAAE,IAAI,CAAC,MAAM;SACrB,CAAC,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,eAAe,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YAC5D,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE;gBAChD,IAAI,EAAE,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;oBAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;wBAClB,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACtC,SAAS,EAAE,QAAQ;wBACnB,OAAO,EAAE,oCAAoC,EAAE,wBAAwB,IAAI,CAAC,SAAS,EAAE;qBACxF,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;oBACpB,OAAO;oBACP,SAAS,EAAE,EAAE;oBACb,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,SAAS,EAAE,IAAI;oBACf,eAAe,EAAE,IAAI;oBACrB,eAAe,EAAE,aAAgC;iBAClD,CAAC,CAAC;gBACH,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;gBAC3B,OAAO,CAAC,EAAE,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,aAAa,CAAC,SAAiB;QAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QACtB,oDAAoD;QACpD,IAAI,EAAE,CAAC,eAAe,EAAE,CAAC;YACvB,EAAE,CAAC,eAAe,EAAE,CAAC;QACvB,CAAC;QACD,EAAE,CAAC,SAAS,GAAG,KAAK,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB,CAAC,SAAiB,EAAE,KAAsB;QAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QACtB,EAAE,CAAC,eAAe,GAAG,KAAK,CAAC;QAE3B,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB,CAAC,SAAiB;QAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,eAAe,IAAI,aAAa,CAAC;IACxE,CAAC;IAED,YAAY,CAAC,SAAiB;QAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QACtB,2BAA2B;QAC3B,IAAI,EAAE,CAAC,eAAe,EAAE,CAAC;YACvB,EAAE,CAAC,eAAe,EAAE,CAAC;QACvB,CAAC;QACD,2BAA2B;QAC3B,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,WAAW,CAAC,SAAiB;QAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,SAAS,IAAI,KAAK,CAAC;IAC1D,CAAC;IAED,MAAM,CAAC,SAAiB;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,qBAAqB;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,sDAAsD;QACtD,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC7D,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAElC,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,OAAmB,EACnB,QAAgB,EAChB,WAAiC;QAEjC,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,IAAI,WAAW,GAAyC,IAAI,CAAC;QAC7D,IAAI,iBAAiB,GAAkB,IAAI,CAAC;QAC5C,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,MAAM,UAAU,GAAG,CAAC,KAAkD,EAAE,EAAE;YACxE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,iBAAiB,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClF,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;gBACjE,UAAU,GAAG,EAAE,CAAC;YAClB,CAAC;YACD,IAAI,WAAW,EAAE,CAAC;gBAChB,YAAY,CAAC,WAAW,CAAC,CAAC;gBAC1B,WAAW,GAAG,IAAI,CAAC;YACrB,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,iBAAiB,GAAG,GAAG,EAAE;YAC7B,IAAI,iBAAiB,EAAE,CAAC;gBACtB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAChD,IAAI,EAAE,EAAE,CAAC;oBACP,EAAE,CAAC,SAAS,GAAG,KAAK,CAAC;oBACrB,EAAE,CAAC,eAAe,GAAG,IAAI,CAAC;gBAC5B,CAAC;gBACD,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;YAClC,UAAU,IAAI,IAAI,CAAC;YACnB,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,WAAW,GAAG,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC3C,CAAC;YACD,IAAI,UAAU,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;gBAC7B,SAAS,EAAE,CAAC;YACd,CAAC;QACH,CAAC,CAAC;QAEF,kDAAkD;QAClD,MAAM,WAAW,GAAG,GAAG,EAAE;YACvB,IAAI,iBAAiB,EAAE,CAAC;gBACtB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAChD,IAAI,EAAE,EAAE,CAAC;oBACP,EAAE,CAAC,eAAe,GAAG,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC7C,IAAI,SAAS;oBAAE,MAAM;gBAErB,uCAAuC;gBACvC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAK,OAAe,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;oBACrE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;oBACvC,OAAO,CAAC,GAAG,CAAC,yBAAyB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;oBAC3D,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;oBAChC,WAAW,EAAE,CAAC;oBACd,SAAS;gBACX,CAAC;gBAED,oDAAoD;gBACpD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAK,OAAe,CAAC,OAAO,KAAK,uBAAuB,EAAE,CAAC;oBACtF,MAAM,KAAK,GAAI,OAAe,CAAC,KAAK,CAAC;oBACrC,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;wBACrB,SAAS,EAAE,CAAC;wBACZ,OAAO,CAAC,GAAG,CAAC,+CAA+C,iBAAiB,EAAE,CAAC,CAAC;wBAChF,yDAAyD;oBAC3D,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,2BAA2B;gBAC3B,IAAI,OAAO,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACpC,MAAM,KAAK,GAAI,OAAe,CAAC,KAAK,CAAC;oBACrC,IAAI,KAAK,EAAE,IAAI,KAAK,qBAAqB,EAAE,CAAC;wBAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;wBAC1B,IAAI,KAAK,EAAE,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;4BAC/C,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBACzB,CAAC;oBACH,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,8BAA8B;gBAC9B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBACjC,SAAS,EAAE,CAAC;oBACZ,MAAM,WAAW,GAAI,OAAe,CAAC,OAAO,CAAC;oBAC7C,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;wBACzB,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;4BACxC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gCACxC,UAAU,CAAC;oCACT,SAAS,EAAE,gBAAgB;oCAC3B,OAAO,EAAE,KAAK,CAAC,IAAI;iCACpB,CAAC,CAAC;4BACL,CAAC;iCAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gCACrC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gCAC9C,UAAU,CAAC;oCACT,SAAS,EAAE,UAAU;oCACrB,OAAO,EAAE,EAAE;oCACX,QAAQ,EAAE,KAAK,CAAC,IAAI;oCACpB,SAAS;iCACV,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;oBACH,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,qCAAqC;gBACrC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC5B,MAAM,OAAO,GAAI,OAAe,CAAC,OAAO,CAAC;oBACzC,IAAI,OAAO,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;wBACvD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;4BACpC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gCACjC,MAAM,aAAa,GAAG,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gCAC3D,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,GAAG,2BAA2B;oCAClE,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,GAAG,cAAc;oCACtE,CAAC,CAAC,aAAa,CAAC;gCAClB,UAAU,CAAC;oCACT,SAAS,EAAE,aAAa;oCACxB,OAAO,EAAE,SAAS;iCACnB,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;oBACH,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,0DAA0D;gBAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC9B,SAAS,EAAE,CAAC;oBACZ,MAAM,MAAM,GAAG,OAAc,CAAC;oBAC9B,OAAO,CAAC,GAAG,CAAC,2BAA2B,iBAAiB,YAAY,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;oBACxI,iBAAiB,EAAE,CAAC;oBACpB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;wBACtB,SAAS,EAAE,iBAAiB,IAAI,EAAE,EAAE,QAAQ;wBAC5C,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,SAAS;wBACrC,KAAK,EAAE,MAAM,CAAC,OAAO,KAAK,SAAS;4BACjC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,kBAAkB,MAAM,CAAC,OAAO,EAAE,CAAC;4BACnE,CAAC,CAAC,SAAS;wBACb,YAAY,EAAE,MAAM,CAAC,cAAc;wBACnC,UAAU,EAAE,MAAM,CAAC,KAAK;4BACtB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE;4BAC1E,CAAC,CAAC,SAAS;qBACd,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;YACH,CAAC;YAED,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,yCAAyC,iBAAiB,yBAAyB,CAAC,CAAC;YACjG,iBAAiB,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,iBAAiB,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,iBAAiB,GAAG,EAAE,KAAK,CAAC,CAAC;YACrE,iBAAiB,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,iBAAiB,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACxG,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSONL persistence for Claude session message history.
|
|
3
|
+
*
|
|
4
|
+
* Each session gets a file at:
|
|
5
|
+
* ~/.quicksave/state/sessions/<session-id>/messages.jsonl
|
|
6
|
+
*
|
|
7
|
+
* One JSON object per line, matching ClaudeHistoryMessage shape.
|
|
8
|
+
* Append-only writes; full-file reads on cold resume.
|
|
9
|
+
*/
|
|
10
|
+
import type { ClaudeHistoryMessage } from '@sumicom/quicksave-shared';
|
|
11
|
+
/**
|
|
12
|
+
* Return the directory for a specific session's persistent data.
|
|
13
|
+
* Creates the directory if it doesn't exist.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getSessionDir(sessionId: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Return the path to a session's messages JSONL file.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getMessagesFilePath(sessionId: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Append a single message to the session's JSONL file.
|
|
22
|
+
* Errors are logged, not thrown.
|
|
23
|
+
*/
|
|
24
|
+
export declare function appendMessageToJSONL(sessionId: string, message: ClaudeHistoryMessage): void;
|
|
25
|
+
/**
|
|
26
|
+
* Load all messages from a session's JSONL file.
|
|
27
|
+
* Returns empty array if file doesn't exist or is unreadable.
|
|
28
|
+
* Skips malformed lines with a warning.
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadMessagesFromJSONL(sessionId: string): ClaudeHistoryMessage[];
|
|
31
|
+
//# sourceMappingURL=sessionStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/ai/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,oBAAoB,GAC5B,IAAI,CAWN;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAChB,oBAAoB,EAAE,CA2BxB"}
|