@claude-transcripts/cli 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +67 -8
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -39113,6 +39113,10 @@ async function errorDetail(res) {
|
|
|
39113
39113
|
return "";
|
|
39114
39114
|
}
|
|
39115
39115
|
}
|
|
39116
|
+
async function exists(path) {
|
|
39117
|
+
const res = await fetch(`${base2()}${path}`);
|
|
39118
|
+
return res.ok;
|
|
39119
|
+
}
|
|
39116
39120
|
async function getOrNull(path) {
|
|
39117
39121
|
const res = await fetch(`${base2()}${path}`);
|
|
39118
39122
|
if (!res.ok)
|
|
@@ -39327,6 +39331,9 @@ class DryRunSink {
|
|
|
39327
39331
|
async existingSession() {
|
|
39328
39332
|
return null;
|
|
39329
39333
|
}
|
|
39334
|
+
async hasTranscriptBlob() {
|
|
39335
|
+
return true;
|
|
39336
|
+
}
|
|
39330
39337
|
async hasTurns() {
|
|
39331
39338
|
return false;
|
|
39332
39339
|
}
|
|
@@ -39360,6 +39367,9 @@ class WebapiSink {
|
|
|
39360
39367
|
const res = await getOrNull(`/api/sessions/${encodeURIComponent(sessionId)}/turns?limit=1`);
|
|
39361
39368
|
return (res?.turns?.length ?? 0) > 0;
|
|
39362
39369
|
}
|
|
39370
|
+
async hasTranscriptBlob(sessionId) {
|
|
39371
|
+
return exists(`/api/s3/sessions/${encodeURIComponent(sessionId)}/transcript.jsonl`);
|
|
39372
|
+
}
|
|
39363
39373
|
async resetSession(sessionId) {
|
|
39364
39374
|
const res = await resetSession(sessionId);
|
|
39365
39375
|
return res.deleted;
|
|
@@ -39394,8 +39404,9 @@ function planReingest(existing, opts) {
|
|
|
39394
39404
|
if (opts.repair) {
|
|
39395
39405
|
if (existing.status === "running")
|
|
39396
39406
|
return { action: "skip", reason: "running" };
|
|
39397
|
-
if (opts.hasTurns)
|
|
39398
|
-
return { action: "skip", reason: "has-turns" };
|
|
39407
|
+
if (opts.hasTurns) {
|
|
39408
|
+
return opts.hasBlob === false ? { action: "repair-blob" } : { action: "skip", reason: "has-turns" };
|
|
39409
|
+
}
|
|
39399
39410
|
return { action: "repair" };
|
|
39400
39411
|
}
|
|
39401
39412
|
if (!opts.force)
|
|
@@ -39463,7 +39474,8 @@ async function runBackfill(argv) {
|
|
|
39463
39474
|
}
|
|
39464
39475
|
const existing = dryRun ? null : await sink.existingSession(t.sessionId);
|
|
39465
39476
|
const hasTurns = repair && existing ? await sink.hasTurns(t.sessionId) : false;
|
|
39466
|
-
const
|
|
39477
|
+
const hasBlob = hasTurns ? await sink.hasTranscriptBlob(t.sessionId) : undefined;
|
|
39478
|
+
const plan = planReingest(existing, { force, replaceLive, repair, hasTurns, hasBlob });
|
|
39467
39479
|
if (plan.action === "skip") {
|
|
39468
39480
|
if (plan.reason === "live-record") {
|
|
39469
39481
|
console.warn(` ! ${t.sessionId}: skipped \u2014 recorded live. --force would delete that record and ` + "rebuild it from the transcript, losing provenance only the hook had. Pass " + "--replace-live to do that deliberately.");
|
|
@@ -39473,11 +39485,18 @@ async function runBackfill(argv) {
|
|
|
39473
39485
|
console.log(` \xB7 ${t.sessionId}: skipped \u2014 still running`);
|
|
39474
39486
|
}
|
|
39475
39487
|
if (plan.reason === "has-turns") {
|
|
39476
|
-
console.log(` \xB7 ${t.sessionId}: skipped \u2014 already has turn content`);
|
|
39488
|
+
console.log(` \xB7 ${t.sessionId}: skipped \u2014 already has turn content and a transcript`);
|
|
39477
39489
|
}
|
|
39478
39490
|
skipped++;
|
|
39479
39491
|
continue;
|
|
39480
39492
|
}
|
|
39493
|
+
if (plan.action === "repair-blob") {
|
|
39494
|
+
const jsonl = await readTranscript(t.path);
|
|
39495
|
+
await sink.putTranscript(t.sessionId, new TextEncoder().encode(jsonl));
|
|
39496
|
+
console.log(` + ${t.sessionId}: re-uploaded the transcript (chunks left alone)`);
|
|
39497
|
+
repaired++;
|
|
39498
|
+
continue;
|
|
39499
|
+
}
|
|
39481
39500
|
if (plan.action === "repair") {
|
|
39482
39501
|
const jsonl = await readTranscript(t.path);
|
|
39483
39502
|
const facts = deriveSessionFacts(jsonl, { hostname: host, sessionIdHint: t.sessionId });
|
|
@@ -40293,6 +40312,9 @@ function makeMirrorCouch(target, onWrite) {
|
|
|
40293
40312
|
},
|
|
40294
40313
|
async putDoc(_db, id, doc, timeoutMs) {
|
|
40295
40314
|
await send({ ...doc, _id: id }, timeoutMs ?? fallback);
|
|
40315
|
+
},
|
|
40316
|
+
async upsertDoc(_db, id, doc, timeoutMs) {
|
|
40317
|
+
await send({ ...doc, _id: id }, timeoutMs ?? fallback);
|
|
40296
40318
|
}
|
|
40297
40319
|
};
|
|
40298
40320
|
}
|
|
@@ -40328,6 +40350,9 @@ function fanOutCouch(clients) {
|
|
|
40328
40350
|
},
|
|
40329
40351
|
async putDoc(db, id, doc, timeoutMs) {
|
|
40330
40352
|
await Promise.allSettled(clients.map((c) => c.putDoc(db, id, doc, timeoutMs)));
|
|
40353
|
+
},
|
|
40354
|
+
async upsertDoc(db, id, doc, timeoutMs) {
|
|
40355
|
+
await Promise.allSettled(clients.map((c) => c.upsertDoc(db, id, doc, timeoutMs)));
|
|
40331
40356
|
}
|
|
40332
40357
|
};
|
|
40333
40358
|
}
|
|
@@ -40403,6 +40428,39 @@ function makeDirectCouch(config, onWrite) {
|
|
|
40403
40428
|
} catch {
|
|
40404
40429
|
onWrite?.(false);
|
|
40405
40430
|
}
|
|
40431
|
+
},
|
|
40432
|
+
async upsertDoc(db, id, doc, timeoutMs = 5000) {
|
|
40433
|
+
const url = `${root}/${db}/${encodeURIComponent(id)}`;
|
|
40434
|
+
const put = (body) => fetch(url, {
|
|
40435
|
+
method: "PUT",
|
|
40436
|
+
headers,
|
|
40437
|
+
body: JSON.stringify(body),
|
|
40438
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40439
|
+
});
|
|
40440
|
+
try {
|
|
40441
|
+
const res = await put(doc);
|
|
40442
|
+
if (res.status !== 409) {
|
|
40443
|
+
onWrite?.(res.ok);
|
|
40444
|
+
return;
|
|
40445
|
+
}
|
|
40446
|
+
const current = await fetch(url, {
|
|
40447
|
+
headers,
|
|
40448
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40449
|
+
});
|
|
40450
|
+
if (!current.ok) {
|
|
40451
|
+
onWrite?.(false);
|
|
40452
|
+
return;
|
|
40453
|
+
}
|
|
40454
|
+
const { _rev } = await current.json();
|
|
40455
|
+
if (!_rev) {
|
|
40456
|
+
onWrite?.(false);
|
|
40457
|
+
return;
|
|
40458
|
+
}
|
|
40459
|
+
const retry = await put({ ...doc, _rev });
|
|
40460
|
+
onWrite?.(retry.ok);
|
|
40461
|
+
} catch {
|
|
40462
|
+
onWrite?.(false);
|
|
40463
|
+
}
|
|
40406
40464
|
}
|
|
40407
40465
|
};
|
|
40408
40466
|
}
|
|
@@ -40913,11 +40971,10 @@ var writeSummary = async (ctx) => {
|
|
|
40913
40971
|
system_checks: {},
|
|
40914
40972
|
source: "live"
|
|
40915
40973
|
};
|
|
40916
|
-
await ctx.couch.
|
|
40974
|
+
await ctx.couch.upsertDoc(ctx.sessionsDb, `summary:${ctx.sessionId}`, doc, 30000);
|
|
40917
40975
|
if (ctx.blob.enabled && ctx.sessionsBucket) {
|
|
40918
40976
|
await ctx.blob.put(ctx.sessionsBucket, `${ctx.sessionId}/summary.json`, JSON.stringify(doc), "application/json");
|
|
40919
40977
|
}
|
|
40920
|
-
ctx.counts.clear();
|
|
40921
40978
|
ctx.targets.clear();
|
|
40922
40979
|
};
|
|
40923
40980
|
var uploadBlobs = async (ctx) => {
|
|
@@ -42779,7 +42836,7 @@ function tools(counts) {
|
|
|
42779
42836
|
function summaryLine(s) {
|
|
42780
42837
|
return row([
|
|
42781
42838
|
[s.sessionId.slice(0, 8), 8],
|
|
42782
|
-
[when(s.timestamp), 16],
|
|
42839
|
+
[when(s.startTimestamp ?? s.timestamp), 16],
|
|
42783
42840
|
[s.status, 10],
|
|
42784
42841
|
[project2(s.cwd), 18],
|
|
42785
42842
|
[num3(s.promptCount), 7],
|
|
@@ -42829,7 +42886,9 @@ async function showDetail(id, limit, json) {
|
|
|
42829
42886
|
return 0;
|
|
42830
42887
|
}
|
|
42831
42888
|
console.log(`session ${s.sessionId} [${s.status}]`);
|
|
42832
|
-
console.log(` started ${s.timestamp ?? "\u2014"}`);
|
|
42889
|
+
console.log(` started ${s.startTimestamp ?? s.timestamp ?? "\u2014"}`);
|
|
42890
|
+
if (s.status === "ended")
|
|
42891
|
+
console.log(` ended ${s.timestamp ?? "\u2014"}`);
|
|
42833
42892
|
console.log(` project ${s.cwd || "\u2014"}`);
|
|
42834
42893
|
console.log(` model ${s.model ?? "\u2014"}`);
|
|
42835
42894
|
console.log(` hostname ${s.hostname || "\u2014"}`);
|
package/package.json
CHANGED