/** A workflow (prompt-template) command: built-in PROMPT_COMMANDS or a custom * `.gg/commands/*.md` entry. `prompt` is the full template body the command * expands to when run. */ export interface WorkflowCommandSpec { name: string; aliases?: readonly string[]; prompt: string; } /** The exact separator AgentSession.prompt() inserts between a command's * template and the user's extra args (see agent-session.ts prompt expansion). * Must stay byte-identical or expanded-command detection silently breaks. */ export declare const USER_INSTRUCTIONS_HEADER = "\n\n## User Instructions\n\n"; /** * True when `text` invokes a known workflow command (first token, name or * alias, case-insensitive). Registry/UI commands and unknown `/foo` return * false — those add no assistant work and are caught by the * `no-assistant-output` gate instead. */ export declare function isWorkflowCommandText(text: string, commands: readonly WorkflowCommandSpec[]): boolean; /** * Match a transcript user-message body back to the workflow command it was * expanded from. AgentSession stores the EXPANDED template as a plain user * message, so without this Ken's digest renders 400-line templates as * `**User:** …` and treats them as user-authored asks. * * Returns the matched command plus any trailing user args, or null. */ export declare function matchExpandedCommand(text: string, commands: readonly WorkflowCommandSpec[]): { command: WorkflowCommandSpec; args: string | null; } | null; /** Count assistant messages — the "did this run produce reviewable work" * signal. Compared before/after a run by the sidecar. */ export declare function countAssistantMessages(messages: ReadonlyArray<{ role: string; }>): number; /** Extract every tool call made by assistant messages from `startIndex` * onward — i.e. the tool calls added during one turn, given the message * array length captured before that turn ran. Used to feed * isMechanicalOnlyTurn without the gate module depending on gg-ai's full * Message type (kept structurally typed so it's easy to unit test). */ export declare function extractTurnToolCalls(messages: ReadonlyArray<{ role: string; content: string | ReadonlyArray<{ type: string; name?: string; args?: Record; }>; }>, startIndex: number): TurnToolCall[]; export type AutopilotSkipReason = "disabled" | "cancelled" | "plan-mode" | "workflow-command" | "mechanical-only" | "no-assistant-output"; export interface AutopilotGateInput { /** The window's autopilot toggle. */ enabled: boolean; /** True when /cancel fired during the turn. */ cancelled: boolean; /** True when the session ended the turn in plan mode (plan modal pending). */ planMode: boolean; /** True when the turn SUBMITTED a plan (exit_plan fired — the sidecar's * pendingPlanPath is set). Ken reviews the plan itself instead of the * work. Optional so existing callers/tests default to false. */ planPending?: boolean; /** True when the turn was a workflow slash command (see isWorkflowCommandText). */ workflowCommand: boolean; /** Assistant messages ADDED by this turn (after minus before). */ assistantMessagesAdded: number; /** True when every tool call this turn was mechanical bash usage (see * isMechanicalOnlyTurn) — nothing for Ken to review. Optional so existing * callers/tests that don't set it default to false (reviewable). */ mechanicalOnly?: boolean; } export type AutopilotGateDecision = { start: true; kind: "work" | "plan"; } | { start: false; reason: AutopilotSkipReason; }; /** * Decide whether the autopilot cycle may start for a just-finished turn. * Checks are ordered cheapest/most-fundamental first; the reason is logged by * the sidecar so skips are debuggable from gg-app-sidecar.log. * * `planPending` beats the workflow/mechanical/no-output checks: a plan * submission via exit_plan flips plan mode OFF and often has only mechanical * tool calls, but it IS reviewable work — Ken reviews the plan itself * (kind: "plan") instead of skipping. `planMode` still wins over it: a turn * that ended INSIDE plan mode (enter without exit) has no submitted plan and * Ken must never prompt into a read-only session. */ export declare function shouldStartAutopilotCycle(input: AutopilotGateInput): AutopilotGateDecision; /** A tool call made during a turn, as recorded on an assistant message's * content parts. Mirrors gg-ai's `ToolCall` shape minus the fields the gate * doesn't need (id). */ export interface TurnToolCall { name: string; args?: Record; } /** * True when the turn has nothing for Ken to review: either it made NO tool * calls at all (a plain-text answer — "a plain question that got answered * with no code touched" is IGNORE per the autopilot contract), or EVERY tool * call was mechanical (a dedicated read-only tool, or bash usage that starts * a background process / is read-only / is a plain git commit-push chain). * ANY non-mechanical call (edit, write, subagent, generate_image, or bash * outside these safe shapes) makes the whole turn reviewable — conservative * default: keep reviewing whenever it's unclear. */ export declare function isMechanicalOnlyTurn(toolCalls: readonly TurnToolCall[]): boolean; //# sourceMappingURL=autopilot-gate.d.ts.map