import { z } from "zod"; import type { AskQuestion, AskUserResult } from "./ask-user.js"; /** * Goals: a long-running objective the user hands to GG Coder ("Bring p95 * latency under 200 ms across the whole API"). Each goal is its own folder under * `~/.gg/goals//` holding `goal.json`; that folder is also the goal's * workspace (the coordinator session's cwd) and, later, its shared library. * Context folders and files the user attaches live elsewhere on disk and are * referenced by absolute path. */ export declare const GOAL_FILE = "goal.json"; /** New names stay short enough to read at a glance in the goal list. */ export declare const GOAL_NAME_MAX = 15; export declare const GOAL_TEXT_MAX = 2000; export declare const GOAL_CONTEXT_MAX = 20; /** Standing instructions the user gives a goal (rules that hold throughout). */ export declare const GOAL_INSTRUCTIONS_MAX = 4000; /** The goal's memory file in its folder: decisions and preferences learned along the way. */ export declare const GOAL_MEMORY_FILE = "MEMORY.md"; /** How much of the memory file is loaded into GG Goals' brief. */ export declare const GOAL_MEMORY_MAX = 16000; declare const contextItemSchema: z.ZodObject<{ path: z.ZodString; kind: z.ZodEnum<{ file: "file"; folder: "folder"; }>; }, z.core.$strip>; declare const goalRecordSchema: z.ZodObject<{ schemaVersion: z.ZodLiteral<1>; id: z.ZodString; name: z.ZodString; goal: z.ZodString; context: z.ZodArray; }, z.core.$strip>>; createdAt: z.ZodString; kickoffAt: z.ZodOptional; startedAt: z.ZodOptional; critterModel: z.ZodOptional>; instructions: z.ZodOptional; pausedAt: z.ZodOptional; }, z.core.$strip>; /** What the app sends to create a goal. Context kinds are re-derived on disk. */ export declare const createGoalInputSchema: z.ZodObject<{ name: z.ZodString; goal: z.ZodString; context: z.ZodDefault>; instructions: z.ZodOptional; }, z.core.$strip>; /** What the app sends to change a goal's context or instructions after it's created. */ export declare const updateGoalInputSchema: z.ZodObject<{ context: z.ZodOptional>; instructions: z.ZodOptional; }, z.core.$strip>; export type UpdateGoalInput = z.input; export type GoalContextItem = z.infer; export type GoalRecord = z.infer; export type CreateGoalInput = z.input; export type GoalResult = { ok: true; value: T; } | { ok: false; error: string; }; /** Folder that holds every goal. */ export declare function goalsRoot(agentDir: string): string; /** Lowercase dashed folder name; empty when the name has no usable characters. */ export declare function goalSlug(name: string): string; /** True when `dir` is exactly one goal folder directly inside `root`. */ export declare function isGoalDir(root: string, dir: string): boolean; /** True when `target` is `root` or anything beneath it. */ export declare function isInsideGoalsRoot(root: string, target: string): boolean; /** Read and validate one goal folder's record; null when absent or invalid. */ export declare function readGoal(dir: string): Promise; /** * Create a goal folder and its record. The folder name is the slug, suffixed * `-2`, `-3`… when taken; `mkdir` without `recursive` makes the claim atomic. */ export declare function createGoal(root: string, input: CreateGoalInput, now: Date): Promise>; /** Every valid goal under `root` with its folder. Unreadable folders are skipped. */ export declare function listGoals(root: string): Promise>; /** * True while a goal still needs GG Goals' automatic first reply: the kickoff * was never started and the conversation has no user or assistant message yet. * The system prompt is not conversation, so it does not count. */ export declare function goalNeedsKickoff(record: GoalRecord, messages: ReadonlyArray<{ role: string; }>): boolean; /** Briefing until the user starts the goal; active from then on. */ export type GoalPhase = "briefing" | "active"; export declare function goalPhase(record: GoalRecord): GoalPhase; /** * True when an ask_user result is the user choosing to start the goal. An * answer comes back as the option's `value` when it has one, so pass the * questions asked: an option labelled GOAL_START_OPTION counts by its value * too (live bug: GG Goals gave it the value "start", the answer came back as * "start", and the goal never started). */ export declare function isGoalStartAnswer(result: AskUserResult, questions?: ReadonlyArray): boolean; /** * Start the goal if `result` is the user choosing to, whether it came back * while GG Goals was still waiting on its question or after the question's * deadline passed (a late answer). Returns the started record, or null when * the answer isn't the start option or the goal had already started. */ export declare function startGoalOnAnswer(dir: string, record: GoalRecord, result: AskUserResult, now: Date, questions?: ReadonlyArray): Promise; /** * Pin the model the goal's workers run on, or clear it (null) so they follow * GG Goals' model. Returns the updated record; null when the goal is gone. */ export declare function setGoalCritterModel(dir: string, pick: { provider: string; model: string; } | null): Promise; /** * Record that the user started the goal. Returns the updated record, or null * when it had already started (or the goal is gone), so it is set only once. */ export declare function markGoalStarted(dir: string, now: Date): Promise; /** * Change a goal's attached context or standing instructions. Paths are * re-resolved on disk like at creation; an empty instructions string clears * them. Takes effect for the goal's next session (GG Goals' brief is fixed * for a session, so its prompt cache holds). */ export declare function updateGoal(dir: string, input: UpdateGoalInput): Promise>; /** Pause a goal (true) or let it carry on (false). Returns the updated record, or null if missing. */ export declare function setGoalPaused(dir: string, paused: boolean, now: Date): Promise; /** * The goal's memory: what GG Goals has written down in its folder's * MEMORY.md (decisions, the user's preferences and corrections, what's done * and what's left). Empty when there's none yet. Long files are cut to * GOAL_MEMORY_MAX, with a note, so the brief stays bounded. */ export declare function readGoalMemory(dir: string): Promise; /** * Delete one goal: its folder (record, notes, artifacts) and the coordinator * sessions stored for it. Attached context lives elsewhere and is untouched. * `id` must name a direct child of `root`; anything else is refused. */ export declare function deleteGoal(root: string, sessionsDir: string, id: string): Promise>; /** * Record that the coordinator's first reply has started. Returns null when it * already had (or the goal is gone), so a second caller never kicks off twice. */ export declare function markGoalKickoff(dir: string, now: Date): Promise; /** The two answers to the coordinator's "ready to start?" question. */ export declare const GOAL_START_OPTION = "Start the goal now"; export declare const GOAL_HOLD_OPTION = "Hang on, I want to discuss it more"; /** * The coordinator's standing brief, appended to the system prompt of a session * whose cwd is a goal folder. Static for the goal's lifetime. */ /** What GG Goals' brief carries besides the goal itself, read once per session. */ export interface GoalBriefExtras { /** The goal folder's MEMORY.md (see readGoalMemory); empty when there's none. */ memory?: string; /** Each attached folder's instruction files (AGENTS.md, CLAUDE.md…), by folder. */ projectRules?: ReadonlyArray<{ readonly folder: string; readonly rules: readonly string[]; }>; } export declare function renderGoalPrompt(dir: string, record: GoalRecord, extras?: GoalBriefExtras): string; /** What GG Goals is told when the user changes the goal's settings mid-session. */ export declare function goalSettingsNote(record: GoalRecord): string; /** * Whether a started goal was cut off mid-work and should pick itself back up * when its session opens again: it isn't paused, and either a worker was * interrupted by the restart or GG Goals' own last turn never finished (its * last message is a tool call, or a tool result or message with no reply * after it). */ export declare function goalWasInterrupted(record: GoalRecord, messages: ReadonlyArray<{ role: string; content?: unknown; }>, workers: ReadonlyArray<{ state: string; recovered?: boolean; }>): boolean; /** * The note behind GG Goals' first run after the goal was interrupted (the * app closed or crashed mid-work): workers don't survive a restart, so it * checks what got done and carries on with the rest. Cut off mid-briefing, * it asks its question again instead. */ export declare function goalResumePrompt(record: GoalRecord): string; /** The hidden instruction behind the coordinator's first, automatic reply. */ export declare function goalKickoffPrompt(record: GoalRecord): string; export {};