@ramarivera/coding-agent-langfuse 0.1.24 → 0.1.26
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 +32 -4
- package/package.json +1 -1
package/dist/backfill.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
5
|
-
import { homedir } from "node:os";
|
|
4
|
+
import { existsSync, mkdirSync, renameSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
5
|
+
import { hostname, homedir } from "node:os";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
7
|
const allAgents = ["claude", "codex", "grok", "opencode", "pi"];
|
|
8
8
|
const importIdentityVersion = "v8-cached-input-token-split";
|
|
@@ -16,6 +16,7 @@ const importIdentityVersions = {
|
|
|
16
16
|
const defaultEndpoint = "https://langfuse.ai.roxasroot.net/otel/v1/traces";
|
|
17
17
|
const deadRemoteEndpoint = "http://langfuse.ai.roxasroot.net:14318/v1/traces";
|
|
18
18
|
const defaultStatePath = join(homedir(), ".local/state/coding-agent-langfuse/backfill-v6.json");
|
|
19
|
+
const currentHost = hostname();
|
|
19
20
|
function usage() {
|
|
20
21
|
return `Usage: coding-agent-langfuse-backfill [options]
|
|
21
22
|
|
|
@@ -157,7 +158,9 @@ function loadState(path) {
|
|
|
157
158
|
}
|
|
158
159
|
function saveState(path, state) {
|
|
159
160
|
mkdirSync(dirname(path), { recursive: true });
|
|
160
|
-
|
|
161
|
+
const tempPath = `${path}.${process.pid}.tmp`;
|
|
162
|
+
writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}\n`);
|
|
163
|
+
renameSync(tempPath, path);
|
|
161
164
|
}
|
|
162
165
|
function listFiles(root, predicate) {
|
|
163
166
|
if (!existsSync(root))
|
|
@@ -566,6 +569,7 @@ function claudeEvents(homeDir) {
|
|
|
566
569
|
return genericJsonlEvents("claude", files, "claude session");
|
|
567
570
|
}
|
|
568
571
|
function piEvents(homeDir) {
|
|
572
|
+
const seenMessageIds = new Set();
|
|
569
573
|
const files = [
|
|
570
574
|
...listFiles(join(homeDir, ".pi/agent/sessions"), (path) => path.endsWith(".jsonl")),
|
|
571
575
|
...listFiles(join(homeDir, ".pi/agent"), (path) => path.endsWith("run-history.jsonl")),
|
|
@@ -594,7 +598,14 @@ function piEvents(homeDir) {
|
|
|
594
598
|
const message = asRecord(row.message);
|
|
595
599
|
const usage = normalizeUsage(message.usage);
|
|
596
600
|
const role = asString(message.role);
|
|
597
|
-
const
|
|
601
|
+
const explicitMessageId = asString(row.id);
|
|
602
|
+
const messageId = explicitMessageId ?? `message-${stableId(path)}-${index}`;
|
|
603
|
+
const dedupeKey = explicitMessageId === undefined
|
|
604
|
+
? `${path}:${messageId}`
|
|
605
|
+
: explicitMessageId;
|
|
606
|
+
if (seenMessageIds.has(dedupeKey))
|
|
607
|
+
continue;
|
|
608
|
+
seenMessageIds.add(dedupeKey);
|
|
598
609
|
const toolCallId = asString(message.toolCallId);
|
|
599
610
|
events.push({
|
|
600
611
|
agent: "pi",
|
|
@@ -1140,16 +1151,24 @@ function toOtlp(events) {
|
|
|
1140
1151
|
attr("session.id", first.sessionId),
|
|
1141
1152
|
attr("langfuse.observation.type", "span"),
|
|
1142
1153
|
attr("agent.name", first.agent),
|
|
1154
|
+
attr("host.name", currentHost),
|
|
1143
1155
|
attr("agent.session_id", first.sessionId),
|
|
1144
1156
|
attr("agent.record_id", "session-root"),
|
|
1145
1157
|
attr("agent.event_count", sortedEvents.length),
|
|
1146
1158
|
attr("langfuse.trace.metadata.agent", first.agent),
|
|
1159
|
+
attr("langfuse.trace.metadata.host", currentHost),
|
|
1160
|
+
attr("langfuse.trace.metadata.machine", currentHost),
|
|
1147
1161
|
attr("langfuse.trace.metadata.source_path", first.sourcePath),
|
|
1148
1162
|
attr("langfuse.trace.metadata.cwd", first.cwd),
|
|
1149
1163
|
attr("langfuse.trace.input", firstInputEvent?.input),
|
|
1150
1164
|
attr("langfuse.trace.output", lastOutputEvent?.output),
|
|
1151
1165
|
attr("langfuse.observation.metadata.agent", first.agent),
|
|
1166
|
+
attr("langfuse.observation.metadata.host", currentHost),
|
|
1167
|
+
attr("langfuse.observation.metadata.machine", currentHost),
|
|
1168
|
+
attr("langfuse.observation.metadata.session_id", first.sessionId),
|
|
1152
1169
|
attr("langfuse.observation.metadata.record_id", "session-root"),
|
|
1170
|
+
attr("langfuse.observation.metadata.source_path", first.sourcePath),
|
|
1171
|
+
attr("langfuse.observation.metadata.cwd", first.cwd),
|
|
1153
1172
|
attr("source.path", first.sourcePath),
|
|
1154
1173
|
attr("cwd", first.cwd),
|
|
1155
1174
|
].filter((item) => Boolean(item));
|
|
@@ -1196,16 +1215,25 @@ function toOtlp(events) {
|
|
|
1196
1215
|
attr("gen_ai.usage.total_tokens", usage?.total),
|
|
1197
1216
|
attr("gen_ai.usage.cost", cost?.total),
|
|
1198
1217
|
attr("agent.name", event.agent),
|
|
1218
|
+
attr("host.name", currentHost),
|
|
1199
1219
|
attr("agent.session_id", event.sessionId),
|
|
1200
1220
|
attr("agent.record_id", event.recordId),
|
|
1201
1221
|
attr("agent.original_start_time", new Date(event.startMs).toISOString()),
|
|
1202
1222
|
attr("agent.original_end_time", event.endMs === undefined ? undefined : new Date(event.endMs).toISOString()),
|
|
1203
1223
|
attr("langfuse.trace.metadata.agent", event.agent),
|
|
1224
|
+
attr("langfuse.trace.metadata.host", currentHost),
|
|
1225
|
+
attr("langfuse.trace.metadata.machine", currentHost),
|
|
1204
1226
|
attr("langfuse.trace.metadata.source_path", event.sourcePath),
|
|
1227
|
+
attr("langfuse.trace.metadata.cwd", event.cwd),
|
|
1205
1228
|
attr("langfuse.trace.metadata.model", event.model),
|
|
1206
1229
|
attr("langfuse.trace.metadata.provider", event.provider),
|
|
1207
1230
|
attr("langfuse.observation.metadata.agent", event.agent),
|
|
1231
|
+
attr("langfuse.observation.metadata.host", currentHost),
|
|
1232
|
+
attr("langfuse.observation.metadata.machine", currentHost),
|
|
1233
|
+
attr("langfuse.observation.metadata.session_id", event.sessionId),
|
|
1208
1234
|
attr("langfuse.observation.metadata.record_id", event.recordId),
|
|
1235
|
+
attr("langfuse.observation.metadata.source_path", event.sourcePath),
|
|
1236
|
+
attr("langfuse.observation.metadata.cwd", event.cwd),
|
|
1209
1237
|
attr("langfuse.observation.metadata.model", modelName ?? event.model),
|
|
1210
1238
|
attr("langfuse.observation.metadata.provider", event.provider),
|
|
1211
1239
|
attr("langfuse.observation.metadata.cost_source", cost?.source),
|