spiracha 1.4.0 → 1.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.
Files changed (159) hide show
  1. package/AGENTS.md +48 -5
  2. package/README.md +40 -5
  3. package/apps/ui/AGENTS.md +23 -4
  4. package/apps/ui/README.md +49 -2
  5. package/apps/ui/dist/client/assets/analytics-DOy1b6Sh.js +1 -0
  6. package/apps/ui/dist/client/assets/{antigravity-conversations._conversationId-DmD0sN8X.js → antigravity-conversations._conversationId-DqySVO2K.js} +2 -2
  7. package/apps/ui/dist/client/assets/antigravity-keychain-panel-B77qJz6f.js +1 -0
  8. package/apps/ui/dist/client/assets/antigravity._workspaceKey-B3NM6gRH.js +1 -0
  9. package/apps/ui/dist/client/assets/{antigravity.index-DEEkjlZa.js → antigravity.index-DP9JC2P9.js} +1 -1
  10. package/apps/ui/dist/client/assets/{badge-DfWvPfKF.js → badge-C3i4OKs8.js} +1 -1
  11. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-8pQ55ci2.js +1 -0
  12. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-DVz5UmtU.js +1 -0
  13. package/apps/ui/dist/client/assets/claude-code._workspaceKey-BBKskSum.js +1 -0
  14. package/apps/ui/dist/client/assets/claude-code._workspaceKey-OkikMUFs.js +1 -0
  15. package/apps/ui/dist/client/assets/claude-code.index-Cwu76dbb.js +1 -0
  16. package/apps/ui/dist/client/assets/claude-code.index-D6eMd08t.js +1 -0
  17. package/apps/ui/dist/client/assets/createServerFn-B-KkwmHU.js +3 -0
  18. package/apps/ui/dist/client/assets/cursor-threads._composerId-hBWlP1D-.js +1 -0
  19. package/apps/ui/dist/client/assets/cursor._workspaceKey-BFPkIRi-.js +1 -0
  20. package/apps/ui/dist/client/assets/cursor.index-8y4o20kb.js +2 -0
  21. package/apps/ui/dist/client/assets/delete-confirm-dialog-Bxs07u-j.js +7 -0
  22. package/apps/ui/dist/client/assets/dist-BrJhN2A0.js +5 -0
  23. package/apps/ui/dist/client/assets/{dist-BhZOxAPP.js → dist-Cmd3AIfD.js} +1 -1
  24. package/apps/ui/dist/client/assets/dropdown-menu-D5cvPaZt.js +1 -0
  25. package/apps/ui/dist/client/assets/{es2015-BkCWttyM.js → es2015-ad6040dw.js} +1 -1
  26. package/apps/ui/dist/client/assets/export-dialog-Dr8d2MqD.js +1 -0
  27. package/apps/ui/dist/client/assets/{formatters-BM9kB7ed.js → formatters-BtqyrX_c.js} +1 -1
  28. package/apps/ui/dist/client/assets/index-C-STgIH4.js +166 -0
  29. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-CKgfJ7GR.js +1 -0
  30. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-zvIJHtQF.js +1 -0
  31. package/apps/ui/dist/client/assets/kiro._workspaceKey-DhVuJuZB.js +1 -0
  32. package/apps/ui/dist/client/assets/kiro._workspaceKey-QArsjkTY.js +1 -0
  33. package/apps/ui/dist/client/assets/kiro.index-C-fr4m7i.js +1 -0
  34. package/apps/ui/dist/client/assets/kiro.index-OYgAdtZd.js +1 -0
  35. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-DLjiTst-.js +1 -0
  36. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-biBwrRbt.js +8 -0
  37. package/apps/ui/dist/client/assets/opencode._workspaceKey-C7OIzMOJ.js +1 -0
  38. package/apps/ui/dist/client/assets/opencode._workspaceKey-sBakX0oI.js +1 -0
  39. package/apps/ui/dist/client/assets/opencode.index-Bl_kNs9N.js +1 -0
  40. package/apps/ui/dist/client/assets/opencode.index-CN53bVmb.js +1 -0
  41. package/apps/ui/dist/client/assets/preload-helper-B8fFrdxC.js +1 -0
  42. package/apps/ui/dist/client/assets/projects._project-D8WloxQN.js +1 -0
  43. package/apps/ui/dist/client/assets/projects.index-5xRtuJdX.js +3 -0
  44. package/apps/ui/dist/client/assets/routes-DnzF_9CX.js +1 -0
  45. package/apps/ui/dist/client/assets/select-CYF6pF37.js +1 -0
  46. package/apps/ui/dist/client/assets/settings-Dx70jgP_.js +1 -0
  47. package/apps/ui/dist/client/assets/styles-B7Zi9EFA.css +1 -0
  48. package/apps/ui/dist/client/assets/tabs-CmuhkT-c.js +7 -0
  49. package/apps/ui/dist/client/assets/thread-transcript-stats-BUNz6u7F.js +1 -0
  50. package/apps/ui/dist/client/assets/threads._threadId-BMRSFow3.js +1 -0
  51. package/apps/ui/dist/client/assets/useMutation-BSFult2i.js +1 -0
  52. package/apps/ui/dist/client/assets/useQuery-CjINKZf1.js +1 -0
  53. package/apps/ui/dist/client/icon.svg +2 -1
  54. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CQ8Jjs3B.js +387 -0
  55. package/apps/ui/dist/server/assets/{antigravity-conversations._conversationId-BtexWY-K.js → antigravity-conversations._conversationId-BKOyL2T6.js} +2 -2
  56. package/apps/ui/dist/server/assets/{antigravity-conversations._conversationId-zMrR6v6R.js → antigravity-conversations._conversationId-eS87Dx7g.js} +1 -1
  57. package/apps/ui/dist/server/assets/claude-code-db-Ik3VStKZ.js +361 -0
  58. package/apps/ui/dist/server/assets/claude-code-queries-Cgzi4K-e.js +37 -0
  59. package/apps/ui/dist/server/assets/claude-code-server-PfraClXS.js +72 -0
  60. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-C55oe6zj.js +18 -0
  61. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-D1RYYi3j.js +473 -0
  62. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-DSvPLEUL.js +11 -0
  63. package/apps/ui/dist/server/assets/claude-code-transcript-C-bxh3cS.js +139 -0
  64. package/apps/ui/dist/server/assets/claude-code-transcript-phase-DmUMc8VU.js +10 -0
  65. package/apps/ui/dist/server/assets/claude-code._workspaceKey-B5Xg_-tE.js +28 -0
  66. package/apps/ui/dist/server/assets/claude-code._workspaceKey-BPlzyXPa.js +11 -0
  67. package/apps/ui/dist/server/assets/claude-code._workspaceKey-DqDve2wl.js +191 -0
  68. package/apps/ui/dist/server/assets/claude-code.index-B7yYR7dD.js +92 -0
  69. package/apps/ui/dist/server/assets/claude-code.index-BUHThG1W.js +11 -0
  70. package/apps/ui/dist/server/assets/{codex-server-CNXSJuc2.js → codex-server-CGXU4H8-.js} +319 -29
  71. package/apps/ui/dist/server/assets/{cursor-db-cYZEU3WQ.js → cursor-db-CZnYy7aT.js} +3 -3
  72. package/apps/ui/dist/server/assets/{cursor-recovery-nq-kR62j.js → cursor-recovery-CXpO8KcD.js} +2 -2
  73. package/apps/ui/dist/server/assets/{cursor-server-C3q7hrp-.js → cursor-server-DNu52A3K.js} +13 -13
  74. package/apps/ui/dist/server/assets/{cursor-threads._composerId-BkMMTQ3v.js → cursor-threads._composerId-Ckn6ItHI.js} +3 -3
  75. package/apps/ui/dist/server/assets/{cursor-threads._composerId-BPJFWfJj.js → cursor-threads._composerId-p9-ARAzc.js} +1 -1
  76. package/apps/ui/dist/server/assets/{cursor-transcript-2iL3KFSK.js → cursor-transcript-B7tGnqtn.js} +1 -1
  77. package/apps/ui/dist/server/assets/{cursor._workspaceKey-C5PdTaKB.js → cursor._workspaceKey-CZuohIUL.js} +1 -1
  78. package/apps/ui/dist/server/assets/{cursor._workspaceKey-Ckj7apKI.js → cursor._workspaceKey-DPp5JSjy.js} +2 -2
  79. package/apps/ui/dist/server/assets/{export-dialog-BItjWgkZ.js → export-dialog-D88ze9Gy.js} +2 -2
  80. package/apps/ui/dist/server/assets/kiro-db--fXrED_-.js +552 -0
  81. package/apps/ui/dist/server/assets/kiro-queries-CzNlM2ok.js +37 -0
  82. package/apps/ui/dist/server/assets/kiro-server-9WRxg2Au.js +72 -0
  83. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-CRY2c7YO.js +11 -0
  84. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-F1UlwxmR.js +449 -0
  85. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-bvTulT7C.js +18 -0
  86. package/apps/ui/dist/server/assets/kiro-transcript-DoekQBaH.js +112 -0
  87. package/apps/ui/dist/server/assets/kiro-transcript-phase-CJG40nQg.js +27 -0
  88. package/apps/ui/dist/server/assets/kiro._workspaceKey-BDe9sQwo.js +11 -0
  89. package/apps/ui/dist/server/assets/kiro._workspaceKey-CJsjgNwO.js +28 -0
  90. package/apps/ui/dist/server/assets/kiro._workspaceKey-D_-4Qb7y.js +193 -0
  91. package/apps/ui/dist/server/assets/kiro.index-C__-UROk.js +11 -0
  92. package/apps/ui/dist/server/assets/kiro.index-CmTbqeYj.js +93 -0
  93. package/apps/ui/dist/server/assets/opencode-db-BM7KjOzc.js +397 -0
  94. package/apps/ui/dist/server/assets/opencode-queries-BeNYXnQv.js +50 -0
  95. package/apps/ui/dist/server/assets/opencode-server-BpQ_kRze.js +72 -0
  96. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-CGQ-t0vD.js +518 -0
  97. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-D8Q7in_Z.js +18 -0
  98. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-DKOvi0lV.js +11 -0
  99. package/apps/ui/dist/server/assets/opencode-think-tags-CAoD-EcZ.js +87 -0
  100. package/apps/ui/dist/server/assets/opencode-transcript-BNTcGNym.js +141 -0
  101. package/apps/ui/dist/server/assets/opencode-transcript-phase-OqLkiQD0.js +32 -0
  102. package/apps/ui/dist/server/assets/opencode._workspaceKey-BdqcWHw1.js +11 -0
  103. package/apps/ui/dist/server/assets/opencode._workspaceKey-CfH96HTT.js +28 -0
  104. package/apps/ui/dist/server/assets/opencode._workspaceKey-DdbHPDrO.js +207 -0
  105. package/apps/ui/dist/server/assets/opencode.index-BbVzkJXP.js +11 -0
  106. package/apps/ui/dist/server/assets/opencode.index-Vh_Gq_1L.js +93 -0
  107. package/apps/ui/dist/server/assets/{projects._project-Bpbc3C-L.js → projects._project-4io5LO0E.js} +1 -1
  108. package/apps/ui/dist/server/assets/{projects._project-CvZho6EQ.js → projects._project-D6ZoGhJ8.js} +2 -2
  109. package/apps/ui/dist/server/assets/{router-6m-ihwqA.js → router-Sac2DGk6.js} +157 -49
  110. package/apps/ui/dist/server/assets/{shared-CPRNYIql.js → shared-DyhChtHf.js} +4 -1
  111. package/apps/ui/dist/server/assets/source-session-export-server-DNutCawb.js +38 -0
  112. package/apps/ui/dist/server/assets/{start-CI_0bSiY.js → start-B_HFwkkk.js} +1 -1
  113. package/apps/ui/dist/server/assets/{tabs-CGA13IZM.js → tabs-DkaChNVg.js} +0 -1
  114. package/apps/ui/dist/server/assets/thread-transcript-stats-Dh34mt2u.js +45 -0
  115. package/apps/ui/dist/server/assets/{threads._threadId-D2GYkVn6.js → threads._threadId-BeXEc4Lo.js} +15 -6
  116. package/apps/ui/dist/server/assets/{threads._threadId-Bs0yuqO9.js → threads._threadId-Ci0S4mKU.js} +1 -1
  117. package/apps/ui/dist/server/server.js +72 -24
  118. package/package.json +21 -4
  119. package/src/lib/claude-code-db.ts +655 -0
  120. package/src/lib/claude-code-exporter-types.ts +110 -0
  121. package/src/lib/claude-code-transcript-phase.ts +25 -0
  122. package/src/lib/claude-code-transcript.ts +180 -0
  123. package/src/lib/codex-browser-db.ts +490 -31
  124. package/src/lib/codex-browser-export.ts +18 -2
  125. package/src/lib/codex-thread-cache.ts +17 -1
  126. package/src/lib/concurrency.ts +25 -0
  127. package/src/lib/kiro-db.ts +949 -0
  128. package/src/lib/kiro-exporter-types.ts +100 -0
  129. package/src/lib/kiro-transcript-phase.ts +41 -0
  130. package/src/lib/kiro-transcript.ts +115 -0
  131. package/src/lib/opencode-db.ts +610 -0
  132. package/src/lib/opencode-exporter-types.ts +129 -0
  133. package/src/lib/opencode-think-tags.ts +126 -0
  134. package/src/lib/opencode-transcript-phase.ts +50 -0
  135. package/src/lib/opencode-transcript.ts +194 -0
  136. package/src/lib/shared.ts +25 -0
  137. package/src/lib/ui-export-archive.ts +61 -0
  138. package/apps/ui/dist/client/assets/analytics-DK2jdvmI.js +0 -1
  139. package/apps/ui/dist/client/assets/antigravity-keychain-panel-BRHVjFAM.js +0 -1
  140. package/apps/ui/dist/client/assets/antigravity._workspaceKey-CGV7amas.js +0 -1
  141. package/apps/ui/dist/client/assets/createServerFn-CgRRVpBH.js +0 -3
  142. package/apps/ui/dist/client/assets/cursor-threads._composerId-Ti2gTm63.js +0 -1
  143. package/apps/ui/dist/client/assets/cursor._workspaceKey-DzD_c6j9.js +0 -1
  144. package/apps/ui/dist/client/assets/cursor.index-PkCFVcl4.js +0 -2
  145. package/apps/ui/dist/client/assets/delete-confirm-dialog-BHRmyLHr.js +0 -11
  146. package/apps/ui/dist/client/assets/dropdown-menu-Dy5cLzTy.js +0 -1
  147. package/apps/ui/dist/client/assets/export-dialog-C86SYHJn.js +0 -1
  148. package/apps/ui/dist/client/assets/index-CPvAP-jk.js +0 -149
  149. package/apps/ui/dist/client/assets/projects._project-Ckf6muWZ.js +0 -1
  150. package/apps/ui/dist/client/assets/projects.index-V5ibNZII.js +0 -3
  151. package/apps/ui/dist/client/assets/routes-Df2tgpyd.js +0 -1
  152. package/apps/ui/dist/client/assets/select-Bf2GwfPR.js +0 -1
  153. package/apps/ui/dist/client/assets/settings-5VQIzME0.js +0 -1
  154. package/apps/ui/dist/client/assets/styles-BhRkXgwB.css +0 -1
  155. package/apps/ui/dist/client/assets/tabs-OO4VU5KR.js +0 -7
  156. package/apps/ui/dist/client/assets/threads._threadId-BgDhFj2I.js +0 -1
  157. package/apps/ui/dist/client/assets/useMutation-CC_B7uy5.js +0 -1
  158. package/apps/ui/dist/client/assets/useQuery-C5By6WKU.js +0 -1
  159. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CRW2kqj0.js +0 -232
@@ -1,18 +1,20 @@
1
1
  import { t as createServerFn } from "../server.js";
2
2
  import { t as createServerRpc } from "./createServerRpc-CF_DEwnm.js";
3
- import { a as cleanInlineTitle, c as formatInlineLiteral, d as readJsonlObjects, h as renderSection, i as cleanExtractedText, l as formatModelLabel, m as renderMetadataBlock, n as asObject, o as createExportWriteStream, p as renderDocumentTitle, r as asString, s as finalizeExportWriteStream, t as asNumber, u as getPortablePathBasename } from "./shared-CPRNYIql.js";
3
+ import { a as sanitizeExportFileName, n as ensureUiExportDir, o as zipExportDirectory, r as getExportMimeType, s as zipExportFile, t as buildUiExportDownloadUrl } from "./ui-export-files-BHLX9bhN.js";
4
+ import { a as cleanExtractedText, c as finalizeExportWriteStream, d as getPortablePathBasename, f as readJsonlObjects$1, g as renderSection, h as renderMetadataBlock, i as asString, l as formatInlineLiteral, m as renderDocumentTitle, n as asNumber, o as cleanInlineTitle, r as asObject, s as createExportWriteStream, u as formatModelLabel } from "./shared-DyhChtHf.js";
4
5
  import { t as mapWithConcurrency } from "./concurrency-VXtYvlGh.js";
5
6
  import { t as isRetryableSqliteError } from "./sqlite-error-LZDrnxdd.js";
6
7
  import { t as applyPathTransforms } from "./path-transforms-DL2IwtYd.js";
7
- import { a as sanitizeExportFileName, n as ensureUiExportDir, o as zipExportDirectory, r as getExportMimeType, s as zipExportFile, t as buildUiExportDownloadUrl } from "./ui-export-files-BHLX9bhN.js";
8
8
  import { finished } from "node:stream/promises";
9
9
  import { z } from "zod";
10
- import { Database } from "bun:sqlite";
10
+ import { createHash, randomUUID } from "node:crypto";
11
11
  import { copyFile, mkdir, mkdtemp, readdir, rename, rm, stat, utimes } from "node:fs/promises";
12
12
  import os from "node:os";
13
13
  import path from "node:path";
14
- import { createReadStream } from "node:fs";
15
- import { createHash, randomUUID } from "node:crypto";
14
+ import { Database, constants } from "bun:sqlite";
15
+ import { closeSync, createReadStream, openSync, readSync, readdirSync, statSync } from "node:fs";
16
+ import { StringDecoder } from "node:string_decoder";
17
+ import { pathToFileURL } from "node:url";
16
18
  //#region ../../src/lib/codex-exporter-types.ts
17
19
  var DEFAULT_CODEX_DIR = path.join(os.homedir(), ".codex");
18
20
  var DEFAULT_DB_PATH = path.join(DEFAULT_CODEX_DIR, "state_5.sqlite");
@@ -57,7 +59,7 @@ var parseCodexTranscriptFile = async (sessionFile, options = {}) => {
57
59
  const maxEvents = options.maxEvents ?? Number.POSITIVE_INFINITY;
58
60
  const maxTurnContexts = options.maxTurnContexts ?? Number.POSITIVE_INFINITY;
59
61
  let sequence = 0;
60
- for await (const parsed of readJsonlObjects(sessionFile)) {
62
+ for await (const parsed of readJsonlObjects$1(sessionFile)) {
61
63
  captureSessionMeta$1(parsed, sessionMeta);
62
64
  if (asString(parsed.type) === "turn_context") {
63
65
  if (turnContexts.length < maxTurnContexts) captureTurnContext(parsed, turnContexts);
@@ -433,12 +435,24 @@ var invalidateCacheByPrefix = async (...prefixes) => {
433
435
  //#endregion
434
436
  //#region ../../src/lib/codex-thread-cache.ts
435
437
  var LARGE_THREAD_SIZE_BYTES = 100 * 1024 * 1024;
438
+ var isMissingFileError$2 = (error) => {
439
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
440
+ };
436
441
  var getCachedParsedCodexTranscript = async (sessionFile) => {
437
442
  const fingerprint = await getFileFingerprint(sessionFile);
438
443
  return withCachedJson(`thread-${hashCacheKeyParts(path.basename(sessionFile), fingerprint)}`, async () => parseCodexTranscriptFile(sessionFile));
439
444
  };
440
445
  var getThreadRolloutLoadState = async (sessionFile, largeTranscriptThresholdBytes = LARGE_THREAD_SIZE_BYTES) => {
441
- const metadata = await stat(sessionFile);
446
+ let metadata;
447
+ try {
448
+ metadata = await stat(sessionFile);
449
+ } catch (error) {
450
+ if (isMissingFileError$2(error)) return {
451
+ fileSizeBytes: null,
452
+ shouldDeferTranscriptLoad: false
453
+ };
454
+ throw error;
455
+ }
442
456
  return {
443
457
  fileSizeBytes: metadata.size,
444
458
  shouldDeferTranscriptLoad: metadata.size > largeTranscriptThresholdBytes
@@ -496,6 +510,13 @@ var runWithSqliteRetry = ({ action, delaysMs = DEFAULT_RETRY_DELAYS_MS, sleep =
496
510
  var SQLITE_DELETE_BATCH_SIZE = 400;
497
511
  var SESSION_FILE_DELETE_CONCURRENCY = 16;
498
512
  var THREAD_LIST_IO_CONCURRENCY = 8;
513
+ var CODEX_READONLY_DB_OPEN_FLAGS = constants.SQLITE_OPEN_READONLY | constants.SQLITE_OPEN_URI;
514
+ var JSONL_READ_CHUNK_BYTES = 64 * 1024;
515
+ var SESSION_META_READ_LIMIT_BYTES = 4 * 1024 * 1024;
516
+ var THREAD_ID_PATTERN = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/iu;
517
+ var isSqliteCantOpenError = (error) => {
518
+ return error.code === "SQLITE_CANTOPEN";
519
+ };
499
520
  var chunkValues = (values, chunkSize) => {
500
521
  const chunks = [];
501
522
  for (let index = 0; index < values.length; index += chunkSize) chunks.push(values.slice(index, index + chunkSize));
@@ -505,15 +526,16 @@ var isPromiseLike = (value) => {
505
526
  if (typeof value !== "object" && typeof value !== "function" || value === null) return false;
506
527
  return "then" in value && typeof value.then === "function";
507
528
  };
508
- var openReadonlyDb = (dbPath, busyTimeoutMs) => {
529
+ var openReadonlyDb = (dbPath) => {
509
530
  const db = new Database(dbPath, { readonly: true });
510
531
  try {
511
- db.exec(`PRAGMA busy_timeout = ${busyTimeoutMs}`);
532
+ db.query("SELECT name FROM sqlite_master LIMIT 1").get();
512
533
  return db;
513
534
  } catch (error) {
514
535
  db.close();
515
- throw error;
536
+ if (!isSqliteCantOpenError(error)) throw error;
516
537
  }
538
+ return new Database(`${pathToFileURL(dbPath).href}?immutable=1`, CODEX_READONLY_DB_OPEN_FLAGS);
517
539
  };
518
540
  var openWritableDb = (dbPath, busyTimeoutMs) => {
519
541
  const db = new Database(dbPath);
@@ -549,7 +571,7 @@ var parseJsonSafely$1 = (value) => {
549
571
  };
550
572
  var withReadonlyDb = (dbPath, callback) => {
551
573
  return runWithSqliteRetry({ action: () => {
552
- const db = openReadonlyDb(dbPath, 5e3);
574
+ const db = openReadonlyDb(dbPath);
553
575
  try {
554
576
  const result = callback(db);
555
577
  if (isPromiseLike(result)) throw new Error("Database callbacks must be synchronous");
@@ -580,9 +602,7 @@ var resolveCodexThreadDbPath = () => {
580
602
  path.join(os.homedir(), ".codex", "state_5.sqlite")
581
603
  ];
582
604
  for (const candidate of candidates) try {
583
- runWithSqliteRetry({ action: () => {
584
- return openReadonlyDb(candidate, 1500);
585
- } }).close();
605
+ if (!statSync(candidate).isFile()) continue;
586
606
  return candidate;
587
607
  } catch {}
588
608
  throw new Error(`Unable to open Codex thread database. Tried: ${candidates.join(", ")}`);
@@ -592,6 +612,256 @@ var readAllThreads = (dbPath) => {
592
612
  return db.query("SELECT * FROM threads ORDER BY COALESCE(updated_at_ms, updated_at * 1000) DESC, id DESC").all();
593
613
  });
594
614
  };
615
+ var resolveCodexDirFromDbPath$1 = (dbPath) => {
616
+ const dbDir = path.dirname(dbPath);
617
+ return path.basename(dbDir) === "sqlite" ? path.dirname(dbDir) : dbDir;
618
+ };
619
+ var parseJsonlObject = (line) => {
620
+ try {
621
+ return JSON.parse(line);
622
+ } catch {
623
+ return null;
624
+ }
625
+ };
626
+ var emitJsonlLine = (line, onRecord) => {
627
+ const trimmed = line.trim();
628
+ const parsed = trimmed ? parseJsonlObject(trimmed) : null;
629
+ if (parsed) onRecord(parsed);
630
+ };
631
+ var emitCompleteJsonlLines = (text, onRecord) => {
632
+ const lines = text.split(/\r?\n/u);
633
+ const pending = lines.pop() ?? "";
634
+ for (const line of lines) emitJsonlLine(line, onRecord);
635
+ return pending;
636
+ };
637
+ var readJsonlObjects = (filePath, onRecord) => {
638
+ let descriptor = null;
639
+ try {
640
+ if (!statSync(filePath).isFile()) return;
641
+ descriptor = openSync(filePath, "r");
642
+ const buffer = Buffer.alloc(JSONL_READ_CHUNK_BYTES);
643
+ const decoder = new StringDecoder("utf8");
644
+ let position = 0;
645
+ let pending = "";
646
+ while (true) {
647
+ const bytesRead = readSync(descriptor, buffer, 0, buffer.length, position);
648
+ if (bytesRead === 0) break;
649
+ position += bytesRead;
650
+ pending += decoder.write(buffer.subarray(0, bytesRead));
651
+ pending = emitCompleteJsonlLines(pending, onRecord);
652
+ }
653
+ emitJsonlLine(pending + decoder.end(), onRecord);
654
+ } catch {
655
+ return;
656
+ } finally {
657
+ if (descriptor !== null) closeSync(descriptor);
658
+ }
659
+ };
660
+ var collectJsonlObjects = (filePath) => {
661
+ const records = [];
662
+ readJsonlObjects(filePath, (record) => {
663
+ records.push(record);
664
+ });
665
+ return records;
666
+ };
667
+ var readSessionIndexEntries = (codexDir) => {
668
+ return collectJsonlObjects(path.join(codexDir, "session_index.jsonl")).filter((entry) => typeof entry.id === "string" && entry.id.length > 0);
669
+ };
670
+ var collectSessionFilesByThreadId = (sessionsDir) => {
671
+ const sessionFiles = /* @__PURE__ */ new Map();
672
+ const visit = (directory) => {
673
+ const entries = (() => {
674
+ try {
675
+ return readdirSync(directory, { withFileTypes: true });
676
+ } catch {
677
+ return null;
678
+ }
679
+ })();
680
+ if (!entries) return;
681
+ for (const entry of entries) {
682
+ const entryPath = path.join(directory, entry.name);
683
+ if (entry.isDirectory()) {
684
+ visit(entryPath);
685
+ continue;
686
+ }
687
+ if (!entry.isFile()) continue;
688
+ const threadId = THREAD_ID_PATTERN.exec(entry.name)?.[1];
689
+ if (threadId && !sessionFiles.has(threadId)) sessionFiles.set(threadId, entryPath);
690
+ }
691
+ };
692
+ visit(sessionsDir);
693
+ return sessionFiles;
694
+ };
695
+ var readSessionMetaLine = (sessionFile) => {
696
+ let descriptor = null;
697
+ try {
698
+ descriptor = openSync(sessionFile, "r");
699
+ const chunks = [];
700
+ let totalBytes = 0;
701
+ while (totalBytes < SESSION_META_READ_LIMIT_BYTES) {
702
+ const buffer = Buffer.alloc(Math.min(64 * 1024, SESSION_META_READ_LIMIT_BYTES - totalBytes));
703
+ const bytesRead = readSync(descriptor, buffer, 0, buffer.length, totalBytes);
704
+ if (bytesRead === 0) break;
705
+ chunks.push(buffer.subarray(0, bytesRead));
706
+ totalBytes += bytesRead;
707
+ if (buffer.subarray(0, bytesRead).includes(10)) break;
708
+ }
709
+ return Buffer.concat(chunks).toString("utf8").split(/\r?\n/u)[0]?.trim() || null;
710
+ } catch {
711
+ return null;
712
+ } finally {
713
+ if (descriptor !== null) closeSync(descriptor);
714
+ }
715
+ };
716
+ var readFallbackSessionMeta = (sessionFile) => {
717
+ const line = readSessionMetaLine(sessionFile);
718
+ if (!line) return null;
719
+ try {
720
+ const record = JSON.parse(line);
721
+ return record.type === "session_meta" && record.payload ? record.payload : null;
722
+ } catch {
723
+ return null;
724
+ }
725
+ };
726
+ var parseIsoMs = (value, fallback) => {
727
+ if (!value) return fallback;
728
+ const parsed = Date.parse(value);
729
+ return Number.isFinite(parsed) ? parsed : fallback;
730
+ };
731
+ var stringOrNull = (value) => typeof value === "string" && value.length > 0 ? value : null;
732
+ var numberOrNull = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
733
+ var objectOrNull = (value) => {
734
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
735
+ };
736
+ var isFallbackSubagent = (sessionMeta) => {
737
+ return Boolean(sessionMeta.thread_source === "subagent" || stringOrNull(sessionMeta.parent_thread_id) || stringOrNull(sessionMeta.forked_from_id));
738
+ };
739
+ var readFallbackRolloutStats = (sessionFile) => {
740
+ let model = null;
741
+ let tokensUsed = 0;
742
+ readJsonlObjects(sessionFile, (record) => {
743
+ const payload = objectOrNull(record.payload);
744
+ if (!payload) return;
745
+ if (record.type === "turn_context") {
746
+ model = stringOrNull(payload.model) ?? model;
747
+ return;
748
+ }
749
+ const payloadType = stringOrNull(payload.type);
750
+ if (payloadType === "message" || payloadType === "agent_message") {
751
+ model = stringOrNull(payload.model) ?? model;
752
+ return;
753
+ }
754
+ if (payloadType !== "token_count") return;
755
+ tokensUsed = numberOrNull(objectOrNull(objectOrNull(payload.info)?.total_token_usage)?.total_tokens) ?? tokensUsed;
756
+ });
757
+ return {
758
+ model,
759
+ tokensUsed
760
+ };
761
+ };
762
+ var buildFallbackThreadRow = (entry, sessionFile, sessionMeta, rolloutStats) => {
763
+ const cwd = stringOrNull(sessionMeta.cwd);
764
+ if (!cwd) return null;
765
+ let mtimeMs = Date.now();
766
+ try {
767
+ mtimeMs = statSync(sessionFile).mtimeMs;
768
+ } catch {}
769
+ const updatedAtMs = parseIsoMs(entry.updated_at, mtimeMs);
770
+ const createdAtMs = parseIsoMs(sessionMeta.timestamp, updatedAtMs);
771
+ const title = entry.thread_name?.trim() || path.basename(sessionFile, ".jsonl");
772
+ const source = stringOrNull(sessionMeta.source) ?? "session_file";
773
+ return {
774
+ agent_nickname: sessionMeta.agent_nickname ?? null,
775
+ agent_path: sessionMeta.agent_path ?? null,
776
+ agent_role: sessionMeta.agent_role ?? null,
777
+ approval_mode: "unknown",
778
+ archived: 0,
779
+ archived_at: null,
780
+ cli_version: sessionMeta.cli_version ?? "",
781
+ created_at: Math.floor(createdAtMs / 1e3),
782
+ created_at_ms: Math.floor(createdAtMs),
783
+ cwd,
784
+ first_user_message: title,
785
+ git_branch: null,
786
+ git_origin_url: null,
787
+ git_sha: null,
788
+ has_user_event: sessionMeta.thread_source === "user" ? 1 : 0,
789
+ id: entry.id,
790
+ memory_mode: "enabled",
791
+ model: rolloutStats.model,
792
+ model_provider: sessionMeta.model_provider ?? "unknown",
793
+ preview: title,
794
+ reasoning_effort: null,
795
+ rollout_path: sessionFile,
796
+ sandbox_policy: "{}",
797
+ source,
798
+ thread_source: sessionMeta.thread_source ?? null,
799
+ title,
800
+ tokens_used: rolloutStats.tokensUsed,
801
+ updated_at: Math.floor(updatedAtMs / 1e3),
802
+ updated_at_ms: Math.floor(updatedAtMs)
803
+ };
804
+ };
805
+ var readFallbackThreadRows = (dbPath, existingThreadIds, projectName = null, options = {}) => {
806
+ const codexDir = resolveCodexDirFromDbPath$1(dbPath);
807
+ const sessionFilesByThreadId = collectSessionFilesByThreadId(path.join(codexDir, "sessions"));
808
+ const fallbackThreads = [];
809
+ for (const entry of readSessionIndexEntries(codexDir)) {
810
+ if (existingThreadIds.has(entry.id)) continue;
811
+ const sessionFile = sessionFilesByThreadId.get(entry.id);
812
+ if (!sessionFile) continue;
813
+ const sessionMeta = readFallbackSessionMeta(sessionFile);
814
+ if (!sessionMeta) continue;
815
+ if (!options.includeSubagents && isFallbackSubagent(sessionMeta)) continue;
816
+ const fallbackThread = buildFallbackThreadRow(entry, sessionFile, sessionMeta, readFallbackRolloutStats(sessionFile));
817
+ if (!fallbackThread || projectName && getPortablePathBasename(fallbackThread.cwd) !== projectName) continue;
818
+ fallbackThreads.push(fallbackThread);
819
+ }
820
+ return fallbackThreads;
821
+ };
822
+ var mergeFallbackThreadRows = (dbPath, threads, projectName = null) => {
823
+ const threadIds = new Set(threads.map((thread) => thread.id));
824
+ return [...threads, ...readFallbackThreadRows(dbPath, threadIds, projectName)].sort((left, right) => {
825
+ const updatedDifference = toTimestampMs(right) - toTimestampMs(left);
826
+ if (updatedDifference !== 0) return updatedDifference;
827
+ return right.id.localeCompare(left.id);
828
+ });
829
+ };
830
+ var applyRolloutActivityTimestamps = (threads) => {
831
+ return threads.map((thread) => {
832
+ let rolloutUpdatedAtMs = toTimestampMs(thread);
833
+ try {
834
+ rolloutUpdatedAtMs = Math.max(rolloutUpdatedAtMs, statSync(thread.rollout_path).mtimeMs);
835
+ } catch {}
836
+ if (rolloutUpdatedAtMs <= toTimestampMs(thread)) return thread;
837
+ return {
838
+ ...thread,
839
+ updated_at: Math.floor(rolloutUpdatedAtMs / 1e3),
840
+ updated_at_ms: Math.floor(rolloutUpdatedAtMs)
841
+ };
842
+ }).sort((left, right) => {
843
+ const updatedDifference = toTimestampMs(right) - toTimestampMs(left);
844
+ if (updatedDifference !== 0) return updatedDifference;
845
+ return right.id.localeCompare(left.id);
846
+ });
847
+ };
848
+ var buildDashboardRecentThreads = (threads) => {
849
+ const bestThreadByProject = /* @__PURE__ */ new Map();
850
+ for (const thread of threads) {
851
+ const project = getPortablePathBasename(thread.cwd);
852
+ if (!project) continue;
853
+ const current = bestThreadByProject.get(project);
854
+ if (!current || toTimestampMs(thread) > toTimestampMs(current)) bestThreadByProject.set(project, thread);
855
+ }
856
+ return [...bestThreadByProject.values()].sort((left, right) => {
857
+ const updatedDifference = toTimestampMs(right) - toTimestampMs(left);
858
+ if (updatedDifference !== 0) return updatedDifference;
859
+ return right.id.localeCompare(left.id);
860
+ }).slice(0, 5).map((thread) => ({
861
+ project: getPortablePathBasename(thread.cwd),
862
+ thread: compactThreadListRow(thread)
863
+ }));
864
+ };
595
865
  var filterThreadsByProject = (threads, projectName) => {
596
866
  if (!projectName) return threads;
597
867
  return threads.filter((thread) => getPortablePathBasename(thread.cwd) === projectName);
@@ -696,7 +966,7 @@ var deleteThreadSessionFiles = async (sessionFiles) => {
696
966
  return uniqueSessionFiles;
697
967
  };
698
968
  var listCodexProjects = (dbPath) => {
699
- return mapProjectSummaries(buildProjectSummaryMap(readAllThreads(dbPath)));
969
+ return mapProjectSummaries(buildProjectSummaryMap(applyRolloutActivityTimestamps(mergeFallbackThreadRows(dbPath, readAllThreads(dbPath)))));
700
970
  };
701
971
  var compactThreadListRow = (thread) => {
702
972
  return {
@@ -706,8 +976,19 @@ var compactThreadListRow = (thread) => {
706
976
  };
707
977
  };
708
978
  var listProjectThreads = async (dbPath, projectName, options = {}) => {
709
- return (await mapWithConcurrency(filterThreadsByProject(readAllThreads(dbPath), projectName), THREAD_LIST_IO_CONCURRENCY, async (thread) => {
979
+ return (await mapWithConcurrency(applyRolloutActivityTimestamps(mergeFallbackThreadRows(dbPath, filterThreadsByProject(readAllThreads(dbPath), projectName), projectName)), THREAD_LIST_IO_CONCURRENCY, async (thread) => {
710
980
  const rollout = await getThreadRolloutLoadState(thread.rollout_path, options.largeTranscriptThresholdBytes);
981
+ if (rollout.fileSizeBytes === null) return {
982
+ project: projectName,
983
+ rolloutSizeBytes: null,
984
+ stats: {
985
+ deferred: false,
986
+ execCommandCount: 0,
987
+ toolCallCount: 0,
988
+ webSearchEventCount: 0
989
+ },
990
+ thread: compactThreadListRow(thread)
991
+ };
711
992
  if (rollout.shouldDeferTranscriptLoad) return {
712
993
  project: projectName,
713
994
  rolloutSizeBytes: rollout.fileSizeBytes,
@@ -736,10 +1017,11 @@ var listProjectThreads = async (dbPath, projectName, options = {}) => {
736
1017
  var getThreadBrowseData = (dbPath, threadId) => {
737
1018
  return withReadonlyDb(dbPath, (db) => {
738
1019
  const existingTableNames = getExistingTableNames(db);
739
- const thread = db.query("SELECT * FROM threads WHERE id = ? LIMIT 1").get(threadId);
1020
+ const dbThread = db.query("SELECT * FROM threads WHERE id = ? LIMIT 1").get(threadId);
1021
+ const thread = dbThread ?? readFallbackThreadRows(dbPath, /* @__PURE__ */ new Set(), null, { includeSubagents: true }).find((fallbackThread) => fallbackThread.id === threadId) ?? null;
740
1022
  if (!thread) throw new Error(`Thread not found: ${threadId}`);
741
1023
  return {
742
- dynamicTools: (existingTableNames.has("thread_dynamic_tools") ? db.query("SELECT thread_id, position, name, description, input_schema, defer_loading, namespace FROM thread_dynamic_tools WHERE thread_id = ? ORDER BY position ASC").all(threadId) : []).map((row) => parseDynamicToolRow(row)),
1024
+ dynamicTools: (dbThread && existingTableNames.has("thread_dynamic_tools") ? db.query("SELECT thread_id, position, name, description, input_schema, defer_loading, namespace FROM thread_dynamic_tools WHERE thread_id = ? ORDER BY position ASC").all(threadId) : []).map((row) => parseDynamicToolRow(row)),
743
1025
  project: getPortablePathBasename(thread.cwd),
744
1026
  relations: getRelationsForThread(db, threadId, existingTableNames),
745
1027
  thread
@@ -747,7 +1029,7 @@ var getThreadBrowseData = (dbPath, threadId) => {
747
1029
  });
748
1030
  };
749
1031
  var getCodexDashboardSummary = (dbPath) => {
750
- const threads = readAllThreads(dbPath);
1032
+ const threads = applyRolloutActivityTimestamps(mergeFallbackThreadRows(dbPath, readAllThreads(dbPath)));
751
1033
  const projects = mapProjectSummaries(buildProjectSummaryMap(threads));
752
1034
  const threadsWithRelations = withReadonlyDb(dbPath, (db) => {
753
1035
  if (!getExistingTableNames(db).has("thread_spawn_edges")) return 0;
@@ -757,10 +1039,7 @@ var getCodexDashboardSummary = (dbPath) => {
757
1039
  return {
758
1040
  activeThreads: threads.filter((thread) => !thread.archived).length,
759
1041
  archivedThreads: threads.filter((thread) => Boolean(thread.archived)).length,
760
- recentThreads: threads.slice(0, 5).filter((thread) => Boolean(getPortablePathBasename(thread.cwd))).map((thread) => ({
761
- project: getPortablePathBasename(thread.cwd),
762
- thread: compactThreadListRow(thread)
763
- })),
1042
+ recentThreads: buildDashboardRecentThreads(threads),
764
1043
  threadsWithRelations,
765
1044
  topProjectsByThreadCount: [...projects].sort((left, right) => {
766
1045
  if (left.threadCount !== right.threadCount) return right.threadCount - left.threadCount;
@@ -827,7 +1106,7 @@ var deleteCodexProject = async (dbPath, projectName, options = {}) => {
827
1106
  }
828
1107
  };
829
1108
  var listScopedThreads = (dbPath, projectName) => {
830
- return filterThreadsByProject(readAllThreads(dbPath), projectName);
1109
+ return mergeFallbackThreadRows(dbPath, filterThreadsByProject(readAllThreads(dbPath), projectName), projectName);
831
1110
  };
832
1111
  var invalidateCodexUiCaches = async () => {
833
1112
  await invalidateCacheByPrefix("analytics-", "thread-");
@@ -905,7 +1184,7 @@ var buildThreadAnalyticsCacheKey = (thread) => {
905
1184
  var parseThreadAnalyticsFile = async (sessionFile) => {
906
1185
  const toolNames = [];
907
1186
  let hasWebSearch = false;
908
- for await (const parsed of readJsonlObjects(sessionFile)) {
1187
+ for await (const parsed of readJsonlObjects$1(sessionFile)) {
909
1188
  if (parsed.type !== "response_item") continue;
910
1189
  const payload = asObject(parsed.payload);
911
1190
  if (!payload) continue;
@@ -1006,7 +1285,7 @@ var writeSessionFileExport = async (target, options, outputPath, transform = (te
1006
1285
  let wroteSection = false;
1007
1286
  try {
1008
1287
  transcriptStream = await createExportWriteStream(transcriptOutputPath);
1009
- for await (const parsed of readJsonlObjects(target.sessionFile)) {
1288
+ for await (const parsed of readJsonlObjects$1(target.sessionFile)) {
1010
1289
  captureSessionMeta(parsed, state.sessionMeta);
1011
1290
  const block = renderCodexTranscriptRecord(parsed, options, state);
1012
1291
  if (!block) continue;
@@ -1043,7 +1322,7 @@ var collectCodexTranscript = async (sessionFile, options, assistantModel = null)
1043
1322
  sections: [],
1044
1323
  sessionMeta: {}
1045
1324
  };
1046
- for await (const parsed of readJsonlObjects(sessionFile)) processCodexTranscriptRecord(parsed, options, state);
1325
+ for await (const parsed of readJsonlObjects$1(sessionFile)) processCodexTranscriptRecord(parsed, options, state);
1047
1326
  return state;
1048
1327
  };
1049
1328
  var getSectionSeparator = () => "\n";
@@ -1500,6 +1779,17 @@ var getRolloutSnapshot = async (rolloutPath) => {
1500
1779
  sizeBytes: metadata.size
1501
1780
  };
1502
1781
  };
1782
+ var isMissingFileError$1 = (error) => {
1783
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
1784
+ };
1785
+ var getExistingRolloutSnapshot = async (threadId, rolloutPath) => {
1786
+ try {
1787
+ return await getRolloutSnapshot(rolloutPath);
1788
+ } catch (error) {
1789
+ if (isMissingFileError$1(error)) throw new Error(`Thread ${threadId} rollout file is missing: ${rolloutPath}`, { cause: error });
1790
+ throw error;
1791
+ }
1792
+ };
1503
1793
  var logExportEvent = (level, event, details) => {
1504
1794
  console[level](`[spiracha:export] ${event}`, details);
1505
1795
  };
@@ -1537,7 +1827,7 @@ var renderCodexThreadDownload = async (input) => {
1537
1827
  ...input.pathDisplaySettings,
1538
1828
  projectPath: browseData.thread.cwd
1539
1829
  }) : text;
1540
- const rolloutSnapshotBefore = await getRolloutSnapshot(browseData.thread.rollout_path);
1830
+ const rolloutSnapshotBefore = await getExistingRolloutSnapshot(input.threadId, browseData.thread.rollout_path);
1541
1831
  logExportEvent("info", "single_start", {
1542
1832
  fileName,
1543
1833
  sizeBytes: rolloutSnapshotBefore.sizeBytes,
@@ -1630,7 +1920,7 @@ var renderCodexThreadsDownload = async (input) => {
1630
1920
  });
1631
1921
  try {
1632
1922
  for (const entry of browseEntries) {
1633
- const rolloutSnapshotBefore = await getRolloutSnapshot(entry.thread.rollout_path);
1923
+ const rolloutSnapshotBefore = await getExistingRolloutSnapshot(entry.thread.id, entry.thread.rollout_path);
1634
1924
  const singleBaseName = buildExportBaseName(entry.thread);
1635
1925
  const uniqueBaseName = buildUniqueBatchEntryBaseName(singleBaseName, entry.thread.id, usedBatchEntryBaseNames);
1636
1926
  const relativeFileName = `${uniqueBaseName}.${input.outputFormat === "md" ? "md" : "txt"}`;
@@ -1,9 +1,9 @@
1
- import { n as asObject, r as asString, t as asNumber } from "./shared-CPRNYIql.js";
1
+ import { i as asString, n as asNumber, r as asObject } from "./shared-DyhChtHf.js";
2
2
  import { getCursorGlobalDbPath, getCursorProjectsDir, getCursorWorkspaceStorageDir, resolveCursorUserDir } from "./cursor-exporter-types-CI3goo-c.js";
3
- import { Database, constants } from "bun:sqlite";
3
+ import { createHash } from "node:crypto";
4
4
  import { readdir, stat } from "node:fs/promises";
5
5
  import path from "node:path";
6
- import { createHash } from "node:crypto";
6
+ import { Database, constants } from "bun:sqlite";
7
7
  //#region ../../src/lib/cursor-db.ts
8
8
  var CURSOR_READONLY_DB_OPEN_FLAGS = constants.SQLITE_OPEN_READONLY | constants.SQLITE_OPEN_URI;
9
9
  var getCursorReadonlyDbUri = (dbPath) => {
@@ -1,7 +1,7 @@
1
1
  import { COMPOSER_DATA_KEY, COMPOSER_HEADERS_KEY, getCursorGlobalDbPath, resolveCursorUserDir } from "./cursor-exporter-types-CI3goo-c.js";
2
- import { findCursorTranscriptDirs, invalidateCursorDiscoveryCache, listCursorWorkspaceGroups, loadGlobalComposerHeaders, openCursorReadonlyDb } from "./cursor-db-cYZEU3WQ.js";
3
- import { Database } from "bun:sqlite";
2
+ import { findCursorTranscriptDirs, invalidateCursorDiscoveryCache, listCursorWorkspaceGroups, loadGlobalComposerHeaders, openCursorReadonlyDb } from "./cursor-db-CZnYy7aT.js";
4
3
  import { rm } from "node:fs/promises";
4
+ import { Database } from "bun:sqlite";
5
5
  //#region ../../src/lib/cursor-recovery.ts
6
6
  var isCursorRunning = async () => {
7
7
  return await Bun.spawn([
@@ -2,10 +2,10 @@ import { t as createServerFn } from "../server.js";
2
2
  import { t as createServerRpc } from "./createServerRpc-CF_DEwnm.js";
3
3
  import { a as sanitizeExportFileName, i as resolveUniqueExportFileBaseName, n as ensureUiExportDir, o as zipExportDirectory, r as getExportMimeType, t as buildUiExportDownloadUrl } from "./ui-export-files-BHLX9bhN.js";
4
4
  import { z } from "zod";
5
+ import { randomUUID } from "node:crypto";
5
6
  import { mkdtemp, rm } from "node:fs/promises";
6
7
  import os from "node:os";
7
8
  import path from "node:path";
8
- import { randomUUID } from "node:crypto";
9
9
  //#region src/lib/cursor-server.ts?tss-serverfn-split
10
10
  var workspaceSchema = z.object({ workspaceKey: z.string().min(1) });
11
11
  var threadSchema = z.object({ composerId: z.string().min(1) });
@@ -31,11 +31,11 @@ var exportThreadsSchema = z.object({
31
31
  });
32
32
  var deleteThreadsSchema = z.object({ composerIds: z.array(z.string().min(1)).min(1) });
33
33
  var ensureCursorClosedForWrite = async () => {
34
- const { isCursorRunning } = await import("./cursor-recovery-nq-kR62j.js");
34
+ const { isCursorRunning } = await import("./cursor-recovery-CXpO8KcD.js");
35
35
  if (await isCursorRunning()) throw new Error("Quit Cursor before deleting. It rewrites chat history on exit, which can resurrect deleted threads.");
36
36
  };
37
37
  var findGroupByKey = async (workspaceKey) => {
38
- const { listCursorWorkspaceGroups } = await import("./cursor-db-cYZEU3WQ.js");
38
+ const { listCursorWorkspaceGroups } = await import("./cursor-db-CZnYy7aT.js");
39
39
  const group = (await listCursorWorkspaceGroups()).find((candidate) => candidate.key === workspaceKey);
40
40
  if (!group) throw new Error(`Cursor workspace not found: ${workspaceKey}`);
41
41
  return group;
@@ -69,7 +69,7 @@ var renderCursorZipDownload = async (rendered, outputFormat) => {
69
69
  };
70
70
  };
71
71
  var findCursorThreadByComposerId = async (composerId) => {
72
- const { listCursorThreadsForGroup, listCursorWorkspaceGroups } = await import("./cursor-db-cYZEU3WQ.js");
72
+ const { listCursorThreadsForGroup, listCursorWorkspaceGroups } = await import("./cursor-db-CZnYy7aT.js");
73
73
  for (const group of await listCursorWorkspaceGroups()) {
74
74
  const thread = (await listCursorThreadsForGroup(group, void 0, { includeTranscriptDirs: false })).find((candidate) => candidate.composerId === composerId);
75
75
  if (thread) return thread;
@@ -77,9 +77,9 @@ var findCursorThreadByComposerId = async (composerId) => {
77
77
  return null;
78
78
  };
79
79
  var renderCursorDownload = async (input) => {
80
- const { readCursorThreadTranscriptWithAgentFiles } = await import("./cursor-db-cYZEU3WQ.js");
80
+ const { readCursorThreadTranscriptWithAgentFiles } = await import("./cursor-db-CZnYy7aT.js");
81
81
  const { getCursorGlobalDbPath } = await import("./cursor-exporter-types-CI3goo-c.js");
82
- const { renderCursorTranscript } = await import("./cursor-transcript-2iL3KFSK.js");
82
+ const { renderCursorTranscript } = await import("./cursor-transcript-B7tGnqtn.js");
83
83
  const globalDbPath = getCursorGlobalDbPath();
84
84
  const rendered = await Promise.all(input.composerIds.map(async (composerId) => {
85
85
  const transcript = await readCursorThreadTranscriptWithAgentFiles(globalDbPath, composerId);
@@ -111,7 +111,7 @@ var listCursorWorkspacesFn_createServerFn_handler = createServerRpc({
111
111
  filename: "src/lib/cursor-server.ts"
112
112
  }, (opts) => listCursorWorkspacesFn.__executeServer(opts));
113
113
  var listCursorWorkspacesFn = createServerFn({ method: "GET" }).handler(listCursorWorkspacesFn_createServerFn_handler, async () => {
114
- const { listCursorWorkspaceGroups } = await import("./cursor-db-cYZEU3WQ.js");
114
+ const { listCursorWorkspaceGroups } = await import("./cursor-db-CZnYy7aT.js");
115
115
  return listCursorWorkspaceGroups();
116
116
  });
117
117
  var listCursorThreadsFn_createServerFn_handler = createServerRpc({
@@ -120,7 +120,7 @@ var listCursorThreadsFn_createServerFn_handler = createServerRpc({
120
120
  filename: "src/lib/cursor-server.ts"
121
121
  }, (opts) => listCursorThreadsFn.__executeServer(opts));
122
122
  var listCursorThreadsFn = createServerFn({ method: "GET" }).validator(workspaceSchema).handler(listCursorThreadsFn_createServerFn_handler, async ({ data }) => {
123
- const { listCursorThreadsForGroup } = await import("./cursor-db-cYZEU3WQ.js");
123
+ const { listCursorThreadsForGroup } = await import("./cursor-db-CZnYy7aT.js");
124
124
  return listCursorThreadsForGroup(await findGroupByKey(data.workspaceKey), void 0, { includeTranscriptDirs: false });
125
125
  });
126
126
  var getCursorThreadDetailFn_createServerFn_handler = createServerRpc({
@@ -129,7 +129,7 @@ var getCursorThreadDetailFn_createServerFn_handler = createServerRpc({
129
129
  filename: "src/lib/cursor-server.ts"
130
130
  }, (opts) => getCursorThreadDetailFn.__executeServer(opts));
131
131
  var getCursorThreadDetailFn = createServerFn({ method: "GET" }).validator(threadSchema).handler(getCursorThreadDetailFn_createServerFn_handler, async ({ data }) => {
132
- const { readCursorThreadTranscriptWithAgentFiles } = await import("./cursor-db-cYZEU3WQ.js");
132
+ const { readCursorThreadTranscriptWithAgentFiles } = await import("./cursor-db-CZnYy7aT.js");
133
133
  const { getCursorGlobalDbPath } = await import("./cursor-exporter-types-CI3goo-c.js");
134
134
  const thread = await findCursorThreadByComposerId(data.composerId);
135
135
  if (!thread) throw new Error(`Cursor thread not found: ${data.composerId}`);
@@ -174,7 +174,7 @@ var recoverCursorWorkspaceFn_createServerFn_handler = createServerRpc({
174
174
  filename: "src/lib/cursor-server.ts"
175
175
  }, (opts) => recoverCursorWorkspaceFn.__executeServer(opts));
176
176
  var recoverCursorWorkspaceFn = createServerFn({ method: "POST" }).validator(recoverSchema).handler(recoverCursorWorkspaceFn_createServerFn_handler, async ({ data }) => {
177
- const { isCursorRunning, recoverCursorWorkspaceGroup } = await import("./cursor-recovery-nq-kR62j.js");
177
+ const { isCursorRunning, recoverCursorWorkspaceGroup } = await import("./cursor-recovery-CXpO8KcD.js");
178
178
  const group = await findGroupByKey(data.workspaceKey);
179
179
  if (data.apply && await isCursorRunning()) throw new Error("Quit Cursor before recovering. It overwrites chat history on exit, undoing the recovery.");
180
180
  return recoverCursorWorkspaceGroup(group, data.apply);
@@ -185,7 +185,7 @@ var deleteCursorThreadsFn_createServerFn_handler = createServerRpc({
185
185
  filename: "src/lib/cursor-server.ts"
186
186
  }, (opts) => deleteCursorThreadsFn.__executeServer(opts));
187
187
  var deleteCursorThreadsFn = createServerFn({ method: "POST" }).validator(deleteThreadsSchema).handler(deleteCursorThreadsFn_createServerFn_handler, async ({ data }) => {
188
- const { collectCursorThreadsForDeletion, pruneCursorThreads } = await import("./cursor-recovery-nq-kR62j.js");
188
+ const { collectCursorThreadsForDeletion, pruneCursorThreads } = await import("./cursor-recovery-CXpO8KcD.js");
189
189
  await ensureCursorClosedForWrite();
190
190
  return pruneCursorThreads(await collectCursorThreadsForDeletion(data.composerIds), true);
191
191
  });
@@ -195,8 +195,8 @@ var deleteCursorWorkspaceFn_createServerFn_handler = createServerRpc({
195
195
  filename: "src/lib/cursor-server.ts"
196
196
  }, (opts) => deleteCursorWorkspaceFn.__executeServer(opts));
197
197
  var deleteCursorWorkspaceFn = createServerFn({ method: "POST" }).validator(workspaceSchema).handler(deleteCursorWorkspaceFn_createServerFn_handler, async ({ data }) => {
198
- const { listCursorThreadsForGroup } = await import("./cursor-db-cYZEU3WQ.js");
199
- const { collectCursorThreadsForDeletion, pruneCursorThreads } = await import("./cursor-recovery-nq-kR62j.js");
198
+ const { listCursorThreadsForGroup } = await import("./cursor-db-CZnYy7aT.js");
199
+ const { collectCursorThreadsForDeletion, pruneCursorThreads } = await import("./cursor-recovery-CXpO8KcD.js");
200
200
  await ensureCursorClosedForWrite();
201
201
  const composerIds = (await listCursorThreadsForGroup(await findGroupByKey(data.workspaceKey), void 0, { includeTranscriptDirs: false })).map((thread) => thread.composerId);
202
202
  if (composerIds.length === 0) return {
@@ -1,14 +1,14 @@
1
1
  import { t as Button } from "./button-CmTDnzOn.js";
2
2
  import { i as deleteCursorThreadsFn, o as exportCursorThreadFn, t as cursorThreadDetailQueryOptions } from "./cursor-queries-NCIM0Nat.js";
3
- import { t as Route } from "./cursor-threads._composerId-BPJFWfJj.js";
3
+ import { t as Route } from "./cursor-threads._composerId-p9-ARAzc.js";
4
4
  import { t as Checkbox } from "./checkbox-C0hovF41.js";
5
5
  import { t as MetricCard } from "./metric-card-ByEeLu0r.js";
6
6
  import { t as PageHeader } from "./page-header-VNSaM3xd.js";
7
7
  import { i as formatList, n as formatBytes, o as formatNumber, r as formatDateTime } from "./formatters-FJaGZgJk.js";
8
- import { a as TranscriptView, c as Breadcrumbs, i as TabsTrigger, n as TabsContent, o as MetadataSection, r as TabsList, s as JsonPanel, t as Tabs } from "./tabs-CGA13IZM.js";
8
+ import { a as TranscriptView, c as Breadcrumbs, i as TabsTrigger, n as TabsContent, o as MetadataSection, r as TabsList, s as JsonPanel, t as Tabs } from "./tabs-DkaChNVg.js";
9
9
  import { n as downloadUrlFile, t as downloadTextFile } from "./download-DMmiy1xf.js";
10
+ import { t as ExportDialog } from "./export-dialog-D88ze9Gy.js";
10
11
  import { t as DeleteConfirmDialog } from "./delete-confirm-dialog-BcBNCxWB.js";
11
- import { t as ExportDialog } from "./export-dialog-BItjWgkZ.js";
12
12
  import { useMemo, useState } from "react";
13
13
  import { Link, useNavigate } from "@tanstack/react-router";
14
14
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -4,7 +4,7 @@ import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/routes/cursor-threads.$composerId.tsx
6
6
  var $$splitErrorComponentImporter = () => import("./cursor-threads._composerId-BB0Y_Mao.js");
7
- var $$splitComponentImporter = () => import("./cursor-threads._composerId-BkMMTQ3v.js");
7
+ var $$splitComponentImporter = () => import("./cursor-threads._composerId-Ckn6ItHI.js");
8
8
  var Route = createFileRoute("/cursor-threads/$composerId")({
9
9
  component: lazyRouteComponent($$splitComponentImporter, "component"),
10
10
  errorComponent: lazyRouteComponent($$splitErrorComponentImporter, "errorComponent"),