import type Database from 'better-sqlite3'; /** Hard caps. Goals are user-typed prose; tight limits keep prompt * injection from blowing the context window on a single thread. */ export declare const MAX_TITLE_CHARS = 200; export declare const MAX_BODY_CHARS = 4000; export declare const MAX_PROGRESS_NOTE_CHARS = 500; export declare const MAX_PROGRESS_NOTES_INJECTED = 5; /** Goal lifecycle states. * - active: counted as the thread's current goal; injected into prompts * - paused: kept around but NOT injected (operator wants a break) * - completed / cancelled: historical only */ export type GoalStatus = 'active' | 'paused' | 'completed' | 'cancelled'; export interface ProgressNote { ts: string; by: string; text: string; } export interface GoalRow { id: number; /** Monotonic logical revision used by agent-side compare-and-set. */ version: number; /** Increments after every successful mutating tool operation. */ mutationEpoch: number; evidenceRequired: boolean; /** Opaque hash of the agent cwd/workspace this goal observes. Empty * means unknown → mutations bump epochs conservatively. */ workspaceScope: string; platform: string; channelId: string; threadId: string; userId: string; title: string; body: string; status: GoalStatus; /** Newest-last array (push on progress; render reversed for "most recent first"). */ progressLog: ProgressNote[]; createdAt: string; updatedAt: string; /** ISO timestamp of completion / cancellation, when applicable. */ closedAt: string | null; } /** Internal authority shared with goal-evidence.ts so completion CAS and * evidence validation use the same SQLite connection/transaction. */ export declare function getGoalsDatabaseForLedger(): Database.Database | null; /** * Set (or replace) the ACTIVE goal for a thread. Idempotent semantics: * if there's already an active goal, it's auto-paused first (kept in * the table) and a fresh row replaces it. This avoids accidental * silent drops of partially-tracked work — the operator can /goal * list to find paused predecessors and /goal resume if they * changed their mind. */ export declare function setActiveGoal(input: { platform: string; channelId: string; threadId: string; userId: string; title: string; body?: string; /** Agent RPC sets false unless force:true; user slash commands keep the * historical replace behavior by omitting it. */ replaceActive?: boolean; evidenceRequired?: boolean; /** Opaque cwd/workspace hash for scoped mutation epochs. */ workspaceScope?: string; }): GoalRow | null; /** Append a progress note to a goal. Caller picks `by` (typically * 'user' for /goal progress, 'agent' for future MCP tool call, * 'system' for status transitions). */ export declare function appendProgress(goalId: number, by: ProgressNote['by'], text: string): boolean; export declare function updateStatus(goalId: number, status: GoalStatus): boolean; /** Resume a paused goal — also auto-pauses any currently-active goal * in the same thread so there's never more than one active. */ export declare function resumeGoal(goalId: number): boolean; export declare function getGoalById(id: number): GoalRow | null; export declare function getGoalByIdState(id: number): { available: boolean; goal: GoalRow | null; }; /** The single active goal for a thread (or null if none). */ export declare function getActiveGoal(platform: string, channelId: string, threadId: string): GoalRow | null; export declare function getActiveGoalState(platform: string, channelId: string, threadId: string): { available: boolean; goal: GoalRow | null; }; /** Cheap boolean form of getActiveGoal — same query but returns only a * flag. Used by the wall-timeout extension path (v1.2.86) where the * caller just needs to know "should we be generous about timeouts on * this thread". Safe to call from hot paths; same fail-soft semantics * as getActiveGoal (db unavailable → false). */ export declare function hasActiveGoal(platform: string, channelId: string, threadId: string): boolean; /** v1.2.86 — when an active goal exists on the addressed thread, the * caller may legitimately need much longer to finish (research/coding * marathons). Multiply the base timeout by AGIM_GOAL_ACTIVE_TIMEOUT_MULTIPLIER * (default 3×). Returns `base` unchanged when no thread context, no * active goal, or db unavailable. * * Hard cap: 6 h. Even with goals, a runaway loop should not pin a * worker indefinitely. */ export declare function applyGoalTimeoutBoost(base: number, ctx?: { platform?: string; channelId?: string; threadId?: string; }): number; /** All goals (any status) for a thread, newest first. Used by /goal list. */ export declare function listGoalsForThread(platform: string, channelId: string, threadId: string, limit?: number): GoalRow[]; /** Admin / debug — every active goal across the install. */ export declare function listAllActiveGoals(): GoalRow[]; /** * Build the per-turn prompt-prefix snippet for the active goal. Bounded * to ~MAX_PROGRESS_NOTES_INJECTED recent notes + truncated body so a * verbose goal doesn't dominate the prompt budget. Empty string when no * active goal — router treats falsy snippets as "skip this block". * * The snippet is OVER THE WIRE only — it's prepended to the prompt the * agent sees but NOT stored in session history, so it doesn't bloat the * persisted conversation. */ export declare function buildGoalSnippet(platform: string, channelId: string, threadId: string): string; /** For /goal show — render an operator-facing summary including ALL * retained progress notes (capped at MAX_PROGRESS_NOTES_LISTED so the * IM bubble doesn't explode). */ export declare function formatGoalShow(goal: GoalRow): string; /** Test-only. Drops everything; safe to call repeatedly in beforeEach. */ export declare function _truncateForTests(): void; export declare function closeGoalsDbForTesting(): void; //# sourceMappingURL=goals.d.ts.map