@ccpocket/bridge 0.1.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.
Files changed (77) hide show
  1. package/README.md +54 -0
  2. package/dist/claude-process.d.ts +108 -0
  3. package/dist/claude-process.js +471 -0
  4. package/dist/claude-process.js.map +1 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +42 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/codex-process.d.ts +46 -0
  9. package/dist/codex-process.js +420 -0
  10. package/dist/codex-process.js.map +1 -0
  11. package/dist/debug-trace-store.d.ts +15 -0
  12. package/dist/debug-trace-store.js +78 -0
  13. package/dist/debug-trace-store.js.map +1 -0
  14. package/dist/firebase-auth.d.ts +35 -0
  15. package/dist/firebase-auth.js +132 -0
  16. package/dist/firebase-auth.js.map +1 -0
  17. package/dist/gallery-store.d.ts +66 -0
  18. package/dist/gallery-store.js +310 -0
  19. package/dist/gallery-store.js.map +1 -0
  20. package/dist/image-store.d.ts +22 -0
  21. package/dist/image-store.js +113 -0
  22. package/dist/image-store.js.map +1 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +153 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/mdns.d.ts +6 -0
  27. package/dist/mdns.js +42 -0
  28. package/dist/mdns.js.map +1 -0
  29. package/dist/parser.d.ts +381 -0
  30. package/dist/parser.js +218 -0
  31. package/dist/parser.js.map +1 -0
  32. package/dist/project-history.d.ts +10 -0
  33. package/dist/project-history.js +73 -0
  34. package/dist/project-history.js.map +1 -0
  35. package/dist/prompt-history-backup.d.ts +15 -0
  36. package/dist/prompt-history-backup.js +46 -0
  37. package/dist/prompt-history-backup.js.map +1 -0
  38. package/dist/push-relay.d.ts +27 -0
  39. package/dist/push-relay.js +69 -0
  40. package/dist/push-relay.js.map +1 -0
  41. package/dist/recording-store.d.ts +51 -0
  42. package/dist/recording-store.js +158 -0
  43. package/dist/recording-store.js.map +1 -0
  44. package/dist/screenshot.d.ts +28 -0
  45. package/dist/screenshot.js +98 -0
  46. package/dist/screenshot.js.map +1 -0
  47. package/dist/sdk-process.d.ts +151 -0
  48. package/dist/sdk-process.js +740 -0
  49. package/dist/sdk-process.js.map +1 -0
  50. package/dist/session.d.ts +126 -0
  51. package/dist/session.js +550 -0
  52. package/dist/session.js.map +1 -0
  53. package/dist/sessions-index.d.ts +86 -0
  54. package/dist/sessions-index.js +1027 -0
  55. package/dist/sessions-index.js.map +1 -0
  56. package/dist/setup-launchd.d.ts +8 -0
  57. package/dist/setup-launchd.js +109 -0
  58. package/dist/setup-launchd.js.map +1 -0
  59. package/dist/startup-info.d.ts +8 -0
  60. package/dist/startup-info.js +78 -0
  61. package/dist/startup-info.js.map +1 -0
  62. package/dist/usage.d.ts +17 -0
  63. package/dist/usage.js +236 -0
  64. package/dist/usage.js.map +1 -0
  65. package/dist/version.d.ts +11 -0
  66. package/dist/version.js +39 -0
  67. package/dist/version.js.map +1 -0
  68. package/dist/websocket.d.ts +71 -0
  69. package/dist/websocket.js +1487 -0
  70. package/dist/websocket.js.map +1 -0
  71. package/dist/worktree-store.d.ts +25 -0
  72. package/dist/worktree-store.js +59 -0
  73. package/dist/worktree-store.js.map +1 -0
  74. package/dist/worktree.d.ts +43 -0
  75. package/dist/worktree.js +295 -0
  76. package/dist/worktree.js.map +1 -0
  77. package/package.json +63 -0
@@ -0,0 +1,550 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { execFileSync } from "node:child_process";
3
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { pathToSlug } from "./sessions-index.js";
7
+ import { SdkProcess } from "./sdk-process.js";
8
+ import { CodexProcess } from "./codex-process.js";
9
+ import { createWorktree } from "./worktree.js";
10
+ const MAX_HISTORY_PER_SESSION = 100;
11
+ export class SessionManager {
12
+ sessions = new Map();
13
+ onMessage;
14
+ imageStore;
15
+ galleryStore;
16
+ onGalleryImage;
17
+ worktreeStore;
18
+ /** Cache slash commands per project path for early loading on subsequent sessions. */
19
+ commandCache = new Map();
20
+ constructor(onMessage, imageStore, galleryStore, onGalleryImage, worktreeStore) {
21
+ this.onMessage = onMessage;
22
+ this.imageStore = imageStore ?? null;
23
+ this.galleryStore = galleryStore ?? null;
24
+ this.onGalleryImage = onGalleryImage ?? null;
25
+ this.worktreeStore = worktreeStore ?? null;
26
+ }
27
+ create(projectPath, options, pastMessages, worktreeOpts, provider, codexOptions) {
28
+ const id = randomUUID().slice(0, 8);
29
+ const effectiveProvider = provider ?? "claude";
30
+ const proc = effectiveProvider === "codex" ? new CodexProcess() : new SdkProcess();
31
+ // Handle worktree: reuse existing or create new
32
+ let wtPath;
33
+ let wtBranch;
34
+ if (worktreeOpts?.existingWorktreePath) {
35
+ // Reuse an existing worktree (resume case)
36
+ wtPath = worktreeOpts.existingWorktreePath;
37
+ wtBranch = worktreeOpts.worktreeBranch;
38
+ console.log(`[session] Reusing existing worktree at ${wtPath}`);
39
+ }
40
+ else if (worktreeOpts?.useWorktree) {
41
+ // Create a new worktree
42
+ try {
43
+ const wt = createWorktree(projectPath, id, worktreeOpts.worktreeBranch);
44
+ wtPath = wt.worktreePath;
45
+ wtBranch = wt.branch;
46
+ console.log(`[session] Created worktree at ${wtPath} (branch: ${wtBranch})`);
47
+ }
48
+ catch (err) {
49
+ console.error(`[session] Failed to create worktree:`, err);
50
+ // Fall through to use original projectPath
51
+ }
52
+ }
53
+ // Use worktree path as cwd if available
54
+ const effectiveCwd = wtPath ?? projectPath;
55
+ let gitBranch = "";
56
+ try {
57
+ gitBranch = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
58
+ cwd: effectiveCwd, encoding: "utf-8",
59
+ }).trim();
60
+ }
61
+ catch { /* not a git repo */ }
62
+ const session = {
63
+ id,
64
+ process: proc,
65
+ provider: effectiveProvider,
66
+ history: [],
67
+ pastMessages: pastMessages && pastMessages.length > 0 ? pastMessages : undefined,
68
+ projectPath,
69
+ status: "starting",
70
+ createdAt: new Date(),
71
+ lastActivityAt: new Date(),
72
+ gitBranch,
73
+ worktreePath: wtPath,
74
+ worktreeBranch: wtBranch,
75
+ // Pre-populate claudeSessionId for resumed sessions so that get_history
76
+ // can return it immediately (before the SDK sends a system/result event).
77
+ claudeSessionId: options?.sessionId,
78
+ };
79
+ // Cache tool_use id → name for enriching tool_result messages
80
+ const toolUseNames = new Map();
81
+ proc.on("message", async (msg) => {
82
+ try {
83
+ session.lastActivityAt = new Date();
84
+ if (effectiveProvider === "claude") {
85
+ // Capture Claude session_id from result events
86
+ if (msg.type === "result" && "sessionId" in msg && msg.sessionId) {
87
+ session.claudeSessionId = msg.sessionId;
88
+ this.saveWorktreeMapping(session);
89
+ }
90
+ if (msg.type === "system" && "sessionId" in msg && msg.sessionId) {
91
+ session.claudeSessionId = msg.sessionId;
92
+ this.saveWorktreeMapping(session);
93
+ }
94
+ // Cache slash commands and skills from system messages.
95
+ if (msg.type === "system" &&
96
+ (msg.subtype === "init" || msg.subtype === "supported_commands") &&
97
+ msg.slashCommands) {
98
+ this.commandCache.set(projectPath, {
99
+ slashCommands: msg.slashCommands,
100
+ skills: msg.skills ?? this.commandCache.get(projectPath)?.skills ?? [],
101
+ });
102
+ }
103
+ // Cache tool_use names from assistant messages
104
+ if (msg.type === "assistant" && Array.isArray(msg.message.content)) {
105
+ for (const content of msg.message.content) {
106
+ if (content.type === "tool_use") {
107
+ const toolUse = content;
108
+ toolUseNames.set(toolUse.id, toolUse.name);
109
+ }
110
+ }
111
+ }
112
+ // Enrich tool_result with toolName
113
+ if (msg.type === "tool_result") {
114
+ const cachedName = toolUseNames.get(msg.toolUseId);
115
+ if (cachedName) {
116
+ msg = { ...msg, toolName: cachedName };
117
+ }
118
+ }
119
+ // Extract images from tool_result content
120
+ if (msg.type === "tool_result" && this.imageStore) {
121
+ const paths = this.imageStore.extractImagePaths(msg.content);
122
+ if (paths.length > 0) {
123
+ const images = await this.imageStore.registerImages(paths);
124
+ if (images.length > 0) {
125
+ msg = { ...msg, images };
126
+ }
127
+ // Also register in GalleryStore (disk-persistent)
128
+ if (this.galleryStore) {
129
+ for (const p of paths) {
130
+ const meta = await this.galleryStore.addImage(p, session.projectPath, session.id);
131
+ if (meta && this.onGalleryImage) {
132
+ this.onGalleryImage(meta);
133
+ }
134
+ }
135
+ }
136
+ }
137
+ // Extract base64 images from content blocks (e.g., MCP screenshots)
138
+ if (msg.rawContentBlocks) {
139
+ const imageBlocks = msg.rawContentBlocks
140
+ .filter((c) => c.type === "image" && c.source?.type === "base64");
141
+ if (imageBlocks.length > 0) {
142
+ const existingImages = msg.images ?? [];
143
+ const newImages = [];
144
+ for (const block of imageBlocks) {
145
+ const source = block.source;
146
+ if (typeof source?.data !== "string" || typeof source?.media_type !== "string")
147
+ continue;
148
+ const b64Data = source.data;
149
+ const mimeType = source.media_type;
150
+ const ref = this.imageStore.registerFromBase64(b64Data, mimeType);
151
+ if (ref) {
152
+ newImages.push(ref);
153
+ // Also persist to GalleryStore
154
+ if (this.galleryStore) {
155
+ const meta = await this.galleryStore.addImageFromBase64(b64Data, mimeType, session.projectPath, session.id);
156
+ if (meta && this.onGalleryImage) {
157
+ this.onGalleryImage(meta);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ if (newImages.length > 0) {
163
+ msg = { ...msg, images: [...existingImages, ...newImages] };
164
+ }
165
+ }
166
+ // Strip transient rawContentBlocks before sending to client
167
+ const { rawContentBlocks: _, ...cleanMsg } = msg;
168
+ msg = cleanMsg;
169
+ }
170
+ }
171
+ }
172
+ else {
173
+ // Codex: capture thread_id for session tracking and worktree restore.
174
+ if (msg.type === "system" && "sessionId" in msg && msg.sessionId) {
175
+ session.claudeSessionId = msg.sessionId;
176
+ this.saveWorktreeMapping(session);
177
+ }
178
+ }
179
+ // Don't add streaming deltas to history
180
+ if (msg.type !== "stream_delta" && msg.type !== "thinking_delta") {
181
+ // When SDK echoes back a user_input with UUID, merge into the
182
+ // UUID-less placeholder that websocket.ts pushed earlier.
183
+ // This avoids duplicate entries while preserving the UUID needed
184
+ // for rewind candidate matching.
185
+ let merged = false;
186
+ if (msg.type === "user_input" &&
187
+ "userMessageUuid" in msg &&
188
+ msg.userMessageUuid) {
189
+ for (let i = session.history.length - 1; i >= 0; i--) {
190
+ const m = session.history[i];
191
+ if (m.type === "user_input" &&
192
+ !("userMessageUuid" in m && m.userMessageUuid)) {
193
+ session.history[i] = msg;
194
+ merged = true;
195
+ break;
196
+ }
197
+ }
198
+ }
199
+ if (!merged) {
200
+ session.history.push(msg);
201
+ }
202
+ if (session.history.length > MAX_HISTORY_PER_SESSION) {
203
+ // Protect user_input messages from eviction so they remain
204
+ // visible when the client requests history after reconnecting.
205
+ const idx = session.history.findIndex(m => m.type !== "user_input");
206
+ if (idx >= 0) {
207
+ session.history.splice(idx, 1);
208
+ }
209
+ else {
210
+ session.history.shift();
211
+ }
212
+ }
213
+ }
214
+ this.onMessage(id, msg);
215
+ // After a result (turn complete), backfill UUIDs from disk.
216
+ // The SDK does not echo user messages via the stream, so
217
+ // in-memory user_input entries lack UUIDs. The disk
218
+ // conversation file always has them.
219
+ if (msg.type === "result") {
220
+ this.backfillUserUuidsFromDisk(session);
221
+ }
222
+ }
223
+ catch (err) {
224
+ console.error(`[session] Error processing message for session ${id}:`, err);
225
+ }
226
+ });
227
+ proc.on("status", (status) => {
228
+ session.status = status;
229
+ });
230
+ proc.on("exit", () => {
231
+ session.status = "idle";
232
+ // Add status message to history so it stays in sync with session.status
233
+ session.history.push({ type: "status", status: "idle" });
234
+ });
235
+ if (effectiveProvider === "codex" && codexOptions) {
236
+ session.codexSettings = {
237
+ approvalPolicy: codexOptions.approvalPolicy,
238
+ sandboxMode: codexOptions.sandboxMode,
239
+ model: codexOptions.model,
240
+ modelReasoningEffort: codexOptions.modelReasoningEffort,
241
+ networkAccessEnabled: codexOptions.networkAccessEnabled,
242
+ webSearchMode: codexOptions.webSearchMode,
243
+ };
244
+ // Resume starts know the thread id up front.
245
+ if (codexOptions.threadId) {
246
+ session.claudeSessionId = codexOptions.threadId;
247
+ this.saveWorktreeMapping(session);
248
+ }
249
+ }
250
+ this.sessions.set(id, session);
251
+ if (effectiveProvider === "codex") {
252
+ proc.start(effectiveCwd, codexOptions);
253
+ }
254
+ else {
255
+ proc.start(effectiveCwd, options);
256
+ }
257
+ console.log(`[session] Created ${effectiveProvider} session ${id} for ${effectiveCwd}${wtPath ? ` (worktree of ${projectPath})` : ""}`);
258
+ return id;
259
+ }
260
+ get(id) {
261
+ return this.sessions.get(id);
262
+ }
263
+ list() {
264
+ return Array.from(this.sessions.values()).map((s) => {
265
+ const pendingPermission = s.status === "waiting_approval" && s.process instanceof SdkProcess
266
+ ? s.process.getPendingPermission()
267
+ : undefined;
268
+ return {
269
+ id: s.id,
270
+ provider: s.provider,
271
+ projectPath: s.projectPath,
272
+ claudeSessionId: s.claudeSessionId,
273
+ status: s.status,
274
+ createdAt: s.createdAt.toISOString(),
275
+ lastActivityAt: s.lastActivityAt.toISOString(),
276
+ gitBranch: s.gitBranch,
277
+ lastMessage: this.extractLastMessage(s),
278
+ messageCount: (s.pastMessages?.length ?? 0) + s.history.length,
279
+ worktreePath: s.worktreePath,
280
+ worktreeBranch: s.worktreeBranch,
281
+ permissionMode: s.process instanceof SdkProcess
282
+ ? s.process.permissionMode
283
+ : undefined,
284
+ codexSettings: s.codexSettings,
285
+ pendingPermission,
286
+ };
287
+ });
288
+ }
289
+ extractLastMessage(s) {
290
+ // Search in-memory history (newest first) for assistant text
291
+ for (let i = s.history.length - 1; i >= 0; i--) {
292
+ const msg = s.history[i];
293
+ if (msg.type === "assistant") {
294
+ const textBlock = msg.message.content.find((c) => c.type === "text");
295
+ if (textBlock && "text" in textBlock && textBlock.text) {
296
+ return textBlock.text.replace(/\s+/g, " ").trim().slice(0, 100);
297
+ }
298
+ }
299
+ }
300
+ // Fallback to pastMessages (raw Claude CLI format)
301
+ if (s.pastMessages) {
302
+ for (let i = s.pastMessages.length - 1; i >= 0; i--) {
303
+ const msg = s.pastMessages[i];
304
+ if (msg.role === "assistant") {
305
+ // Handle string content (defensive — normally array)
306
+ if (typeof msg.content === "string") {
307
+ return msg.content.replace(/\s+/g, " ").trim().slice(0, 100);
308
+ }
309
+ const content = msg.content;
310
+ const textBlock = content?.find((c) => c.type === "text");
311
+ if (textBlock?.text)
312
+ return textBlock.text.replace(/\s+/g, " ").trim().slice(0, 100);
313
+ }
314
+ }
315
+ }
316
+ return "";
317
+ }
318
+ getCachedCommands(projectPath) {
319
+ return this.commandCache.get(projectPath);
320
+ }
321
+ /** Get worktree store for external use (e.g., resume_session in websocket.ts). */
322
+ getWorktreeStore() {
323
+ return this.worktreeStore;
324
+ }
325
+ /** Save worktree mapping when a provider session ID is available. */
326
+ saveWorktreeMapping(session) {
327
+ if (this.worktreeStore && session.claudeSessionId && session.worktreePath && session.worktreeBranch) {
328
+ this.worktreeStore.set(session.claudeSessionId, {
329
+ worktreePath: session.worktreePath,
330
+ worktreeBranch: session.worktreeBranch,
331
+ projectPath: session.projectPath,
332
+ });
333
+ }
334
+ }
335
+ /**
336
+ * Rewind files to their state at the specified user message.
337
+ * Delegates to the session's SdkProcess.rewindFiles().
338
+ */
339
+ async rewindFiles(id, targetUuid, dryRun) {
340
+ const session = this.sessions.get(id);
341
+ if (!session) {
342
+ return { canRewind: false, error: "Session not found" };
343
+ }
344
+ if (session.provider === "codex") {
345
+ return { canRewind: false, error: "Rewind is not supported for Codex sessions" };
346
+ }
347
+ return session.process.rewindFiles(targetUuid, dryRun);
348
+ }
349
+ /**
350
+ * Rewind the conversation to a specific point.
351
+ * Stops the current process and restarts with resumeSessionAt.
352
+ *
353
+ * `targetUuid` is a **user message UUID**. The SDK's `resumeSessionAt`
354
+ * expects an **assistant message UUID**, so we look up the assistant
355
+ * message that follows the target user message.
356
+ */
357
+ rewindConversation(id, targetUuid, onReady) {
358
+ const session = this.sessions.get(id);
359
+ if (!session) {
360
+ throw new Error(`Session ${id} not found`);
361
+ }
362
+ if (session.provider === "codex") {
363
+ throw new Error("Rewind is not supported for Codex sessions");
364
+ }
365
+ const claudeSessionId = session.claudeSessionId;
366
+ if (!claudeSessionId) {
367
+ throw new Error("Session has no Claude session ID");
368
+ }
369
+ // resumeSessionAt expects assistant message UUID (per SDK docs).
370
+ // Convert user UUID → following assistant UUID.
371
+ const assistantUuid = this.findAssistantUuidAfterUser(session, targetUuid);
372
+ if (!assistantUuid) {
373
+ throw new Error("Cannot find assistant message after target user message");
374
+ }
375
+ const projectPath = session.projectPath;
376
+ const permissionMode = session.process.permissionMode;
377
+ const worktreePath = session.worktreePath;
378
+ const worktreeBranch = session.worktreeBranch;
379
+ // Stop and destroy the current session
380
+ this.destroy(id);
381
+ // Create a new session with resumeSessionAt (assistant UUID)
382
+ const newId = this.create(projectPath, {
383
+ sessionId: claudeSessionId,
384
+ permissionMode,
385
+ resumeSessionAt: assistantUuid,
386
+ }, undefined, worktreePath ? { existingWorktreePath: worktreePath, worktreeBranch } : undefined);
387
+ onReady(newId);
388
+ }
389
+ /**
390
+ * Find the assistant message UUID that follows a given user message UUID.
391
+ *
392
+ * Searches in-memory history first, then pastMessages (disk history).
393
+ */
394
+ findAssistantUuidAfterUser(session, userUuid) {
395
+ // 1. Search in-memory history
396
+ let foundUser = false;
397
+ for (const msg of session.history) {
398
+ if (!foundUser) {
399
+ // user_input or tool_result with matching userMessageUuid
400
+ if ((msg.type === "user_input" || msg.type === "tool_result") &&
401
+ "userMessageUuid" in msg &&
402
+ msg.userMessageUuid === userUuid) {
403
+ foundUser = true;
404
+ }
405
+ continue;
406
+ }
407
+ // Found user message — look for next assistant
408
+ if (msg.type === "assistant" && "messageUuid" in msg && msg.messageUuid) {
409
+ return msg.messageUuid;
410
+ }
411
+ }
412
+ // 2. Search pastMessages (disk history with uuid field)
413
+ if (session.pastMessages) {
414
+ foundUser = false;
415
+ for (const raw of session.pastMessages) {
416
+ const pm = raw;
417
+ if (!foundUser) {
418
+ if (pm.role === "user" && pm.uuid === userUuid) {
419
+ foundUser = true;
420
+ }
421
+ continue;
422
+ }
423
+ if (pm.role === "assistant" && pm.uuid) {
424
+ return pm.uuid;
425
+ }
426
+ }
427
+ }
428
+ return null;
429
+ }
430
+ /**
431
+ * Read the Claude CLI conversation history file from disk and backfill
432
+ * `userMessageUuid` into in-memory history entries that are missing it.
433
+ *
434
+ * The SDK does not echo user messages via the stream, so in-memory
435
+ * `user_input` entries (pushed by websocket.ts) lack UUIDs. The disk
436
+ * file, however, always contains UUIDs. We match by text content.
437
+ *
438
+ * Also re-broadcasts the updated `user_input` message so the Flutter
439
+ * client can update its UserChatEntry.messageUuid values.
440
+ */
441
+ backfillUserUuidsFromDisk(session) {
442
+ if (!session.claudeSessionId || !session.projectPath)
443
+ return;
444
+ const historyPath = this.findHistoryJsonlPath(session);
445
+ if (!historyPath)
446
+ return;
447
+ let lines;
448
+ try {
449
+ const raw = readFileSync(historyPath, "utf-8").trim();
450
+ if (!raw)
451
+ return;
452
+ lines = raw.split("\n");
453
+ }
454
+ catch {
455
+ // File may not exist yet (e.g., very new session)
456
+ return;
457
+ }
458
+ // Collect user message text→uuid queue from disk.
459
+ // Use an array per text key so duplicate messages ("yes", "ok", etc.)
460
+ // are matched in order rather than collapsed to one UUID.
461
+ const diskUuids = new Map();
462
+ for (const line of lines) {
463
+ try {
464
+ const entry = JSON.parse(line);
465
+ if (entry.type !== "user" && entry.role !== "user")
466
+ continue;
467
+ if (!entry.uuid)
468
+ continue;
469
+ // Extract text from content array
470
+ const content = entry.message?.content;
471
+ if (!Array.isArray(content))
472
+ continue;
473
+ const texts = content
474
+ .filter((c) => c.type === "text")
475
+ .map((c) => c.text);
476
+ if (texts.length > 0) {
477
+ const key = texts.join("\n");
478
+ const arr = diskUuids.get(key) ?? [];
479
+ arr.push(entry.uuid);
480
+ diskUuids.set(key, arr);
481
+ }
482
+ }
483
+ catch {
484
+ // skip malformed lines
485
+ }
486
+ }
487
+ // Backfill UUIDs into in-memory history
488
+ for (const msg of session.history) {
489
+ if (msg.type === "user_input" &&
490
+ !("userMessageUuid" in msg && msg.userMessageUuid)) {
491
+ const text = msg.text;
492
+ const queue = text ? diskUuids.get(text) : undefined;
493
+ if (queue && queue.length > 0) {
494
+ msg.userMessageUuid = queue.shift();
495
+ // Re-broadcast so Flutter can update UserChatEntry.messageUuid
496
+ this.onMessage(session.id, msg);
497
+ }
498
+ }
499
+ }
500
+ }
501
+ findHistoryJsonlPath(session) {
502
+ if (!session.claudeSessionId)
503
+ return null;
504
+ const projectsDir = join(homedir(), ".claude", "projects");
505
+ const fileName = `${session.claudeSessionId}.jsonl`;
506
+ const slugCandidates = new Set([
507
+ pathToSlug(session.projectPath),
508
+ ]);
509
+ // Worktree sessions are persisted under the worktree slug, not projectPath.
510
+ if (session.worktreePath) {
511
+ slugCandidates.add(pathToSlug(session.worktreePath));
512
+ }
513
+ for (const slug of slugCandidates) {
514
+ const candidate = join(projectsDir, slug, fileName);
515
+ if (existsSync(candidate))
516
+ return candidate;
517
+ }
518
+ // Fallback: scan all project dirs in case metadata paths drift.
519
+ try {
520
+ const entries = readdirSync(projectsDir, { withFileTypes: true });
521
+ for (const entry of entries) {
522
+ if (!entry.isDirectory() || entry.name.startsWith("."))
523
+ continue;
524
+ const candidate = join(projectsDir, entry.name, fileName);
525
+ if (existsSync(candidate))
526
+ return candidate;
527
+ }
528
+ }
529
+ catch {
530
+ return null;
531
+ }
532
+ return null;
533
+ }
534
+ destroy(id) {
535
+ const session = this.sessions.get(id);
536
+ if (!session)
537
+ return false;
538
+ session.process.stop();
539
+ session.process.removeAllListeners();
540
+ this.sessions.delete(id);
541
+ console.log(`[session] Destroyed session ${id}`);
542
+ return true;
543
+ }
544
+ destroyAll() {
545
+ for (const [id] of this.sessions) {
546
+ this.destroy(id);
547
+ }
548
+ }
549
+ }
550
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ export interface SessionIndexEntry {
2
+ sessionId: string;
3
+ provider: "claude" | "codex";
4
+ summary?: string;
5
+ firstPrompt: string;
6
+ lastPrompt?: string;
7
+ messageCount: number;
8
+ created: string;
9
+ modified: string;
10
+ gitBranch: string;
11
+ projectPath: string;
12
+ /** Raw cwd used to resume this session (worktree path for codex, if any). */
13
+ resumeCwd?: string;
14
+ isSidechain: boolean;
15
+ codexSettings?: {
16
+ approvalPolicy?: string;
17
+ sandboxMode?: string;
18
+ model?: string;
19
+ modelReasoningEffort?: string;
20
+ networkAccessEnabled?: boolean;
21
+ webSearchMode?: string;
22
+ };
23
+ }
24
+ export interface GetRecentSessionsOptions {
25
+ limit?: number;
26
+ offset?: number;
27
+ projectPath?: string;
28
+ }
29
+ export interface GetRecentSessionsResult {
30
+ sessions: SessionIndexEntry[];
31
+ hasMore: boolean;
32
+ }
33
+ /** Convert a filesystem path to Claude's project directory slug (e.g. /foo/bar → -foo-bar). */
34
+ export declare function pathToSlug(p: string): string;
35
+ /**
36
+ * Normalize a worktree cwd back to the main project path.
37
+ * e.g. /path/to/project-worktrees/branch → /path/to/project
38
+ */
39
+ export declare function normalizeWorktreePath(p: string): string;
40
+ /**
41
+ * Check if a directory slug represents a worktree directory for a given project slug.
42
+ * e.g. "-Users-x-proj-worktrees-branch" is a worktree dir for "-Users-x-proj".
43
+ */
44
+ export declare function isWorktreeSlug(dirSlug: string, projectSlug: string): boolean;
45
+ /**
46
+ * Scan a directory for JSONL session files and create SessionIndexEntry objects.
47
+ * Used as a fallback when sessions-index.json is missing (common for worktree sessions).
48
+ */
49
+ export declare function scanJsonlDir(dirPath: string): Promise<SessionIndexEntry[]>;
50
+ export declare function getAllRecentSessions(options?: GetRecentSessionsOptions): Promise<GetRecentSessionsResult>;
51
+ export interface SessionHistoryMessage {
52
+ role: "user" | "assistant";
53
+ uuid?: string;
54
+ timestamp?: string;
55
+ /** Skill loading prompt or other meta message (rendered as a chip). */
56
+ isMeta?: boolean;
57
+ /** Number of images attached to this user message (for display indicator). */
58
+ imageCount?: number;
59
+ content: Array<{
60
+ type: string;
61
+ text?: string;
62
+ id?: string;
63
+ name?: string;
64
+ input?: Record<string, unknown>;
65
+ }>;
66
+ }
67
+ /**
68
+ * Read past conversation messages from a session's JSONL file.
69
+ * Returns user and assistant messages suitable for display.
70
+ */
71
+ export declare function getSessionHistory(sessionId: string): Promise<SessionHistoryMessage[]>;
72
+ export interface ExtractedImage {
73
+ base64: string;
74
+ mimeType: string;
75
+ }
76
+ /**
77
+ * Extract image base64 data from a Claude Code session JSONL for a specific message UUID.
78
+ */
79
+ export declare function extractMessageImages(sessionId: string, messageUuid: string): Promise<ExtractedImage[]>;
80
+ export declare function getCodexSessionHistory(threadId: string): Promise<SessionHistoryMessage[]>;
81
+ /**
82
+ * Look up session metadata for a set of Claude CLI sessionIds.
83
+ * Returns a map from sessionId to a subset of session metadata.
84
+ * More efficient than getAllRecentSessions when you only need a few entries.
85
+ */
86
+ export declare function findSessionsByClaudeIds(ids: Set<string>): Promise<Map<string, Pick<SessionIndexEntry, "summary" | "firstPrompt" | "lastPrompt" | "projectPath">>>;