codesesh 0.13.0 → 0.15.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/README.md +2 -0
- package/dist/{chunk-BV65IEWZ.js → chunk-NBCLV4CX.js} +1255 -1220
- package/dist/chunk-NBCLV4CX.js.map +1 -0
- package/dist/{dist-VD54GDPO.js → dist-5356XOFP.js} +17 -10
- package/dist/index.js +959 -867
- package/dist/index.js.map +1 -1
- package/dist/scan-refresh-worker.js +1 -1
- package/dist/search-index-worker.js +1 -1
- package/dist/smart-tag-worker.js +1 -1
- package/dist/web/assets/index-B6p64k_Q.js +113 -0
- package/dist/web/assets/index-DiFr4_5-.css +2 -0
- package/dist/web/assets/react-3acXkZNw.js +1821 -0
- package/dist/web/assets/vendor-CShgXaOi.js +40 -0
- package/dist/web/index.html +4 -4
- package/package.json +1 -1
- package/dist/chunk-BV65IEWZ.js.map +0 -1
- package/dist/web/assets/index-ZikfLnUo.js +0 -113
- package/dist/web/assets/index-y6Zx3LT1.css +0 -2
- package/dist/web/assets/react-DBHwgW7V.js +0 -1821
- package/dist/web/assets/vendor-bXsb4Kz4.js +0 -40
- /package/dist/{dist-VD54GDPO.js.map → dist-5356XOFP.js.map} +0 -0
|
@@ -72,15 +72,18 @@ function getRegisteredAgents() {
|
|
|
72
72
|
return registrations;
|
|
73
73
|
}
|
|
74
74
|
function getAgentInfoMap(sessionsByAgent) {
|
|
75
|
-
return registrations.map((
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
return registrations.map((registration) => {
|
|
76
|
+
const agent = registration.create();
|
|
77
|
+
return {
|
|
78
|
+
name: agent.name,
|
|
79
|
+
displayName: agent.displayName,
|
|
80
|
+
icon: registration.icon,
|
|
81
|
+
count: sessionsByAgent[agent.name] ?? 0
|
|
82
|
+
};
|
|
83
|
+
});
|
|
81
84
|
}
|
|
82
85
|
function getAgentByName(name) {
|
|
83
|
-
return registrations.find((
|
|
86
|
+
return registrations.find((registration) => registration.create().name === name);
|
|
84
87
|
}
|
|
85
88
|
function parsedSession(session) {
|
|
86
89
|
return { status: "parsed", data: session };
|
|
@@ -106,6 +109,26 @@ var BaseAgent = class {
|
|
|
106
109
|
};
|
|
107
110
|
var FileSystemSessionSource = class extends BaseAgent {
|
|
108
111
|
sessionMetaMap = /* @__PURE__ */ new Map();
|
|
112
|
+
scan(options) {
|
|
113
|
+
const sources = this.listSessionSources(options);
|
|
114
|
+
const sessions = [];
|
|
115
|
+
options?.onProgress?.({ total: sources.length, processed: 0, sessions: 0 });
|
|
116
|
+
for (const [index, source] of sources.entries()) {
|
|
117
|
+
try {
|
|
118
|
+
const session = this.scanSessionSource(source.sourcePath, options);
|
|
119
|
+
if (session) sessions.push(session);
|
|
120
|
+
} catch {
|
|
121
|
+
continue;
|
|
122
|
+
} finally {
|
|
123
|
+
options?.onProgress?.({
|
|
124
|
+
total: sources.length,
|
|
125
|
+
processed: index + 1,
|
|
126
|
+
sessions: sessions.length
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return sessions;
|
|
131
|
+
}
|
|
109
132
|
getSessionMetaMap() {
|
|
110
133
|
return this.sessionMetaMap;
|
|
111
134
|
}
|
|
@@ -380,15 +403,6 @@ function resolveSessionTitle(explicit, message, directory) {
|
|
|
380
403
|
}
|
|
381
404
|
return UNTITLED_SESSION;
|
|
382
405
|
}
|
|
383
|
-
function parsed(data) {
|
|
384
|
-
return { status: "parsed", data };
|
|
385
|
-
}
|
|
386
|
-
function skipped(reason) {
|
|
387
|
-
return reason ? { status: "skipped", reason } : { status: "skipped" };
|
|
388
|
-
}
|
|
389
|
-
function filtered(reason) {
|
|
390
|
-
return reason ? { status: "filtered", reason } : { status: "filtered" };
|
|
391
|
-
}
|
|
392
406
|
function isInternalEventType2(value) {
|
|
393
407
|
return isInternalEventType(value);
|
|
394
408
|
}
|
|
@@ -457,80 +471,6 @@ function firstUserMessageTitle(messages) {
|
|
|
457
471
|
}
|
|
458
472
|
return null;
|
|
459
473
|
}
|
|
460
|
-
var PerfTracer = class {
|
|
461
|
-
rootMarkers = [];
|
|
462
|
-
activeStack = [];
|
|
463
|
-
enabled = false;
|
|
464
|
-
enable() {
|
|
465
|
-
this.enabled = true;
|
|
466
|
-
}
|
|
467
|
-
start(name) {
|
|
468
|
-
const marker = {
|
|
469
|
-
name,
|
|
470
|
-
startTime: performance.now(),
|
|
471
|
-
children: []
|
|
472
|
-
};
|
|
473
|
-
if (!this.enabled) return marker;
|
|
474
|
-
const parent = this.activeStack[this.activeStack.length - 1];
|
|
475
|
-
if (parent) {
|
|
476
|
-
marker.parent = parent;
|
|
477
|
-
parent.children.push(marker);
|
|
478
|
-
} else {
|
|
479
|
-
this.rootMarkers.push(marker);
|
|
480
|
-
}
|
|
481
|
-
this.activeStack.push(marker);
|
|
482
|
-
return marker;
|
|
483
|
-
}
|
|
484
|
-
end(marker) {
|
|
485
|
-
if (!this.enabled) return;
|
|
486
|
-
const target = marker ?? this.activeStack[this.activeStack.length - 1];
|
|
487
|
-
if (!target) return;
|
|
488
|
-
target.endTime = performance.now();
|
|
489
|
-
target.duration = target.endTime - target.startTime;
|
|
490
|
-
while (this.activeStack.length > 0) {
|
|
491
|
-
const popped = this.activeStack.pop();
|
|
492
|
-
if (popped === target) break;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
measure(name, fn) {
|
|
496
|
-
const marker = this.start(name);
|
|
497
|
-
try {
|
|
498
|
-
return fn();
|
|
499
|
-
} finally {
|
|
500
|
-
this.end(marker);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
async measureAsync(name, fn) {
|
|
504
|
-
const marker = this.start(name);
|
|
505
|
-
try {
|
|
506
|
-
return await fn();
|
|
507
|
-
} finally {
|
|
508
|
-
this.end(marker);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
getReport() {
|
|
512
|
-
if (!this.enabled) return "Performance tracing disabled";
|
|
513
|
-
const lines = [];
|
|
514
|
-
lines.push("\n=== Performance Report ===\n");
|
|
515
|
-
for (const marker of this.rootMarkers) {
|
|
516
|
-
this.formatMarker(marker, 0, lines);
|
|
517
|
-
}
|
|
518
|
-
return lines.join("\n");
|
|
519
|
-
}
|
|
520
|
-
formatMarker(marker, depth, lines) {
|
|
521
|
-
const indent = " ".repeat(depth);
|
|
522
|
-
const duration = marker.duration?.toFixed(2) ?? "?";
|
|
523
|
-
lines.push(`${indent}${marker.name}: ${duration}ms`);
|
|
524
|
-
for (const child of marker.children) {
|
|
525
|
-
this.formatMarker(child, depth + 1, lines);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
reset() {
|
|
529
|
-
this.rootMarkers = [];
|
|
530
|
-
this.activeStack = [];
|
|
531
|
-
}
|
|
532
|
-
};
|
|
533
|
-
var perf = new PerfTracer();
|
|
534
474
|
var aliases_default = {
|
|
535
475
|
"anthropic--claude-4.6-opus": "claude-opus-4-6",
|
|
536
476
|
"anthropic--claude-4.6-sonnet": "claude-sonnet-4-6",
|
|
@@ -854,6 +794,179 @@ function withEstimatedSessionCost(stats, model) {
|
|
|
854
794
|
function estimateTokenCost(model, tokens) {
|
|
855
795
|
return estimateCostForTokens(model, tokens)?.cost ?? null;
|
|
856
796
|
}
|
|
797
|
+
var TranscriptBuilder = class {
|
|
798
|
+
constructor(options = {}) {
|
|
799
|
+
this.options = options;
|
|
800
|
+
}
|
|
801
|
+
options;
|
|
802
|
+
messages = [];
|
|
803
|
+
pendingToolCalls = /* @__PURE__ */ new Map();
|
|
804
|
+
currentAssistant = null;
|
|
805
|
+
latestTextAssistant = null;
|
|
806
|
+
beginTurn() {
|
|
807
|
+
this.currentAssistant = null;
|
|
808
|
+
this.latestTextAssistant = null;
|
|
809
|
+
}
|
|
810
|
+
appendMessage(input) {
|
|
811
|
+
const message = this.createMessage(input);
|
|
812
|
+
this.messages.push(message);
|
|
813
|
+
this.registerToolCalls(message.parts);
|
|
814
|
+
if (message.role === "assistant") {
|
|
815
|
+
this.currentAssistant = message;
|
|
816
|
+
if (message.parts.some((part) => part.type === "text")) {
|
|
817
|
+
this.latestTextAssistant = message;
|
|
818
|
+
}
|
|
819
|
+
} else if (message.role === "user") {
|
|
820
|
+
this.beginTurn();
|
|
821
|
+
}
|
|
822
|
+
return message;
|
|
823
|
+
}
|
|
824
|
+
appendAssistantPart(part, input, options = {}) {
|
|
825
|
+
const current = this.currentAssistant;
|
|
826
|
+
const canReuse = current !== null && (options.grouping === "current" || (part.type === "text" ? !current.parts.some((item) => item.type === "tool") : part.type === "reasoning" ? !current.parts.some((item) => item.type === "text" || item.type === "tool") : false));
|
|
827
|
+
const message = canReuse ? current : this.appendMessage({ ...input, role: "assistant", parts: [part] });
|
|
828
|
+
if (canReuse) {
|
|
829
|
+
if (options.deduplicateTail) this.appendPartIfNew(message, part);
|
|
830
|
+
else message.parts.push(part);
|
|
831
|
+
this.applyMissingMetadata(message, input);
|
|
832
|
+
}
|
|
833
|
+
if (part.type === "text") {
|
|
834
|
+
this.latestTextAssistant = message;
|
|
835
|
+
} else if (options.resetLatestText) {
|
|
836
|
+
this.latestTextAssistant = null;
|
|
837
|
+
}
|
|
838
|
+
return message;
|
|
839
|
+
}
|
|
840
|
+
appendToolCall(part, input, options = {}) {
|
|
841
|
+
const target = options.target === "current" ? this.currentAssistant : this.latestTextAssistant ?? this.currentAssistant;
|
|
842
|
+
const message = target ? target : this.appendMessage({
|
|
843
|
+
...input,
|
|
844
|
+
role: "assistant",
|
|
845
|
+
mode: options.modeOnCreate ?? (options.markModeAsTool ? "tool" : input.mode),
|
|
846
|
+
parts: [part]
|
|
847
|
+
});
|
|
848
|
+
if (target) {
|
|
849
|
+
message.parts.push(part);
|
|
850
|
+
this.applyMissingMetadata(message, input);
|
|
851
|
+
if (options.markModeAsTool) message.mode = "tool";
|
|
852
|
+
this.registerToolCall(part);
|
|
853
|
+
}
|
|
854
|
+
this.currentAssistant = message;
|
|
855
|
+
return message;
|
|
856
|
+
}
|
|
857
|
+
appendToCurrentAssistant(part) {
|
|
858
|
+
if (!this.currentAssistant) return false;
|
|
859
|
+
this.currentAssistant.parts.push(part);
|
|
860
|
+
return true;
|
|
861
|
+
}
|
|
862
|
+
updateToolCall(callId, update) {
|
|
863
|
+
const part = this.pendingToolCalls.get(callId);
|
|
864
|
+
if (!part) return false;
|
|
865
|
+
update(part);
|
|
866
|
+
return true;
|
|
867
|
+
}
|
|
868
|
+
resolveToolCall(callId, resolution) {
|
|
869
|
+
return this.updateToolCall(callId, (part) => {
|
|
870
|
+
const state = part.state ?? (part.state = {});
|
|
871
|
+
if (resolution.output !== void 0) state.output = resolution.output;
|
|
872
|
+
if (resolution.status !== void 0) state.status = resolution.status;
|
|
873
|
+
if (resolution.metadata !== void 0) state.metadata = resolution.metadata;
|
|
874
|
+
if (resolution.consume) this.pendingToolCalls.delete(callId);
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
attachUsageToLatestAssistant(tokens, options = {}) {
|
|
878
|
+
for (let index = this.messages.length - 1; index >= 0; index -= 1) {
|
|
879
|
+
const message = this.messages[index];
|
|
880
|
+
if (message.role !== "assistant" || message.tokens) continue;
|
|
881
|
+
message.tokens = tokens;
|
|
882
|
+
if (options.model !== void 0) message.model ??= options.model;
|
|
883
|
+
if (options.cost !== void 0) message.cost = options.cost;
|
|
884
|
+
if (options.costSource !== void 0) message.cost_source = options.costSource;
|
|
885
|
+
return true;
|
|
886
|
+
}
|
|
887
|
+
return false;
|
|
888
|
+
}
|
|
889
|
+
finish(baseStats) {
|
|
890
|
+
const messages = cleanParsedMessages(this.messages);
|
|
891
|
+
const derived = this.deriveStats(messages);
|
|
892
|
+
if (!baseStats) return { messages, stats: derived };
|
|
893
|
+
return {
|
|
894
|
+
messages,
|
|
895
|
+
stats: {
|
|
896
|
+
...derived,
|
|
897
|
+
...baseStats,
|
|
898
|
+
message_count: messages.length,
|
|
899
|
+
cost_source: baseStats.cost_source
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
createMessage(input) {
|
|
904
|
+
const sparse = this.options.messageDefaults === "sparse";
|
|
905
|
+
return {
|
|
906
|
+
id: input.id,
|
|
907
|
+
role: input.role,
|
|
908
|
+
agent: sparse ? input.agent : input.agent ?? null,
|
|
909
|
+
time_created: input.timestampMs,
|
|
910
|
+
mode: sparse ? input.mode : input.mode ?? null,
|
|
911
|
+
model: sparse ? input.model : input.model ?? null,
|
|
912
|
+
provider: sparse ? input.provider : input.provider ?? null,
|
|
913
|
+
tokens: input.tokens,
|
|
914
|
+
cost: sparse ? input.cost : input.cost ?? 0,
|
|
915
|
+
cost_source: input.costSource,
|
|
916
|
+
parts: input.parts ?? [],
|
|
917
|
+
subagent_id: input.subagentId,
|
|
918
|
+
nickname: input.nickname
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
registerToolCalls(parts) {
|
|
922
|
+
for (const part of parts) this.registerToolCall(part);
|
|
923
|
+
}
|
|
924
|
+
registerToolCall(part) {
|
|
925
|
+
if (part.type === "tool" && part.callID) {
|
|
926
|
+
this.pendingToolCalls.set(part.callID, part);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
appendPartIfNew(message, part) {
|
|
930
|
+
const tail = message.parts.at(-1);
|
|
931
|
+
if (tail?.type === part.type && tail.text === part.text) return;
|
|
932
|
+
message.parts.push(part);
|
|
933
|
+
}
|
|
934
|
+
applyMissingMetadata(message, input) {
|
|
935
|
+
if (!message.id && input.id) message.id = input.id;
|
|
936
|
+
if (message.agent == null && input.agent !== void 0) message.agent = input.agent;
|
|
937
|
+
if (message.mode == null && input.mode !== void 0) message.mode = input.mode;
|
|
938
|
+
if (message.model == null && input.model !== void 0) message.model = input.model;
|
|
939
|
+
if (message.provider == null && input.provider !== void 0) message.provider = input.provider;
|
|
940
|
+
if (!message.tokens && input.tokens) message.tokens = input.tokens;
|
|
941
|
+
if ((message.cost ?? 0) === 0 && input.cost !== void 0) message.cost = input.cost;
|
|
942
|
+
if (!message.cost_source && input.costSource) message.cost_source = input.costSource;
|
|
943
|
+
}
|
|
944
|
+
deriveStats(messages) {
|
|
945
|
+
let totalInputTokens = 0;
|
|
946
|
+
let totalOutputTokens = 0;
|
|
947
|
+
let totalCacheReadTokens = 0;
|
|
948
|
+
let totalCacheCreateTokens = 0;
|
|
949
|
+
let totalCost = 0;
|
|
950
|
+
let hasEstimatedCost = false;
|
|
951
|
+
for (const message of messages) {
|
|
952
|
+
totalInputTokens += message.tokens?.input ?? 0;
|
|
953
|
+
totalOutputTokens += message.tokens?.output ?? 0;
|
|
954
|
+
totalCacheReadTokens += message.tokens?.cache_read ?? 0;
|
|
955
|
+
totalCacheCreateTokens += message.tokens?.cache_create ?? 0;
|
|
956
|
+
totalCost += message.cost ?? 0;
|
|
957
|
+
if (message.cost_source === "estimated") hasEstimatedCost = true;
|
|
958
|
+
}
|
|
959
|
+
return {
|
|
960
|
+
message_count: messages.length,
|
|
961
|
+
total_input_tokens: totalInputTokens,
|
|
962
|
+
total_output_tokens: totalOutputTokens,
|
|
963
|
+
total_cache_read_tokens: totalCacheReadTokens || void 0,
|
|
964
|
+
total_cache_create_tokens: totalCacheCreateTokens || void 0,
|
|
965
|
+
total_cost: totalCost,
|
|
966
|
+
cost_source: totalCost > 0 ? hasEstimatedCost ? "estimated" : "recorded" : void 0
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
};
|
|
857
970
|
var HEAD_INDEX_VERSION = "claudecode-head-v2";
|
|
858
971
|
function parseTimestampMs(data) {
|
|
859
972
|
const raw = String(data["timestamp"] ?? "").trim();
|
|
@@ -908,48 +1021,6 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
908
1021
|
}
|
|
909
1022
|
return false;
|
|
910
1023
|
}
|
|
911
|
-
scan(options) {
|
|
912
|
-
if (!this.basePath) return [];
|
|
913
|
-
const scanMarker = perf.start("claudecode:scan");
|
|
914
|
-
const heads = [];
|
|
915
|
-
const listMarker = perf.start("listProjectDirs");
|
|
916
|
-
const projectDirs = this.listProjectDirs();
|
|
917
|
-
perf.end(listMarker);
|
|
918
|
-
const filesByProject = projectDirs.map((projectDir) => {
|
|
919
|
-
const fileMarker = perf.start(`listJsonlFiles:${basename2(projectDir)}`);
|
|
920
|
-
const files = this.listJsonlFiles(projectDir).filter((file) => {
|
|
921
|
-
try {
|
|
922
|
-
return matchesScanWindow(statSync2(file).mtimeMs, options);
|
|
923
|
-
} catch {
|
|
924
|
-
return false;
|
|
925
|
-
}
|
|
926
|
-
});
|
|
927
|
-
perf.end(fileMarker);
|
|
928
|
-
return { projectDir, files };
|
|
929
|
-
});
|
|
930
|
-
const totalFiles = filesByProject.reduce((total, item) => total + item.files.length, 0);
|
|
931
|
-
options?.onProgress?.({ total: totalFiles, processed: 0, sessions: 0 });
|
|
932
|
-
let processed = 0;
|
|
933
|
-
for (const { projectDir, files } of filesByProject) {
|
|
934
|
-
for (const file of files) {
|
|
935
|
-
try {
|
|
936
|
-
const parseMarker = perf.start(`parseSessionHead:${basename2(file)}`);
|
|
937
|
-
const head = getParsedSession(this.parseSessionHeadResult(file, projectDir));
|
|
938
|
-
perf.end(parseMarker);
|
|
939
|
-
if (head) {
|
|
940
|
-
heads.push(head);
|
|
941
|
-
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, file, projectDir));
|
|
942
|
-
}
|
|
943
|
-
} catch {
|
|
944
|
-
} finally {
|
|
945
|
-
processed += 1;
|
|
946
|
-
options?.onProgress?.({ total: totalFiles, processed, sessions: heads.length });
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
perf.end(scanMarker);
|
|
951
|
-
return heads;
|
|
952
|
-
}
|
|
953
1024
|
listSessionSources(options) {
|
|
954
1025
|
if (!this.basePath) return [];
|
|
955
1026
|
const refs = [];
|
|
@@ -987,42 +1058,16 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
987
1058
|
throw new Error(`Session file missing: ${meta.sourcePath}`);
|
|
988
1059
|
}
|
|
989
1060
|
const content = readFileSync2(meta.sourcePath, "utf-8");
|
|
990
|
-
const
|
|
991
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
992
|
-
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
1061
|
+
const builder = new TranscriptBuilder();
|
|
993
1062
|
const assistantUuidToToolCalls = /* @__PURE__ */ new Map();
|
|
994
1063
|
const countedUsageKeys = /* @__PURE__ */ new Set();
|
|
995
|
-
const assistantState = {
|
|
996
|
-
currentIndex: null,
|
|
997
|
-
latestTextIndex: null
|
|
998
|
-
};
|
|
999
|
-
let totalCost = 0;
|
|
1000
|
-
let totalInputTokens = 0;
|
|
1001
|
-
let totalOutputTokens = 0;
|
|
1002
|
-
let totalCacheRead = 0;
|
|
1003
|
-
let totalCacheCreate = 0;
|
|
1004
1064
|
for (const record of parseJsonlLines(content)) {
|
|
1005
1065
|
try {
|
|
1006
|
-
this.convertRecord(
|
|
1007
|
-
record,
|
|
1008
|
-
messages,
|
|
1009
|
-
pendingToolCalls,
|
|
1010
|
-
ignoredToolCallIds,
|
|
1011
|
-
assistantUuidToToolCalls,
|
|
1012
|
-
countedUsageKeys,
|
|
1013
|
-
assistantState
|
|
1014
|
-
);
|
|
1066
|
+
this.convertRecord(record, builder, assistantUuidToToolCalls, countedUsageKeys);
|
|
1015
1067
|
} catch {
|
|
1016
1068
|
}
|
|
1017
1069
|
}
|
|
1018
|
-
const
|
|
1019
|
-
for (const msg of cleanedMessages) {
|
|
1020
|
-
totalCost += msg.cost ?? 0;
|
|
1021
|
-
totalInputTokens += msg.tokens?.input ?? 0;
|
|
1022
|
-
totalOutputTokens += msg.tokens?.output ?? 0;
|
|
1023
|
-
totalCacheRead += msg.tokens?.cache_read ?? 0;
|
|
1024
|
-
totalCacheCreate += msg.tokens?.cache_create ?? 0;
|
|
1025
|
-
}
|
|
1070
|
+
const transcript = builder.finish();
|
|
1026
1071
|
return {
|
|
1027
1072
|
id: meta.id,
|
|
1028
1073
|
title: meta.title,
|
|
@@ -1031,16 +1076,8 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1031
1076
|
version: void 0,
|
|
1032
1077
|
time_created: meta.createdAt,
|
|
1033
1078
|
time_updated: meta.updatedAt,
|
|
1034
|
-
stats:
|
|
1035
|
-
|
|
1036
|
-
total_input_tokens: totalInputTokens,
|
|
1037
|
-
total_output_tokens: totalOutputTokens,
|
|
1038
|
-
total_cost: totalCost,
|
|
1039
|
-
cost_source: totalCost > 0 ? "estimated" : void 0,
|
|
1040
|
-
total_cache_read_tokens: totalCacheRead,
|
|
1041
|
-
total_cache_create_tokens: totalCacheCreate
|
|
1042
|
-
},
|
|
1043
|
-
messages: cleanedMessages
|
|
1079
|
+
stats: transcript.stats,
|
|
1080
|
+
messages: transcript.messages
|
|
1044
1081
|
};
|
|
1045
1082
|
}
|
|
1046
1083
|
// --- Private helpers ---
|
|
@@ -1251,41 +1288,24 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1251
1288
|
return null;
|
|
1252
1289
|
}
|
|
1253
1290
|
// --- Record conversion ---
|
|
1254
|
-
convertRecord(data,
|
|
1291
|
+
convertRecord(data, builder, assistantUuidToToolCalls, countedUsageKeys) {
|
|
1255
1292
|
if (data["isMeta"] === true) return;
|
|
1256
1293
|
const msgType = String(data["type"] ?? "");
|
|
1257
1294
|
if (isInternalEventType(msgType)) return;
|
|
1258
1295
|
if (msgType === "assistant") {
|
|
1259
|
-
this.convertAssistantRecord(
|
|
1260
|
-
data,
|
|
1261
|
-
messages,
|
|
1262
|
-
pendingToolCalls,
|
|
1263
|
-
ignoredToolCallIds,
|
|
1264
|
-
assistantUuidToToolCalls,
|
|
1265
|
-
countedUsageKeys,
|
|
1266
|
-
assistantState
|
|
1267
|
-
);
|
|
1296
|
+
this.convertAssistantRecord(data, builder, assistantUuidToToolCalls, countedUsageKeys);
|
|
1268
1297
|
} else if (msgType === "user") {
|
|
1269
|
-
this.convertUserRecord(
|
|
1270
|
-
data,
|
|
1271
|
-
messages,
|
|
1272
|
-
pendingToolCalls,
|
|
1273
|
-
ignoredToolCallIds,
|
|
1274
|
-
assistantUuidToToolCalls,
|
|
1275
|
-
assistantState
|
|
1276
|
-
);
|
|
1298
|
+
this.convertUserRecord(data, builder, assistantUuidToToolCalls);
|
|
1277
1299
|
} else if (msgType === "tool_result") {
|
|
1278
|
-
this.convertToolResultRecord(data,
|
|
1300
|
+
this.convertToolResultRecord(data, builder);
|
|
1279
1301
|
}
|
|
1280
1302
|
}
|
|
1281
|
-
convertAssistantRecord(data,
|
|
1303
|
+
convertAssistantRecord(data, builder, assistantUuidToToolCalls, countedUsageKeys) {
|
|
1282
1304
|
const msg = data["message"] ?? {};
|
|
1283
1305
|
const timestampMs = parseTimestampMs(data);
|
|
1284
1306
|
const rawContent = msg["content"] ?? [];
|
|
1285
1307
|
const uuid = String(data["uuid"] ?? "");
|
|
1286
1308
|
const toolCallIds = [];
|
|
1287
|
-
let currentAssistantIndex = assistantState.currentIndex;
|
|
1288
|
-
let latestAssistantTextIndex = assistantState.latestTextIndex;
|
|
1289
1309
|
if (Array.isArray(rawContent)) {
|
|
1290
1310
|
for (const item of rawContent) {
|
|
1291
1311
|
if (!item || typeof item !== "object") continue;
|
|
@@ -1294,46 +1314,41 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1294
1314
|
if (partType === "thinking") {
|
|
1295
1315
|
const text = cleanInternalText(String(part["thinking"] ?? ""));
|
|
1296
1316
|
if (text) {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
{
|
|
1300
|
-
|
|
1317
|
+
const message2 = builder.appendAssistantPart(
|
|
1318
|
+
this.buildReasoningPart(text, timestampMs),
|
|
1319
|
+
{ id: uuid, timestampMs, agent: "claude" },
|
|
1320
|
+
{ deduplicateTail: true }
|
|
1301
1321
|
);
|
|
1322
|
+
this.applyAssistantMetadata(message2, data, msg, countedUsageKeys);
|
|
1302
1323
|
}
|
|
1303
1324
|
continue;
|
|
1304
1325
|
}
|
|
1305
1326
|
if (partType === "text") {
|
|
1306
1327
|
const text = cleanInternalText(String(part["text"] ?? ""));
|
|
1307
1328
|
if (text) {
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
{
|
|
1311
|
-
|
|
1329
|
+
const message2 = builder.appendAssistantPart(
|
|
1330
|
+
this.buildTextPart(text, timestampMs),
|
|
1331
|
+
{
|
|
1332
|
+
id: uuid,
|
|
1333
|
+
timestampMs,
|
|
1334
|
+
agent: "claude"
|
|
1335
|
+
},
|
|
1336
|
+
{ deduplicateTail: true }
|
|
1312
1337
|
);
|
|
1313
|
-
|
|
1338
|
+
this.applyAssistantMetadata(message2, data, msg, countedUsageKeys);
|
|
1314
1339
|
}
|
|
1315
1340
|
continue;
|
|
1316
1341
|
}
|
|
1317
1342
|
if (partType !== "tool_use") continue;
|
|
1318
|
-
const toolName = String(part["name"] ?? "").trim();
|
|
1319
1343
|
const toolCallId = String(part["id"] ?? "").trim();
|
|
1320
|
-
if (toolName && toolCallId && this.shouldIgnoreTool(toolName)) {
|
|
1321
|
-
ignoredToolCallIds.add(toolCallId);
|
|
1322
|
-
continue;
|
|
1323
|
-
}
|
|
1324
1344
|
const toolPart = this.buildToolPart(part, timestampMs);
|
|
1325
|
-
const
|
|
1326
|
-
messageId: uuid,
|
|
1327
|
-
data,
|
|
1328
|
-
msg,
|
|
1329
|
-
timestampMs,
|
|
1345
|
+
const message = builder.appendToolCall(
|
|
1330
1346
|
toolPart,
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1347
|
+
{ id: uuid, timestampMs, agent: "claude" },
|
|
1348
|
+
{ modeOnCreate: "tool" }
|
|
1349
|
+
);
|
|
1350
|
+
this.applyAssistantMetadata(message, data, msg, countedUsageKeys);
|
|
1335
1351
|
if (toolCallId) {
|
|
1336
|
-
pendingToolCalls.set(toolCallId, [msgIndex, partIndex]);
|
|
1337
1352
|
toolCallIds.push(toolCallId);
|
|
1338
1353
|
}
|
|
1339
1354
|
}
|
|
@@ -1341,10 +1356,8 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1341
1356
|
if (toolCallIds.length > 0) {
|
|
1342
1357
|
assistantUuidToToolCalls.set(uuid, toolCallIds);
|
|
1343
1358
|
}
|
|
1344
|
-
assistantState.currentIndex = currentAssistantIndex;
|
|
1345
|
-
assistantState.latestTextIndex = latestAssistantTextIndex;
|
|
1346
1359
|
}
|
|
1347
|
-
convertUserRecord(data,
|
|
1360
|
+
convertUserRecord(data, builder, assistantUuidToToolCalls) {
|
|
1348
1361
|
const msg = data["message"] ?? {};
|
|
1349
1362
|
const timestampMs = parseTimestampMs(data);
|
|
1350
1363
|
const content = msg["content"] ?? "";
|
|
@@ -1352,18 +1365,14 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1352
1365
|
if (typeof content === "string") {
|
|
1353
1366
|
const parts = this.normalizeUserTextParts(content, timestampMs);
|
|
1354
1367
|
if (parts.length === 0) {
|
|
1355
|
-
|
|
1356
|
-
assistantState.latestTextIndex = null;
|
|
1368
|
+
builder.beginTurn();
|
|
1357
1369
|
return;
|
|
1358
1370
|
}
|
|
1359
|
-
|
|
1360
|
-
assistantState.currentIndex = null;
|
|
1361
|
-
assistantState.latestTextIndex = null;
|
|
1371
|
+
builder.appendMessage({ id: uuid, role: "user", timestampMs, parts });
|
|
1362
1372
|
return;
|
|
1363
1373
|
}
|
|
1364
1374
|
if (!Array.isArray(content)) {
|
|
1365
|
-
|
|
1366
|
-
assistantState.latestTextIndex = null;
|
|
1375
|
+
builder.beginTurn();
|
|
1367
1376
|
return;
|
|
1368
1377
|
}
|
|
1369
1378
|
const visibleParts = this.normalizeUserTextParts(content, timestampMs);
|
|
@@ -1373,15 +1382,8 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1373
1382
|
const ci = item;
|
|
1374
1383
|
if (ci["type"] !== "tool_result") continue;
|
|
1375
1384
|
const toolCallId = this.resolveToolCallId(data, ci, assistantUuidToToolCalls);
|
|
1376
|
-
if (toolCallId && ignoredToolCallIds.has(toolCallId)) continue;
|
|
1377
1385
|
const outputParts = this.normalizeClaudeToolOutput(ci["content"], timestampMs);
|
|
1378
|
-
if (this.backfillToolOutput(
|
|
1379
|
-
messages,
|
|
1380
|
-
pendingToolCalls,
|
|
1381
|
-
toolCallId,
|
|
1382
|
-
outputParts,
|
|
1383
|
-
toolStateUpdates
|
|
1384
|
-
)) {
|
|
1386
|
+
if (this.backfillToolOutput(builder, toolCallId, outputParts, toolStateUpdates)) {
|
|
1385
1387
|
continue;
|
|
1386
1388
|
}
|
|
1387
1389
|
const fallback = this.buildFallbackToolMessage({
|
|
@@ -1390,17 +1392,14 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1390
1392
|
toolCallId,
|
|
1391
1393
|
outputParts
|
|
1392
1394
|
});
|
|
1393
|
-
if (fallback)
|
|
1395
|
+
if (fallback) builder.appendMessage(fallback);
|
|
1394
1396
|
}
|
|
1395
1397
|
if (visibleParts.length > 0) {
|
|
1396
|
-
|
|
1397
|
-
this.buildMessage({ messageId: uuid, role: "user", timestampMs, parts: visibleParts })
|
|
1398
|
-
);
|
|
1398
|
+
builder.appendMessage({ id: uuid, role: "user", timestampMs, parts: visibleParts });
|
|
1399
1399
|
}
|
|
1400
|
-
|
|
1401
|
-
assistantState.latestTextIndex = null;
|
|
1400
|
+
builder.beginTurn();
|
|
1402
1401
|
}
|
|
1403
|
-
convertToolResultRecord(data,
|
|
1402
|
+
convertToolResultRecord(data, builder) {
|
|
1404
1403
|
const timestampMs = parseTimestampMs(data);
|
|
1405
1404
|
const msg = data["message"] ?? {};
|
|
1406
1405
|
const outputParts = this.normalizeClaudeToolOutput(msg["content"], timestampMs);
|
|
@@ -1411,25 +1410,8 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1411
1410
|
toolCallId: null,
|
|
1412
1411
|
outputParts
|
|
1413
1412
|
});
|
|
1414
|
-
if (fallback)
|
|
1415
|
-
|
|
1416
|
-
assistantState.latestTextIndex = null;
|
|
1417
|
-
}
|
|
1418
|
-
// --- Message building ---
|
|
1419
|
-
buildMessage(opts) {
|
|
1420
|
-
return {
|
|
1421
|
-
id: opts.messageId,
|
|
1422
|
-
role: opts.role,
|
|
1423
|
-
agent: opts.agent ?? null,
|
|
1424
|
-
time_created: opts.timestampMs,
|
|
1425
|
-
mode: opts.mode ?? null,
|
|
1426
|
-
model: opts.model ?? null,
|
|
1427
|
-
provider: opts.provider ?? null,
|
|
1428
|
-
tokens: opts.tokens ? opts.tokens : void 0,
|
|
1429
|
-
cost: opts.cost ?? 0,
|
|
1430
|
-
cost_source: opts.cost_source,
|
|
1431
|
-
parts: opts.parts
|
|
1432
|
-
};
|
|
1413
|
+
if (fallback) builder.appendMessage(fallback);
|
|
1414
|
+
builder.beginTurn();
|
|
1433
1415
|
}
|
|
1434
1416
|
buildTextPart(text, timestampMs) {
|
|
1435
1417
|
return { type: "text", text, time_created: timestampMs };
|
|
@@ -1472,71 +1454,6 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1472
1454
|
}
|
|
1473
1455
|
}
|
|
1474
1456
|
}
|
|
1475
|
-
// --- Assistant message grouping ---
|
|
1476
|
-
appendAssistantReasoning(messages, opts, currentIndex) {
|
|
1477
|
-
const part = this.buildReasoningPart(opts.text, opts.timestampMs);
|
|
1478
|
-
if (currentIndex !== null) {
|
|
1479
|
-
const message2 = messages[currentIndex];
|
|
1480
|
-
const hasText = message2.parts.some((p) => p.type === "text");
|
|
1481
|
-
const hasTool = message2.parts.some((p) => p.type === "tool");
|
|
1482
|
-
if (!hasText && !hasTool) {
|
|
1483
|
-
this.appendPartIfNew(message2, part);
|
|
1484
|
-
this.applyAssistantMetadata(message2, opts.data, opts.msg, opts.countedUsageKeys);
|
|
1485
|
-
return currentIndex;
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
const message = this.buildMessage({
|
|
1489
|
-
messageId: opts.messageId,
|
|
1490
|
-
role: "assistant",
|
|
1491
|
-
timestampMs: opts.timestampMs,
|
|
1492
|
-
parts: [part],
|
|
1493
|
-
agent: "claude"
|
|
1494
|
-
});
|
|
1495
|
-
this.applyAssistantMetadata(message, opts.data, opts.msg, opts.countedUsageKeys);
|
|
1496
|
-
messages.push(message);
|
|
1497
|
-
return messages.length - 1;
|
|
1498
|
-
}
|
|
1499
|
-
appendAssistantText(messages, opts, currentIndex) {
|
|
1500
|
-
const part = this.buildTextPart(opts.text, opts.timestampMs);
|
|
1501
|
-
if (currentIndex !== null) {
|
|
1502
|
-
const message2 = messages[currentIndex];
|
|
1503
|
-
const hasTool = message2.parts.some((p) => p.type === "tool");
|
|
1504
|
-
if (!hasTool) {
|
|
1505
|
-
this.appendPartIfNew(message2, part);
|
|
1506
|
-
this.applyAssistantMetadata(message2, opts.data, opts.msg, opts.countedUsageKeys);
|
|
1507
|
-
return currentIndex;
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
const message = this.buildMessage({
|
|
1511
|
-
messageId: opts.messageId,
|
|
1512
|
-
role: "assistant",
|
|
1513
|
-
timestampMs: opts.timestampMs,
|
|
1514
|
-
parts: [part],
|
|
1515
|
-
agent: "claude"
|
|
1516
|
-
});
|
|
1517
|
-
this.applyAssistantMetadata(message, opts.data, opts.msg, opts.countedUsageKeys);
|
|
1518
|
-
messages.push(message);
|
|
1519
|
-
return messages.length - 1;
|
|
1520
|
-
}
|
|
1521
|
-
attachToolCallToLatestAssistant(messages, opts) {
|
|
1522
|
-
if (opts.latestTextIndex !== null) {
|
|
1523
|
-
const message2 = messages[opts.latestTextIndex];
|
|
1524
|
-
message2.parts.push(opts.toolPart);
|
|
1525
|
-
this.applyAssistantMetadata(message2, opts.data, opts.msg, opts.countedUsageKeys);
|
|
1526
|
-
return [opts.latestTextIndex, message2.parts.length - 1];
|
|
1527
|
-
}
|
|
1528
|
-
const message = this.buildMessage({
|
|
1529
|
-
messageId: opts.messageId,
|
|
1530
|
-
role: "assistant",
|
|
1531
|
-
timestampMs: opts.timestampMs,
|
|
1532
|
-
parts: [opts.toolPart],
|
|
1533
|
-
agent: "claude",
|
|
1534
|
-
mode: "tool"
|
|
1535
|
-
});
|
|
1536
|
-
this.applyAssistantMetadata(message, opts.data, opts.msg, opts.countedUsageKeys);
|
|
1537
|
-
messages.push(message);
|
|
1538
|
-
return [messages.length - 1, 0];
|
|
1539
|
-
}
|
|
1540
1457
|
// --- User content normalization ---
|
|
1541
1458
|
normalizeUserTextParts(content, timestampMs) {
|
|
1542
1459
|
if (typeof content === "string") {
|
|
@@ -1568,9 +1485,17 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1568
1485
|
const parts = [];
|
|
1569
1486
|
for (const item of content) {
|
|
1570
1487
|
if (typeof item === "object" && item !== null) {
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1573
|
-
)
|
|
1488
|
+
const itemRecord = item;
|
|
1489
|
+
const source = itemRecord["source"];
|
|
1490
|
+
if (itemRecord["type"] === "image" && source) {
|
|
1491
|
+
const data = typeof source["data"] === "string" ? source["data"] : "";
|
|
1492
|
+
const mimeType = typeof source["media_type"] === "string" ? source["media_type"] : "";
|
|
1493
|
+
if (data && mimeType.startsWith("image/")) {
|
|
1494
|
+
parts.push({ type: "image", data, mime_type: mimeType, time_created: timestampMs });
|
|
1495
|
+
}
|
|
1496
|
+
continue;
|
|
1497
|
+
}
|
|
1498
|
+
const text2 = String(itemRecord["text"] ?? itemRecord["content"] ?? "");
|
|
1574
1499
|
const cleaned = cleanInternalText(text2);
|
|
1575
1500
|
if (cleaned) parts.push(this.buildTextPart(cleaned, timestampMs));
|
|
1576
1501
|
} else if (typeof item === "string") {
|
|
@@ -1584,29 +1509,19 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1584
1509
|
return text ? [this.buildTextPart(text, timestampMs)] : [];
|
|
1585
1510
|
}
|
|
1586
1511
|
// --- Tool backfill ---
|
|
1587
|
-
backfillToolOutput(
|
|
1512
|
+
backfillToolOutput(builder, callId, outputParts, stateUpdates) {
|
|
1588
1513
|
if (!callId) return false;
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
existing.push(...outputParts);
|
|
1597
|
-
} else if (existing === null || existing === void 0) {
|
|
1598
|
-
state.output = [...outputParts];
|
|
1599
|
-
} else {
|
|
1600
|
-
state.output = [existing, ...outputParts];
|
|
1514
|
+
return builder.updateToolCall(callId, (part) => {
|
|
1515
|
+
const state = part.state ?? (part.state = {});
|
|
1516
|
+
if (outputParts.length > 0) {
|
|
1517
|
+
const existing = state.output;
|
|
1518
|
+
if (Array.isArray(existing)) existing.push(...outputParts);
|
|
1519
|
+
else if (existing == null) state.output = [...outputParts];
|
|
1520
|
+
else state.output = [existing, ...outputParts];
|
|
1601
1521
|
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
}
|
|
1606
|
-
if (outputParts.length > 0 && !state.status) {
|
|
1607
|
-
state.status = "completed";
|
|
1608
|
-
}
|
|
1609
|
-
return outputParts.length > 0 || !!stateUpdates;
|
|
1522
|
+
if (stateUpdates) Object.assign(state, stateUpdates);
|
|
1523
|
+
if (outputParts.length > 0 && !state.status) state.status = "completed";
|
|
1524
|
+
});
|
|
1610
1525
|
}
|
|
1611
1526
|
resolveToolCallId(data, item, assistantUuidToToolCalls) {
|
|
1612
1527
|
const directId = String(item["tool_use_id"] ?? "").trim();
|
|
@@ -1634,24 +1549,12 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1634
1549
|
// --- Fallback ---
|
|
1635
1550
|
buildFallbackToolMessage(opts) {
|
|
1636
1551
|
if (opts.outputParts.length === 0) return null;
|
|
1637
|
-
return
|
|
1638
|
-
|
|
1552
|
+
return {
|
|
1553
|
+
id: opts.messageId,
|
|
1639
1554
|
role: "tool",
|
|
1640
1555
|
timestampMs: opts.timestampMs,
|
|
1641
1556
|
parts: opts.outputParts
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
// --- Utilities ---
|
|
1645
|
-
shouldIgnoreTool(toolName) {
|
|
1646
|
-
return toolName === "TodoWrite";
|
|
1647
|
-
}
|
|
1648
|
-
appendPartIfNew(message, part) {
|
|
1649
|
-
const parts = message.parts;
|
|
1650
|
-
if (parts.length > 0 && parts[parts.length - 1].type === part.type) {
|
|
1651
|
-
const tail = parts[parts.length - 1];
|
|
1652
|
-
if (tail.text === part.text) return;
|
|
1653
|
-
}
|
|
1654
|
-
parts.push(part);
|
|
1557
|
+
};
|
|
1655
1558
|
}
|
|
1656
1559
|
};
|
|
1657
1560
|
var DatabaseConstructor = null;
|
|
@@ -2318,50 +2221,6 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2318
2221
|
return skippedSession("malformed metadata");
|
|
2319
2222
|
}
|
|
2320
2223
|
}
|
|
2321
|
-
scan(options) {
|
|
2322
|
-
if (!this.basePath) return [];
|
|
2323
|
-
const scanMarker = perf.start("kimi:scan");
|
|
2324
|
-
const listMarker = perf.start("listSessionDirs");
|
|
2325
|
-
const sessionDirs = this.listSessionDirs();
|
|
2326
|
-
perf.end(listMarker);
|
|
2327
|
-
const metas = [];
|
|
2328
|
-
for (const dir of sessionDirs) {
|
|
2329
|
-
try {
|
|
2330
|
-
const parseMarker = perf.start(`parseSessionDir:${basename4(dir)}`);
|
|
2331
|
-
const meta = getParsedSession(this.parseSessionDirResult(dir));
|
|
2332
|
-
perf.end(parseMarker);
|
|
2333
|
-
if (meta && matchesScanWindow(meta.createdAt, options)) {
|
|
2334
|
-
metas.push(meta);
|
|
2335
|
-
}
|
|
2336
|
-
} catch {
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
options?.onProgress?.({ total: metas.length, processed: 0, sessions: 0 });
|
|
2340
|
-
const heads = [];
|
|
2341
|
-
let processed = 0;
|
|
2342
|
-
for (const meta of metas) {
|
|
2343
|
-
try {
|
|
2344
|
-
meta.sourceFingerprint = this.sourceFingerprint(meta);
|
|
2345
|
-
this.sessionMetaMap.set(meta.id, meta);
|
|
2346
|
-
const stats = this.extractStats(meta.sourcePath);
|
|
2347
|
-
heads.push({
|
|
2348
|
-
id: meta.id,
|
|
2349
|
-
slug: `kimi/${meta.id}`,
|
|
2350
|
-
title: meta.title,
|
|
2351
|
-
directory: meta.cwd,
|
|
2352
|
-
time_created: meta.createdAt,
|
|
2353
|
-
time_updated: meta.createdAt,
|
|
2354
|
-
stats
|
|
2355
|
-
});
|
|
2356
|
-
} catch {
|
|
2357
|
-
} finally {
|
|
2358
|
-
processed += 1;
|
|
2359
|
-
options?.onProgress?.({ total: metas.length, processed, sessions: heads.length });
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
perf.end(scanMarker);
|
|
2363
|
-
return heads;
|
|
2364
|
-
}
|
|
2365
2224
|
listSessionSources(options) {
|
|
2366
2225
|
if (!this.basePath) return [];
|
|
2367
2226
|
const refs = [];
|
|
@@ -2403,8 +2262,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2403
2262
|
getSessionDataFromContext(meta) {
|
|
2404
2263
|
if (!meta.contextFile) throw new Error("context.jsonl is missing");
|
|
2405
2264
|
const content = readFileSync3(meta.contextFile, "utf-8");
|
|
2406
|
-
const
|
|
2407
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2265
|
+
const builder = new TranscriptBuilder();
|
|
2408
2266
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
2409
2267
|
let seq = 0;
|
|
2410
2268
|
const fallbackTs = meta.createdAt;
|
|
@@ -2416,65 +2274,55 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2416
2274
|
if (role === "user") {
|
|
2417
2275
|
const text = cleanInternalText(kimiContentText(record.content));
|
|
2418
2276
|
if (text) {
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
})
|
|
2426
|
-
);
|
|
2277
|
+
builder.appendMessage({
|
|
2278
|
+
id: `context-${seq}`,
|
|
2279
|
+
role: "user",
|
|
2280
|
+
timestampMs: fallbackTs,
|
|
2281
|
+
parts: [{ type: "text", text, time_created: fallbackTs }]
|
|
2282
|
+
});
|
|
2427
2283
|
}
|
|
2428
2284
|
continue;
|
|
2429
2285
|
}
|
|
2430
2286
|
if (role === "assistant") {
|
|
2431
|
-
const
|
|
2287
|
+
const message = this.buildContextAssistantMessage(
|
|
2432
2288
|
record,
|
|
2433
2289
|
seq,
|
|
2434
2290
|
ignoredToolCallIds,
|
|
2435
2291
|
fallbackTs
|
|
2436
2292
|
);
|
|
2437
2293
|
if (!message) continue;
|
|
2438
|
-
|
|
2439
|
-
messages.push(message);
|
|
2440
|
-
for (const [callId, partIndex] of toolIndexes) {
|
|
2441
|
-
pendingToolCalls.set(callId, [msgIndex, partIndex]);
|
|
2442
|
-
}
|
|
2294
|
+
builder.appendMessage(message);
|
|
2443
2295
|
continue;
|
|
2444
2296
|
}
|
|
2445
2297
|
if (role === "tool") {
|
|
2446
2298
|
const callId = String(record.tool_call_id ?? "").trim();
|
|
2447
2299
|
if (callId && ignoredToolCallIds.has(callId)) continue;
|
|
2448
2300
|
const outputParts = normalizeToolOutputParts(record.content, fallbackTs);
|
|
2449
|
-
if (callId && this.backfillToolOutput(
|
|
2301
|
+
if (callId && this.backfillToolOutput(builder, callId, outputParts)) {
|
|
2450
2302
|
continue;
|
|
2451
2303
|
}
|
|
2452
2304
|
if (outputParts.length > 0) {
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
})
|
|
2460
|
-
);
|
|
2305
|
+
builder.appendMessage({
|
|
2306
|
+
id: `context-${seq}`,
|
|
2307
|
+
role: "tool",
|
|
2308
|
+
timestampMs: fallbackTs,
|
|
2309
|
+
parts: outputParts
|
|
2310
|
+
});
|
|
2461
2311
|
}
|
|
2462
2312
|
}
|
|
2463
2313
|
} catch {
|
|
2464
2314
|
}
|
|
2465
2315
|
}
|
|
2466
2316
|
const stats = this.extractStats(meta.sourcePath);
|
|
2467
|
-
return this.buildSessionData(meta,
|
|
2317
|
+
return this.buildSessionData(meta, builder, stats);
|
|
2468
2318
|
}
|
|
2469
2319
|
getSessionDataFromWire(meta) {
|
|
2470
2320
|
const wirePath = meta.wireFile ?? join6(meta.sourcePath, "wire.jsonl");
|
|
2471
2321
|
if (!existsSync6(wirePath)) throw new Error("wire.jsonl is missing");
|
|
2472
2322
|
const content = readFileSync3(wirePath, "utf-8");
|
|
2473
|
-
const
|
|
2474
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2323
|
+
const builder = new TranscriptBuilder();
|
|
2475
2324
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
2476
2325
|
const openToolArgumentBuffer = /* @__PURE__ */ new Map();
|
|
2477
|
-
let currentAssistantIndex = null;
|
|
2478
2326
|
let openToolCallId = null;
|
|
2479
2327
|
let seq = 0;
|
|
2480
2328
|
for (const record of parseJsonlLines(content)) {
|
|
@@ -2491,19 +2339,13 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2491
2339
|
const inputTokens = Number(usage["input_tokens"] ?? 0);
|
|
2492
2340
|
const outputTokens = Number(usage["output_tokens"] ?? 0);
|
|
2493
2341
|
if (inputTokens || outputTokens) {
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
msg.cost = cost;
|
|
2502
|
-
msg.cost_source = "estimated";
|
|
2503
|
-
}
|
|
2504
|
-
break;
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2342
|
+
const tokens = { input: inputTokens, output: outputTokens };
|
|
2343
|
+
const cost = estimateTokenCost(this.defaultModel, tokens);
|
|
2344
|
+
builder.attachUsageToLatestAssistant(tokens, {
|
|
2345
|
+
model: this.defaultModel,
|
|
2346
|
+
cost: cost ?? void 0,
|
|
2347
|
+
costSource: cost === null ? void 0 : "estimated"
|
|
2348
|
+
});
|
|
2507
2349
|
}
|
|
2508
2350
|
}
|
|
2509
2351
|
if (msgType === "TurnBegin") {
|
|
@@ -2511,37 +2353,37 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2511
2353
|
if (Array.isArray(userInput) && userInput.length > 0) {
|
|
2512
2354
|
const text = cleanInternalText(kimiContentText(userInput));
|
|
2513
2355
|
if (text) {
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
})
|
|
2521
|
-
);
|
|
2356
|
+
builder.appendMessage({
|
|
2357
|
+
id: `wire-${seq}`,
|
|
2358
|
+
role: "user",
|
|
2359
|
+
timestampMs,
|
|
2360
|
+
parts: [{ type: "text", text, time_created: timestampMs }]
|
|
2361
|
+
});
|
|
2522
2362
|
}
|
|
2523
2363
|
}
|
|
2524
|
-
|
|
2364
|
+
builder.beginTurn();
|
|
2525
2365
|
openToolCallId = null;
|
|
2526
2366
|
continue;
|
|
2527
2367
|
}
|
|
2528
2368
|
if (msgType === "ContentPart") {
|
|
2529
|
-
currentAssistantIndex = this.getOrCreateWireAssistant(
|
|
2530
|
-
messages,
|
|
2531
|
-
currentAssistantIndex,
|
|
2532
|
-
`wire-${seq}`
|
|
2533
|
-
);
|
|
2534
|
-
const assistant = messages[currentAssistantIndex];
|
|
2535
2369
|
const partType = String(payload.type ?? "");
|
|
2536
2370
|
if (partType === "think") {
|
|
2537
2371
|
const text = cleanInternalText(String(payload.think ?? ""));
|
|
2538
2372
|
if (text) {
|
|
2539
|
-
|
|
2373
|
+
builder.appendAssistantPart(
|
|
2374
|
+
{ type: "reasoning", text, time_created: timestampMs },
|
|
2375
|
+
{ id: `wire-${seq}`, timestampMs: 0, agent: "kimi" },
|
|
2376
|
+
{ grouping: "current" }
|
|
2377
|
+
);
|
|
2540
2378
|
}
|
|
2541
2379
|
} else if (partType === "text") {
|
|
2542
2380
|
const text = cleanInternalText(String(payload.text ?? ""));
|
|
2543
2381
|
if (text) {
|
|
2544
|
-
|
|
2382
|
+
builder.appendAssistantPart(
|
|
2383
|
+
{ type: "text", text, time_created: timestampMs },
|
|
2384
|
+
{ id: `wire-${seq}`, timestampMs: 0, agent: "kimi" },
|
|
2385
|
+
{ grouping: "current" }
|
|
2386
|
+
);
|
|
2545
2387
|
}
|
|
2546
2388
|
}
|
|
2547
2389
|
continue;
|
|
@@ -2556,12 +2398,6 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2556
2398
|
continue;
|
|
2557
2399
|
}
|
|
2558
2400
|
if (!function_ || !callId || !toolName) continue;
|
|
2559
|
-
currentAssistantIndex = this.getOrCreateWireAssistant(
|
|
2560
|
-
messages,
|
|
2561
|
-
currentAssistantIndex,
|
|
2562
|
-
`wire-${seq}`
|
|
2563
|
-
);
|
|
2564
|
-
const assistant = messages[currentAssistantIndex];
|
|
2565
2401
|
const rawArgs = function_.arguments;
|
|
2566
2402
|
const normalizedArgs = normalizeToolArguments(rawArgs);
|
|
2567
2403
|
const buffer = typeof rawArgs === "string" && typeof normalizedArgs !== "string" ? rawArgs : null;
|
|
@@ -2573,10 +2409,11 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2573
2409
|
state: { arguments: normalizedArgs, output: null },
|
|
2574
2410
|
time_created: timestampMs
|
|
2575
2411
|
};
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2412
|
+
builder.appendToolCall(
|
|
2413
|
+
toolPart,
|
|
2414
|
+
{ id: `wire-${seq}`, timestampMs: 0, agent: "kimi" },
|
|
2415
|
+
{ markModeAsTool: true, target: "current" }
|
|
2416
|
+
);
|
|
2580
2417
|
openToolCallId = callId;
|
|
2581
2418
|
if (buffer !== null) {
|
|
2582
2419
|
openToolArgumentBuffer.set(callId, buffer);
|
|
@@ -2590,8 +2427,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2590
2427
|
argumentsPart,
|
|
2591
2428
|
openToolCallId,
|
|
2592
2429
|
openToolArgumentBuffer,
|
|
2593
|
-
|
|
2594
|
-
pendingToolCalls
|
|
2430
|
+
builder
|
|
2595
2431
|
);
|
|
2596
2432
|
continue;
|
|
2597
2433
|
}
|
|
@@ -2599,27 +2435,24 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2599
2435
|
const callId = String(payload.tool_call_id ?? "").trim();
|
|
2600
2436
|
if (callId && ignoredToolCallIds.has(callId)) continue;
|
|
2601
2437
|
const outputParts = normalizeWireToolOutputParts(payload.return_value, timestampMs);
|
|
2602
|
-
if (callId && this.backfillToolOutput(
|
|
2438
|
+
if (callId && this.backfillToolOutput(builder, callId, outputParts)) {
|
|
2603
2439
|
continue;
|
|
2604
2440
|
}
|
|
2605
2441
|
if (outputParts.length > 0) {
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
})
|
|
2613
|
-
);
|
|
2442
|
+
builder.appendMessage({
|
|
2443
|
+
id: `wire-${seq}`,
|
|
2444
|
+
role: "tool",
|
|
2445
|
+
timestampMs,
|
|
2446
|
+
parts: outputParts
|
|
2447
|
+
});
|
|
2614
2448
|
}
|
|
2615
2449
|
continue;
|
|
2616
2450
|
}
|
|
2617
2451
|
} catch {
|
|
2618
2452
|
}
|
|
2619
2453
|
}
|
|
2620
|
-
const filteredMessages = messages.filter((m) => m.parts.length > 0);
|
|
2621
2454
|
const stats = this.extractStats(meta.sourcePath);
|
|
2622
|
-
return this.buildSessionData(meta,
|
|
2455
|
+
return this.buildSessionData(meta, builder, stats);
|
|
2623
2456
|
}
|
|
2624
2457
|
// --- Helpers ---
|
|
2625
2458
|
sourceFingerprint(meta) {
|
|
@@ -2637,23 +2470,8 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2637
2470
|
fileMtime(meta.wireFile)
|
|
2638
2471
|
]);
|
|
2639
2472
|
}
|
|
2640
|
-
buildMessage(opts) {
|
|
2641
|
-
return {
|
|
2642
|
-
id: opts.messageId,
|
|
2643
|
-
role: opts.role,
|
|
2644
|
-
agent: opts.agent ?? null,
|
|
2645
|
-
time_created: opts.timestampMs,
|
|
2646
|
-
mode: opts.mode ?? null,
|
|
2647
|
-
model: opts.model ?? null,
|
|
2648
|
-
provider: opts.provider ?? null,
|
|
2649
|
-
tokens: opts.tokens ? opts.tokens : void 0,
|
|
2650
|
-
cost: opts.cost ?? 0,
|
|
2651
|
-
parts: opts.parts
|
|
2652
|
-
};
|
|
2653
|
-
}
|
|
2654
2473
|
buildContextAssistantMessage(record, seq, ignoredToolCallIds, fallbackTs) {
|
|
2655
2474
|
const parts = [];
|
|
2656
|
-
const toolIndexes = /* @__PURE__ */ new Map();
|
|
2657
2475
|
const content = record.content;
|
|
2658
2476
|
if (Array.isArray(content)) {
|
|
2659
2477
|
for (const item of content) {
|
|
@@ -2691,71 +2509,41 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2691
2509
|
state: { arguments: normalizeToolArguments(function_.arguments), output: null },
|
|
2692
2510
|
time_created: fallbackTs
|
|
2693
2511
|
};
|
|
2694
|
-
toolIndexes.set(callId, parts.length);
|
|
2695
2512
|
parts.push(part);
|
|
2696
2513
|
}
|
|
2697
2514
|
}
|
|
2698
2515
|
if (parts.length === 0) {
|
|
2699
|
-
return
|
|
2700
|
-
message: this.buildMessage({
|
|
2701
|
-
messageId: `context-${seq}`,
|
|
2702
|
-
role: "assistant",
|
|
2703
|
-
timestampMs: fallbackTs,
|
|
2704
|
-
parts: []
|
|
2705
|
-
}),
|
|
2706
|
-
toolIndexes
|
|
2707
|
-
};
|
|
2516
|
+
return null;
|
|
2708
2517
|
}
|
|
2709
2518
|
const allTools = parts.every((p) => p.type === "tool");
|
|
2710
|
-
|
|
2711
|
-
|
|
2519
|
+
return {
|
|
2520
|
+
id: `context-${seq}`,
|
|
2712
2521
|
role: "assistant",
|
|
2713
2522
|
timestampMs: fallbackTs,
|
|
2714
2523
|
parts,
|
|
2715
2524
|
agent: "kimi",
|
|
2716
2525
|
mode: allTools ? "tool" : void 0
|
|
2717
|
-
}
|
|
2718
|
-
return { message, toolIndexes };
|
|
2719
|
-
}
|
|
2720
|
-
getOrCreateWireAssistant(messages, currentIndex, messageId) {
|
|
2721
|
-
if (currentIndex !== null) return currentIndex;
|
|
2722
|
-
messages.push(
|
|
2723
|
-
this.buildMessage({
|
|
2724
|
-
messageId,
|
|
2725
|
-
role: "assistant",
|
|
2726
|
-
timestampMs: 0,
|
|
2727
|
-
parts: [],
|
|
2728
|
-
agent: "kimi"
|
|
2729
|
-
})
|
|
2730
|
-
);
|
|
2731
|
-
return messages.length - 1;
|
|
2526
|
+
};
|
|
2732
2527
|
}
|
|
2733
|
-
appendWireToolCallPart(argumentsPart, openCallId, buffer,
|
|
2734
|
-
if (!openCallId
|
|
2528
|
+
appendWireToolCallPart(argumentsPart, openCallId, buffer, builder) {
|
|
2529
|
+
if (!openCallId) return;
|
|
2735
2530
|
const existing = buffer.get(openCallId) ?? "";
|
|
2736
2531
|
const combined = existing + argumentsPart;
|
|
2737
2532
|
try {
|
|
2738
|
-
const
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2533
|
+
const parsed = JSON.parse(combined);
|
|
2534
|
+
if (builder.updateToolCall(openCallId, (part) => {
|
|
2535
|
+
const state = part.state ?? (part.state = {});
|
|
2536
|
+
state.arguments = parsed;
|
|
2537
|
+
})) {
|
|
2538
|
+
buffer.delete(openCallId);
|
|
2744
2539
|
}
|
|
2745
|
-
buffer.delete(openCallId);
|
|
2746
2540
|
} catch {
|
|
2747
2541
|
buffer.set(openCallId, combined);
|
|
2748
2542
|
}
|
|
2749
2543
|
}
|
|
2750
|
-
backfillToolOutput(
|
|
2544
|
+
backfillToolOutput(builder, callId, outputParts) {
|
|
2751
2545
|
if (!outputParts.length || !callId) return false;
|
|
2752
|
-
|
|
2753
|
-
if (!location) return false;
|
|
2754
|
-
const part = messages[location[0]]?.parts[location[1]];
|
|
2755
|
-
if (!part) return false;
|
|
2756
|
-
if (!part.state) part.state = {};
|
|
2757
|
-
part.state.output = [...outputParts];
|
|
2758
|
-
return true;
|
|
2546
|
+
return builder.resolveToolCall(callId, { output: [...outputParts] });
|
|
2759
2547
|
}
|
|
2760
2548
|
extractStats(sessionDir) {
|
|
2761
2549
|
let totalCost = 0;
|
|
@@ -2811,14 +2599,8 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2811
2599
|
}
|
|
2812
2600
|
return stats;
|
|
2813
2601
|
}
|
|
2814
|
-
buildSessionData(meta,
|
|
2815
|
-
const
|
|
2816
|
-
stats.message_count = cleanedMessages.length;
|
|
2817
|
-
const totalCost = cleanedMessages.reduce((sum, message) => sum + (message.cost ?? 0), 0);
|
|
2818
|
-
if (totalCost > 0) {
|
|
2819
|
-
stats.total_cost = Number(totalCost.toFixed(8));
|
|
2820
|
-
stats.cost_source = "estimated";
|
|
2821
|
-
}
|
|
2602
|
+
buildSessionData(meta, builder, stats) {
|
|
2603
|
+
const transcript = builder.finish(stats);
|
|
2822
2604
|
return {
|
|
2823
2605
|
id: meta.id,
|
|
2824
2606
|
title: meta.title,
|
|
@@ -2826,16 +2608,273 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2826
2608
|
directory: meta.cwd,
|
|
2827
2609
|
time_created: meta.createdAt,
|
|
2828
2610
|
time_updated: meta.createdAt,
|
|
2829
|
-
stats,
|
|
2830
|
-
messages:
|
|
2611
|
+
stats: transcript.stats,
|
|
2612
|
+
messages: transcript.messages
|
|
2831
2613
|
};
|
|
2832
2614
|
}
|
|
2833
2615
|
};
|
|
2616
|
+
var PARSE_FAIL = /* @__PURE__ */ Symbol("parse-fail");
|
|
2617
|
+
var EXEC_OUTPUT_ENVELOPE_RE = /^Script completed\nWall time [^\n]*\nOutput:\n?/;
|
|
2618
|
+
function stripExecOutputEnvelope(text) {
|
|
2619
|
+
return text.replace(EXEC_OUTPUT_ENVELOPE_RE, "");
|
|
2620
|
+
}
|
|
2621
|
+
function splitExecToolName(name) {
|
|
2622
|
+
if (name.startsWith("mcp__")) {
|
|
2623
|
+
const separator = name.lastIndexOf("__");
|
|
2624
|
+
if (separator > 0 && separator + 2 < name.length) {
|
|
2625
|
+
return { name: name.slice(separator + 2), namespace: name.slice(0, separator + 2) };
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
return { name };
|
|
2629
|
+
}
|
|
2630
|
+
function pickExecOutputTarget(calls) {
|
|
2631
|
+
for (let index = calls.length - 1; index >= 0; index -= 1) {
|
|
2632
|
+
const { name } = splitExecToolName(calls[index].name);
|
|
2633
|
+
if (name !== "apply_patch" && name !== "update_plan") return index;
|
|
2634
|
+
}
|
|
2635
|
+
return calls.length - 1;
|
|
2636
|
+
}
|
|
2637
|
+
function getExecPatchText(args) {
|
|
2638
|
+
if (typeof args === "string") return args;
|
|
2639
|
+
if (args && typeof args === "object") {
|
|
2640
|
+
const patch = args["patch"];
|
|
2641
|
+
if (typeof patch === "string") return patch;
|
|
2642
|
+
}
|
|
2643
|
+
return "";
|
|
2644
|
+
}
|
|
2645
|
+
function decodeExecCalls(input) {
|
|
2646
|
+
if (typeof input !== "string" || !input.includes("tools.")) return [];
|
|
2647
|
+
const scope = collectStringVars(input);
|
|
2648
|
+
const calls = [];
|
|
2649
|
+
const callRe = /tools\.([A-Za-z_$][\w$]*)\s*\(/g;
|
|
2650
|
+
let match;
|
|
2651
|
+
while ((match = callRe.exec(input)) !== null) {
|
|
2652
|
+
const reader = new JsValueReader(input, callRe.lastIndex, scope);
|
|
2653
|
+
const args = reader.parseValue();
|
|
2654
|
+
if (args !== PARSE_FAIL) {
|
|
2655
|
+
calls.push({ name: match[1], args });
|
|
2656
|
+
callRe.lastIndex = reader.pos;
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
return calls;
|
|
2660
|
+
}
|
|
2661
|
+
function collectStringVars(input) {
|
|
2662
|
+
const scope = /* @__PURE__ */ new Map();
|
|
2663
|
+
const assignRe = /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*/g;
|
|
2664
|
+
let match;
|
|
2665
|
+
while ((match = assignRe.exec(input)) !== null) {
|
|
2666
|
+
const reader = new JsValueReader(input, assignRe.lastIndex, scope);
|
|
2667
|
+
const value = reader.parseValue();
|
|
2668
|
+
if (value !== PARSE_FAIL) {
|
|
2669
|
+
if (typeof value === "string") scope.set(match[1], value);
|
|
2670
|
+
assignRe.lastIndex = reader.pos;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
return scope;
|
|
2674
|
+
}
|
|
2675
|
+
var IDENT_START_RE = /[A-Za-z_$]/;
|
|
2676
|
+
var IDENT_PART_RE = /[\w$]/;
|
|
2677
|
+
var JsValueReader = class {
|
|
2678
|
+
pos;
|
|
2679
|
+
src;
|
|
2680
|
+
scope;
|
|
2681
|
+
constructor(src, start, scope) {
|
|
2682
|
+
this.src = src;
|
|
2683
|
+
this.pos = start;
|
|
2684
|
+
this.scope = scope;
|
|
2685
|
+
}
|
|
2686
|
+
parseValue() {
|
|
2687
|
+
this.skipTrivia();
|
|
2688
|
+
const char = this.src[this.pos];
|
|
2689
|
+
if (char === void 0) return PARSE_FAIL;
|
|
2690
|
+
if (char === "{") return this.parseObject();
|
|
2691
|
+
if (char === "[") return this.parseArray();
|
|
2692
|
+
if (char === '"' || char === "'" || char === "`") return this.parseString(char);
|
|
2693
|
+
if (char === "-" || char === "+" || char >= "0" && char <= "9") return this.parseNumber();
|
|
2694
|
+
if (IDENT_START_RE.test(char)) return this.parseIdentifierValue();
|
|
2695
|
+
return PARSE_FAIL;
|
|
2696
|
+
}
|
|
2697
|
+
parseObject() {
|
|
2698
|
+
this.pos++;
|
|
2699
|
+
const result = {};
|
|
2700
|
+
this.skipTrivia();
|
|
2701
|
+
if (this.src[this.pos] === "}") {
|
|
2702
|
+
this.pos++;
|
|
2703
|
+
return result;
|
|
2704
|
+
}
|
|
2705
|
+
while (this.pos < this.src.length) {
|
|
2706
|
+
this.skipTrivia();
|
|
2707
|
+
const key = this.parseKey();
|
|
2708
|
+
if (key === PARSE_FAIL) return PARSE_FAIL;
|
|
2709
|
+
this.skipTrivia();
|
|
2710
|
+
if (this.src[this.pos] === ":") {
|
|
2711
|
+
this.pos++;
|
|
2712
|
+
const value = this.parseValue();
|
|
2713
|
+
if (value === PARSE_FAIL) return PARSE_FAIL;
|
|
2714
|
+
result[key] = value;
|
|
2715
|
+
} else {
|
|
2716
|
+
result[key] = this.resolveIdentifier(key);
|
|
2717
|
+
}
|
|
2718
|
+
this.skipTrivia();
|
|
2719
|
+
const next = this.src[this.pos];
|
|
2720
|
+
if (next === ",") {
|
|
2721
|
+
this.pos++;
|
|
2722
|
+
this.skipTrivia();
|
|
2723
|
+
if (this.src[this.pos] === "}") {
|
|
2724
|
+
this.pos++;
|
|
2725
|
+
return result;
|
|
2726
|
+
}
|
|
2727
|
+
continue;
|
|
2728
|
+
}
|
|
2729
|
+
if (next === "}") {
|
|
2730
|
+
this.pos++;
|
|
2731
|
+
return result;
|
|
2732
|
+
}
|
|
2733
|
+
return PARSE_FAIL;
|
|
2734
|
+
}
|
|
2735
|
+
return PARSE_FAIL;
|
|
2736
|
+
}
|
|
2737
|
+
parseArray() {
|
|
2738
|
+
this.pos++;
|
|
2739
|
+
const result = [];
|
|
2740
|
+
this.skipTrivia();
|
|
2741
|
+
if (this.src[this.pos] === "]") {
|
|
2742
|
+
this.pos++;
|
|
2743
|
+
return result;
|
|
2744
|
+
}
|
|
2745
|
+
while (this.pos < this.src.length) {
|
|
2746
|
+
const value = this.parseValue();
|
|
2747
|
+
if (value === PARSE_FAIL) return PARSE_FAIL;
|
|
2748
|
+
result.push(value);
|
|
2749
|
+
this.skipTrivia();
|
|
2750
|
+
const next = this.src[this.pos];
|
|
2751
|
+
if (next === ",") {
|
|
2752
|
+
this.pos++;
|
|
2753
|
+
this.skipTrivia();
|
|
2754
|
+
if (this.src[this.pos] === "]") {
|
|
2755
|
+
this.pos++;
|
|
2756
|
+
return result;
|
|
2757
|
+
}
|
|
2758
|
+
continue;
|
|
2759
|
+
}
|
|
2760
|
+
if (next === "]") {
|
|
2761
|
+
this.pos++;
|
|
2762
|
+
return result;
|
|
2763
|
+
}
|
|
2764
|
+
return PARSE_FAIL;
|
|
2765
|
+
}
|
|
2766
|
+
return PARSE_FAIL;
|
|
2767
|
+
}
|
|
2768
|
+
parseKey() {
|
|
2769
|
+
const char = this.src[this.pos];
|
|
2770
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
2771
|
+
const value = this.parseString(char);
|
|
2772
|
+
return typeof value === "string" ? value : PARSE_FAIL;
|
|
2773
|
+
}
|
|
2774
|
+
if (char !== void 0 && IDENT_START_RE.test(char)) return this.readIdentifier();
|
|
2775
|
+
return PARSE_FAIL;
|
|
2776
|
+
}
|
|
2777
|
+
parseString(quote) {
|
|
2778
|
+
this.pos++;
|
|
2779
|
+
let out = "";
|
|
2780
|
+
while (this.pos < this.src.length) {
|
|
2781
|
+
const char = this.src[this.pos++];
|
|
2782
|
+
if (char === "\\") {
|
|
2783
|
+
out += this.readEscape();
|
|
2784
|
+
continue;
|
|
2785
|
+
}
|
|
2786
|
+
if (char === quote) break;
|
|
2787
|
+
out += char;
|
|
2788
|
+
}
|
|
2789
|
+
return out;
|
|
2790
|
+
}
|
|
2791
|
+
readEscape() {
|
|
2792
|
+
const char = this.src[this.pos++];
|
|
2793
|
+
switch (char) {
|
|
2794
|
+
case "n":
|
|
2795
|
+
return "\n";
|
|
2796
|
+
case "t":
|
|
2797
|
+
return " ";
|
|
2798
|
+
case "r":
|
|
2799
|
+
return "\r";
|
|
2800
|
+
case "b":
|
|
2801
|
+
return "\b";
|
|
2802
|
+
case "f":
|
|
2803
|
+
return "\f";
|
|
2804
|
+
case "v":
|
|
2805
|
+
return "\v";
|
|
2806
|
+
case "0":
|
|
2807
|
+
return "\0";
|
|
2808
|
+
case "u": {
|
|
2809
|
+
const hex = this.src.slice(this.pos, this.pos + 4);
|
|
2810
|
+
if (/^[0-9a-fA-F]{4}$/.test(hex)) {
|
|
2811
|
+
this.pos += 4;
|
|
2812
|
+
return String.fromCharCode(parseInt(hex, 16));
|
|
2813
|
+
}
|
|
2814
|
+
return "u";
|
|
2815
|
+
}
|
|
2816
|
+
case "x": {
|
|
2817
|
+
const hex = this.src.slice(this.pos, this.pos + 2);
|
|
2818
|
+
if (/^[0-9a-fA-F]{2}$/.test(hex)) {
|
|
2819
|
+
this.pos += 2;
|
|
2820
|
+
return String.fromCharCode(parseInt(hex, 16));
|
|
2821
|
+
}
|
|
2822
|
+
return "x";
|
|
2823
|
+
}
|
|
2824
|
+
default:
|
|
2825
|
+
return char ?? "";
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
parseNumber() {
|
|
2829
|
+
const numberRe = /[-+]?(?:0[xX][0-9a-fA-F]+|(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?)/y;
|
|
2830
|
+
numberRe.lastIndex = this.pos;
|
|
2831
|
+
const match = numberRe.exec(this.src);
|
|
2832
|
+
if (!match) return PARSE_FAIL;
|
|
2833
|
+
this.pos += match[0].length;
|
|
2834
|
+
return Number(match[0]);
|
|
2835
|
+
}
|
|
2836
|
+
parseIdentifierValue() {
|
|
2837
|
+
const name = this.readIdentifier();
|
|
2838
|
+
if (name === "true") return true;
|
|
2839
|
+
if (name === "false") return false;
|
|
2840
|
+
if (name === "null") return null;
|
|
2841
|
+
if (name === "undefined") return void 0;
|
|
2842
|
+
return this.resolveIdentifier(name);
|
|
2843
|
+
}
|
|
2844
|
+
resolveIdentifier(name) {
|
|
2845
|
+
return this.scope.has(name) ? this.scope.get(name) : void 0;
|
|
2846
|
+
}
|
|
2847
|
+
readIdentifier() {
|
|
2848
|
+
const start = this.pos;
|
|
2849
|
+
while (this.pos < this.src.length && IDENT_PART_RE.test(this.src[this.pos])) this.pos++;
|
|
2850
|
+
return this.src.slice(start, this.pos);
|
|
2851
|
+
}
|
|
2852
|
+
skipTrivia() {
|
|
2853
|
+
while (this.pos < this.src.length) {
|
|
2854
|
+
const char = this.src[this.pos];
|
|
2855
|
+
if (char === " " || char === " " || char === "\n" || char === "\r") {
|
|
2856
|
+
this.pos++;
|
|
2857
|
+
continue;
|
|
2858
|
+
}
|
|
2859
|
+
if (char === "/" && this.src[this.pos + 1] === "/") {
|
|
2860
|
+
const newline = this.src.indexOf("\n", this.pos + 2);
|
|
2861
|
+
this.pos = newline === -1 ? this.src.length : newline + 1;
|
|
2862
|
+
continue;
|
|
2863
|
+
}
|
|
2864
|
+
if (char === "/" && this.src[this.pos + 1] === "*") {
|
|
2865
|
+
const close = this.src.indexOf("*/", this.pos + 2);
|
|
2866
|
+
this.pos = close === -1 ? this.src.length : close + 2;
|
|
2867
|
+
continue;
|
|
2868
|
+
}
|
|
2869
|
+
break;
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
};
|
|
2834
2873
|
var PROPOSED_PLAN_PATTERN = /<proposed_plan>\s*([\s\S]*?)\s*<\/proposed_plan>/;
|
|
2835
2874
|
var PLAN_APPROVAL_PREFIX = "PLEASE IMPLEMENT THIS PLAN";
|
|
2836
2875
|
var SUBAGENT_NOTIFICATION_PATTERN = /<subagent_notification>\s*([\s\S]*?)\s*<\/subagent_notification>/;
|
|
2837
2876
|
var HEAD_INDEX_VERSION2 = "codex-head-v1";
|
|
2838
|
-
var PARSER_VERSION = "codex-parser-
|
|
2877
|
+
var PARSER_VERSION = "codex-parser-v4";
|
|
2839
2878
|
var DEVELOPER_LIKE_USER_MARKERS = [
|
|
2840
2879
|
"agents.md instructions for",
|
|
2841
2880
|
"<instructions>",
|
|
@@ -2912,6 +2951,20 @@ function normalizeCustomToolArguments(toolName, input) {
|
|
|
2912
2951
|
}
|
|
2913
2952
|
return input;
|
|
2914
2953
|
}
|
|
2954
|
+
function flattenOutputText(output) {
|
|
2955
|
+
if (typeof output === "string") return output;
|
|
2956
|
+
if (Array.isArray(output)) {
|
|
2957
|
+
return output.map((item) => {
|
|
2958
|
+
if (typeof item === "string") return item;
|
|
2959
|
+
if (item && typeof item === "object") {
|
|
2960
|
+
const text = item["text"];
|
|
2961
|
+
if (typeof text === "string") return text;
|
|
2962
|
+
}
|
|
2963
|
+
return "";
|
|
2964
|
+
}).join("");
|
|
2965
|
+
}
|
|
2966
|
+
return "";
|
|
2967
|
+
}
|
|
2915
2968
|
var PATCH_BEGIN_RE = /\*\*\* Begin Patch/;
|
|
2916
2969
|
var PATCH_END_RE = /\*\*\* End Patch/;
|
|
2917
2970
|
var PATCH_HEADER_RE = /\*\*\*\s+(Add|Delete|Update|Move)\s+File:\s*(.+)/;
|
|
@@ -3015,36 +3068,6 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3015
3068
|
return false;
|
|
3016
3069
|
}
|
|
3017
3070
|
}
|
|
3018
|
-
scan(options) {
|
|
3019
|
-
if (!this.basePath) return [];
|
|
3020
|
-
const scanMarker = perf.start("codex:scan");
|
|
3021
|
-
const indexMarker = perf.start("loadSessionIndex");
|
|
3022
|
-
this.loadSessionIndex();
|
|
3023
|
-
perf.end(indexMarker);
|
|
3024
|
-
const heads = [];
|
|
3025
|
-
const listMarker = perf.start("listRolloutFiles");
|
|
3026
|
-
const files = this.listRolloutFiles(options);
|
|
3027
|
-
perf.end(listMarker);
|
|
3028
|
-
options?.onProgress?.({ total: files.length, processed: 0, sessions: 0 });
|
|
3029
|
-
let processed = 0;
|
|
3030
|
-
for (const file of files) {
|
|
3031
|
-
try {
|
|
3032
|
-
const parseMarker = perf.start(`parseSessionHead:${basename5(file)}`);
|
|
3033
|
-
const head = getParsedSession(this.parseSessionHeadResult(file, options));
|
|
3034
|
-
perf.end(parseMarker);
|
|
3035
|
-
if (head) {
|
|
3036
|
-
heads.push(head);
|
|
3037
|
-
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, file));
|
|
3038
|
-
}
|
|
3039
|
-
} catch {
|
|
3040
|
-
} finally {
|
|
3041
|
-
processed += 1;
|
|
3042
|
-
options?.onProgress?.({ total: files.length, processed, sessions: heads.length });
|
|
3043
|
-
}
|
|
3044
|
-
}
|
|
3045
|
-
perf.end(scanMarker);
|
|
3046
|
-
return heads;
|
|
3047
|
-
}
|
|
3048
3071
|
listSessionSources(options) {
|
|
3049
3072
|
if (!this.basePath) return [];
|
|
3050
3073
|
this.loadSessionIndex();
|
|
@@ -3054,9 +3077,9 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3054
3077
|
fingerprint: this.sourceFingerprint(file)
|
|
3055
3078
|
}));
|
|
3056
3079
|
}
|
|
3057
|
-
scanSessionSource(sourcePath) {
|
|
3080
|
+
scanSessionSource(sourcePath, options) {
|
|
3058
3081
|
this.loadSessionIndex();
|
|
3059
|
-
const head = getParsedSession(this.parseSessionHeadResult(sourcePath));
|
|
3082
|
+
const head = getParsedSession(this.parseSessionHeadResult(sourcePath, options));
|
|
3060
3083
|
if (head) {
|
|
3061
3084
|
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, sourcePath));
|
|
3062
3085
|
}
|
|
@@ -3066,14 +3089,11 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3066
3089
|
const meta = this.sessionMetaMap.get(sessionId);
|
|
3067
3090
|
if (!meta) throw new Error(`Session not found: ${sessionId}`);
|
|
3068
3091
|
if (!existsSync7(meta.sourcePath)) throw new Error(`Session file missing: ${meta.sourcePath}`);
|
|
3069
|
-
const
|
|
3070
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
3092
|
+
const transcript = new TranscriptBuilder();
|
|
3071
3093
|
let totalInputTokens = 0;
|
|
3072
3094
|
let totalOutputTokens = 0;
|
|
3073
3095
|
let totalCacheReadTokens = 0;
|
|
3074
3096
|
let totalCost = 0;
|
|
3075
|
-
let currentAssistantIndex = null;
|
|
3076
|
-
let latestAssistantTextIndex = null;
|
|
3077
3097
|
let pendingPlan = null;
|
|
3078
3098
|
let activeModel = meta.model;
|
|
3079
3099
|
let prevCumulativeTotal = 0;
|
|
@@ -3088,24 +3108,7 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3088
3108
|
const payload = record["payload"] ?? {};
|
|
3089
3109
|
activeModel = extractModelName(payload["model"]) ?? activeModel;
|
|
3090
3110
|
}
|
|
3091
|
-
|
|
3092
|
-
record,
|
|
3093
|
-
messages,
|
|
3094
|
-
pendingToolCalls,
|
|
3095
|
-
meta.id,
|
|
3096
|
-
currentAssistantIndex,
|
|
3097
|
-
latestAssistantTextIndex,
|
|
3098
|
-
pendingPlan
|
|
3099
|
-
);
|
|
3100
|
-
currentAssistantIndex = result.currentAssistantIndex;
|
|
3101
|
-
latestAssistantTextIndex = result.latestAssistantTextIndex;
|
|
3102
|
-
pendingPlan = result.pendingPlan;
|
|
3103
|
-
if (currentAssistantIndex !== null && activeModel) {
|
|
3104
|
-
const message = messages[currentAssistantIndex];
|
|
3105
|
-
if (message?.role === "assistant" && !message.model) {
|
|
3106
|
-
message.model = activeModel;
|
|
3107
|
-
}
|
|
3108
|
-
}
|
|
3111
|
+
pendingPlan = this.convertRecord(record, transcript, pendingPlan, activeModel);
|
|
3109
3112
|
if (recordType === "event_msg") {
|
|
3110
3113
|
const payload = record["payload"] ?? {};
|
|
3111
3114
|
if (String(payload["type"] ?? "") === "token_count") {
|
|
@@ -3141,24 +3144,19 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3141
3144
|
totalInputTokens += totalInput;
|
|
3142
3145
|
totalOutputTokens += outputTokens + reasoningTokens;
|
|
3143
3146
|
totalCacheReadTokens += totalCacheRead;
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
totalCost += cost;
|
|
3158
|
-
}
|
|
3159
|
-
break;
|
|
3160
|
-
}
|
|
3161
|
-
}
|
|
3147
|
+
const tokens = {
|
|
3148
|
+
input: totalInput,
|
|
3149
|
+
output: outputTokens,
|
|
3150
|
+
reasoning: reasoningTokens || void 0,
|
|
3151
|
+
cache_read: totalCacheRead || void 0
|
|
3152
|
+
};
|
|
3153
|
+
const cost = estimateTokenCost(activeModel, tokens);
|
|
3154
|
+
transcript.attachUsageToLatestAssistant(tokens, {
|
|
3155
|
+
model: activeModel,
|
|
3156
|
+
cost: cost ?? void 0,
|
|
3157
|
+
costSource: cost === null ? void 0 : "estimated"
|
|
3158
|
+
});
|
|
3159
|
+
totalCost += cost ?? 0;
|
|
3162
3160
|
}
|
|
3163
3161
|
}
|
|
3164
3162
|
}
|
|
@@ -3166,10 +3164,15 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3166
3164
|
} catch {
|
|
3167
3165
|
}
|
|
3168
3166
|
}
|
|
3169
|
-
if (pendingPlan
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3167
|
+
if (pendingPlan) transcript.appendToCurrentAssistant(pendingPlan);
|
|
3168
|
+
const result = transcript.finish({
|
|
3169
|
+
message_count: 0,
|
|
3170
|
+
total_input_tokens: totalInputTokens,
|
|
3171
|
+
total_output_tokens: totalOutputTokens,
|
|
3172
|
+
total_cache_read_tokens: totalCacheReadTokens || void 0,
|
|
3173
|
+
total_cost: totalCost,
|
|
3174
|
+
cost_source: totalCost > 0 ? "estimated" : void 0
|
|
3175
|
+
});
|
|
3173
3176
|
return {
|
|
3174
3177
|
id: meta.id,
|
|
3175
3178
|
title: meta.title,
|
|
@@ -3177,15 +3180,8 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3177
3180
|
directory: meta.directory,
|
|
3178
3181
|
time_created: meta.createdAt,
|
|
3179
3182
|
time_updated: meta.updatedAt,
|
|
3180
|
-
stats:
|
|
3181
|
-
|
|
3182
|
-
total_input_tokens: totalInputTokens,
|
|
3183
|
-
total_output_tokens: totalOutputTokens,
|
|
3184
|
-
total_cache_read_tokens: totalCacheReadTokens || void 0,
|
|
3185
|
-
total_cost: totalCost,
|
|
3186
|
-
cost_source: totalCost > 0 ? "estimated" : void 0
|
|
3187
|
-
},
|
|
3188
|
-
messages: cleanedMessages
|
|
3183
|
+
stats: result.stats,
|
|
3184
|
+
messages: result.messages
|
|
3189
3185
|
};
|
|
3190
3186
|
}
|
|
3191
3187
|
// ---- File listing ----
|
|
@@ -3504,22 +3500,16 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3504
3500
|
return null;
|
|
3505
3501
|
}
|
|
3506
3502
|
// ---- Record conversion ----
|
|
3507
|
-
convertRecord(data,
|
|
3503
|
+
convertRecord(data, transcript, pendingPlan, activeModel) {
|
|
3508
3504
|
const recordType = String(data["type"] ?? "");
|
|
3509
|
-
if (isInternalEventType2(recordType))
|
|
3510
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3511
|
-
}
|
|
3505
|
+
if (isInternalEventType2(recordType)) return pendingPlan;
|
|
3512
3506
|
if (recordType === "session_meta" || recordType === "event_msg") {
|
|
3513
|
-
return
|
|
3514
|
-
}
|
|
3515
|
-
if (recordType !== "response_item") {
|
|
3516
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3507
|
+
return pendingPlan;
|
|
3517
3508
|
}
|
|
3509
|
+
if (recordType !== "response_item") return pendingPlan;
|
|
3518
3510
|
const payload = data["payload"] ?? {};
|
|
3519
3511
|
const payloadType = String(payload["type"] ?? "");
|
|
3520
|
-
if (isInternalEventType2(payloadType))
|
|
3521
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3522
|
-
}
|
|
3512
|
+
if (isInternalEventType2(payloadType)) return pendingPlan;
|
|
3523
3513
|
const timestampMs = parseTimestampMs2(data) || parseTimestampMs2(payload);
|
|
3524
3514
|
switch (payloadType) {
|
|
3525
3515
|
case "message": {
|
|
@@ -3527,60 +3517,39 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3527
3517
|
if (role === "assistant") {
|
|
3528
3518
|
return this.convertAssistantMessage(
|
|
3529
3519
|
payload,
|
|
3530
|
-
|
|
3520
|
+
transcript,
|
|
3531
3521
|
timestampMs,
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
pendingPlan
|
|
3522
|
+
pendingPlan,
|
|
3523
|
+
activeModel
|
|
3535
3524
|
);
|
|
3536
3525
|
}
|
|
3537
3526
|
if (role === "user") {
|
|
3538
|
-
return this.convertUserMessage(
|
|
3539
|
-
payload,
|
|
3540
|
-
messages,
|
|
3541
|
-
timestampMs,
|
|
3542
|
-
currentAssistantIndex,
|
|
3543
|
-
latestAssistantTextIndex,
|
|
3544
|
-
pendingPlan
|
|
3545
|
-
);
|
|
3527
|
+
return this.convertUserMessage(payload, transcript, timestampMs, pendingPlan);
|
|
3546
3528
|
}
|
|
3547
3529
|
break;
|
|
3548
3530
|
}
|
|
3549
3531
|
case "reasoning":
|
|
3550
|
-
|
|
3532
|
+
this.convertReasoning(payload, transcript, timestampMs, activeModel);
|
|
3533
|
+
return null;
|
|
3551
3534
|
case "function_call":
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
messages,
|
|
3555
|
-
pendingToolCalls,
|
|
3556
|
-
timestampMs,
|
|
3557
|
-
currentAssistantIndex,
|
|
3558
|
-
latestAssistantTextIndex
|
|
3559
|
-
);
|
|
3535
|
+
this.convertFunctionCall(payload, transcript, timestampMs, activeModel);
|
|
3536
|
+
return null;
|
|
3560
3537
|
case "function_call_output":
|
|
3561
|
-
this.
|
|
3562
|
-
return
|
|
3538
|
+
this.convertToolCallOutput(payload, transcript, timestampMs);
|
|
3539
|
+
return pendingPlan;
|
|
3563
3540
|
case "custom_tool_call":
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
messages,
|
|
3567
|
-
pendingToolCalls,
|
|
3568
|
-
timestampMs,
|
|
3569
|
-
currentAssistantIndex,
|
|
3570
|
-
latestAssistantTextIndex
|
|
3571
|
-
);
|
|
3541
|
+
this.convertCustomToolCall(payload, transcript, timestampMs, activeModel);
|
|
3542
|
+
return null;
|
|
3572
3543
|
case "custom_tool_call_output":
|
|
3573
|
-
this.
|
|
3574
|
-
return
|
|
3544
|
+
this.convertToolCallOutput(payload, transcript, timestampMs);
|
|
3545
|
+
return pendingPlan;
|
|
3575
3546
|
}
|
|
3576
|
-
return
|
|
3547
|
+
return pendingPlan;
|
|
3577
3548
|
}
|
|
3578
3549
|
// ---- Assistant message ----
|
|
3579
|
-
convertAssistantMessage(payload,
|
|
3550
|
+
convertAssistantMessage(payload, transcript, timestampMs, pendingPlan, activeModel) {
|
|
3580
3551
|
const content = payload["content"];
|
|
3581
|
-
if (!Array.isArray(content))
|
|
3582
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3583
|
-
}
|
|
3552
|
+
if (!Array.isArray(content)) return pendingPlan;
|
|
3584
3553
|
const textParts = [];
|
|
3585
3554
|
for (const item of content) {
|
|
3586
3555
|
if (typeof item !== "object" || item === null) continue;
|
|
@@ -3590,9 +3559,7 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3590
3559
|
if (text.trim()) textParts.push(text);
|
|
3591
3560
|
}
|
|
3592
3561
|
}
|
|
3593
|
-
if (textParts.length === 0)
|
|
3594
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3595
|
-
}
|
|
3562
|
+
if (textParts.length === 0) return pendingPlan;
|
|
3596
3563
|
const fullText = textParts.join("\n");
|
|
3597
3564
|
const planMatch = fullText.match(PROPOSED_PLAN_PATTERN);
|
|
3598
3565
|
if (planMatch) {
|
|
@@ -3606,61 +3573,34 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3606
3573
|
pendingPlan = planPart;
|
|
3607
3574
|
}
|
|
3608
3575
|
const displayText = cleanInternalText(fullText.replace(PROPOSED_PLAN_PATTERN, ""));
|
|
3609
|
-
if (!displayText)
|
|
3610
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3611
|
-
}
|
|
3576
|
+
if (!displayText) return pendingPlan;
|
|
3612
3577
|
const textPart = { type: "text", text: displayText, time_created: timestampMs };
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
}
|
|
3621
|
-
}
|
|
3622
|
-
messages.push(
|
|
3623
|
-
this.buildMessage({
|
|
3624
|
-
messageId: "",
|
|
3625
|
-
role: "assistant",
|
|
3626
|
-
timestampMs,
|
|
3627
|
-
parts: [textPart],
|
|
3628
|
-
agent: "codex"
|
|
3629
|
-
})
|
|
3630
|
-
);
|
|
3631
|
-
currentAssistantIndex = messages.length - 1;
|
|
3632
|
-
latestAssistantTextIndex = currentAssistantIndex;
|
|
3633
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3578
|
+
transcript.appendAssistantPart(textPart, {
|
|
3579
|
+
id: "",
|
|
3580
|
+
timestampMs,
|
|
3581
|
+
agent: "codex",
|
|
3582
|
+
model: activeModel
|
|
3583
|
+
});
|
|
3584
|
+
return pendingPlan;
|
|
3634
3585
|
}
|
|
3635
3586
|
// ---- User message ----
|
|
3636
|
-
convertUserMessage(payload,
|
|
3587
|
+
convertUserMessage(payload, transcript, timestampMs, pendingPlan) {
|
|
3637
3588
|
const content = payload["content"];
|
|
3638
3589
|
const text = Array.isArray(content) ? content.map(
|
|
3639
3590
|
(c) => typeof c === "object" && c !== null ? String(c["text"] ?? "") : String(c ?? "")
|
|
3640
3591
|
).join(" ") : String(content ?? "");
|
|
3641
3592
|
const visibleText = cleanInternalText(text);
|
|
3642
|
-
if (!visibleText)
|
|
3643
|
-
|
|
3644
|
-
}
|
|
3645
|
-
if (isDeveloperLikeUserMessage(visibleText)) {
|
|
3646
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3647
|
-
}
|
|
3593
|
+
if (!visibleText) return pendingPlan;
|
|
3594
|
+
if (isDeveloperLikeUserMessage(visibleText)) return pendingPlan;
|
|
3648
3595
|
if (visibleText.trimStart().startsWith(PLAN_APPROVAL_PREFIX)) {
|
|
3649
|
-
if (pendingPlan
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
timestampMs,
|
|
3658
|
-
parts: [{ type: "text", text: visibleText, time_created: timestampMs }]
|
|
3659
|
-
})
|
|
3660
|
-
);
|
|
3661
|
-
currentAssistantIndex = null;
|
|
3662
|
-
latestAssistantTextIndex = null;
|
|
3663
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3596
|
+
if (pendingPlan) transcript.appendToCurrentAssistant(pendingPlan);
|
|
3597
|
+
transcript.appendMessage({
|
|
3598
|
+
id: "",
|
|
3599
|
+
role: "user",
|
|
3600
|
+
timestampMs,
|
|
3601
|
+
parts: [{ type: "text", text: visibleText, time_created: timestampMs }]
|
|
3602
|
+
});
|
|
3603
|
+
return null;
|
|
3664
3604
|
}
|
|
3665
3605
|
const subagentMatch = visibleText.match(SUBAGENT_NOTIFICATION_PATTERN);
|
|
3666
3606
|
if (subagentMatch) {
|
|
@@ -3674,41 +3614,32 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3674
3614
|
text: completedText || `Subagent ${nickname} completed`,
|
|
3675
3615
|
time_created: timestampMs
|
|
3676
3616
|
};
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
currentAssistantIndex = null;
|
|
3689
|
-
latestAssistantTextIndex = null;
|
|
3690
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3617
|
+
transcript.appendMessage({
|
|
3618
|
+
id: "",
|
|
3619
|
+
role: "assistant",
|
|
3620
|
+
timestampMs,
|
|
3621
|
+
parts: [textPart],
|
|
3622
|
+
agent: "codex",
|
|
3623
|
+
subagentId: agentId || void 0,
|
|
3624
|
+
nickname: nickname || void 0
|
|
3625
|
+
});
|
|
3626
|
+
transcript.beginTurn();
|
|
3627
|
+
return pendingPlan;
|
|
3691
3628
|
} catch {
|
|
3692
3629
|
}
|
|
3693
3630
|
}
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
);
|
|
3702
|
-
currentAssistantIndex = null;
|
|
3703
|
-
latestAssistantTextIndex = null;
|
|
3704
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3631
|
+
transcript.appendMessage({
|
|
3632
|
+
id: "",
|
|
3633
|
+
role: "user",
|
|
3634
|
+
timestampMs,
|
|
3635
|
+
parts: [{ type: "text", text: visibleText, time_created: timestampMs }]
|
|
3636
|
+
});
|
|
3637
|
+
return pendingPlan;
|
|
3705
3638
|
}
|
|
3706
3639
|
// ---- Reasoning ----
|
|
3707
|
-
convertReasoning(payload,
|
|
3640
|
+
convertReasoning(payload, transcript, timestampMs, activeModel) {
|
|
3708
3641
|
const summary = payload["summary"];
|
|
3709
|
-
if (!Array.isArray(summary))
|
|
3710
|
-
return { currentAssistantIndex, latestAssistantTextIndex: null, pendingPlan: null };
|
|
3711
|
-
}
|
|
3642
|
+
if (!Array.isArray(summary)) return;
|
|
3712
3643
|
const texts = [];
|
|
3713
3644
|
for (const item of summary) {
|
|
3714
3645
|
if (typeof item === "object" && item !== null) {
|
|
@@ -3719,42 +3650,25 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3719
3650
|
}
|
|
3720
3651
|
}
|
|
3721
3652
|
}
|
|
3722
|
-
if (texts.length === 0)
|
|
3723
|
-
return { currentAssistantIndex, latestAssistantTextIndex: null, pendingPlan: null };
|
|
3724
|
-
}
|
|
3653
|
+
if (texts.length === 0) return;
|
|
3725
3654
|
const reasoningText = texts.join("\n");
|
|
3726
3655
|
const part = { type: "reasoning", text: reasoningText, time_created: timestampMs };
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
if (!hasText && !hasTool) {
|
|
3732
|
-
message.parts.push(part);
|
|
3733
|
-
return { currentAssistantIndex, latestAssistantTextIndex: null, pendingPlan: null };
|
|
3734
|
-
}
|
|
3735
|
-
}
|
|
3736
|
-
messages.push(
|
|
3737
|
-
this.buildMessage({
|
|
3738
|
-
messageId: "",
|
|
3739
|
-
role: "assistant",
|
|
3656
|
+
transcript.appendAssistantPart(
|
|
3657
|
+
part,
|
|
3658
|
+
{
|
|
3659
|
+
id: "",
|
|
3740
3660
|
timestampMs,
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
}
|
|
3661
|
+
agent: "codex",
|
|
3662
|
+
model: activeModel
|
|
3663
|
+
},
|
|
3664
|
+
{ resetLatestText: true }
|
|
3744
3665
|
);
|
|
3745
|
-
return {
|
|
3746
|
-
currentAssistantIndex: messages.length - 1,
|
|
3747
|
-
latestAssistantTextIndex: null,
|
|
3748
|
-
pendingPlan: null
|
|
3749
|
-
};
|
|
3750
3666
|
}
|
|
3751
3667
|
// ---- Function call ----
|
|
3752
|
-
convertFunctionCall(payload,
|
|
3668
|
+
convertFunctionCall(payload, transcript, timestampMs, activeModel) {
|
|
3753
3669
|
const callId = String(payload["call_id"] ?? "").trim();
|
|
3754
3670
|
const name = String(payload["name"] ?? "").trim();
|
|
3755
|
-
if (!name)
|
|
3756
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan: null };
|
|
3757
|
-
}
|
|
3671
|
+
if (!name) return;
|
|
3758
3672
|
const toolIdentity = resolveToolIdentity(name, payload["namespace"]);
|
|
3759
3673
|
const arguments_ = normalizeToolArguments2(payload["arguments"]);
|
|
3760
3674
|
const toolPart = {
|
|
@@ -3769,58 +3683,35 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3769
3683
|
},
|
|
3770
3684
|
time_created: timestampMs
|
|
3771
3685
|
};
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
message.parts.push(toolPart);
|
|
3777
|
-
message.mode = "tool";
|
|
3778
|
-
if (callId) {
|
|
3779
|
-
pendingToolCalls.set(callId, [targetIndex, partIndex]);
|
|
3780
|
-
}
|
|
3781
|
-
return {
|
|
3782
|
-
currentAssistantIndex: targetIndex,
|
|
3783
|
-
latestAssistantTextIndex: targetIndex,
|
|
3784
|
-
pendingPlan: null
|
|
3785
|
-
};
|
|
3786
|
-
}
|
|
3787
|
-
messages.push(
|
|
3788
|
-
this.buildMessage({
|
|
3789
|
-
messageId: "",
|
|
3790
|
-
role: "assistant",
|
|
3791
|
-
timestampMs,
|
|
3792
|
-
parts: [toolPart],
|
|
3793
|
-
agent: "codex",
|
|
3794
|
-
mode: "tool"
|
|
3795
|
-
})
|
|
3686
|
+
transcript.appendToolCall(
|
|
3687
|
+
toolPart,
|
|
3688
|
+
{ id: "", timestampMs, agent: "codex", model: activeModel },
|
|
3689
|
+
{ markModeAsTool: true }
|
|
3796
3690
|
);
|
|
3797
|
-
const newIndex = messages.length - 1;
|
|
3798
|
-
if (callId) {
|
|
3799
|
-
pendingToolCalls.set(callId, [newIndex, 0]);
|
|
3800
|
-
}
|
|
3801
|
-
return { currentAssistantIndex: newIndex, latestAssistantTextIndex: null, pendingPlan: null };
|
|
3802
3691
|
}
|
|
3803
3692
|
// ---- Function call output ----
|
|
3804
|
-
|
|
3693
|
+
convertToolCallOutput(payload, transcript, timestampMs) {
|
|
3805
3694
|
const callId = String(payload["call_id"] ?? "").trim();
|
|
3806
3695
|
if (!callId) return;
|
|
3807
|
-
const
|
|
3808
|
-
|
|
3809
|
-
|
|
3696
|
+
const outputText = cleanInternalText(
|
|
3697
|
+
stripExecOutputEnvelope(flattenOutputText(payload["output"]))
|
|
3698
|
+
);
|
|
3810
3699
|
const outputParts = outputText ? [{ type: "text", text: outputText, time_created: timestampMs }] : [];
|
|
3811
|
-
const [msgIndex, partIndex] = location;
|
|
3812
|
-
const state = messages[msgIndex].parts[partIndex].state ?? (messages[msgIndex].parts[partIndex].state = {});
|
|
3813
3700
|
if (outputParts.length > 0) {
|
|
3814
|
-
|
|
3815
|
-
state.status = "completed";
|
|
3701
|
+
transcript.resolveToolCall(callId, { output: outputParts, status: "completed" });
|
|
3816
3702
|
}
|
|
3817
3703
|
}
|
|
3818
3704
|
// ---- Custom tool call ----
|
|
3819
|
-
convertCustomToolCall(payload,
|
|
3705
|
+
convertCustomToolCall(payload, transcript, timestampMs, activeModel) {
|
|
3820
3706
|
const callId = String(payload["call_id"] ?? "").trim();
|
|
3821
3707
|
const name = String(payload["name"] ?? "").trim();
|
|
3822
|
-
if (!name)
|
|
3823
|
-
|
|
3708
|
+
if (!name) return;
|
|
3709
|
+
if (name === "exec") {
|
|
3710
|
+
const decoded = decodeExecCalls(payload["input"]);
|
|
3711
|
+
if (decoded.length > 0) {
|
|
3712
|
+
this.appendDecodedExecCalls(decoded, callId, transcript, timestampMs, activeModel);
|
|
3713
|
+
return;
|
|
3714
|
+
}
|
|
3824
3715
|
}
|
|
3825
3716
|
const toolIdentity = resolveToolIdentity(name, payload["namespace"]);
|
|
3826
3717
|
const rawInput = payload["input"];
|
|
@@ -3837,70 +3728,117 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3837
3728
|
},
|
|
3838
3729
|
time_created: timestampMs
|
|
3839
3730
|
};
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
message.parts.push(toolPart);
|
|
3845
|
-
message.mode = "tool";
|
|
3846
|
-
if (callId) {
|
|
3847
|
-
pendingToolCalls.set(callId, [targetIndex, partIndex]);
|
|
3848
|
-
}
|
|
3849
|
-
return {
|
|
3850
|
-
currentAssistantIndex: targetIndex,
|
|
3851
|
-
latestAssistantTextIndex: targetIndex,
|
|
3852
|
-
pendingPlan: null
|
|
3853
|
-
};
|
|
3854
|
-
}
|
|
3855
|
-
messages.push(
|
|
3856
|
-
this.buildMessage({
|
|
3857
|
-
messageId: "",
|
|
3858
|
-
role: "assistant",
|
|
3859
|
-
timestampMs,
|
|
3860
|
-
parts: [toolPart],
|
|
3861
|
-
agent: "codex",
|
|
3862
|
-
mode: "tool"
|
|
3863
|
-
})
|
|
3731
|
+
transcript.appendToolCall(
|
|
3732
|
+
toolPart,
|
|
3733
|
+
{ id: "", timestampMs, agent: "codex", model: activeModel },
|
|
3734
|
+
{ markModeAsTool: true }
|
|
3864
3735
|
);
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3736
|
+
}
|
|
3737
|
+
// ---- Decoded code-mode exec calls ----
|
|
3738
|
+
appendDecodedExecCalls(calls, callId, transcript, timestampMs, activeModel) {
|
|
3739
|
+
const outputIndex = pickExecOutputTarget(calls);
|
|
3740
|
+
calls.forEach((call, index) => {
|
|
3741
|
+
const partCallId = index === outputIndex ? callId : `${callId}#${index}`;
|
|
3742
|
+
this.appendDecodedExecCall(call, partCallId, transcript, timestampMs, activeModel);
|
|
3743
|
+
});
|
|
3744
|
+
}
|
|
3745
|
+
appendDecodedExecCall(call, callId, transcript, timestampMs, activeModel) {
|
|
3746
|
+
const { name, namespace } = splitExecToolName(call.name);
|
|
3747
|
+
const toolIdentity = resolveToolIdentity(name, namespace);
|
|
3748
|
+
const arguments_ = name === "apply_patch" ? parseApplyPatchInput(getExecPatchText(call.args)) : call.args;
|
|
3749
|
+
const toolPart = {
|
|
3750
|
+
type: "tool",
|
|
3751
|
+
tool: toolIdentity.tool,
|
|
3752
|
+
callID: callId,
|
|
3753
|
+
title: `Tool: ${toolIdentity.tool}`,
|
|
3754
|
+
state: {
|
|
3755
|
+
arguments: arguments_,
|
|
3756
|
+
output: null,
|
|
3757
|
+
metadata: toolIdentity.metadata
|
|
3758
|
+
},
|
|
3759
|
+
time_created: timestampMs
|
|
3760
|
+
};
|
|
3761
|
+
transcript.appendToolCall(
|
|
3762
|
+
toolPart,
|
|
3763
|
+
{ id: "", timestampMs, agent: "codex", model: activeModel },
|
|
3764
|
+
{ markModeAsTool: true }
|
|
3765
|
+
);
|
|
3766
|
+
}
|
|
3767
|
+
};
|
|
3768
|
+
var PerfTracer = class {
|
|
3769
|
+
rootMarkers = [];
|
|
3770
|
+
activeStack = [];
|
|
3771
|
+
enabled = false;
|
|
3772
|
+
enable() {
|
|
3773
|
+
this.enabled = true;
|
|
3774
|
+
}
|
|
3775
|
+
start(name) {
|
|
3776
|
+
const marker = {
|
|
3777
|
+
name,
|
|
3778
|
+
startTime: performance.now(),
|
|
3779
|
+
children: []
|
|
3780
|
+
};
|
|
3781
|
+
if (!this.enabled) return marker;
|
|
3782
|
+
const parent = this.activeStack[this.activeStack.length - 1];
|
|
3783
|
+
if (parent) {
|
|
3784
|
+
marker.parent = parent;
|
|
3785
|
+
parent.children.push(marker);
|
|
3786
|
+
} else {
|
|
3787
|
+
this.rootMarkers.push(marker);
|
|
3788
|
+
}
|
|
3789
|
+
this.activeStack.push(marker);
|
|
3790
|
+
return marker;
|
|
3791
|
+
}
|
|
3792
|
+
end(marker) {
|
|
3793
|
+
if (!this.enabled) return;
|
|
3794
|
+
const target = marker ?? this.activeStack[this.activeStack.length - 1];
|
|
3795
|
+
if (!target) return;
|
|
3796
|
+
target.endTime = performance.now();
|
|
3797
|
+
target.duration = target.endTime - target.startTime;
|
|
3798
|
+
while (this.activeStack.length > 0) {
|
|
3799
|
+
const popped = this.activeStack.pop();
|
|
3800
|
+
if (popped === target) break;
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
measure(name, fn) {
|
|
3804
|
+
const marker = this.start(name);
|
|
3805
|
+
try {
|
|
3806
|
+
return fn();
|
|
3807
|
+
} finally {
|
|
3808
|
+
this.end(marker);
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
async measureAsync(name, fn) {
|
|
3812
|
+
const marker = this.start(name);
|
|
3813
|
+
try {
|
|
3814
|
+
return await fn();
|
|
3815
|
+
} finally {
|
|
3816
|
+
this.end(marker);
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
getReport() {
|
|
3820
|
+
if (!this.enabled) return "Performance tracing disabled";
|
|
3821
|
+
const lines = [];
|
|
3822
|
+
lines.push("\n=== Performance Report ===\n");
|
|
3823
|
+
for (const marker of this.rootMarkers) {
|
|
3824
|
+
this.formatMarker(marker, 0, lines);
|
|
3868
3825
|
}
|
|
3869
|
-
return
|
|
3826
|
+
return lines.join("\n");
|
|
3870
3827
|
}
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
const
|
|
3874
|
-
|
|
3875
|
-
const
|
|
3876
|
-
|
|
3877
|
-
const outputText = cleanInternalText(String(payload["output"] ?? ""));
|
|
3878
|
-
const outputParts = outputText ? [{ type: "text", text: outputText, time_created: timestampMs }] : [];
|
|
3879
|
-
const [msgIndex, partIndex] = location;
|
|
3880
|
-
const state = messages[msgIndex].parts[partIndex].state ?? (messages[msgIndex].parts[partIndex].state = {});
|
|
3881
|
-
if (outputParts.length > 0) {
|
|
3882
|
-
state.output = [...outputParts];
|
|
3883
|
-
state.status = "completed";
|
|
3828
|
+
formatMarker(marker, depth, lines) {
|
|
3829
|
+
const indent = " ".repeat(depth);
|
|
3830
|
+
const duration = marker.duration?.toFixed(2) ?? "?";
|
|
3831
|
+
lines.push(`${indent}${marker.name}: ${duration}ms`);
|
|
3832
|
+
for (const child of marker.children) {
|
|
3833
|
+
this.formatMarker(child, depth + 1, lines);
|
|
3884
3834
|
}
|
|
3885
3835
|
}
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
id: opts.messageId,
|
|
3890
|
-
role: opts.role,
|
|
3891
|
-
agent: opts.agent ?? null,
|
|
3892
|
-
time_created: opts.timestampMs,
|
|
3893
|
-
mode: opts.mode ?? null,
|
|
3894
|
-
model: opts.model ?? null,
|
|
3895
|
-
provider: opts.provider ?? null,
|
|
3896
|
-
tokens: opts.tokens ? opts.tokens : void 0,
|
|
3897
|
-
cost: opts.cost ?? 0,
|
|
3898
|
-
parts: opts.parts,
|
|
3899
|
-
subagent_id: opts.subagent_id,
|
|
3900
|
-
nickname: opts.nickname
|
|
3901
|
-
};
|
|
3836
|
+
reset() {
|
|
3837
|
+
this.rootMarkers = [];
|
|
3838
|
+
this.activeStack = [];
|
|
3902
3839
|
}
|
|
3903
3840
|
};
|
|
3841
|
+
var perf = new PerfTracer();
|
|
3904
3842
|
var CURSOR_TOOL_TITLE_MAP = {
|
|
3905
3843
|
read_file_v2: "read",
|
|
3906
3844
|
edit_file_v2: "edit",
|
|
@@ -4068,12 +4006,12 @@ var CursorAgent = class extends DatabaseSessionSource {
|
|
|
4068
4006
|
try {
|
|
4069
4007
|
const row = wsDb.prepare("SELECT value FROM ItemTable WHERE key = 'composer.composerData'").get();
|
|
4070
4008
|
if (!row?.value) continue;
|
|
4071
|
-
const
|
|
4009
|
+
const parsed = JSON.parse(row.value);
|
|
4072
4010
|
let composers;
|
|
4073
|
-
if (
|
|
4074
|
-
composers =
|
|
4075
|
-
} else if (Array.isArray(
|
|
4076
|
-
composers =
|
|
4011
|
+
if (parsed !== null && typeof parsed === "object" && "allComposers" in parsed && Array.isArray(parsed["allComposers"])) {
|
|
4012
|
+
composers = parsed.allComposers;
|
|
4013
|
+
} else if (Array.isArray(parsed)) {
|
|
4014
|
+
composers = parsed;
|
|
4077
4015
|
} else {
|
|
4078
4016
|
continue;
|
|
4079
4017
|
}
|
|
@@ -4452,10 +4390,10 @@ var CursorAgent = class extends DatabaseSessionSource {
|
|
|
4452
4390
|
if (toolData.result !== void 0) {
|
|
4453
4391
|
if (typeof toolData.result === "string") {
|
|
4454
4392
|
try {
|
|
4455
|
-
const
|
|
4456
|
-
state.output =
|
|
4457
|
-
if (
|
|
4458
|
-
state.error =
|
|
4393
|
+
const parsed = JSON.parse(toolData.result);
|
|
4394
|
+
state.output = parsed;
|
|
4395
|
+
if (parsed.error || parsed.message || parsed.stderr) {
|
|
4396
|
+
state.error = parsed.error || parsed.message || parsed.stderr;
|
|
4459
4397
|
state.status = "error";
|
|
4460
4398
|
}
|
|
4461
4399
|
} catch {
|
|
@@ -4577,20 +4515,6 @@ function normalizeTextParts(content, timestampMs) {
|
|
|
4577
4515
|
const text = cleanInternalText(contentToText(content));
|
|
4578
4516
|
return text ? [{ type: "text", text, time_created: timestampMs }] : [];
|
|
4579
4517
|
}
|
|
4580
|
-
function buildMessage(params) {
|
|
4581
|
-
return {
|
|
4582
|
-
id: params.id,
|
|
4583
|
-
role: params.role,
|
|
4584
|
-
agent: params.agent,
|
|
4585
|
-
time_created: params.timestampMs,
|
|
4586
|
-
provider: params.provider,
|
|
4587
|
-
model: params.model,
|
|
4588
|
-
tokens: params.tokens,
|
|
4589
|
-
cost: params.cost,
|
|
4590
|
-
cost_source: params.costSource,
|
|
4591
|
-
parts: params.parts
|
|
4592
|
-
};
|
|
4593
|
-
}
|
|
4594
4518
|
function getEntryTimestamp(entry) {
|
|
4595
4519
|
return parseTimestampMs3(entry["timestamp"]);
|
|
4596
4520
|
}
|
|
@@ -4634,29 +4558,6 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4634
4558
|
if (!this.basePath) return false;
|
|
4635
4559
|
return this.listSessionFiles().length > 0;
|
|
4636
4560
|
}
|
|
4637
|
-
scan(options) {
|
|
4638
|
-
if (!this.basePath) return [];
|
|
4639
|
-
const scanMarker = perf.start("pi:scan");
|
|
4640
|
-
const files = this.listSessionFiles(options);
|
|
4641
|
-
options?.onProgress?.({ total: files.length, processed: 0, sessions: 0 });
|
|
4642
|
-
const heads = [];
|
|
4643
|
-
let processed = 0;
|
|
4644
|
-
for (const file of files) {
|
|
4645
|
-
try {
|
|
4646
|
-
const head = getParsedSession(this.parseSessionHeadResult(file));
|
|
4647
|
-
if (head) {
|
|
4648
|
-
heads.push(head);
|
|
4649
|
-
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, file));
|
|
4650
|
-
}
|
|
4651
|
-
} catch {
|
|
4652
|
-
} finally {
|
|
4653
|
-
processed += 1;
|
|
4654
|
-
options?.onProgress?.({ total: files.length, processed, sessions: heads.length });
|
|
4655
|
-
}
|
|
4656
|
-
}
|
|
4657
|
-
perf.end(scanMarker);
|
|
4658
|
-
return heads;
|
|
4659
|
-
}
|
|
4660
4561
|
listSessionSources(options) {
|
|
4661
4562
|
if (!this.basePath) return [];
|
|
4662
4563
|
return this.listSessionFiles(options).map((file) => ({
|
|
@@ -4676,9 +4577,8 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4676
4577
|
const meta = this.sessionMetaMap.get(sessionId);
|
|
4677
4578
|
if (!meta) throw new Error(`Session not found: ${sessionId}`);
|
|
4678
4579
|
if (!existsSync9(meta.sourcePath)) throw new Error(`Session file missing: ${meta.sourcePath}`);
|
|
4679
|
-
const
|
|
4680
|
-
const state = this.convertEntries(
|
|
4681
|
-
const cleanedMessages = cleanParsedMessages(state.messages);
|
|
4580
|
+
const parsed = this.parsePiFile(meta.sourcePath);
|
|
4581
|
+
const state = this.convertEntries(parsed.pathEntries);
|
|
4682
4582
|
return {
|
|
4683
4583
|
id: meta.id,
|
|
4684
4584
|
title: meta.title,
|
|
@@ -4687,7 +4587,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4687
4587
|
time_created: meta.createdAt,
|
|
4688
4588
|
time_updated: meta.updatedAt,
|
|
4689
4589
|
stats: {
|
|
4690
|
-
message_count:
|
|
4590
|
+
message_count: state.messages.length,
|
|
4691
4591
|
total_input_tokens: state.totalInputTokens,
|
|
4692
4592
|
total_output_tokens: state.totalOutputTokens,
|
|
4693
4593
|
total_cache_read_tokens: state.totalCacheReadTokens || void 0,
|
|
@@ -4695,7 +4595,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4695
4595
|
total_cost: state.totalCost,
|
|
4696
4596
|
cost_source: state.totalCost > 0 ? "recorded" : void 0
|
|
4697
4597
|
},
|
|
4698
|
-
messages:
|
|
4598
|
+
messages: state.messages
|
|
4699
4599
|
};
|
|
4700
4600
|
}
|
|
4701
4601
|
listSessionFiles(options) {
|
|
@@ -4739,18 +4639,18 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4739
4639
|
return JSON.stringify([HEAD_INDEX_VERSION3, PARSER_VERSION2, stat.mtimeMs, stat.size]);
|
|
4740
4640
|
}
|
|
4741
4641
|
parseSessionHeadResult(filePath) {
|
|
4742
|
-
const
|
|
4743
|
-
const state = this.convertEntries(
|
|
4642
|
+
const parsed = this.parsePiFile(filePath);
|
|
4643
|
+
const state = this.convertEntries(parsed.pathEntries);
|
|
4744
4644
|
const messageCount = state.messages.length;
|
|
4745
4645
|
if (messageCount === 0) return filteredSession("no visible messages");
|
|
4746
4646
|
const modelUsage = Object.keys(state.modelUsage).length > 0 ? state.modelUsage : void 0;
|
|
4747
4647
|
return parsedSession({
|
|
4748
|
-
id:
|
|
4749
|
-
slug: `pi/${
|
|
4750
|
-
title:
|
|
4751
|
-
directory:
|
|
4752
|
-
time_created:
|
|
4753
|
-
time_updated:
|
|
4648
|
+
id: parsed.sessionId,
|
|
4649
|
+
slug: `pi/${parsed.sessionId}`,
|
|
4650
|
+
title: parsed.title,
|
|
4651
|
+
directory: parsed.directory,
|
|
4652
|
+
time_created: parsed.createdAt,
|
|
4653
|
+
time_updated: parsed.updatedAt,
|
|
4754
4654
|
stats: {
|
|
4755
4655
|
message_count: messageCount,
|
|
4756
4656
|
total_input_tokens: state.totalInputTokens,
|
|
@@ -4812,74 +4712,52 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4812
4712
|
return null;
|
|
4813
4713
|
}
|
|
4814
4714
|
convertEntries(entries) {
|
|
4815
|
-
const
|
|
4816
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
4715
|
+
const builder = new TranscriptBuilder({ messageDefaults: "sparse" });
|
|
4817
4716
|
const modelUsage = {};
|
|
4818
|
-
let totalInputTokens = 0;
|
|
4819
|
-
let totalOutputTokens = 0;
|
|
4820
|
-
let totalCacheReadTokens = 0;
|
|
4821
|
-
let totalCacheCreateTokens = 0;
|
|
4822
|
-
let totalCost = 0;
|
|
4823
4717
|
for (const entry of entries) {
|
|
4824
4718
|
const timestampMs = getEntryTimestamp(entry);
|
|
4825
4719
|
const type = String(entry["type"] ?? "");
|
|
4826
4720
|
if (type === "message") {
|
|
4827
4721
|
const message = entry["message"];
|
|
4828
4722
|
if (!isObject(message)) continue;
|
|
4829
|
-
const
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
messages.length,
|
|
4835
|
-
messages
|
|
4836
|
-
);
|
|
4837
|
-
if (!result) continue;
|
|
4838
|
-
if (result.message) messages.push(result.message);
|
|
4839
|
-
totalInputTokens += result.inputTokens;
|
|
4840
|
-
totalOutputTokens += result.outputTokens;
|
|
4841
|
-
totalCacheReadTokens += result.cacheReadTokens;
|
|
4842
|
-
totalCacheCreateTokens += result.cacheCreateTokens;
|
|
4843
|
-
totalCost += result.cost;
|
|
4844
|
-
if (result.model && result.totalTokens > 0) {
|
|
4845
|
-
modelUsage[result.model] = (modelUsage[result.model] ?? 0) + result.totalTokens;
|
|
4723
|
+
const result2 = this.convertAgentMessage(entry, message, timestampMs, builder);
|
|
4724
|
+
if (!result2) continue;
|
|
4725
|
+
if (result2.message) builder.appendMessage(result2.message);
|
|
4726
|
+
if (result2.model && result2.totalTokens > 0) {
|
|
4727
|
+
modelUsage[result2.model] = (modelUsage[result2.model] ?? 0) + result2.totalTokens;
|
|
4846
4728
|
}
|
|
4847
4729
|
continue;
|
|
4848
4730
|
}
|
|
4849
4731
|
const summary = this.convertSummaryEntry(entry, timestampMs);
|
|
4850
|
-
if (summary)
|
|
4732
|
+
if (summary) builder.appendMessage(summary);
|
|
4851
4733
|
}
|
|
4734
|
+
const result = builder.finish();
|
|
4852
4735
|
return {
|
|
4853
|
-
messages,
|
|
4854
|
-
totalInputTokens,
|
|
4855
|
-
totalOutputTokens,
|
|
4856
|
-
totalCacheReadTokens,
|
|
4857
|
-
totalCacheCreateTokens,
|
|
4858
|
-
totalCost,
|
|
4736
|
+
messages: result.messages,
|
|
4737
|
+
totalInputTokens: result.stats.total_input_tokens,
|
|
4738
|
+
totalOutputTokens: result.stats.total_output_tokens,
|
|
4739
|
+
totalCacheReadTokens: result.stats.total_cache_read_tokens ?? 0,
|
|
4740
|
+
totalCacheCreateTokens: result.stats.total_cache_create_tokens ?? 0,
|
|
4741
|
+
totalCost: result.stats.total_cost,
|
|
4859
4742
|
modelUsage
|
|
4860
4743
|
};
|
|
4861
4744
|
}
|
|
4862
|
-
convertAgentMessage(entry, message, timestampMs,
|
|
4745
|
+
convertAgentMessage(entry, message, timestampMs, builder) {
|
|
4863
4746
|
const id = String(entry["id"] ?? "");
|
|
4864
4747
|
const role = String(message["role"] ?? "");
|
|
4865
4748
|
if (role === "user") {
|
|
4866
4749
|
const parts = normalizeTextParts(message["content"], timestampMs);
|
|
4867
4750
|
if (parts.length === 0) return null;
|
|
4868
|
-
return this.emptyUsageResult(
|
|
4751
|
+
return this.emptyUsageResult({ id, role: "user", timestampMs, parts });
|
|
4869
4752
|
}
|
|
4870
4753
|
if (role === "assistant") {
|
|
4871
|
-
const parts = this.normalizeAssistantParts(
|
|
4872
|
-
message["content"],
|
|
4873
|
-
timestampMs,
|
|
4874
|
-
pendingToolCalls,
|
|
4875
|
-
nextMessageIndex
|
|
4876
|
-
);
|
|
4754
|
+
const parts = this.normalizeAssistantParts(message["content"], timestampMs);
|
|
4877
4755
|
if (parts.length === 0) return null;
|
|
4878
4756
|
const usage = this.normalizeUsage(message["usage"]);
|
|
4879
4757
|
const model = typeof message["model"] === "string" ? message["model"].trim() : null;
|
|
4880
4758
|
const cost = usage.cost ?? estimateTokenCost(model, usage.tokens) ?? 0;
|
|
4881
4759
|
return {
|
|
4882
|
-
message:
|
|
4760
|
+
message: {
|
|
4883
4761
|
id,
|
|
4884
4762
|
role: "assistant",
|
|
4885
4763
|
agent: "pi",
|
|
@@ -4890,18 +4768,13 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4890
4768
|
tokens: usage.tokens,
|
|
4891
4769
|
cost: cost || void 0,
|
|
4892
4770
|
costSource: cost > 0 ? "recorded" : void 0
|
|
4893
|
-
}
|
|
4894
|
-
inputTokens: usage.inputTokens,
|
|
4895
|
-
outputTokens: usage.outputTokens,
|
|
4896
|
-
cacheReadTokens: usage.cacheReadTokens,
|
|
4897
|
-
cacheCreateTokens: usage.cacheCreateTokens,
|
|
4771
|
+
},
|
|
4898
4772
|
totalTokens: usage.totalTokens,
|
|
4899
|
-
cost,
|
|
4900
4773
|
model
|
|
4901
4774
|
};
|
|
4902
4775
|
}
|
|
4903
4776
|
if (role === "toolResult") {
|
|
4904
|
-
this.attachToolResult(message, timestampMs,
|
|
4777
|
+
this.attachToolResult(message, timestampMs, builder);
|
|
4905
4778
|
return this.emptyUsageResult();
|
|
4906
4779
|
}
|
|
4907
4780
|
if (role === "bashExecution") {
|
|
@@ -4910,24 +4783,22 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4910
4783
|
if (role === "custom" && message["display"] === true) {
|
|
4911
4784
|
const parts = normalizeTextParts(message["content"], timestampMs);
|
|
4912
4785
|
if (parts.length === 0) return null;
|
|
4913
|
-
return this.emptyUsageResult(
|
|
4786
|
+
return this.emptyUsageResult({ id, role: "user", timestampMs, parts });
|
|
4914
4787
|
}
|
|
4915
4788
|
if (role === "branchSummary" || role === "compactionSummary") {
|
|
4916
4789
|
const summary = String(message["summary"] ?? "").trim();
|
|
4917
4790
|
if (!summary) return null;
|
|
4918
|
-
return this.emptyUsageResult(
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
})
|
|
4926
|
-
);
|
|
4791
|
+
return this.emptyUsageResult({
|
|
4792
|
+
id,
|
|
4793
|
+
role: "assistant",
|
|
4794
|
+
agent: "pi",
|
|
4795
|
+
timestampMs,
|
|
4796
|
+
parts: [{ type: "text", text: summary, time_created: timestampMs }]
|
|
4797
|
+
});
|
|
4927
4798
|
}
|
|
4928
4799
|
return null;
|
|
4929
4800
|
}
|
|
4930
|
-
normalizeAssistantParts(content, timestampMs
|
|
4801
|
+
normalizeAssistantParts(content, timestampMs) {
|
|
4931
4802
|
if (!Array.isArray(content)) return [];
|
|
4932
4803
|
const parts = [];
|
|
4933
4804
|
for (const item of content) {
|
|
@@ -4958,29 +4829,26 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4958
4829
|
}
|
|
4959
4830
|
};
|
|
4960
4831
|
parts.push(toolPart);
|
|
4961
|
-
if (callId) pendingToolCalls.set(callId, [messageIndex, parts.length - 1]);
|
|
4962
4832
|
}
|
|
4963
4833
|
}
|
|
4964
4834
|
return parts;
|
|
4965
4835
|
}
|
|
4966
|
-
attachToolResult(message, timestampMs,
|
|
4836
|
+
attachToolResult(message, timestampMs, builder) {
|
|
4967
4837
|
const callId = String(message["toolCallId"] ?? "").trim();
|
|
4968
4838
|
const output = normalizeTextParts(message["content"], timestampMs);
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
target.state.metadata = message["details"];
|
|
4977
|
-
pendingToolCalls.delete(callId);
|
|
4839
|
+
if (!callId) return;
|
|
4840
|
+
builder.resolveToolCall(callId, {
|
|
4841
|
+
output,
|
|
4842
|
+
status: message["isError"] === true ? "error" : "completed",
|
|
4843
|
+
metadata: message["details"],
|
|
4844
|
+
consume: true
|
|
4845
|
+
});
|
|
4978
4846
|
}
|
|
4979
4847
|
convertBashExecution(id, message, timestampMs) {
|
|
4980
4848
|
const command = String(message["command"] ?? "");
|
|
4981
4849
|
const output = String(message["output"] ?? "");
|
|
4982
4850
|
const isError = Number(message["exitCode"] ?? 0) !== 0 || message["cancelled"] === true;
|
|
4983
|
-
return
|
|
4851
|
+
return {
|
|
4984
4852
|
id,
|
|
4985
4853
|
role: "tool",
|
|
4986
4854
|
timestampMs,
|
|
@@ -5003,7 +4871,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
5003
4871
|
}
|
|
5004
4872
|
}
|
|
5005
4873
|
]
|
|
5006
|
-
}
|
|
4874
|
+
};
|
|
5007
4875
|
}
|
|
5008
4876
|
convertSummaryEntry(entry, timestampMs) {
|
|
5009
4877
|
const type = entry["type"];
|
|
@@ -5014,13 +4882,13 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
5014
4882
|
const rawText = type === "custom_message" ? contentToText(entry["content"]) : String(entry["summary"] ?? "");
|
|
5015
4883
|
const text = cleanInternalText(rawText);
|
|
5016
4884
|
if (!text) return null;
|
|
5017
|
-
return
|
|
4885
|
+
return {
|
|
5018
4886
|
id: String(entry["id"] ?? ""),
|
|
5019
4887
|
role: type === "custom_message" ? "user" : "assistant",
|
|
5020
4888
|
agent: type === "custom_message" ? void 0 : "pi",
|
|
5021
4889
|
timestampMs,
|
|
5022
4890
|
parts: [{ type: "text", text, time_created: timestampMs }]
|
|
5023
|
-
}
|
|
4891
|
+
};
|
|
5024
4892
|
}
|
|
5025
4893
|
normalizeUsage(raw) {
|
|
5026
4894
|
const usage = isObject(raw) ? raw : {};
|
|
@@ -5050,12 +4918,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
5050
4918
|
emptyUsageResult(message) {
|
|
5051
4919
|
return {
|
|
5052
4920
|
message,
|
|
5053
|
-
inputTokens: 0,
|
|
5054
|
-
outputTokens: 0,
|
|
5055
|
-
cacheReadTokens: 0,
|
|
5056
|
-
cacheCreateTokens: 0,
|
|
5057
4921
|
totalTokens: 0,
|
|
5058
|
-
cost: 0,
|
|
5059
4922
|
model: null
|
|
5060
4923
|
};
|
|
5061
4924
|
}
|
|
@@ -5076,44 +4939,30 @@ var ZCodeAgent = class extends OpenCodeSqliteAgent {
|
|
|
5076
4939
|
}
|
|
5077
4940
|
};
|
|
5078
4941
|
registerAgent({
|
|
5079
|
-
name: "claudecode",
|
|
5080
|
-
displayName: "Claude Code",
|
|
5081
4942
|
icon: "/icon/agent/claudecode.svg",
|
|
5082
4943
|
create: () => new ClaudeCodeAgent()
|
|
5083
4944
|
});
|
|
5084
4945
|
registerAgent({
|
|
5085
|
-
name: "opencode",
|
|
5086
|
-
displayName: "OpenCode",
|
|
5087
4946
|
icon: "/icon/agent/opencode.svg",
|
|
5088
4947
|
create: () => new OpenCodeAgent()
|
|
5089
4948
|
});
|
|
5090
4949
|
registerAgent({
|
|
5091
|
-
name: "zcode",
|
|
5092
|
-
displayName: "ZCode",
|
|
5093
4950
|
icon: "/icon/agent/zcode.svg",
|
|
5094
4951
|
create: () => new ZCodeAgent()
|
|
5095
4952
|
});
|
|
5096
4953
|
registerAgent({
|
|
5097
|
-
name: "kimi",
|
|
5098
|
-
displayName: "Kimi-Cli",
|
|
5099
4954
|
icon: "/icon/agent/kimi.svg",
|
|
5100
4955
|
create: () => new KimiAgent()
|
|
5101
4956
|
});
|
|
5102
4957
|
registerAgent({
|
|
5103
|
-
name: "codex",
|
|
5104
|
-
displayName: "Codex",
|
|
5105
4958
|
icon: "/icon/agent/codex.svg",
|
|
5106
4959
|
create: () => new CodexAgent()
|
|
5107
4960
|
});
|
|
5108
4961
|
registerAgent({
|
|
5109
|
-
name: "pi",
|
|
5110
|
-
displayName: "Pi",
|
|
5111
4962
|
icon: "/icon/agent/pi.svg",
|
|
5112
4963
|
create: () => new PiAgent()
|
|
5113
4964
|
});
|
|
5114
4965
|
registerAgent({
|
|
5115
|
-
name: "cursor",
|
|
5116
|
-
displayName: "Cursor",
|
|
5117
4966
|
icon: "/icon/agent/cursor.svg",
|
|
5118
4967
|
create: () => new CursorAgent()
|
|
5119
4968
|
});
|
|
@@ -6103,7 +5952,7 @@ function buildSessionContentFromMessages(title, messages) {
|
|
|
6103
5952
|
}
|
|
6104
5953
|
return chunks.join("\n");
|
|
6105
5954
|
}
|
|
6106
|
-
var CACHE_SCHEMA_VERSION =
|
|
5955
|
+
var CACHE_SCHEMA_VERSION = 14;
|
|
6107
5956
|
function withCacheDb(fn) {
|
|
6108
5957
|
const cachePath = getCachePath2();
|
|
6109
5958
|
const db = openDb(cachePath);
|
|
@@ -6157,6 +6006,12 @@ function createCacheTables(db) {
|
|
|
6157
6006
|
index_version TEXT NOT NULL,
|
|
6158
6007
|
last_sync_at INTEGER NOT NULL
|
|
6159
6008
|
);
|
|
6009
|
+
|
|
6010
|
+
CREATE TABLE IF NOT EXISTS pending_reindex (
|
|
6011
|
+
agent_name TEXT NOT NULL,
|
|
6012
|
+
session_id TEXT NOT NULL,
|
|
6013
|
+
PRIMARY KEY (agent_name, session_id)
|
|
6014
|
+
);
|
|
6160
6015
|
`);
|
|
6161
6016
|
}
|
|
6162
6017
|
function createSessionTables(db) {
|
|
@@ -6376,6 +6231,7 @@ function createSearchTables(db) {
|
|
|
6376
6231
|
activity_time INTEGER NOT NULL,
|
|
6377
6232
|
content_text TEXT NOT NULL,
|
|
6378
6233
|
content_hash TEXT NOT NULL,
|
|
6234
|
+
indexed_message_count INTEGER NOT NULL,
|
|
6379
6235
|
indexed_at INTEGER NOT NULL,
|
|
6380
6236
|
UNIQUE(agent_name, session_id)
|
|
6381
6237
|
);
|
|
@@ -6409,6 +6265,24 @@ function createSearchTriggers(db) {
|
|
|
6409
6265
|
END;
|
|
6410
6266
|
`);
|
|
6411
6267
|
}
|
|
6268
|
+
function addIndexedMessageCount(db) {
|
|
6269
|
+
if (!tableExists(db, "session_documents")) return;
|
|
6270
|
+
if (!columnExists(db, "session_documents", "indexed_message_count")) {
|
|
6271
|
+
db.exec(
|
|
6272
|
+
"ALTER TABLE session_documents ADD COLUMN indexed_message_count INTEGER NOT NULL DEFAULT 0"
|
|
6273
|
+
);
|
|
6274
|
+
}
|
|
6275
|
+
if (!tableExists(db, "messages")) return;
|
|
6276
|
+
db.exec(`
|
|
6277
|
+
UPDATE session_documents
|
|
6278
|
+
SET indexed_message_count = (
|
|
6279
|
+
SELECT COUNT(*)
|
|
6280
|
+
FROM messages
|
|
6281
|
+
WHERE messages.agent_name = session_documents.agent_name
|
|
6282
|
+
AND messages.session_id = session_documents.session_id
|
|
6283
|
+
)
|
|
6284
|
+
`);
|
|
6285
|
+
}
|
|
6412
6286
|
function dropSearchTriggers(db) {
|
|
6413
6287
|
db.exec(`
|
|
6414
6288
|
DROP TRIGGER IF EXISTS session_documents_ai;
|
|
@@ -6514,6 +6388,9 @@ function readLegacyCacheVersion(db) {
|
|
|
6514
6388
|
return Number(versionRow?.value ?? 0);
|
|
6515
6389
|
}
|
|
6516
6390
|
function inferCacheSchemaVersion(db) {
|
|
6391
|
+
if (columnExists(db, "session_documents", "indexed_message_count")) {
|
|
6392
|
+
return 14;
|
|
6393
|
+
}
|
|
6517
6394
|
if (tableExists(db, "message_tools")) {
|
|
6518
6395
|
return 11;
|
|
6519
6396
|
}
|
|
@@ -6832,6 +6709,20 @@ function invalidateSearchContentHashes(db) {
|
|
|
6832
6709
|
db.exec("UPDATE session_documents SET content_hash = ''");
|
|
6833
6710
|
}
|
|
6834
6711
|
}
|
|
6712
|
+
var CODEX_EXEC_DECODE_MIGRATION_KEY = "codex_exec_decode_migrated_v3";
|
|
6713
|
+
function migrateCodexExecDecode(db) {
|
|
6714
|
+
if (!tableExists(db, "cache_meta")) return;
|
|
6715
|
+
const done = db.prepare("SELECT value FROM cache_meta WHERE key = ?").get(CODEX_EXEC_DECODE_MIGRATION_KEY);
|
|
6716
|
+
if (done) return;
|
|
6717
|
+
if (tableExists(db, "sessions") && tableExists(db, "pending_reindex")) {
|
|
6718
|
+
db.exec(
|
|
6719
|
+
"INSERT OR IGNORE INTO pending_reindex(agent_name, session_id) SELECT agent_name, session_id FROM sessions WHERE agent_name = 'codex'"
|
|
6720
|
+
);
|
|
6721
|
+
}
|
|
6722
|
+
db.prepare(
|
|
6723
|
+
"INSERT INTO cache_meta(key, value) VALUES (?, '1') ON CONFLICT(key) DO UPDATE SET value = '1'"
|
|
6724
|
+
).run(CODEX_EXEC_DECODE_MIGRATION_KEY);
|
|
6725
|
+
}
|
|
6835
6726
|
function rebuildSearchIndex(db) {
|
|
6836
6727
|
if (!tableExists(db, "session_documents_fts")) {
|
|
6837
6728
|
return;
|
|
@@ -6889,6 +6780,7 @@ function ensureSchema(db, dbPath) {
|
|
|
6889
6780
|
if (currentVersion === 0 && !hasAnyCacheSchema(db)) {
|
|
6890
6781
|
createLatestCacheSchema(db);
|
|
6891
6782
|
setCacheSchemaVersion(db);
|
|
6783
|
+
migrateCodexExecDecode(db);
|
|
6892
6784
|
return;
|
|
6893
6785
|
}
|
|
6894
6786
|
runSchemaMigrations(db, {
|
|
@@ -6948,13 +6840,15 @@ function ensureSchema(db, dbPath) {
|
|
|
6948
6840
|
refreshProjectIdentities(db2);
|
|
6949
6841
|
}
|
|
6950
6842
|
},
|
|
6951
|
-
{ version: 13, migrate: createCacheTables }
|
|
6843
|
+
{ version: 13, migrate: createCacheTables },
|
|
6844
|
+
{ version: 14, migrate: addIndexedMessageCount }
|
|
6952
6845
|
]
|
|
6953
6846
|
});
|
|
6954
6847
|
createLatestCacheSchema(db);
|
|
6955
6848
|
if (getUserVersion(db) <= CACHE_SCHEMA_VERSION) {
|
|
6956
6849
|
setCacheSchemaVersion(db);
|
|
6957
6850
|
}
|
|
6851
|
+
migrateCodexExecDecode(db);
|
|
6958
6852
|
}
|
|
6959
6853
|
function escapeFtsTerm(value) {
|
|
6960
6854
|
return value.replaceAll('"', '""');
|
|
@@ -7080,6 +6974,10 @@ function toFtsQuery(input) {
|
|
|
7080
6974
|
(token, index, values) => token !== "OR" || index > 0 && index < values.length - 1 && values[index - 1] !== "OR" && values[index + 1] !== "OR"
|
|
7081
6975
|
).join(" ");
|
|
7082
6976
|
}
|
|
6977
|
+
function readPendingReindexIds(db, agentName) {
|
|
6978
|
+
const rows = db.prepare("SELECT session_id FROM pending_reindex WHERE agent_name = ?").all(agentName);
|
|
6979
|
+
return new Set(rows.map((row) => String(row.session_id)));
|
|
6980
|
+
}
|
|
7083
6981
|
var SEARCH_INDEX_STATE_BATCH_SIZE = 900;
|
|
7084
6982
|
function shouldBulkSyncSearchIndex(options, changedCount) {
|
|
7085
6983
|
if (options.isBulk != null) {
|
|
@@ -7105,14 +7003,18 @@ function sessionContentHash(session) {
|
|
|
7105
7003
|
session.stats.total_tokens ?? 0
|
|
7106
7004
|
]);
|
|
7107
7005
|
}
|
|
7108
|
-
function searchIndexStateFromRows(indexedRows, messageCountRows) {
|
|
7006
|
+
function searchIndexStateFromRows(indexedRows, messageCountRows, pendingReindexSessionIds = /* @__PURE__ */ new Set()) {
|
|
7109
7007
|
return {
|
|
7110
7008
|
contentHashBySessionId: new Map(
|
|
7111
7009
|
indexedRows.map((row) => [String(row.session_id), String(row.content_hash ?? "")])
|
|
7112
7010
|
),
|
|
7011
|
+
indexedMessageCountBySessionId: new Map(
|
|
7012
|
+
indexedRows.map((row) => [String(row.session_id), Number(row.indexed_message_count ?? 0)])
|
|
7013
|
+
),
|
|
7113
7014
|
messageCountBySessionId: new Map(
|
|
7114
7015
|
messageCountRows.map((row) => [String(row.session_id), Number(row.value ?? 0)])
|
|
7115
|
-
)
|
|
7016
|
+
),
|
|
7017
|
+
pendingReindexSessionIds
|
|
7116
7018
|
};
|
|
7117
7019
|
}
|
|
7118
7020
|
function readSearchIndexState(db, agentName, sessionIds) {
|
|
@@ -7127,18 +7029,26 @@ function readSearchIndexState(db, agentName, sessionIds) {
|
|
|
7127
7029
|
SELECT
|
|
7128
7030
|
requested.session_id,
|
|
7129
7031
|
documents.content_hash,
|
|
7032
|
+
documents.indexed_message_count,
|
|
7130
7033
|
COUNT(messages.message_index) AS value
|
|
7131
7034
|
FROM requested_session_ids AS requested
|
|
7132
7035
|
LEFT JOIN session_documents AS documents
|
|
7133
7036
|
ON documents.agent_name = ? AND documents.session_id = requested.session_id
|
|
7134
7037
|
LEFT JOIN messages
|
|
7135
7038
|
ON messages.agent_name = ? AND messages.session_id = requested.session_id
|
|
7136
|
-
GROUP BY
|
|
7039
|
+
GROUP BY
|
|
7040
|
+
requested.session_id,
|
|
7041
|
+
documents.content_hash,
|
|
7042
|
+
documents.indexed_message_count
|
|
7137
7043
|
`
|
|
7138
7044
|
).all(...batch, agentName, agentName);
|
|
7139
7045
|
rows.push(...batchRows);
|
|
7140
7046
|
}
|
|
7141
|
-
return searchIndexStateFromRows(rows, rows);
|
|
7047
|
+
return searchIndexStateFromRows(rows, rows, readPendingReindexIds(db, agentName));
|
|
7048
|
+
}
|
|
7049
|
+
function searchIndexEntryNeedsUpdate(state, session) {
|
|
7050
|
+
const sessionId = session.id;
|
|
7051
|
+
return state.pendingReindexSessionIds.has(sessionId) || state.contentHashBySessionId.get(sessionId) !== sessionContentHash(session) || state.indexedMessageCountBySessionId.get(sessionId) !== (state.messageCountBySessionId.get(sessionId) ?? 0);
|
|
7142
7052
|
}
|
|
7143
7053
|
function loadSearchIndexEntry(agentName, change, loadSessionData) {
|
|
7144
7054
|
try {
|
|
@@ -7163,6 +7073,12 @@ function loadSearchIndexEntry(agentName, change, loadSessionData) {
|
|
|
7163
7073
|
return null;
|
|
7164
7074
|
}
|
|
7165
7075
|
}
|
|
7076
|
+
function* loadSearchIndexEntries(agentName, changes, loadSessionData) {
|
|
7077
|
+
for (const change of changes) {
|
|
7078
|
+
const entry = loadSearchIndexEntry(agentName, change, loadSessionData);
|
|
7079
|
+
if (entry) yield entry;
|
|
7080
|
+
}
|
|
7081
|
+
}
|
|
7166
7082
|
function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
7167
7083
|
const deleteRow = db.prepare(
|
|
7168
7084
|
"DELETE FROM session_documents WHERE agent_name = ? AND session_id = ?"
|
|
@@ -7234,8 +7150,9 @@ function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
|
7234
7150
|
activity_time,
|
|
7235
7151
|
content_text,
|
|
7236
7152
|
content_hash,
|
|
7153
|
+
indexed_message_count,
|
|
7237
7154
|
indexed_at
|
|
7238
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
7155
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
7239
7156
|
ON CONFLICT(agent_name, session_id) DO UPDATE SET
|
|
7240
7157
|
slug = excluded.slug,
|
|
7241
7158
|
title = excluded.title,
|
|
@@ -7248,19 +7165,26 @@ function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
|
7248
7165
|
activity_time = excluded.activity_time,
|
|
7249
7166
|
content_text = excluded.content_text,
|
|
7250
7167
|
content_hash = excluded.content_hash,
|
|
7168
|
+
indexed_message_count = excluded.indexed_message_count,
|
|
7251
7169
|
indexed_at = excluded.indexed_at
|
|
7252
7170
|
`);
|
|
7171
|
+
const clearPendingReindex = db.prepare(
|
|
7172
|
+
"DELETE FROM pending_reindex WHERE agent_name = ? AND session_id = ?"
|
|
7173
|
+
);
|
|
7253
7174
|
for (const sessionId of new Set(removedSessionIds)) {
|
|
7254
7175
|
deleteRow.run(agentName, sessionId);
|
|
7255
7176
|
deleteFileActivity.run(agentName, sessionId);
|
|
7256
7177
|
deleteMessageTools.run(agentName, sessionId, 0);
|
|
7257
7178
|
deleteMessages.run(agentName, sessionId, 0);
|
|
7179
|
+
clearPendingReindex.run(agentName, sessionId);
|
|
7258
7180
|
}
|
|
7181
|
+
let indexed = 0;
|
|
7259
7182
|
for (const entry of entries) {
|
|
7260
7183
|
const activityTime = entry.session.time_updated ?? entry.session.time_created;
|
|
7261
7184
|
upsertSessionRow(upsertIndexedSession, agentName, entry.session, null, entry.sortIndex, null);
|
|
7262
7185
|
deleteFileActivity.run(agentName, entry.session.id);
|
|
7263
7186
|
deleteMessageTools.run(agentName, entry.session.id, 0);
|
|
7187
|
+
clearPendingReindex.run(agentName, entry.session.id);
|
|
7264
7188
|
writeFileActivityRows(insertFileActivity, entry.fileActivity);
|
|
7265
7189
|
for (const message of entry.messages) {
|
|
7266
7190
|
upsertMessage.run(
|
|
@@ -7303,39 +7227,51 @@ function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
|
7303
7227
|
activityTime,
|
|
7304
7228
|
entry.contentText,
|
|
7305
7229
|
entry.contentHash,
|
|
7230
|
+
entry.messages.length,
|
|
7306
7231
|
Date.now()
|
|
7307
7232
|
);
|
|
7233
|
+
indexed += 1;
|
|
7308
7234
|
}
|
|
7235
|
+
return indexed;
|
|
7309
7236
|
}
|
|
7310
7237
|
function syncSessionSearchIndex(agentName, sessions, loadSessionData, options = {}) {
|
|
7311
7238
|
return withCacheDb((db) => {
|
|
7312
7239
|
ensureFtsConsistency(db);
|
|
7313
7240
|
const startedAt = performance.now();
|
|
7314
7241
|
const existingRows = db.prepare(
|
|
7315
|
-
"SELECT session_id, content_hash FROM session_documents WHERE agent_name = ? ORDER BY id"
|
|
7242
|
+
"SELECT session_id, content_hash, indexed_message_count FROM session_documents WHERE agent_name = ? ORDER BY id"
|
|
7316
7243
|
).all(agentName);
|
|
7317
7244
|
const sessionSortIndexMap = new Map(sessions.map((session, index) => [session.id, index]));
|
|
7318
7245
|
const messageCountRows = db.prepare(
|
|
7319
7246
|
"SELECT session_id, COUNT(*) AS value FROM messages WHERE agent_name = ? GROUP BY session_id"
|
|
7320
7247
|
).all(agentName);
|
|
7321
|
-
const searchIndexState = searchIndexStateFromRows(
|
|
7248
|
+
const searchIndexState = searchIndexStateFromRows(
|
|
7249
|
+
existingRows,
|
|
7250
|
+
messageCountRows,
|
|
7251
|
+
readPendingReindexIds(db, agentName)
|
|
7252
|
+
);
|
|
7322
7253
|
const sessionMap = new Map(sessions.map((session) => [session.id, session]));
|
|
7323
7254
|
const toDelete = existingRows.map((row) => String(row.session_id)).filter((sessionId) => !sessionMap.has(sessionId));
|
|
7324
7255
|
const toUpsert = sessions.filter(
|
|
7325
|
-
(session) => searchIndexState
|
|
7256
|
+
(session) => searchIndexEntryNeedsUpdate(searchIndexState, session)
|
|
7326
7257
|
);
|
|
7327
7258
|
const changedCount = toDelete.length + toUpsert.length;
|
|
7328
7259
|
const isBulk = shouldBulkSyncSearchIndex(options, changedCount);
|
|
7329
|
-
const
|
|
7330
|
-
|
|
7260
|
+
const changes = toUpsert.map((session) => ({
|
|
7261
|
+
session,
|
|
7262
|
+
sortIndex: sessionSortIndexMap.get(session.id) ?? 0
|
|
7263
|
+
}));
|
|
7264
|
+
let indexed = 0;
|
|
7265
|
+
const writeRows = () => {
|
|
7266
|
+
indexed = writeSearchIndexRows(
|
|
7267
|
+
db,
|
|
7331
7268
|
agentName,
|
|
7332
|
-
|
|
7333
|
-
loadSessionData
|
|
7334
|
-
)
|
|
7335
|
-
|
|
7336
|
-
const writeRows = () => writeSearchIndexRows(db, agentName, toDelete, loaded);
|
|
7269
|
+
toDelete,
|
|
7270
|
+
loadSearchIndexEntries(agentName, changes, loadSessionData)
|
|
7271
|
+
);
|
|
7272
|
+
};
|
|
7337
7273
|
let rebuildDurationMs;
|
|
7338
|
-
const needsRebuild = isBulk &&
|
|
7274
|
+
const needsRebuild = isBulk && changedCount > 0;
|
|
7339
7275
|
if (needsRebuild) {
|
|
7340
7276
|
db.transaction(() => {
|
|
7341
7277
|
dropSearchTriggers(db);
|
|
@@ -7357,8 +7293,8 @@ function syncSessionSearchIndex(agentName, sessions, loadSessionData, options =
|
|
|
7357
7293
|
sessions: sessions.length,
|
|
7358
7294
|
changed: toUpsert.length,
|
|
7359
7295
|
deleted: toDelete.length,
|
|
7360
|
-
indexed
|
|
7361
|
-
skipped: toUpsert.length -
|
|
7296
|
+
indexed,
|
|
7297
|
+
skipped: toUpsert.length - indexed,
|
|
7362
7298
|
durationMs: performance.now() - startedAt,
|
|
7363
7299
|
rebuildDurationMs
|
|
7364
7300
|
};
|
|
@@ -7386,15 +7322,22 @@ function syncSessionSearchIndexChanges(agentName, changes, removedSessionIds, lo
|
|
|
7386
7322
|
changes.map(({ session }) => session.id)
|
|
7387
7323
|
);
|
|
7388
7324
|
const toUpsert = changes.filter(
|
|
7389
|
-
({ session }) => (searchIndexState
|
|
7325
|
+
({ session }) => searchIndexEntryNeedsUpdate(searchIndexState, session)
|
|
7390
7326
|
);
|
|
7391
7327
|
const uniqueRemovedSessionIds = Array.from(new Set(removedSessionIds));
|
|
7392
7328
|
const changedCount = uniqueRemovedSessionIds.length + toUpsert.length;
|
|
7393
7329
|
const isBulk = shouldBulkSyncSearchIndex(options, changedCount);
|
|
7394
|
-
|
|
7395
|
-
const writeRows = () =>
|
|
7330
|
+
let indexed = 0;
|
|
7331
|
+
const writeRows = () => {
|
|
7332
|
+
indexed = writeSearchIndexRows(
|
|
7333
|
+
db,
|
|
7334
|
+
agentName,
|
|
7335
|
+
uniqueRemovedSessionIds,
|
|
7336
|
+
loadSearchIndexEntries(agentName, toUpsert, loadSessionData)
|
|
7337
|
+
);
|
|
7338
|
+
};
|
|
7396
7339
|
let rebuildDurationMs;
|
|
7397
|
-
const needsRebuild = isBulk &&
|
|
7340
|
+
const needsRebuild = isBulk && changedCount > 0;
|
|
7398
7341
|
if (needsRebuild) {
|
|
7399
7342
|
db.transaction(() => {
|
|
7400
7343
|
dropSearchTriggers(db);
|
|
@@ -7416,8 +7359,8 @@ function syncSessionSearchIndexChanges(agentName, changes, removedSessionIds, lo
|
|
|
7416
7359
|
sessions: changes.length,
|
|
7417
7360
|
changed: toUpsert.length,
|
|
7418
7361
|
deleted: uniqueRemovedSessionIds.length,
|
|
7419
|
-
indexed
|
|
7420
|
-
skipped: toUpsert.length -
|
|
7362
|
+
indexed,
|
|
7363
|
+
skipped: toUpsert.length - indexed,
|
|
7421
7364
|
durationMs: performance.now() - startedAt,
|
|
7422
7365
|
rebuildDurationMs
|
|
7423
7366
|
};
|
|
@@ -7431,26 +7374,26 @@ function mergeSearchLists(left, right) {
|
|
|
7431
7374
|
return values.length > 0 ? [...new Set(values)] : void 0;
|
|
7432
7375
|
}
|
|
7433
7376
|
function mergeSearchQueryOptions(query, options) {
|
|
7434
|
-
const
|
|
7377
|
+
const parsed = parseSearchQuery(query);
|
|
7435
7378
|
return {
|
|
7436
|
-
text:
|
|
7379
|
+
text: parsed.text || (parsed.hasQualifiers ? "" : query.trim()),
|
|
7437
7380
|
options: {
|
|
7438
7381
|
...options,
|
|
7439
|
-
agent: options.agent ??
|
|
7440
|
-
project: options.project ??
|
|
7441
|
-
projectKind: options.projectKind ??
|
|
7442
|
-
projectKey: options.projectKey ??
|
|
7443
|
-
cwd: options.cwd ??
|
|
7444
|
-
tags: mergeSearchLists(options.tags,
|
|
7445
|
-
tools: mergeSearchLists(options.tools,
|
|
7446
|
-
file: options.file ??
|
|
7447
|
-
fileKind: options.fileKind ??
|
|
7448
|
-
costMin: options.costMin ??
|
|
7449
|
-
costMax: options.costMax ??
|
|
7450
|
-
costMinExclusive: options.costMinExclusive ??
|
|
7451
|
-
costMaxExclusive: options.costMaxExclusive ??
|
|
7382
|
+
agent: options.agent ?? parsed.filters.agent,
|
|
7383
|
+
project: options.project ?? parsed.filters.project,
|
|
7384
|
+
projectKind: options.projectKind ?? parsed.filters.projectKind,
|
|
7385
|
+
projectKey: options.projectKey ?? parsed.filters.projectKey,
|
|
7386
|
+
cwd: options.cwd ?? parsed.filters.cwd,
|
|
7387
|
+
tags: mergeSearchLists(options.tags, parsed.filters.tags),
|
|
7388
|
+
tools: mergeSearchLists(options.tools, parsed.filters.tools),
|
|
7389
|
+
file: options.file ?? parsed.filters.file,
|
|
7390
|
+
fileKind: options.fileKind ?? parsed.filters.fileKind,
|
|
7391
|
+
costMin: options.costMin ?? parsed.filters.costMin,
|
|
7392
|
+
costMax: options.costMax ?? parsed.filters.costMax,
|
|
7393
|
+
costMinExclusive: options.costMinExclusive ?? parsed.filters.costMinExclusive,
|
|
7394
|
+
costMaxExclusive: options.costMaxExclusive ?? parsed.filters.costMaxExclusive
|
|
7452
7395
|
},
|
|
7453
|
-
parsed
|
|
7396
|
+
parsed
|
|
7454
7397
|
};
|
|
7455
7398
|
}
|
|
7456
7399
|
function sessionMatchesSearchCost(session, options) {
|
|
@@ -8067,7 +8010,8 @@ function loadCachedSessionData(agentName, sessionId) {
|
|
|
8067
8010
|
if (!row) {
|
|
8068
8011
|
return null;
|
|
8069
8012
|
}
|
|
8070
|
-
const
|
|
8013
|
+
const pendingReindex = db.prepare("SELECT 1 FROM pending_reindex WHERE agent_name = ? AND session_id = ?").get(agentName, sessionId) != null;
|
|
8014
|
+
const messageRows = pendingReindex ? [] : db.prepare(
|
|
8071
8015
|
`
|
|
8072
8016
|
SELECT
|
|
8073
8017
|
message_id,
|
|
@@ -8504,6 +8448,47 @@ async function ensureSessionTags(agent, sessions, workerUrl) {
|
|
|
8504
8448
|
return ensureSessionTagsSync(agent, sessions);
|
|
8505
8449
|
}
|
|
8506
8450
|
}
|
|
8451
|
+
async function finalizeAgentScan(agent, sessions, context) {
|
|
8452
|
+
const { finalization, options, timing, agentStart, onProgress } = context;
|
|
8453
|
+
const isIncremental = finalization.kind === "incremental";
|
|
8454
|
+
if (!isIncremental) {
|
|
8455
|
+
onProgress?.({ agent: agent.name, phase: "complete", newCount: sessions.length });
|
|
8456
|
+
}
|
|
8457
|
+
const identityStart = performance.now();
|
|
8458
|
+
const sessionsWithIdentity = attachMissingProjectIdentities(sessions);
|
|
8459
|
+
timing.identity = performance.now() - identityStart;
|
|
8460
|
+
let tagged = { sessions: sessionsWithIdentity, changed: false };
|
|
8461
|
+
if (finalization.kind !== "cache-only") {
|
|
8462
|
+
const tagsStart = performance.now();
|
|
8463
|
+
tagged = options.includeSmartTags === false ? tagged : await ensureSessionTags(agent, sessionsWithIdentity, options.smartTagWorkerUrl);
|
|
8464
|
+
timing.tags = performance.now() - tagsStart;
|
|
8465
|
+
}
|
|
8466
|
+
if (options.writeCache !== false) {
|
|
8467
|
+
if (finalization.kind === "incremental") {
|
|
8468
|
+
saveCachedSessionDiff(
|
|
8469
|
+
agent,
|
|
8470
|
+
finalization.cached.sessions,
|
|
8471
|
+
tagged.sessions,
|
|
8472
|
+
finalization.changedIds
|
|
8473
|
+
);
|
|
8474
|
+
} else if (finalization.kind === "unchanged" && tagged.changed) {
|
|
8475
|
+
saveCachedSessionDiff(agent, finalization.cached.sessions, tagged.sessions);
|
|
8476
|
+
}
|
|
8477
|
+
}
|
|
8478
|
+
if (isIncremental) {
|
|
8479
|
+
onProgress?.({ agent: agent.name, phase: "complete", newCount: tagged.sessions.length });
|
|
8480
|
+
}
|
|
8481
|
+
const heads = filterSessions(tagged.sessions, options);
|
|
8482
|
+
timing.total = performance.now() - agentStart;
|
|
8483
|
+
return {
|
|
8484
|
+
agent,
|
|
8485
|
+
heads,
|
|
8486
|
+
fromCache: true,
|
|
8487
|
+
...isIncremental ? { refreshed: true } : {},
|
|
8488
|
+
timing,
|
|
8489
|
+
cacheTimestamp: isIncremental ? finalization.cacheTimestamp : finalization.cached.timestamp
|
|
8490
|
+
};
|
|
8491
|
+
}
|
|
8507
8492
|
async function scanAgentSmart(agent, options, onProgress) {
|
|
8508
8493
|
const agentStart = performance.now();
|
|
8509
8494
|
const timing = { total: 0 };
|
|
@@ -8524,19 +8509,13 @@ async function scanAgentSmart(agent, options, onProgress) {
|
|
|
8524
8509
|
phase: "cache",
|
|
8525
8510
|
cachedCount: cached.sessions.length
|
|
8526
8511
|
});
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
|
|
8530
|
-
timing.identity = performance.now() - t32;
|
|
8531
|
-
const filtered3 = filterSessions(cachedWithIdentity2, options);
|
|
8532
|
-
timing.total = performance.now() - agentStart;
|
|
8533
|
-
return {
|
|
8534
|
-
agent,
|
|
8535
|
-
heads: filtered3,
|
|
8536
|
-
fromCache: true,
|
|
8512
|
+
return finalizeAgentScan(agent, cached.sessions, {
|
|
8513
|
+
finalization: { kind: "cache-only", cached },
|
|
8514
|
+
options,
|
|
8537
8515
|
timing,
|
|
8538
|
-
|
|
8539
|
-
|
|
8516
|
+
agentStart,
|
|
8517
|
+
onProgress
|
|
8518
|
+
});
|
|
8540
8519
|
}
|
|
8541
8520
|
const isAvail = agent.isAvailable();
|
|
8542
8521
|
if (!isAvail) {
|
|
@@ -8564,55 +8543,26 @@ async function scanAgentSmart(agent, options, onProgress) {
|
|
|
8564
8543
|
agent.incrementalScan(cached.sessions, checkResult.changedIds || [])
|
|
8565
8544
|
);
|
|
8566
8545
|
timing.scan = performance.now() - t2;
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
agent,
|
|
8576
|
-
cached.sessions,
|
|
8577
|
-
tagged2.sessions,
|
|
8578
|
-
checkResult.changedIds ?? []
|
|
8579
|
-
);
|
|
8580
|
-
}
|
|
8581
|
-
onProgress?.({
|
|
8582
|
-
agent: agent.name,
|
|
8583
|
-
phase: "complete",
|
|
8584
|
-
newCount: tagged2.sessions.length
|
|
8585
|
-
});
|
|
8586
|
-
const filtered3 = filterSessions(tagged2.sessions, options);
|
|
8587
|
-
timing.total = performance.now() - agentStart;
|
|
8588
|
-
return {
|
|
8589
|
-
agent,
|
|
8590
|
-
heads: filtered3,
|
|
8591
|
-
fromCache: true,
|
|
8592
|
-
refreshed: true,
|
|
8546
|
+
return finalizeAgentScan(agent, updatedSessions, {
|
|
8547
|
+
finalization: {
|
|
8548
|
+
kind: "incremental",
|
|
8549
|
+
cached,
|
|
8550
|
+
changedIds: checkResult.changedIds ?? [],
|
|
8551
|
+
cacheTimestamp: checkResult.timestamp
|
|
8552
|
+
},
|
|
8553
|
+
options,
|
|
8593
8554
|
timing,
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
onProgress?.({ agent: agent.name, phase: "complete", newCount: cached.sessions.length });
|
|
8598
|
-
const t3 = performance.now();
|
|
8599
|
-
const cachedWithIdentity = attachMissingProjectIdentities(cached.sessions);
|
|
8600
|
-
timing.identity = performance.now() - t3;
|
|
8601
|
-
const t4 = performance.now();
|
|
8602
|
-
const tagged = options.includeSmartTags === false ? { sessions: cachedWithIdentity, changed: false } : await ensureSessionTags(agent, cachedWithIdentity, options.smartTagWorkerUrl);
|
|
8603
|
-
timing.tags = performance.now() - t4;
|
|
8604
|
-
if (tagged.changed && options.writeCache !== false) {
|
|
8605
|
-
saveCachedSessionDiff(agent, cached.sessions, tagged.sessions);
|
|
8555
|
+
agentStart,
|
|
8556
|
+
onProgress
|
|
8557
|
+
});
|
|
8606
8558
|
}
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
agent,
|
|
8611
|
-
heads: filtered2,
|
|
8612
|
-
fromCache: true,
|
|
8559
|
+
return finalizeAgentScan(agent, cached.sessions, {
|
|
8560
|
+
finalization: { kind: "unchanged", cached },
|
|
8561
|
+
options,
|
|
8613
8562
|
timing,
|
|
8614
|
-
|
|
8615
|
-
|
|
8563
|
+
agentStart,
|
|
8564
|
+
onProgress
|
|
8565
|
+
});
|
|
8616
8566
|
}
|
|
8617
8567
|
}
|
|
8618
8568
|
if (options.cacheOnly) {
|
|
@@ -8660,9 +8610,9 @@ async function scanAgentFull(agent, options, onProgress, timing = { total: 0 },
|
|
|
8660
8610
|
markAgentFullSyncCompleted(agent.name);
|
|
8661
8611
|
}
|
|
8662
8612
|
onProgress?.({ agent: agent.name, phase: "complete", newCount: tagged.sessions.length });
|
|
8663
|
-
const
|
|
8613
|
+
const filtered = filterSessions(tagged.sessions, options);
|
|
8664
8614
|
timing.total = performance.now() - agentStart;
|
|
8665
|
-
return { agent, heads:
|
|
8615
|
+
return { agent, heads: filtered, fromCache: false, timing };
|
|
8666
8616
|
} catch (err) {
|
|
8667
8617
|
console.error(`Error scanning ${agent.name}:`, err);
|
|
8668
8618
|
return { agent, heads: [], fromCache: false };
|
|
@@ -8710,67 +8660,35 @@ async function scanSessions(options = {}, onProgress) {
|
|
|
8710
8660
|
async function scanSessionsAsync(options = {}, onProgress) {
|
|
8711
8661
|
return scanSessions(options, onProgress);
|
|
8712
8662
|
}
|
|
8713
|
-
var
|
|
8714
|
-
var
|
|
8663
|
+
var STATE_DB_FILENAME = "state.db";
|
|
8664
|
+
var STATE_SCHEMA_VERSION = 2;
|
|
8715
8665
|
var MEMORY_STATE_STORE = "memory";
|
|
8716
|
-
var
|
|
8717
|
-
var BookmarkStorageUnavailableError = class extends Error {
|
|
8666
|
+
var StateStorageUnavailableError = class extends Error {
|
|
8718
8667
|
constructor() {
|
|
8719
8668
|
super("SQLite state database is unavailable");
|
|
8720
|
-
this.name = "
|
|
8669
|
+
this.name = "StateStorageUnavailableError";
|
|
8721
8670
|
}
|
|
8722
8671
|
};
|
|
8723
8672
|
function getStateDir() {
|
|
8724
|
-
if (process.env.CODESESH_STATE_DIR)
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
const p = platform2();
|
|
8728
|
-
if (p === "darwin") {
|
|
8673
|
+
if (process.env.CODESESH_STATE_DIR) return process.env.CODESESH_STATE_DIR;
|
|
8674
|
+
const currentPlatform = platform2();
|
|
8675
|
+
if (currentPlatform === "darwin") {
|
|
8729
8676
|
return join12(homedir5(), "Library", "Application Support", "codesesh");
|
|
8730
8677
|
}
|
|
8731
|
-
if (
|
|
8678
|
+
if (currentPlatform === "win32") {
|
|
8732
8679
|
const appData = process.env.APPDATA ?? process.env.LOCALAPPDATA;
|
|
8733
8680
|
return join12(appData ?? join12(homedir5(), "AppData", "Roaming"), "codesesh");
|
|
8734
8681
|
}
|
|
8735
8682
|
return join12(process.env.XDG_DATA_HOME ?? join12(homedir5(), ".local", "share"), "codesesh");
|
|
8736
8683
|
}
|
|
8737
8684
|
function getStateDbPath() {
|
|
8738
|
-
return join12(getStateDir(),
|
|
8685
|
+
return join12(getStateDir(), STATE_DB_FILENAME);
|
|
8739
8686
|
}
|
|
8740
8687
|
function useMemoryStateStore() {
|
|
8741
8688
|
return process.env.CODESESH_STATE_STORE === MEMORY_STATE_STORE;
|
|
8742
8689
|
}
|
|
8743
|
-
function
|
|
8744
|
-
return JSON.stringify([agentKey, sessionId]);
|
|
8745
|
-
}
|
|
8746
|
-
function getActivityTime(bookmark) {
|
|
8747
|
-
return bookmark.time_updated ?? bookmark.time_created;
|
|
8748
|
-
}
|
|
8749
|
-
function sortBookmarks(bookmarks) {
|
|
8750
|
-
return bookmarks.sort((a, b) => {
|
|
8751
|
-
const activityDelta = getActivityTime(b) - getActivityTime(a);
|
|
8752
|
-
return activityDelta || b.bookmarked_at - a.bookmarked_at;
|
|
8753
|
-
});
|
|
8754
|
-
}
|
|
8755
|
-
function listMemoryBookmarks() {
|
|
8756
|
-
return sortBookmarks(Array.from(memoryBookmarks.values()));
|
|
8757
|
-
}
|
|
8758
|
-
function upsertMemoryBookmark(bookmark) {
|
|
8759
|
-
const key = getBookmarkKey(bookmark.agentKey, bookmark.sessionId);
|
|
8760
|
-
const saved = {
|
|
8761
|
-
...bookmark,
|
|
8762
|
-
bookmarked_at: memoryBookmarks.get(key)?.bookmarked_at ?? Date.now()
|
|
8763
|
-
};
|
|
8764
|
-
memoryBookmarks.set(key, saved);
|
|
8765
|
-
return saved;
|
|
8766
|
-
}
|
|
8767
|
-
function createStateSchema(db) {
|
|
8690
|
+
function createBookmarksTable(db) {
|
|
8768
8691
|
db.exec(`
|
|
8769
|
-
CREATE TABLE IF NOT EXISTS state_meta (
|
|
8770
|
-
key TEXT PRIMARY KEY,
|
|
8771
|
-
value TEXT NOT NULL
|
|
8772
|
-
);
|
|
8773
|
-
|
|
8774
8692
|
CREATE TABLE IF NOT EXISTS bookmarks (
|
|
8775
8693
|
agent_name TEXT NOT NULL,
|
|
8776
8694
|
session_id TEXT NOT NULL,
|
|
@@ -8785,6 +8703,27 @@ function createStateSchema(db) {
|
|
|
8785
8703
|
);
|
|
8786
8704
|
`);
|
|
8787
8705
|
}
|
|
8706
|
+
function createSessionAliasesTable(db) {
|
|
8707
|
+
db.exec(`
|
|
8708
|
+
CREATE TABLE IF NOT EXISTS session_aliases (
|
|
8709
|
+
agent_name TEXT NOT NULL,
|
|
8710
|
+
session_id TEXT NOT NULL,
|
|
8711
|
+
alias TEXT NOT NULL,
|
|
8712
|
+
updated_at INTEGER NOT NULL,
|
|
8713
|
+
PRIMARY KEY (agent_name, session_id)
|
|
8714
|
+
);
|
|
8715
|
+
`);
|
|
8716
|
+
}
|
|
8717
|
+
function createStateSchema(db) {
|
|
8718
|
+
db.exec(`
|
|
8719
|
+
CREATE TABLE IF NOT EXISTS state_meta (
|
|
8720
|
+
key TEXT PRIMARY KEY,
|
|
8721
|
+
value TEXT NOT NULL
|
|
8722
|
+
);
|
|
8723
|
+
`);
|
|
8724
|
+
createBookmarksTable(db);
|
|
8725
|
+
createSessionAliasesTable(db);
|
|
8726
|
+
}
|
|
8788
8727
|
function readLegacyStateVersion(db) {
|
|
8789
8728
|
if (!tableExists(db, "state_meta") || !columnExists(db, "state_meta", "key") || !columnExists(db, "state_meta", "value")) {
|
|
8790
8729
|
return 0;
|
|
@@ -8794,13 +8733,9 @@ function readLegacyStateVersion(db) {
|
|
|
8794
8733
|
}
|
|
8795
8734
|
function getCurrentStateSchemaVersion(db) {
|
|
8796
8735
|
const userVersion = getUserVersion(db);
|
|
8797
|
-
if (userVersion > 0)
|
|
8798
|
-
return userVersion;
|
|
8799
|
-
}
|
|
8736
|
+
if (userVersion > 0) return userVersion;
|
|
8800
8737
|
const legacyVersion = readLegacyStateVersion(db);
|
|
8801
|
-
if (legacyVersion > 0)
|
|
8802
|
-
return legacyVersion;
|
|
8803
|
-
}
|
|
8738
|
+
if (legacyVersion > 0) return legacyVersion;
|
|
8804
8739
|
return tableExists(db, "bookmarks") ? 1 : 0;
|
|
8805
8740
|
}
|
|
8806
8741
|
function hasAnyStateSchema(db) {
|
|
@@ -8808,14 +8743,14 @@ function hasAnyStateSchema(db) {
|
|
|
8808
8743
|
}
|
|
8809
8744
|
function setStateSchemaVersion(db) {
|
|
8810
8745
|
createStateSchema(db);
|
|
8811
|
-
setUserVersion(db,
|
|
8746
|
+
setUserVersion(db, STATE_SCHEMA_VERSION);
|
|
8812
8747
|
db.prepare(
|
|
8813
8748
|
`
|
|
8814
8749
|
INSERT INTO state_meta(key, value)
|
|
8815
8750
|
VALUES ('version', ?)
|
|
8816
8751
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
8817
8752
|
`
|
|
8818
|
-
).run(String(
|
|
8753
|
+
).run(String(STATE_SCHEMA_VERSION));
|
|
8819
8754
|
}
|
|
8820
8755
|
function ensureSchema2(db, dbPath) {
|
|
8821
8756
|
const currentVersion = getCurrentStateSchemaVersion(db);
|
|
@@ -8826,22 +8761,22 @@ function ensureSchema2(db, dbPath) {
|
|
|
8826
8761
|
runSchemaMigrations(db, {
|
|
8827
8762
|
dbPath,
|
|
8828
8763
|
currentVersion,
|
|
8829
|
-
targetVersion:
|
|
8764
|
+
targetVersion: STATE_SCHEMA_VERSION,
|
|
8830
8765
|
backupLabel: "state-migration",
|
|
8831
|
-
backupTables: ["bookmarks"],
|
|
8832
|
-
migrations: [
|
|
8766
|
+
backupTables: ["bookmarks", "session_aliases"],
|
|
8767
|
+
migrations: [
|
|
8768
|
+
{ version: 1, migrate: createBookmarksTable },
|
|
8769
|
+
{ version: 2, migrate: createSessionAliasesTable }
|
|
8770
|
+
]
|
|
8833
8771
|
});
|
|
8834
|
-
|
|
8835
|
-
if (getUserVersion(db) <= BOOKMARK_SCHEMA_VERSION) {
|
|
8772
|
+
if (currentVersion <= STATE_SCHEMA_VERSION) {
|
|
8836
8773
|
setStateSchemaVersion(db);
|
|
8837
8774
|
}
|
|
8838
8775
|
}
|
|
8839
8776
|
function withStateDb(fn) {
|
|
8840
8777
|
const statePath = getStateDbPath();
|
|
8841
8778
|
const db = openDb(statePath);
|
|
8842
|
-
if (!db)
|
|
8843
|
-
throw new BookmarkStorageUnavailableError();
|
|
8844
|
-
}
|
|
8779
|
+
if (!db) throw new StateStorageUnavailableError();
|
|
8845
8780
|
try {
|
|
8846
8781
|
ensureSchema2(db, statePath);
|
|
8847
8782
|
return fn(db);
|
|
@@ -8849,6 +8784,31 @@ function withStateDb(fn) {
|
|
|
8849
8784
|
db.close();
|
|
8850
8785
|
}
|
|
8851
8786
|
}
|
|
8787
|
+
var memoryBookmarks = /* @__PURE__ */ new Map();
|
|
8788
|
+
function getBookmarkKey(agentKey, sessionId) {
|
|
8789
|
+
return JSON.stringify([agentKey, sessionId]);
|
|
8790
|
+
}
|
|
8791
|
+
function getActivityTime(bookmark) {
|
|
8792
|
+
return bookmark.time_updated ?? bookmark.time_created;
|
|
8793
|
+
}
|
|
8794
|
+
function sortBookmarks(bookmarks) {
|
|
8795
|
+
return bookmarks.sort((a, b) => {
|
|
8796
|
+
const activityDelta = getActivityTime(b) - getActivityTime(a);
|
|
8797
|
+
return activityDelta || b.bookmarked_at - a.bookmarked_at;
|
|
8798
|
+
});
|
|
8799
|
+
}
|
|
8800
|
+
function listMemoryBookmarks() {
|
|
8801
|
+
return sortBookmarks(Array.from(memoryBookmarks.values()));
|
|
8802
|
+
}
|
|
8803
|
+
function upsertMemoryBookmark(bookmark) {
|
|
8804
|
+
const key = getBookmarkKey(bookmark.agentKey, bookmark.sessionId);
|
|
8805
|
+
const saved = {
|
|
8806
|
+
...bookmark,
|
|
8807
|
+
bookmarked_at: memoryBookmarks.get(key)?.bookmarked_at ?? Date.now()
|
|
8808
|
+
};
|
|
8809
|
+
memoryBookmarks.set(key, saved);
|
|
8810
|
+
return saved;
|
|
8811
|
+
}
|
|
8852
8812
|
function toBookmarkRecord(row) {
|
|
8853
8813
|
return {
|
|
8854
8814
|
agentKey: String(row.agent_name ?? ""),
|
|
@@ -9021,6 +8981,78 @@ function deleteBookmark(agentKey, sessionId) {
|
|
|
9021
8981
|
).run(agentKey, sessionId);
|
|
9022
8982
|
});
|
|
9023
8983
|
}
|
|
8984
|
+
var SESSION_ALIAS_MAX_LENGTH = 160;
|
|
8985
|
+
var memoryAliases = /* @__PURE__ */ new Map();
|
|
8986
|
+
function getAliasKey(agentKey, sessionId) {
|
|
8987
|
+
return JSON.stringify([agentKey, sessionId]);
|
|
8988
|
+
}
|
|
8989
|
+
function toSessionAlias(row) {
|
|
8990
|
+
return {
|
|
8991
|
+
agentKey: String(row.agent_name ?? ""),
|
|
8992
|
+
sessionId: String(row.session_id ?? ""),
|
|
8993
|
+
alias: String(row.alias ?? ""),
|
|
8994
|
+
updated_at: Number(row.updated_at ?? 0)
|
|
8995
|
+
};
|
|
8996
|
+
}
|
|
8997
|
+
function normalizeSessionAlias(value) {
|
|
8998
|
+
const alias = value.trim();
|
|
8999
|
+
if (!alias || alias.length > SESSION_ALIAS_MAX_LENGTH) return null;
|
|
9000
|
+
return alias;
|
|
9001
|
+
}
|
|
9002
|
+
function listSessionAliases() {
|
|
9003
|
+
if (useMemoryStateStore()) return [...memoryAliases.values()];
|
|
9004
|
+
return withStateDb(
|
|
9005
|
+
(db) => db.prepare(
|
|
9006
|
+
`
|
|
9007
|
+
SELECT agent_name, session_id, alias, updated_at
|
|
9008
|
+
FROM session_aliases
|
|
9009
|
+
ORDER BY updated_at DESC
|
|
9010
|
+
`
|
|
9011
|
+
).all().map(toSessionAlias)
|
|
9012
|
+
);
|
|
9013
|
+
}
|
|
9014
|
+
function upsertSessionAlias(agentKey, sessionId, alias) {
|
|
9015
|
+
const normalizedAlias = normalizeSessionAlias(alias);
|
|
9016
|
+
if (!normalizedAlias) {
|
|
9017
|
+
throw new TypeError("Invalid session alias");
|
|
9018
|
+
}
|
|
9019
|
+
const saved = {
|
|
9020
|
+
agentKey,
|
|
9021
|
+
sessionId,
|
|
9022
|
+
alias: normalizedAlias,
|
|
9023
|
+
updated_at: Date.now()
|
|
9024
|
+
};
|
|
9025
|
+
if (useMemoryStateStore()) {
|
|
9026
|
+
memoryAliases.set(getAliasKey(agentKey, sessionId), saved);
|
|
9027
|
+
return saved;
|
|
9028
|
+
}
|
|
9029
|
+
return withStateDb((db) => {
|
|
9030
|
+
db.prepare(
|
|
9031
|
+
`
|
|
9032
|
+
INSERT INTO session_aliases(agent_name, session_id, alias, updated_at)
|
|
9033
|
+
VALUES (?, ?, ?, ?)
|
|
9034
|
+
ON CONFLICT(agent_name, session_id) DO UPDATE SET
|
|
9035
|
+
alias = excluded.alias,
|
|
9036
|
+
updated_at = excluded.updated_at
|
|
9037
|
+
`
|
|
9038
|
+
).run(saved.agentKey, saved.sessionId, saved.alias, saved.updated_at);
|
|
9039
|
+
return saved;
|
|
9040
|
+
});
|
|
9041
|
+
}
|
|
9042
|
+
function deleteSessionAlias(agentKey, sessionId) {
|
|
9043
|
+
if (useMemoryStateStore()) {
|
|
9044
|
+
memoryAliases.delete(getAliasKey(agentKey, sessionId));
|
|
9045
|
+
return;
|
|
9046
|
+
}
|
|
9047
|
+
withStateDb((db) => {
|
|
9048
|
+
db.prepare(
|
|
9049
|
+
`
|
|
9050
|
+
DELETE FROM session_aliases
|
|
9051
|
+
WHERE agent_name = ? AND session_id = ?
|
|
9052
|
+
`
|
|
9053
|
+
).run(agentKey, sessionId);
|
|
9054
|
+
});
|
|
9055
|
+
}
|
|
9024
9056
|
var DASHBOARD_RECENT_LIMIT = 10;
|
|
9025
9057
|
function getTotalTokens(stats) {
|
|
9026
9058
|
return stats.total_tokens ?? stats.total_input_tokens + stats.total_output_tokens;
|
|
@@ -9235,8 +9267,8 @@ function searchRecentSessions(snapshot, options) {
|
|
|
9235
9267
|
matchType: "recent"
|
|
9236
9268
|
}));
|
|
9237
9269
|
}
|
|
9238
|
-
function deriveFileQuery(query,
|
|
9239
|
-
return options.file ?? (!
|
|
9270
|
+
function deriveFileQuery(query, parsed, options) {
|
|
9271
|
+
return options.file ?? (!parsed.text ? parsed.filters.file : void 0) ?? (!parsed.hasQualifiers && query ? parsed.text || query : "");
|
|
9240
9272
|
}
|
|
9241
9273
|
function mergeSearchResultSources(results, limit) {
|
|
9242
9274
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -9255,8 +9287,8 @@ function canSkipSessionsSearch(fileQuery, textQuery, options) {
|
|
|
9255
9287
|
fileQuery && !textQuery && !options.tools?.length && !options.tags?.length && options.from == null && options.to == null
|
|
9256
9288
|
);
|
|
9257
9289
|
}
|
|
9258
|
-
function searchIndexedSessions(query, textQuery,
|
|
9259
|
-
const fileQuery = deriveFileQuery(query,
|
|
9290
|
+
function searchIndexedSessions(query, textQuery, parsed, options) {
|
|
9291
|
+
const fileQuery = deriveFileQuery(query, parsed, options);
|
|
9260
9292
|
const fileResults = fileQuery ? searchFileActivitySessions(fileQuery, options) : [];
|
|
9261
9293
|
const sessionResults = canSkipSessionsSearch(fileQuery, textQuery, options) ? [] : searchSessions(query, options);
|
|
9262
9294
|
return mergeSearchResultSources([...fileResults, ...sessionResults], options.limit ?? 50);
|
|
@@ -9286,16 +9318,12 @@ export {
|
|
|
9286
9318
|
normalizeTitleText,
|
|
9287
9319
|
basenameTitle,
|
|
9288
9320
|
resolveSessionTitle,
|
|
9289
|
-
parsed,
|
|
9290
|
-
skipped,
|
|
9291
|
-
filtered,
|
|
9292
9321
|
cleanInternalText,
|
|
9293
9322
|
cleanMessagePart,
|
|
9294
9323
|
cleanMessageParts,
|
|
9295
9324
|
cleanParsedMessage,
|
|
9296
9325
|
cleanParsedMessages,
|
|
9297
9326
|
firstUserMessageTitle,
|
|
9298
|
-
perf,
|
|
9299
9327
|
getPricingRegistry,
|
|
9300
9328
|
hasBillablePricing,
|
|
9301
9329
|
refreshPricingCache,
|
|
@@ -9308,6 +9336,7 @@ export {
|
|
|
9308
9336
|
openDbReadOnly,
|
|
9309
9337
|
openDb,
|
|
9310
9338
|
isSqliteAvailable,
|
|
9339
|
+
perf,
|
|
9311
9340
|
fallbackDisplayName,
|
|
9312
9341
|
realFs,
|
|
9313
9342
|
isProjectIdentityKind,
|
|
@@ -9329,6 +9358,7 @@ export {
|
|
|
9329
9358
|
parseSearchQuery,
|
|
9330
9359
|
syncSessionSearchIndex,
|
|
9331
9360
|
syncSessionSearchIndexChanges,
|
|
9361
|
+
mergeSearchQueryOptions,
|
|
9332
9362
|
searchSessions,
|
|
9333
9363
|
listFileActivity,
|
|
9334
9364
|
listSessionFileActivity,
|
|
@@ -9353,11 +9383,16 @@ export {
|
|
|
9353
9383
|
ensureSessionTagsSync,
|
|
9354
9384
|
scanSessions,
|
|
9355
9385
|
scanSessionsAsync,
|
|
9356
|
-
|
|
9386
|
+
StateStorageUnavailableError,
|
|
9357
9387
|
listBookmarks,
|
|
9358
9388
|
upsertBookmark,
|
|
9359
9389
|
importBookmarks,
|
|
9360
9390
|
deleteBookmark,
|
|
9391
|
+
SESSION_ALIAS_MAX_LENGTH,
|
|
9392
|
+
normalizeSessionAlias,
|
|
9393
|
+
listSessionAliases,
|
|
9394
|
+
upsertSessionAlias,
|
|
9395
|
+
deleteSessionAlias,
|
|
9361
9396
|
DASHBOARD_RECENT_LIMIT,
|
|
9362
9397
|
getTotalTokens,
|
|
9363
9398
|
getSessionAgentName,
|
|
@@ -9367,4 +9402,4 @@ export {
|
|
|
9367
9402
|
buildDashboard,
|
|
9368
9403
|
executeSessionSearch
|
|
9369
9404
|
};
|
|
9370
|
-
//# sourceMappingURL=chunk-
|
|
9405
|
+
//# sourceMappingURL=chunk-NBCLV4CX.js.map
|