@theokit/sdk 2.2.0 → 2.3.0

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.
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `runToCompletion` continuation driver (M1 Phase 3 — plan m1-run-to-completion).
3
+ *
4
+ * Drives repeated `send()`s on a STATEFUL agent until a genuine terminal,
5
+ * consuming the `RunResult.stoppedAtIterationLimit` signal shipped in 2.2.0.
6
+ * The agent's session preserves conversation history across sends, so after a
7
+ * truncated round the driver only re-sends a short continuation prompt (it does
8
+ * NOT reconstruct history). Mirrors the injectable shape of `run-until.ts` and
9
+ * absorbs the outer-loop policy hand-rolled in `theocode/server/lib/agent-loop.ts`.
10
+ *
11
+ * The core is decision-pure + injectable (`agent` is only the `.send` port) so
12
+ * every terminal is unit-testable with a fake send — fixture mode never sets
13
+ * `stoppedAtIterationLimit`, so injection is the only deterministic path.
14
+ *
15
+ * @internal
16
+ */
17
+ /** Minimal agent port the driver needs — the instance `.send()` surface. */
18
+ export interface RunToCompletionAgent {
19
+ send(message: string, options?: SendOptions): Promise<{
20
+ wait(): Promise<RunResult>;
21
+ }>;
22
+ }
@@ -625,7 +625,7 @@ type RunStatus = "running" | "finished" | "error" | "cancelled";
625
625
  *
626
626
  * @public
627
627
  */
628
- type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "fork" | "usePersonality" | "workflow";
628
+ type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "runToCompletion" | "fork" | "usePersonality" | "workflow";
629
629
  /**
630
630
  * Git metadata attached to cloud runs.
631
631
  *
@@ -688,6 +688,59 @@ interface RunResult {
688
688
  */
689
689
  stoppedAtIterationLimit?: boolean;
690
690
  }
691
+ /**
692
+ * Options for {@link SDKAgent.runToCompletion} (M1 Phase 3 — continuation driver).
693
+ *
694
+ * @public
695
+ */
696
+ interface RunToCompletionOptions {
697
+ /**
698
+ * Maximum number of continuation rounds (re-sends) before giving up with
699
+ * `terminal: "step_limit"`. Default 5. A hard ceiling that prevents a
700
+ * runaway loop when the model keeps truncating.
701
+ */
702
+ maxRounds?: number;
703
+ /**
704
+ * The short prompt re-sent after a truncated round to make the (stateful)
705
+ * agent resume. Defaults to a generic "continue" instruction. The original
706
+ * conversation is preserved by the agent's session, so this need not repeat
707
+ * the task.
708
+ */
709
+ continuationPrompt?: string;
710
+ /** Called once per truncated round that triggers a re-send (for metrics/logging). */
711
+ onTruncated?: (event: {
712
+ round: number;
713
+ }) => void | Promise<void>;
714
+ /** Abort signal; checked between rounds — once aborted, no further round starts. */
715
+ signal?: AbortSignal;
716
+ /** Per-send options forwarded to each underlying `send()` (e.g. `maxIterations`). */
717
+ sendOptions?: SendOptions;
718
+ }
719
+ /**
720
+ * Result of {@link SDKAgent.runToCompletion}.
721
+ *
722
+ * @public
723
+ */
724
+ interface RunToCompletionResult {
725
+ /**
726
+ * Why the driver stopped:
727
+ * - `"done"` — a round finished without truncating (the model is done).
728
+ * - `"step_limit"` — `maxRounds` exhausted (or aborted) while still truncating.
729
+ * - `"no_progress"` — two consecutive rounds produced empty output.
730
+ */
731
+ terminal: "done" | "step_limit" | "no_progress";
732
+ /**
733
+ * Index of the final round. Round 0 is the initial `send`; rounds ≥ 1 are
734
+ * continuation re-sends. So `terminal: "done"` with `rounds: 0` means the
735
+ * first send finished without truncating; `rounds: N` means N continuation
736
+ * re-sends happened. For `step_limit`, `rounds` equals `maxRounds`.
737
+ */
738
+ rounds: number;
739
+ /** The `RunResult` of the final round. */
740
+ lastResult: RunResult;
741
+ /** Token usage summed across all rounds; `undefined` when no round reported usage. */
742
+ usage?: TokenUsage;
743
+ }
691
744
  /**
692
745
  * Structured error attached to a {@link RunResult} when the underlying run
693
746
  * transitioned to `"error"` status. `message` is always present; `code` is
@@ -840,4 +893,4 @@ interface Run {
840
893
  onDidChangeStatus(listener: (status: RunStatus) => void): () => void;
841
894
  }
842
895
 
843
- export type { ToolCall as $, AgentConversationTurn as A, SDKToolUseMessage as B, CustomTool as C, SDKUserMessage as D, SDKUserMessageEvent as E, SendOptions as F, ShellCommand as G, ShellConversationTurn as H, InteractionUpdate as I, ShellOutput as J, ShellOutputDeltaUpdate as K, StepCompletedUpdate as L, ModelSelection as M, StepStartedUpdate as N, SummaryCompletedUpdate as O, PartialToolCallUpdate as P, SummaryStartedUpdate as Q, RunResult as R, SDKMessage as S, SummaryUpdate as T, TextBlock as U, TextDeltaUpdate as V, ThinkingCompletedUpdate as W, ThinkingDeltaUpdate as X, ThinkingMessage as Y, TokenDeltaUpdate as Z, TokenUsage as _, McpServerConfig as a, ToolCallCompletedUpdate as a0, ToolCallStartedUpdate as a1, ToolResult as a2, ToolUseBlock as a3, TurnEndedUpdate as a4, UserMessage as a5, UserMessageAppendedUpdate as a6, Run as b, AssistantMessage as c, ConversationStep as d, ConversationTurn as e, CostBreakdown as f, CostSource as g, CostStatus as h, McpAuthConfig as i, McpHttpServerConfig as j, McpOAuthConfig as k, McpStdioServerConfig as l, ModelParameterValue as m, RunErrorDetail as n, RunGitInfo as o, RunOperation as p, RunStatus as q, SDKAssistantMessage as r, SDKImage as s, SDKImageDimension as t, SDKObjectDelta as u, SDKRequestMessage as v, SDKStatusMessage as w, SDKSystemMessage as x, SDKTaskMessage as y, SDKThinkingMessage as z };
896
+ export type { TokenDeltaUpdate as $, AgentConversationTurn as A, SDKTaskMessage as B, CustomTool as C, SDKThinkingMessage as D, SDKToolUseMessage as E, SDKUserMessage as F, SDKUserMessageEvent as G, SendOptions as H, InteractionUpdate as I, ShellCommand as J, ShellConversationTurn as K, ShellOutput as L, ModelSelection as M, ShellOutputDeltaUpdate as N, StepCompletedUpdate as O, PartialToolCallUpdate as P, StepStartedUpdate as Q, RunResult as R, SDKMessage as S, SummaryCompletedUpdate as T, SummaryStartedUpdate as U, SummaryUpdate as V, TextBlock as W, TextDeltaUpdate as X, ThinkingCompletedUpdate as Y, ThinkingDeltaUpdate as Z, ThinkingMessage as _, McpServerConfig as a, TokenUsage as a0, ToolCall as a1, ToolCallCompletedUpdate as a2, ToolCallStartedUpdate as a3, ToolResult as a4, ToolUseBlock as a5, TurnEndedUpdate as a6, UserMessage as a7, UserMessageAppendedUpdate as a8, Run as b, AssistantMessage as c, ConversationStep as d, ConversationTurn as e, CostBreakdown as f, CostSource as g, CostStatus as h, McpAuthConfig as i, McpHttpServerConfig as j, McpOAuthConfig as k, McpStdioServerConfig as l, ModelParameterValue as m, RunErrorDetail as n, RunGitInfo as o, RunOperation as p, RunStatus as q, RunToCompletionOptions as r, RunToCompletionResult as s, SDKAssistantMessage as t, SDKImage as u, SDKImageDimension as v, SDKObjectDelta as w, SDKRequestMessage as x, SDKStatusMessage as y, SDKSystemMessage as z };
@@ -625,7 +625,7 @@ type RunStatus = "running" | "finished" | "error" | "cancelled";
625
625
  *
626
626
  * @public
627
627
  */
628
- type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "fork" | "usePersonality" | "workflow";
628
+ type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "runToCompletion" | "fork" | "usePersonality" | "workflow";
629
629
  /**
630
630
  * Git metadata attached to cloud runs.
631
631
  *
@@ -688,6 +688,59 @@ interface RunResult {
688
688
  */
689
689
  stoppedAtIterationLimit?: boolean;
690
690
  }
691
+ /**
692
+ * Options for {@link SDKAgent.runToCompletion} (M1 Phase 3 — continuation driver).
693
+ *
694
+ * @public
695
+ */
696
+ interface RunToCompletionOptions {
697
+ /**
698
+ * Maximum number of continuation rounds (re-sends) before giving up with
699
+ * `terminal: "step_limit"`. Default 5. A hard ceiling that prevents a
700
+ * runaway loop when the model keeps truncating.
701
+ */
702
+ maxRounds?: number;
703
+ /**
704
+ * The short prompt re-sent after a truncated round to make the (stateful)
705
+ * agent resume. Defaults to a generic "continue" instruction. The original
706
+ * conversation is preserved by the agent's session, so this need not repeat
707
+ * the task.
708
+ */
709
+ continuationPrompt?: string;
710
+ /** Called once per truncated round that triggers a re-send (for metrics/logging). */
711
+ onTruncated?: (event: {
712
+ round: number;
713
+ }) => void | Promise<void>;
714
+ /** Abort signal; checked between rounds — once aborted, no further round starts. */
715
+ signal?: AbortSignal;
716
+ /** Per-send options forwarded to each underlying `send()` (e.g. `maxIterations`). */
717
+ sendOptions?: SendOptions;
718
+ }
719
+ /**
720
+ * Result of {@link SDKAgent.runToCompletion}.
721
+ *
722
+ * @public
723
+ */
724
+ interface RunToCompletionResult {
725
+ /**
726
+ * Why the driver stopped:
727
+ * - `"done"` — a round finished without truncating (the model is done).
728
+ * - `"step_limit"` — `maxRounds` exhausted (or aborted) while still truncating.
729
+ * - `"no_progress"` — two consecutive rounds produced empty output.
730
+ */
731
+ terminal: "done" | "step_limit" | "no_progress";
732
+ /**
733
+ * Index of the final round. Round 0 is the initial `send`; rounds ≥ 1 are
734
+ * continuation re-sends. So `terminal: "done"` with `rounds: 0` means the
735
+ * first send finished without truncating; `rounds: N` means N continuation
736
+ * re-sends happened. For `step_limit`, `rounds` equals `maxRounds`.
737
+ */
738
+ rounds: number;
739
+ /** The `RunResult` of the final round. */
740
+ lastResult: RunResult;
741
+ /** Token usage summed across all rounds; `undefined` when no round reported usage. */
742
+ usage?: TokenUsage;
743
+ }
691
744
  /**
692
745
  * Structured error attached to a {@link RunResult} when the underlying run
693
746
  * transitioned to `"error"` status. `message` is always present; `code` is
@@ -840,4 +893,4 @@ interface Run {
840
893
  onDidChangeStatus(listener: (status: RunStatus) => void): () => void;
841
894
  }
842
895
 
843
- export type { ToolCall as $, AgentConversationTurn as A, SDKToolUseMessage as B, CustomTool as C, SDKUserMessage as D, SDKUserMessageEvent as E, SendOptions as F, ShellCommand as G, ShellConversationTurn as H, InteractionUpdate as I, ShellOutput as J, ShellOutputDeltaUpdate as K, StepCompletedUpdate as L, ModelSelection as M, StepStartedUpdate as N, SummaryCompletedUpdate as O, PartialToolCallUpdate as P, SummaryStartedUpdate as Q, RunResult as R, SDKMessage as S, SummaryUpdate as T, TextBlock as U, TextDeltaUpdate as V, ThinkingCompletedUpdate as W, ThinkingDeltaUpdate as X, ThinkingMessage as Y, TokenDeltaUpdate as Z, TokenUsage as _, McpServerConfig as a, ToolCallCompletedUpdate as a0, ToolCallStartedUpdate as a1, ToolResult as a2, ToolUseBlock as a3, TurnEndedUpdate as a4, UserMessage as a5, UserMessageAppendedUpdate as a6, Run as b, AssistantMessage as c, ConversationStep as d, ConversationTurn as e, CostBreakdown as f, CostSource as g, CostStatus as h, McpAuthConfig as i, McpHttpServerConfig as j, McpOAuthConfig as k, McpStdioServerConfig as l, ModelParameterValue as m, RunErrorDetail as n, RunGitInfo as o, RunOperation as p, RunStatus as q, SDKAssistantMessage as r, SDKImage as s, SDKImageDimension as t, SDKObjectDelta as u, SDKRequestMessage as v, SDKStatusMessage as w, SDKSystemMessage as x, SDKTaskMessage as y, SDKThinkingMessage as z };
896
+ export type { TokenDeltaUpdate as $, AgentConversationTurn as A, SDKTaskMessage as B, CustomTool as C, SDKThinkingMessage as D, SDKToolUseMessage as E, SDKUserMessage as F, SDKUserMessageEvent as G, SendOptions as H, InteractionUpdate as I, ShellCommand as J, ShellConversationTurn as K, ShellOutput as L, ModelSelection as M, ShellOutputDeltaUpdate as N, StepCompletedUpdate as O, PartialToolCallUpdate as P, StepStartedUpdate as Q, RunResult as R, SDKMessage as S, SummaryCompletedUpdate as T, SummaryStartedUpdate as U, SummaryUpdate as V, TextBlock as W, TextDeltaUpdate as X, ThinkingCompletedUpdate as Y, ThinkingDeltaUpdate as Z, ThinkingMessage as _, McpServerConfig as a, TokenUsage as a0, ToolCall as a1, ToolCallCompletedUpdate as a2, ToolCallStartedUpdate as a3, ToolResult as a4, ToolUseBlock as a5, TurnEndedUpdate as a6, UserMessage as a7, UserMessageAppendedUpdate as a8, Run as b, AssistantMessage as c, ConversationStep as d, ConversationTurn as e, CostBreakdown as f, CostSource as g, CostStatus as h, McpAuthConfig as i, McpHttpServerConfig as j, McpOAuthConfig as k, McpStdioServerConfig as l, ModelParameterValue as m, RunErrorDetail as n, RunGitInfo as o, RunOperation as p, RunStatus as q, RunToCompletionOptions as r, RunToCompletionResult as s, SDKAssistantMessage as t, SDKImage as u, SDKImageDimension as v, SDKObjectDelta as w, SDKRequestMessage as x, SDKStatusMessage as y, SDKSystemMessage as z };
@@ -608,6 +608,20 @@ export interface SDKAgent {
608
608
  * @public
609
609
  */
610
610
  fork?(options: import("./fork.js").ForkOptions): Promise<import("./fork.js").ForkResult>;
611
+ /**
612
+ * Drive `send` to completion across iteration-ceiling truncations (M1 Phase 3).
613
+ * When a `send` stops at the loop's iteration cap (`RunResult.stoppedAtIterationLimit`),
614
+ * this re-sends a short continuation prompt — the agent's stateful session
615
+ * preserves the conversation — until a genuine terminal: `done` (finished),
616
+ * `step_limit` (`maxRounds` exhausted), or `no_progress` (two empty rounds).
617
+ *
618
+ * Local agents only. Cloud agents throw
619
+ * {@link import("../errors.js").UnsupportedRunOperationError} (the cloud
620
+ * runtime manages its own continuation policy server-side).
621
+ *
622
+ * @public
623
+ */
624
+ runToCompletion?(message: string, options?: import("./run.js").RunToCompletionOptions): Promise<import("./run.js").RunToCompletionResult>;
611
625
  /**
612
626
  * Direct API to third-party memory adapter(s) registered via
613
627
  * `plugins: [...]` (ADR D141 / D142). Returns `null` when no adapter
@@ -20,7 +20,11 @@
20
20
  * @public
21
21
  */
22
22
  export interface StoredMessage {
23
- /** Origin of the message. `tool_call` / `tool_result` reserved for forward compat. */
23
+ /**
24
+ * Origin of the message. `tool_call` / `tool_result` are produced by
25
+ * `buildReplayHistory` (M1-3) for stateless replay; a consumer feeding a
26
+ * `user`/`assistant`-only wire-mapper must map those two roles itself.
27
+ */
24
28
  role: "user" | "assistant" | "system" | "tool_call" | "tool_result";
25
29
  /** UTF-8 payload. May be empty string (e.g., a tool with no return value). */
26
30
  content: string;
@@ -19,7 +19,7 @@ export type RunStatus = "running" | "finished" | "error" | "cancelled";
19
19
  *
20
20
  * @public
21
21
  */
22
- export type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "fork" | "usePersonality" | "workflow";
22
+ export type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "runToCompletion" | "fork" | "usePersonality" | "workflow";
23
23
  /**
24
24
  * Git metadata attached to cloud runs.
25
25
  *
@@ -82,6 +82,59 @@ export interface RunResult {
82
82
  */
83
83
  stoppedAtIterationLimit?: boolean;
84
84
  }
85
+ /**
86
+ * Options for {@link SDKAgent.runToCompletion} (M1 Phase 3 — continuation driver).
87
+ *
88
+ * @public
89
+ */
90
+ export interface RunToCompletionOptions {
91
+ /**
92
+ * Maximum number of continuation rounds (re-sends) before giving up with
93
+ * `terminal: "step_limit"`. Default 5. A hard ceiling that prevents a
94
+ * runaway loop when the model keeps truncating.
95
+ */
96
+ maxRounds?: number;
97
+ /**
98
+ * The short prompt re-sent after a truncated round to make the (stateful)
99
+ * agent resume. Defaults to a generic "continue" instruction. The original
100
+ * conversation is preserved by the agent's session, so this need not repeat
101
+ * the task.
102
+ */
103
+ continuationPrompt?: string;
104
+ /** Called once per truncated round that triggers a re-send (for metrics/logging). */
105
+ onTruncated?: (event: {
106
+ round: number;
107
+ }) => void | Promise<void>;
108
+ /** Abort signal; checked between rounds — once aborted, no further round starts. */
109
+ signal?: AbortSignal;
110
+ /** Per-send options forwarded to each underlying `send()` (e.g. `maxIterations`). */
111
+ sendOptions?: SendOptions;
112
+ }
113
+ /**
114
+ * Result of {@link SDKAgent.runToCompletion}.
115
+ *
116
+ * @public
117
+ */
118
+ export interface RunToCompletionResult {
119
+ /**
120
+ * Why the driver stopped:
121
+ * - `"done"` — a round finished without truncating (the model is done).
122
+ * - `"step_limit"` — `maxRounds` exhausted (or aborted) while still truncating.
123
+ * - `"no_progress"` — two consecutive rounds produced empty output.
124
+ */
125
+ terminal: "done" | "step_limit" | "no_progress";
126
+ /**
127
+ * Index of the final round. Round 0 is the initial `send`; rounds ≥ 1 are
128
+ * continuation re-sends. So `terminal: "done"` with `rounds: 0` means the
129
+ * first send finished without truncating; `rounds: N` means N continuation
130
+ * re-sends happened. For `step_limit`, `rounds` equals `maxRounds`.
131
+ */
132
+ rounds: number;
133
+ /** The `RunResult` of the final round. */
134
+ lastResult: RunResult;
135
+ /** Token usage summed across all rounds; `undefined` when no round reported usage. */
136
+ usage?: TokenUsage;
137
+ }
85
138
  /**
86
139
  * Structured error attached to a {@link RunResult} when the underlying run
87
140
  * transitioned to `"error"` status. `message` is always present; `code` is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theokit/sdk",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "TypeScript SDK for the Theo agent harness — same surface, local or cloud.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/usetheo/theokit-sdk#readme",
@@ -294,8 +294,8 @@
294
294
  "typedoc": "^0.28.19",
295
295
  "ws": "^8.18.0",
296
296
  "zod": "^4.0.0",
297
- "@theokit/sdk-handoff": "0.1.0",
298
- "@theokit/sdk-memory": "0.1.0"
297
+ "@theokit/sdk-memory": "0.1.0",
298
+ "@theokit/sdk-handoff": "0.1.0"
299
299
  },
300
300
  "scripts": {
301
301
  "build": "tsup && cp src/internal/providers/provider-catalog.json dist/provider-catalog.json",