@ramarivera/coding-agent-langfuse 0.1.33 → 0.1.35

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 CHANGED
@@ -77,6 +77,12 @@ The Windows path intentionally uses a per-user Scheduled Task for the default
77
77
  `npx` workflow. A true Windows SCM service needs an installed wrapper or native
78
78
  service binary; raw `sc.exe` is not a good fit for a transient npm command.
79
79
 
80
+ The generated services are package-manager agnostic. By default the installer
81
+ uses `npx` through the service `PATH` (`/usr/bin/env npx` on macOS and Linux)
82
+ and captures the current `PATH`; use `--npx-path` and `--path` when installing
83
+ from a shell manager such as Homebrew, nvm, fnm, Volta, asdf, mise, or a system
84
+ Node.js install.
85
+
80
86
  ## Backfill windows
81
87
 
82
88
  Backfill only a timeframe when repairing a host or replaying a recent window:
package/dist/service.d.ts CHANGED
@@ -13,6 +13,7 @@ type ServiceOptions = {
13
13
  batchSize: number;
14
14
  pollIntervalMs: number;
15
15
  postDelayMs: number;
16
+ npxPath: string;
16
17
  since?: string;
17
18
  dryRun: boolean;
18
19
  start: boolean;
package/dist/service.js CHANGED
@@ -20,6 +20,7 @@ Service options:
20
20
  --state PATH Dedupe state file
21
21
  --home PATH Home directory to scan (default: current user home)
22
22
  --package-spec SPEC npx package spec (default: ${defaultPackageSpec})
23
+ --npx-path PATH npx executable path for host services (default: auto-detected)
23
24
  --batch-size N OTLP spans per POST (default: 10)
24
25
  --poll-interval-ms N Delay between --follow scans (default: 5000)
25
26
  --post-delay-ms N Delay after each successful OTLP POST (default: 0)
@@ -44,6 +45,7 @@ function parseServiceArgs(argv) {
44
45
  let statePath = "";
45
46
  let name = "";
46
47
  let packageSpec = defaultPackageSpec;
48
+ let npxPath = process.env.CODING_AGENT_LANGFUSE_NPX_PATH ?? "";
47
49
  let batchSize = 10;
48
50
  let pollIntervalMs = 5_000;
49
51
  let postDelayMs = 0;
@@ -81,6 +83,9 @@ function parseServiceArgs(argv) {
81
83
  else if (arg === "--package-spec") {
82
84
  packageSpec = next();
83
85
  }
86
+ else if (arg === "--npx-path") {
87
+ npxPath = next();
88
+ }
84
89
  else if (arg === "--batch-size") {
85
90
  batchSize = parsePositiveInt(arg, next());
86
91
  }
@@ -114,6 +119,7 @@ function parseServiceArgs(argv) {
114
119
  name ||= defaultServiceName(agents, platform);
115
120
  workingDirectory ||= homeDir;
116
121
  pathEnv ||= defaultPathEnv(homeDir, platform);
122
+ npxPath ||= defaultNpxPath(platform);
117
123
  statePath ||= join(homeDir, ".local/state/coding-agent-langfuse", `${name}.json`);
118
124
  return {
119
125
  action,
@@ -124,6 +130,7 @@ function parseServiceArgs(argv) {
124
130
  homeDir,
125
131
  name,
126
132
  packageSpec,
133
+ npxPath,
127
134
  batchSize,
128
135
  pollIntervalMs,
129
136
  postDelayMs,
@@ -254,7 +261,7 @@ async function serviceMain(argv = process.argv.slice(2)) {
254
261
  }
255
262
  function buildFollowCommand(options) {
256
263
  const command = [
257
- options.platform === "win32" ? "npx.cmd" : "npx",
264
+ options.npxPath,
258
265
  "--yes",
259
266
  options.packageSpec,
260
267
  "--agents",
@@ -299,6 +306,7 @@ WantedBy=default.target
299
306
  `;
300
307
  }
301
308
  function renderLaunchdPlist(options, command) {
309
+ const programArguments = launchdCommand(command);
302
310
  return `<?xml version="1.0" encoding="UTF-8"?>
303
311
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
304
312
  <plist version="1.0">
@@ -307,7 +315,7 @@ function renderLaunchdPlist(options, command) {
307
315
  <string>${escapeXml(options.name)}</string>
308
316
  <key>ProgramArguments</key>
309
317
  <array>
310
- ${command.map((part) => ` <string>${escapeXml(part)}</string>`).join("\n")}
318
+ ${programArguments.map((part) => ` <string>${escapeXml(part)}</string>`).join("\n")}
311
319
  </array>
312
320
  <key>EnvironmentVariables</key>
313
321
  <dict>
@@ -376,6 +384,8 @@ function defaultServiceName(agents, platform) {
376
384
  : `coding-agent-langfuse-${suffix}`;
377
385
  }
378
386
  function defaultPathEnv(homeDir, platform) {
387
+ if (process.env.PATH)
388
+ return process.env.PATH;
379
389
  if (platform === "win32") {
380
390
  return [
381
391
  "%APPDATA%\\npm",
@@ -385,7 +395,6 @@ function defaultPathEnv(homeDir, platform) {
385
395
  ].join(";");
386
396
  }
387
397
  return [
388
- join(homeDir, ".local/share/mise/shims"),
389
398
  join(homeDir, ".local/bin"),
390
399
  "/opt/homebrew/bin",
391
400
  "/usr/local/bin",
@@ -395,6 +404,30 @@ function defaultPathEnv(homeDir, platform) {
395
404
  "/sbin",
396
405
  ].join(":");
397
406
  }
407
+ function defaultNpxPath(platform) {
408
+ if (platform === "win32") {
409
+ return findExecutable("npx.cmd", "where") ?? "npx.cmd";
410
+ }
411
+ return "npx";
412
+ }
413
+ function launchdCommand(command) {
414
+ const [program, ...args] = command;
415
+ if (!program)
416
+ return command;
417
+ return program.includes("/") ? command : ["/usr/bin/env", program, ...args];
418
+ }
419
+ function findExecutable(name, finder) {
420
+ try {
421
+ const output = execFileSync(finder, [name], {
422
+ encoding: "utf8",
423
+ stdio: ["ignore", "pipe", "ignore"],
424
+ });
425
+ return output.split(/\r?\n/).find((line) => line.trim().length > 0)?.trim();
426
+ }
427
+ catch {
428
+ return undefined;
429
+ }
430
+ }
398
431
  function parsePositiveInt(flag, value) {
399
432
  const parsed = Number.parseInt(value, 10);
400
433
  if (!Number.isFinite(parsed) || parsed < 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramarivera/coding-agent-langfuse",
3
- "version": "0.1.33",
3
+ "version": "0.1.35",
4
4
  "description": "Universal coding-agent Langfuse backfiller and live OTLP helpers",
5
5
  "type": "module",
6
6
  "license": "MIT",