feat: Pi Text-Agent — initialer Commit (sauberes Repo)
Vollständiges Multi-Agenten-System für Fact-Checking, Artikelschreiben und Argumentationsanalyse. Zwei Backends: llama.cpp (★ bevorzugt) und Ollama. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
5146b7fa30
62 changed files with 11279 additions and 0 deletions
107
lib/logger.ts
Normal file
107
lib/logger.ts
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* lib/logger.ts
|
||||
* Einfacher File-Logger für alle Agenten.
|
||||
*
|
||||
* Schreibt strukturierte Log-Einträge nach ~/.pi/agent/logs/<timestamp>[_<jobId>].log
|
||||
* Im verbose-Modus werden alle Einträge zusätzlich auf stderr ausgegeben.
|
||||
* Warnung/Fehler gehen immer auf stderr (unabhängig von verbose).
|
||||
*
|
||||
* Verwendung:
|
||||
* import { createLogger } from "../lib/logger.js";
|
||||
* const log = createLogger({ verbose: cliFlags.verbose });
|
||||
* log.info("Claims extrahieren...", { model, numChunks: 3 });
|
||||
* log.warn("0 Claims in Chunk", { chunk: 2 });
|
||||
* log.error("Ollama nicht erreichbar", { url: OLLAMA_HOST });
|
||||
*/
|
||||
|
||||
import { appendFileSync, mkdirSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Konstanten
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const LOG_DIR = join(homedir(), ".pi", "agent", "logs");
|
||||
|
||||
export type LogLevel = "info" | "warn" | "error" | "debug";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Logger-Klasse
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export class Logger {
|
||||
private logFile: string | null;
|
||||
private verbose: boolean;
|
||||
|
||||
constructor(opts?: { logFile?: string; verbose?: boolean }) {
|
||||
this.logFile = opts?.logFile ?? null;
|
||||
this.verbose = opts?.verbose ?? false;
|
||||
}
|
||||
|
||||
log(level: LogLevel, message: string, data?: Record<string, unknown>): void {
|
||||
const ts = new Date().toISOString();
|
||||
const dataStr = data ? " " + JSON.stringify(data) : "";
|
||||
const line = `[${ts}] [${level.toUpperCase().padEnd(5)}] ${message}${dataStr}\n`;
|
||||
|
||||
// In Datei schreiben (append, non-blocking, Fehler ignorieren)
|
||||
if (this.logFile) {
|
||||
try {
|
||||
appendFileSync(this.logFile, line);
|
||||
} catch {
|
||||
// Log-Fehler dürfen den Programmablauf nicht stören
|
||||
}
|
||||
}
|
||||
|
||||
// Auf stderr ausgeben wenn verbose ODER level >= warn
|
||||
if (this.verbose || level === "error" || level === "warn") {
|
||||
process.stderr.write(line);
|
||||
}
|
||||
}
|
||||
|
||||
info(message: string, data?: Record<string, unknown>): void {
|
||||
this.log("info", message, data);
|
||||
}
|
||||
|
||||
warn(message: string, data?: Record<string, unknown>): void {
|
||||
this.log("warn", message, data);
|
||||
}
|
||||
|
||||
error(message: string, data?: Record<string, unknown>): void {
|
||||
this.log("error", message, data);
|
||||
}
|
||||
|
||||
debug(message: string, data?: Record<string, unknown>): void {
|
||||
this.log("debug", message, data);
|
||||
}
|
||||
}
|
||||
|
||||
// Null-Logger für Kontexte wo kein Logging gewünscht ist
|
||||
export const nullLogger = new Logger();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Factory
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Erstellt einen Logger der in eine neue Log-Datei schreibt.
|
||||
* @param opts.jobId Optionaler Suffix für den Dateinamen (z.B. "umerziehung")
|
||||
* @param opts.verbose Wenn true: alle Log-Einträge auf stderr
|
||||
*/
|
||||
export function createLogger(opts?: { jobId?: string; verbose?: boolean }): Logger {
|
||||
try {
|
||||
mkdirSync(LOG_DIR, { recursive: true });
|
||||
} catch {
|
||||
// Verzeichnis existiert bereits oder kein Schreibzugriff
|
||||
}
|
||||
|
||||
const ts = new Date()
|
||||
.toISOString()
|
||||
.replace(/T/, "_")
|
||||
.replace(/:/g, "-")
|
||||
.slice(0, 19); // "2026-04-16_14-30-00"
|
||||
const suffix = opts?.jobId ? `_${opts.jobId}` : "";
|
||||
const logFile = join(LOG_DIR, `${ts}${suffix}.log`);
|
||||
|
||||
return new Logger({ logFile, verbose: opts?.verbose ?? false });
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue