@pinet/agent-goal 0.2.13 โ†’ 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @pinet/agent-goal
2
2
 
3
- A standalone Pi extension that keeps one agent session working toward one durable, bounded goal. It does not require Pinet, the Pinet broker, RALPH, or Slack.
3
+ A standalone Pi extension that keeps one agent session working toward one durable goal. It does not require Pinet, the broker, RALPH, or Slack.
4
4
 
5
- The worker runs normally and stops when its current pass is finished. Every settled active-goal run is independently evaluated as `continue`, `complete`, or `blocked`; the worker does not need to make a special terminal request. Completed, blocked, budget-limited, paused, and cleared goals do not continue.
5
+ The worker runs normally. Every settled active-goal run is independently evaluated as `continue`, `complete`, or `blocked`. A continuation starts only while the goal remains active, unsnoozed, and within any operator-enabled limits.
6
6
 
7
7
  ## Install
8
8
 
@@ -10,95 +10,71 @@ The worker runs normally and stops when its current pass is finished. Every sett
10
10
  pi install npm:@pinet/agent-goal
11
11
  ```
12
12
 
13
- For local development:
13
+ For local development: `pi -e ./agent-goal/index.ts`.
14
14
 
15
- ```bash
16
- pi -e ./agent-goal/index.ts
17
- ```
18
-
19
- ## Commands and UI
15
+ ## Commands and terminal UI
20
16
 
21
17
  ```text
22
- /goal <objective> Create and immediately start a goal
23
- /goal Open the minimal goal window (text in headless modes)
24
- /goal budget turns=<n> [tokens=<n>] Change total turn/token ceilings
25
- /goal pause Pause automatic evaluation and continuation
26
- /goal resume Resume and immediately continue
27
- /goal complete Mark complete manually
28
- /goal clear Delete the goal
29
- /goal hide Hide the compact persistent goal status
30
- /goal show Show the compact persistent goal status
18
+ /goal <idea> Ask the agent to refine a possible goal with you
19
+ /goal demo Start an agent-guided walkthrough
20
+ /goal Open the create/details overlay
21
+ /goal update Open the edit form
22
+ /goal update <objective> Apply a new objective to the next continuation
23
+ /goal update name <name> Rename immediately
24
+ /goal update objective <objective> Apply a new objective to the next continuation
25
+ /goal update budget turns <n> Set an optional total-turn limit
26
+ /goal update budget runtime <2h> Set an optional total-runtime limit
27
+ /goal update budget off Disable continuation limits
28
+ /goal snooze <30m|2h|1d> Snooze, then continue automatically
29
+ /goal close Complete and clear the current goal
30
+ /goal clear Clear the current goal immediately
31
+ /goal hide | /goal show Hide or show compact status
31
32
  ```
32
33
 
33
- Pi's footer is the only persistent goal UI and shows compact status and budget usage without duplicating the detailed dashboard. In interactive mode, `/goal` opens the detailed control window with the objective, lifecycle state, budget bars, latest evaluator guidance, and continuation state. Press `b` to edit total turn and token ceilings in place; digits edit the selected field, Tab switches fields, Enter saves, and Escape cancels. Other visible keyboard actions pause or resume the goal, mark it complete, clear it, or close the window; complete and clear require a second keypress, and validation errors remain visible in the open window. Press Escape, `q`, or Ctrl+C to close it. `/goal` retains the detailed textual dashboard in headless sessions.
34
+ `/goal <idea>` starts a normal agent turn to clarify the outcome, scope, constraints, completion evidence, and optional limits; it does not create anything until you confirm the resulting goal. The persistent row is deliberately compact: `๐ŸŽฏ name elapsed`. `/goal` opens a terminal-native overlay. An empty session gets a create form; an existing goal gets details and `e` edit, `b` limits, `s` timed snooze, and `x` close controls. Escape cancels a form or closes the details overlay; Ctrl+C also closes the overlay. Closing a goal requires confirmation and remains available for blocked and budget-limited goals.
35
+
36
+ `/goal demo` asks the agent to walk through a small example, checkpointing, inspection, and verified completion. Demo and idea discussions require a session without an existing goal; otherwise the command reports an error without starting a turn. The walkthrough asks for consent before creating its example goal.
37
+
38
+ Name changes are visible immediately. Objective changes are fenced from stale evaluations and are used by the next continuation. Snooze is timed only: there is no indefinite pause or manual resume action, and a compare-and-swap wake prevents duplicate continuation.
39
+
40
+ Only one current goal may exist per Pi session. A verified completion clears that current goal so another can be created; `/goal close` records completion before clearing, while `/goal clear` removes it immediately. Clearing removes its persisted checkpoints as well.
34
41
 
35
- Only one goal may exist per Pi session. Clear the existing goal before creating another.
42
+ ## Agent tools and checkpoints
36
43
 
37
- The agent also receives four model-visible tools:
44
+ The extension registers five model-visible tools:
38
45
 
39
- - `create_goal` โ€” create its own bounded, user-aligned durable goal
40
- - `update_goal_budget` โ€” change the current goal's total turn or token ceiling
41
- - `get_goal` โ€” inspect the current objective, status, and budget
42
- - `update_goal` โ€” optionally attach a `complete` or `blocked` hint for independent verification
46
+ - `create_goal` โ€” create a user-aligned goal with a short name and objective
47
+ - `checkpoint_goal` โ€” append progress with optional evidence, next step, or blocker
48
+ - `update_goal_budget` โ€” set optional turn/runtime continuation limits or turn them off
49
+ - `get_goal` โ€” inspect current durable state
50
+ - `update_goal` โ€” attach a `complete` or `blocked` candidate for independent evaluation
43
51
 
44
- An agent-created goal cannot replace an existing goal. The creating run is evaluated when it settles, but its iteration and token usage are not charged because some work may predate goal creation. A `continue` decision starts the first charged goal iteration.
52
+ Checkpoints are agent-reported progress records, not recovery snapshots. They persist with the goal. The overlay initially shows the newest three checkpoints. Tab/Shift+Tab selects across the full history; Enter opens the selected checkpoint's full summary, evidence, next step, and blocker. Use โ†‘/โ†“ to scroll and Escape to return. The headless dashboard shows the newest three and `โ€ฆ and X more`.
45
53
 
46
- ## Budgets
54
+ ## Optional continuation limits
47
55
 
48
- Goals default to 25 settled iterations. Optional token and runtime limits are supported:
56
+ New goals are unlimited by default. Turns and runtime limits are opt-in and only decide whether a future continuation may start; they never interrupt in-flight work. Existing usage is preserved when limits change or are disabled. Configured environment values remain hard ceilings/defaults when present:
49
57
 
50
58
  ```text
51
59
  PI_AGENT_GOAL_MAX_ITERATIONS=25
52
- PI_AGENT_GOAL_MAX_TOKENS=200000
53
60
  PI_AGENT_GOAL_MAX_RUNTIME_MS=14400000
54
61
  ```
55
62
 
56
- Iteration and runtime limits are always reliable. Token accounting uses usage reported by Pi providers. Operators and the goal-bearing agent may update total turn and token ceilings without recreating the goal. Changes are optimistic and atomic, cannot reduce a ceiling below accounted usage, must reserve capacity for a currently active turn, and cannot exceed a configured default ceiling when one exists. Increasing an exhausted budget reactivates the same goal when capacity is available; no budget change alters the objective or erases usage.
63
+ Legacy token limits and accounted token usage remain readable and enforceable for stored goals, but token controls are omitted from the new UX because provider accounting is not reliably comparable.
57
64
 
58
- The evaluator reviews every settled run, including the final allowed turn, so a completed goal is not incorrectly classified as budget-limited; only another continuation is prevented. The former `PI_AGENT_GOAL_EVALUATION_INTERVAL` setting is accepted for configuration compatibility but no longer changes evaluation frequency.
65
+ The evaluator reviews every settled run, including the final allowed turn, before a goal becomes budget-limited. Increasing or disabling exhausted limits reactivates the same goal when continuation capacity exists.
59
66
 
60
67
  ## Persistence and recovery
61
68
 
62
- The default adapter stores goals and continuation claims in SQLite at:
69
+ SQLite storage defaults to `~/.pi/agent/agent-goals.sqlite`; set `PI_AGENT_GOAL_DB` to override it. Schema upgrades add nullable name/snooze fields and durable checkpoints without discarding legacy goals or token data. Legacy goals derive their display name from their objective.
63
70
 
64
- ```text
65
- ~/.pi/agent/agent-goals.sqlite
66
- ```
67
-
68
- Set `PI_AGENT_GOAL_DB` to use another path. The stable Pi session ID is the storage scope, so resuming a session restores its goal. Optimistic goal versions reject stale mutations.
71
+ Optimistic versions reject stale mutations. Metadata/limit edits atomically advance pending evaluation, candidate, and continuation-claim versions. Evaluation commit updates lifecycle and usage fields only, so an old result cannot overwrite a newer name, objective, limit, or snooze. Settlements arriving during evaluation are aggregated and charged exactly once.
69
72
 
70
- Every continuation first acquires a durable, idempotent per-session claim. Busy sessions persist a deferred claim and schedule an in-process wake for their retry time without consuming failure attempts. Started claims schedule an expiry wake, remain until the next agent run begins, and recover safely after interruption or session resume. Evaluator and unavailable/rejected continuation failures use bounded exponential retries; exhausted retries block the goal with a diagnostic reason.
71
-
72
- Settlements that arrive during an in-flight evaluation are atomically aggregated in storage. Every settled iteration and token delta is charged, while the evaluator receives the newest bounded progress and any preserved terminal candidate. Event sinks receive `goal.evaluated` for every committed evaluation; a no-hint `continue` also retains the compatibility `goal.auto_continued` event.
73
+ Every continuation acquires a durable per-session claim. Busy sessions defer with an in-process wake. Timed snooze uses the same scheduler; expiry clears the snooze with compare-and-swap before continuation, so duplicate timer callbacks cannot produce duplicate wakes. Failures use bounded retries and eventually block with a diagnostic reason.
73
74
 
74
75
  ## Architecture
75
76
 
76
- The domain and runtime depend on ports rather than Pi, Pinet, or SQLite:
77
-
78
- ```ts
79
- interface GoalEvaluator {
80
- evaluate(goal: AgentGoal, progress: GoalProgress): Promise<GoalEvaluation>;
81
- }
82
-
83
- interface GoalContinuation {
84
- continueIfIdle(
85
- goal: AgentGoal,
86
- request: GoalContinuationRequest,
87
- ): Promise<GoalContinuationResult>;
88
- }
89
-
90
- interface GoalEventSink {
91
- record(event: GoalEvent): Promise<void> | void;
92
- }
93
-
94
- interface GoalWakeScheduler {
95
- schedule(scopeId: string, wakeAt: string, wake: () => void): void;
96
- cancel(scopeId: string): void;
97
- close(): void;
98
- }
99
- ```
100
-
101
- `GoalStorage` includes optimistic goal mutation, atomic pending-settlement aggregation, and durable continuation-claim operations. `TimerGoalWakeScheduler` is the default process-local wake adapter and can be replaced through `GoalRuntimeOptions`. The package exports `GoalRuntime`, both storage adapters, the wake adapter, `PiGoalEvaluator`, dashboard formatters, lifecycle event types, and `registerAgentGoal`.
77
+ The runtime depends on ports for evaluation, continuation, events, wake scheduling, and storage. `GoalStorage` owns optimistic goal mutations, checkpoints, pending-settlement aggregation, terminal candidates, and continuation claims. The package exports `GoalRuntime`, memory/SQLite storage, `TimerGoalWakeScheduler`, `PiGoalEvaluator`, dashboard formatters, and `registerAgentGoal`.
102
78
 
103
79
  ```ts
104
80
  import { registerAgentGoal } from "@pinet/agent-goal";
@@ -108,26 +84,10 @@ registerAgentGoal(pi, {
108
84
  evaluator: myEvaluator,
109
85
  continuation: myAtomicContinuationAdapter,
110
86
  eventSink: myEventSink,
111
- defaultBudget: { maxIterations: 20, maxTokens: 150_000 },
87
+ defaultBudget: { maxIterations: 20, maxRuntimeMs: 14_400_000 },
112
88
  });
113
89
  ```
114
90
 
115
- The continuation adapter owns the final idle check and idempotent enqueue. Pi's current API does not expose Codex's exact `start_turn_if_idle` primitive, so the default adapter performs the closest safe operation: it rechecks session identity, idle state, and pending messages immediately before submitting a follow-up. A future Pi or Pinet adapter can provide a truly atomic implementation without changing `GoalRuntime`.
116
-
117
- A future Pinet integration can use broker storage and evaluation plus RALPH recovery through these ports, without introducing multi-agent decomposition.
118
-
119
- ## Automatic evaluation
120
-
121
- The extension registers model-visible `create_goal`, `update_goal_budget`, `get_goal`, and `update_goal` tools. The worker can establish its own user-aligned goal, inspect it, and adjust its bounded capacity. `update_goal` is optional: it records a terminal hint rather than mutating goal state directly. Every `agent_settled` event accounts the run and invokes the independent evaluator whether or not the worker supplied that hint.
122
-
123
- The evaluator returns one of:
124
-
125
- - `continue` with the next required work
126
- - `complete` with completion evidence
127
- - `blocked` with a specific unavailable external dependency
128
-
129
- The standalone in-process evaluator receives bounded recent assistant and tool evidence plus any terminal candidate. Its output is strictly parsed. Newer settled progress supersedes an older in-flight result. Invalid output and provider failures are retried within policy, then recorded as a blocked goal rather than allowing an unverified terminal decision.
130
-
131
- The standalone evaluator intentionally remains a zero-process, zero-runtime-dependency baseline. A future Pinet broker adapter can replace storage, evaluation, continuation, and events to add authoritative evidence inspection, atomic wake scheduling, and watchdog recovery. Subagent evaluators remain optional adapters; tmux and spawned Pi processes are not required.
91
+ Pi's current API does not expose Codex's exact `start_turn_if_idle` primitive. The default adapter rechecks session identity, idle state, and pending messages immediately before follow-up submission. A Pinet adapter can replace these ports without changing `GoalRuntime`.
132
92
 
133
- Continuation prompts explicitly treat the objective as user-provided task data, never as higher-priority instructions.
93
+ Continuation prompts treat the objective as user-provided task data, never as higher-priority instructions.
@@ -1,4 +1,6 @@
1
- import type { AgentGoal, GoalContinuationClaim } from "./domain.js";
1
+ import type { AgentGoal, GoalCheckpoint, GoalContinuationClaim } from "./domain.js";
2
2
  export declare function displayGoalText(value: string, maxLength: number): string;
3
- export declare function formatGoalStatus(goal: AgentGoal): string;
4
- export declare function formatGoalDashboard(goal: AgentGoal, claim?: GoalContinuationClaim): string[];
3
+ export declare function goalDisplayName(goal: AgentGoal): string;
4
+ export declare function formatElapsed(milliseconds: number): string;
5
+ export declare function formatGoalStatus(goal: AgentGoal, now?: number): string;
6
+ export declare function formatGoalDashboard(goal: AgentGoal, claim?: GoalContinuationClaim, checkpoints?: GoalCheckpoint[]): string[];
package/dist/dashboard.js CHANGED
@@ -1,35 +1,48 @@
1
+ import { stripVTControlCharacters } from "node:util";
1
2
  export function displayGoalText(value, maxLength) {
2
- const normalized = value
3
- .replaceAll("\n", " ")
4
- .replaceAll("\r", " ")
5
- .replaceAll("\u001b", "")
3
+ const normalized = Array.from(stripVTControlCharacters(value).replaceAll(/\r?\n/g, " "))
4
+ .filter((character) => {
5
+ const code = character.codePointAt(0) ?? 0;
6
+ return code >= 32 && (code < 127 || code > 159);
7
+ })
8
+ .join("")
6
9
  .trim();
7
10
  return normalized.length > maxLength ? `${normalized.slice(0, maxLength - 3)}...` : normalized;
8
11
  }
9
- export function formatGoalStatus(goal) {
10
- const iterations = `${goal.usage.iterations}/${goal.budget.maxIterations}`;
11
- const tokens = goal.budget.maxTokens
12
- ? ` ยท ${goal.usage.tokens}/${goal.budget.maxTokens} tok`
13
- : "";
14
- return `goal: ${goal.status} ยท ${iterations} turns${tokens}`;
12
+ export function goalDisplayName(goal) {
13
+ return displayGoalText(goal.name ?? goal.objective, 72);
15
14
  }
16
- export function formatGoalDashboard(goal, claim) {
17
- const usage = [
18
- `Turns ${goal.usage.iterations}/${goal.budget.maxIterations}`,
19
- goal.budget.maxTokens === undefined
20
- ? `Tokens ${goal.usage.tokens}`
21
- : `Tokens ${goal.usage.tokens}/${goal.budget.maxTokens}`,
22
- goal.budget.maxRuntimeMs === undefined
23
- ? undefined
24
- : `Runtime limit ${Math.round(goal.budget.maxRuntimeMs / 60_000)}m`,
25
- ]
26
- .filter((value) => value !== undefined)
27
- .join(" ยท ");
15
+ export function formatElapsed(milliseconds) {
16
+ const seconds = Math.max(0, Math.floor(milliseconds / 1_000));
17
+ if (seconds < 60)
18
+ return `${seconds}s`;
19
+ const minutes = Math.floor(seconds / 60);
20
+ if (minutes < 60)
21
+ return `${minutes}m ${seconds % 60}s`;
22
+ const hours = Math.floor(minutes / 60);
23
+ return `${hours}h ${minutes % 60}m`;
24
+ }
25
+ export function formatGoalStatus(goal, now = Date.now()) {
26
+ const end = goal.status === "active" ? now : Date.parse(goal.updatedAt);
27
+ return `๐ŸŽฏ ${goalDisplayName(goal)} ${formatElapsed(end - Date.parse(goal.createdAt))}`;
28
+ }
29
+ export function formatGoalDashboard(goal, claim, checkpoints = []) {
28
30
  const lines = [
29
31
  `Goal ยท ${goal.status} ยท v${goal.version}`,
32
+ goalDisplayName(goal),
30
33
  displayGoalText(goal.objective, 120),
31
- usage,
32
34
  ];
35
+ const limits = [
36
+ goal.budget.maxIterations === undefined
37
+ ? undefined
38
+ : `Turns ${goal.usage.iterations}/${goal.budget.maxIterations}`,
39
+ goal.budget.maxRuntimeMs === undefined
40
+ ? undefined
41
+ : `Runtime ${Math.round(goal.budget.maxRuntimeMs / 60_000)}m`,
42
+ ].filter((value) => value !== undefined);
43
+ lines.push(limits.length ? `Limits: ${limits.join(" ยท ")}` : "Limits: off");
44
+ if (goal.snoozedUntil)
45
+ lines.push(`Snoozed until ${goal.snoozedUntil}`);
33
46
  if (goal.lastEvaluation) {
34
47
  lines.push(`Last ${goal.lastEvaluation.outcome.toUpperCase()}: ${displayGoalText(goal.lastEvaluation.reason, 100)}`);
35
48
  }
@@ -37,6 +50,11 @@ export function formatGoalDashboard(goal, claim) {
37
50
  lines.push(`Reason: ${displayGoalText(goal.blockedReason, 100)}`);
38
51
  if (claim)
39
52
  lines.push(`Continuation: ${claim.state} ยท attempt ${claim.attempt}`);
40
- lines.push("/goal budget turns=<n> tokens=<n> ยท pause ยท resume ยท complete ยท clear ยท hide");
53
+ for (const checkpoint of checkpoints.slice(0, 3)) {
54
+ lines.push(`Checkpoint ${checkpoint.createdAt}: ${displayGoalText(checkpoint.summary, 90)}`);
55
+ }
56
+ if (checkpoints.length > 3)
57
+ lines.push(`โ€ฆ and ${checkpoints.length - 3} more checkpoints`);
58
+ lines.push("/goal update ยท snooze <duration> ยท close ยท hide");
41
59
  return lines;
42
60
  }
package/dist/domain.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export type GoalStatus = "active" | "paused" | "blocked" | "budget_limited" | "complete";
2
2
  export interface GoalBudget {
3
- maxIterations: number;
3
+ maxIterations?: number;
4
+ /** @deprecated Token usage is provider-reported and is retained for stored-goal compatibility only. */
4
5
  maxTokens?: number;
5
6
  maxRuntimeMs?: number;
6
7
  }
@@ -10,8 +11,21 @@ export interface GoalUsage {
10
11
  }
11
12
  export interface GoalBudgetUpdate {
12
13
  maxIterations?: number;
14
+ maxRuntimeMs?: number;
15
+ disabled?: boolean;
16
+ /** @deprecated Retained for compatibility with previously stored goals. */
13
17
  maxTokens?: number;
14
18
  }
19
+ export interface GoalCheckpoint {
20
+ id: string;
21
+ scopeId: string;
22
+ goalId: string;
23
+ summary: string;
24
+ evidence?: string;
25
+ nextStep?: string;
26
+ blocker?: string;
27
+ createdAt: string;
28
+ }
15
29
  export interface GoalEvaluationRecord {
16
30
  id: string;
17
31
  outcome: GoalEvaluation["outcome"];
@@ -21,9 +35,12 @@ export interface GoalEvaluationRecord {
21
35
  export interface AgentGoal {
22
36
  id: string;
23
37
  scopeId: string;
38
+ /** Legacy goals derive their display name from the objective until first edited. */
39
+ name?: string;
24
40
  objective: string;
25
41
  status: GoalStatus;
26
42
  blockedReason?: string;
43
+ snoozedUntil?: string;
27
44
  budget: GoalBudget;
28
45
  usage: GoalUsage;
29
46
  lastSettledAt?: string;
@@ -91,6 +108,8 @@ export interface GoalStorage {
91
108
  create(goal: AgentGoal): Promise<void>;
92
109
  replace(goal: AgentGoal, expectedVersion: number): Promise<boolean>;
93
110
  updateBudget(goal: AgentGoal, expectedVersion: number): Promise<boolean>;
111
+ addCheckpoint(checkpoint: GoalCheckpoint): Promise<boolean>;
112
+ listCheckpoints(scopeId: string): Promise<GoalCheckpoint[]>;
94
113
  delete(scopeId: string, expectedVersion: number): Promise<boolean>;
95
114
  getPendingEvaluation(scopeId: string): Promise<GoalPendingEvaluation | undefined>;
96
115
  appendPendingEvaluation(pending: GoalPendingEvaluation): Promise<boolean>;
@@ -152,6 +171,20 @@ export type GoalEvent = {
152
171
  type: "goal.budget_changed";
153
172
  goal: AgentGoal;
154
173
  previousBudget: GoalBudget;
174
+ } | {
175
+ type: "goal.updated";
176
+ goal: AgentGoal;
177
+ } | {
178
+ type: "goal.checkpoint_added";
179
+ goal: AgentGoal;
180
+ checkpoint: GoalCheckpoint;
181
+ } | {
182
+ type: "goal.snoozed";
183
+ goal: AgentGoal;
184
+ snoozedUntil: string;
185
+ } | {
186
+ type: "goal.snooze_expired";
187
+ goal: AgentGoal;
155
188
  } | {
156
189
  type: "goal.evaluated";
157
190
  goal: AgentGoal;
@@ -1,11 +1,29 @@
1
1
  import type { Theme } from "@earendil-works/pi-coding-agent";
2
2
  import { type Component } from "@earendil-works/pi-tui";
3
- import type { AgentGoal, GoalContinuationClaim } from "./domain.js";
4
- export type GoalWindowLifecycleAction = "pause" | "resume" | "complete" | "clear" | "close";
5
- export type GoalWindowAction = GoalWindowLifecycleAction | {
3
+ import type { AgentGoal, GoalCheckpoint, GoalContinuationClaim } from "./domain.js";
4
+ export type GoalWindowAction = "close" | "closeGoal"
5
+ /** @deprecated Parsed only for compatibility with older integrations; not exposed in the UI. */
6
+ | "pause"
7
+ /** @deprecated Parsed only for compatibility with older integrations; not exposed in the UI. */
8
+ | "resume" | {
9
+ type: "create";
10
+ name: string;
11
+ objective: string;
12
+ maxIterations?: number;
13
+ maxRuntimeMs?: number;
14
+ } | {
15
+ type: "edit";
16
+ name?: string;
17
+ objective?: string;
18
+ } | {
6
19
  type: "budget";
7
- maxIterations: number;
20
+ maxIterations?: number;
21
+ maxRuntimeMs?: number;
8
22
  maxTokens?: number;
23
+ disabled?: boolean;
24
+ } | {
25
+ type: "snooze";
26
+ durationMs: number;
9
27
  };
10
28
  export declare class GoalWindow implements Component {
11
29
  private readonly goal;
@@ -15,14 +33,33 @@ export declare class GoalWindow implements Component {
15
33
  private readonly requestRender;
16
34
  private readonly now;
17
35
  private readonly actionError?;
18
- private pendingConfirmation;
36
+ private readonly checkpoints;
37
+ private mode;
38
+ private textField;
39
+ private name;
40
+ private objective;
41
+ private initialName;
42
+ private initialObjective;
19
43
  private budgetField;
20
44
  private budgetTurns;
21
- private budgetTokens;
22
- private replaceBudgetValue;
23
- private budgetInputError;
24
- constructor(goal: AgentGoal | undefined, claim: GoalContinuationClaim | undefined, theme: Theme, onAction: (action: GoalWindowAction) => void, requestRender?: () => void, now?: () => number, actionError?: string | undefined);
45
+ private budgetRuntime;
46
+ private snoozeDuration;
47
+ private inputError;
48
+ private confirmClose;
49
+ private selectedCheckpoint;
50
+ private checkpointOffset;
51
+ private checkpointLineCount;
52
+ private refreshTimer;
53
+ constructor(goal: AgentGoal | undefined, claim: GoalContinuationClaim | undefined, theme: Theme, onAction: (action: GoalWindowAction) => void, requestRender?: () => void, now?: () => number, actionError?: string | undefined, checkpoints?: GoalCheckpoint[], initialMode?: "details" | "edit");
25
54
  handleInput(data: string): void;
55
+ private openTextForm;
56
+ private handleTextForm;
57
+ private openBudgetForm;
58
+ private handleBudgetForm;
59
+ private handleSnoozeForm;
26
60
  render(width: number): string[];
61
+ private finish;
27
62
  invalidate(): void;
63
+ dispose(): void;
28
64
  }
65
+ export declare function parseDuration(value: string): number | undefined;