@workerdeck/core 2.1.0 → 2.2.1

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/build/index.d.mts CHANGED
@@ -14,6 +14,16 @@ declare const SUPPORTED_ATTACHMENT_TYPES: string;
14
14
  declare function attachmentContentBlocks(attachments: readonly AttachmentInput[]): Array<Record<string, unknown>>;
15
15
  declare function attachmentRef(attachment: AttachmentInput): MessageAttachment;
16
16
  //#endregion
17
+ //#region src/lib/local-command.d.ts
18
+ type LocalCommandResult = {
19
+ command: string;
20
+ stdout: string;
21
+ stderr: string;
22
+ exitCode: number;
23
+ };
24
+ declare function localCommandTranscript(result: LocalCommandResult): string;
25
+ declare function localCommandContext(pending: readonly string[]): string | undefined;
26
+ //#endregion
17
27
  //#region src/executors/tool-executor.d.ts
18
28
  type ToolExecutionResult = {
19
29
  status: 'ok';
@@ -93,6 +103,7 @@ interface Runner {
93
103
  }): () => void;
94
104
  eventAt?(seq: number): SessionEvent | undefined;
95
105
  sendMessage(text: string, attachments?: readonly AttachmentInput[]): void;
106
+ queueLocalCommand?(result: LocalCommandResult): void;
96
107
  mcpServers?(): Promise<McpServerStatusInfo[] | undefined>;
97
108
  reconnectMcpServer?(name: string): Promise<void>;
98
109
  setMcpServerEnabled?(name: string, enabled: boolean): Promise<void>;
@@ -132,7 +143,7 @@ type SessionRunnerConfig = CreateSessionRequest & {
132
143
  env?: Record<string, string | undefined>;
133
144
  pathToClaudeCodeExecutable?: string;
134
145
  extraOptions?: Partial<Options>;
135
- defaultApprovalTimeoutMs?: number;
146
+ defaultApprovalTimeoutMs?: number | null;
136
147
  backfillHistory?: boolean;
137
148
  historyFn?: HistoryFn;
138
149
  sessionInfoFn?: SessionInfoFn;
@@ -151,6 +162,7 @@ declare class SessionRunner implements Runner {
151
162
  setTitle(title: string | undefined): void;
152
163
  start(): Promise<void>;
153
164
  sendMessage(text: string, attachments?: readonly AttachmentInput[]): void;
165
+ queueLocalCommand(result: LocalCommandResult): void;
154
166
  mcpServers(): Promise<McpServerStatusInfo[] | undefined>;
155
167
  reconnectMcpServer(name: string): Promise<void>;
156
168
  setMcpServerEnabled(name: string, enabled: boolean): Promise<void>;
@@ -195,7 +207,7 @@ type AiSdkRunnerConfig = Omit<CreateSessionRequest, 'cwd'> & {
195
207
  toolName: string;
196
208
  input: unknown;
197
209
  }) => boolean;
198
- approvalTimeoutMs?: number;
210
+ defaultApprovalTimeoutMs?: number | null;
199
211
  resolveModel?: (modelId: string | undefined) => LanguageModel$1;
200
212
  reportMcpServers?: () => Promise<McpServerStatusInfo[] | undefined>;
201
213
  onClose?: () => void | Promise<void>;
@@ -230,6 +242,7 @@ type AiSdkSessionState = {
230
242
  model?: string;
231
243
  lastActivityAt?: number;
232
244
  parkedAt?: number;
245
+ pendingLocalCommands?: string[];
233
246
  };
234
247
  type ToolCallOutput = {
235
248
  type: 'text';
@@ -254,6 +267,7 @@ declare class AiSdkRunner implements Runner {
254
267
  park(): RunnerSnapshot | undefined;
255
268
  snapshot(): RunnerSnapshot | undefined;
256
269
  sendMessage(text: string, attachments?: readonly AttachmentInput[]): void;
270
+ queueLocalCommand(result: LocalCommandResult): void;
257
271
  resolveToolCall(toolCallId: string, output: ToolCallOutput, options?: {
258
272
  isError?: boolean;
259
273
  }): boolean;
@@ -495,7 +509,7 @@ type EngineSessionOptions = {
495
509
  toolName: string;
496
510
  input: unknown;
497
511
  }) => boolean;
498
- approvalTimeoutMs?: number;
512
+ approvalTimeoutMs?: number | null;
499
513
  seedVfs?: Record<string, string>;
500
514
  id?: string;
501
515
  };
@@ -742,7 +756,7 @@ type CodexRunnerConfig = CreateSessionRequest & {
742
756
  connectFn: AppServerConnectFn;
743
757
  env?: Record<string, string | undefined>;
744
758
  codexHome?: string;
745
- defaultApprovalTimeoutMs?: number;
759
+ defaultApprovalTimeoutMs?: number | null;
746
760
  backfillHistory?: boolean;
747
761
  };
748
762
  declare class CodexRunner implements Runner {
@@ -758,6 +772,7 @@ declare class CodexRunner implements Runner {
758
772
  setTitle(title: string | undefined): void;
759
773
  start(): Promise<void>;
760
774
  sendMessage(text: string, attachments?: readonly AttachmentInput[]): void;
775
+ queueLocalCommand(result: LocalCommandResult): void;
761
776
  resolvePermission(requestId: string, decision: PermissionDecision): boolean;
762
777
  interrupt(): Promise<void>;
763
778
  clearContext(): Promise<void>;
@@ -797,5 +812,5 @@ declare class JsonRpcStdioConnection {
797
812
  //#region src/engines/provider/adapter.d.ts
798
813
  declare const providerAdapter: EngineAdapter;
799
814
  //#endregion
800
- export { AiSdkRunner, type AiSdkRunnerConfig, type AiSdkSessionState, type AppServerConnectFn, type AppServerConnectOptions, type AppServerConnection, type AppServerHistoryTurn, type AppServerItem, type AppServerThreadListResponse, type AppServerThreadSummary, type AppServerTokenUsage, type AppServerTurn, type AppServerUserInput, type AttachmentInput, type AttachmentKind, type BridgeAnswer, BrowserBridgeExecutor, type BrowserBridgeExecutorOptions, CLAUDE_CATALOG, CODEX_CATALOG, type ClaudeAuthProbe, type ClaudeAuthStatus, CodexRunner, type CodexRunnerConfig, type DeferredDispatch, DeferredExecutor, type DeferredExecutorOptions, type EngineAdapter, type EngineAvailability, type EngineRunnerRequest, type EngineSessionOptions, type HistoryFn, type HostFetch, type HostToolDefinition, InputQueue, JsonRpcError, JsonRpcStdioConnection, type LanguageModel, type McpConnection, type ModelCatalog, type ParkedExecution, type PendingEntry, type PendingKind, type PendingOutcome, PendingRequestRegistry, type PendingToolCall, type PermissionDecision, type QueryFn, QuickJsExecutor, type QuickJsExecutorOptions, type RegisterOptions, type Runner, type RunnerSnapshot, SUPPORTED_ATTACHMENT_TYPES, type SessionEventListener, SessionRunner, type SessionRunnerConfig, type SettledBy, type Tool, type ToolCallOutput, type ToolContext, type ToolContextOptions, type ToolDefinition, type ToolExecutionCall, type ToolExecutionDispatch, type ToolExecutionResult, type ToolExecutor, type ToolSet, type ToolTrust, type WebFetchDigest, type WebFetchFn, type WebFetchOptions, type WebFetchResult, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, truncateResultBlocks, withHostTools, withMcpTools };
815
+ export { AiSdkRunner, type AiSdkRunnerConfig, type AiSdkSessionState, type AppServerConnectFn, type AppServerConnectOptions, type AppServerConnection, type AppServerHistoryTurn, type AppServerItem, type AppServerThreadListResponse, type AppServerThreadSummary, type AppServerTokenUsage, type AppServerTurn, type AppServerUserInput, type AttachmentInput, type AttachmentKind, type BridgeAnswer, BrowserBridgeExecutor, type BrowserBridgeExecutorOptions, CLAUDE_CATALOG, CODEX_CATALOG, type ClaudeAuthProbe, type ClaudeAuthStatus, CodexRunner, type CodexRunnerConfig, type DeferredDispatch, DeferredExecutor, type DeferredExecutorOptions, type EngineAdapter, type EngineAvailability, type EngineRunnerRequest, type EngineSessionOptions, type HistoryFn, type HostFetch, type HostToolDefinition, InputQueue, JsonRpcError, JsonRpcStdioConnection, type LanguageModel, type LocalCommandResult, type McpConnection, type ModelCatalog, type ParkedExecution, type PendingEntry, type PendingKind, type PendingOutcome, PendingRequestRegistry, type PendingToolCall, type PermissionDecision, type QueryFn, QuickJsExecutor, type QuickJsExecutorOptions, type RegisterOptions, type Runner, type RunnerSnapshot, SUPPORTED_ATTACHMENT_TYPES, type SessionEventListener, SessionRunner, type SessionRunnerConfig, type SettledBy, type Tool, type ToolCallOutput, type ToolContext, type ToolContextOptions, type ToolDefinition, type ToolExecutionCall, type ToolExecutionDispatch, type ToolExecutionResult, type ToolExecutor, type ToolSet, type ToolTrust, type WebFetchDigest, type WebFetchFn, type WebFetchOptions, type WebFetchResult, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, localCommandContext, localCommandTranscript, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, truncateResultBlocks, withHostTools, withMcpTools };
801
816
  //# sourceMappingURL=index.d.mts.map
package/build/index.mjs CHANGED
@@ -189,6 +189,26 @@ var InputQueue = class {
189
189
  }
190
190
  };
191
191
  //#endregion
192
+ //#region src/lib/local-command.ts
193
+ const LOCAL_COMMAND_CAVEAT = "<local-command-caveat>Caveat: the messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to.</local-command-caveat>";
194
+ function localCommandTranscript(result) {
195
+ const tag = result.exitCode === 0 ? "local-command-stdout" : "local-command-stderr";
196
+ const lines = [`$ ${result.command}`];
197
+ const stdout = result.stdout.trimEnd();
198
+ const stderr = result.stderr.trimEnd();
199
+ if (stdout) lines.push(stdout);
200
+ if (stderr) lines.push(stderr);
201
+ if (result.exitCode !== 0) lines.push(`[exit ${result.exitCode}]`);
202
+ return `<${tag}>${lines.join("\n")}</${tag}>`;
203
+ }
204
+ function localCommandContext(pending) {
205
+ if (pending.length === 0) return;
206
+ return [LOCAL_COMMAND_CAVEAT, ...pending].join("\n");
207
+ }
208
+ function isSlashCommand(text) {
209
+ return /^\s*\/[A-Za-z]/.test(text);
210
+ }
211
+ //#endregion
192
212
  //#region src/lib/patch.ts
193
213
  const MAX_PATCH_LINES = 400;
194
214
  const HUNK_HEADER = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
@@ -454,6 +474,12 @@ function normalizeSdkMessage(msg) {
454
474
  }
455
475
  }
456
476
  //#endregion
477
+ //#region src/lib/approval-timeout.ts
478
+ function resolveApprovalTimeoutMs(session, fallback) {
479
+ const value = session === void 0 ? fallback : session;
480
+ return value === void 0 || value === null || value <= 0 ? void 0 : value;
481
+ }
482
+ //#endregion
457
483
  //#region src/lib/event-log.ts
458
484
  var EventLog = class {
459
485
  #events = [];
@@ -878,7 +904,6 @@ function toolUseBlocks(content) {
878
904
  }
879
905
  //#endregion
880
906
  //#region src/engines/claude/runner.ts
881
- const DEFAULT_APPROVAL_TIMEOUT_MS$1 = 3e5;
882
907
  var SessionRunner = class {
883
908
  id;
884
909
  createdAt;
@@ -898,6 +923,7 @@ var SessionRunner = class {
898
923
  #totalCostUsd;
899
924
  #numTurns;
900
925
  #input = new InputQueue();
926
+ #pendingLocalCommands = [];
901
927
  #query;
902
928
  #capabilitiesEmitted = false;
903
929
  #subscriptionType;
@@ -970,6 +996,11 @@ var SessionRunner = class {
970
996
  sendMessage(text, attachments) {
971
997
  if (this.#closed) throw new Error("session is closed");
972
998
  const blocks = attachments?.length ? attachmentContentBlocks(attachments) : [];
999
+ const context = isSlashCommand(text) ? void 0 : this.#takeLocalCommands();
1000
+ if (context) blocks.unshift({
1001
+ type: "text",
1002
+ text: context
1003
+ });
973
1004
  const content = blocks.length ? [...blocks, ...text ? [{
974
1005
  type: "text",
975
1006
  text
@@ -994,6 +1025,26 @@ var SessionRunner = class {
994
1025
  uuid: randomUUID()
995
1026
  });
996
1027
  }
1028
+ queueLocalCommand(result) {
1029
+ if (this.#closed) throw new Error("session is closed");
1030
+ const text = localCommandTranscript(result);
1031
+ this.#pendingLocalCommands.push(text);
1032
+ this.#emit({
1033
+ type: "user_message",
1034
+ message: {
1035
+ role: "user",
1036
+ content: text
1037
+ },
1038
+ parentToolUseId: null,
1039
+ synthetic: true,
1040
+ uuid: randomUUID()
1041
+ });
1042
+ }
1043
+ #takeLocalCommands() {
1044
+ const context = localCommandContext(this.#pendingLocalCommands);
1045
+ this.#pendingLocalCommands = [];
1046
+ return context;
1047
+ }
997
1048
  async mcpServers() {
998
1049
  const query = this.#query;
999
1050
  if (typeof query?.mcpServerStatus !== "function") return;
@@ -1020,6 +1071,7 @@ var SessionRunner = class {
1020
1071
  }
1021
1072
  async clearContext() {
1022
1073
  if (this.#status === "closed" || this.#status === "failed") throw new Error("session is closed");
1074
+ this.#pendingLocalCommands = [];
1023
1075
  this.sendMessage("/clear");
1024
1076
  }
1025
1077
  async setPermissionMode(mode) {
@@ -1050,6 +1102,7 @@ var SessionRunner = class {
1050
1102
  close(reason = "client") {
1051
1103
  if (this.#closed) return;
1052
1104
  this.#closed = true;
1105
+ this.#pendingLocalCommands = [];
1053
1106
  for (const [id, pending] of this.#pending) this.#settleApproval(id, pending, {
1054
1107
  behavior: "deny",
1055
1108
  message: "Session closed"
@@ -1201,6 +1254,7 @@ var SessionRunner = class {
1201
1254
  if (body) {
1202
1255
  this.#emit(body);
1203
1256
  if (body.type === "conversation_reset") {
1257
+ this.#pendingLocalCommands = [];
1204
1258
  if (body.sdkSessionId) this.#sdkSessionId = body.sdkSessionId;
1205
1259
  this.#fetchContextUsage();
1206
1260
  }
@@ -1301,7 +1355,7 @@ var SessionRunner = class {
1301
1355
  }
1302
1356
  #canUseTool = (toolName, input, options) => {
1303
1357
  const id = randomUUID();
1304
- const timeoutMs = this.#config.approvalTimeoutMs ?? this.#config.defaultApprovalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS$1;
1358
+ const timeoutMs = resolveApprovalTimeoutMs(this.#config.approvalTimeoutMs, this.#config.defaultApprovalTimeoutMs);
1305
1359
  const request = {
1306
1360
  id,
1307
1361
  toolName,
@@ -1312,7 +1366,7 @@ var SessionRunner = class {
1312
1366
  description: options.description,
1313
1367
  decisionReason: options.decisionReason,
1314
1368
  agentId: options.agentID,
1315
- expiresAt: Date.now() + timeoutMs
1369
+ expiresAt: timeoutMs === void 0 ? void 0 : Date.now() + timeoutMs
1316
1370
  };
1317
1371
  const questionBehavior = this.#config.questionBehavior ?? "ask";
1318
1372
  if (toolName === "AskUserQuestion" && questionBehavior !== "ask") {
@@ -1320,7 +1374,7 @@ var SessionRunner = class {
1320
1374
  return Promise.resolve(this.#resolveQuestionByPolicy(request, questionBehavior));
1321
1375
  }
1322
1376
  return new Promise((resolve) => {
1323
- const timer = setTimeout(() => {
1377
+ const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
1324
1378
  const pending = this.#pending.get(id);
1325
1379
  if (pending) this.#settleApproval(id, pending, {
1326
1380
  behavior: "deny",
@@ -1460,6 +1514,7 @@ var AiSdkRunner = class {
1460
1514
  #statusDetail;
1461
1515
  #permissionMode;
1462
1516
  #messages = [];
1517
+ #pendingLocalCommands = [];
1463
1518
  #pendingToolCalls = /* @__PURE__ */ new Map();
1464
1519
  #dispatched = /* @__PURE__ */ new Set();
1465
1520
  #turnChain = Promise.resolve();
@@ -1494,6 +1549,7 @@ var AiSdkRunner = class {
1494
1549
  if (!state || !Array.isArray(state.messages)) throw new Error("session snapshot is missing its provider-engine state");
1495
1550
  this.#log.restore(snapshot.events, snapshot.seq, state.lastActivityAt);
1496
1551
  this.#messages = [...state.messages];
1552
+ this.#pendingLocalCommands = [...state.pendingLocalCommands ?? []];
1497
1553
  for (const call of state.pendingToolCalls) this.#pendingToolCalls.set(call.toolCallId, call);
1498
1554
  this.#dispatched = new Set(state.dispatched);
1499
1555
  this.#numTurns = state.numTurns;
@@ -1594,7 +1650,8 @@ var AiSdkRunner = class {
1594
1650
  permissionMode: this.#permissionMode,
1595
1651
  model: this.#modelAlias,
1596
1652
  lastActivityAt: this.#log.lastActivityAt,
1597
- parkedAt: Date.now()
1653
+ parkedAt: Date.now(),
1654
+ ...this.#pendingLocalCommands.length ? { pendingLocalCommands: [...this.#pendingLocalCommands] } : {}
1598
1655
  };
1599
1656
  return {
1600
1657
  engine: "provider",
@@ -1610,15 +1667,25 @@ var AiSdkRunner = class {
1610
1667
  sendMessage(text, attachments) {
1611
1668
  if (this.#parked) throw new Error("session is parked");
1612
1669
  if (this.#closed) throw new Error("session is closed");
1613
- const content = attachments?.length ? [...attachments.map((attachment) => ({
1670
+ const files = (attachments ?? []).map((attachment) => ({
1614
1671
  type: "file",
1615
1672
  data: attachment.data,
1616
1673
  mediaType: normalizeMediaType(attachment.mediaType),
1617
1674
  filename: attachment.name
1618
- })), ...text ? [{
1619
- type: "text",
1620
- text
1621
- }] : []] : text;
1675
+ }));
1676
+ const context = localCommandContext(this.#pendingLocalCommands);
1677
+ this.#pendingLocalCommands = [];
1678
+ const content = files.length || context ? [
1679
+ ...context ? [{
1680
+ type: "text",
1681
+ text: context
1682
+ }] : [],
1683
+ ...files,
1684
+ ...text ? [{
1685
+ type: "text",
1686
+ text
1687
+ }] : []
1688
+ ] : text;
1622
1689
  this.#messages.push({
1623
1690
  role: "user",
1624
1691
  content
@@ -1635,6 +1702,22 @@ var AiSdkRunner = class {
1635
1702
  });
1636
1703
  this.#scheduleTurn();
1637
1704
  }
1705
+ queueLocalCommand(result) {
1706
+ if (this.#parked) throw new Error("session is parked");
1707
+ if (this.#closed) throw new Error("session is closed");
1708
+ const text = localCommandTranscript(result);
1709
+ this.#pendingLocalCommands.push(text);
1710
+ this.#emit({
1711
+ type: "user_message",
1712
+ message: {
1713
+ role: "user",
1714
+ content: text
1715
+ },
1716
+ parentToolUseId: null,
1717
+ synthetic: true,
1718
+ uuid: randomUUID()
1719
+ });
1720
+ }
1638
1721
  resolveToolCall(toolCallId, output, options) {
1639
1722
  if (!this.#settlePendingCall(toolCallId, output, options?.isError === true)) return false;
1640
1723
  if (this.#pendingToolCalls.size === 0) this.#scheduleTurn();
@@ -1735,6 +1818,7 @@ var AiSdkRunner = class {
1735
1818
  if (this.#closed) throw new Error("session is closed");
1736
1819
  if (this.#pendingToolCalls.size > 0) throw new Error("cannot clear context while tool calls are outstanding");
1737
1820
  this.#messages = [];
1821
+ this.#pendingLocalCommands = [];
1738
1822
  this.#emit({ type: "conversation_reset" });
1739
1823
  });
1740
1824
  this.#turnChain = run.then(() => void 0, () => void 0);
@@ -1802,6 +1886,7 @@ var AiSdkRunner = class {
1802
1886
  if (this.#closed || this.#parked) return;
1803
1887
  this.#closed = true;
1804
1888
  this.#abort?.abort();
1889
+ this.#pendingLocalCommands = [];
1805
1890
  this.#pendingToolCalls.clear();
1806
1891
  this.#dispatched.clear();
1807
1892
  for (const { timer } of this.#pendingApprovals.values()) clearTimeout(timer);
@@ -1850,7 +1935,7 @@ var AiSdkRunner = class {
1850
1935
  continue;
1851
1936
  }
1852
1937
  const requestId = randomUUID();
1853
- const timeoutMs = this.#config.approvalTimeoutMs ?? 12e4;
1938
+ const timeoutMs = resolveApprovalTimeoutMs(this.#config.approvalTimeoutMs, this.#config.defaultApprovalTimeoutMs);
1854
1939
  const request = {
1855
1940
  id: requestId,
1856
1941
  toolName: call.toolName,
@@ -1858,9 +1943,9 @@ var AiSdkRunner = class {
1858
1943
  toolUseId: call.toolCallId,
1859
1944
  title: `Agent wants to run ${call.toolName}`,
1860
1945
  displayName: call.toolName,
1861
- expiresAt: Date.now() + timeoutMs
1946
+ expiresAt: timeoutMs === void 0 ? void 0 : Date.now() + timeoutMs
1862
1947
  };
1863
- const timer = setTimeout(() => {
1948
+ const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
1864
1949
  if (!this.#pendingApprovals.has(requestId)) return;
1865
1950
  this.resolvePermission(requestId, {
1866
1951
  behavior: "deny",
@@ -3038,7 +3123,7 @@ function createEngineSession(options) {
3038
3123
  executionBackend: typeof options.backend === "function" ? void 0 : options.backend ?? "server",
3039
3124
  executionLimits: options.executionLimits,
3040
3125
  shouldApprove: options.shouldApprove,
3041
- approvalTimeoutMs: options.approvalTimeoutMs,
3126
+ defaultApprovalTimeoutMs: options.approvalTimeoutMs,
3042
3127
  reportMcpServers: options.mcp ? () => Promise.resolve(declaredServers === void 0 ? options.mcp.servers : options.mcp.servers.filter((s) => declaredServers.includes(s.name))) : void 0
3043
3128
  }, options.id);
3044
3129
  return runner;
@@ -3778,7 +3863,6 @@ const APPROVALS_REVIEWER_BY_MODE = {
3778
3863
  auto: "auto_review",
3779
3864
  bypassPermissions: "user"
3780
3865
  };
3781
- const DEFAULT_APPROVAL_TIMEOUT_MS = 3e5;
3782
3866
  const CODEX_IMAGE_TOOL = "CodexImageGeneration";
3783
3867
  const CODEX_AGENT_TOOL = "CodexAgent";
3784
3868
  const CODEX_COLLAB_TOOL = "CodexCollab";
@@ -4049,6 +4133,7 @@ var CodexRunner = class {
4049
4133
  #planType;
4050
4134
  #resolvedEffort;
4051
4135
  #queue = [];
4136
+ #pendingLocalCommands = [];
4052
4137
  #turnChain = Promise.resolve();
4053
4138
  #activeTurn;
4054
4139
  #connection;
@@ -4236,8 +4321,29 @@ var CodexRunner = class {
4236
4321
  type: "text",
4237
4322
  text
4238
4323
  });
4324
+ const context = localCommandContext(this.#pendingLocalCommands);
4325
+ this.#pendingLocalCommands = [];
4326
+ if (context) parts.unshift({
4327
+ type: "text",
4328
+ text: context
4329
+ });
4239
4330
  return parts;
4240
4331
  }
4332
+ queueLocalCommand(result) {
4333
+ if (this.#closed) throw new Error("session is closed");
4334
+ const text = localCommandTranscript(result);
4335
+ this.#pendingLocalCommands.push(text);
4336
+ this.#emit({
4337
+ type: "user_message",
4338
+ message: {
4339
+ role: "user",
4340
+ content: text
4341
+ },
4342
+ parentToolUseId: null,
4343
+ synthetic: true,
4344
+ uuid: randomUUID()
4345
+ });
4346
+ }
4241
4347
  resolvePermission(requestId, decision) {
4242
4348
  const pending = this.#approvals.get(requestId);
4243
4349
  if (!pending) return false;
@@ -4278,6 +4384,7 @@ var CodexRunner = class {
4278
4384
  message: "the conversation was cleared"
4279
4385
  }, "policy");
4280
4386
  this.#resumedHistory = void 0;
4387
+ this.#pendingLocalCommands = [];
4281
4388
  this.#emit({
4282
4389
  type: "conversation_reset",
4283
4390
  sdkSessionId: this.#sdkSessionId
@@ -4331,6 +4438,7 @@ var CodexRunner = class {
4331
4438
  if (this.#closed) return;
4332
4439
  this.#closed = true;
4333
4440
  this.#queue.length = 0;
4441
+ this.#pendingLocalCommands = [];
4334
4442
  for (const [id, pending] of this.#approvals) this.#settleApproval(id, pending, {
4335
4443
  behavior: "deny",
4336
4444
  message: "Session closed"
@@ -4798,16 +4906,16 @@ var CodexRunner = class {
4798
4906
  if (behavior !== "ask") return Promise.resolve(this.#resolveQuestionByPolicy(channel, params, behavior));
4799
4907
  }
4800
4908
  const id = randomUUID();
4801
- const timeoutMs = this.#config.approvalTimeoutMs ?? this.#config.defaultApprovalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS;
4909
+ const timeoutMs = resolveApprovalTimeoutMs(this.#config.approvalTimeoutMs, this.#config.defaultApprovalTimeoutMs);
4802
4910
  const itemId = channel.itemId(params);
4803
4911
  const request = {
4804
4912
  id,
4805
4913
  ...channel.describe(params),
4806
4914
  toolUseId: itemId ? `${this.#activeTurn?.nonce ?? "codex"}:${itemId}` : id,
4807
- expiresAt: Date.now() + timeoutMs
4915
+ expiresAt: timeoutMs === void 0 ? void 0 : Date.now() + timeoutMs
4808
4916
  };
4809
4917
  return new Promise((resolve) => {
4810
- const timer = setTimeout(() => {
4918
+ const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
4811
4919
  const pending = this.#approvals.get(id);
4812
4920
  if (pending) this.#settleApproval(id, pending, {
4813
4921
  behavior: "deny",
@@ -5513,6 +5621,6 @@ function getEngineAdapter(engine) {
5513
5621
  return ADAPTERS[engine ?? "claude"];
5514
5622
  }
5515
5623
  //#endregion
5516
- export { AiSdkRunner, BrowserBridgeExecutor, CLAUDE_CATALOG, CODEX_CATALOG, CodexRunner, DeferredExecutor, InputQueue, JsonRpcError, JsonRpcStdioConnection, PendingRequestRegistry, QuickJsExecutor, SUPPORTED_ATTACHMENT_TYPES, SessionRunner, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, truncateResultBlocks, withHostTools, withMcpTools };
5624
+ export { AiSdkRunner, BrowserBridgeExecutor, CLAUDE_CATALOG, CODEX_CATALOG, CodexRunner, DeferredExecutor, InputQueue, JsonRpcError, JsonRpcStdioConnection, PendingRequestRegistry, QuickJsExecutor, SUPPORTED_ATTACHMENT_TYPES, SessionRunner, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, localCommandContext, localCommandTranscript, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, truncateResultBlocks, withHostTools, withMcpTools };
5517
5625
 
5518
5626
  //# sourceMappingURL=index.mjs.map