@ramarivera/coding-agent-langfuse 0.1.37 → 0.1.39

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 CHANGED
@@ -19,6 +19,17 @@ const defaultMaxRequestBytes = 12 * 1024 * 1024;
19
19
  const defaultMaxFieldBytes = 512 * 1024;
20
20
  const defaultStatePath = join(homedir(), ".local/state/coding-agent-langfuse/backfill-v6.json");
21
21
  const currentHost = hostname();
22
+ function projectMetadata(cwd) {
23
+ if (!cwd)
24
+ return {};
25
+ const normalized = cwd.replace(/[\\/]+$/, "");
26
+ const projectName = normalized.split(/[\\/]+/).filter(Boolean).at(-1);
27
+ return {
28
+ projectPath: cwd,
29
+ projectName,
30
+ projectFolder: projectName,
31
+ };
32
+ }
22
33
  function usage() {
23
34
  return `Usage: coding-agent-langfuse-backfill [options]
24
35
 
@@ -1204,6 +1215,7 @@ function toOtlp(events, options = {}) {
1204
1215
  const traceStartMs = sortedEvents[0]?.startMs ?? Date.now();
1205
1216
  const traceEndMs = Math.max(...sortedEvents.map((event) => event.endMs ?? event.startMs + 1), traceStartMs + 1);
1206
1217
  const shouldEmitRootSpan = sortedEvents.some((event) => event.recordId === "session");
1218
+ const firstProject = projectMetadata(first.cwd);
1207
1219
  const rootAttributes = [
1208
1220
  attr("service.name", `agent.${first.agent}`),
1209
1221
  attr("deployment.environment", "local"),
@@ -1223,6 +1235,9 @@ function toOtlp(events, options = {}) {
1223
1235
  attr("langfuse.trace.metadata.machine", currentHost),
1224
1236
  attr("langfuse.trace.metadata.source_path", first.sourcePath),
1225
1237
  attr("langfuse.trace.metadata.cwd", first.cwd),
1238
+ attr("langfuse.trace.metadata.project_path", firstProject.projectPath),
1239
+ attr("langfuse.trace.metadata.project_name", firstProject.projectName),
1240
+ attr("langfuse.trace.metadata.project_folder", firstProject.projectFolder),
1226
1241
  attr("langfuse.observation.metadata.agent", first.agent),
1227
1242
  attr("langfuse.observation.metadata.host", currentHost),
1228
1243
  attr("langfuse.observation.metadata.machine", currentHost),
@@ -1230,8 +1245,14 @@ function toOtlp(events, options = {}) {
1230
1245
  attr("langfuse.observation.metadata.record_id", "session-root"),
1231
1246
  attr("langfuse.observation.metadata.source_path", first.sourcePath),
1232
1247
  attr("langfuse.observation.metadata.cwd", first.cwd),
1248
+ attr("langfuse.observation.metadata.project_path", firstProject.projectPath),
1249
+ attr("langfuse.observation.metadata.project_name", firstProject.projectName),
1250
+ attr("langfuse.observation.metadata.project_folder", firstProject.projectFolder),
1233
1251
  attr("source.path", first.sourcePath),
1234
1252
  attr("cwd", first.cwd),
1253
+ attr("project.path", firstProject.projectPath),
1254
+ attr("project.name", firstProject.projectName),
1255
+ attr("project.folder", firstProject.projectFolder),
1235
1256
  ].filter((item) => Boolean(item));
1236
1257
  const rootSpan = {
1237
1258
  traceId: traceId(first),
@@ -1251,6 +1272,7 @@ function toOtlp(events, options = {}) {
1251
1272
  const generation = isGenerationEvent(event);
1252
1273
  const usage = usageDetails(event.usage);
1253
1274
  const cost = costDetails(event.usage, modelName);
1275
+ const eventProject = projectMetadata(event.cwd);
1254
1276
  const costForLangfuse = cost === undefined
1255
1277
  ? undefined
1256
1278
  : {
@@ -1288,6 +1310,9 @@ function toOtlp(events, options = {}) {
1288
1310
  attr("langfuse.observation.metadata.record_id", event.recordId),
1289
1311
  attr("langfuse.observation.metadata.source_path", event.sourcePath),
1290
1312
  attr("langfuse.observation.metadata.cwd", event.cwd),
1313
+ attr("langfuse.observation.metadata.project_path", eventProject.projectPath),
1314
+ attr("langfuse.observation.metadata.project_name", eventProject.projectName),
1315
+ attr("langfuse.observation.metadata.project_folder", eventProject.projectFolder),
1291
1316
  attr("langfuse.observation.metadata.model", modelName ?? event.model),
1292
1317
  attr("langfuse.observation.metadata.provider", event.provider),
1293
1318
  attr("langfuse.observation.metadata.cost_source", cost?.source),
@@ -1295,6 +1320,9 @@ function toOtlp(events, options = {}) {
1295
1320
  attr("langfuse.observation.output", event.output),
1296
1321
  attr("source.path", event.sourcePath),
1297
1322
  attr("cwd", event.cwd),
1323
+ attr("project.path", eventProject.projectPath),
1324
+ attr("project.name", eventProject.projectName),
1325
+ attr("project.folder", eventProject.projectFolder),
1298
1326
  attr("role", event.role),
1299
1327
  attr("agent.model", event.model),
1300
1328
  attr("agent.provider", event.provider),
package/dist/service.d.ts CHANGED
@@ -34,5 +34,6 @@ type ServicePlan = {
34
34
  declare function parseServiceArgs(argv: string[]): ServiceOptions;
35
35
  declare function buildServicePlan(options: ServiceOptions): ServicePlan;
36
36
  declare function serviceMain(argv?: string[]): Promise<ServicePlan>;
37
+ declare function redactStatusOutput(output: string): string;
37
38
  declare function lifecycleEnv(): NodeJS.ProcessEnv;
38
- export { type ServiceOptions, type ServicePlan, buildServicePlan, parseServiceArgs, serviceMain, lifecycleEnv, };
39
+ export { type ServiceOptions, type ServicePlan, buildServicePlan, redactStatusOutput, parseServiceArgs, serviceMain, lifecycleEnv, };
package/dist/service.js CHANGED
@@ -249,7 +249,7 @@ async function serviceMain(argv = process.argv.slice(2)) {
249
249
  return plan;
250
250
  }
251
251
  if (options.action === "status") {
252
- runCommands(plan.statusCommands);
252
+ runStatusCommands(plan.statusCommands);
253
253
  console.log(JSON.stringify(plan, null, 2));
254
254
  return plan;
255
255
  }
@@ -452,6 +452,31 @@ function runCommands(commands, options = {}) {
452
452
  }
453
453
  }
454
454
  }
455
+ function runStatusCommands(commands) {
456
+ const env = lifecycleEnv();
457
+ for (const command of commands) {
458
+ const output = execFileSync(command[0], command.slice(1), {
459
+ encoding: "utf8",
460
+ env,
461
+ stdio: ["ignore", "pipe", "pipe"],
462
+ });
463
+ process.stdout.write(redactStatusOutput(output));
464
+ }
465
+ }
466
+ function redactStatusOutput(output) {
467
+ return output
468
+ .split(/\r?\n/)
469
+ .map((line) => {
470
+ if (/^\s*[A-Za-z_][A-Za-z0-9_()]*\s*=>\s*/.test(line)) {
471
+ return line.replace(/=>\s*.*/, "=> [redacted]");
472
+ }
473
+ if (/^\s*(Path|PATH|.*(?:TOKEN|KEY|SECRET|PASSWORD|AUTH|CREDENTIAL).*)\s*:/i.test(line)) {
474
+ return line.replace(/:\s*.*/, ": [redacted]");
475
+ }
476
+ return line;
477
+ })
478
+ .join("\n");
479
+ }
455
480
  function lifecycleEnv() {
456
481
  const keys = [
457
482
  "PATH",
@@ -499,4 +524,4 @@ function escapeXml(value) {
499
524
  .replaceAll('"', "&quot;")
500
525
  .replaceAll("'", "&apos;");
501
526
  }
502
- export { buildServicePlan, parseServiceArgs, serviceMain, lifecycleEnv, };
527
+ export { buildServicePlan, redactStatusOutput, parseServiceArgs, serviceMain, lifecycleEnv, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramarivera/coding-agent-langfuse",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "description": "Universal coding-agent Langfuse backfiller and live OTLP helpers",
5
5
  "type": "module",
6
6
  "license": "MIT",