/**
 * Session state inference.
 *
 * Turns a chronological slice of normalized `SessionEvent`s (typically the tail
 * of a transcript) plus lightweight context (file mtime, cwd, branch, whether
 * the owning process is alive) into a `SessionState`: is the agent working,
 * waiting on the user, or idle — and did it open a PR, is it in a worktree, is
 * it tied to a tracker ticket. Pure functions, no I/O, so the whole thing is
 * unit-testable and shared by both the live `--active` path and the incremental
 * scanner (which persists the durable signals to the index).
 *
 * Structural signals are preferred over prose heuristics: Claude's
 * `ExitPlanMode` / `AskUserQuestion` tool calls are exact "waiting on you"
 * markers. Codex has no such tools, so it falls back to last-role + question
 * shape + mtime — same function, driven off the normalized events.
 */
import type { SessionAttachment, SessionEvent, TodoItem, TodoProgress } from './types.js';
import { type ProducedArtifact } from './highlights.js';
export type { TodoItem, TodoProgress };
export type SessionActivity = 'working' | 'waiting_input' | 'idle';
export type AwaitingReason = 'question' | 'plan_review' | 'permission';
/** One discrete choice the agent offered the user. */
export interface QuestionOption {
    /** The choice label — also what a free-text reply channel sends back. */
    label: string;
    /** Optional longer description shown under the label. */
    description?: string;
    /**
     * Selection keystroke for an interactive TUI prompt (AskUserQuestion / plan /
     * permission are select-lists, not text inputs): a digit ('1'), or 'esc' to
     * cancel/deny. Absent for a plain prose question, which takes free text.
     */
    key?: string;
}
/**
 * The decision an agent handed back to the user, extracted at the SOURCE so every
 * consumer (Factory panel, teams, cloud) gets the real question + options instead
 * of re-deriving them from a truncated preview line. `reason` mirrors
 * {@link AwaitingReason}; `options` is present when the agent offered discrete choices.
 */
export interface StructuredQuestion {
    text: string;
    reason: AwaitingReason;
    options?: QuestionOption[];
}
export interface DetectedPr {
    url: string;
    number?: number;
}
export interface DetectedWorktree {
    /** Absolute worktree path (the session cwd). */
    path: string;
    /** The `<slug>` under `.agents/worktrees/`. */
    slug: string;
    branch?: string;
}
export interface DetectedTicket {
    /** Tracker key, e.g. `RUSH-1234`. */
    id: string;
    url?: string;
}
/**
 * Detect per-session rate-limit / usage-limit signals in assistant or error
 * text (RUSH-1523). Matches the same shapes the ext's prewarm detectBlockingPrompt
 * uses, plus common Claude/Codex/Gemini limit strings.
 */
export declare function detectRateLimited(text?: string): boolean;
export interface SessionState {
    activity: SessionActivity;
    awaitingReason?: AwaitingReason;
    lastRole?: 'user' | 'assistant';
    lastEventKind?: SessionEvent['type'];
    /** Single-line description of the latest turn (message text or tool action). */
    preview?: string;
    /**
     * True when the transcript shows the session is rate/usage limited (RUSH-1523).
     * Distinct from account-level usageStatus — this is per-session evidence.
     */
    rateLimited?: boolean;
    /**
     * The structured decision the agent is waiting on (question / plan / permission),
     * with its options when it offered any. Set only when activity is waiting_input.
     */
    question?: StructuredQuestion;
    /**
     * The plan markdown from the most recent `ExitPlanMode` tool call, surfaced
     * when `awaitingReason === 'plan_review'`. The state engine detects the
     * handoff off the same tool event; carrying the plan text alongside it lets
     * consumers (the Factory NEEDS-YOU panel, `agents sessions <id> --json`)
     * render the actual plan without re-parsing the transcript.
     */
    plan?: string;
    /**
     * Live plan progress from the most recent `TodoWrite` (RUSH-1380). Present when
     * the session has written a todo list; drives the Fleet N/M pill +
     * checklist, notably for remote/device-dispatched agents with no local stream.
     */
    todos?: TodoProgress;
    /** Durable documents created in the bounded transcript slice. */
    artifacts?: ProducedArtifact[];
    /** First created plan document, for consumers that give plans special treatment. */
    planFile?: string;
    /** Last few assistant turns (most-recent last), one line each — panel context. */
    tail?: string[];
    lastActivityMs?: number;
    pr?: DetectedPr;
    worktree?: DetectedWorktree;
    ticket?: DetectedTicket;
    /** Tracker refs this session CREATED (Linear create_issue / gh issue create). */
    createdTickets?: string[];
    /** Team name this session SPAWNED via `agents teams create/add`. */
    spawnedTeam?: string;
    /** Displayable files/screenshots attached to the session prompt. */
    attachments?: SessionAttachment[];
}
export interface StateContext {
    /** Session file mtime; drives running-vs-stale. */
    mtimeMs?: number;
    cwd?: string;
    gitBranch?: string;
    /** Whether the owning OS process is alive (from the active scanner). */
    pidAlive?: boolean;
    /** Override the running window (defaults to 2 min, matching active.ts). */
    activeWindowMs?: number;
}
/**
 * Derive live plan progress from a checklist tool call's args. Accepts Claude's
 * `TodoWrite` (`todos: [{content,status,activeForm}]`), Kimi's `TodoList`
 * (`todos: [{title,status}]`, where finished is `done` rather than `completed`)
 * and Codex's `update_plan` (`plan: [{step,status}]`) shapes, so the CLI is the
 * single source of checklist state for every agent. Returns undefined when there
 * is no usable list, so a session with no plan carries no `todos` field.
 */
export declare function extractTodoProgress(args?: Record<string, any>): TodoProgress | undefined;
/** Fold snapshot checklist tools and Claude TaskCreate/TaskUpdate event logs. */
export declare function extractTodoProgressFromEvents(events: SessionEvent[]): TodoProgress | undefined;
/** Derive a recency-ordered, de-duplicated list of directories touched by tools. */
export declare function extractRecentDirectoriesTouched(events: SessionEvent[], cwd?: string): string[] | undefined;
export declare const WORKTREE_RE: RegExp;
/** Detect a worktree from the session cwd, per the `.agents/worktrees/<slug>/` convention. */
export declare function detectWorktree(cwd?: string, branch?: string): DetectedWorktree | undefined;
/** Detect a tracker ticket from free text (prompt/topic) then a branch name. */
export declare function detectTicket(text?: string, branch?: string): DetectedTicket | undefined;
/** Pull a PR URL + number out of tool-result output text. */
export declare function extractPrUrl(output?: string): DetectedPr | undefined;
/** True when a Bash/exec command string is a `gh pr create`. */
export declare function isPrCreateCommand(command?: string): boolean;
/**
 * The team a session SPAWNED, from an `agents teams create/add <name>` command.
 * Returns the team name, or undefined if the command isn't a team spawn. Note this
 * is the opposite of `isTeamOrigin` (which marks sessions spawned BY a team).
 */
export declare function detectSpawnedTeam(command?: string): string | undefined;
/**
 * True when a tool_use call CREATES a tracker ticket — a Linear MCP `create_issue`
 * tool, or a Bash `gh issue create`. The created id is then read from the matching
 * tool_result via {@link extractCreatedTicket}.
 */
export declare function isTicketCreateTool(name?: string, command?: string): boolean;
/**
 * Pull a created ticket ref out of a create-issue tool_result. Linear returns a
 * key like `RUSH-1234`; `gh issue create` returns the issue URL, from which we
 * take `#<number>`. Returns undefined when neither shape is present.
 */
export declare function extractCreatedTicket(text?: string): string | undefined;
/**
 * Pull the plan markdown out of an `ExitPlanMode` tool_use event's args. The
 * Claude tool schema is `{ plan: string }`; the transcript parser already
 * lifts `input` onto `event.args`. Returns undefined for a missing/empty plan
 * so consumers can rely on `plan?: string` truthiness.
 */
export declare function extractPlanText(args?: Record<string, any>): string | undefined;
/**
 * Structured question from a Claude `AskUserQuestion` tool call. Its input is
 * `{ questions: [{ question, header, options: [{label, description}] }] }` and the
 * whole thing is already parsed onto `event.args` by the transcript parser — this
 * surfaces the first question + its options (instead of collapsing to a generic
 * "Asked you a question"). The prompt is a select-list, so each option carries its
 * 1-based selection digit as `key`.
 */
export declare function structuredQuestionFromAsk(args?: Record<string, any>): StructuredQuestion | undefined;
/**
 * Infer live activity + a preview from a chronological event slice. `pr` /
 * `ticket` / `worktree` are attached by `inferSessionState`; this focuses on the
 * running-vs-waiting-vs-idle decision and the preview line.
 */
export declare function inferActivity(events: SessionEvent[], ctx?: StateContext): SessionState;
/**
 * Scan an event slice for the durable signals that aren't about the cwd: the PR
 * opened, the injected ticket, plus the artifacts the session PRODUCED — tracker
 * refs it created and any team it spawned. Each `gh pr create` / create-issue tool
 * call is correlated with the nearest following tool_result; the team name comes
 * straight off the `agents teams create/add` command.
 */
export declare function detectDurableSignals(events: SessionEvent[]): {
    pr?: DetectedPr;
    ticket?: DetectedTicket;
    createdTickets?: string[];
    spawnedTeam?: string;
    attachments?: SessionAttachment[];
};
/** Full inference: activity + preview + durable signals + worktree/ticket from ctx. */
export declare function inferSessionState(events: SessionEvent[], ctx?: StateContext): SessionState;
