@letta-ai/letta-agent-sdk 0.6.0 → 0.6.2

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.
Files changed (38) hide show
  1. package/README.md +0 -1
  2. package/dist/agent-creation.d.ts +3 -7
  3. package/dist/agent-creation.d.ts.map +1 -1
  4. package/dist/app-server-session.d.ts +0 -5
  5. package/dist/app-server-session.d.ts.map +1 -1
  6. package/dist/client-base.d.ts +4 -1
  7. package/dist/client-base.d.ts.map +1 -1
  8. package/dist/client-entry.js +250 -317
  9. package/dist/client-entry.js.map +12 -12
  10. package/dist/cloud-management.d.ts.map +1 -1
  11. package/dist/cloud-session.d.ts.map +1 -1
  12. package/dist/index.d.ts +2 -4
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +252 -319
  15. package/dist/index.js.map +14 -14
  16. package/dist/management-types.d.ts +3 -0
  17. package/dist/management-types.d.ts.map +1 -1
  18. package/dist/remote-client-session-core.d.ts +22 -2
  19. package/dist/remote-client-session-core.d.ts.map +1 -1
  20. package/dist/remote-turn-coordinator.d.ts +10 -0
  21. package/dist/remote-turn-coordinator.d.ts.map +1 -1
  22. package/dist/tests/advanced-session.d.ts +1 -1
  23. package/dist/tests/advanced-session.d.ts.map +1 -1
  24. package/dist/types.d.ts +0 -21
  25. package/dist/types.d.ts.map +1 -1
  26. package/dist/validation.d.ts.map +1 -1
  27. package/package.json +2 -2
  28. package/src/agent-creation.ts +93 -55
  29. package/src/app-server-session.ts +4 -151
  30. package/src/client-base.ts +7 -4
  31. package/src/cloud-management.ts +18 -1
  32. package/src/cloud-session.ts +3 -1
  33. package/src/index.ts +9 -10
  34. package/src/management-types.ts +3 -0
  35. package/src/remote-client-session-core.ts +35 -5
  36. package/src/remote-turn-coordinator.ts +27 -0
  37. package/src/types.ts +0 -25
  38. package/src/validation.ts +0 -23
@@ -11,12 +11,7 @@ import type {
11
11
  RuntimeStartResponseMessage,
12
12
  UpdateModelResponseMessage,
13
13
  } from "@letta-ai/letta-code/app-server-protocol";
14
- import {
15
- buildSystemPrompt,
16
- GIT_MEMORY_ENABLED_TAG,
17
- LETTA_CODE_ORIGIN_TAG,
18
- } from "@letta-ai/letta-code/agent-presets";
19
- import { buildInitialAgentBody } from "./agent-creation.js";
14
+ import { createAgentBody } from "./agent-creation.js";
20
15
  import { normalizeAppServerModels } from "./app-server-models.js";
21
16
  import {
22
17
  buildCanUseToolContext,
@@ -99,152 +94,10 @@ export type AppServerSessionOptions = Partial<LettaCodeRemoteClientOptions> & {
99
94
  connect?: (
100
95
  sessionEnv?: Record<string, string>,
101
96
  ) => Promise<{ url: string; close(): void }>;
102
- /** Whether SDK create-agent payloads should add the origin tag automatically. */
103
- includeSdkOriginTag?: boolean;
104
97
  };
105
98
 
106
99
  export type AppServerSessionMode = RuntimeSessionMode;
107
100
 
108
- function isPresetSystemPrompt(value: string): boolean {
109
- return [
110
- "default",
111
- "letta-claude",
112
- "letta-codex",
113
- "letta-gemini",
114
- "claude",
115
- "codex",
116
- "gemini",
117
- ].includes(value);
118
- }
119
-
120
- function assertRemoteCreateAgentOptionsSupported(options: CreateAgentOptions): void {
121
- if (options.allowedTools !== undefined || options.disallowedTools !== undefined) {
122
- throw new Error("App-server createAgent() does not yet support allowedTools/disallowedTools.");
123
- }
124
- if (options.canUseTool !== undefined) {
125
- throw new Error("App-server createAgent() does not yet support canUseTool callbacks.");
126
- }
127
- if (options.systemInfoReminder !== undefined) {
128
- throw new Error("App-server createAgent() does not yet support systemInfoReminder overrides.");
129
- }
130
- if (options.dreaming?.behavior !== undefined) {
131
- throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
132
- }
133
- }
134
-
135
- function normalizeMemoryBlock(block: Record<string, unknown>): Record<string, unknown> {
136
- const normalized = { ...block };
137
- if (normalized.value === undefined && typeof normalized.content === "string") {
138
- normalized.value = normalized.content;
139
- }
140
- return normalized;
141
- }
142
-
143
- function upsertMemoryBlock(
144
- blocks: Array<Record<string, unknown>>,
145
- block: Record<string, unknown>,
146
- ): void {
147
- const label = block.label;
148
- if (typeof label === "string") {
149
- const existingIndex = blocks.findIndex((candidate) => candidate.label === label);
150
- if (existingIndex >= 0) {
151
- blocks[existingIndex] = block;
152
- return;
153
- }
154
- }
155
- blocks.push(block);
156
- }
157
-
158
- export async function createAgentBody(
159
- options: CreateAgentOptions,
160
- settings: { includeSdkOriginTag?: boolean } = {},
161
- ): Promise<Record<string, unknown>> {
162
- assertRemoteCreateAgentOptionsSupported(options);
163
-
164
- const includeOriginTag = settings.includeSdkOriginTag ?? true;
165
- const body = await buildInitialAgentBody(options);
166
-
167
- if (Array.isArray(body.tags)) {
168
- body.tags = body.tags.filter(
169
- (tag) =>
170
- (includeOriginTag || tag !== LETTA_CODE_ORIGIN_TAG) &&
171
- (options.memfs !== false || tag !== GIT_MEMORY_ENABLED_TAG),
172
- );
173
- }
174
-
175
- if (options.embedding !== undefined) body.embedding = options.embedding;
176
- if (options.hidden !== undefined) body.hidden = options.hidden;
177
- // When baseTools is omitted, the harness applies its created-agent
178
- // defaults (web_search, fetch_webpage). An explicit list is pinned exactly:
179
- // `tools` alone does not suppress the Letta agent type's defaults, so both
180
- // default tool attachment and its default tool rules are disabled here.
181
- if (options.baseTools === undefined) {
182
- delete body.tools;
183
- delete body.include_base_tools;
184
- delete body.include_base_tool_rules;
185
- } else {
186
- body.tools = options.baseTools;
187
- body.include_base_tools = false;
188
- body.include_base_tool_rules = false;
189
- }
190
-
191
- if (options.systemPrompt === undefined) {
192
- if (options.memfs === false) {
193
- body.system = buildSystemPrompt("default", "standard");
194
- }
195
- } else {
196
- if (typeof options.systemPrompt === "string") {
197
- if (isPresetSystemPrompt(options.systemPrompt)) {
198
- throw new Error("createAgent() does not yet support system prompt presets for this backend.");
199
- }
200
- body.system = options.systemPrompt;
201
- } else {
202
- throw new Error("createAgent() does not yet support system prompt preset objects for this backend.");
203
- }
204
- }
205
-
206
- const hasMemoryConfiguration =
207
- Array.isArray(body.memory_blocks) ||
208
- options.memory !== undefined ||
209
- options.persona !== undefined ||
210
- options.human !== undefined;
211
- const memoryBlocks = Array.isArray(body.memory_blocks)
212
- ? body.memory_blocks
213
- .filter(
214
- (block): block is Record<string, unknown> =>
215
- block !== null && typeof block === "object",
216
- )
217
- .map((block) => ({ ...block }))
218
- : [];
219
- const blockIds: string[] = [];
220
- for (const item of options.memory ?? []) {
221
- if (typeof item === "string") {
222
- throw new Error("App-server createAgent() does not yet support memory preset names.");
223
- }
224
- if ("blockId" in item) {
225
- blockIds.push(item.blockId);
226
- } else {
227
- upsertMemoryBlock(
228
- memoryBlocks,
229
- normalizeMemoryBlock(item as unknown as Record<string, unknown>),
230
- );
231
- }
232
- }
233
- if (options.persona !== undefined) {
234
- upsertMemoryBlock(memoryBlocks, {
235
- label: "persona",
236
- value: options.persona,
237
- });
238
- }
239
- if (options.human !== undefined) {
240
- upsertMemoryBlock(memoryBlocks, { label: "human", value: options.human });
241
- }
242
- if (hasMemoryConfiguration) body.memory_blocks = memoryBlocks;
243
- if (blockIds.length > 0) body.block_ids = blockIds;
244
-
245
- return body;
246
- }
247
-
248
101
  export function externalToolGroups(tools: AnyAgentTool[] | undefined): Array<Record<string, unknown>> | undefined {
249
102
  if (!tools || tools.length === 0) return undefined;
250
103
  return [
@@ -779,6 +632,8 @@ export class AppServerSession extends RemoteClientSessionCore {
779
632
  throw new Error(response.error ?? "Failed to start app-server runtime");
780
633
  }
781
634
 
635
+ this.watchTransportDisconnect(client);
636
+
782
637
  const tools = agentToolNames(response.agent);
783
638
  const skillSources = options.skillSources;
784
639
  const clientToolset = "toolset" in options ? options.toolset : undefined;
@@ -883,9 +738,7 @@ export class AppServerSession extends RemoteClientSessionCore {
883
738
 
884
739
  if (this.mode.kind === "create-agent") {
885
740
  command.create_agent = {
886
- body: await createAgentBody(this.mode.options, {
887
- includeSdkOriginTag: this.remoteOptions.includeSdkOriginTag,
888
- }),
741
+ body: await createAgentBody(this.mode.options),
889
742
  // Hidden (worker-style) agents default to unpinned.
890
743
  pin_global:
891
744
  this.remoteOptions.pinGlobalAgent ??
@@ -86,8 +86,8 @@ function looksLikeConversationId(id: string): boolean {
86
86
  return id.startsWith("conv-") || id.startsWith("local-conv-");
87
87
  }
88
88
 
89
- type TurnSession = LettaCodeSession & {
90
- runTurn(message: SendMessage): Promise<SDKResultMessage>;
89
+ type OneShotSession = LettaCodeSession & {
90
+ sendAndWaitForResult(message: SendMessage): Promise<SDKResultMessage>;
91
91
  };
92
92
 
93
93
  /**
@@ -314,7 +314,10 @@ export class LettaAgentClientBase {
314
314
  return this.resumeLocalSession(id, options);
315
315
  }
316
316
 
317
- /** One-shot prompt convenience helper using a new conversation. */
317
+ /**
318
+ * One-shot convenience for scripts, smoke tests, and evals.
319
+ * Applications should use a session when they need interactive turn state.
320
+ */
318
321
  async prompt(
319
322
  message: SendMessage,
320
323
  agentId: string,
@@ -323,7 +326,7 @@ export class LettaAgentClientBase {
323
326
  const session = this.createSession(agentId, options);
324
327
 
325
328
  try {
326
- return await (session as TurnSession).runTurn(message);
329
+ return await (session as OneShotSession).sendAndWaitForResult(message);
327
330
  } finally {
328
331
  session.close();
329
332
  }
@@ -74,6 +74,23 @@ function isNotFound(error: unknown): boolean {
74
74
  return error instanceof APIError && error.status === 404;
75
75
  }
76
76
 
77
+ /**
78
+ * The SDK cursor contract is chronological: `before` always means older and
79
+ * `after` always means newer. The Cloud REST API interprets cursors relative
80
+ * to sort order instead, and its default order is newest-first, so descending
81
+ * requests need their cursor keys swapped at this boundary. The app-server
82
+ * transport already receives chronological cursors and must not swap.
83
+ */
84
+ function toOrderRelativeCursors(query: MessageListParams): MessageListParams {
85
+ if ((query.order ?? "desc") !== "desc") return query;
86
+ const { before, after, ...rest } = query;
87
+ return {
88
+ ...rest,
89
+ ...(after != null ? { before: after } : {}),
90
+ ...(before != null ? { after: before } : {}),
91
+ };
92
+ }
93
+
77
94
  /** Cloud management backed by the canonical generated Letta TypeScript client. */
78
95
  export class CloudManagementTransport implements ManagementTransport {
79
96
  constructor(private readonly client: Letta) {}
@@ -206,7 +223,7 @@ export class CloudManagementTransport implements ManagementTransport {
206
223
  ): Promise<ConversationMessagesResult> {
207
224
  const page = await this.client.conversations.messages.list(
208
225
  conversationId,
209
- query,
226
+ toOrderRelativeCursors(query),
210
227
  );
211
228
  return { messages: page.items };
212
229
  }
@@ -5,10 +5,10 @@ import {
5
5
  createAppServerClient,
6
6
  type AppServerClient,
7
7
  } from "@letta-ai/letta-code/app-server-client";
8
+ import { createAgentBody } from "./agent-creation.js";
8
9
  import {
9
10
  AppServerRuntimeController,
10
11
  agentToolNames,
11
- createAgentBody,
12
12
  createExternalToolCallHandler,
13
13
  externalToolGroups,
14
14
  registerAppServerControlRequestHandler,
@@ -398,6 +398,8 @@ export class CloudEnvironmentSession extends RemoteClientSessionCore {
398
398
  throw new Error(response.error ?? "Failed to start Cloud status runtime");
399
399
  }
400
400
 
401
+ this.watchTransportDisconnect(client);
402
+
401
403
  const tools = agentToolNames(response.agent);
402
404
  const skillSources = options.skillSources;
403
405
  const clientToolset = "toolset" in options ? options.toolset : undefined;
package/src/index.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @example
7
7
  * ```typescript
8
- * import { LettaAgentClient, createAgent, createSession, resumeSession, prompt } from '@letta-ai/letta-agent-sdk';
8
+ * import { LettaAgentClient, createAgent, createSession, resumeSession } from '@letta-ai/letta-agent-sdk';
9
9
  *
10
10
  * const client = new LettaAgentClient({ backend: 'local' });
11
11
  * const agentId = await client.createAgent();
@@ -23,8 +23,6 @@
23
23
  * // Create new conversation on specific agent
24
24
  * const session = createSession(agentId);
25
25
  *
26
- * // One-shot prompt in a new conversation
27
- * const result = await prompt('Hello', agentId);
28
26
  * ```
29
27
  */
30
28
 
@@ -83,7 +81,6 @@ export type {
83
81
  SDKProtocolMessage,
84
82
  SDKProtocolCommand,
85
83
  SendCommandOptions,
86
- RunTurnOptions,
87
84
  RecoverPendingApprovalsOptions,
88
85
  RecoverPendingApprovalsResult,
89
86
  ChangeDeviceStateOptions,
@@ -265,18 +262,20 @@ export function resumeSession(
265
262
  }
266
263
 
267
264
  /**
268
- * One-shot prompt convenience function.
265
+ * One-shot convenience for scripts, smoke tests, and evals.
269
266
  *
270
- * Uses the specified agent in a new conversation.
271
- * - Uses a short-lived session and returns the final turn result.
267
+ * Creates a short-lived conversation, waits for the final result, and closes
268
+ * the session. Applications that need streaming, approvals, cancellation,
269
+ * queueing, or continued interaction should use createSession() with send()
270
+ * and stream() instead.
272
271
  *
273
272
  * @example
274
273
  * ```typescript
275
274
  * const result = await prompt('What is the capital of France?', agentId); // specific agent
276
275
  * ```
277
276
  */
278
- type TurnSession = LettaCodeSession & {
279
- runTurn(message: SendMessage): Promise<SDKResultMessage>;
277
+ type OneShotSession = LettaCodeSession & {
278
+ sendAndWaitForResult(message: SendMessage): Promise<SDKResultMessage>;
280
279
  };
281
280
 
282
281
  type InitializableSession = LettaCodeSession & {
@@ -291,7 +290,7 @@ export async function prompt(
291
290
  const session = createSession(agentId, options);
292
291
 
293
292
  try {
294
- return await (session as TurnSession).runTurn(message);
293
+ return await (session as OneShotSession).sendAndWaitForResult(message);
295
294
  } finally {
296
295
  session.close();
297
296
  }
@@ -81,8 +81,11 @@ export interface UpdateConversationOptions {
81
81
  }
82
82
 
83
83
  export interface ConversationMessagesOptions {
84
+ /** Return messages before this message ID (cursor for older pages, regardless of `order`). */
84
85
  before?: Present<MessageListParams["before"]>;
86
+ /** Return messages after this message ID (cursor for newer pages, regardless of `order`). */
85
87
  after?: Present<MessageListParams["after"]>;
88
+ /** Sort order of the returned page. Defaults to "desc" (newest first). */
86
89
  order?: "asc" | "desc";
87
90
  limit?: Present<MessageListParams["limit"]>;
88
91
  }
@@ -13,7 +13,6 @@ import type {
13
13
  RecoverPendingApprovalsOptions,
14
14
  RecoverPendingApprovalsResult,
15
15
  RemoveQueuedMessageResult,
16
- RunTurnOptions,
17
16
  SDKInitMessage,
18
17
  SDKMessage,
19
18
  SDKProtocolCommand,
@@ -78,6 +77,7 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
78
77
  private readonly requestTimeoutMs: number | undefined;
79
78
  private initializePromise: Promise<SDKInitMessage> | null = null;
80
79
  private removeMessageHandler: (() => void) | null = null;
80
+ private detachTransportDisconnect: (() => void) | null = null;
81
81
  private readonly turns: RemoteTurnCoordinator;
82
82
  private toolNames: string[] | undefined;
83
83
  private deviceStatusListeners = new Set<(status: SessionDeviceStatus) => void>();
@@ -189,6 +189,8 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
189
189
  private cleanupFailedInitialize(): void {
190
190
  this.removeMessageHandler?.();
191
191
  this.removeMessageHandler = null;
192
+ this.detachTransportDisconnect?.();
193
+ this.detachTransportDisconnect = null;
192
194
  this.controller?.close();
193
195
  this.controller = null;
194
196
  // Subclass-owned resources (spawned connections, sandboxes, handlers)
@@ -225,10 +227,7 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
225
227
  }
226
228
  }
227
229
 
228
- async runTurn(
229
- message: SendMessage,
230
- _options: RunTurnOptions = {},
231
- ): Promise<SDKResultMessage> {
230
+ async sendAndWaitForResult(message: SendMessage): Promise<SDKResultMessage> {
232
231
  if (this.turns.hasInFlightTurn()) {
233
232
  throw new Error(
234
233
  `A turn is already in flight for this ${this.label} session. Use send() and stream() to let the listener queue messages.`,
@@ -547,6 +546,8 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
547
546
  this.closed = true;
548
547
  this.removeMessageHandler?.();
549
548
  this.removeMessageHandler = null;
549
+ this.detachTransportDisconnect?.();
550
+ this.detachTransportDisconnect = null;
550
551
  this.turns.close();
551
552
  for (const cancel of [...this.deviceStatusRefreshCancels]) {
552
553
  cancel(new Error(`Session closed while waiting for ${this.label} device status`));
@@ -623,6 +624,35 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
623
624
 
624
625
  protected abstract initializeRuntimeController(): Promise<RuntimeSessionInit>;
625
626
 
627
+ /**
628
+ * Fail the session when its transport drops unexpectedly.
629
+ *
630
+ * Without this an in-flight turn parks forever: nextMessage() only settles
631
+ * through the coordinator, and the socket's own pending-request rejection
632
+ * covers request/response commands, not streaming turns.
633
+ *
634
+ * The session is not revived — the runtime lived on the dead socket. The
635
+ * caller observes the error and rebuilds via resumeSession().
636
+ *
637
+ * Subclasses call this only once their runtime is live: a drop before that
638
+ * already surfaces as a rejected connect or runtime-start, and failing the
639
+ * session there would defeat initialize()'s retry path. Explicit closes do
640
+ * not notify, so this fires for faults only. Detaching stays here so every
641
+ * teardown path — clean close and failed initialize alike — covers it.
642
+ */
643
+ protected watchTransportDisconnect(client: {
644
+ onDisconnect(handler: () => void): () => void;
645
+ }): void {
646
+ this.detachTransportDisconnect?.();
647
+ this.detachTransportDisconnect = client.onDisconnect(() => {
648
+ if (this.closed) return;
649
+ this.turns.closeWithError(
650
+ `The ${this.label} connection closed unexpectedly; resume the conversation to continue.`,
651
+ );
652
+ this.close();
653
+ });
654
+ }
655
+
626
656
  protected async afterRuntimeInitialized(): Promise<void> {
627
657
  // Optional hook for subclasses to send transport-specific startup frames.
628
658
  }
@@ -160,6 +160,33 @@ export class RemoteTurnCoordinator {
160
160
  });
161
161
  }
162
162
 
163
+ /**
164
+ * Close after the transport dropped, surfacing the failure to stream
165
+ * consumers first.
166
+ *
167
+ * A plain close() resolves waiting consumers with `null`, which is
168
+ * indistinguishable from a conversation ending normally. A dead socket
169
+ * cannot deliver a turn-scoped failure of its own, so the error is
170
+ * synthesized here before the queue drains.
171
+ */
172
+ closeWithError(detail: string): void {
173
+ if (this.closed) return;
174
+ const active = this.activeTurn;
175
+ if (active) {
176
+ this.failTurn(active, detail);
177
+ } else {
178
+ this.enqueue({
179
+ type: "error",
180
+ message: detail,
181
+ errorCode: "error",
182
+ stopReason: "error",
183
+ errorDetail: detail,
184
+ recoverable: false,
185
+ });
186
+ }
187
+ this.close();
188
+ }
189
+
163
190
  close(): void {
164
191
  if (this.closed) return;
165
192
  this.closed = true;
package/src/types.ts CHANGED
@@ -68,20 +68,6 @@ export interface TextContent {
68
68
  text: string;
69
69
  }
70
70
 
71
- export interface RunTurnOptions {
72
- /**
73
- * Max automatic approval-conflict recovery attempts for this turn.
74
- * Overrides session-level maxApprovalRecoveryAttempts when provided.
75
- */
76
- maxApprovalRecoveryAttempts?: number;
77
-
78
- /**
79
- * Timeout in milliseconds for each approval recovery request.
80
- * Overrides session-level approvalRecoveryTimeoutMs when provided.
81
- */
82
- recoveryTimeoutMs?: number;
83
- }
84
-
85
71
  export interface RecoverPendingApprovalsOptions {
86
72
  /**
87
73
  * Timeout in milliseconds for the recovery control request.
@@ -711,17 +697,6 @@ export interface CreateSessionOptions {
711
697
  */
712
698
  mcpServers?: McpServers;
713
699
 
714
- /**
715
- * Max automatic approval-conflict recovery attempts per runTurn() call.
716
- * Set to 0 to disable automatic recovery.
717
- */
718
- maxApprovalRecoveryAttempts?: number;
719
-
720
- /**
721
- * Timeout in milliseconds for a single approval recovery request.
722
- */
723
- approvalRecoveryTimeoutMs?: number;
724
-
725
700
  /**
726
701
  * Cloud repository resources to attach for the lifetime of the SDK session.
727
702
  * For relationships that should outlive the session, use
package/src/validation.ts CHANGED
@@ -54,28 +54,6 @@ function getBlockLabels(memory: MemoryItem[]): string[] {
54
54
  .filter((label): label is string => label !== null);
55
55
  }
56
56
 
57
- function validateApprovalRecoveryOptions(options: CreateSessionOptions): void {
58
- if (
59
- options.maxApprovalRecoveryAttempts !== undefined &&
60
- (!Number.isInteger(options.maxApprovalRecoveryAttempts) ||
61
- options.maxApprovalRecoveryAttempts < 0)
62
- ) {
63
- throw new Error(
64
- "Invalid maxApprovalRecoveryAttempts. Expected a non-negative integer."
65
- );
66
- }
67
-
68
- if (
69
- options.approvalRecoveryTimeoutMs !== undefined &&
70
- (!Number.isInteger(options.approvalRecoveryTimeoutMs) ||
71
- options.approvalRecoveryTimeoutMs <= 0)
72
- ) {
73
- throw new Error(
74
- "Invalid approvalRecoveryTimeoutMs. Expected a positive integer."
75
- );
76
- }
77
- }
78
-
79
57
  function validateRemovedSessionOptions(options: CreateSessionOptions): void {
80
58
  const removedOptions = options as CreateSessionOptions & Record<string, unknown>;
81
59
  if (removedOptions.systemPrompt !== undefined) {
@@ -250,7 +228,6 @@ export function validateCreateSessionOptions(options: CreateSessionOptions): voi
250
228
  validateMcpServers(options.mcpServers);
251
229
  validateReasoningEffort(options.reasoningEffort);
252
230
  validateDreamingOptions(options.dreaming);
253
- validateApprovalRecoveryOptions(options);
254
231
  validateRemovedSessionOptions(options);
255
232
  }
256
233