@sumicom/quicksave 0.6.0 → 0.6.1
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/asyncQueue.d.ts +7 -6
- package/dist/ai/asyncQueue.d.ts.map +1 -1
- package/dist/ai/asyncQueue.js +31 -21
- package/dist/ai/asyncQueue.js.map +1 -1
- package/dist/ai/asyncQueue.test.js +18 -18
- package/dist/ai/asyncQueue.test.js.map +1 -1
- package/dist/ai/cardBuilder.d.ts +11 -2
- package/dist/ai/cardBuilder.d.ts.map +1 -1
- package/dist/ai/cardBuilder.js +113 -21
- package/dist/ai/cardBuilder.js.map +1 -1
- package/dist/ai/claudeCliProvider.d.ts +19 -0
- package/dist/ai/claudeCliProvider.d.ts.map +1 -0
- package/dist/ai/claudeCliProvider.js +466 -0
- package/dist/ai/claudeCliProvider.js.map +1 -0
- package/dist/ai/claudeSdkProvider.d.ts +18 -0
- package/dist/ai/claudeSdkProvider.d.ts.map +1 -0
- package/dist/ai/claudeSdkProvider.js +418 -0
- package/dist/ai/claudeSdkProvider.js.map +1 -0
- package/dist/ai/commitSummary.d.ts +4 -0
- package/dist/ai/commitSummary.d.ts.map +1 -1
- package/dist/ai/commitSummary.js +80 -40
- package/dist/ai/commitSummary.js.map +1 -1
- package/dist/ai/provider.d.ts +54 -0
- package/dist/ai/provider.d.ts.map +1 -0
- package/dist/ai/provider.js +2 -0
- package/dist/ai/provider.js.map +1 -0
- package/dist/ai/sandboxMcp.d.ts +12 -0
- package/dist/ai/sandboxMcp.d.ts.map +1 -0
- package/dist/ai/sandboxMcp.js +12 -0
- package/dist/ai/sandboxMcp.js.map +1 -0
- package/dist/ai/sandboxMcpStdio.d.ts +16 -0
- package/dist/ai/sandboxMcpStdio.d.ts.map +1 -0
- package/dist/ai/sandboxMcpStdio.js +127 -0
- package/dist/ai/sandboxMcpStdio.js.map +1 -0
- package/dist/ai/sessionManager.d.ts +100 -0
- package/dist/ai/sessionManager.d.ts.map +1 -0
- package/dist/ai/sessionManager.js +595 -0
- package/dist/ai/sessionManager.js.map +1 -0
- package/dist/ai/sessionRegistry.d.ts +28 -0
- package/dist/ai/sessionRegistry.d.ts.map +1 -0
- package/dist/ai/sessionRegistry.js +148 -0
- package/dist/ai/sessionRegistry.js.map +1 -0
- package/dist/git/operations.d.ts +6 -1
- package/dist/git/operations.d.ts.map +1 -1
- package/dist/git/operations.js +31 -2
- package/dist/git/operations.js.map +1 -1
- package/dist/handlers/messageHandler.d.ts +8 -3
- package/dist/handlers/messageHandler.d.ts.map +1 -1
- package/dist/handlers/messageHandler.js +96 -12
- package/dist/handlers/messageHandler.js.map +1 -1
- package/dist/handlers/messageHandler.test.js +1 -1
- package/dist/index.js +3 -40
- package/dist/index.js.map +1 -1
- package/dist/service/ensureDaemon.d.ts.map +1 -1
- package/dist/service/ensureDaemon.js +15 -2
- package/dist/service/ensureDaemon.js.map +1 -1
- package/dist/service/ipc.test.js +6 -6
- package/dist/service/ipcClient.js +1 -1
- package/dist/service/run.d.ts.map +1 -1
- package/dist/service/run.js +22 -15
- package/dist/service/run.js.map +1 -1
- package/dist/service/singleton.d.ts +4 -0
- package/dist/service/singleton.d.ts.map +1 -1
- package/dist/service/singleton.js +28 -2
- package/dist/service/singleton.js.map +1 -1
- package/dist/service/singleton.test.js +1 -1
- package/package.json +5 -3
- package/dist/ai/claudeCodeService.d.ts +0 -122
- package/dist/ai/claudeCodeService.d.ts.map +0 -1
- package/dist/ai/claudeCodeService.js +0 -869
- package/dist/ai/claudeCodeService.js.map +0 -1
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { resolve, join } from 'path';
|
|
3
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
4
|
+
import { DEFAULT_MODEL, matchAllowPattern } from '@sumicom/quicksave-shared';
|
|
5
|
+
import { StreamCardBuilder, buildCardsFromHistory } from './cardBuilder.js';
|
|
6
|
+
import { SANDBOX_BASH_TOOL, SET_TITLE_TOOL } from './sandboxMcp.js';
|
|
7
|
+
import { getSessionRegistry } from './sessionRegistry.js';
|
|
8
|
+
/**
|
|
9
|
+
* Events emitted:
|
|
10
|
+
* 'card-event' (event: CardEvent)
|
|
11
|
+
* 'card-stream-end' (result: CardStreamEnd)
|
|
12
|
+
* 'user-input-request' (request: ClaudeUserInputRequestPayload)
|
|
13
|
+
* 'user-input-resolved' ({ requestId, sessionId })
|
|
14
|
+
* 'session-updated' ({ sessionId, isActive, isStreaming, hasPendingInput, permissionMode })
|
|
15
|
+
* 'preferences-updated' (prefs: ClaudePreferences)
|
|
16
|
+
* 'session-config-updated' ({ sessionId, config: Record<string, ConfigValue> })
|
|
17
|
+
*/
|
|
18
|
+
/** Tools auto-approved at each permission level (no user prompt). */
|
|
19
|
+
const AUTO_APPROVE = {
|
|
20
|
+
bypassPermissions: new Set([
|
|
21
|
+
'Edit', 'Write', 'NotebookEdit', 'TodoWrite', 'Agent', 'EnterWorktree', 'ExitWorktree',
|
|
22
|
+
'WebFetch', 'WebSearch', 'Bash',
|
|
23
|
+
'Skill', 'ToolSearch', 'Config',
|
|
24
|
+
'CronCreate', 'CronDelete', 'CronList', 'RemoteTrigger',
|
|
25
|
+
'EnterPlanMode', 'ExitPlanMode',
|
|
26
|
+
'TaskOutput', 'TaskStop',
|
|
27
|
+
]),
|
|
28
|
+
acceptEdits: new Set(['Edit', 'Write', 'NotebookEdit', 'TodoWrite', 'Agent', 'EnterWorktree', 'ExitWorktree', 'EnterPlanMode']),
|
|
29
|
+
default: new Set(['TodoWrite', 'EnterWorktree', 'ExitWorktree', 'Agent', 'EnterPlanMode']),
|
|
30
|
+
plan: new Set(['EnterPlanMode']),
|
|
31
|
+
};
|
|
32
|
+
const DEFAULT_SYSTEM_PROMPT = [
|
|
33
|
+
'For non-destructive shell commands (ls, cat, find, git log, git status, git diff, etc.), prefer SandboxBash over Bash. SandboxBash runs in a sandboxed environment. Use Bash only for commands that modify state.',
|
|
34
|
+
'Call SetTitle to set a descriptive session title when you start a new task or switch context. Keep titles short (e.g. "Fixing auth middleware", "Adding unit tests for UserService"). Update it when the focus changes.',
|
|
35
|
+
].join('\n\n');
|
|
36
|
+
function buildSystemPrompt(extra) {
|
|
37
|
+
return extra ? `${DEFAULT_SYSTEM_PROMPT}\n\n${extra}` : DEFAULT_SYSTEM_PROMPT;
|
|
38
|
+
}
|
|
39
|
+
export class SessionManager extends EventEmitter {
|
|
40
|
+
sessions = new Map();
|
|
41
|
+
sessionPermissions = new Map();
|
|
42
|
+
sessionSandboxed = new Map();
|
|
43
|
+
sessionConfigs = new Map();
|
|
44
|
+
pendingInputRequests = new Map();
|
|
45
|
+
requestCounter = 0;
|
|
46
|
+
runtimeAllowPatterns = [];
|
|
47
|
+
preferences = { model: DEFAULT_MODEL };
|
|
48
|
+
provider;
|
|
49
|
+
/** SDK-based provider (alternative to CLI). Selected by QUICKSAVE_PROVIDER=sdk env var. */
|
|
50
|
+
sdkProvider;
|
|
51
|
+
/** Guards against concurrent cold resumes. Queues prompts arriving while a spawn is in flight. */
|
|
52
|
+
coldResumeInFlight = new Map();
|
|
53
|
+
constructor(provider, sdkProvider) {
|
|
54
|
+
super();
|
|
55
|
+
this.provider = provider;
|
|
56
|
+
this.sdkProvider = sdkProvider;
|
|
57
|
+
}
|
|
58
|
+
/** Select provider based on QUICKSAVE_PROVIDER env var. Default: CLI. */
|
|
59
|
+
getActiveProvider() {
|
|
60
|
+
if (process.env.QUICKSAVE_PROVIDER === 'sdk' && this.sdkProvider) {
|
|
61
|
+
return this.sdkProvider;
|
|
62
|
+
}
|
|
63
|
+
return this.provider;
|
|
64
|
+
}
|
|
65
|
+
// ── Preferences ──
|
|
66
|
+
async initPreferences() {
|
|
67
|
+
// Model is tracked from the last session's init event via onModelDetected callback.
|
|
68
|
+
}
|
|
69
|
+
getPreferences() {
|
|
70
|
+
return { ...this.preferences };
|
|
71
|
+
}
|
|
72
|
+
setPreferences(prefs) {
|
|
73
|
+
const next = { ...this.preferences };
|
|
74
|
+
let changed = false;
|
|
75
|
+
if (prefs.model !== undefined && prefs.model !== this.preferences.model) {
|
|
76
|
+
next.model = prefs.model;
|
|
77
|
+
changed = true;
|
|
78
|
+
}
|
|
79
|
+
if (prefs.reasoningEffort !== undefined && prefs.reasoningEffort !== this.preferences.reasoningEffort) {
|
|
80
|
+
next.reasoningEffort = prefs.reasoningEffort;
|
|
81
|
+
changed = true;
|
|
82
|
+
}
|
|
83
|
+
if (changed) {
|
|
84
|
+
this.preferences = next;
|
|
85
|
+
this.emit('preferences-updated', this.preferences);
|
|
86
|
+
}
|
|
87
|
+
return { ...this.preferences };
|
|
88
|
+
}
|
|
89
|
+
// ── Session Config ──
|
|
90
|
+
getSessionConfig(sessionId) {
|
|
91
|
+
return { ...this.sessionConfigs.get(sessionId) };
|
|
92
|
+
}
|
|
93
|
+
setSessionConfig(sessionId, key, value) {
|
|
94
|
+
const prev = this.sessionConfigs.get(sessionId) ?? {};
|
|
95
|
+
const next = { ...prev, [key]: value };
|
|
96
|
+
this.sessionConfigs.set(sessionId, next);
|
|
97
|
+
if (key === 'model' && typeof value === 'string') {
|
|
98
|
+
this.setPreferences({ model: value });
|
|
99
|
+
}
|
|
100
|
+
else if (key === 'reasoningEffort' && (typeof value === 'string' || value === null)) {
|
|
101
|
+
this.setPreferences({ reasoningEffort: value });
|
|
102
|
+
}
|
|
103
|
+
else if (key === 'permissionMode' && typeof value === 'string') {
|
|
104
|
+
this.setPermissionLevel(sessionId, value);
|
|
105
|
+
}
|
|
106
|
+
else if (key === 'sandboxed' && typeof value === 'boolean') {
|
|
107
|
+
this.sessionSandboxed.set(sessionId, value);
|
|
108
|
+
const ps = this.sessions.get(sessionId);
|
|
109
|
+
if (ps)
|
|
110
|
+
ps.sandboxed = value;
|
|
111
|
+
}
|
|
112
|
+
this.emit('session-config-updated', { sessionId, config: next });
|
|
113
|
+
return next;
|
|
114
|
+
}
|
|
115
|
+
// ── Session Lifecycle ──
|
|
116
|
+
async startSession(opts) {
|
|
117
|
+
const validModes = ['default', 'acceptEdits', 'bypassPermissions', 'plan'];
|
|
118
|
+
const level = validModes.includes(opts.permissionMode)
|
|
119
|
+
? opts.permissionMode : 'acceptEdits';
|
|
120
|
+
const sandboxed = !!opts.sandboxed;
|
|
121
|
+
const systemPrompt = buildSystemPrompt(opts.systemPrompt);
|
|
122
|
+
// Create cardBuilder with 'pending' sessionId — will be updated after provider returns real one
|
|
123
|
+
const cardBuilder = new StreamCardBuilder('pending', opts.streamId, opts.cwd);
|
|
124
|
+
const callbacks = this.makeCallbacks('pending');
|
|
125
|
+
const { sessionId, session: providerSession } = await this.getActiveProvider().startSession({
|
|
126
|
+
prompt: opts.prompt,
|
|
127
|
+
cwd: opts.cwd,
|
|
128
|
+
streamId: opts.streamId,
|
|
129
|
+
model: opts.model,
|
|
130
|
+
permissionLevel: level,
|
|
131
|
+
sandboxed,
|
|
132
|
+
systemPrompt,
|
|
133
|
+
}, cardBuilder, callbacks);
|
|
134
|
+
// Update cardBuilder with real sessionId — new session has no prior JSONL
|
|
135
|
+
cardBuilder.updateSessionId(sessionId);
|
|
136
|
+
cardBuilder.jsonlCutoff = 0;
|
|
137
|
+
// Update callbacks to use real sessionId (re-bind the closures)
|
|
138
|
+
// The callbacks are already handed to the provider; for the permission handler
|
|
139
|
+
// we capture `sessionId` from the request parameter, so this is safe.
|
|
140
|
+
// Register session
|
|
141
|
+
this.sessionPermissions.set(sessionId, level);
|
|
142
|
+
if (sandboxed)
|
|
143
|
+
this.sessionSandboxed.set(sessionId, true);
|
|
144
|
+
const prevConfig = this.sessionConfigs.get(sessionId) ?? {};
|
|
145
|
+
this.sessionConfigs.set(sessionId, {
|
|
146
|
+
...prevConfig,
|
|
147
|
+
model: opts.model ?? DEFAULT_MODEL,
|
|
148
|
+
permissionMode: level,
|
|
149
|
+
sandboxed,
|
|
150
|
+
});
|
|
151
|
+
const managed = {
|
|
152
|
+
sessionId,
|
|
153
|
+
providerSession,
|
|
154
|
+
cwd: opts.cwd,
|
|
155
|
+
streaming: true,
|
|
156
|
+
permissionLevel: level,
|
|
157
|
+
sandboxed,
|
|
158
|
+
cardBuilder,
|
|
159
|
+
};
|
|
160
|
+
this.sessions.set(sessionId, managed);
|
|
161
|
+
this.emitSessionUpdate(sessionId);
|
|
162
|
+
return sessionId;
|
|
163
|
+
}
|
|
164
|
+
async resumeSession(opts) {
|
|
165
|
+
const existing = this.sessions.get(opts.sessionId);
|
|
166
|
+
// Hot resume: session is streaming and provider session is alive
|
|
167
|
+
if (existing?.streaming && existing.providerSession?.alive) {
|
|
168
|
+
console.log(`[session-manager] hot resume session=${opts.sessionId.slice(0, 8)} streaming=true`);
|
|
169
|
+
// Add user prompt to cardBuilder for getCards on reconnect
|
|
170
|
+
if (existing.cardBuilder) {
|
|
171
|
+
existing.cardBuilder.userMessage(opts.prompt);
|
|
172
|
+
}
|
|
173
|
+
// Queue the streamId so consumeStream picks it up after the current turn's result
|
|
174
|
+
const ps = existing.providerSession;
|
|
175
|
+
if (ps.pendingStreamIds) {
|
|
176
|
+
ps.pendingStreamIds.push(opts.streamId);
|
|
177
|
+
}
|
|
178
|
+
existing.providerSession.sendUserMessage(opts.prompt);
|
|
179
|
+
return opts.sessionId;
|
|
180
|
+
}
|
|
181
|
+
// Cold resume already in flight — queue the prompt instead of spawning again
|
|
182
|
+
const inFlight = this.coldResumeInFlight.get(opts.sessionId);
|
|
183
|
+
if (inFlight) {
|
|
184
|
+
console.log(`[session-manager] cold resume in flight, queuing prompt for session=${opts.sessionId.slice(0, 8)}`);
|
|
185
|
+
inFlight.queuedPrompts.push(opts.prompt);
|
|
186
|
+
return opts.sessionId;
|
|
187
|
+
}
|
|
188
|
+
// Cold resume: mark as in-flight, then delegate to provider
|
|
189
|
+
console.log(`[session-manager] cold resume session=${opts.sessionId.slice(0, 8)}`);
|
|
190
|
+
const flight = { queuedPrompts: [] };
|
|
191
|
+
this.coldResumeInFlight.set(opts.sessionId, flight);
|
|
192
|
+
try {
|
|
193
|
+
const level = this.sessionPermissions.get(opts.sessionId) ?? 'acceptEdits';
|
|
194
|
+
const sandboxed = this.sessionSandboxed.get(opts.sessionId) ?? false;
|
|
195
|
+
const cardBuilder = existing?.cardBuilder ?? new StreamCardBuilder(opts.sessionId, opts.streamId, opts.cwd);
|
|
196
|
+
await cardBuilder.snapshotCutoff();
|
|
197
|
+
const callbacks = this.makeCallbacks(opts.sessionId);
|
|
198
|
+
const { sessionId, session: providerSession } = await this.getActiveProvider().resumeSession({
|
|
199
|
+
sessionId: opts.sessionId,
|
|
200
|
+
prompt: opts.prompt,
|
|
201
|
+
cwd: opts.cwd,
|
|
202
|
+
streamId: opts.streamId,
|
|
203
|
+
permissionLevel: level,
|
|
204
|
+
sandboxed,
|
|
205
|
+
systemPrompt: buildSystemPrompt(),
|
|
206
|
+
}, cardBuilder, callbacks);
|
|
207
|
+
// Update or create session entry
|
|
208
|
+
if (existing) {
|
|
209
|
+
existing.providerSession = providerSession;
|
|
210
|
+
existing.streaming = true;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
const managed = {
|
|
214
|
+
sessionId,
|
|
215
|
+
providerSession,
|
|
216
|
+
cwd: opts.cwd,
|
|
217
|
+
streaming: true,
|
|
218
|
+
permissionLevel: level,
|
|
219
|
+
sandboxed,
|
|
220
|
+
cardBuilder,
|
|
221
|
+
};
|
|
222
|
+
this.sessions.set(sessionId, managed);
|
|
223
|
+
}
|
|
224
|
+
this.emitSessionUpdate(sessionId);
|
|
225
|
+
// Drain queued prompts that arrived while spawning
|
|
226
|
+
for (const queued of flight.queuedPrompts) {
|
|
227
|
+
console.log(`[session-manager] draining queued prompt for session=${sessionId.slice(0, 8)}`);
|
|
228
|
+
providerSession.sendUserMessage(queued);
|
|
229
|
+
}
|
|
230
|
+
return sessionId;
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
this.coldResumeInFlight.delete(opts.sessionId);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async cancelSession(sessionId) {
|
|
237
|
+
const ps = this.sessions.get(sessionId);
|
|
238
|
+
if (!ps?.providerSession)
|
|
239
|
+
return false;
|
|
240
|
+
console.log(`[session-manager] cancel session=${sessionId.slice(0, 8)}`);
|
|
241
|
+
ps.providerSession.interrupt();
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
closeSession(sessionId) {
|
|
245
|
+
const ps = this.sessions.get(sessionId);
|
|
246
|
+
if (!ps)
|
|
247
|
+
return false;
|
|
248
|
+
if (ps.providerSession) {
|
|
249
|
+
ps.providerSession.kill();
|
|
250
|
+
ps.providerSession = null;
|
|
251
|
+
}
|
|
252
|
+
this.sessions.delete(sessionId);
|
|
253
|
+
this.emitSessionUpdate(sessionId);
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
// ── Permission ──
|
|
257
|
+
setPermissionLevel(sessionId, level) {
|
|
258
|
+
const ps = this.sessions.get(sessionId);
|
|
259
|
+
if (ps)
|
|
260
|
+
ps.permissionLevel = level;
|
|
261
|
+
this.sessionPermissions.set(sessionId, level);
|
|
262
|
+
this.emit('session-updated', {
|
|
263
|
+
sessionId,
|
|
264
|
+
isActive: !!ps,
|
|
265
|
+
isStreaming: ps?.streaming ?? false,
|
|
266
|
+
hasPendingInput: ps ? Array.from(this.pendingInputRequests.values()).some(p => p.request.sessionId === sessionId) : false,
|
|
267
|
+
permissionMode: level,
|
|
268
|
+
});
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
getPermissionLevel(sessionId) {
|
|
272
|
+
return this.sessions.get(sessionId)?.permissionLevel ?? 'acceptEdits';
|
|
273
|
+
}
|
|
274
|
+
resolveUserInput(response) {
|
|
275
|
+
const pending = this.pendingInputRequests.get(response.requestId);
|
|
276
|
+
if (!pending)
|
|
277
|
+
return false;
|
|
278
|
+
this.pendingInputRequests.delete(response.requestId);
|
|
279
|
+
pending.resolve(response);
|
|
280
|
+
// Clear pending input on the card
|
|
281
|
+
const ps = this.sessions.get(pending.request.sessionId);
|
|
282
|
+
if (ps?.cardBuilder) {
|
|
283
|
+
const cardEvt = ps.cardBuilder.clearPendingInput(response.requestId);
|
|
284
|
+
if (cardEvt)
|
|
285
|
+
this.emit('card-event', cardEvt);
|
|
286
|
+
}
|
|
287
|
+
// Persist allow pattern to settings.local.json if provided
|
|
288
|
+
if (response.allowPattern && ps?.cwd) {
|
|
289
|
+
this.persistAllowPattern(ps.cwd, response.allowPattern).catch((err) => {
|
|
290
|
+
console.error('[persistAllowPattern] failed:', err);
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
this.emit('user-input-resolved', { requestId: response.requestId, sessionId: pending.request.sessionId });
|
|
294
|
+
this.emitSessionUpdate(pending.request.sessionId);
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
// ── Query ──
|
|
298
|
+
getActiveSessions() {
|
|
299
|
+
const pendingSessionIds = new Set(Array.from(this.pendingInputRequests.values()).map(p => p.request.sessionId));
|
|
300
|
+
return Array.from(this.sessions.entries()).map(([id, ps]) => ({
|
|
301
|
+
sessionId: id,
|
|
302
|
+
cwd: ps.cwd,
|
|
303
|
+
isStreaming: ps.streaming,
|
|
304
|
+
hasPendingInput: pendingSessionIds.has(id),
|
|
305
|
+
permissionMode: ps.permissionLevel,
|
|
306
|
+
sandboxed: ps.sandboxed || undefined,
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
isStreaming(sessionId) {
|
|
310
|
+
return this.sessions.get(sessionId)?.streaming ?? false;
|
|
311
|
+
}
|
|
312
|
+
isOpen(sessionId) {
|
|
313
|
+
return this.sessions.has(sessionId);
|
|
314
|
+
}
|
|
315
|
+
getSessionCwd(sessionId) {
|
|
316
|
+
return this.sessions.get(sessionId)?.cwd;
|
|
317
|
+
}
|
|
318
|
+
getActiveSessionCount() {
|
|
319
|
+
return this.sessions.size;
|
|
320
|
+
}
|
|
321
|
+
getCardBuilder(sessionId) {
|
|
322
|
+
return this.sessions.get(sessionId)?.cardBuilder ?? null;
|
|
323
|
+
}
|
|
324
|
+
async listAvailableSessions(cwd) {
|
|
325
|
+
const registry = getSessionRegistry();
|
|
326
|
+
const registryEntries = registry.getEntriesForProject(cwd);
|
|
327
|
+
const pendingSessionIds = new Set(Array.from(this.pendingInputRequests.values()).map(p => p.request.sessionId));
|
|
328
|
+
return registryEntries.map(entry => ({
|
|
329
|
+
sessionId: entry.sessionId,
|
|
330
|
+
summary: entry.title ?? entry.firstPrompt ?? entry.sessionId.slice(0, 8),
|
|
331
|
+
lastModified: entry.lastAccessedAt,
|
|
332
|
+
createdAt: entry.createdAt,
|
|
333
|
+
cwd: entry.cwd,
|
|
334
|
+
gitBranch: entry.gitBranch,
|
|
335
|
+
messageCount: entry.messageCount,
|
|
336
|
+
isActive: this.sessions.has(entry.sessionId),
|
|
337
|
+
isStreaming: this.sessions.get(entry.sessionId)?.streaming ?? false,
|
|
338
|
+
hasPendingInput: pendingSessionIds.has(entry.sessionId),
|
|
339
|
+
permissionMode: this.sessions.get(entry.sessionId)?.permissionLevel
|
|
340
|
+
?? this.sessionPermissions.get(entry.sessionId),
|
|
341
|
+
}));
|
|
342
|
+
}
|
|
343
|
+
async getCards(sessionId, cwd, offset = 0, limit = 50) {
|
|
344
|
+
const ps = this.sessions.get(sessionId);
|
|
345
|
+
const cutoff = ps?.cardBuilder?.jsonlCutoff ?? undefined;
|
|
346
|
+
// Read JSONL history up to the cutoff (excludes the active turn's messages).
|
|
347
|
+
const result = await buildCardsFromHistory(sessionId, cwd, offset, limit, cutoff);
|
|
348
|
+
// Append in-memory cards for the active turn — no overlap, no dedup needed.
|
|
349
|
+
if (ps?.cardBuilder) {
|
|
350
|
+
const streamingCards = ps.cardBuilder.getCards();
|
|
351
|
+
if (streamingCards.length > 0) {
|
|
352
|
+
result.cards.push(...streamingCards);
|
|
353
|
+
result.total += streamingCards.length;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// Overlay pending inputs from pendingInputRequests onto matching cards.
|
|
357
|
+
const pendingByToolUseId = new Map();
|
|
358
|
+
for (const [, pending] of this.pendingInputRequests) {
|
|
359
|
+
if (pending.request.sessionId === sessionId && pending.request.toolUseId) {
|
|
360
|
+
pendingByToolUseId.set(pending.request.toolUseId, {
|
|
361
|
+
sessionId: pending.request.sessionId,
|
|
362
|
+
requestId: pending.request.requestId,
|
|
363
|
+
inputType: pending.request.inputType,
|
|
364
|
+
title: pending.request.title,
|
|
365
|
+
message: pending.request.message,
|
|
366
|
+
options: pending.request.options,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (pendingByToolUseId.size > 0) {
|
|
371
|
+
for (const card of result.cards) {
|
|
372
|
+
if (card.type === 'tool_call' && card.toolUseId) {
|
|
373
|
+
const pending = pendingByToolUseId.get(card.toolUseId);
|
|
374
|
+
if (pending && !card.pendingInput) {
|
|
375
|
+
card.pendingInput = pending;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// Attach session title from config or registry
|
|
381
|
+
const configTitle = this.sessionConfigs.get(sessionId)?.title;
|
|
382
|
+
if (configTitle) {
|
|
383
|
+
result.title = configTitle;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
const registry = getSessionRegistry();
|
|
387
|
+
const entry = registry.getEntry(cwd, sessionId);
|
|
388
|
+
if (entry?.title)
|
|
389
|
+
result.title = entry.title;
|
|
390
|
+
}
|
|
391
|
+
return result;
|
|
392
|
+
}
|
|
393
|
+
getPendingInputRequests() {
|
|
394
|
+
return Array.from(this.pendingInputRequests.values()).map(p => p.request);
|
|
395
|
+
}
|
|
396
|
+
getDebugState() {
|
|
397
|
+
const pendingInputs = Array.from(this.pendingInputRequests.values()).map(p => ({
|
|
398
|
+
requestId: p.request.requestId,
|
|
399
|
+
sessionId: p.request.sessionId,
|
|
400
|
+
toolName: p.request.toolName,
|
|
401
|
+
agentId: p.request.agentId,
|
|
402
|
+
inputType: p.request.inputType,
|
|
403
|
+
}));
|
|
404
|
+
return { pendingInputs, activeSessions: this.getActiveSessions() };
|
|
405
|
+
}
|
|
406
|
+
cleanup() {
|
|
407
|
+
for (const [requestId, pending] of this.pendingInputRequests) {
|
|
408
|
+
pending.resolve({ sessionId: '', requestId, action: 'allow' });
|
|
409
|
+
}
|
|
410
|
+
this.pendingInputRequests.clear();
|
|
411
|
+
for (const [, ps] of this.sessions) {
|
|
412
|
+
if (ps.providerSession) {
|
|
413
|
+
try {
|
|
414
|
+
ps.providerSession.kill();
|
|
415
|
+
}
|
|
416
|
+
catch { }
|
|
417
|
+
ps.providerSession = null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
this.sessions.clear();
|
|
421
|
+
}
|
|
422
|
+
// ── Private: Callbacks Factory ──
|
|
423
|
+
makeCallbacks(_initialSessionId) {
|
|
424
|
+
return {
|
|
425
|
+
emitCardEvent: (event) => {
|
|
426
|
+
this.emit('card-event', event);
|
|
427
|
+
},
|
|
428
|
+
emitStreamEnd: (result) => {
|
|
429
|
+
this.emit('card-stream-end', result);
|
|
430
|
+
// Update session streaming state
|
|
431
|
+
const ps = this.sessions.get(result.sessionId);
|
|
432
|
+
if (ps) {
|
|
433
|
+
ps.streaming = false;
|
|
434
|
+
this.emitSessionUpdate(result.sessionId);
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
handlePermissionRequest: async (sessionId, req) => {
|
|
438
|
+
return this.handlePermissionRequest(sessionId, req);
|
|
439
|
+
},
|
|
440
|
+
onModelDetected: (model) => {
|
|
441
|
+
this.preferences.model = model;
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
// ── Private: Permission Handling ──
|
|
446
|
+
async handlePermissionRequest(sessionId, req) {
|
|
447
|
+
const { toolName, toolInput, toolUseId } = req;
|
|
448
|
+
// Check auto-approve rules first
|
|
449
|
+
if (this.shouldAutoApprove(sessionId, toolName, toolInput)) {
|
|
450
|
+
return { action: 'allow' };
|
|
451
|
+
}
|
|
452
|
+
// Check runtime allow patterns
|
|
453
|
+
if (this.runtimeAllowPatterns.some(p => matchAllowPattern(p, toolName, toolInput))) {
|
|
454
|
+
return { action: 'allow' };
|
|
455
|
+
}
|
|
456
|
+
// Forward to PWA for user decision
|
|
457
|
+
const requestId = `perm-${++this.requestCounter}`;
|
|
458
|
+
const isQuestion = toolName === 'AskUserQuestion';
|
|
459
|
+
const questions = isQuestion ? toolInput.questions : undefined;
|
|
460
|
+
const request = {
|
|
461
|
+
sessionId,
|
|
462
|
+
requestId,
|
|
463
|
+
inputType: isQuestion ? 'question' : 'permission',
|
|
464
|
+
title: isQuestion
|
|
465
|
+
? questions?.[0]?.question ?? 'Question from Claude'
|
|
466
|
+
: `Allow ${toolName}?`,
|
|
467
|
+
message: isQuestion ? undefined : JSON.stringify(toolInput).slice(0, 500),
|
|
468
|
+
toolName,
|
|
469
|
+
toolInput,
|
|
470
|
+
toolUseId,
|
|
471
|
+
...(isQuestion && questions ? {
|
|
472
|
+
options: questions.flatMap((q) => (q.options ?? []).map((opt) => ({
|
|
473
|
+
key: opt.label,
|
|
474
|
+
label: opt.label,
|
|
475
|
+
description: opt.description,
|
|
476
|
+
}))),
|
|
477
|
+
} : {}),
|
|
478
|
+
};
|
|
479
|
+
// Create card with pending input
|
|
480
|
+
const ps = this.sessions.get(sessionId);
|
|
481
|
+
const cb = ps?.cardBuilder;
|
|
482
|
+
if (cb) {
|
|
483
|
+
const pendingAttachment = {
|
|
484
|
+
sessionId,
|
|
485
|
+
requestId,
|
|
486
|
+
inputType: request.inputType,
|
|
487
|
+
title: request.title,
|
|
488
|
+
message: request.message,
|
|
489
|
+
options: request.options,
|
|
490
|
+
};
|
|
491
|
+
const cardEvt = cb.toolCallFromPermission(toolName, toolInput, toolUseId, pendingAttachment);
|
|
492
|
+
this.emit('card-event', cardEvt);
|
|
493
|
+
}
|
|
494
|
+
this.emit('user-input-request', request);
|
|
495
|
+
// Wait for user response
|
|
496
|
+
const response = await this.waitForUserInput(requestId, request);
|
|
497
|
+
if (response.action === 'deny') {
|
|
498
|
+
return { action: 'deny', response: response.response || 'User denied permission' };
|
|
499
|
+
}
|
|
500
|
+
// For AskUserQuestion, inject answer
|
|
501
|
+
if (isQuestion && response.response) {
|
|
502
|
+
const answers = {};
|
|
503
|
+
if (questions?.[0]?.question) {
|
|
504
|
+
answers[questions[0].question] = response.response;
|
|
505
|
+
}
|
|
506
|
+
return { action: 'allow', updatedInput: { ...toolInput, answers } };
|
|
507
|
+
}
|
|
508
|
+
return { action: 'allow' };
|
|
509
|
+
}
|
|
510
|
+
shouldAutoApprove(sessionId, toolName, input) {
|
|
511
|
+
// SetTitle — always approve
|
|
512
|
+
if (toolName === SET_TITLE_TOOL) {
|
|
513
|
+
if (input.title)
|
|
514
|
+
this.updateSessionTitle(sessionId, input.title);
|
|
515
|
+
return true;
|
|
516
|
+
}
|
|
517
|
+
// SandboxBash: auto-approve when sandboxed, otherwise check as Bash
|
|
518
|
+
if (toolName === SANDBOX_BASH_TOOL) {
|
|
519
|
+
if (this.sessions.get(sessionId)?.sandboxed)
|
|
520
|
+
return true;
|
|
521
|
+
toolName = 'Bash'; // fall through to permission check as Bash
|
|
522
|
+
}
|
|
523
|
+
// Check permission level auto-approve set
|
|
524
|
+
const level = this.sessions.get(sessionId)?.permissionLevel
|
|
525
|
+
?? this.sessionPermissions.get(sessionId) ?? 'acceptEdits';
|
|
526
|
+
if (!AUTO_APPROVE[level].has(toolName))
|
|
527
|
+
return false;
|
|
528
|
+
// For file-writing tools, restrict to project cwd
|
|
529
|
+
const FILE_WRITE_TOOLS = new Set(['Write', 'Edit', 'NotebookEdit']);
|
|
530
|
+
if (FILE_WRITE_TOOLS.has(toolName)) {
|
|
531
|
+
const cwd = this.sessions.get(sessionId)?.cwd;
|
|
532
|
+
const filePath = (input.file_path ?? input.path);
|
|
533
|
+
if (filePath && cwd) {
|
|
534
|
+
const resolvedFile = resolve(filePath);
|
|
535
|
+
const resolvedCwd = resolve(cwd);
|
|
536
|
+
return resolvedFile === resolvedCwd || resolvedFile.startsWith(resolvedCwd + '/');
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
/** Update session title (triggered by SetTitle MCP tool). */
|
|
542
|
+
updateSessionTitle(sessionId, title) {
|
|
543
|
+
const config = this.sessionConfigs.get(sessionId) ?? {};
|
|
544
|
+
this.sessionConfigs.set(sessionId, { ...config, title });
|
|
545
|
+
this.emit('session-config-updated', { sessionId, config: this.sessionConfigs.get(sessionId) });
|
|
546
|
+
// Update session registry so it persists across restarts
|
|
547
|
+
const ps = this.sessions.get(sessionId);
|
|
548
|
+
if (ps?.cwd) {
|
|
549
|
+
const registry = getSessionRegistry();
|
|
550
|
+
const entry = registry.getEntry(ps.cwd, sessionId);
|
|
551
|
+
if (entry) {
|
|
552
|
+
registry.upsertEntry({ ...entry, title, lastAccessedAt: Date.now() });
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
emitSessionUpdate(sessionId) {
|
|
557
|
+
const ps = this.sessions.get(sessionId);
|
|
558
|
+
const hasPendingInput = Array.from(this.pendingInputRequests.values())
|
|
559
|
+
.some(p => p.request.sessionId === sessionId);
|
|
560
|
+
this.emit('session-updated', {
|
|
561
|
+
sessionId,
|
|
562
|
+
isActive: !!ps,
|
|
563
|
+
isStreaming: ps?.streaming ?? false,
|
|
564
|
+
hasPendingInput,
|
|
565
|
+
permissionMode: ps?.permissionLevel ?? this.sessionPermissions.get(sessionId),
|
|
566
|
+
sandboxed: ps?.sandboxed ?? this.sessionSandboxed.get(sessionId) ?? false,
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
async persistAllowPattern(cwd, pattern) {
|
|
570
|
+
if (!this.runtimeAllowPatterns.includes(pattern)) {
|
|
571
|
+
this.runtimeAllowPatterns.push(pattern);
|
|
572
|
+
}
|
|
573
|
+
const settingsPath = join(cwd, '.claude', 'settings.local.json');
|
|
574
|
+
let settings = {};
|
|
575
|
+
try {
|
|
576
|
+
settings = JSON.parse(await readFile(settingsPath, 'utf-8'));
|
|
577
|
+
}
|
|
578
|
+
catch { /* file doesn't exist yet */ }
|
|
579
|
+
const permissions = settings.permissions ?? {};
|
|
580
|
+
const allow = Array.isArray(permissions.allow) ? [...permissions.allow] : [];
|
|
581
|
+
if (!allow.includes(pattern)) {
|
|
582
|
+
allow.push(pattern);
|
|
583
|
+
settings.permissions = { ...permissions, allow };
|
|
584
|
+
await mkdir(join(cwd, '.claude'), { recursive: true });
|
|
585
|
+
await writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
586
|
+
console.log(`[persistAllowPattern] saved ${pattern} to ${settingsPath}`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
waitForUserInput(requestId, request) {
|
|
590
|
+
return new Promise((resolve) => {
|
|
591
|
+
this.pendingInputRequests.set(requestId, { resolve, request });
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
//# sourceMappingURL=sessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionManager.js","sourceRoot":"","sources":["../../src/ai/sessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session registry — tracks which sessions have been opened via quicksave.
|
|
3
|
+
*
|
|
4
|
+
* Storage layout:
|
|
5
|
+
* ~/.quicksave/state/session-registry/{encoded-project-path}/{sessionId}.json
|
|
6
|
+
*
|
|
7
|
+
* Path encoding: `/` → `-` (same convention as Claude Code's ~/.claude/projects/).
|
|
8
|
+
*
|
|
9
|
+
* In-memory: two-level Map<cwd, Map<sessionId, entry>>.
|
|
10
|
+
* Loaded once at daemon startup; writes update memory + single file synchronously.
|
|
11
|
+
*/
|
|
12
|
+
import type { SessionRegistryEntry } from '@sumicom/quicksave-shared';
|
|
13
|
+
export declare class SessionRegistry {
|
|
14
|
+
private registry;
|
|
15
|
+
/**
|
|
16
|
+
* Scan session-registry directory and load all entries into memory.
|
|
17
|
+
*/
|
|
18
|
+
loadAll(): void;
|
|
19
|
+
getEntry(cwd: string, sessionId: string): SessionRegistryEntry | undefined;
|
|
20
|
+
getEntriesForProject(cwd?: string): SessionRegistryEntry[];
|
|
21
|
+
upsertEntry(entry: SessionRegistryEntry): void;
|
|
22
|
+
updateEntry(cwd: string, sessionId: string, updates: Partial<SessionRegistryEntry>): SessionRegistryEntry | null;
|
|
23
|
+
deleteEntry(cwd: string, sessionId: string): boolean;
|
|
24
|
+
private setInMemory;
|
|
25
|
+
private writeToDisk;
|
|
26
|
+
}
|
|
27
|
+
export declare function getSessionRegistry(): SessionRegistry;
|
|
28
|
+
//# sourceMappingURL=sessionRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionRegistry.d.ts","sourceRoot":"","sources":["../../src/ai/sessionRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAaH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAMtE,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAwD;IAExE;;OAEG;IACH,OAAO,IAAI,IAAI;IA8Cf,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAI1E,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAgB1D,WAAW,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAK9C,WAAW,CACT,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACrC,oBAAoB,GAAG,IAAI;IAQ9B,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAoBpD,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,WAAW;CAepB;AAID,wBAAgB,kBAAkB,IAAI,eAAe,CAMpD"}
|