codesesh 0.13.0 → 0.14.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-VRVZJDNL.js} +893 -1190
- package/dist/chunk-VRVZJDNL.js.map +1 -0
- package/dist/{dist-VD54GDPO.js → dist-C3KC3XKJ.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-BNLxu3RT.js +113 -0
- package/dist/web/assets/index-BYElqfX-.css +2 -0
- package/dist/web/assets/react-3acXkZNw.js +1821 -0
- package/dist/web/assets/vendor-Lx2mL9a6.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-C3KC3XKJ.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,23 @@ 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();
|
|
1061
|
+
const builder = new TranscriptBuilder();
|
|
992
1062
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
993
1063
|
const assistantUuidToToolCalls = /* @__PURE__ */ new Map();
|
|
994
1064
|
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
1065
|
for (const record of parseJsonlLines(content)) {
|
|
1005
1066
|
try {
|
|
1006
1067
|
this.convertRecord(
|
|
1007
1068
|
record,
|
|
1008
|
-
|
|
1009
|
-
pendingToolCalls,
|
|
1069
|
+
builder,
|
|
1010
1070
|
ignoredToolCallIds,
|
|
1011
1071
|
assistantUuidToToolCalls,
|
|
1012
|
-
countedUsageKeys
|
|
1013
|
-
assistantState
|
|
1072
|
+
countedUsageKeys
|
|
1014
1073
|
);
|
|
1015
1074
|
} catch {
|
|
1016
1075
|
}
|
|
1017
1076
|
}
|
|
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
|
-
}
|
|
1077
|
+
const transcript = builder.finish();
|
|
1026
1078
|
return {
|
|
1027
1079
|
id: meta.id,
|
|
1028
1080
|
title: meta.title,
|
|
@@ -1031,16 +1083,8 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1031
1083
|
version: void 0,
|
|
1032
1084
|
time_created: meta.createdAt,
|
|
1033
1085
|
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
|
|
1086
|
+
stats: transcript.stats,
|
|
1087
|
+
messages: transcript.messages
|
|
1044
1088
|
};
|
|
1045
1089
|
}
|
|
1046
1090
|
// --- Private helpers ---
|
|
@@ -1251,41 +1295,30 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1251
1295
|
return null;
|
|
1252
1296
|
}
|
|
1253
1297
|
// --- Record conversion ---
|
|
1254
|
-
convertRecord(data,
|
|
1298
|
+
convertRecord(data, builder, ignoredToolCallIds, assistantUuidToToolCalls, countedUsageKeys) {
|
|
1255
1299
|
if (data["isMeta"] === true) return;
|
|
1256
1300
|
const msgType = String(data["type"] ?? "");
|
|
1257
1301
|
if (isInternalEventType(msgType)) return;
|
|
1258
1302
|
if (msgType === "assistant") {
|
|
1259
1303
|
this.convertAssistantRecord(
|
|
1260
1304
|
data,
|
|
1261
|
-
|
|
1262
|
-
pendingToolCalls,
|
|
1305
|
+
builder,
|
|
1263
1306
|
ignoredToolCallIds,
|
|
1264
1307
|
assistantUuidToToolCalls,
|
|
1265
|
-
countedUsageKeys
|
|
1266
|
-
assistantState
|
|
1308
|
+
countedUsageKeys
|
|
1267
1309
|
);
|
|
1268
1310
|
} else if (msgType === "user") {
|
|
1269
|
-
this.convertUserRecord(
|
|
1270
|
-
data,
|
|
1271
|
-
messages,
|
|
1272
|
-
pendingToolCalls,
|
|
1273
|
-
ignoredToolCallIds,
|
|
1274
|
-
assistantUuidToToolCalls,
|
|
1275
|
-
assistantState
|
|
1276
|
-
);
|
|
1311
|
+
this.convertUserRecord(data, builder, ignoredToolCallIds, assistantUuidToToolCalls);
|
|
1277
1312
|
} else if (msgType === "tool_result") {
|
|
1278
|
-
this.convertToolResultRecord(data,
|
|
1313
|
+
this.convertToolResultRecord(data, builder);
|
|
1279
1314
|
}
|
|
1280
1315
|
}
|
|
1281
|
-
convertAssistantRecord(data,
|
|
1316
|
+
convertAssistantRecord(data, builder, ignoredToolCallIds, assistantUuidToToolCalls, countedUsageKeys) {
|
|
1282
1317
|
const msg = data["message"] ?? {};
|
|
1283
1318
|
const timestampMs = parseTimestampMs(data);
|
|
1284
1319
|
const rawContent = msg["content"] ?? [];
|
|
1285
1320
|
const uuid = String(data["uuid"] ?? "");
|
|
1286
1321
|
const toolCallIds = [];
|
|
1287
|
-
let currentAssistantIndex = assistantState.currentIndex;
|
|
1288
|
-
let latestAssistantTextIndex = assistantState.latestTextIndex;
|
|
1289
1322
|
if (Array.isArray(rawContent)) {
|
|
1290
1323
|
for (const item of rawContent) {
|
|
1291
1324
|
if (!item || typeof item !== "object") continue;
|
|
@@ -1294,23 +1327,28 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1294
1327
|
if (partType === "thinking") {
|
|
1295
1328
|
const text = cleanInternalText(String(part["thinking"] ?? ""));
|
|
1296
1329
|
if (text) {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
{
|
|
1300
|
-
|
|
1330
|
+
const message2 = builder.appendAssistantPart(
|
|
1331
|
+
this.buildReasoningPart(text, timestampMs),
|
|
1332
|
+
{ id: uuid, timestampMs, agent: "claude" },
|
|
1333
|
+
{ deduplicateTail: true }
|
|
1301
1334
|
);
|
|
1335
|
+
this.applyAssistantMetadata(message2, data, msg, countedUsageKeys);
|
|
1302
1336
|
}
|
|
1303
1337
|
continue;
|
|
1304
1338
|
}
|
|
1305
1339
|
if (partType === "text") {
|
|
1306
1340
|
const text = cleanInternalText(String(part["text"] ?? ""));
|
|
1307
1341
|
if (text) {
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
{
|
|
1311
|
-
|
|
1342
|
+
const message2 = builder.appendAssistantPart(
|
|
1343
|
+
this.buildTextPart(text, timestampMs),
|
|
1344
|
+
{
|
|
1345
|
+
id: uuid,
|
|
1346
|
+
timestampMs,
|
|
1347
|
+
agent: "claude"
|
|
1348
|
+
},
|
|
1349
|
+
{ deduplicateTail: true }
|
|
1312
1350
|
);
|
|
1313
|
-
|
|
1351
|
+
this.applyAssistantMetadata(message2, data, msg, countedUsageKeys);
|
|
1314
1352
|
}
|
|
1315
1353
|
continue;
|
|
1316
1354
|
}
|
|
@@ -1322,18 +1360,13 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1322
1360
|
continue;
|
|
1323
1361
|
}
|
|
1324
1362
|
const toolPart = this.buildToolPart(part, timestampMs);
|
|
1325
|
-
const
|
|
1326
|
-
messageId: uuid,
|
|
1327
|
-
data,
|
|
1328
|
-
msg,
|
|
1329
|
-
timestampMs,
|
|
1363
|
+
const message = builder.appendToolCall(
|
|
1330
1364
|
toolPart,
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1365
|
+
{ id: uuid, timestampMs, agent: "claude" },
|
|
1366
|
+
{ modeOnCreate: "tool" }
|
|
1367
|
+
);
|
|
1368
|
+
this.applyAssistantMetadata(message, data, msg, countedUsageKeys);
|
|
1335
1369
|
if (toolCallId) {
|
|
1336
|
-
pendingToolCalls.set(toolCallId, [msgIndex, partIndex]);
|
|
1337
1370
|
toolCallIds.push(toolCallId);
|
|
1338
1371
|
}
|
|
1339
1372
|
}
|
|
@@ -1341,10 +1374,8 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1341
1374
|
if (toolCallIds.length > 0) {
|
|
1342
1375
|
assistantUuidToToolCalls.set(uuid, toolCallIds);
|
|
1343
1376
|
}
|
|
1344
|
-
assistantState.currentIndex = currentAssistantIndex;
|
|
1345
|
-
assistantState.latestTextIndex = latestAssistantTextIndex;
|
|
1346
1377
|
}
|
|
1347
|
-
convertUserRecord(data,
|
|
1378
|
+
convertUserRecord(data, builder, ignoredToolCallIds, assistantUuidToToolCalls) {
|
|
1348
1379
|
const msg = data["message"] ?? {};
|
|
1349
1380
|
const timestampMs = parseTimestampMs(data);
|
|
1350
1381
|
const content = msg["content"] ?? "";
|
|
@@ -1352,18 +1383,14 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1352
1383
|
if (typeof content === "string") {
|
|
1353
1384
|
const parts = this.normalizeUserTextParts(content, timestampMs);
|
|
1354
1385
|
if (parts.length === 0) {
|
|
1355
|
-
|
|
1356
|
-
assistantState.latestTextIndex = null;
|
|
1386
|
+
builder.beginTurn();
|
|
1357
1387
|
return;
|
|
1358
1388
|
}
|
|
1359
|
-
|
|
1360
|
-
assistantState.currentIndex = null;
|
|
1361
|
-
assistantState.latestTextIndex = null;
|
|
1389
|
+
builder.appendMessage({ id: uuid, role: "user", timestampMs, parts });
|
|
1362
1390
|
return;
|
|
1363
1391
|
}
|
|
1364
1392
|
if (!Array.isArray(content)) {
|
|
1365
|
-
|
|
1366
|
-
assistantState.latestTextIndex = null;
|
|
1393
|
+
builder.beginTurn();
|
|
1367
1394
|
return;
|
|
1368
1395
|
}
|
|
1369
1396
|
const visibleParts = this.normalizeUserTextParts(content, timestampMs);
|
|
@@ -1375,13 +1402,7 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1375
1402
|
const toolCallId = this.resolveToolCallId(data, ci, assistantUuidToToolCalls);
|
|
1376
1403
|
if (toolCallId && ignoredToolCallIds.has(toolCallId)) continue;
|
|
1377
1404
|
const outputParts = this.normalizeClaudeToolOutput(ci["content"], timestampMs);
|
|
1378
|
-
if (this.backfillToolOutput(
|
|
1379
|
-
messages,
|
|
1380
|
-
pendingToolCalls,
|
|
1381
|
-
toolCallId,
|
|
1382
|
-
outputParts,
|
|
1383
|
-
toolStateUpdates
|
|
1384
|
-
)) {
|
|
1405
|
+
if (this.backfillToolOutput(builder, toolCallId, outputParts, toolStateUpdates)) {
|
|
1385
1406
|
continue;
|
|
1386
1407
|
}
|
|
1387
1408
|
const fallback = this.buildFallbackToolMessage({
|
|
@@ -1390,17 +1411,14 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1390
1411
|
toolCallId,
|
|
1391
1412
|
outputParts
|
|
1392
1413
|
});
|
|
1393
|
-
if (fallback)
|
|
1414
|
+
if (fallback) builder.appendMessage(fallback);
|
|
1394
1415
|
}
|
|
1395
1416
|
if (visibleParts.length > 0) {
|
|
1396
|
-
|
|
1397
|
-
this.buildMessage({ messageId: uuid, role: "user", timestampMs, parts: visibleParts })
|
|
1398
|
-
);
|
|
1417
|
+
builder.appendMessage({ id: uuid, role: "user", timestampMs, parts: visibleParts });
|
|
1399
1418
|
}
|
|
1400
|
-
|
|
1401
|
-
assistantState.latestTextIndex = null;
|
|
1419
|
+
builder.beginTurn();
|
|
1402
1420
|
}
|
|
1403
|
-
convertToolResultRecord(data,
|
|
1421
|
+
convertToolResultRecord(data, builder) {
|
|
1404
1422
|
const timestampMs = parseTimestampMs(data);
|
|
1405
1423
|
const msg = data["message"] ?? {};
|
|
1406
1424
|
const outputParts = this.normalizeClaudeToolOutput(msg["content"], timestampMs);
|
|
@@ -1411,25 +1429,8 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1411
1429
|
toolCallId: null,
|
|
1412
1430
|
outputParts
|
|
1413
1431
|
});
|
|
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
|
-
};
|
|
1432
|
+
if (fallback) builder.appendMessage(fallback);
|
|
1433
|
+
builder.beginTurn();
|
|
1433
1434
|
}
|
|
1434
1435
|
buildTextPart(text, timestampMs) {
|
|
1435
1436
|
return { type: "text", text, time_created: timestampMs };
|
|
@@ -1472,71 +1473,6 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1472
1473
|
}
|
|
1473
1474
|
}
|
|
1474
1475
|
}
|
|
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
1476
|
// --- User content normalization ---
|
|
1541
1477
|
normalizeUserTextParts(content, timestampMs) {
|
|
1542
1478
|
if (typeof content === "string") {
|
|
@@ -1584,29 +1520,19 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1584
1520
|
return text ? [this.buildTextPart(text, timestampMs)] : [];
|
|
1585
1521
|
}
|
|
1586
1522
|
// --- Tool backfill ---
|
|
1587
|
-
backfillToolOutput(
|
|
1523
|
+
backfillToolOutput(builder, callId, outputParts, stateUpdates) {
|
|
1588
1524
|
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];
|
|
1525
|
+
return builder.updateToolCall(callId, (part) => {
|
|
1526
|
+
const state = part.state ?? (part.state = {});
|
|
1527
|
+
if (outputParts.length > 0) {
|
|
1528
|
+
const existing = state.output;
|
|
1529
|
+
if (Array.isArray(existing)) existing.push(...outputParts);
|
|
1530
|
+
else if (existing == null) state.output = [...outputParts];
|
|
1531
|
+
else state.output = [existing, ...outputParts];
|
|
1601
1532
|
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
}
|
|
1606
|
-
if (outputParts.length > 0 && !state.status) {
|
|
1607
|
-
state.status = "completed";
|
|
1608
|
-
}
|
|
1609
|
-
return outputParts.length > 0 || !!stateUpdates;
|
|
1533
|
+
if (stateUpdates) Object.assign(state, stateUpdates);
|
|
1534
|
+
if (outputParts.length > 0 && !state.status) state.status = "completed";
|
|
1535
|
+
});
|
|
1610
1536
|
}
|
|
1611
1537
|
resolveToolCallId(data, item, assistantUuidToToolCalls) {
|
|
1612
1538
|
const directId = String(item["tool_use_id"] ?? "").trim();
|
|
@@ -1634,25 +1560,17 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1634
1560
|
// --- Fallback ---
|
|
1635
1561
|
buildFallbackToolMessage(opts) {
|
|
1636
1562
|
if (opts.outputParts.length === 0) return null;
|
|
1637
|
-
return
|
|
1638
|
-
|
|
1563
|
+
return {
|
|
1564
|
+
id: opts.messageId,
|
|
1639
1565
|
role: "tool",
|
|
1640
1566
|
timestampMs: opts.timestampMs,
|
|
1641
1567
|
parts: opts.outputParts
|
|
1642
|
-
}
|
|
1568
|
+
};
|
|
1643
1569
|
}
|
|
1644
1570
|
// --- Utilities ---
|
|
1645
1571
|
shouldIgnoreTool(toolName) {
|
|
1646
1572
|
return toolName === "TodoWrite";
|
|
1647
1573
|
}
|
|
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);
|
|
1655
|
-
}
|
|
1656
1574
|
};
|
|
1657
1575
|
var DatabaseConstructor = null;
|
|
1658
1576
|
try {
|
|
@@ -2318,50 +2236,6 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2318
2236
|
return skippedSession("malformed metadata");
|
|
2319
2237
|
}
|
|
2320
2238
|
}
|
|
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
2239
|
listSessionSources(options) {
|
|
2366
2240
|
if (!this.basePath) return [];
|
|
2367
2241
|
const refs = [];
|
|
@@ -2403,8 +2277,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2403
2277
|
getSessionDataFromContext(meta) {
|
|
2404
2278
|
if (!meta.contextFile) throw new Error("context.jsonl is missing");
|
|
2405
2279
|
const content = readFileSync3(meta.contextFile, "utf-8");
|
|
2406
|
-
const
|
|
2407
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2280
|
+
const builder = new TranscriptBuilder();
|
|
2408
2281
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
2409
2282
|
let seq = 0;
|
|
2410
2283
|
const fallbackTs = meta.createdAt;
|
|
@@ -2416,65 +2289,55 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2416
2289
|
if (role === "user") {
|
|
2417
2290
|
const text = cleanInternalText(kimiContentText(record.content));
|
|
2418
2291
|
if (text) {
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
})
|
|
2426
|
-
);
|
|
2292
|
+
builder.appendMessage({
|
|
2293
|
+
id: `context-${seq}`,
|
|
2294
|
+
role: "user",
|
|
2295
|
+
timestampMs: fallbackTs,
|
|
2296
|
+
parts: [{ type: "text", text, time_created: fallbackTs }]
|
|
2297
|
+
});
|
|
2427
2298
|
}
|
|
2428
2299
|
continue;
|
|
2429
2300
|
}
|
|
2430
2301
|
if (role === "assistant") {
|
|
2431
|
-
const
|
|
2302
|
+
const message = this.buildContextAssistantMessage(
|
|
2432
2303
|
record,
|
|
2433
2304
|
seq,
|
|
2434
2305
|
ignoredToolCallIds,
|
|
2435
2306
|
fallbackTs
|
|
2436
2307
|
);
|
|
2437
2308
|
if (!message) continue;
|
|
2438
|
-
|
|
2439
|
-
messages.push(message);
|
|
2440
|
-
for (const [callId, partIndex] of toolIndexes) {
|
|
2441
|
-
pendingToolCalls.set(callId, [msgIndex, partIndex]);
|
|
2442
|
-
}
|
|
2309
|
+
builder.appendMessage(message);
|
|
2443
2310
|
continue;
|
|
2444
2311
|
}
|
|
2445
2312
|
if (role === "tool") {
|
|
2446
2313
|
const callId = String(record.tool_call_id ?? "").trim();
|
|
2447
2314
|
if (callId && ignoredToolCallIds.has(callId)) continue;
|
|
2448
2315
|
const outputParts = normalizeToolOutputParts(record.content, fallbackTs);
|
|
2449
|
-
if (callId && this.backfillToolOutput(
|
|
2316
|
+
if (callId && this.backfillToolOutput(builder, callId, outputParts)) {
|
|
2450
2317
|
continue;
|
|
2451
2318
|
}
|
|
2452
2319
|
if (outputParts.length > 0) {
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
})
|
|
2460
|
-
);
|
|
2320
|
+
builder.appendMessage({
|
|
2321
|
+
id: `context-${seq}`,
|
|
2322
|
+
role: "tool",
|
|
2323
|
+
timestampMs: fallbackTs,
|
|
2324
|
+
parts: outputParts
|
|
2325
|
+
});
|
|
2461
2326
|
}
|
|
2462
2327
|
}
|
|
2463
2328
|
} catch {
|
|
2464
2329
|
}
|
|
2465
2330
|
}
|
|
2466
2331
|
const stats = this.extractStats(meta.sourcePath);
|
|
2467
|
-
return this.buildSessionData(meta,
|
|
2332
|
+
return this.buildSessionData(meta, builder, stats);
|
|
2468
2333
|
}
|
|
2469
2334
|
getSessionDataFromWire(meta) {
|
|
2470
2335
|
const wirePath = meta.wireFile ?? join6(meta.sourcePath, "wire.jsonl");
|
|
2471
2336
|
if (!existsSync6(wirePath)) throw new Error("wire.jsonl is missing");
|
|
2472
2337
|
const content = readFileSync3(wirePath, "utf-8");
|
|
2473
|
-
const
|
|
2474
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2338
|
+
const builder = new TranscriptBuilder();
|
|
2475
2339
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
2476
2340
|
const openToolArgumentBuffer = /* @__PURE__ */ new Map();
|
|
2477
|
-
let currentAssistantIndex = null;
|
|
2478
2341
|
let openToolCallId = null;
|
|
2479
2342
|
let seq = 0;
|
|
2480
2343
|
for (const record of parseJsonlLines(content)) {
|
|
@@ -2491,19 +2354,13 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2491
2354
|
const inputTokens = Number(usage["input_tokens"] ?? 0);
|
|
2492
2355
|
const outputTokens = Number(usage["output_tokens"] ?? 0);
|
|
2493
2356
|
if (inputTokens || outputTokens) {
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
msg.cost = cost;
|
|
2502
|
-
msg.cost_source = "estimated";
|
|
2503
|
-
}
|
|
2504
|
-
break;
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2357
|
+
const tokens = { input: inputTokens, output: outputTokens };
|
|
2358
|
+
const cost = estimateTokenCost(this.defaultModel, tokens);
|
|
2359
|
+
builder.attachUsageToLatestAssistant(tokens, {
|
|
2360
|
+
model: this.defaultModel,
|
|
2361
|
+
cost: cost ?? void 0,
|
|
2362
|
+
costSource: cost === null ? void 0 : "estimated"
|
|
2363
|
+
});
|
|
2507
2364
|
}
|
|
2508
2365
|
}
|
|
2509
2366
|
if (msgType === "TurnBegin") {
|
|
@@ -2511,37 +2368,37 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2511
2368
|
if (Array.isArray(userInput) && userInput.length > 0) {
|
|
2512
2369
|
const text = cleanInternalText(kimiContentText(userInput));
|
|
2513
2370
|
if (text) {
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
})
|
|
2521
|
-
);
|
|
2371
|
+
builder.appendMessage({
|
|
2372
|
+
id: `wire-${seq}`,
|
|
2373
|
+
role: "user",
|
|
2374
|
+
timestampMs,
|
|
2375
|
+
parts: [{ type: "text", text, time_created: timestampMs }]
|
|
2376
|
+
});
|
|
2522
2377
|
}
|
|
2523
2378
|
}
|
|
2524
|
-
|
|
2379
|
+
builder.beginTurn();
|
|
2525
2380
|
openToolCallId = null;
|
|
2526
2381
|
continue;
|
|
2527
2382
|
}
|
|
2528
2383
|
if (msgType === "ContentPart") {
|
|
2529
|
-
currentAssistantIndex = this.getOrCreateWireAssistant(
|
|
2530
|
-
messages,
|
|
2531
|
-
currentAssistantIndex,
|
|
2532
|
-
`wire-${seq}`
|
|
2533
|
-
);
|
|
2534
|
-
const assistant = messages[currentAssistantIndex];
|
|
2535
2384
|
const partType = String(payload.type ?? "");
|
|
2536
2385
|
if (partType === "think") {
|
|
2537
2386
|
const text = cleanInternalText(String(payload.think ?? ""));
|
|
2538
2387
|
if (text) {
|
|
2539
|
-
|
|
2388
|
+
builder.appendAssistantPart(
|
|
2389
|
+
{ type: "reasoning", text, time_created: timestampMs },
|
|
2390
|
+
{ id: `wire-${seq}`, timestampMs: 0, agent: "kimi" },
|
|
2391
|
+
{ grouping: "current" }
|
|
2392
|
+
);
|
|
2540
2393
|
}
|
|
2541
2394
|
} else if (partType === "text") {
|
|
2542
2395
|
const text = cleanInternalText(String(payload.text ?? ""));
|
|
2543
2396
|
if (text) {
|
|
2544
|
-
|
|
2397
|
+
builder.appendAssistantPart(
|
|
2398
|
+
{ type: "text", text, time_created: timestampMs },
|
|
2399
|
+
{ id: `wire-${seq}`, timestampMs: 0, agent: "kimi" },
|
|
2400
|
+
{ grouping: "current" }
|
|
2401
|
+
);
|
|
2545
2402
|
}
|
|
2546
2403
|
}
|
|
2547
2404
|
continue;
|
|
@@ -2556,12 +2413,6 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2556
2413
|
continue;
|
|
2557
2414
|
}
|
|
2558
2415
|
if (!function_ || !callId || !toolName) continue;
|
|
2559
|
-
currentAssistantIndex = this.getOrCreateWireAssistant(
|
|
2560
|
-
messages,
|
|
2561
|
-
currentAssistantIndex,
|
|
2562
|
-
`wire-${seq}`
|
|
2563
|
-
);
|
|
2564
|
-
const assistant = messages[currentAssistantIndex];
|
|
2565
2416
|
const rawArgs = function_.arguments;
|
|
2566
2417
|
const normalizedArgs = normalizeToolArguments(rawArgs);
|
|
2567
2418
|
const buffer = typeof rawArgs === "string" && typeof normalizedArgs !== "string" ? rawArgs : null;
|
|
@@ -2573,10 +2424,11 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2573
2424
|
state: { arguments: normalizedArgs, output: null },
|
|
2574
2425
|
time_created: timestampMs
|
|
2575
2426
|
};
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2427
|
+
builder.appendToolCall(
|
|
2428
|
+
toolPart,
|
|
2429
|
+
{ id: `wire-${seq}`, timestampMs: 0, agent: "kimi" },
|
|
2430
|
+
{ markModeAsTool: true, target: "current" }
|
|
2431
|
+
);
|
|
2580
2432
|
openToolCallId = callId;
|
|
2581
2433
|
if (buffer !== null) {
|
|
2582
2434
|
openToolArgumentBuffer.set(callId, buffer);
|
|
@@ -2590,8 +2442,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2590
2442
|
argumentsPart,
|
|
2591
2443
|
openToolCallId,
|
|
2592
2444
|
openToolArgumentBuffer,
|
|
2593
|
-
|
|
2594
|
-
pendingToolCalls
|
|
2445
|
+
builder
|
|
2595
2446
|
);
|
|
2596
2447
|
continue;
|
|
2597
2448
|
}
|
|
@@ -2599,27 +2450,24 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2599
2450
|
const callId = String(payload.tool_call_id ?? "").trim();
|
|
2600
2451
|
if (callId && ignoredToolCallIds.has(callId)) continue;
|
|
2601
2452
|
const outputParts = normalizeWireToolOutputParts(payload.return_value, timestampMs);
|
|
2602
|
-
if (callId && this.backfillToolOutput(
|
|
2453
|
+
if (callId && this.backfillToolOutput(builder, callId, outputParts)) {
|
|
2603
2454
|
continue;
|
|
2604
2455
|
}
|
|
2605
2456
|
if (outputParts.length > 0) {
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
})
|
|
2613
|
-
);
|
|
2457
|
+
builder.appendMessage({
|
|
2458
|
+
id: `wire-${seq}`,
|
|
2459
|
+
role: "tool",
|
|
2460
|
+
timestampMs,
|
|
2461
|
+
parts: outputParts
|
|
2462
|
+
});
|
|
2614
2463
|
}
|
|
2615
2464
|
continue;
|
|
2616
2465
|
}
|
|
2617
2466
|
} catch {
|
|
2618
2467
|
}
|
|
2619
2468
|
}
|
|
2620
|
-
const filteredMessages = messages.filter((m) => m.parts.length > 0);
|
|
2621
2469
|
const stats = this.extractStats(meta.sourcePath);
|
|
2622
|
-
return this.buildSessionData(meta,
|
|
2470
|
+
return this.buildSessionData(meta, builder, stats);
|
|
2623
2471
|
}
|
|
2624
2472
|
// --- Helpers ---
|
|
2625
2473
|
sourceFingerprint(meta) {
|
|
@@ -2637,23 +2485,8 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2637
2485
|
fileMtime(meta.wireFile)
|
|
2638
2486
|
]);
|
|
2639
2487
|
}
|
|
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
2488
|
buildContextAssistantMessage(record, seq, ignoredToolCallIds, fallbackTs) {
|
|
2655
2489
|
const parts = [];
|
|
2656
|
-
const toolIndexes = /* @__PURE__ */ new Map();
|
|
2657
2490
|
const content = record.content;
|
|
2658
2491
|
if (Array.isArray(content)) {
|
|
2659
2492
|
for (const item of content) {
|
|
@@ -2691,71 +2524,41 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2691
2524
|
state: { arguments: normalizeToolArguments(function_.arguments), output: null },
|
|
2692
2525
|
time_created: fallbackTs
|
|
2693
2526
|
};
|
|
2694
|
-
toolIndexes.set(callId, parts.length);
|
|
2695
2527
|
parts.push(part);
|
|
2696
2528
|
}
|
|
2697
2529
|
}
|
|
2698
2530
|
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
|
-
};
|
|
2531
|
+
return null;
|
|
2708
2532
|
}
|
|
2709
2533
|
const allTools = parts.every((p) => p.type === "tool");
|
|
2710
|
-
|
|
2711
|
-
|
|
2534
|
+
return {
|
|
2535
|
+
id: `context-${seq}`,
|
|
2712
2536
|
role: "assistant",
|
|
2713
2537
|
timestampMs: fallbackTs,
|
|
2714
2538
|
parts,
|
|
2715
2539
|
agent: "kimi",
|
|
2716
2540
|
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;
|
|
2541
|
+
};
|
|
2732
2542
|
}
|
|
2733
|
-
appendWireToolCallPart(argumentsPart, openCallId, buffer,
|
|
2734
|
-
if (!openCallId
|
|
2543
|
+
appendWireToolCallPart(argumentsPart, openCallId, buffer, builder) {
|
|
2544
|
+
if (!openCallId) return;
|
|
2735
2545
|
const existing = buffer.get(openCallId) ?? "";
|
|
2736
2546
|
const combined = existing + argumentsPart;
|
|
2737
2547
|
try {
|
|
2738
|
-
const
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2548
|
+
const parsed = JSON.parse(combined);
|
|
2549
|
+
if (builder.updateToolCall(openCallId, (part) => {
|
|
2550
|
+
const state = part.state ?? (part.state = {});
|
|
2551
|
+
state.arguments = parsed;
|
|
2552
|
+
})) {
|
|
2553
|
+
buffer.delete(openCallId);
|
|
2744
2554
|
}
|
|
2745
|
-
buffer.delete(openCallId);
|
|
2746
2555
|
} catch {
|
|
2747
2556
|
buffer.set(openCallId, combined);
|
|
2748
2557
|
}
|
|
2749
2558
|
}
|
|
2750
|
-
backfillToolOutput(
|
|
2559
|
+
backfillToolOutput(builder, callId, outputParts) {
|
|
2751
2560
|
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;
|
|
2561
|
+
return builder.resolveToolCall(callId, { output: [...outputParts] });
|
|
2759
2562
|
}
|
|
2760
2563
|
extractStats(sessionDir) {
|
|
2761
2564
|
let totalCost = 0;
|
|
@@ -2811,14 +2614,8 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2811
2614
|
}
|
|
2812
2615
|
return stats;
|
|
2813
2616
|
}
|
|
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
|
-
}
|
|
2617
|
+
buildSessionData(meta, builder, stats) {
|
|
2618
|
+
const transcript = builder.finish(stats);
|
|
2822
2619
|
return {
|
|
2823
2620
|
id: meta.id,
|
|
2824
2621
|
title: meta.title,
|
|
@@ -2826,8 +2623,8 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2826
2623
|
directory: meta.cwd,
|
|
2827
2624
|
time_created: meta.createdAt,
|
|
2828
2625
|
time_updated: meta.createdAt,
|
|
2829
|
-
stats,
|
|
2830
|
-
messages:
|
|
2626
|
+
stats: transcript.stats,
|
|
2627
|
+
messages: transcript.messages
|
|
2831
2628
|
};
|
|
2832
2629
|
}
|
|
2833
2630
|
};
|
|
@@ -3015,36 +2812,6 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3015
2812
|
return false;
|
|
3016
2813
|
}
|
|
3017
2814
|
}
|
|
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
2815
|
listSessionSources(options) {
|
|
3049
2816
|
if (!this.basePath) return [];
|
|
3050
2817
|
this.loadSessionIndex();
|
|
@@ -3054,9 +2821,9 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3054
2821
|
fingerprint: this.sourceFingerprint(file)
|
|
3055
2822
|
}));
|
|
3056
2823
|
}
|
|
3057
|
-
scanSessionSource(sourcePath) {
|
|
2824
|
+
scanSessionSource(sourcePath, options) {
|
|
3058
2825
|
this.loadSessionIndex();
|
|
3059
|
-
const head = getParsedSession(this.parseSessionHeadResult(sourcePath));
|
|
2826
|
+
const head = getParsedSession(this.parseSessionHeadResult(sourcePath, options));
|
|
3060
2827
|
if (head) {
|
|
3061
2828
|
this.sessionMetaMap.set(head.id, this.buildSessionMeta(head, sourcePath));
|
|
3062
2829
|
}
|
|
@@ -3066,14 +2833,11 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3066
2833
|
const meta = this.sessionMetaMap.get(sessionId);
|
|
3067
2834
|
if (!meta) throw new Error(`Session not found: ${sessionId}`);
|
|
3068
2835
|
if (!existsSync7(meta.sourcePath)) throw new Error(`Session file missing: ${meta.sourcePath}`);
|
|
3069
|
-
const
|
|
3070
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2836
|
+
const transcript = new TranscriptBuilder();
|
|
3071
2837
|
let totalInputTokens = 0;
|
|
3072
2838
|
let totalOutputTokens = 0;
|
|
3073
2839
|
let totalCacheReadTokens = 0;
|
|
3074
2840
|
let totalCost = 0;
|
|
3075
|
-
let currentAssistantIndex = null;
|
|
3076
|
-
let latestAssistantTextIndex = null;
|
|
3077
2841
|
let pendingPlan = null;
|
|
3078
2842
|
let activeModel = meta.model;
|
|
3079
2843
|
let prevCumulativeTotal = 0;
|
|
@@ -3088,24 +2852,7 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3088
2852
|
const payload = record["payload"] ?? {};
|
|
3089
2853
|
activeModel = extractModelName(payload["model"]) ?? activeModel;
|
|
3090
2854
|
}
|
|
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
|
-
}
|
|
2855
|
+
pendingPlan = this.convertRecord(record, transcript, pendingPlan, activeModel);
|
|
3109
2856
|
if (recordType === "event_msg") {
|
|
3110
2857
|
const payload = record["payload"] ?? {};
|
|
3111
2858
|
if (String(payload["type"] ?? "") === "token_count") {
|
|
@@ -3141,24 +2888,19 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3141
2888
|
totalInputTokens += totalInput;
|
|
3142
2889
|
totalOutputTokens += outputTokens + reasoningTokens;
|
|
3143
2890
|
totalCacheReadTokens += totalCacheRead;
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
totalCost += cost;
|
|
3158
|
-
}
|
|
3159
|
-
break;
|
|
3160
|
-
}
|
|
3161
|
-
}
|
|
2891
|
+
const tokens = {
|
|
2892
|
+
input: totalInput,
|
|
2893
|
+
output: outputTokens,
|
|
2894
|
+
reasoning: reasoningTokens || void 0,
|
|
2895
|
+
cache_read: totalCacheRead || void 0
|
|
2896
|
+
};
|
|
2897
|
+
const cost = estimateTokenCost(activeModel, tokens);
|
|
2898
|
+
transcript.attachUsageToLatestAssistant(tokens, {
|
|
2899
|
+
model: activeModel,
|
|
2900
|
+
cost: cost ?? void 0,
|
|
2901
|
+
costSource: cost === null ? void 0 : "estimated"
|
|
2902
|
+
});
|
|
2903
|
+
totalCost += cost ?? 0;
|
|
3162
2904
|
}
|
|
3163
2905
|
}
|
|
3164
2906
|
}
|
|
@@ -3166,10 +2908,15 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3166
2908
|
} catch {
|
|
3167
2909
|
}
|
|
3168
2910
|
}
|
|
3169
|
-
if (pendingPlan
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
2911
|
+
if (pendingPlan) transcript.appendToCurrentAssistant(pendingPlan);
|
|
2912
|
+
const result = transcript.finish({
|
|
2913
|
+
message_count: 0,
|
|
2914
|
+
total_input_tokens: totalInputTokens,
|
|
2915
|
+
total_output_tokens: totalOutputTokens,
|
|
2916
|
+
total_cache_read_tokens: totalCacheReadTokens || void 0,
|
|
2917
|
+
total_cost: totalCost,
|
|
2918
|
+
cost_source: totalCost > 0 ? "estimated" : void 0
|
|
2919
|
+
});
|
|
3173
2920
|
return {
|
|
3174
2921
|
id: meta.id,
|
|
3175
2922
|
title: meta.title,
|
|
@@ -3177,15 +2924,8 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3177
2924
|
directory: meta.directory,
|
|
3178
2925
|
time_created: meta.createdAt,
|
|
3179
2926
|
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
|
|
2927
|
+
stats: result.stats,
|
|
2928
|
+
messages: result.messages
|
|
3189
2929
|
};
|
|
3190
2930
|
}
|
|
3191
2931
|
// ---- File listing ----
|
|
@@ -3504,22 +3244,16 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3504
3244
|
return null;
|
|
3505
3245
|
}
|
|
3506
3246
|
// ---- Record conversion ----
|
|
3507
|
-
convertRecord(data,
|
|
3247
|
+
convertRecord(data, transcript, pendingPlan, activeModel) {
|
|
3508
3248
|
const recordType = String(data["type"] ?? "");
|
|
3509
|
-
if (isInternalEventType2(recordType))
|
|
3510
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3511
|
-
}
|
|
3249
|
+
if (isInternalEventType2(recordType)) return pendingPlan;
|
|
3512
3250
|
if (recordType === "session_meta" || recordType === "event_msg") {
|
|
3513
|
-
return
|
|
3514
|
-
}
|
|
3515
|
-
if (recordType !== "response_item") {
|
|
3516
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3251
|
+
return pendingPlan;
|
|
3517
3252
|
}
|
|
3253
|
+
if (recordType !== "response_item") return pendingPlan;
|
|
3518
3254
|
const payload = data["payload"] ?? {};
|
|
3519
3255
|
const payloadType = String(payload["type"] ?? "");
|
|
3520
|
-
if (isInternalEventType2(payloadType))
|
|
3521
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3522
|
-
}
|
|
3256
|
+
if (isInternalEventType2(payloadType)) return pendingPlan;
|
|
3523
3257
|
const timestampMs = parseTimestampMs2(data) || parseTimestampMs2(payload);
|
|
3524
3258
|
switch (payloadType) {
|
|
3525
3259
|
case "message": {
|
|
@@ -3527,60 +3261,39 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3527
3261
|
if (role === "assistant") {
|
|
3528
3262
|
return this.convertAssistantMessage(
|
|
3529
3263
|
payload,
|
|
3530
|
-
|
|
3264
|
+
transcript,
|
|
3531
3265
|
timestampMs,
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
pendingPlan
|
|
3266
|
+
pendingPlan,
|
|
3267
|
+
activeModel
|
|
3535
3268
|
);
|
|
3536
3269
|
}
|
|
3537
3270
|
if (role === "user") {
|
|
3538
|
-
return this.convertUserMessage(
|
|
3539
|
-
payload,
|
|
3540
|
-
messages,
|
|
3541
|
-
timestampMs,
|
|
3542
|
-
currentAssistantIndex,
|
|
3543
|
-
latestAssistantTextIndex,
|
|
3544
|
-
pendingPlan
|
|
3545
|
-
);
|
|
3271
|
+
return this.convertUserMessage(payload, transcript, timestampMs, pendingPlan);
|
|
3546
3272
|
}
|
|
3547
3273
|
break;
|
|
3548
3274
|
}
|
|
3549
3275
|
case "reasoning":
|
|
3550
|
-
|
|
3276
|
+
this.convertReasoning(payload, transcript, timestampMs, activeModel);
|
|
3277
|
+
return null;
|
|
3551
3278
|
case "function_call":
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
messages,
|
|
3555
|
-
pendingToolCalls,
|
|
3556
|
-
timestampMs,
|
|
3557
|
-
currentAssistantIndex,
|
|
3558
|
-
latestAssistantTextIndex
|
|
3559
|
-
);
|
|
3279
|
+
this.convertFunctionCall(payload, transcript, timestampMs, activeModel);
|
|
3280
|
+
return null;
|
|
3560
3281
|
case "function_call_output":
|
|
3561
|
-
this.
|
|
3562
|
-
return
|
|
3282
|
+
this.convertToolCallOutput(payload, transcript, timestampMs);
|
|
3283
|
+
return pendingPlan;
|
|
3563
3284
|
case "custom_tool_call":
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
messages,
|
|
3567
|
-
pendingToolCalls,
|
|
3568
|
-
timestampMs,
|
|
3569
|
-
currentAssistantIndex,
|
|
3570
|
-
latestAssistantTextIndex
|
|
3571
|
-
);
|
|
3285
|
+
this.convertCustomToolCall(payload, transcript, timestampMs, activeModel);
|
|
3286
|
+
return null;
|
|
3572
3287
|
case "custom_tool_call_output":
|
|
3573
|
-
this.
|
|
3574
|
-
return
|
|
3288
|
+
this.convertToolCallOutput(payload, transcript, timestampMs);
|
|
3289
|
+
return pendingPlan;
|
|
3575
3290
|
}
|
|
3576
|
-
return
|
|
3291
|
+
return pendingPlan;
|
|
3577
3292
|
}
|
|
3578
3293
|
// ---- Assistant message ----
|
|
3579
|
-
convertAssistantMessage(payload,
|
|
3294
|
+
convertAssistantMessage(payload, transcript, timestampMs, pendingPlan, activeModel) {
|
|
3580
3295
|
const content = payload["content"];
|
|
3581
|
-
if (!Array.isArray(content))
|
|
3582
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3583
|
-
}
|
|
3296
|
+
if (!Array.isArray(content)) return pendingPlan;
|
|
3584
3297
|
const textParts = [];
|
|
3585
3298
|
for (const item of content) {
|
|
3586
3299
|
if (typeof item !== "object" || item === null) continue;
|
|
@@ -3590,9 +3303,7 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3590
3303
|
if (text.trim()) textParts.push(text);
|
|
3591
3304
|
}
|
|
3592
3305
|
}
|
|
3593
|
-
if (textParts.length === 0)
|
|
3594
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3595
|
-
}
|
|
3306
|
+
if (textParts.length === 0) return pendingPlan;
|
|
3596
3307
|
const fullText = textParts.join("\n");
|
|
3597
3308
|
const planMatch = fullText.match(PROPOSED_PLAN_PATTERN);
|
|
3598
3309
|
if (planMatch) {
|
|
@@ -3606,61 +3317,34 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3606
3317
|
pendingPlan = planPart;
|
|
3607
3318
|
}
|
|
3608
3319
|
const displayText = cleanInternalText(fullText.replace(PROPOSED_PLAN_PATTERN, ""));
|
|
3609
|
-
if (!displayText)
|
|
3610
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3611
|
-
}
|
|
3320
|
+
if (!displayText) return pendingPlan;
|
|
3612
3321
|
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 };
|
|
3322
|
+
transcript.appendAssistantPart(textPart, {
|
|
3323
|
+
id: "",
|
|
3324
|
+
timestampMs,
|
|
3325
|
+
agent: "codex",
|
|
3326
|
+
model: activeModel
|
|
3327
|
+
});
|
|
3328
|
+
return pendingPlan;
|
|
3634
3329
|
}
|
|
3635
3330
|
// ---- User message ----
|
|
3636
|
-
convertUserMessage(payload,
|
|
3331
|
+
convertUserMessage(payload, transcript, timestampMs, pendingPlan) {
|
|
3637
3332
|
const content = payload["content"];
|
|
3638
3333
|
const text = Array.isArray(content) ? content.map(
|
|
3639
3334
|
(c) => typeof c === "object" && c !== null ? String(c["text"] ?? "") : String(c ?? "")
|
|
3640
3335
|
).join(" ") : String(content ?? "");
|
|
3641
3336
|
const visibleText = cleanInternalText(text);
|
|
3642
|
-
if (!visibleText)
|
|
3643
|
-
|
|
3644
|
-
}
|
|
3645
|
-
if (isDeveloperLikeUserMessage(visibleText)) {
|
|
3646
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3647
|
-
}
|
|
3337
|
+
if (!visibleText) return pendingPlan;
|
|
3338
|
+
if (isDeveloperLikeUserMessage(visibleText)) return pendingPlan;
|
|
3648
3339
|
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 };
|
|
3340
|
+
if (pendingPlan) transcript.appendToCurrentAssistant(pendingPlan);
|
|
3341
|
+
transcript.appendMessage({
|
|
3342
|
+
id: "",
|
|
3343
|
+
role: "user",
|
|
3344
|
+
timestampMs,
|
|
3345
|
+
parts: [{ type: "text", text: visibleText, time_created: timestampMs }]
|
|
3346
|
+
});
|
|
3347
|
+
return null;
|
|
3664
3348
|
}
|
|
3665
3349
|
const subagentMatch = visibleText.match(SUBAGENT_NOTIFICATION_PATTERN);
|
|
3666
3350
|
if (subagentMatch) {
|
|
@@ -3674,41 +3358,32 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3674
3358
|
text: completedText || `Subagent ${nickname} completed`,
|
|
3675
3359
|
time_created: timestampMs
|
|
3676
3360
|
};
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
currentAssistantIndex = null;
|
|
3689
|
-
latestAssistantTextIndex = null;
|
|
3690
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3361
|
+
transcript.appendMessage({
|
|
3362
|
+
id: "",
|
|
3363
|
+
role: "assistant",
|
|
3364
|
+
timestampMs,
|
|
3365
|
+
parts: [textPart],
|
|
3366
|
+
agent: "codex",
|
|
3367
|
+
subagentId: agentId || void 0,
|
|
3368
|
+
nickname: nickname || void 0
|
|
3369
|
+
});
|
|
3370
|
+
transcript.beginTurn();
|
|
3371
|
+
return pendingPlan;
|
|
3691
3372
|
} catch {
|
|
3692
3373
|
}
|
|
3693
3374
|
}
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
);
|
|
3702
|
-
currentAssistantIndex = null;
|
|
3703
|
-
latestAssistantTextIndex = null;
|
|
3704
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan };
|
|
3375
|
+
transcript.appendMessage({
|
|
3376
|
+
id: "",
|
|
3377
|
+
role: "user",
|
|
3378
|
+
timestampMs,
|
|
3379
|
+
parts: [{ type: "text", text: visibleText, time_created: timestampMs }]
|
|
3380
|
+
});
|
|
3381
|
+
return pendingPlan;
|
|
3705
3382
|
}
|
|
3706
3383
|
// ---- Reasoning ----
|
|
3707
|
-
convertReasoning(payload,
|
|
3384
|
+
convertReasoning(payload, transcript, timestampMs, activeModel) {
|
|
3708
3385
|
const summary = payload["summary"];
|
|
3709
|
-
if (!Array.isArray(summary))
|
|
3710
|
-
return { currentAssistantIndex, latestAssistantTextIndex: null, pendingPlan: null };
|
|
3711
|
-
}
|
|
3386
|
+
if (!Array.isArray(summary)) return;
|
|
3712
3387
|
const texts = [];
|
|
3713
3388
|
for (const item of summary) {
|
|
3714
3389
|
if (typeof item === "object" && item !== null) {
|
|
@@ -3719,42 +3394,25 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3719
3394
|
}
|
|
3720
3395
|
}
|
|
3721
3396
|
}
|
|
3722
|
-
if (texts.length === 0)
|
|
3723
|
-
return { currentAssistantIndex, latestAssistantTextIndex: null, pendingPlan: null };
|
|
3724
|
-
}
|
|
3397
|
+
if (texts.length === 0) return;
|
|
3725
3398
|
const reasoningText = texts.join("\n");
|
|
3726
3399
|
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",
|
|
3400
|
+
transcript.appendAssistantPart(
|
|
3401
|
+
part,
|
|
3402
|
+
{
|
|
3403
|
+
id: "",
|
|
3740
3404
|
timestampMs,
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
}
|
|
3405
|
+
agent: "codex",
|
|
3406
|
+
model: activeModel
|
|
3407
|
+
},
|
|
3408
|
+
{ resetLatestText: true }
|
|
3744
3409
|
);
|
|
3745
|
-
return {
|
|
3746
|
-
currentAssistantIndex: messages.length - 1,
|
|
3747
|
-
latestAssistantTextIndex: null,
|
|
3748
|
-
pendingPlan: null
|
|
3749
|
-
};
|
|
3750
3410
|
}
|
|
3751
3411
|
// ---- Function call ----
|
|
3752
|
-
convertFunctionCall(payload,
|
|
3412
|
+
convertFunctionCall(payload, transcript, timestampMs, activeModel) {
|
|
3753
3413
|
const callId = String(payload["call_id"] ?? "").trim();
|
|
3754
3414
|
const name = String(payload["name"] ?? "").trim();
|
|
3755
|
-
if (!name)
|
|
3756
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan: null };
|
|
3757
|
-
}
|
|
3415
|
+
if (!name) return;
|
|
3758
3416
|
const toolIdentity = resolveToolIdentity(name, payload["namespace"]);
|
|
3759
3417
|
const arguments_ = normalizeToolArguments2(payload["arguments"]);
|
|
3760
3418
|
const toolPart = {
|
|
@@ -3769,59 +3427,27 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3769
3427
|
},
|
|
3770
3428
|
time_created: timestampMs
|
|
3771
3429
|
};
|
|
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
|
-
})
|
|
3430
|
+
transcript.appendToolCall(
|
|
3431
|
+
toolPart,
|
|
3432
|
+
{ id: "", timestampMs, agent: "codex", model: activeModel },
|
|
3433
|
+
{ markModeAsTool: true }
|
|
3796
3434
|
);
|
|
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
3435
|
}
|
|
3803
3436
|
// ---- Function call output ----
|
|
3804
|
-
|
|
3437
|
+
convertToolCallOutput(payload, transcript, timestampMs) {
|
|
3805
3438
|
const callId = String(payload["call_id"] ?? "").trim();
|
|
3806
3439
|
if (!callId) return;
|
|
3807
|
-
const location = pendingToolCalls.get(callId);
|
|
3808
|
-
if (!location) return;
|
|
3809
3440
|
const outputText = cleanInternalText(String(payload["output"] ?? ""));
|
|
3810
3441
|
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
3442
|
if (outputParts.length > 0) {
|
|
3814
|
-
|
|
3815
|
-
state.status = "completed";
|
|
3443
|
+
transcript.resolveToolCall(callId, { output: outputParts, status: "completed" });
|
|
3816
3444
|
}
|
|
3817
3445
|
}
|
|
3818
3446
|
// ---- Custom tool call ----
|
|
3819
|
-
convertCustomToolCall(payload,
|
|
3447
|
+
convertCustomToolCall(payload, transcript, timestampMs, activeModel) {
|
|
3820
3448
|
const callId = String(payload["call_id"] ?? "").trim();
|
|
3821
3449
|
const name = String(payload["name"] ?? "").trim();
|
|
3822
|
-
if (!name)
|
|
3823
|
-
return { currentAssistantIndex, latestAssistantTextIndex, pendingPlan: null };
|
|
3824
|
-
}
|
|
3450
|
+
if (!name) return;
|
|
3825
3451
|
const toolIdentity = resolveToolIdentity(name, payload["namespace"]);
|
|
3826
3452
|
const rawInput = payload["input"];
|
|
3827
3453
|
const normalizedInput = normalizeCustomToolArguments(name, rawInput);
|
|
@@ -3837,70 +3463,87 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3837
3463
|
},
|
|
3838
3464
|
time_created: timestampMs
|
|
3839
3465
|
};
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3466
|
+
transcript.appendToolCall(
|
|
3467
|
+
toolPart,
|
|
3468
|
+
{ id: "", timestampMs, agent: "codex", model: activeModel },
|
|
3469
|
+
{ markModeAsTool: true }
|
|
3470
|
+
);
|
|
3471
|
+
}
|
|
3472
|
+
};
|
|
3473
|
+
var PerfTracer = class {
|
|
3474
|
+
rootMarkers = [];
|
|
3475
|
+
activeStack = [];
|
|
3476
|
+
enabled = false;
|
|
3477
|
+
enable() {
|
|
3478
|
+
this.enabled = true;
|
|
3479
|
+
}
|
|
3480
|
+
start(name) {
|
|
3481
|
+
const marker = {
|
|
3482
|
+
name,
|
|
3483
|
+
startTime: performance.now(),
|
|
3484
|
+
children: []
|
|
3485
|
+
};
|
|
3486
|
+
if (!this.enabled) return marker;
|
|
3487
|
+
const parent = this.activeStack[this.activeStack.length - 1];
|
|
3488
|
+
if (parent) {
|
|
3489
|
+
marker.parent = parent;
|
|
3490
|
+
parent.children.push(marker);
|
|
3491
|
+
} else {
|
|
3492
|
+
this.rootMarkers.push(marker);
|
|
3493
|
+
}
|
|
3494
|
+
this.activeStack.push(marker);
|
|
3495
|
+
return marker;
|
|
3496
|
+
}
|
|
3497
|
+
end(marker) {
|
|
3498
|
+
if (!this.enabled) return;
|
|
3499
|
+
const target = marker ?? this.activeStack[this.activeStack.length - 1];
|
|
3500
|
+
if (!target) return;
|
|
3501
|
+
target.endTime = performance.now();
|
|
3502
|
+
target.duration = target.endTime - target.startTime;
|
|
3503
|
+
while (this.activeStack.length > 0) {
|
|
3504
|
+
const popped = this.activeStack.pop();
|
|
3505
|
+
if (popped === target) break;
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
measure(name, fn) {
|
|
3509
|
+
const marker = this.start(name);
|
|
3510
|
+
try {
|
|
3511
|
+
return fn();
|
|
3512
|
+
} finally {
|
|
3513
|
+
this.end(marker);
|
|
3854
3514
|
}
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
mode: "tool"
|
|
3863
|
-
})
|
|
3864
|
-
);
|
|
3865
|
-
const newIndex = messages.length - 1;
|
|
3866
|
-
if (callId) {
|
|
3867
|
-
pendingToolCalls.set(callId, [newIndex, 0]);
|
|
3515
|
+
}
|
|
3516
|
+
async measureAsync(name, fn) {
|
|
3517
|
+
const marker = this.start(name);
|
|
3518
|
+
try {
|
|
3519
|
+
return await fn();
|
|
3520
|
+
} finally {
|
|
3521
|
+
this.end(marker);
|
|
3868
3522
|
}
|
|
3869
|
-
return { currentAssistantIndex: newIndex, latestAssistantTextIndex: null, pendingPlan: null };
|
|
3870
3523
|
}
|
|
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";
|
|
3524
|
+
getReport() {
|
|
3525
|
+
if (!this.enabled) return "Performance tracing disabled";
|
|
3526
|
+
const lines = [];
|
|
3527
|
+
lines.push("\n=== Performance Report ===\n");
|
|
3528
|
+
for (const marker of this.rootMarkers) {
|
|
3529
|
+
this.formatMarker(marker, 0, lines);
|
|
3884
3530
|
}
|
|
3531
|
+
return lines.join("\n");
|
|
3885
3532
|
}
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
cost: opts.cost ?? 0,
|
|
3898
|
-
parts: opts.parts,
|
|
3899
|
-
subagent_id: opts.subagent_id,
|
|
3900
|
-
nickname: opts.nickname
|
|
3901
|
-
};
|
|
3533
|
+
formatMarker(marker, depth, lines) {
|
|
3534
|
+
const indent = " ".repeat(depth);
|
|
3535
|
+
const duration = marker.duration?.toFixed(2) ?? "?";
|
|
3536
|
+
lines.push(`${indent}${marker.name}: ${duration}ms`);
|
|
3537
|
+
for (const child of marker.children) {
|
|
3538
|
+
this.formatMarker(child, depth + 1, lines);
|
|
3539
|
+
}
|
|
3540
|
+
}
|
|
3541
|
+
reset() {
|
|
3542
|
+
this.rootMarkers = [];
|
|
3543
|
+
this.activeStack = [];
|
|
3902
3544
|
}
|
|
3903
3545
|
};
|
|
3546
|
+
var perf = new PerfTracer();
|
|
3904
3547
|
var CURSOR_TOOL_TITLE_MAP = {
|
|
3905
3548
|
read_file_v2: "read",
|
|
3906
3549
|
edit_file_v2: "edit",
|
|
@@ -4068,12 +3711,12 @@ var CursorAgent = class extends DatabaseSessionSource {
|
|
|
4068
3711
|
try {
|
|
4069
3712
|
const row = wsDb.prepare("SELECT value FROM ItemTable WHERE key = 'composer.composerData'").get();
|
|
4070
3713
|
if (!row?.value) continue;
|
|
4071
|
-
const
|
|
3714
|
+
const parsed = JSON.parse(row.value);
|
|
4072
3715
|
let composers;
|
|
4073
|
-
if (
|
|
4074
|
-
composers =
|
|
4075
|
-
} else if (Array.isArray(
|
|
4076
|
-
composers =
|
|
3716
|
+
if (parsed !== null && typeof parsed === "object" && "allComposers" in parsed && Array.isArray(parsed["allComposers"])) {
|
|
3717
|
+
composers = parsed.allComposers;
|
|
3718
|
+
} else if (Array.isArray(parsed)) {
|
|
3719
|
+
composers = parsed;
|
|
4077
3720
|
} else {
|
|
4078
3721
|
continue;
|
|
4079
3722
|
}
|
|
@@ -4452,10 +4095,10 @@ var CursorAgent = class extends DatabaseSessionSource {
|
|
|
4452
4095
|
if (toolData.result !== void 0) {
|
|
4453
4096
|
if (typeof toolData.result === "string") {
|
|
4454
4097
|
try {
|
|
4455
|
-
const
|
|
4456
|
-
state.output =
|
|
4457
|
-
if (
|
|
4458
|
-
state.error =
|
|
4098
|
+
const parsed = JSON.parse(toolData.result);
|
|
4099
|
+
state.output = parsed;
|
|
4100
|
+
if (parsed.error || parsed.message || parsed.stderr) {
|
|
4101
|
+
state.error = parsed.error || parsed.message || parsed.stderr;
|
|
4459
4102
|
state.status = "error";
|
|
4460
4103
|
}
|
|
4461
4104
|
} catch {
|
|
@@ -4577,20 +4220,6 @@ function normalizeTextParts(content, timestampMs) {
|
|
|
4577
4220
|
const text = cleanInternalText(contentToText(content));
|
|
4578
4221
|
return text ? [{ type: "text", text, time_created: timestampMs }] : [];
|
|
4579
4222
|
}
|
|
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
4223
|
function getEntryTimestamp(entry) {
|
|
4595
4224
|
return parseTimestampMs3(entry["timestamp"]);
|
|
4596
4225
|
}
|
|
@@ -4634,29 +4263,6 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4634
4263
|
if (!this.basePath) return false;
|
|
4635
4264
|
return this.listSessionFiles().length > 0;
|
|
4636
4265
|
}
|
|
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
4266
|
listSessionSources(options) {
|
|
4661
4267
|
if (!this.basePath) return [];
|
|
4662
4268
|
return this.listSessionFiles(options).map((file) => ({
|
|
@@ -4676,9 +4282,8 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4676
4282
|
const meta = this.sessionMetaMap.get(sessionId);
|
|
4677
4283
|
if (!meta) throw new Error(`Session not found: ${sessionId}`);
|
|
4678
4284
|
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);
|
|
4285
|
+
const parsed = this.parsePiFile(meta.sourcePath);
|
|
4286
|
+
const state = this.convertEntries(parsed.pathEntries);
|
|
4682
4287
|
return {
|
|
4683
4288
|
id: meta.id,
|
|
4684
4289
|
title: meta.title,
|
|
@@ -4687,7 +4292,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4687
4292
|
time_created: meta.createdAt,
|
|
4688
4293
|
time_updated: meta.updatedAt,
|
|
4689
4294
|
stats: {
|
|
4690
|
-
message_count:
|
|
4295
|
+
message_count: state.messages.length,
|
|
4691
4296
|
total_input_tokens: state.totalInputTokens,
|
|
4692
4297
|
total_output_tokens: state.totalOutputTokens,
|
|
4693
4298
|
total_cache_read_tokens: state.totalCacheReadTokens || void 0,
|
|
@@ -4695,7 +4300,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4695
4300
|
total_cost: state.totalCost,
|
|
4696
4301
|
cost_source: state.totalCost > 0 ? "recorded" : void 0
|
|
4697
4302
|
},
|
|
4698
|
-
messages:
|
|
4303
|
+
messages: state.messages
|
|
4699
4304
|
};
|
|
4700
4305
|
}
|
|
4701
4306
|
listSessionFiles(options) {
|
|
@@ -4739,18 +4344,18 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4739
4344
|
return JSON.stringify([HEAD_INDEX_VERSION3, PARSER_VERSION2, stat.mtimeMs, stat.size]);
|
|
4740
4345
|
}
|
|
4741
4346
|
parseSessionHeadResult(filePath) {
|
|
4742
|
-
const
|
|
4743
|
-
const state = this.convertEntries(
|
|
4347
|
+
const parsed = this.parsePiFile(filePath);
|
|
4348
|
+
const state = this.convertEntries(parsed.pathEntries);
|
|
4744
4349
|
const messageCount = state.messages.length;
|
|
4745
4350
|
if (messageCount === 0) return filteredSession("no visible messages");
|
|
4746
4351
|
const modelUsage = Object.keys(state.modelUsage).length > 0 ? state.modelUsage : void 0;
|
|
4747
4352
|
return parsedSession({
|
|
4748
|
-
id:
|
|
4749
|
-
slug: `pi/${
|
|
4750
|
-
title:
|
|
4751
|
-
directory:
|
|
4752
|
-
time_created:
|
|
4753
|
-
time_updated:
|
|
4353
|
+
id: parsed.sessionId,
|
|
4354
|
+
slug: `pi/${parsed.sessionId}`,
|
|
4355
|
+
title: parsed.title,
|
|
4356
|
+
directory: parsed.directory,
|
|
4357
|
+
time_created: parsed.createdAt,
|
|
4358
|
+
time_updated: parsed.updatedAt,
|
|
4754
4359
|
stats: {
|
|
4755
4360
|
message_count: messageCount,
|
|
4756
4361
|
total_input_tokens: state.totalInputTokens,
|
|
@@ -4812,74 +4417,52 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4812
4417
|
return null;
|
|
4813
4418
|
}
|
|
4814
4419
|
convertEntries(entries) {
|
|
4815
|
-
const
|
|
4816
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
4420
|
+
const builder = new TranscriptBuilder({ messageDefaults: "sparse" });
|
|
4817
4421
|
const modelUsage = {};
|
|
4818
|
-
let totalInputTokens = 0;
|
|
4819
|
-
let totalOutputTokens = 0;
|
|
4820
|
-
let totalCacheReadTokens = 0;
|
|
4821
|
-
let totalCacheCreateTokens = 0;
|
|
4822
|
-
let totalCost = 0;
|
|
4823
4422
|
for (const entry of entries) {
|
|
4824
4423
|
const timestampMs = getEntryTimestamp(entry);
|
|
4825
4424
|
const type = String(entry["type"] ?? "");
|
|
4826
4425
|
if (type === "message") {
|
|
4827
4426
|
const message = entry["message"];
|
|
4828
4427
|
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;
|
|
4428
|
+
const result2 = this.convertAgentMessage(entry, message, timestampMs, builder);
|
|
4429
|
+
if (!result2) continue;
|
|
4430
|
+
if (result2.message) builder.appendMessage(result2.message);
|
|
4431
|
+
if (result2.model && result2.totalTokens > 0) {
|
|
4432
|
+
modelUsage[result2.model] = (modelUsage[result2.model] ?? 0) + result2.totalTokens;
|
|
4846
4433
|
}
|
|
4847
4434
|
continue;
|
|
4848
4435
|
}
|
|
4849
4436
|
const summary = this.convertSummaryEntry(entry, timestampMs);
|
|
4850
|
-
if (summary)
|
|
4437
|
+
if (summary) builder.appendMessage(summary);
|
|
4851
4438
|
}
|
|
4439
|
+
const result = builder.finish();
|
|
4852
4440
|
return {
|
|
4853
|
-
messages,
|
|
4854
|
-
totalInputTokens,
|
|
4855
|
-
totalOutputTokens,
|
|
4856
|
-
totalCacheReadTokens,
|
|
4857
|
-
totalCacheCreateTokens,
|
|
4858
|
-
totalCost,
|
|
4441
|
+
messages: result.messages,
|
|
4442
|
+
totalInputTokens: result.stats.total_input_tokens,
|
|
4443
|
+
totalOutputTokens: result.stats.total_output_tokens,
|
|
4444
|
+
totalCacheReadTokens: result.stats.total_cache_read_tokens ?? 0,
|
|
4445
|
+
totalCacheCreateTokens: result.stats.total_cache_create_tokens ?? 0,
|
|
4446
|
+
totalCost: result.stats.total_cost,
|
|
4859
4447
|
modelUsage
|
|
4860
4448
|
};
|
|
4861
4449
|
}
|
|
4862
|
-
convertAgentMessage(entry, message, timestampMs,
|
|
4450
|
+
convertAgentMessage(entry, message, timestampMs, builder) {
|
|
4863
4451
|
const id = String(entry["id"] ?? "");
|
|
4864
4452
|
const role = String(message["role"] ?? "");
|
|
4865
4453
|
if (role === "user") {
|
|
4866
4454
|
const parts = normalizeTextParts(message["content"], timestampMs);
|
|
4867
4455
|
if (parts.length === 0) return null;
|
|
4868
|
-
return this.emptyUsageResult(
|
|
4456
|
+
return this.emptyUsageResult({ id, role: "user", timestampMs, parts });
|
|
4869
4457
|
}
|
|
4870
4458
|
if (role === "assistant") {
|
|
4871
|
-
const parts = this.normalizeAssistantParts(
|
|
4872
|
-
message["content"],
|
|
4873
|
-
timestampMs,
|
|
4874
|
-
pendingToolCalls,
|
|
4875
|
-
nextMessageIndex
|
|
4876
|
-
);
|
|
4459
|
+
const parts = this.normalizeAssistantParts(message["content"], timestampMs);
|
|
4877
4460
|
if (parts.length === 0) return null;
|
|
4878
4461
|
const usage = this.normalizeUsage(message["usage"]);
|
|
4879
4462
|
const model = typeof message["model"] === "string" ? message["model"].trim() : null;
|
|
4880
4463
|
const cost = usage.cost ?? estimateTokenCost(model, usage.tokens) ?? 0;
|
|
4881
4464
|
return {
|
|
4882
|
-
message:
|
|
4465
|
+
message: {
|
|
4883
4466
|
id,
|
|
4884
4467
|
role: "assistant",
|
|
4885
4468
|
agent: "pi",
|
|
@@ -4890,18 +4473,13 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4890
4473
|
tokens: usage.tokens,
|
|
4891
4474
|
cost: cost || void 0,
|
|
4892
4475
|
costSource: cost > 0 ? "recorded" : void 0
|
|
4893
|
-
}
|
|
4894
|
-
inputTokens: usage.inputTokens,
|
|
4895
|
-
outputTokens: usage.outputTokens,
|
|
4896
|
-
cacheReadTokens: usage.cacheReadTokens,
|
|
4897
|
-
cacheCreateTokens: usage.cacheCreateTokens,
|
|
4476
|
+
},
|
|
4898
4477
|
totalTokens: usage.totalTokens,
|
|
4899
|
-
cost,
|
|
4900
4478
|
model
|
|
4901
4479
|
};
|
|
4902
4480
|
}
|
|
4903
4481
|
if (role === "toolResult") {
|
|
4904
|
-
this.attachToolResult(message, timestampMs,
|
|
4482
|
+
this.attachToolResult(message, timestampMs, builder);
|
|
4905
4483
|
return this.emptyUsageResult();
|
|
4906
4484
|
}
|
|
4907
4485
|
if (role === "bashExecution") {
|
|
@@ -4910,24 +4488,22 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4910
4488
|
if (role === "custom" && message["display"] === true) {
|
|
4911
4489
|
const parts = normalizeTextParts(message["content"], timestampMs);
|
|
4912
4490
|
if (parts.length === 0) return null;
|
|
4913
|
-
return this.emptyUsageResult(
|
|
4491
|
+
return this.emptyUsageResult({ id, role: "user", timestampMs, parts });
|
|
4914
4492
|
}
|
|
4915
4493
|
if (role === "branchSummary" || role === "compactionSummary") {
|
|
4916
4494
|
const summary = String(message["summary"] ?? "").trim();
|
|
4917
4495
|
if (!summary) return null;
|
|
4918
|
-
return this.emptyUsageResult(
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
})
|
|
4926
|
-
);
|
|
4496
|
+
return this.emptyUsageResult({
|
|
4497
|
+
id,
|
|
4498
|
+
role: "assistant",
|
|
4499
|
+
agent: "pi",
|
|
4500
|
+
timestampMs,
|
|
4501
|
+
parts: [{ type: "text", text: summary, time_created: timestampMs }]
|
|
4502
|
+
});
|
|
4927
4503
|
}
|
|
4928
4504
|
return null;
|
|
4929
4505
|
}
|
|
4930
|
-
normalizeAssistantParts(content, timestampMs
|
|
4506
|
+
normalizeAssistantParts(content, timestampMs) {
|
|
4931
4507
|
if (!Array.isArray(content)) return [];
|
|
4932
4508
|
const parts = [];
|
|
4933
4509
|
for (const item of content) {
|
|
@@ -4958,29 +4534,26 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4958
4534
|
}
|
|
4959
4535
|
};
|
|
4960
4536
|
parts.push(toolPart);
|
|
4961
|
-
if (callId) pendingToolCalls.set(callId, [messageIndex, parts.length - 1]);
|
|
4962
4537
|
}
|
|
4963
4538
|
}
|
|
4964
4539
|
return parts;
|
|
4965
4540
|
}
|
|
4966
|
-
attachToolResult(message, timestampMs,
|
|
4541
|
+
attachToolResult(message, timestampMs, builder) {
|
|
4967
4542
|
const callId = String(message["toolCallId"] ?? "").trim();
|
|
4968
4543
|
const output = normalizeTextParts(message["content"], timestampMs);
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
target.state.metadata = message["details"];
|
|
4977
|
-
pendingToolCalls.delete(callId);
|
|
4544
|
+
if (!callId) return;
|
|
4545
|
+
builder.resolveToolCall(callId, {
|
|
4546
|
+
output,
|
|
4547
|
+
status: message["isError"] === true ? "error" : "completed",
|
|
4548
|
+
metadata: message["details"],
|
|
4549
|
+
consume: true
|
|
4550
|
+
});
|
|
4978
4551
|
}
|
|
4979
4552
|
convertBashExecution(id, message, timestampMs) {
|
|
4980
4553
|
const command = String(message["command"] ?? "");
|
|
4981
4554
|
const output = String(message["output"] ?? "");
|
|
4982
4555
|
const isError = Number(message["exitCode"] ?? 0) !== 0 || message["cancelled"] === true;
|
|
4983
|
-
return
|
|
4556
|
+
return {
|
|
4984
4557
|
id,
|
|
4985
4558
|
role: "tool",
|
|
4986
4559
|
timestampMs,
|
|
@@ -5003,7 +4576,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
5003
4576
|
}
|
|
5004
4577
|
}
|
|
5005
4578
|
]
|
|
5006
|
-
}
|
|
4579
|
+
};
|
|
5007
4580
|
}
|
|
5008
4581
|
convertSummaryEntry(entry, timestampMs) {
|
|
5009
4582
|
const type = entry["type"];
|
|
@@ -5014,13 +4587,13 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
5014
4587
|
const rawText = type === "custom_message" ? contentToText(entry["content"]) : String(entry["summary"] ?? "");
|
|
5015
4588
|
const text = cleanInternalText(rawText);
|
|
5016
4589
|
if (!text) return null;
|
|
5017
|
-
return
|
|
4590
|
+
return {
|
|
5018
4591
|
id: String(entry["id"] ?? ""),
|
|
5019
4592
|
role: type === "custom_message" ? "user" : "assistant",
|
|
5020
4593
|
agent: type === "custom_message" ? void 0 : "pi",
|
|
5021
4594
|
timestampMs,
|
|
5022
4595
|
parts: [{ type: "text", text, time_created: timestampMs }]
|
|
5023
|
-
}
|
|
4596
|
+
};
|
|
5024
4597
|
}
|
|
5025
4598
|
normalizeUsage(raw) {
|
|
5026
4599
|
const usage = isObject(raw) ? raw : {};
|
|
@@ -5050,12 +4623,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
5050
4623
|
emptyUsageResult(message) {
|
|
5051
4624
|
return {
|
|
5052
4625
|
message,
|
|
5053
|
-
inputTokens: 0,
|
|
5054
|
-
outputTokens: 0,
|
|
5055
|
-
cacheReadTokens: 0,
|
|
5056
|
-
cacheCreateTokens: 0,
|
|
5057
4626
|
totalTokens: 0,
|
|
5058
|
-
cost: 0,
|
|
5059
4627
|
model: null
|
|
5060
4628
|
};
|
|
5061
4629
|
}
|
|
@@ -5076,44 +4644,30 @@ var ZCodeAgent = class extends OpenCodeSqliteAgent {
|
|
|
5076
4644
|
}
|
|
5077
4645
|
};
|
|
5078
4646
|
registerAgent({
|
|
5079
|
-
name: "claudecode",
|
|
5080
|
-
displayName: "Claude Code",
|
|
5081
4647
|
icon: "/icon/agent/claudecode.svg",
|
|
5082
4648
|
create: () => new ClaudeCodeAgent()
|
|
5083
4649
|
});
|
|
5084
4650
|
registerAgent({
|
|
5085
|
-
name: "opencode",
|
|
5086
|
-
displayName: "OpenCode",
|
|
5087
4651
|
icon: "/icon/agent/opencode.svg",
|
|
5088
4652
|
create: () => new OpenCodeAgent()
|
|
5089
4653
|
});
|
|
5090
4654
|
registerAgent({
|
|
5091
|
-
name: "zcode",
|
|
5092
|
-
displayName: "ZCode",
|
|
5093
4655
|
icon: "/icon/agent/zcode.svg",
|
|
5094
4656
|
create: () => new ZCodeAgent()
|
|
5095
4657
|
});
|
|
5096
4658
|
registerAgent({
|
|
5097
|
-
name: "kimi",
|
|
5098
|
-
displayName: "Kimi-Cli",
|
|
5099
4659
|
icon: "/icon/agent/kimi.svg",
|
|
5100
4660
|
create: () => new KimiAgent()
|
|
5101
4661
|
});
|
|
5102
4662
|
registerAgent({
|
|
5103
|
-
name: "codex",
|
|
5104
|
-
displayName: "Codex",
|
|
5105
4663
|
icon: "/icon/agent/codex.svg",
|
|
5106
4664
|
create: () => new CodexAgent()
|
|
5107
4665
|
});
|
|
5108
4666
|
registerAgent({
|
|
5109
|
-
name: "pi",
|
|
5110
|
-
displayName: "Pi",
|
|
5111
4667
|
icon: "/icon/agent/pi.svg",
|
|
5112
4668
|
create: () => new PiAgent()
|
|
5113
4669
|
});
|
|
5114
4670
|
registerAgent({
|
|
5115
|
-
name: "cursor",
|
|
5116
|
-
displayName: "Cursor",
|
|
5117
4671
|
icon: "/icon/agent/cursor.svg",
|
|
5118
4672
|
create: () => new CursorAgent()
|
|
5119
4673
|
});
|
|
@@ -6103,7 +5657,7 @@ function buildSessionContentFromMessages(title, messages) {
|
|
|
6103
5657
|
}
|
|
6104
5658
|
return chunks.join("\n");
|
|
6105
5659
|
}
|
|
6106
|
-
var CACHE_SCHEMA_VERSION =
|
|
5660
|
+
var CACHE_SCHEMA_VERSION = 14;
|
|
6107
5661
|
function withCacheDb(fn) {
|
|
6108
5662
|
const cachePath = getCachePath2();
|
|
6109
5663
|
const db = openDb(cachePath);
|
|
@@ -6376,6 +5930,7 @@ function createSearchTables(db) {
|
|
|
6376
5930
|
activity_time INTEGER NOT NULL,
|
|
6377
5931
|
content_text TEXT NOT NULL,
|
|
6378
5932
|
content_hash TEXT NOT NULL,
|
|
5933
|
+
indexed_message_count INTEGER NOT NULL,
|
|
6379
5934
|
indexed_at INTEGER NOT NULL,
|
|
6380
5935
|
UNIQUE(agent_name, session_id)
|
|
6381
5936
|
);
|
|
@@ -6409,6 +5964,24 @@ function createSearchTriggers(db) {
|
|
|
6409
5964
|
END;
|
|
6410
5965
|
`);
|
|
6411
5966
|
}
|
|
5967
|
+
function addIndexedMessageCount(db) {
|
|
5968
|
+
if (!tableExists(db, "session_documents")) return;
|
|
5969
|
+
if (!columnExists(db, "session_documents", "indexed_message_count")) {
|
|
5970
|
+
db.exec(
|
|
5971
|
+
"ALTER TABLE session_documents ADD COLUMN indexed_message_count INTEGER NOT NULL DEFAULT 0"
|
|
5972
|
+
);
|
|
5973
|
+
}
|
|
5974
|
+
if (!tableExists(db, "messages")) return;
|
|
5975
|
+
db.exec(`
|
|
5976
|
+
UPDATE session_documents
|
|
5977
|
+
SET indexed_message_count = (
|
|
5978
|
+
SELECT COUNT(*)
|
|
5979
|
+
FROM messages
|
|
5980
|
+
WHERE messages.agent_name = session_documents.agent_name
|
|
5981
|
+
AND messages.session_id = session_documents.session_id
|
|
5982
|
+
)
|
|
5983
|
+
`);
|
|
5984
|
+
}
|
|
6412
5985
|
function dropSearchTriggers(db) {
|
|
6413
5986
|
db.exec(`
|
|
6414
5987
|
DROP TRIGGER IF EXISTS session_documents_ai;
|
|
@@ -6514,6 +6087,9 @@ function readLegacyCacheVersion(db) {
|
|
|
6514
6087
|
return Number(versionRow?.value ?? 0);
|
|
6515
6088
|
}
|
|
6516
6089
|
function inferCacheSchemaVersion(db) {
|
|
6090
|
+
if (columnExists(db, "session_documents", "indexed_message_count")) {
|
|
6091
|
+
return 14;
|
|
6092
|
+
}
|
|
6517
6093
|
if (tableExists(db, "message_tools")) {
|
|
6518
6094
|
return 11;
|
|
6519
6095
|
}
|
|
@@ -6948,7 +6524,8 @@ function ensureSchema(db, dbPath) {
|
|
|
6948
6524
|
refreshProjectIdentities(db2);
|
|
6949
6525
|
}
|
|
6950
6526
|
},
|
|
6951
|
-
{ version: 13, migrate: createCacheTables }
|
|
6527
|
+
{ version: 13, migrate: createCacheTables },
|
|
6528
|
+
{ version: 14, migrate: addIndexedMessageCount }
|
|
6952
6529
|
]
|
|
6953
6530
|
});
|
|
6954
6531
|
createLatestCacheSchema(db);
|
|
@@ -7110,6 +6687,9 @@ function searchIndexStateFromRows(indexedRows, messageCountRows) {
|
|
|
7110
6687
|
contentHashBySessionId: new Map(
|
|
7111
6688
|
indexedRows.map((row) => [String(row.session_id), String(row.content_hash ?? "")])
|
|
7112
6689
|
),
|
|
6690
|
+
indexedMessageCountBySessionId: new Map(
|
|
6691
|
+
indexedRows.map((row) => [String(row.session_id), Number(row.indexed_message_count ?? 0)])
|
|
6692
|
+
),
|
|
7113
6693
|
messageCountBySessionId: new Map(
|
|
7114
6694
|
messageCountRows.map((row) => [String(row.session_id), Number(row.value ?? 0)])
|
|
7115
6695
|
)
|
|
@@ -7127,19 +6707,27 @@ function readSearchIndexState(db, agentName, sessionIds) {
|
|
|
7127
6707
|
SELECT
|
|
7128
6708
|
requested.session_id,
|
|
7129
6709
|
documents.content_hash,
|
|
6710
|
+
documents.indexed_message_count,
|
|
7130
6711
|
COUNT(messages.message_index) AS value
|
|
7131
6712
|
FROM requested_session_ids AS requested
|
|
7132
6713
|
LEFT JOIN session_documents AS documents
|
|
7133
6714
|
ON documents.agent_name = ? AND documents.session_id = requested.session_id
|
|
7134
6715
|
LEFT JOIN messages
|
|
7135
6716
|
ON messages.agent_name = ? AND messages.session_id = requested.session_id
|
|
7136
|
-
GROUP BY
|
|
6717
|
+
GROUP BY
|
|
6718
|
+
requested.session_id,
|
|
6719
|
+
documents.content_hash,
|
|
6720
|
+
documents.indexed_message_count
|
|
7137
6721
|
`
|
|
7138
6722
|
).all(...batch, agentName, agentName);
|
|
7139
6723
|
rows.push(...batchRows);
|
|
7140
6724
|
}
|
|
7141
6725
|
return searchIndexStateFromRows(rows, rows);
|
|
7142
6726
|
}
|
|
6727
|
+
function searchIndexEntryNeedsUpdate(state, session) {
|
|
6728
|
+
const sessionId = session.id;
|
|
6729
|
+
return state.contentHashBySessionId.get(sessionId) !== sessionContentHash(session) || state.indexedMessageCountBySessionId.get(sessionId) !== (state.messageCountBySessionId.get(sessionId) ?? 0);
|
|
6730
|
+
}
|
|
7143
6731
|
function loadSearchIndexEntry(agentName, change, loadSessionData) {
|
|
7144
6732
|
try {
|
|
7145
6733
|
const data = loadSessionData(change.session.id);
|
|
@@ -7163,6 +6751,12 @@ function loadSearchIndexEntry(agentName, change, loadSessionData) {
|
|
|
7163
6751
|
return null;
|
|
7164
6752
|
}
|
|
7165
6753
|
}
|
|
6754
|
+
function* loadSearchIndexEntries(agentName, changes, loadSessionData) {
|
|
6755
|
+
for (const change of changes) {
|
|
6756
|
+
const entry = loadSearchIndexEntry(agentName, change, loadSessionData);
|
|
6757
|
+
if (entry) yield entry;
|
|
6758
|
+
}
|
|
6759
|
+
}
|
|
7166
6760
|
function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
7167
6761
|
const deleteRow = db.prepare(
|
|
7168
6762
|
"DELETE FROM session_documents WHERE agent_name = ? AND session_id = ?"
|
|
@@ -7234,8 +6828,9 @@ function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
|
7234
6828
|
activity_time,
|
|
7235
6829
|
content_text,
|
|
7236
6830
|
content_hash,
|
|
6831
|
+
indexed_message_count,
|
|
7237
6832
|
indexed_at
|
|
7238
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
6833
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
7239
6834
|
ON CONFLICT(agent_name, session_id) DO UPDATE SET
|
|
7240
6835
|
slug = excluded.slug,
|
|
7241
6836
|
title = excluded.title,
|
|
@@ -7248,6 +6843,7 @@ function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
|
7248
6843
|
activity_time = excluded.activity_time,
|
|
7249
6844
|
content_text = excluded.content_text,
|
|
7250
6845
|
content_hash = excluded.content_hash,
|
|
6846
|
+
indexed_message_count = excluded.indexed_message_count,
|
|
7251
6847
|
indexed_at = excluded.indexed_at
|
|
7252
6848
|
`);
|
|
7253
6849
|
for (const sessionId of new Set(removedSessionIds)) {
|
|
@@ -7256,6 +6852,7 @@ function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
|
7256
6852
|
deleteMessageTools.run(agentName, sessionId, 0);
|
|
7257
6853
|
deleteMessages.run(agentName, sessionId, 0);
|
|
7258
6854
|
}
|
|
6855
|
+
let indexed = 0;
|
|
7259
6856
|
for (const entry of entries) {
|
|
7260
6857
|
const activityTime = entry.session.time_updated ?? entry.session.time_created;
|
|
7261
6858
|
upsertSessionRow(upsertIndexedSession, agentName, entry.session, null, entry.sortIndex, null);
|
|
@@ -7303,16 +6900,19 @@ function writeSearchIndexRows(db, agentName, removedSessionIds, entries) {
|
|
|
7303
6900
|
activityTime,
|
|
7304
6901
|
entry.contentText,
|
|
7305
6902
|
entry.contentHash,
|
|
6903
|
+
entry.messages.length,
|
|
7306
6904
|
Date.now()
|
|
7307
6905
|
);
|
|
6906
|
+
indexed += 1;
|
|
7308
6907
|
}
|
|
6908
|
+
return indexed;
|
|
7309
6909
|
}
|
|
7310
6910
|
function syncSessionSearchIndex(agentName, sessions, loadSessionData, options = {}) {
|
|
7311
6911
|
return withCacheDb((db) => {
|
|
7312
6912
|
ensureFtsConsistency(db);
|
|
7313
6913
|
const startedAt = performance.now();
|
|
7314
6914
|
const existingRows = db.prepare(
|
|
7315
|
-
"SELECT session_id, content_hash FROM session_documents WHERE agent_name = ? ORDER BY id"
|
|
6915
|
+
"SELECT session_id, content_hash, indexed_message_count FROM session_documents WHERE agent_name = ? ORDER BY id"
|
|
7316
6916
|
).all(agentName);
|
|
7317
6917
|
const sessionSortIndexMap = new Map(sessions.map((session, index) => [session.id, index]));
|
|
7318
6918
|
const messageCountRows = db.prepare(
|
|
@@ -7322,20 +6922,25 @@ function syncSessionSearchIndex(agentName, sessions, loadSessionData, options =
|
|
|
7322
6922
|
const sessionMap = new Map(sessions.map((session) => [session.id, session]));
|
|
7323
6923
|
const toDelete = existingRows.map((row) => String(row.session_id)).filter((sessionId) => !sessionMap.has(sessionId));
|
|
7324
6924
|
const toUpsert = sessions.filter(
|
|
7325
|
-
(session) => searchIndexState
|
|
6925
|
+
(session) => searchIndexEntryNeedsUpdate(searchIndexState, session)
|
|
7326
6926
|
);
|
|
7327
6927
|
const changedCount = toDelete.length + toUpsert.length;
|
|
7328
6928
|
const isBulk = shouldBulkSyncSearchIndex(options, changedCount);
|
|
7329
|
-
const
|
|
7330
|
-
|
|
6929
|
+
const changes = toUpsert.map((session) => ({
|
|
6930
|
+
session,
|
|
6931
|
+
sortIndex: sessionSortIndexMap.get(session.id) ?? 0
|
|
6932
|
+
}));
|
|
6933
|
+
let indexed = 0;
|
|
6934
|
+
const writeRows = () => {
|
|
6935
|
+
indexed = writeSearchIndexRows(
|
|
6936
|
+
db,
|
|
7331
6937
|
agentName,
|
|
7332
|
-
|
|
7333
|
-
loadSessionData
|
|
7334
|
-
)
|
|
7335
|
-
|
|
7336
|
-
const writeRows = () => writeSearchIndexRows(db, agentName, toDelete, loaded);
|
|
6938
|
+
toDelete,
|
|
6939
|
+
loadSearchIndexEntries(agentName, changes, loadSessionData)
|
|
6940
|
+
);
|
|
6941
|
+
};
|
|
7337
6942
|
let rebuildDurationMs;
|
|
7338
|
-
const needsRebuild = isBulk &&
|
|
6943
|
+
const needsRebuild = isBulk && changedCount > 0;
|
|
7339
6944
|
if (needsRebuild) {
|
|
7340
6945
|
db.transaction(() => {
|
|
7341
6946
|
dropSearchTriggers(db);
|
|
@@ -7357,8 +6962,8 @@ function syncSessionSearchIndex(agentName, sessions, loadSessionData, options =
|
|
|
7357
6962
|
sessions: sessions.length,
|
|
7358
6963
|
changed: toUpsert.length,
|
|
7359
6964
|
deleted: toDelete.length,
|
|
7360
|
-
indexed
|
|
7361
|
-
skipped: toUpsert.length -
|
|
6965
|
+
indexed,
|
|
6966
|
+
skipped: toUpsert.length - indexed,
|
|
7362
6967
|
durationMs: performance.now() - startedAt,
|
|
7363
6968
|
rebuildDurationMs
|
|
7364
6969
|
};
|
|
@@ -7386,15 +6991,22 @@ function syncSessionSearchIndexChanges(agentName, changes, removedSessionIds, lo
|
|
|
7386
6991
|
changes.map(({ session }) => session.id)
|
|
7387
6992
|
);
|
|
7388
6993
|
const toUpsert = changes.filter(
|
|
7389
|
-
({ session }) => (searchIndexState
|
|
6994
|
+
({ session }) => searchIndexEntryNeedsUpdate(searchIndexState, session)
|
|
7390
6995
|
);
|
|
7391
6996
|
const uniqueRemovedSessionIds = Array.from(new Set(removedSessionIds));
|
|
7392
6997
|
const changedCount = uniqueRemovedSessionIds.length + toUpsert.length;
|
|
7393
6998
|
const isBulk = shouldBulkSyncSearchIndex(options, changedCount);
|
|
7394
|
-
|
|
7395
|
-
const writeRows = () =>
|
|
6999
|
+
let indexed = 0;
|
|
7000
|
+
const writeRows = () => {
|
|
7001
|
+
indexed = writeSearchIndexRows(
|
|
7002
|
+
db,
|
|
7003
|
+
agentName,
|
|
7004
|
+
uniqueRemovedSessionIds,
|
|
7005
|
+
loadSearchIndexEntries(agentName, toUpsert, loadSessionData)
|
|
7006
|
+
);
|
|
7007
|
+
};
|
|
7396
7008
|
let rebuildDurationMs;
|
|
7397
|
-
const needsRebuild = isBulk &&
|
|
7009
|
+
const needsRebuild = isBulk && changedCount > 0;
|
|
7398
7010
|
if (needsRebuild) {
|
|
7399
7011
|
db.transaction(() => {
|
|
7400
7012
|
dropSearchTriggers(db);
|
|
@@ -7416,8 +7028,8 @@ function syncSessionSearchIndexChanges(agentName, changes, removedSessionIds, lo
|
|
|
7416
7028
|
sessions: changes.length,
|
|
7417
7029
|
changed: toUpsert.length,
|
|
7418
7030
|
deleted: uniqueRemovedSessionIds.length,
|
|
7419
|
-
indexed
|
|
7420
|
-
skipped: toUpsert.length -
|
|
7031
|
+
indexed,
|
|
7032
|
+
skipped: toUpsert.length - indexed,
|
|
7421
7033
|
durationMs: performance.now() - startedAt,
|
|
7422
7034
|
rebuildDurationMs
|
|
7423
7035
|
};
|
|
@@ -7431,26 +7043,26 @@ function mergeSearchLists(left, right) {
|
|
|
7431
7043
|
return values.length > 0 ? [...new Set(values)] : void 0;
|
|
7432
7044
|
}
|
|
7433
7045
|
function mergeSearchQueryOptions(query, options) {
|
|
7434
|
-
const
|
|
7046
|
+
const parsed = parseSearchQuery(query);
|
|
7435
7047
|
return {
|
|
7436
|
-
text:
|
|
7048
|
+
text: parsed.text || (parsed.hasQualifiers ? "" : query.trim()),
|
|
7437
7049
|
options: {
|
|
7438
7050
|
...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 ??
|
|
7051
|
+
agent: options.agent ?? parsed.filters.agent,
|
|
7052
|
+
project: options.project ?? parsed.filters.project,
|
|
7053
|
+
projectKind: options.projectKind ?? parsed.filters.projectKind,
|
|
7054
|
+
projectKey: options.projectKey ?? parsed.filters.projectKey,
|
|
7055
|
+
cwd: options.cwd ?? parsed.filters.cwd,
|
|
7056
|
+
tags: mergeSearchLists(options.tags, parsed.filters.tags),
|
|
7057
|
+
tools: mergeSearchLists(options.tools, parsed.filters.tools),
|
|
7058
|
+
file: options.file ?? parsed.filters.file,
|
|
7059
|
+
fileKind: options.fileKind ?? parsed.filters.fileKind,
|
|
7060
|
+
costMin: options.costMin ?? parsed.filters.costMin,
|
|
7061
|
+
costMax: options.costMax ?? parsed.filters.costMax,
|
|
7062
|
+
costMinExclusive: options.costMinExclusive ?? parsed.filters.costMinExclusive,
|
|
7063
|
+
costMaxExclusive: options.costMaxExclusive ?? parsed.filters.costMaxExclusive
|
|
7452
7064
|
},
|
|
7453
|
-
parsed
|
|
7065
|
+
parsed
|
|
7454
7066
|
};
|
|
7455
7067
|
}
|
|
7456
7068
|
function sessionMatchesSearchCost(session, options) {
|
|
@@ -8504,6 +8116,47 @@ async function ensureSessionTags(agent, sessions, workerUrl) {
|
|
|
8504
8116
|
return ensureSessionTagsSync(agent, sessions);
|
|
8505
8117
|
}
|
|
8506
8118
|
}
|
|
8119
|
+
async function finalizeAgentScan(agent, sessions, context) {
|
|
8120
|
+
const { finalization, options, timing, agentStart, onProgress } = context;
|
|
8121
|
+
const isIncremental = finalization.kind === "incremental";
|
|
8122
|
+
if (!isIncremental) {
|
|
8123
|
+
onProgress?.({ agent: agent.name, phase: "complete", newCount: sessions.length });
|
|
8124
|
+
}
|
|
8125
|
+
const identityStart = performance.now();
|
|
8126
|
+
const sessionsWithIdentity = attachMissingProjectIdentities(sessions);
|
|
8127
|
+
timing.identity = performance.now() - identityStart;
|
|
8128
|
+
let tagged = { sessions: sessionsWithIdentity, changed: false };
|
|
8129
|
+
if (finalization.kind !== "cache-only") {
|
|
8130
|
+
const tagsStart = performance.now();
|
|
8131
|
+
tagged = options.includeSmartTags === false ? tagged : await ensureSessionTags(agent, sessionsWithIdentity, options.smartTagWorkerUrl);
|
|
8132
|
+
timing.tags = performance.now() - tagsStart;
|
|
8133
|
+
}
|
|
8134
|
+
if (options.writeCache !== false) {
|
|
8135
|
+
if (finalization.kind === "incremental") {
|
|
8136
|
+
saveCachedSessionDiff(
|
|
8137
|
+
agent,
|
|
8138
|
+
finalization.cached.sessions,
|
|
8139
|
+
tagged.sessions,
|
|
8140
|
+
finalization.changedIds
|
|
8141
|
+
);
|
|
8142
|
+
} else if (finalization.kind === "unchanged" && tagged.changed) {
|
|
8143
|
+
saveCachedSessionDiff(agent, finalization.cached.sessions, tagged.sessions);
|
|
8144
|
+
}
|
|
8145
|
+
}
|
|
8146
|
+
if (isIncremental) {
|
|
8147
|
+
onProgress?.({ agent: agent.name, phase: "complete", newCount: tagged.sessions.length });
|
|
8148
|
+
}
|
|
8149
|
+
const heads = filterSessions(tagged.sessions, options);
|
|
8150
|
+
timing.total = performance.now() - agentStart;
|
|
8151
|
+
return {
|
|
8152
|
+
agent,
|
|
8153
|
+
heads,
|
|
8154
|
+
fromCache: true,
|
|
8155
|
+
...isIncremental ? { refreshed: true } : {},
|
|
8156
|
+
timing,
|
|
8157
|
+
cacheTimestamp: isIncremental ? finalization.cacheTimestamp : finalization.cached.timestamp
|
|
8158
|
+
};
|
|
8159
|
+
}
|
|
8507
8160
|
async function scanAgentSmart(agent, options, onProgress) {
|
|
8508
8161
|
const agentStart = performance.now();
|
|
8509
8162
|
const timing = { total: 0 };
|
|
@@ -8524,19 +8177,13 @@ async function scanAgentSmart(agent, options, onProgress) {
|
|
|
8524
8177
|
phase: "cache",
|
|
8525
8178
|
cachedCount: cached.sessions.length
|
|
8526
8179
|
});
|
|
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,
|
|
8180
|
+
return finalizeAgentScan(agent, cached.sessions, {
|
|
8181
|
+
finalization: { kind: "cache-only", cached },
|
|
8182
|
+
options,
|
|
8537
8183
|
timing,
|
|
8538
|
-
|
|
8539
|
-
|
|
8184
|
+
agentStart,
|
|
8185
|
+
onProgress
|
|
8186
|
+
});
|
|
8540
8187
|
}
|
|
8541
8188
|
const isAvail = agent.isAvailable();
|
|
8542
8189
|
if (!isAvail) {
|
|
@@ -8564,55 +8211,26 @@ async function scanAgentSmart(agent, options, onProgress) {
|
|
|
8564
8211
|
agent.incrementalScan(cached.sessions, checkResult.changedIds || [])
|
|
8565
8212
|
);
|
|
8566
8213
|
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,
|
|
8214
|
+
return finalizeAgentScan(agent, updatedSessions, {
|
|
8215
|
+
finalization: {
|
|
8216
|
+
kind: "incremental",
|
|
8217
|
+
cached,
|
|
8218
|
+
changedIds: checkResult.changedIds ?? [],
|
|
8219
|
+
cacheTimestamp: checkResult.timestamp
|
|
8220
|
+
},
|
|
8221
|
+
options,
|
|
8593
8222
|
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);
|
|
8223
|
+
agentStart,
|
|
8224
|
+
onProgress
|
|
8225
|
+
});
|
|
8606
8226
|
}
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
agent,
|
|
8611
|
-
heads: filtered2,
|
|
8612
|
-
fromCache: true,
|
|
8227
|
+
return finalizeAgentScan(agent, cached.sessions, {
|
|
8228
|
+
finalization: { kind: "unchanged", cached },
|
|
8229
|
+
options,
|
|
8613
8230
|
timing,
|
|
8614
|
-
|
|
8615
|
-
|
|
8231
|
+
agentStart,
|
|
8232
|
+
onProgress
|
|
8233
|
+
});
|
|
8616
8234
|
}
|
|
8617
8235
|
}
|
|
8618
8236
|
if (options.cacheOnly) {
|
|
@@ -8660,9 +8278,9 @@ async function scanAgentFull(agent, options, onProgress, timing = { total: 0 },
|
|
|
8660
8278
|
markAgentFullSyncCompleted(agent.name);
|
|
8661
8279
|
}
|
|
8662
8280
|
onProgress?.({ agent: agent.name, phase: "complete", newCount: tagged.sessions.length });
|
|
8663
|
-
const
|
|
8281
|
+
const filtered = filterSessions(tagged.sessions, options);
|
|
8664
8282
|
timing.total = performance.now() - agentStart;
|
|
8665
|
-
return { agent, heads:
|
|
8283
|
+
return { agent, heads: filtered, fromCache: false, timing };
|
|
8666
8284
|
} catch (err) {
|
|
8667
8285
|
console.error(`Error scanning ${agent.name}:`, err);
|
|
8668
8286
|
return { agent, heads: [], fromCache: false };
|
|
@@ -8710,67 +8328,35 @@ async function scanSessions(options = {}, onProgress) {
|
|
|
8710
8328
|
async function scanSessionsAsync(options = {}, onProgress) {
|
|
8711
8329
|
return scanSessions(options, onProgress);
|
|
8712
8330
|
}
|
|
8713
|
-
var
|
|
8714
|
-
var
|
|
8331
|
+
var STATE_DB_FILENAME = "state.db";
|
|
8332
|
+
var STATE_SCHEMA_VERSION = 2;
|
|
8715
8333
|
var MEMORY_STATE_STORE = "memory";
|
|
8716
|
-
var
|
|
8717
|
-
var BookmarkStorageUnavailableError = class extends Error {
|
|
8334
|
+
var StateStorageUnavailableError = class extends Error {
|
|
8718
8335
|
constructor() {
|
|
8719
8336
|
super("SQLite state database is unavailable");
|
|
8720
|
-
this.name = "
|
|
8337
|
+
this.name = "StateStorageUnavailableError";
|
|
8721
8338
|
}
|
|
8722
8339
|
};
|
|
8723
8340
|
function getStateDir() {
|
|
8724
|
-
if (process.env.CODESESH_STATE_DIR)
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
const p = platform2();
|
|
8728
|
-
if (p === "darwin") {
|
|
8341
|
+
if (process.env.CODESESH_STATE_DIR) return process.env.CODESESH_STATE_DIR;
|
|
8342
|
+
const currentPlatform = platform2();
|
|
8343
|
+
if (currentPlatform === "darwin") {
|
|
8729
8344
|
return join12(homedir5(), "Library", "Application Support", "codesesh");
|
|
8730
8345
|
}
|
|
8731
|
-
if (
|
|
8346
|
+
if (currentPlatform === "win32") {
|
|
8732
8347
|
const appData = process.env.APPDATA ?? process.env.LOCALAPPDATA;
|
|
8733
8348
|
return join12(appData ?? join12(homedir5(), "AppData", "Roaming"), "codesesh");
|
|
8734
8349
|
}
|
|
8735
8350
|
return join12(process.env.XDG_DATA_HOME ?? join12(homedir5(), ".local", "share"), "codesesh");
|
|
8736
8351
|
}
|
|
8737
8352
|
function getStateDbPath() {
|
|
8738
|
-
return join12(getStateDir(),
|
|
8353
|
+
return join12(getStateDir(), STATE_DB_FILENAME);
|
|
8739
8354
|
}
|
|
8740
8355
|
function useMemoryStateStore() {
|
|
8741
8356
|
return process.env.CODESESH_STATE_STORE === MEMORY_STATE_STORE;
|
|
8742
8357
|
}
|
|
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) {
|
|
8358
|
+
function createBookmarksTable(db) {
|
|
8768
8359
|
db.exec(`
|
|
8769
|
-
CREATE TABLE IF NOT EXISTS state_meta (
|
|
8770
|
-
key TEXT PRIMARY KEY,
|
|
8771
|
-
value TEXT NOT NULL
|
|
8772
|
-
);
|
|
8773
|
-
|
|
8774
8360
|
CREATE TABLE IF NOT EXISTS bookmarks (
|
|
8775
8361
|
agent_name TEXT NOT NULL,
|
|
8776
8362
|
session_id TEXT NOT NULL,
|
|
@@ -8785,6 +8371,27 @@ function createStateSchema(db) {
|
|
|
8785
8371
|
);
|
|
8786
8372
|
`);
|
|
8787
8373
|
}
|
|
8374
|
+
function createSessionAliasesTable(db) {
|
|
8375
|
+
db.exec(`
|
|
8376
|
+
CREATE TABLE IF NOT EXISTS session_aliases (
|
|
8377
|
+
agent_name TEXT NOT NULL,
|
|
8378
|
+
session_id TEXT NOT NULL,
|
|
8379
|
+
alias TEXT NOT NULL,
|
|
8380
|
+
updated_at INTEGER NOT NULL,
|
|
8381
|
+
PRIMARY KEY (agent_name, session_id)
|
|
8382
|
+
);
|
|
8383
|
+
`);
|
|
8384
|
+
}
|
|
8385
|
+
function createStateSchema(db) {
|
|
8386
|
+
db.exec(`
|
|
8387
|
+
CREATE TABLE IF NOT EXISTS state_meta (
|
|
8388
|
+
key TEXT PRIMARY KEY,
|
|
8389
|
+
value TEXT NOT NULL
|
|
8390
|
+
);
|
|
8391
|
+
`);
|
|
8392
|
+
createBookmarksTable(db);
|
|
8393
|
+
createSessionAliasesTable(db);
|
|
8394
|
+
}
|
|
8788
8395
|
function readLegacyStateVersion(db) {
|
|
8789
8396
|
if (!tableExists(db, "state_meta") || !columnExists(db, "state_meta", "key") || !columnExists(db, "state_meta", "value")) {
|
|
8790
8397
|
return 0;
|
|
@@ -8794,13 +8401,9 @@ function readLegacyStateVersion(db) {
|
|
|
8794
8401
|
}
|
|
8795
8402
|
function getCurrentStateSchemaVersion(db) {
|
|
8796
8403
|
const userVersion = getUserVersion(db);
|
|
8797
|
-
if (userVersion > 0)
|
|
8798
|
-
return userVersion;
|
|
8799
|
-
}
|
|
8404
|
+
if (userVersion > 0) return userVersion;
|
|
8800
8405
|
const legacyVersion = readLegacyStateVersion(db);
|
|
8801
|
-
if (legacyVersion > 0)
|
|
8802
|
-
return legacyVersion;
|
|
8803
|
-
}
|
|
8406
|
+
if (legacyVersion > 0) return legacyVersion;
|
|
8804
8407
|
return tableExists(db, "bookmarks") ? 1 : 0;
|
|
8805
8408
|
}
|
|
8806
8409
|
function hasAnyStateSchema(db) {
|
|
@@ -8808,14 +8411,14 @@ function hasAnyStateSchema(db) {
|
|
|
8808
8411
|
}
|
|
8809
8412
|
function setStateSchemaVersion(db) {
|
|
8810
8413
|
createStateSchema(db);
|
|
8811
|
-
setUserVersion(db,
|
|
8414
|
+
setUserVersion(db, STATE_SCHEMA_VERSION);
|
|
8812
8415
|
db.prepare(
|
|
8813
8416
|
`
|
|
8814
8417
|
INSERT INTO state_meta(key, value)
|
|
8815
8418
|
VALUES ('version', ?)
|
|
8816
8419
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
8817
8420
|
`
|
|
8818
|
-
).run(String(
|
|
8421
|
+
).run(String(STATE_SCHEMA_VERSION));
|
|
8819
8422
|
}
|
|
8820
8423
|
function ensureSchema2(db, dbPath) {
|
|
8821
8424
|
const currentVersion = getCurrentStateSchemaVersion(db);
|
|
@@ -8826,22 +8429,22 @@ function ensureSchema2(db, dbPath) {
|
|
|
8826
8429
|
runSchemaMigrations(db, {
|
|
8827
8430
|
dbPath,
|
|
8828
8431
|
currentVersion,
|
|
8829
|
-
targetVersion:
|
|
8432
|
+
targetVersion: STATE_SCHEMA_VERSION,
|
|
8830
8433
|
backupLabel: "state-migration",
|
|
8831
|
-
backupTables: ["bookmarks"],
|
|
8832
|
-
migrations: [
|
|
8434
|
+
backupTables: ["bookmarks", "session_aliases"],
|
|
8435
|
+
migrations: [
|
|
8436
|
+
{ version: 1, migrate: createBookmarksTable },
|
|
8437
|
+
{ version: 2, migrate: createSessionAliasesTable }
|
|
8438
|
+
]
|
|
8833
8439
|
});
|
|
8834
|
-
|
|
8835
|
-
if (getUserVersion(db) <= BOOKMARK_SCHEMA_VERSION) {
|
|
8440
|
+
if (currentVersion <= STATE_SCHEMA_VERSION) {
|
|
8836
8441
|
setStateSchemaVersion(db);
|
|
8837
8442
|
}
|
|
8838
8443
|
}
|
|
8839
8444
|
function withStateDb(fn) {
|
|
8840
8445
|
const statePath = getStateDbPath();
|
|
8841
8446
|
const db = openDb(statePath);
|
|
8842
|
-
if (!db)
|
|
8843
|
-
throw new BookmarkStorageUnavailableError();
|
|
8844
|
-
}
|
|
8447
|
+
if (!db) throw new StateStorageUnavailableError();
|
|
8845
8448
|
try {
|
|
8846
8449
|
ensureSchema2(db, statePath);
|
|
8847
8450
|
return fn(db);
|
|
@@ -8849,6 +8452,31 @@ function withStateDb(fn) {
|
|
|
8849
8452
|
db.close();
|
|
8850
8453
|
}
|
|
8851
8454
|
}
|
|
8455
|
+
var memoryBookmarks = /* @__PURE__ */ new Map();
|
|
8456
|
+
function getBookmarkKey(agentKey, sessionId) {
|
|
8457
|
+
return JSON.stringify([agentKey, sessionId]);
|
|
8458
|
+
}
|
|
8459
|
+
function getActivityTime(bookmark) {
|
|
8460
|
+
return bookmark.time_updated ?? bookmark.time_created;
|
|
8461
|
+
}
|
|
8462
|
+
function sortBookmarks(bookmarks) {
|
|
8463
|
+
return bookmarks.sort((a, b) => {
|
|
8464
|
+
const activityDelta = getActivityTime(b) - getActivityTime(a);
|
|
8465
|
+
return activityDelta || b.bookmarked_at - a.bookmarked_at;
|
|
8466
|
+
});
|
|
8467
|
+
}
|
|
8468
|
+
function listMemoryBookmarks() {
|
|
8469
|
+
return sortBookmarks(Array.from(memoryBookmarks.values()));
|
|
8470
|
+
}
|
|
8471
|
+
function upsertMemoryBookmark(bookmark) {
|
|
8472
|
+
const key = getBookmarkKey(bookmark.agentKey, bookmark.sessionId);
|
|
8473
|
+
const saved = {
|
|
8474
|
+
...bookmark,
|
|
8475
|
+
bookmarked_at: memoryBookmarks.get(key)?.bookmarked_at ?? Date.now()
|
|
8476
|
+
};
|
|
8477
|
+
memoryBookmarks.set(key, saved);
|
|
8478
|
+
return saved;
|
|
8479
|
+
}
|
|
8852
8480
|
function toBookmarkRecord(row) {
|
|
8853
8481
|
return {
|
|
8854
8482
|
agentKey: String(row.agent_name ?? ""),
|
|
@@ -9021,6 +8649,78 @@ function deleteBookmark(agentKey, sessionId) {
|
|
|
9021
8649
|
).run(agentKey, sessionId);
|
|
9022
8650
|
});
|
|
9023
8651
|
}
|
|
8652
|
+
var SESSION_ALIAS_MAX_LENGTH = 160;
|
|
8653
|
+
var memoryAliases = /* @__PURE__ */ new Map();
|
|
8654
|
+
function getAliasKey(agentKey, sessionId) {
|
|
8655
|
+
return JSON.stringify([agentKey, sessionId]);
|
|
8656
|
+
}
|
|
8657
|
+
function toSessionAlias(row) {
|
|
8658
|
+
return {
|
|
8659
|
+
agentKey: String(row.agent_name ?? ""),
|
|
8660
|
+
sessionId: String(row.session_id ?? ""),
|
|
8661
|
+
alias: String(row.alias ?? ""),
|
|
8662
|
+
updated_at: Number(row.updated_at ?? 0)
|
|
8663
|
+
};
|
|
8664
|
+
}
|
|
8665
|
+
function normalizeSessionAlias(value) {
|
|
8666
|
+
const alias = value.trim();
|
|
8667
|
+
if (!alias || alias.length > SESSION_ALIAS_MAX_LENGTH) return null;
|
|
8668
|
+
return alias;
|
|
8669
|
+
}
|
|
8670
|
+
function listSessionAliases() {
|
|
8671
|
+
if (useMemoryStateStore()) return [...memoryAliases.values()];
|
|
8672
|
+
return withStateDb(
|
|
8673
|
+
(db) => db.prepare(
|
|
8674
|
+
`
|
|
8675
|
+
SELECT agent_name, session_id, alias, updated_at
|
|
8676
|
+
FROM session_aliases
|
|
8677
|
+
ORDER BY updated_at DESC
|
|
8678
|
+
`
|
|
8679
|
+
).all().map(toSessionAlias)
|
|
8680
|
+
);
|
|
8681
|
+
}
|
|
8682
|
+
function upsertSessionAlias(agentKey, sessionId, alias) {
|
|
8683
|
+
const normalizedAlias = normalizeSessionAlias(alias);
|
|
8684
|
+
if (!normalizedAlias) {
|
|
8685
|
+
throw new TypeError("Invalid session alias");
|
|
8686
|
+
}
|
|
8687
|
+
const saved = {
|
|
8688
|
+
agentKey,
|
|
8689
|
+
sessionId,
|
|
8690
|
+
alias: normalizedAlias,
|
|
8691
|
+
updated_at: Date.now()
|
|
8692
|
+
};
|
|
8693
|
+
if (useMemoryStateStore()) {
|
|
8694
|
+
memoryAliases.set(getAliasKey(agentKey, sessionId), saved);
|
|
8695
|
+
return saved;
|
|
8696
|
+
}
|
|
8697
|
+
return withStateDb((db) => {
|
|
8698
|
+
db.prepare(
|
|
8699
|
+
`
|
|
8700
|
+
INSERT INTO session_aliases(agent_name, session_id, alias, updated_at)
|
|
8701
|
+
VALUES (?, ?, ?, ?)
|
|
8702
|
+
ON CONFLICT(agent_name, session_id) DO UPDATE SET
|
|
8703
|
+
alias = excluded.alias,
|
|
8704
|
+
updated_at = excluded.updated_at
|
|
8705
|
+
`
|
|
8706
|
+
).run(saved.agentKey, saved.sessionId, saved.alias, saved.updated_at);
|
|
8707
|
+
return saved;
|
|
8708
|
+
});
|
|
8709
|
+
}
|
|
8710
|
+
function deleteSessionAlias(agentKey, sessionId) {
|
|
8711
|
+
if (useMemoryStateStore()) {
|
|
8712
|
+
memoryAliases.delete(getAliasKey(agentKey, sessionId));
|
|
8713
|
+
return;
|
|
8714
|
+
}
|
|
8715
|
+
withStateDb((db) => {
|
|
8716
|
+
db.prepare(
|
|
8717
|
+
`
|
|
8718
|
+
DELETE FROM session_aliases
|
|
8719
|
+
WHERE agent_name = ? AND session_id = ?
|
|
8720
|
+
`
|
|
8721
|
+
).run(agentKey, sessionId);
|
|
8722
|
+
});
|
|
8723
|
+
}
|
|
9024
8724
|
var DASHBOARD_RECENT_LIMIT = 10;
|
|
9025
8725
|
function getTotalTokens(stats) {
|
|
9026
8726
|
return stats.total_tokens ?? stats.total_input_tokens + stats.total_output_tokens;
|
|
@@ -9235,8 +8935,8 @@ function searchRecentSessions(snapshot, options) {
|
|
|
9235
8935
|
matchType: "recent"
|
|
9236
8936
|
}));
|
|
9237
8937
|
}
|
|
9238
|
-
function deriveFileQuery(query,
|
|
9239
|
-
return options.file ?? (!
|
|
8938
|
+
function deriveFileQuery(query, parsed, options) {
|
|
8939
|
+
return options.file ?? (!parsed.text ? parsed.filters.file : void 0) ?? (!parsed.hasQualifiers && query ? parsed.text || query : "");
|
|
9240
8940
|
}
|
|
9241
8941
|
function mergeSearchResultSources(results, limit) {
|
|
9242
8942
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -9255,8 +8955,8 @@ function canSkipSessionsSearch(fileQuery, textQuery, options) {
|
|
|
9255
8955
|
fileQuery && !textQuery && !options.tools?.length && !options.tags?.length && options.from == null && options.to == null
|
|
9256
8956
|
);
|
|
9257
8957
|
}
|
|
9258
|
-
function searchIndexedSessions(query, textQuery,
|
|
9259
|
-
const fileQuery = deriveFileQuery(query,
|
|
8958
|
+
function searchIndexedSessions(query, textQuery, parsed, options) {
|
|
8959
|
+
const fileQuery = deriveFileQuery(query, parsed, options);
|
|
9260
8960
|
const fileResults = fileQuery ? searchFileActivitySessions(fileQuery, options) : [];
|
|
9261
8961
|
const sessionResults = canSkipSessionsSearch(fileQuery, textQuery, options) ? [] : searchSessions(query, options);
|
|
9262
8962
|
return mergeSearchResultSources([...fileResults, ...sessionResults], options.limit ?? 50);
|
|
@@ -9286,16 +8986,12 @@ export {
|
|
|
9286
8986
|
normalizeTitleText,
|
|
9287
8987
|
basenameTitle,
|
|
9288
8988
|
resolveSessionTitle,
|
|
9289
|
-
parsed,
|
|
9290
|
-
skipped,
|
|
9291
|
-
filtered,
|
|
9292
8989
|
cleanInternalText,
|
|
9293
8990
|
cleanMessagePart,
|
|
9294
8991
|
cleanMessageParts,
|
|
9295
8992
|
cleanParsedMessage,
|
|
9296
8993
|
cleanParsedMessages,
|
|
9297
8994
|
firstUserMessageTitle,
|
|
9298
|
-
perf,
|
|
9299
8995
|
getPricingRegistry,
|
|
9300
8996
|
hasBillablePricing,
|
|
9301
8997
|
refreshPricingCache,
|
|
@@ -9308,6 +9004,7 @@ export {
|
|
|
9308
9004
|
openDbReadOnly,
|
|
9309
9005
|
openDb,
|
|
9310
9006
|
isSqliteAvailable,
|
|
9007
|
+
perf,
|
|
9311
9008
|
fallbackDisplayName,
|
|
9312
9009
|
realFs,
|
|
9313
9010
|
isProjectIdentityKind,
|
|
@@ -9329,6 +9026,7 @@ export {
|
|
|
9329
9026
|
parseSearchQuery,
|
|
9330
9027
|
syncSessionSearchIndex,
|
|
9331
9028
|
syncSessionSearchIndexChanges,
|
|
9029
|
+
mergeSearchQueryOptions,
|
|
9332
9030
|
searchSessions,
|
|
9333
9031
|
listFileActivity,
|
|
9334
9032
|
listSessionFileActivity,
|
|
@@ -9353,11 +9051,16 @@ export {
|
|
|
9353
9051
|
ensureSessionTagsSync,
|
|
9354
9052
|
scanSessions,
|
|
9355
9053
|
scanSessionsAsync,
|
|
9356
|
-
|
|
9054
|
+
StateStorageUnavailableError,
|
|
9357
9055
|
listBookmarks,
|
|
9358
9056
|
upsertBookmark,
|
|
9359
9057
|
importBookmarks,
|
|
9360
9058
|
deleteBookmark,
|
|
9059
|
+
SESSION_ALIAS_MAX_LENGTH,
|
|
9060
|
+
normalizeSessionAlias,
|
|
9061
|
+
listSessionAliases,
|
|
9062
|
+
upsertSessionAlias,
|
|
9063
|
+
deleteSessionAlias,
|
|
9361
9064
|
DASHBOARD_RECENT_LIMIT,
|
|
9362
9065
|
getTotalTokens,
|
|
9363
9066
|
getSessionAgentName,
|
|
@@ -9367,4 +9070,4 @@ export {
|
|
|
9367
9070
|
buildDashboard,
|
|
9368
9071
|
executeSessionSearch
|
|
9369
9072
|
};
|
|
9370
|
-
//# sourceMappingURL=chunk-
|
|
9073
|
+
//# sourceMappingURL=chunk-VRVZJDNL.js.map
|