/** * Agent Behavior Log — write/read service. * * Translates strongly-typed `BehaviorLogEvent` values into rows of the * `agent_behavior_log` table and reads them back as typed records. * * Design choices: * - One service instance owns one DB handle; tests pass `:memory:`. * - All writes are append-only inserts; no updates, no deletes. * - Best-effort logging — `record()` swallows DB errors after logging * them, so observability never takes the request path down. * - Read APIs are minimal: this PR ships the schema + write surface. * Digest/aggregation queries land in a follow-up. * * Wiring of producers (Slack-failure listener, prompt-size sampler, * orchestrator action logger) is intentionally out of scope for this * PR — see P0-5 / prompt-generator follow-ups. * * @module services/observability/agent-behavior-log.service */ import { type ObservabilityDatabase, type OpenObservabilityDatabaseOptions } from './observability-db.js'; import { type BehaviorLogEvent, type BehaviorLogEventType } from './agent-behavior-log.types.js'; import { type ComponentLogger } from '../core/logger.service.js'; /** * Decoded behavior log row — `details_json` is parsed back into an * object, and `event_type` is narrowed to the discriminator union. */ export interface BehaviorLogRecord { id: number; ts: number; eventType: BehaviorLogEventType; agent: string; subject: string; taskId: string; reason: string; amount: number; details: Record; } /** * Options for constructing an `AgentBehaviorLogService`. Either pass an * existing DB handle (preferred for tests) or a set of opener options * the service should use to open its own handle. */ export interface AgentBehaviorLogServiceOptions { /** Pre-opened database handle. Service does NOT take ownership. */ db?: ObservabilityDatabase; /** Opener options used when `db` is not supplied. */ openOptions?: OpenObservabilityDatabaseOptions; /** Optional time source — defaults to `Date.now`. Used in tests. */ now?: () => number; /** Optional logger override. */ logger?: ComponentLogger; } /** * Append-only writer + minimal reader for the `agent_behavior_log` * table. * * @example * ```ts * const svc = new AgentBehaviorLogService(); * svc.record({ * type: 'agent.action', * agent: 'crewly-orc', * actionType: 'delegate', * taskId: 'req-123', * details: { recipient: 'sam' }, * }); * ``` */ export declare class AgentBehaviorLogService { private readonly db; private readonly ownsDb; private readonly now; private readonly logger; private insertStmt; constructor(options?: AgentBehaviorLogServiceOptions); /** * Lazily prepare and cache the insert statement. Avoids paying the * prepare cost for callers that only ever read. */ private getInsertStmt; /** * Record one behavior event. * * Translates the discriminated `BehaviorLogEvent` into a * `BehaviorLogRow`-compatible parameter object and inserts. Errors * are caught and logged — observability writes must NEVER throw into * the calling code path. * * @param event - The strongly-typed event to record * @returns The newly inserted row id, or `null` if the write failed */ record(event: BehaviorLogEvent): number | null; /** * Translate a `BehaviorLogEvent` into the parameter object expected * by the prepared insert statement. * * The discriminator branch is exhaustive — adding a new event type * forces a TypeScript error here until the new branch is added. */ private toRowParams; /** Build params for an `agent.action` event. */ private buildAgentActionParams; /** Build params for an `agent.escalation` event. */ private buildEscalationParams; /** Build params for a `slack.delivery.failed` event. */ private buildSlackFailureParams; /** Build params for a `prompt.size.bytes` event. */ private buildPromptSizeParams; /** * Return the most recent N rows, newest first. Optionally filter by * event type. Intended for diagnostics and tests; production digest * code should use a dedicated aggregation query. * * @param limit - Max rows to return (capped at 1000) * @param eventType - Optional event-type filter */ listRecent(limit?: number, eventType?: BehaviorLogEventType): BehaviorLogRecord[]; /** * Count rows by event type since a given timestamp. Useful for the * weekly digest's per-event totals. * * @param sinceTs - Inclusive ms-since-epoch lower bound (default 0 = all time) */ countByEvent(sinceTs?: number): Record; /** * Close the underlying DB handle if this service opened it. Safe to * call multiple times. */ close(): void; } //# sourceMappingURL=agent-behavior-log.service.d.ts.map