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.
- package/AGENTS.md +48 -5
- package/README.md +40 -5
- package/apps/ui/AGENTS.md +23 -4
- package/apps/ui/README.md +49 -2
- package/apps/ui/dist/client/assets/analytics-DOy1b6Sh.js +1 -0
- package/apps/ui/dist/client/assets/{antigravity-conversations._conversationId-DmD0sN8X.js → antigravity-conversations._conversationId-DqySVO2K.js} +2 -2
- package/apps/ui/dist/client/assets/antigravity-keychain-panel-B77qJz6f.js +1 -0
- package/apps/ui/dist/client/assets/antigravity._workspaceKey-B3NM6gRH.js +1 -0
- package/apps/ui/dist/client/assets/{antigravity.index-DEEkjlZa.js → antigravity.index-DP9JC2P9.js} +1 -1
- package/apps/ui/dist/client/assets/{badge-DfWvPfKF.js → badge-C3i4OKs8.js} +1 -1
- package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-8pQ55ci2.js +1 -0
- package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-DVz5UmtU.js +1 -0
- package/apps/ui/dist/client/assets/claude-code._workspaceKey-BBKskSum.js +1 -0
- package/apps/ui/dist/client/assets/claude-code._workspaceKey-OkikMUFs.js +1 -0
- package/apps/ui/dist/client/assets/claude-code.index-Cwu76dbb.js +1 -0
- package/apps/ui/dist/client/assets/claude-code.index-D6eMd08t.js +1 -0
- package/apps/ui/dist/client/assets/createServerFn-B-KkwmHU.js +3 -0
- package/apps/ui/dist/client/assets/cursor-threads._composerId-hBWlP1D-.js +1 -0
- package/apps/ui/dist/client/assets/cursor._workspaceKey-BFPkIRi-.js +1 -0
- package/apps/ui/dist/client/assets/cursor.index-8y4o20kb.js +2 -0
- package/apps/ui/dist/client/assets/delete-confirm-dialog-Bxs07u-j.js +7 -0
- package/apps/ui/dist/client/assets/dist-BrJhN2A0.js +5 -0
- package/apps/ui/dist/client/assets/{dist-BhZOxAPP.js → dist-Cmd3AIfD.js} +1 -1
- package/apps/ui/dist/client/assets/dropdown-menu-D5cvPaZt.js +1 -0
- package/apps/ui/dist/client/assets/{es2015-BkCWttyM.js → es2015-ad6040dw.js} +1 -1
- package/apps/ui/dist/client/assets/export-dialog-Dr8d2MqD.js +1 -0
- package/apps/ui/dist/client/assets/{formatters-BM9kB7ed.js → formatters-BtqyrX_c.js} +1 -1
- package/apps/ui/dist/client/assets/index-C-STgIH4.js +166 -0
- package/apps/ui/dist/client/assets/kiro-sessions._sessionId-CKgfJ7GR.js +1 -0
- package/apps/ui/dist/client/assets/kiro-sessions._sessionId-zvIJHtQF.js +1 -0
- package/apps/ui/dist/client/assets/kiro._workspaceKey-DhVuJuZB.js +1 -0
- package/apps/ui/dist/client/assets/kiro._workspaceKey-QArsjkTY.js +1 -0
- package/apps/ui/dist/client/assets/kiro.index-C-fr4m7i.js +1 -0
- package/apps/ui/dist/client/assets/kiro.index-OYgAdtZd.js +1 -0
- package/apps/ui/dist/client/assets/opencode-sessions._sessionId-DLjiTst-.js +1 -0
- package/apps/ui/dist/client/assets/opencode-sessions._sessionId-biBwrRbt.js +8 -0
- package/apps/ui/dist/client/assets/opencode._workspaceKey-C7OIzMOJ.js +1 -0
- package/apps/ui/dist/client/assets/opencode._workspaceKey-sBakX0oI.js +1 -0
- package/apps/ui/dist/client/assets/opencode.index-Bl_kNs9N.js +1 -0
- package/apps/ui/dist/client/assets/opencode.index-CN53bVmb.js +1 -0
- package/apps/ui/dist/client/assets/preload-helper-B8fFrdxC.js +1 -0
- package/apps/ui/dist/client/assets/projects._project-D8WloxQN.js +1 -0
- package/apps/ui/dist/client/assets/projects.index-5xRtuJdX.js +3 -0
- package/apps/ui/dist/client/assets/routes-DnzF_9CX.js +1 -0
- package/apps/ui/dist/client/assets/select-CYF6pF37.js +1 -0
- package/apps/ui/dist/client/assets/settings-Dx70jgP_.js +1 -0
- package/apps/ui/dist/client/assets/styles-B7Zi9EFA.css +1 -0
- package/apps/ui/dist/client/assets/tabs-CmuhkT-c.js +7 -0
- package/apps/ui/dist/client/assets/thread-transcript-stats-BUNz6u7F.js +1 -0
- package/apps/ui/dist/client/assets/threads._threadId-BMRSFow3.js +1 -0
- package/apps/ui/dist/client/assets/useMutation-BSFult2i.js +1 -0
- package/apps/ui/dist/client/assets/useQuery-CjINKZf1.js +1 -0
- package/apps/ui/dist/client/icon.svg +2 -1
- package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CQ8Jjs3B.js +387 -0
- package/apps/ui/dist/server/assets/{antigravity-conversations._conversationId-BtexWY-K.js → antigravity-conversations._conversationId-BKOyL2T6.js} +2 -2
- package/apps/ui/dist/server/assets/{antigravity-conversations._conversationId-zMrR6v6R.js → antigravity-conversations._conversationId-eS87Dx7g.js} +1 -1
- package/apps/ui/dist/server/assets/claude-code-db-Ik3VStKZ.js +361 -0
- package/apps/ui/dist/server/assets/claude-code-queries-Cgzi4K-e.js +37 -0
- package/apps/ui/dist/server/assets/claude-code-server-PfraClXS.js +72 -0
- package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-C55oe6zj.js +18 -0
- package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-D1RYYi3j.js +473 -0
- package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-DSvPLEUL.js +11 -0
- package/apps/ui/dist/server/assets/claude-code-transcript-C-bxh3cS.js +139 -0
- package/apps/ui/dist/server/assets/claude-code-transcript-phase-DmUMc8VU.js +10 -0
- package/apps/ui/dist/server/assets/claude-code._workspaceKey-B5Xg_-tE.js +28 -0
- package/apps/ui/dist/server/assets/claude-code._workspaceKey-BPlzyXPa.js +11 -0
- package/apps/ui/dist/server/assets/claude-code._workspaceKey-DqDve2wl.js +191 -0
- package/apps/ui/dist/server/assets/claude-code.index-B7yYR7dD.js +92 -0
- package/apps/ui/dist/server/assets/claude-code.index-BUHThG1W.js +11 -0
- package/apps/ui/dist/server/assets/{codex-server-CNXSJuc2.js → codex-server-CGXU4H8-.js} +319 -29
- package/apps/ui/dist/server/assets/{cursor-db-cYZEU3WQ.js → cursor-db-CZnYy7aT.js} +3 -3
- package/apps/ui/dist/server/assets/{cursor-recovery-nq-kR62j.js → cursor-recovery-CXpO8KcD.js} +2 -2
- package/apps/ui/dist/server/assets/{cursor-server-C3q7hrp-.js → cursor-server-DNu52A3K.js} +13 -13
- package/apps/ui/dist/server/assets/{cursor-threads._composerId-BkMMTQ3v.js → cursor-threads._composerId-Ckn6ItHI.js} +3 -3
- package/apps/ui/dist/server/assets/{cursor-threads._composerId-BPJFWfJj.js → cursor-threads._composerId-p9-ARAzc.js} +1 -1
- package/apps/ui/dist/server/assets/{cursor-transcript-2iL3KFSK.js → cursor-transcript-B7tGnqtn.js} +1 -1
- package/apps/ui/dist/server/assets/{cursor._workspaceKey-C5PdTaKB.js → cursor._workspaceKey-CZuohIUL.js} +1 -1
- package/apps/ui/dist/server/assets/{cursor._workspaceKey-Ckj7apKI.js → cursor._workspaceKey-DPp5JSjy.js} +2 -2
- package/apps/ui/dist/server/assets/{export-dialog-BItjWgkZ.js → export-dialog-D88ze9Gy.js} +2 -2
- package/apps/ui/dist/server/assets/kiro-db--fXrED_-.js +552 -0
- package/apps/ui/dist/server/assets/kiro-queries-CzNlM2ok.js +37 -0
- package/apps/ui/dist/server/assets/kiro-server-9WRxg2Au.js +72 -0
- package/apps/ui/dist/server/assets/kiro-sessions._sessionId-CRY2c7YO.js +11 -0
- package/apps/ui/dist/server/assets/kiro-sessions._sessionId-F1UlwxmR.js +449 -0
- package/apps/ui/dist/server/assets/kiro-sessions._sessionId-bvTulT7C.js +18 -0
- package/apps/ui/dist/server/assets/kiro-transcript-DoekQBaH.js +112 -0
- package/apps/ui/dist/server/assets/kiro-transcript-phase-CJG40nQg.js +27 -0
- package/apps/ui/dist/server/assets/kiro._workspaceKey-BDe9sQwo.js +11 -0
- package/apps/ui/dist/server/assets/kiro._workspaceKey-CJsjgNwO.js +28 -0
- package/apps/ui/dist/server/assets/kiro._workspaceKey-D_-4Qb7y.js +193 -0
- package/apps/ui/dist/server/assets/kiro.index-C__-UROk.js +11 -0
- package/apps/ui/dist/server/assets/kiro.index-CmTbqeYj.js +93 -0
- package/apps/ui/dist/server/assets/opencode-db-BM7KjOzc.js +397 -0
- package/apps/ui/dist/server/assets/opencode-queries-BeNYXnQv.js +50 -0
- package/apps/ui/dist/server/assets/opencode-server-BpQ_kRze.js +72 -0
- package/apps/ui/dist/server/assets/opencode-sessions._sessionId-CGQ-t0vD.js +518 -0
- package/apps/ui/dist/server/assets/opencode-sessions._sessionId-D8Q7in_Z.js +18 -0
- package/apps/ui/dist/server/assets/opencode-sessions._sessionId-DKOvi0lV.js +11 -0
- package/apps/ui/dist/server/assets/opencode-think-tags-CAoD-EcZ.js +87 -0
- package/apps/ui/dist/server/assets/opencode-transcript-BNTcGNym.js +141 -0
- package/apps/ui/dist/server/assets/opencode-transcript-phase-OqLkiQD0.js +32 -0
- package/apps/ui/dist/server/assets/opencode._workspaceKey-BdqcWHw1.js +11 -0
- package/apps/ui/dist/server/assets/opencode._workspaceKey-CfH96HTT.js +28 -0
- package/apps/ui/dist/server/assets/opencode._workspaceKey-DdbHPDrO.js +207 -0
- package/apps/ui/dist/server/assets/opencode.index-BbVzkJXP.js +11 -0
- package/apps/ui/dist/server/assets/opencode.index-Vh_Gq_1L.js +93 -0
- package/apps/ui/dist/server/assets/{projects._project-Bpbc3C-L.js → projects._project-4io5LO0E.js} +1 -1
- package/apps/ui/dist/server/assets/{projects._project-CvZho6EQ.js → projects._project-D6ZoGhJ8.js} +2 -2
- package/apps/ui/dist/server/assets/{router-6m-ihwqA.js → router-Sac2DGk6.js} +157 -49
- package/apps/ui/dist/server/assets/{shared-CPRNYIql.js → shared-DyhChtHf.js} +4 -1
- package/apps/ui/dist/server/assets/source-session-export-server-DNutCawb.js +38 -0
- package/apps/ui/dist/server/assets/{start-CI_0bSiY.js → start-B_HFwkkk.js} +1 -1
- package/apps/ui/dist/server/assets/{tabs-CGA13IZM.js → tabs-DkaChNVg.js} +0 -1
- package/apps/ui/dist/server/assets/thread-transcript-stats-Dh34mt2u.js +45 -0
- package/apps/ui/dist/server/assets/{threads._threadId-D2GYkVn6.js → threads._threadId-BeXEc4Lo.js} +15 -6
- package/apps/ui/dist/server/assets/{threads._threadId-Bs0yuqO9.js → threads._threadId-Ci0S4mKU.js} +1 -1
- package/apps/ui/dist/server/server.js +72 -24
- package/package.json +21 -4
- package/src/lib/claude-code-db.ts +655 -0
- package/src/lib/claude-code-exporter-types.ts +110 -0
- package/src/lib/claude-code-transcript-phase.ts +25 -0
- package/src/lib/claude-code-transcript.ts +180 -0
- package/src/lib/codex-browser-db.ts +490 -31
- package/src/lib/codex-browser-export.ts +18 -2
- package/src/lib/codex-thread-cache.ts +17 -1
- package/src/lib/concurrency.ts +25 -0
- package/src/lib/kiro-db.ts +949 -0
- package/src/lib/kiro-exporter-types.ts +100 -0
- package/src/lib/kiro-transcript-phase.ts +41 -0
- package/src/lib/kiro-transcript.ts +115 -0
- package/src/lib/opencode-db.ts +610 -0
- package/src/lib/opencode-exporter-types.ts +129 -0
- package/src/lib/opencode-think-tags.ts +126 -0
- package/src/lib/opencode-transcript-phase.ts +50 -0
- package/src/lib/opencode-transcript.ts +194 -0
- package/src/lib/shared.ts +25 -0
- package/src/lib/ui-export-archive.ts +61 -0
- package/apps/ui/dist/client/assets/analytics-DK2jdvmI.js +0 -1
- package/apps/ui/dist/client/assets/antigravity-keychain-panel-BRHVjFAM.js +0 -1
- package/apps/ui/dist/client/assets/antigravity._workspaceKey-CGV7amas.js +0 -1
- package/apps/ui/dist/client/assets/createServerFn-CgRRVpBH.js +0 -3
- package/apps/ui/dist/client/assets/cursor-threads._composerId-Ti2gTm63.js +0 -1
- package/apps/ui/dist/client/assets/cursor._workspaceKey-DzD_c6j9.js +0 -1
- package/apps/ui/dist/client/assets/cursor.index-PkCFVcl4.js +0 -2
- package/apps/ui/dist/client/assets/delete-confirm-dialog-BHRmyLHr.js +0 -11
- package/apps/ui/dist/client/assets/dropdown-menu-Dy5cLzTy.js +0 -1
- package/apps/ui/dist/client/assets/export-dialog-C86SYHJn.js +0 -1
- package/apps/ui/dist/client/assets/index-CPvAP-jk.js +0 -149
- package/apps/ui/dist/client/assets/projects._project-Ckf6muWZ.js +0 -1
- package/apps/ui/dist/client/assets/projects.index-V5ibNZII.js +0 -3
- package/apps/ui/dist/client/assets/routes-Df2tgpyd.js +0 -1
- package/apps/ui/dist/client/assets/select-Bf2GwfPR.js +0 -1
- package/apps/ui/dist/client/assets/settings-5VQIzME0.js +0 -1
- package/apps/ui/dist/client/assets/styles-BhRkXgwB.css +0 -1
- package/apps/ui/dist/client/assets/tabs-OO4VU5KR.js +0 -7
- package/apps/ui/dist/client/assets/threads._threadId-BgDhFj2I.js +0 -1
- package/apps/ui/dist/client/assets/useMutation-CC_B7uy5.js +0 -1
- package/apps/ui/dist/client/assets/useQuery-C5By6WKU.js +0 -1
- 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
|
|
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 {
|
|
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 {
|
|
15
|
-
import {
|
|
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
|
-
|
|
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
|
|
529
|
+
var openReadonlyDb = (dbPath) => {
|
|
509
530
|
const db = new Database(dbPath, { readonly: true });
|
|
510
531
|
try {
|
|
511
|
-
db.
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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 {
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
4
|
import { readdir, stat } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import {
|
|
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) => {
|
package/apps/ui/dist/server/assets/{cursor-recovery-nq-kR62j.js → cursor-recovery-CXpO8KcD.js}
RENAMED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
199
|
-
const { collectCursorThreadsForDeletion, pruneCursorThreads } = await import("./cursor-recovery-
|
|
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-
|
|
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-
|
|
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-
|
|
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"),
|