Files
OmniRoute/bin/cli/commands/logs.mjs
oyi77 2d601ea459 feat: CLI Integration Suite for issue #2016
- Add tool-detector.ts (6 CLI tools: claude, codex, opencode, cline, kilocode, continue)
- Add config-generator/ factory + 6 generators (JSON + YAML)
- Add doctor/checks.ts for CLI tool health checks
- Add log-streamer.ts for usage log streaming
- Add @omniroute/opencode-provider npm package
- Add 5 CLI commands: config, status, logs, update, provider
- Add 3 API routes: config, detect, apply
- Update bin/omniroute.mjs, bin/cli/index.mjs, package.json
- Update docs: SETUP_GUIDE.md, CLI-TOOLS.md
- All tests pass (4302/4326, 24 pre-existing failures unchanged)
2026-05-14 17:26:30 +07:00

84 lines
2.5 KiB
JavaScript

import { parseArgs, getStringFlag, hasFlag } from "../args.mjs";
import { printHeading, printInfo, printError } from "../io.mjs";
function printLogsHelp() {
console.log(`
Usage:
omniroute logs [options]
Options:
--follow Stream logs in real-time
--filter <level> Filter by level (error, warn, info) — comma-separated
--lines <n> Number of lines to fetch (default: 100)
--timeout <ms> Connection timeout in ms (default: 30000)
--base-url <url> OmniRoute API base URL (default: http://localhost:20128)
--json Output as JSON
--help Show this help
`);
}
export async function runLogsCommand(argv) {
const { flags } = parseArgs(argv);
if (hasFlag(flags, "help") || hasFlag(flags, "h")) {
printLogsHelp();
return 0;
}
const baseUrl = getStringFlag(flags, "base-url") || "http://localhost:20128";
const follow = hasFlag(flags, "follow");
const filter = getStringFlag(flags, "filter");
const lines = getStringFlag(flags, "lines") || "100";
const timeout = parseInt(getStringFlag(flags, "timeout") || "30000", 10);
const filters = filter ? filter.split(",").map((f) => f.trim()) : [];
const { createLogStream } = await import("../../../src/lib/cli-helper/log-streamer.js");
const { stream, stop } = createLogStream({ baseUrl, filters, follow, timeout });
const reader = stream.getReader();
const decoder = new TextDecoder();
let buffer = "";
const processLine = (line) => {
if (!line.trim()) return;
if (hasFlag(flags, "json")) {
console.log(line);
return;
}
try {
const parsed = JSON.parse(line);
const level = parsed.level || "info";
const ts = parsed.timestamp || new Date().toISOString();
const msg = parsed.message || JSON.stringify(parsed);
const prefix =
{ error: "\x1b[31m[ERR]", warn: "\x1b[33m[WRN]", info: "\x1b[36m[INF]" }[level] || "[INF]";
console.log(`${prefix}\x1b[0m ${ts} ${msg}`);
} catch {
console.log(line);
}
};
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) processLine(line);
}
if (buffer) processLine(buffer);
} catch (err) {
if (err.name === "AbortError") {
printInfo("Log stream stopped.");
} else {
printError(`Log stream error: ${err.message}`);
}
} finally {
stop();
}
return 0;
}