Files
my-pi/pi-permission-system/src/session-logger.ts
T

92 lines
3.1 KiB
TypeScript

import { join } from "node:path";
import { DEBUG_LOG_FILENAME, REVIEW_LOG_FILENAME } from "./config-paths";
import {
ensurePermissionSystemLogsDirectory,
type PermissionSystemExtensionConfig,
} from "./extension-config";
import {
createPermissionSystemLogger,
type PermissionSystemLogger,
} from "./logging";
/**
* Narrowest logging seam — consumers that only write review-log entries.
* Injected into `PermissionPrompter` and the RPC handlers.
*/
export interface ReviewLogger {
review(event: string, details?: Record<string, unknown>): void;
}
/**
* Logging seam for consumers that write both debug and review entries.
* Injected into `ConfigStore`, `ParentAuthorizer`, and `ForwardedRequestServer`.
*/
export interface DebugReviewLogger extends ReviewLogger {
debug(event: string, details?: Record<string, unknown>): void;
}
/**
* Unified logging + notification surface for handler deps.
*
* Replaces three separate logging fields (`writeDebugLog`,
* `writeReviewLog`, `notifyWarning`) with a single typed collaborator.
* This is an intermediate abstraction on the path to PermissionSession (#129).
*/
export interface SessionLogger extends DebugReviewLogger {
warn(message: string): void;
}
/** Narrow dependencies for constructing a {@link SessionLogger}. */
export interface SessionLoggerDeps {
/** Root logs directory; the debug + review log file paths derive from it. */
globalLogsDir: string;
/** Reads current config for the debug/review write toggles (call-time). */
getConfig: () => PermissionSystemExtensionConfig;
/** Surfaces a warning message to the user; called at warn/IO-failure time. */
notify: (message: string) => void;
}
/**
* Concrete `SessionLogger` implementation.
*
* Composes the JSONL log writer, privately owns the IO-failure warning
* dedup Set, and routes both IO-failure warnings and explicit warn() calls
* through the injected notify sink. No ExtensionRuntime reference required.
*/
export class PermissionSessionLogger implements SessionLogger {
private readonly writer: PermissionSystemLogger;
private readonly reported = new Set<string>();
private readonly notify: (message: string) => void;
constructor(deps: SessionLoggerDeps) {
this.writer = createPermissionSystemLogger({
getConfig: deps.getConfig,
debugLogPath: join(deps.globalLogsDir, DEBUG_LOG_FILENAME),
reviewLogPath: join(deps.globalLogsDir, REVIEW_LOG_FILENAME),
ensureLogsDirectory: () =>
ensurePermissionSystemLogsDirectory(deps.globalLogsDir),
});
this.notify = deps.notify;
}
debug(event: string, details?: Record<string, unknown>): void {
const warning = this.writer.debug(event, details);
if (warning) this.reportOnce(warning);
}
review(event: string, details?: Record<string, unknown>): void {
const warning = this.writer.review(event, details);
if (warning) this.reportOnce(warning);
}
warn(message: string): void {
this.notify(message);
}
private reportOnce(warning: string): void {
if (this.reported.has(warning)) return;
this.reported.add(warning);
this.notify(warning);
}
}