agent-tail-core 0.3.0 → 0.3.1

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
@@ -2,10 +2,12 @@
2
2
 
3
3
  CLI and shared core for [agent-tail](https://agent-tail.vercel.app/) — pipes server output and browser console logs to log files your AI coding agents can read and `grep`.
4
4
 
5
+ > **Tip:** Install the umbrella [`agent-tail`](https://www.npmjs.com/package/agent-tail) package to get the CLI, Vite plugin, and Next.js plugin in one install: `npm install -D agent-tail`
6
+
5
7
  ## Quick start
6
8
 
7
9
  ```bash
8
- npx agent-tail-core run 'fe: npm run dev' 'api: uvicorn main:app'
10
+ npx agent-tail run 'fe: npm run dev' 'api: uvicorn main:app'
9
11
  ```
10
12
 
11
13
  Each service gets its own log file (`fe.log`, `api.log`) plus a `combined.log` with all output interleaved. A `latest` symlink always points to the current session:
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as cmd_run, r as cmd_wrap, t as cmd_init } from "./commands-CzU-rrPM.mjs";
2
+ import { n as cmd_run, r as cmd_wrap, t as cmd_init } from "./commands-LpvDep8T.mjs";
3
3
  import { parseArgs } from "node:util";
4
4
 
5
5
  //#region src/cli.ts
@@ -49,7 +49,11 @@ var LogManager = class {
49
49
  fs.unlinkSync(latest_link);
50
50
  } catch {}
51
51
  const relative_target = path.relative(log_dir, session_dir);
52
- fs.symlinkSync(relative_target, latest_link);
52
+ try {
53
+ fs.symlinkSync(relative_target, latest_link);
54
+ } catch {
55
+ fs.writeFileSync(latest_link, session_dir);
56
+ }
53
57
  }
54
58
  prune_sessions(log_dir) {
55
59
  try {
@@ -73,8 +77,12 @@ var LogManager = class {
73
77
  const log_dir = path.resolve(project_root, this.options.logDir);
74
78
  const latest_link = path.join(log_dir, "latest");
75
79
  try {
76
- const real = fs.realpathSync(latest_link);
77
- if (fs.statSync(real).isDirectory()) return real;
80
+ const stat = fs.lstatSync(latest_link);
81
+ let target;
82
+ if (stat.isSymbolicLink()) target = fs.realpathSync(latest_link);
83
+ else if (stat.isFile()) target = fs.readFileSync(latest_link, "utf-8").trim();
84
+ else throw new Error("unexpected latest type");
85
+ if (fs.existsSync(target) && fs.statSync(target).isDirectory()) return target;
78
86
  } catch {}
79
87
  const log_path = this.initialize(project_root);
80
88
  return path.dirname(log_path);
@@ -82,8 +90,8 @@ var LogManager = class {
82
90
  check_gitignore(project_root) {
83
91
  const gitignore_path = path.join(project_root, ".gitignore");
84
92
  try {
85
- const lines = fs.readFileSync(gitignore_path, "utf-8").split("\n").map((l) => l.trim());
86
- const log_dir = this.options.logDir;
93
+ const lines = fs.readFileSync(gitignore_path, "utf-8").split(/\r?\n/).map((l) => l.trim());
94
+ const log_dir = this.options.logDir.replace(/\\/g, "/");
87
95
  const parts = log_dir.split("/");
88
96
  let covered = false;
89
97
  for (let i = 1; i <= parts.length; i++) {
@@ -171,7 +179,7 @@ function parse_service_configs(args) {
171
179
  * Write data to a log stream and optionally to combined.log with a prefix.
172
180
  */
173
181
  function write_to_logs(chunk, name, log_stream, combined_stream, excludes = []) {
174
- const lines = chunk.toString().split("\n");
182
+ const lines = chunk.toString().split(/\r?\n/);
175
183
  for (let i = 0; i < lines.length; i++) if (lines[i].length > 0) {
176
184
  if (excludes.length && should_exclude(lines[i], excludes)) continue;
177
185
  log_stream.write(lines[i] + "\n");
@@ -197,13 +205,14 @@ function cmd_wrap(project_root, name, command, options = DEFAULT_CLI_OPTIONS) {
197
205
  combined_stream = fs.createWriteStream(combined_file, { flags: "a" });
198
206
  }
199
207
  console.log(`${PREFIX} ${name} → ${log_file}`);
200
- const child = spawn("sh", ["-c", command.join(" ")], {
208
+ const child = spawn(command.join(" "), {
201
209
  stdio: [
202
210
  "inherit",
203
211
  "pipe",
204
212
  "pipe"
205
213
  ],
206
- env: { ...process.env }
214
+ env: { ...process.env },
215
+ shell: true
207
216
  });
208
217
  child.stdout?.on("data", (chunk) => {
209
218
  process.stdout.write(chunk);
@@ -261,16 +270,17 @@ function cmd_run(project_root, service_args, options = DEFAULT_CLI_OPTIONS) {
261
270
  const tag = `${COLORS[i % COLORS.length]}[${svc.name}]${RESET}`;
262
271
  const log_file = path.join(session_dir, `${svc.name}.log`);
263
272
  const log_stream = fs.createWriteStream(log_file, { flags: "a" });
264
- const child = spawn("sh", ["-c", svc.command], {
273
+ const child = spawn(svc.command, {
265
274
  stdio: [
266
275
  "inherit",
267
276
  "pipe",
268
277
  "pipe"
269
278
  ],
270
- env: { ...process.env }
279
+ env: { ...process.env },
280
+ shell: true
271
281
  });
272
282
  function handle(target, chunk) {
273
- const lines = chunk.toString().split("\n");
283
+ const lines = chunk.toString().split(/\r?\n/);
274
284
  for (let j = 0; j < lines.length; j++) if (lines[j].length > 0) {
275
285
  if (options.excludes.length && should_exclude(lines[j], options.excludes)) continue;
276
286
  log_stream.write(lines[j] + "\n");
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { a as resolve_session_dir, c as LogManager, i as parse_service_configs, l as should_exclude, n as cmd_run, o as DEFAULT_OPTIONS, r as cmd_wrap, s as resolve_options, t as cmd_init } from "./commands-CzU-rrPM.mjs";
1
+ import { a as resolve_session_dir, c as LogManager, i as parse_service_configs, l as should_exclude, n as cmd_run, o as DEFAULT_OPTIONS, r as cmd_wrap, s as resolve_options, t as cmd_init } from "./commands-LpvDep8T.mjs";
2
2
 
3
3
  //#region src/formatter.ts
4
4
  function format_log_line(entry) {
5
- return `[${entry.timestamp}] [${entry.level.toUpperCase().padEnd(7)}] ${entry.args.join(" ")}${entry.url ? ` (${entry.url})` : ""}${entry.stack ? `\n ${entry.stack.split("\n").join("\n ")}` : ""}\n`;
5
+ return `[${entry.timestamp}] [${entry.level.toUpperCase().padEnd(7)}] ${entry.args.join(" ")}${entry.url ? ` (${entry.url})` : ""}${entry.stack ? `\n ${entry.stack.split(/\r?\n/).join("\n ")}` : ""}\n`;
6
6
  }
7
7
 
8
8
  //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-tail-core",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "description": "Core utilities for agent-tail log capture plugins.",
6
6
  "license": "MIT",
7
7
  "repository": {