@ramarivera/coding-agent-langfuse 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backfill.js +87 -20
- package/package.json +1 -1
package/dist/backfill.js
CHANGED
|
@@ -7,8 +7,11 @@ import { dirname, join } from "node:path";
|
|
|
7
7
|
const allAgents = ["claude", "codex", "grok", "opencode", "pi"];
|
|
8
8
|
const importIdentityVersion = "v8-cached-input-token-split";
|
|
9
9
|
const importIdentityVersions = {
|
|
10
|
+
claude: "v11-tool-results",
|
|
10
11
|
codex: "v9-codex-conversation-events",
|
|
12
|
+
grok: "v11-chat-history-only",
|
|
11
13
|
opencode: "v10-opencode-message-parts",
|
|
14
|
+
pi: "v11-tool-results",
|
|
12
15
|
};
|
|
13
16
|
const defaultEndpoint = "https://langfuse.ai.roxasroot.net/otel/v1/traces";
|
|
14
17
|
const deadRemoteEndpoint = "http://langfuse.ai.roxasroot.net:14318/v1/traces";
|
|
@@ -590,33 +593,56 @@ function piEvents(homeDir) {
|
|
|
590
593
|
continue;
|
|
591
594
|
const message = asRecord(row.message);
|
|
592
595
|
const usage = normalizeUsage(message.usage);
|
|
596
|
+
const role = asString(message.role);
|
|
597
|
+
const messageId = asString(row.id) ?? `message-${index}`;
|
|
598
|
+
const toolCallId = asString(message.toolCallId);
|
|
593
599
|
events.push({
|
|
594
600
|
agent: "pi",
|
|
595
601
|
sourcePath: path,
|
|
596
602
|
sessionId,
|
|
597
|
-
recordId:
|
|
598
|
-
name:
|
|
599
|
-
|
|
603
|
+
recordId: messageId,
|
|
604
|
+
name: role === "toolResult"
|
|
605
|
+
? `pi toolResult ${asString(message.toolName) ?? "call"}`
|
|
606
|
+
: `pi ${role ?? "message"}`,
|
|
607
|
+
role,
|
|
600
608
|
model: asString(message.model) ?? asString(row.model),
|
|
601
609
|
provider: asString(message.provider),
|
|
602
610
|
cwd,
|
|
603
611
|
startMs: getTimestampMs(row.timestamp ?? message.timestamp, startMs + index),
|
|
604
612
|
endMs: getTimestampMs(message.completed, startMs + index + 1),
|
|
605
|
-
parentRecordId:
|
|
606
|
-
|
|
613
|
+
parentRecordId: toolCallId
|
|
614
|
+
? `tool-${toolCallId}`
|
|
615
|
+
: asString(row.parentId) ?? "session",
|
|
616
|
+
input: role === "user"
|
|
607
617
|
? extractText(message.content)
|
|
608
618
|
: undefined,
|
|
609
|
-
output:
|
|
619
|
+
output: role === "assistant" || role === "toolResult"
|
|
610
620
|
? extractText(message.content)
|
|
611
621
|
: undefined,
|
|
612
622
|
usage,
|
|
623
|
+
metadata: pick(message, ["toolCallId", "toolName", "isError", "stopReason"]),
|
|
613
624
|
});
|
|
625
|
+
for (const reasoning of reasoningFromContent(message.content)) {
|
|
626
|
+
events.push({
|
|
627
|
+
agent: "pi",
|
|
628
|
+
sourcePath: path,
|
|
629
|
+
sessionId,
|
|
630
|
+
recordId: `reasoning-${messageId}-${reasoning.index}`,
|
|
631
|
+
name: "pi reasoning",
|
|
632
|
+
cwd,
|
|
633
|
+
model: asString(message.model),
|
|
634
|
+
startMs: getTimestampMs(row.timestamp, startMs + index),
|
|
635
|
+
parentRecordId: messageId,
|
|
636
|
+
output: reasoning.text,
|
|
637
|
+
metadata: { has_signature: reasoning.hasSignature },
|
|
638
|
+
});
|
|
639
|
+
}
|
|
614
640
|
for (const tool of toolCallsFromContent(message.content)) {
|
|
615
641
|
events.push({
|
|
616
642
|
agent: "pi",
|
|
617
643
|
sourcePath: path,
|
|
618
644
|
sessionId,
|
|
619
|
-
recordId: tool.id
|
|
645
|
+
recordId: `tool-${tool.id}`,
|
|
620
646
|
name: `pi tool ${tool.name}`,
|
|
621
647
|
cwd,
|
|
622
648
|
model: asString(message.model),
|
|
@@ -630,7 +656,7 @@ function piEvents(homeDir) {
|
|
|
630
656
|
});
|
|
631
657
|
}
|
|
632
658
|
function grokEvents(homeDir) {
|
|
633
|
-
const files = listFiles(join(homeDir, ".grok/sessions"), (path) => path.endsWith(".jsonl"));
|
|
659
|
+
const files = listFiles(join(homeDir, ".grok/sessions"), (path) => path.endsWith("chat_history.jsonl"));
|
|
634
660
|
return genericJsonlEvents("grok", files, "grok session");
|
|
635
661
|
}
|
|
636
662
|
function opencodeEvents(homeDir, rowLimit) {
|
|
@@ -866,6 +892,12 @@ function genericJsonlEvents(agent, files, sessionName) {
|
|
|
866
892
|
for (const [index, row] of rows.entries()) {
|
|
867
893
|
const message = asRecord(row.message);
|
|
868
894
|
const role = asString(message.role) ?? asString(row.type);
|
|
895
|
+
const recordId = asString(row.uuid) ??
|
|
896
|
+
asString(row.id) ??
|
|
897
|
+
asString(row.toolUseID) ??
|
|
898
|
+
`row-${index}`;
|
|
899
|
+
const toolUseId = asString(row.toolUseID) ?? asString(row.tool_use_id);
|
|
900
|
+
const content = message.content ?? row.content;
|
|
869
901
|
const timestamp = getTimestampMs(row.timestamp ?? row.time_created, startMs + index);
|
|
870
902
|
const usage = normalizeUsage(message.usage ?? row.usage);
|
|
871
903
|
events.push({
|
|
@@ -873,22 +905,23 @@ function genericJsonlEvents(agent, files, sessionName) {
|
|
|
873
905
|
sourcePath: path,
|
|
874
906
|
sessionId: asString(row.sessionId) ?? asString(row.session_id) ??
|
|
875
907
|
sessionId,
|
|
876
|
-
recordId
|
|
877
|
-
|
|
878
|
-
asString(row.
|
|
879
|
-
|
|
880
|
-
name: `${agent} ${role ?? "event"}`,
|
|
908
|
+
recordId,
|
|
909
|
+
name: role === "tool_result" || role === "toolResult"
|
|
910
|
+
? `${agent} toolResult ${asString(row.toolName) ?? "call"}`
|
|
911
|
+
: `${agent} ${role ?? "event"}`,
|
|
881
912
|
role,
|
|
882
913
|
model: asString(getPath(message, ["model"])) ?? asString(row.model),
|
|
883
914
|
cwd: asString(row.cwd) ?? cwd,
|
|
884
915
|
startMs: timestamp,
|
|
885
|
-
parentRecordId:
|
|
886
|
-
|
|
916
|
+
parentRecordId: toolUseId
|
|
917
|
+
? `tool-${toolUseId}`
|
|
918
|
+
: asString(row.parentUuid) ?? asString(row.parentId) ?? "session",
|
|
887
919
|
input: role === "user"
|
|
888
|
-
? extractText(
|
|
920
|
+
? extractText(content)
|
|
889
921
|
: undefined,
|
|
890
|
-
output: role === "assistant"
|
|
891
|
-
|
|
922
|
+
output: role === "assistant" || role === "tool_result" ||
|
|
923
|
+
role === "toolResult"
|
|
924
|
+
? extractText(content)
|
|
892
925
|
: undefined,
|
|
893
926
|
usage,
|
|
894
927
|
metadata: pick(row, [
|
|
@@ -899,12 +932,26 @@ function genericJsonlEvents(agent, files, sessionName) {
|
|
|
899
932
|
"error",
|
|
900
933
|
]),
|
|
901
934
|
});
|
|
902
|
-
for (const
|
|
935
|
+
for (const reasoning of reasoningFromContent(content)) {
|
|
936
|
+
events.push({
|
|
937
|
+
agent,
|
|
938
|
+
sourcePath: path,
|
|
939
|
+
sessionId,
|
|
940
|
+
recordId: `reasoning-${recordId}-${reasoning.index}`,
|
|
941
|
+
name: `${agent} reasoning`,
|
|
942
|
+
cwd,
|
|
943
|
+
startMs: timestamp,
|
|
944
|
+
parentRecordId: recordId,
|
|
945
|
+
output: reasoning.text,
|
|
946
|
+
metadata: { has_signature: reasoning.hasSignature },
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
for (const tool of toolCallsFromContent(content)) {
|
|
903
950
|
events.push({
|
|
904
951
|
agent,
|
|
905
952
|
sourcePath: path,
|
|
906
953
|
sessionId,
|
|
907
|
-
recordId: tool.id
|
|
954
|
+
recordId: `tool-${tool.id}`,
|
|
908
955
|
name: `${agent} tool ${tool.name}`,
|
|
909
956
|
cwd,
|
|
910
957
|
startMs: timestamp,
|
|
@@ -934,6 +981,26 @@ function toolCallsFromContent(content) {
|
|
|
934
981
|
];
|
|
935
982
|
});
|
|
936
983
|
}
|
|
984
|
+
function reasoningFromContent(content) {
|
|
985
|
+
if (!Array.isArray(content))
|
|
986
|
+
return [];
|
|
987
|
+
return content.flatMap((item, index) => {
|
|
988
|
+
const record = asRecord(item);
|
|
989
|
+
const type = asString(record.type);
|
|
990
|
+
if (type !== "thinking" && type !== "reasoning")
|
|
991
|
+
return [];
|
|
992
|
+
const text = extractText(record.thinking ?? record.text, 8000);
|
|
993
|
+
if (!text)
|
|
994
|
+
return [];
|
|
995
|
+
return [
|
|
996
|
+
{
|
|
997
|
+
index,
|
|
998
|
+
text,
|
|
999
|
+
hasSignature: record.thinkingSignature !== undefined || record.signature !== undefined,
|
|
1000
|
+
},
|
|
1001
|
+
];
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
937
1004
|
function pick(source, keys) {
|
|
938
1005
|
const out = {};
|
|
939
1006
|
for (const key of keys) {
|