UNPKG

agentcrumbs

Version:
116 lines 3.75 kB
import fs from "node:fs"; import { formatCrumbPretty, formatCrumbJson } from "../format.js"; import { getFlag, hasFlag } from "../args.js"; import { parseAppFlags, getStoreFilePath } from "../app-store.js"; export async function tail(args) { const ns = getFlag(args, "--ns"); const tag = getFlag(args, "--tag"); const match = getFlag(args, "--match"); const session = getFlag(args, "--session"); const json = hasFlag(args, "--json"); const appCtx = parseAppFlags(args); const showApp = appCtx.allApps; const filePath = getStoreFilePath(appCtx); const dir = filePath.replace(/\/[^/]+$/, ""); if (!fs.existsSync(filePath)) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(filePath, ""); process.stderr.write("Waiting for crumbs... (start the collector: agentcrumbs collect)\n"); } // Print existing lines from the end (last 50) const existing = readLastLines(filePath, 50); for (const crumb of existing) { if (matchesCrumb(crumb, { ns, tag, match, session })) { printCrumb(crumb, json, showApp); } } // Watch for new lines let fileSize = fs.statSync(filePath).size; const watcher = fs.watch(filePath, () => { try { const newSize = fs.statSync(filePath).size; if (newSize <= fileSize) { fileSize = newSize; return; } const buffer = Buffer.alloc(newSize - fileSize); const fd = fs.openSync(filePath, "r"); fs.readSync(fd, buffer, 0, buffer.length, fileSize); fs.closeSync(fd); fileSize = newSize; const lines = buffer.toString("utf-8").split("\n").filter(Boolean); for (const line of lines) { try { const crumb = JSON.parse(line); if (matchesCrumb(crumb, { ns, tag, match, session })) { printCrumb(crumb, json, showApp); } } catch { // skip invalid lines } } } catch { // ignore read errors } }); const shutdown = () => { watcher.close(); process.exit(0); }; process.on("SIGINT", shutdown); process.on("SIGTERM", shutdown); } function matchesCrumb(crumb, filters) { if (filters.ns) { const pattern = filters.ns.replace(/\*/g, ".*"); if (!new RegExp(`^${pattern}$`).test(crumb.ns)) return false; } if (filters.tag) { if (!crumb.tags?.includes(filters.tag)) return false; } if (filters.session) { if (crumb.sid !== filters.session) return false; } if (filters.match) { const str = JSON.stringify(crumb); if (!str.includes(filters.match)) return false; } return true; } function printCrumb(crumb, json, showApp) { if (json) { process.stdout.write(formatCrumbJson(crumb) + "\n"); } else { process.stdout.write(formatCrumbPretty(crumb, { showApp }) + "\n"); } } function readLastLines(filePath, count) { try { const content = fs.readFileSync(filePath, "utf-8"); const lines = content.split("\n").filter(Boolean); const lastLines = lines.slice(-count); return lastLines .map((line) => { try { return JSON.parse(line); } catch { return null; } }) .filter((c) => c !== null); } catch { return []; } } //# sourceMappingURL=tail.js.map