@ramarivera/coding-agent-langfuse 0.1.16 → 0.1.17
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 +12 -1
- package/dist/backfill.d.ts +10 -2
- package/dist/backfill.js +82 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,18 @@ npx @ramarivera/coding-agent-langfuse@latest \
|
|
|
18
18
|
--agents claude,codex,grok,pi,opencode \
|
|
19
19
|
--endpoint https://langfuse.ai.roxasroot.net/otel/v1/traces \
|
|
20
20
|
--state "$HOME/.local/state/coding-agent-langfuse/backfill-v6.json" \
|
|
21
|
-
--batch-size
|
|
21
|
+
--batch-size 10
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Run live incremental forwarding without putting inference behind a gateway:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
npx @ramarivera/coding-agent-langfuse@latest \
|
|
28
|
+
--agents codex \
|
|
29
|
+
--endpoint https://langfuse.ai.roxasroot.net/otel/v1/traces \
|
|
30
|
+
--state "$HOME/.local/state/coding-agent-langfuse/live-codex.json" \
|
|
31
|
+
--batch-size 10 \
|
|
32
|
+
--follow
|
|
22
33
|
```
|
|
23
34
|
|
|
24
35
|
The importer is fail-fast: the first failed OTLP POST stops the run, prints the
|
package/dist/backfill.d.ts
CHANGED
|
@@ -33,6 +33,9 @@ type BackfillOptions = {
|
|
|
33
33
|
statePath: string;
|
|
34
34
|
homeDir: string;
|
|
35
35
|
dryRun: boolean;
|
|
36
|
+
follow: boolean;
|
|
37
|
+
pollIntervalMs: number;
|
|
38
|
+
idleExitAfterMs?: number;
|
|
36
39
|
limit?: number;
|
|
37
40
|
sinceMs?: number;
|
|
38
41
|
untilMs?: number;
|
|
@@ -50,6 +53,10 @@ type RunSummary = {
|
|
|
50
53
|
endpoint: string;
|
|
51
54
|
statePath: string;
|
|
52
55
|
};
|
|
56
|
+
type FollowSummary = RunSummary & {
|
|
57
|
+
iterations: number;
|
|
58
|
+
follow: true;
|
|
59
|
+
};
|
|
53
60
|
declare function parseArgs(argv: string[]): BackfillOptions;
|
|
54
61
|
declare function codexEvents(homeDir: string): BackfillEvent[];
|
|
55
62
|
declare function claudeEvents(homeDir: string): BackfillEvent[];
|
|
@@ -60,5 +67,6 @@ declare function fingerprint(event: BackfillEvent): string;
|
|
|
60
67
|
declare function toOtlp(events: BackfillEvent[]): Record<string, unknown>;
|
|
61
68
|
declare function discoverEvents(options: BackfillOptions): BackfillEvent[];
|
|
62
69
|
declare function run(options: BackfillOptions): Promise<RunSummary>;
|
|
63
|
-
declare function
|
|
64
|
-
|
|
70
|
+
declare function follow(options: BackfillOptions): Promise<FollowSummary>;
|
|
71
|
+
declare function main(argv?: string[]): Promise<RunSummary | FollowSummary>;
|
|
72
|
+
export { type BackfillEvent, type BackfillOptions, claudeEvents, codexEvents, discoverEvents, fingerprint, follow, grokEvents, main, opencodeEvents, parseArgs, piEvents, run, toOtlp, };
|
package/dist/backfill.js
CHANGED
|
@@ -21,6 +21,9 @@ Options:
|
|
|
21
21
|
--until ISO_OR_MS Only import events before or at this timestamp
|
|
22
22
|
--limit N Stop after N unsent events
|
|
23
23
|
--batch-size N OTLP spans per POST (default: 50)
|
|
24
|
+
--follow Keep scanning and sending newly written events
|
|
25
|
+
--poll-interval-ms N Delay between --follow scans (default: 5000)
|
|
26
|
+
--idle-exit-after-ms N Stop --follow after this much time without new sends
|
|
24
27
|
--dry-run Discover and dedupe without sending or mutating state
|
|
25
28
|
--help Show this help
|
|
26
29
|
`;
|
|
@@ -34,6 +37,9 @@ function parseArgs(argv) {
|
|
|
34
37
|
let sinceMs;
|
|
35
38
|
let untilMs;
|
|
36
39
|
let batchSize = 50;
|
|
40
|
+
let follow = false;
|
|
41
|
+
let pollIntervalMs = 5_000;
|
|
42
|
+
let idleExitAfterMs;
|
|
37
43
|
const agents = new Set(allAgents);
|
|
38
44
|
for (let i = 0; i < argv.length; i++) {
|
|
39
45
|
const arg = argv[i];
|
|
@@ -75,6 +81,15 @@ function parseArgs(argv) {
|
|
|
75
81
|
else if (arg === "--batch-size") {
|
|
76
82
|
batchSize = Number.parseInt(next(), 10);
|
|
77
83
|
}
|
|
84
|
+
else if (arg === "--follow") {
|
|
85
|
+
follow = true;
|
|
86
|
+
}
|
|
87
|
+
else if (arg === "--poll-interval-ms") {
|
|
88
|
+
pollIntervalMs = Number.parseInt(next(), 10);
|
|
89
|
+
}
|
|
90
|
+
else if (arg === "--idle-exit-after-ms") {
|
|
91
|
+
idleExitAfterMs = Number.parseInt(next(), 10);
|
|
92
|
+
}
|
|
78
93
|
else if (arg === "--since") {
|
|
79
94
|
sinceMs = parseTime(next());
|
|
80
95
|
}
|
|
@@ -88,6 +103,13 @@ function parseArgs(argv) {
|
|
|
88
103
|
if (!Number.isFinite(batchSize) || batchSize < 1) {
|
|
89
104
|
throw new Error("--batch-size must be a positive integer");
|
|
90
105
|
}
|
|
106
|
+
if (!Number.isFinite(pollIntervalMs) || pollIntervalMs < 1) {
|
|
107
|
+
throw new Error("--poll-interval-ms must be a positive integer");
|
|
108
|
+
}
|
|
109
|
+
if (idleExitAfterMs !== undefined &&
|
|
110
|
+
(!Number.isFinite(idleExitAfterMs) || idleExitAfterMs < 1)) {
|
|
111
|
+
throw new Error("--idle-exit-after-ms must be a positive integer");
|
|
112
|
+
}
|
|
91
113
|
if (limit !== undefined && (!Number.isFinite(limit) || limit < 1)) {
|
|
92
114
|
throw new Error("--limit must be a positive integer");
|
|
93
115
|
}
|
|
@@ -97,6 +119,9 @@ function parseArgs(argv) {
|
|
|
97
119
|
statePath,
|
|
98
120
|
homeDir,
|
|
99
121
|
dryRun,
|
|
122
|
+
follow,
|
|
123
|
+
pollIntervalMs,
|
|
124
|
+
idleExitAfterMs,
|
|
100
125
|
limit,
|
|
101
126
|
sinceMs,
|
|
102
127
|
untilMs,
|
|
@@ -1035,8 +1060,63 @@ async function run(options) {
|
|
|
1035
1060
|
statePath: options.statePath,
|
|
1036
1061
|
};
|
|
1037
1062
|
}
|
|
1063
|
+
function mergeSummary(base, next) {
|
|
1064
|
+
return {
|
|
1065
|
+
discovered: Object.fromEntries(allAgents.map((agent) => [
|
|
1066
|
+
agent,
|
|
1067
|
+
Math.max(base.discovered[agent] ?? 0, next.discovered[agent] ?? 0),
|
|
1068
|
+
])),
|
|
1069
|
+
sent: base.sent + next.sent,
|
|
1070
|
+
skipped: next.skipped,
|
|
1071
|
+
failed: base.failed + next.failed,
|
|
1072
|
+
notAttempted: next.notAttempted,
|
|
1073
|
+
aborted: base.aborted || next.aborted,
|
|
1074
|
+
...(next.error ? { error: next.error } : base.error ? { error: base.error } : {}),
|
|
1075
|
+
dryRun: base.dryRun,
|
|
1076
|
+
endpoint: base.endpoint,
|
|
1077
|
+
statePath: base.statePath,
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
function sleep(ms) {
|
|
1081
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1082
|
+
}
|
|
1083
|
+
async function follow(options) {
|
|
1084
|
+
let iterations = 0;
|
|
1085
|
+
let lastSendOrStartMs = Date.now();
|
|
1086
|
+
let aggregate;
|
|
1087
|
+
while (true) {
|
|
1088
|
+
iterations += 1;
|
|
1089
|
+
const summary = await run(options);
|
|
1090
|
+
aggregate = aggregate === undefined ? summary : mergeSummary(aggregate, summary);
|
|
1091
|
+
if (summary.sent > 0)
|
|
1092
|
+
lastSendOrStartMs = Date.now();
|
|
1093
|
+
if (summary.aborted)
|
|
1094
|
+
break;
|
|
1095
|
+
if (options.idleExitAfterMs !== undefined &&
|
|
1096
|
+
Date.now() - lastSendOrStartMs >= options.idleExitAfterMs) {
|
|
1097
|
+
break;
|
|
1098
|
+
}
|
|
1099
|
+
await sleep(options.pollIntervalMs);
|
|
1100
|
+
}
|
|
1101
|
+
return {
|
|
1102
|
+
...(aggregate ?? {
|
|
1103
|
+
discovered: Object.fromEntries(allAgents.map((agent) => [agent, 0])),
|
|
1104
|
+
sent: 0,
|
|
1105
|
+
skipped: 0,
|
|
1106
|
+
failed: 0,
|
|
1107
|
+
notAttempted: 0,
|
|
1108
|
+
aborted: false,
|
|
1109
|
+
dryRun: options.dryRun,
|
|
1110
|
+
endpoint: options.endpoint,
|
|
1111
|
+
statePath: options.statePath,
|
|
1112
|
+
}),
|
|
1113
|
+
iterations,
|
|
1114
|
+
follow: true,
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1038
1117
|
async function main(argv = process.argv.slice(2)) {
|
|
1039
|
-
const
|
|
1118
|
+
const options = parseArgs(argv);
|
|
1119
|
+
const summary = options.follow ? await follow(options) : await run(options);
|
|
1040
1120
|
console.log(JSON.stringify(summary, null, 2));
|
|
1041
1121
|
return summary;
|
|
1042
1122
|
}
|
|
@@ -1050,4 +1130,4 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
1050
1130
|
process.exit(1);
|
|
1051
1131
|
}
|
|
1052
1132
|
}
|
|
1053
|
-
export { claudeEvents, codexEvents, discoverEvents, fingerprint, grokEvents, main, opencodeEvents, parseArgs, piEvents, run, toOtlp, };
|
|
1133
|
+
export { claudeEvents, codexEvents, discoverEvents, fingerprint, follow, grokEvents, main, opencodeEvents, parseArgs, piEvents, run, toOtlp, };
|