@getpaseo/server 0.9.2 → 0.10.0-beta.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.
Files changed (145) hide show
  1. package/dist/scripts/supervisor.js +51 -21
  2. package/dist/server/server/agent/agent-manager.js +22 -2
  3. package/dist/server/server/agent/agent-prompt.js +12 -0
  4. package/dist/server/server/agent/agent-sdk-types.d.ts +3 -0
  5. package/dist/server/server/agent/mcp-shared.d.ts +5 -1
  6. package/dist/server/server/agent/mcp-shared.js +2 -1
  7. package/dist/server/server/agent/provider-registry.js +2 -2
  8. package/dist/server/server/agent/providers/acp-agent.js +20 -11
  9. package/dist/server/server/agent/providers/claude/agent.d.ts +1 -2
  10. package/dist/server/server/agent/providers/claude/agent.js +10 -9
  11. package/dist/server/server/agent/providers/claude/models.d.ts +1 -1
  12. package/dist/server/server/agent/providers/claude/models.js +1 -5
  13. package/dist/server/server/agent/providers/claude/project-dir.d.ts +1 -0
  14. package/dist/server/server/agent/providers/claude/project-dir.js +5 -1
  15. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +6 -1
  16. package/dist/server/server/agent/providers/codex-app-server-agent.js +10 -1
  17. package/dist/server/server/agent/providers/generic-acp-agent.js +3 -1
  18. package/dist/server/server/agent/providers/omp/agent.js +23 -6
  19. package/dist/server/server/agent/providers/omp/rpc-types.d.ts +1 -0
  20. package/dist/server/server/agent/providers/omp/rpc-types.js +1 -0
  21. package/dist/server/server/agent/providers/opencode/bridge.d.ts +5 -1
  22. package/dist/server/server/agent/providers/opencode/bridge.js +56 -5
  23. package/dist/server/server/agent/providers/opencode/http-error.d.ts +8 -0
  24. package/dist/server/server/agent/providers/opencode/http-error.js +13 -0
  25. package/dist/server/server/agent/providers/opencode/runtime-client.d.ts +38 -0
  26. package/dist/server/server/agent/providers/opencode/runtime-client.js +131 -0
  27. package/dist/server/server/agent/providers/opencode/runtime-notice.d.ts +3 -0
  28. package/dist/server/server/agent/providers/opencode/runtime-notice.js +47 -0
  29. package/dist/server/server/agent/providers/opencode/server-manager.js +19 -8
  30. package/dist/server/server/agent/providers/opencode/v2/agent.d.ts +36 -0
  31. package/dist/server/server/agent/providers/opencode/v2/agent.js +208 -0
  32. package/dist/server/server/agent/providers/opencode/v2/api.d.ts +18 -0
  33. package/dist/server/server/agent/providers/opencode/v2/api.js +2 -0
  34. package/dist/server/server/agent/providers/opencode/v2/bridge-plugin.bundle.mjs +6693 -0
  35. package/dist/server/server/agent/providers/opencode/v2/capabilities.d.ts +3 -0
  36. package/dist/server/server/agent/providers/opencode/v2/capabilities.js +13 -0
  37. package/dist/server/server/agent/providers/opencode/v2/children.d.ts +20 -0
  38. package/dist/server/server/agent/providers/opencode/v2/children.js +75 -0
  39. package/dist/server/server/agent/providers/opencode/v2/commands.d.ts +4 -0
  40. package/dist/server/server/agent/providers/opencode/v2/commands.js +36 -0
  41. package/dist/server/server/agent/providers/opencode/v2/configuration.d.ts +8 -0
  42. package/dist/server/server/agent/providers/opencode/v2/configuration.js +64 -0
  43. package/dist/server/server/agent/providers/opencode/v2/history.d.ts +4 -0
  44. package/dist/server/server/agent/providers/opencode/v2/history.js +15 -0
  45. package/dist/server/server/agent/providers/opencode/v2/mapping.d.ts +7 -0
  46. package/dist/server/server/agent/providers/opencode/v2/mapping.js +42 -0
  47. package/dist/server/server/agent/providers/opencode/v2/permissions.d.ts +18 -0
  48. package/dist/server/server/agent/providers/opencode/v2/permissions.js +157 -0
  49. package/dist/server/server/agent/providers/opencode/v2/readiness.d.ts +18 -0
  50. package/dist/server/server/agent/providers/opencode/v2/readiness.js +51 -0
  51. package/dist/server/server/agent/providers/opencode/v2/runtime.d.ts +36 -0
  52. package/dist/server/server/agent/providers/opencode/v2/runtime.js +230 -0
  53. package/dist/server/server/agent/providers/opencode/v2/session.d.ts +84 -0
  54. package/dist/server/server/agent/providers/opencode/v2/session.js +465 -0
  55. package/dist/server/server/agent/providers/opencode/v2/structured-output.d.ts +8 -0
  56. package/dist/server/server/agent/providers/opencode/v2/structured-output.js +32 -0
  57. package/dist/server/server/agent/providers/opencode/v2/timeline.d.ts +28 -0
  58. package/dist/server/server/agent/providers/opencode/v2/timeline.js +154 -0
  59. package/dist/server/server/agent/providers/opencode/v2/turns.d.ts +40 -0
  60. package/dist/server/server/agent/providers/opencode/v2/turns.js +226 -0
  61. package/dist/server/server/agent/providers/opencode-agent.d.ts +26 -7
  62. package/dist/server/server/agent/providers/opencode-agent.js +100 -40
  63. package/dist/server/server/agent/providers/pi/agent.d.ts +6 -6
  64. package/dist/server/server/agent/providers/pi/agent.js +114 -165
  65. package/dist/server/server/agent/providers/pi/extensions/child-session.d.ts +4 -0
  66. package/dist/server/server/agent/providers/pi/extensions/child-session.js +59 -0
  67. package/dist/server/server/agent/providers/pi/extensions/contract.d.ts +68 -0
  68. package/dist/server/server/agent/providers/pi/extensions/contract.js +2 -0
  69. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.d.ts +3 -0
  70. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.js +159 -0
  71. package/dist/server/server/agent/providers/pi/extensions/host.d.ts +28 -0
  72. package/dist/server/server/agent/providers/pi/extensions/host.js +94 -0
  73. package/dist/server/server/agent/providers/pi/extensions/index.d.ts +7 -0
  74. package/dist/server/server/agent/providers/pi/extensions/index.js +6 -0
  75. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.d.ts +3 -0
  76. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.js +138 -0
  77. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.d.ts +3 -0
  78. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.js +38 -0
  79. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.d.ts +3 -0
  80. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.js +63 -0
  81. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.d.ts +3 -0
  82. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.js +48 -0
  83. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.d.ts +3 -0
  84. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.js +131 -0
  85. package/dist/server/server/agent/providers/pi/extensions/registry.d.ts +2 -0
  86. package/dist/server/server/agent/providers/pi/extensions/registry.js +21 -0
  87. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.d.ts +3 -0
  88. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.js +180 -0
  89. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.d.ts +3 -0
  90. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.js +51 -0
  91. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.d.ts +22 -0
  92. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.js +66 -0
  93. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.d.ts +4 -0
  94. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.js +79 -0
  95. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.d.ts +3 -0
  96. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.js +149 -0
  97. package/dist/server/server/agent/providers/pi/history-mapper.d.ts +7 -2
  98. package/dist/server/server/agent/providers/pi/history-mapper.js +78 -35
  99. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +3 -0
  100. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +170 -0
  101. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +355 -0
  102. package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +1 -6
  103. package/dist/server/server/agent/providers/pi/tool-call-mapper.js +1 -97
  104. package/dist/server/server/agent/tools/paseo-tools.js +22 -15
  105. package/dist/server/server/auth.d.ts +1 -2
  106. package/dist/server/server/auth.js +8 -14
  107. package/dist/server/server/bootstrap.js +10 -2
  108. package/dist/server/server/daemon-instance.d.ts +1 -0
  109. package/dist/server/server/daemon-instance.js +1 -0
  110. package/dist/server/server/exports.d.ts +1 -1
  111. package/dist/server/server/exports.js +1 -1
  112. package/dist/server/server/local-credential.d.ts +6 -0
  113. package/dist/server/server/local-credential.js +82 -0
  114. package/dist/server/server/session-admission-auth.d.ts +16 -0
  115. package/dist/server/server/session-admission-auth.js +26 -0
  116. package/dist/server/server/websocket-server.d.ts +6 -1
  117. package/dist/server/server/websocket-server.js +132 -55
  118. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js} +1 -1
  119. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.br → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.br} +0 -0
  120. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.gz +0 -0
  121. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js → desktop-attachment-store-d5d3402a752965d3037191484127123b.js} +1 -1
  122. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.br → desktop-attachment-store-d5d3402a752965d3037191484127123b.js.br} +0 -0
  123. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-d5d3402a752965d3037191484127123b.js.gz +0 -0
  124. package/dist/server/web-ui/_expo/static/js/web/{index-8868523fc6d311c5da524c067d1cd426.js → index-69ce3c243032c3bedfc6f2ad379a4cdd.js} +1579 -1575
  125. package/dist/server/web-ui/_expo/static/js/web/index-69ce3c243032c3bedfc6f2ad379a4cdd.js.br +0 -0
  126. package/dist/server/web-ui/_expo/static/js/web/index-69ce3c243032c3bedfc6f2ad379a4cdd.js.gz +0 -0
  127. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js} +1 -1
  128. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.br → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.br} +0 -0
  129. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.gz +0 -0
  130. package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js → native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js} +3 -3
  131. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.br +0 -0
  132. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.gz +0 -0
  133. package/dist/server/web-ui/index.html +1 -1
  134. package/dist/server/web-ui/index.html.br +0 -0
  135. package/dist/server/web-ui/index.html.gz +0 -0
  136. package/dist/src/server/daemon-instance.js +1 -0
  137. package/dist/src/server/local-credential.js +82 -0
  138. package/package.json +8 -7
  139. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.gz +0 -0
  140. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.gz +0 -0
  141. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.br +0 -0
  142. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.gz +0 -0
  143. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.gz +0 -0
  144. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.br +0 -0
  145. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.gz +0 -0
@@ -1,7 +1,6 @@
1
1
  import { fork, spawn } from "child_process";
2
- import { mkdirSync } from "node:fs";
3
2
  import path from "node:path";
4
- import { createStream as createRotatingFileStream } from "rotating-file-stream";
3
+ import { createStream as createRotatingFileStream, } from "rotating-file-stream";
5
4
  import { signalProcessTree } from "../src/utils/tree-kill.js";
6
5
  const WORKER_HEARTBEAT_INTERVAL_MS = 1000;
7
6
  const WORKER_TERMINATION_GRACE_MS = 10000;
@@ -49,16 +48,51 @@ function toRotatingFileStreamSize(size) {
49
48
  const unit = (match[2] ?? "M").toUpperCase();
50
49
  return `${value}${unit}`;
51
50
  }
52
- function createSupervisorLogStream(options) {
53
- if (!options) {
54
- return null;
55
- }
56
- mkdirSync(path.dirname(options.path), { recursive: true });
57
- return createRotatingFileStream(path.basename(options.path), {
58
- path: path.dirname(options.path),
59
- size: toRotatingFileStreamSize(options.rotate.maxSize),
60
- maxFiles: options.rotate.maxFiles,
61
- });
51
+ // daemon.log is best effort: a full disk or a replaced log path must not take the
52
+ // supervisor, and with it the worker, down. A failed stream is dropped and a new one
53
+ // is opened on the next write, so logging resumes once the file is writable again.
54
+ function createDurableLog(options, reportFailure) {
55
+ let stream = null;
56
+ let failing = false;
57
+ const open = (logFile) => {
58
+ const next = createRotatingFileStream(path.basename(logFile.path), {
59
+ path: path.dirname(logFile.path),
60
+ size: toRotatingFileStreamSize(logFile.rotate.maxSize),
61
+ maxFiles: logFile.rotate.maxFiles,
62
+ });
63
+ next.on("error", (error) => {
64
+ if (stream === next) {
65
+ stream = null;
66
+ }
67
+ if (!failing) {
68
+ failing = true;
69
+ reportFailure(`Cannot write ${logFile.path}, will retry on the next log line: ${error.message}`);
70
+ }
71
+ });
72
+ return next;
73
+ };
74
+ return {
75
+ write(chunk) {
76
+ if (!options) {
77
+ return;
78
+ }
79
+ stream ?? (stream = open(options));
80
+ stream.write(chunk, (error) => {
81
+ if (!error) {
82
+ failing = false;
83
+ }
84
+ });
85
+ },
86
+ close() {
87
+ return new Promise((resolve) => {
88
+ if (!stream) {
89
+ resolve();
90
+ return;
91
+ }
92
+ stream.end(() => resolve());
93
+ });
94
+ },
95
+ };
62
96
  }
63
97
  export function runSupervisor(options) {
64
98
  const restartOnCrash = options.restartOnCrash ?? false;
@@ -73,9 +107,11 @@ export function runSupervisor(options) {
73
107
  let lifecycleFailed = false;
74
108
  let publication = Promise.resolve();
75
109
  let forceKillTimer = null;
76
- const logStream = createSupervisorLogStream(options.logFile);
110
+ const durableLog = createDurableLog(options.logFile, (message) => {
111
+ process.stderr.write(`[${options.name}] ${message}\n`);
112
+ });
77
113
  const writeDurableChunk = (chunk) => {
78
- logStream?.write(chunk);
114
+ durableLog.write(chunk);
79
115
  };
80
116
  const writeLifecycleLog = (message, fields = {}) => {
81
117
  writeDurableChunk(`${JSON.stringify({
@@ -91,13 +127,7 @@ export function runSupervisor(options) {
91
127
  process.stderr.write(`[${options.name}] ${message}\n`);
92
128
  writeLifecycleLog(message);
93
129
  };
94
- const closeLogStream = () => new Promise((resolve) => {
95
- if (!logStream) {
96
- resolve();
97
- return;
98
- }
99
- logStream.end(resolve);
100
- });
130
+ const closeLogStream = () => durableLog.close();
101
131
  const exitSupervisor = (code) => {
102
132
  if (exiting) {
103
133
  return;
@@ -2413,11 +2413,31 @@ export class AgentManager {
2413
2413
  durableTimelineHasRows,
2414
2414
  options,
2415
2415
  });
2416
+ // Read history before publishing the agent: a provider failure must leave the
2417
+ // session unregistered so the registration catch closes it.
2418
+ const startupHistory = [];
2419
+ if (session.initialTimeline?.length && !managed.historyPrimed) {
2420
+ for await (const event of session.streamHistory()) {
2421
+ startupHistory.push(limitAgentStreamEventContent(event));
2422
+ }
2423
+ }
2416
2424
  this.assertAcceptingAgentRegistrations();
2417
2425
  this.agents.set(resolvedAgentId, managed);
2418
2426
  registered = true;
2419
2427
  // Initialize previousStatus to track transitions
2420
2428
  this.previousStatuses.set(resolvedAgentId, managed.lifecycle);
2429
+ if (session.initialTimeline?.length) {
2430
+ if (!managed.historyPrimed) {
2431
+ // Legacy/imported chats need their existing history before startup rows.
2432
+ await this.primeTimelineFromLegacyProviderHistory(managed, false, startupHistory);
2433
+ }
2434
+ else {
2435
+ for (const entry of session.initialTimeline) {
2436
+ this.recordTimeline(managed.id, entry.item, { timestamp: entry.timestamp });
2437
+ }
2438
+ }
2439
+ this.refreshSessionPersistence(managed);
2440
+ }
2421
2441
  await this.refreshRuntimeInfo(managed, { emit: false });
2422
2442
  this.assertAgentRegistrationActive(managed);
2423
2443
  await this.persistSnapshot(managed, {
@@ -2817,7 +2837,7 @@ export class AgentManager {
2817
2837
  this.touchUpdatedAt(agent);
2818
2838
  this.emitState(agent);
2819
2839
  }
2820
- async primeTimelineFromLegacyProviderHistory(agent, broadcast) {
2840
+ async primeTimelineFromLegacyProviderHistory(agent, broadcast, history = agent.session.streamHistory()) {
2821
2841
  const deferredBroadcast = typeof broadcast === "function";
2822
2842
  const historyEvents = [];
2823
2843
  const historySubagentEvents = [];
@@ -2826,7 +2846,7 @@ export class AgentManager {
2826
2846
  // Collect the whole replay before touching either store. A stream that fails
2827
2847
  // halfway then leaves the committed timeline as it was, instead of a partial
2828
2848
  // copy the next attempt would append to.
2829
- for await (const rawEvent of agent.session.streamHistory()) {
2849
+ for await (const rawEvent of history) {
2830
2850
  const event = limitAgentStreamEventContent(rawEvent);
2831
2851
  if (event.type === "provider_subagent") {
2832
2852
  historySubagentEvents.push(event);
@@ -234,6 +234,10 @@ function formatFinishNotificationBody(params) {
234
234
  }
235
235
  return sections.join("\n\n");
236
236
  }
237
+ // A caller waits on a child through one armed notification. Arming again, such as a
238
+ // follow-up prompt while the child still runs, replaces the earlier one so the child's
239
+ // next finish reaches the caller once.
240
+ const armedFinishNotifications = new WeakMap();
237
241
  export function setupFinishNotification(params) {
238
242
  const { agentManager, agentStorage, childAgentId, callerAgentId, requireParentOwnership = false, logger, } = params;
239
243
  let hasSeenRunning = false;
@@ -241,11 +245,19 @@ export function setupFinishNotification(params) {
241
245
  const notifiedPermissionRequestIds = new Set();
242
246
  let unsubscribe = null;
243
247
  let notificationQueue = Promise.resolve();
248
+ const armedByManager = armedFinishNotifications.get(agentManager) ?? new Map();
249
+ armedFinishNotifications.set(agentManager, armedByManager);
250
+ const armedKey = JSON.stringify([childAgentId, callerAgentId]);
251
+ armedByManager.get(armedKey)?.();
252
+ armedByManager.set(armedKey, stop);
244
253
  function stop() {
245
254
  if (stopped)
246
255
  return;
247
256
  stopped = true;
248
257
  unsubscribe?.();
258
+ if (armedByManager.get(armedKey) === stop) {
259
+ armedByManager.delete(armedKey);
260
+ }
249
261
  }
250
262
  async function notify(reason, permissionRequest) {
251
263
  const callerRecord = await agentStorage.get(callerAgentId);
@@ -585,6 +585,9 @@ export interface AgentSession {
585
585
  readonly id: string | null;
586
586
  readonly capabilities: AgentCapabilityFlags;
587
587
  readonly features?: AgentFeature[];
588
+ /** New provider-owned rows to commit on registration. streamHistory must also
589
+ * replay them at their original timestamps; restored sessions omit old rows. */
590
+ readonly initialTimeline?: ImportedTimelineEntry[];
588
591
  run(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<AgentRunResult>;
589
592
  startTurn(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<{
590
593
  turnId: string;
@@ -62,6 +62,10 @@ export interface ResolvedProviderModel {
62
62
  model: string | undefined;
63
63
  }
64
64
  export declare function resolveRequiredProviderModel(providerValue: string): Required<ResolvedProviderModel>;
65
+ export interface AgentWaitWithTimeoutResult extends WaitForAgentResult {
66
+ /** The wait gave up while the agent was still working. */
67
+ timedOut: boolean;
68
+ }
65
69
  /**
66
70
  * Wraps agentManager.waitForAgentEvent with a self-imposed timeout.
67
71
  * Returns a friendly message when timeout occurs, rather than letting
@@ -70,7 +74,7 @@ export declare function resolveRequiredProviderModel(providerValue: string): Req
70
74
  export declare function waitForAgentWithTimeout(agentManager: AgentManager, agentId: string, options?: {
71
75
  signal?: AbortSignal;
72
76
  waitForActive?: boolean;
73
- }): Promise<WaitForAgentResult>;
77
+ }): Promise<AgentWaitWithTimeoutResult>;
74
78
  export declare function sanitizePermissionRequest(permission: AgentPermissionRequest): AgentPermissionRequest;
75
79
  export declare function sanitizePermissionRequest(permission: null | undefined): null;
76
80
  export declare function sanitizePermissionRequest(permission: AgentPermissionRequest | null | undefined): AgentPermissionRequest | null;
@@ -93,7 +93,7 @@ export async function waitForAgentWithTimeout(agentManager, agentId, options) {
93
93
  signal: combinedController.signal,
94
94
  waitForActive: options?.waitForActive,
95
95
  });
96
- return result;
96
+ return { ...result, timedOut: false };
97
97
  }
98
98
  catch (error) {
99
99
  if (error instanceof Error && error.message === "wait timeout") {
@@ -111,6 +111,7 @@ export async function waitForAgentWithTimeout(agentManager, agentId, options) {
111
111
  status: snapshot?.lifecycle ?? "idle",
112
112
  permission: null,
113
113
  lastMessage: message,
114
+ timedOut: true,
114
115
  };
115
116
  }
116
117
  throw error;
@@ -9,7 +9,7 @@ import { CursorACPAgentClient } from "./providers/cursor-acp-agent.js";
9
9
  import { GenericACPAgentClient } from "./providers/generic-acp-agent.js";
10
10
  import { KimiACPAgentClient } from "./providers/kimi-acp-agent.js";
11
11
  import { KiroACPAgentClient } from "./providers/kiro-acp-agent.js";
12
- import { OpenCodeAgentClient } from "./providers/opencode-agent.js";
12
+ import { OpenCodeRuntimeClient } from "./providers/opencode/runtime-client.js";
13
13
  import { OmpAgentClient } from "./providers/omp/agent.js";
14
14
  import { PiRpcAgentClient } from "./providers/pi/agent.js";
15
15
  import { TraeACPAgentClient } from "./providers/trae-acp-agent.js";
@@ -73,7 +73,7 @@ const PROVIDER_CLIENT_FACTORIES = {
73
73
  command: getCursorACPCommand(runtimeSettings),
74
74
  env: runtimeSettings?.env,
75
75
  }),
76
- opencode: (logger, runtimeSettings, options) => new OpenCodeAgentClient(logger, runtimeSettings, {
76
+ opencode: (logger, runtimeSettings, options) => new OpenCodeRuntimeClient(logger, runtimeSettings, {
77
77
  managedProcesses: options?.managedProcesses,
78
78
  bridge: options?.openCodeBridge,
79
79
  }),
@@ -22,6 +22,16 @@ function assertChildWithPipes(child) {
22
22
  throw new Error("Child process did not expose stdio pipes");
23
23
  }
24
24
  }
25
+ // Node reports a failed spawn (missing binary or missing cwd) as a child
26
+ // `error` event; without a listener it becomes an uncaught exception.
27
+ function rejectOnSpawnError(child, stderrChunks) {
28
+ return new Promise((_, reject) => {
29
+ child.once("error", (error) => {
30
+ const stderr = stderrChunks.join("").trim();
31
+ reject(new Error(stderr ? `${String(error)}\n${stderr}` : String(error)));
32
+ });
33
+ });
34
+ }
25
35
  function isRecord(value) {
26
36
  return value != null && typeof value === "object" && !Array.isArray(value);
27
37
  }
@@ -753,12 +763,7 @@ export class ACPAgentClient {
753
763
  child.stderr.on("data", (chunk) => {
754
764
  stderrChunks.push(chunk.toString());
755
765
  });
756
- const spawnErrorPromise = new Promise((_, reject) => {
757
- child.once("error", (error) => {
758
- const stderr = stderrChunks.join("").trim();
759
- reject(new Error(stderr ? `${String(error)}\n${stderr}` : String(error)));
760
- });
761
- });
766
+ const spawnErrorPromise = rejectOnSpawnError(child, stderrChunks);
762
767
  const spawnReadyPromise = new Promise((resolve) => {
763
768
  child.once("spawn", () => {
764
769
  resolve();
@@ -1850,6 +1855,7 @@ export class ACPAgentSession {
1850
1855
  child.stderr.on("data", (chunk) => {
1851
1856
  stderrChunks.push(chunk.toString());
1852
1857
  });
1858
+ const spawnError = rejectOnSpawnError(child, stderrChunks);
1853
1859
  child.once("exit", (code, signal) => {
1854
1860
  if (this.closed) {
1855
1861
  return;
@@ -1871,11 +1877,14 @@ export class ACPAgentSession {
1871
1877
  // close the process even when the ACP handshake itself rejects.
1872
1878
  this.child = child;
1873
1879
  this.connection = connection;
1874
- const initialize = await this.runACPRequest(() => connection.initialize({
1875
- protocolVersion: PROTOCOL_VERSION,
1876
- clientCapabilities: buildACPClientCapabilities(this.clientCapabilityMeta, this.clientCapabilities),
1877
- clientInfo: { name: "Paseo", version: "dev" },
1878
- }));
1880
+ const initialize = await this.runACPRequest(() => Promise.race([
1881
+ connection.initialize({
1882
+ protocolVersion: PROTOCOL_VERSION,
1883
+ clientCapabilities: buildACPClientCapabilities(this.clientCapabilityMeta, this.clientCapabilities),
1884
+ clientInfo: { name: "Paseo", version: "dev" },
1885
+ }),
1886
+ spawnError,
1887
+ ]));
1879
1888
  return { child, connection, initialize };
1880
1889
  }
1881
1890
  async runACPRequest(request) {
@@ -24,7 +24,6 @@ interface ClaudeAgentClientOptions {
24
24
  queryFactory?: ClaudeQueryFactory;
25
25
  resolveBinary?: () => Promise<string>;
26
26
  resolveVersion?: (signal?: AbortSignal) => Promise<string>;
27
- configDir?: string;
28
27
  rewindSdk?: ClaudeRewindSdk;
29
28
  }
30
29
  export declare function extractUserMessageText(content: unknown): string | null;
@@ -39,7 +38,6 @@ export declare class ClaudeAgentClient implements AgentClient {
39
38
  private readonly queryFactory?;
40
39
  private readonly resolveBinary;
41
40
  private readonly resolveVersion;
42
- private readonly configDir?;
43
41
  private readonly rewindSdk;
44
42
  constructor(options: ClaudeAgentClientOptions);
45
43
  resolveConfiguredModel(model: AgentModelDefinition): AgentModelDefinition;
@@ -48,6 +46,7 @@ export declare class ClaudeAgentClient implements AgentClient {
48
46
  getCatalogCacheKey(_options: FetchCatalogOptions): Promise<string>;
49
47
  fetchCatalog(_options: FetchCatalogOptions, context?: ProviderRefreshContext): Promise<ProviderCatalog>;
50
48
  resolveDefaultModeId({ env: launchEnv }: ResolveAgentDefaultModeInput): Promise<string>;
49
+ private buildProviderEnv;
51
50
  listFeatures(config: AgentSessionConfig): Promise<AgentFeature[]>;
52
51
  listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
53
52
  importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../../agent-sdk-types.js").ImportedProviderSession>;
@@ -1,7 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import { promises } from "node:fs";
4
- import os from "node:os";
5
4
  import path from "node:path";
6
5
  import { mapClaudeCanceledToolCall, mapClaudeCompletedToolCall, mapClaudeFailedToolCall, mapClaudeRunningToolCall, } from "./tool-call-mapper.js";
7
6
  import { mapTaskNotificationSystemRecordToToolCall, mapTaskNotificationUserContentToToolCall, readTaskNotificationToolUseIdFromHistoryRecord, } from "./task-notification-tool-call.js";
@@ -23,7 +22,7 @@ import { renderPromptAttachmentAsText } from "../../prompt-attachments.js";
23
22
  import { claudeQuery } from "./query.js";
24
23
  import { realClaudeRewindSdk, revertClaudeConversation, revertClaudeFiles, } from "./rewind.js";
25
24
  import { normalizeProviderReplayTimestamp } from "../../provider-history-timestamps.js";
26
- import { claudeProjectDirSync } from "./project-dir.js";
25
+ import { claudeConfigDir, claudeProjectDirSync } from "./project-dir.js";
27
26
  import { THINKING_APPLIES_NEXT_TURN_NOTICE } from "../../provider-notices.js";
28
27
  import { isProviderImageMarkdown, materializeProviderImage, renderProviderImageOutputAsAssistantMarkdown, } from "../provider-image-output.js";
29
28
  import { getAgentStreamEventTurnId, } from "../../agent-sdk-types.js";
@@ -1060,7 +1059,6 @@ export class ClaudeAgentClient {
1060
1059
  this.resolveVersion =
1061
1060
  options.resolveVersion ??
1062
1061
  ((signal) => resolveClaudeCodeVersion(this.runtimeSettings, signal));
1063
- this.configDir = options.configDir;
1064
1062
  this.rewindSdk = options.rewindSdk ?? realClaudeRewindSdk;
1065
1063
  }
1066
1064
  resolveConfiguredModel(model) {
@@ -1117,20 +1115,23 @@ export class ClaudeAgentClient {
1117
1115
  catch (error) {
1118
1116
  this.logger.warn({ err: error }, "Failed to resolve Claude Code version for model catalog");
1119
1117
  }
1120
- const models = await runProviderRefreshActivity(context, "settings", () => getClaudeModelsWithSettings(this.logger, this.configDir, claudeCodeVersion));
1121
- const modeCatalog = claudeModeCatalog(createProviderEnv({ baseEnv: process.env, runtimeSettings: this.runtimeSettings }));
1118
+ const env = this.buildProviderEnv();
1119
+ const models = await runProviderRefreshActivity(context, "settings", () => getClaudeModelsWithSettings(this.logger, claudeConfigDir(env), claudeCodeVersion));
1120
+ const modeCatalog = claudeModeCatalog(env);
1122
1121
  return {
1123
1122
  models,
1124
1123
  ...modeCatalog,
1125
1124
  };
1126
1125
  }
1127
1126
  async resolveDefaultModeId({ env: launchEnv }) {
1128
- const env = createProviderEnv({
1127
+ return claudeModeCatalog(this.buildProviderEnv(launchEnv)).defaultModeId;
1128
+ }
1129
+ buildProviderEnv(launchEnv) {
1130
+ return createProviderEnv({
1129
1131
  baseEnv: process.env,
1130
1132
  runtimeSettings: this.runtimeSettings,
1131
1133
  overlays: [launchEnv],
1132
1134
  });
1133
- return claudeModeCatalog(env).defaultModeId;
1134
1135
  }
1135
1136
  async listFeatures(config) {
1136
1137
  const claudeConfig = this.assertConfig(config);
@@ -1140,7 +1141,7 @@ export class ClaudeAgentClient {
1140
1141
  });
1141
1142
  }
1142
1143
  async listImportableSessions(options) {
1143
- const configDir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
1144
+ const configDir = claudeConfigDir(this.buildProviderEnv());
1144
1145
  const sessionsRoot = options?.cwd
1145
1146
  ? claudeProjectDirSync(options.cwd, { configDir })
1146
1147
  : path.join(configDir, "projects");
@@ -4018,7 +4019,7 @@ class ClaudeAgentSession {
4018
4019
  const cwd = this.config.cwd;
4019
4020
  if (!cwd)
4020
4021
  return null;
4021
- const configDir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
4022
+ const configDir = claudeConfigDir(this.buildSdkEnv());
4022
4023
  const candidates = [cwd];
4023
4024
  try {
4024
4025
  const realCwd = fs.realpathSync(cwd);
@@ -3,7 +3,7 @@ import type { AgentModelDefinition } from "../../agent-sdk-types.js";
3
3
  export declare function getClaudeModels(claudeCodeVersion?: string): AgentModelDefinition[];
4
4
  export declare function resolveConfiguredClaudeModel(model: AgentModelDefinition): AgentModelDefinition;
5
5
  export declare function findClaudeModel(modelId: string | null | undefined): AgentModelDefinition | undefined;
6
- export declare function getClaudeModelsWithSettings(logger: Logger, configDir?: string, claudeCodeVersion?: string): Promise<AgentModelDefinition[]>;
6
+ export declare function getClaudeModelsWithSettings(logger: Logger, configDir: string, claudeCodeVersion?: string): Promise<AgentModelDefinition[]>;
7
7
  /**
8
8
  * Normalize a runtime model string (from SDK init message) to a known model ID.
9
9
  * Handles the `[1m]` suffix that the SDK appends for 1M context sessions.
@@ -1,5 +1,4 @@
1
1
  import * as fs from "node:fs/promises";
2
- import * as os from "node:os";
3
2
  import * as path from "node:path";
4
3
  import { getClaudeCustomModelThinkingOptions, getClaudeManifestModels, normalizeClaudeManifestModelId, normalizeClaudeRuntimeModelId as normalizeClaudeManifestRuntimeModelId, } from "./model-manifest.js";
5
4
  const CLAUDE_SETTINGS_MODEL_ENV_KEYS = [
@@ -55,7 +54,7 @@ export async function getClaudeModelsWithSettings(logger, configDir, claudeCodeV
55
54
  return models;
56
55
  }
57
56
  async function readClaudeSettingsModels(logger, configDir) {
58
- const settingsPath = path.join(resolveClaudeConfigDir(configDir), "settings.json");
57
+ const settingsPath = path.join(configDir, "settings.json");
59
58
  let parsed;
60
59
  try {
61
60
  const rawSettings = await fs.readFile(settingsPath, "utf8");
@@ -84,9 +83,6 @@ async function readClaudeSettingsModels(logger, configDir) {
84
83
  }
85
84
  return models;
86
85
  }
87
- function resolveClaudeConfigDir(configDir) {
88
- return configDir ?? process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
89
- }
90
86
  function addSettingsModel(models, value, settingsKey) {
91
87
  if (typeof value !== "string") {
92
88
  return;
@@ -3,4 +3,5 @@ export interface ClaudeProjectDirOptions {
3
3
  }
4
4
  export declare function claudeProjectDir(cwd: string, options?: ClaudeProjectDirOptions): Promise<string>;
5
5
  export declare function claudeProjectDirSync(cwd: string, options?: ClaudeProjectDirOptions): string;
6
+ export declare function claudeConfigDir(env: NodeJS.ProcessEnv): string;
6
7
  //# sourceMappingURL=project-dir.d.ts.map
@@ -51,7 +51,11 @@ function hashSuffix(input) {
51
51
  }
52
52
  return Math.abs(hash).toString(36);
53
53
  }
54
+ // Claude Code keeps its settings and transcripts here for a process launched with `env`.
55
+ export function claudeConfigDir(env) {
56
+ return env.CLAUDE_CONFIG_DIR ?? join(homedir(), ".claude");
57
+ }
54
58
  function resolveConfigDir(options) {
55
- return options?.configDir ?? process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), ".claude");
59
+ return options?.configDir ?? claudeConfigDir(process.env);
56
60
  }
57
61
  //# sourceMappingURL=project-dir.js.map
@@ -20,7 +20,7 @@ interface CodexAppServerAgentDeps {
20
20
  label: string;
21
21
  extends: string;
22
22
  };
23
- customCodexConfig?: Record<string, unknown> | null;
23
+ customCodexConfig?: CodexCustomProviderConfig | null;
24
24
  _createCodexClient?: (child: ChildProcessWithoutNullStreams, logger: Logger, getTraceContext: () => CodexAppServerTraceContext) => CodexAppServerClientLike;
25
25
  resolveSlashCommandInvocation?: (prompt: AgentPromptInput) => Promise<{
26
26
  commandName: string;
@@ -108,6 +108,10 @@ type CodexAppServerUserInput = {
108
108
  } | CodexSkillPromptBlock;
109
109
  export declare function codexAppServerTurnInputFromPrompt(prompt: CodexPromptInput, logger: Logger): Promise<CodexAppServerUserInput[]>;
110
110
  export declare function buildCodexAppServerEnv(runtimeSettings?: ProviderRuntimeSettings, launchEnv?: Record<string, string>): NodeJS.ProcessEnv;
111
+ interface CodexCustomProviderConfig {
112
+ model_provider: string;
113
+ model_providers: Record<string, Record<string, unknown>>;
114
+ }
111
115
  export declare class CodexAppServerAgentSession implements AgentSession {
112
116
  private readonly resumeHandle;
113
117
  private readonly spawnAppServer;
@@ -359,6 +363,7 @@ export declare class CodexAppServerAgentClient implements AgentClient {
359
363
  private autoReviewEnabledPromise;
360
364
  constructor(logger: Logger, runtimeSettings?: ProviderRuntimeSettings | undefined, deps?: CodexAppServerAgentDeps);
361
365
  private sessionDeps;
366
+ private customProviderConfig;
362
367
  private resolveGoalsEnabled;
363
368
  private resolveAutoReviewEnabled;
364
369
  private probeAutoReviewEnabled;
@@ -635,6 +635,7 @@ async function readCodexThreadWindow(client, logger, window) {
635
635
  // Older Codex builds ignore the unknown key and keep that order.
636
636
  sortKey: "updated_at",
637
637
  ...(window.cwd ? { cwd: window.cwd } : {}),
638
+ ...(window.modelProviders ? { modelProviders: window.modelProviders } : {}),
638
639
  ...(cursor ? { cursor } : {}),
639
640
  }));
640
641
  const page = Array.isArray(response?.data) ? response.data.filter(isRecord) : [];
@@ -5604,9 +5605,12 @@ export class CodexAppServerAgentClient {
5604
5605
  sessionDeps() {
5605
5606
  return {
5606
5607
  ...this.deps,
5607
- customCodexConfig: buildCodexCustomProviderConfig(this.runtimeSettings, this.deps.customProvider),
5608
+ customCodexConfig: this.customProviderConfig(),
5608
5609
  };
5609
5610
  }
5611
+ customProviderConfig() {
5612
+ return buildCodexCustomProviderConfig(this.runtimeSettings, this.deps.customProvider);
5613
+ }
5610
5614
  resolveGoalsEnabled() {
5611
5615
  if (!this.goalsEnabledPromise) {
5612
5616
  this.goalsEnabledPromise = (async () => {
@@ -5717,9 +5721,14 @@ export class CodexAppServerAgentClient {
5717
5721
  // filtering since most threads will be from other cwds, then keep the
5718
5722
  // local realpath-aware filter for symlink-equivalent workspace paths.
5719
5723
  const listLimit = options?.cwd ? Math.max(scanLimit, 50) : scanLimit;
5724
+ // Codex records each thread under the model provider that ran it and,
5725
+ // unless told otherwise, lists only the provider its own config selects.
5726
+ // A custom provider runs under its own id, so ask for exactly that one.
5727
+ const customProviderConfig = this.customProviderConfig();
5720
5728
  const allThreads = await readCodexThreadWindow(client, this.logger, {
5721
5729
  limit: listLimit,
5722
5730
  cwd: options?.cwd,
5731
+ ...(customProviderConfig ? { modelProviders: [customProviderConfig.model_provider] } : {}),
5723
5732
  });
5724
5733
  const threads = filterCodexThreadsByCwd(allThreads, options?.cwd);
5725
5734
  return threads.slice(0, limit).map((thread) => {
@@ -29,7 +29,9 @@ export class GenericACPAgentClient extends ACPAgentClient {
29
29
  },
30
30
  defaultCommand: options.command,
31
31
  capabilities: buildGenericACPCapabilities(providerParams),
32
- waitForInitialCommands: options.waitForInitialCommands,
32
+ // ACP agents advertise slash commands with available_commands_update after
33
+ // session/new, so the first listCommands() waits for that batch.
34
+ waitForInitialCommands: options.waitForInitialCommands ?? true,
33
35
  initialCommandsWaitTimeoutMs: options.initialCommandsWaitTimeoutMs,
34
36
  clientCapabilities: providerParams.clientCapabilities,
35
37
  clientCapabilityMeta: options.clientCapabilityMeta,
@@ -336,6 +336,17 @@ function getInputQuestionTitle(title, placeholder) {
336
336
  }
337
337
  return "Optional response";
338
338
  }
339
+ function readSelectOptions(options, optionDetails) {
340
+ const labels = readStringArray(options);
341
+ const details = Array.isArray(optionDetails) ? optionDetails : [];
342
+ return labels.map((label, index) => {
343
+ const detail = details[index];
344
+ const description = isRecord(detail) && typeof detail.description === "string" && detail.description.trim() !== ""
345
+ ? detail.description
346
+ : undefined;
347
+ return description === undefined ? { label } : { label, description };
348
+ });
349
+ }
339
350
  function readStringArray(value) {
340
351
  return Array.isArray(value)
341
352
  ? value.filter((item) => typeof item === "string")
@@ -349,7 +360,7 @@ function mapExtensionUiRequestToPermission(event, options = {}) {
349
360
  const label = options.label ?? "OMP";
350
361
  switch (event.method) {
351
362
  case "select": {
352
- const selectOptions = readStringArray(event.options);
363
+ const selectOptions = readSelectOptions(event.options, event.optionDetails);
353
364
  if (options.combineOptionalComment) {
354
365
  return buildCombinedAskUserQuestionPermission(event, {
355
366
  provider,
@@ -396,7 +407,7 @@ function mapExtensionUiRequestToPermission(event, options = {}) {
396
407
  question: [optionalString(event.title), optionalString(event.message)]
397
408
  .filter(Boolean)
398
409
  .join("\n\n"),
399
- options: ["Yes", "No"],
410
+ options: [{ label: "Yes" }, { label: "No" }],
400
411
  multiSelect: false,
401
412
  });
402
413
  default:
@@ -439,7 +450,10 @@ function buildExtensionUiQuestionPermission(event, input) {
439
450
  {
440
451
  question: input.question,
441
452
  header: QUESTION_RESPONSE_HEADER,
442
- options: input.options.map((label) => ({ label })),
453
+ options: input.options.map((option) => ({
454
+ label: option.label,
455
+ ...(option.description === undefined ? {} : { description: option.description }),
456
+ })),
443
457
  multiSelect: input.multiSelect,
444
458
  ...(input.placeholder ? { placeholder: input.placeholder } : {}),
445
459
  ...(input.allowEmpty ? { allowEmpty: true } : {}),
@@ -454,7 +468,7 @@ function buildExtensionUiQuestionPermission(event, input) {
454
468
  };
455
469
  }
456
470
  function buildCombinedAskUserQuestionPermission(event, input) {
457
- const visibleOptions = input.options.filter((option) => !isOmpAskUserFreeformOption(option));
471
+ const visibleOptions = input.options.filter((option) => !isOmpAskUserFreeformOption(option.label));
458
472
  const allowOther = input.allowFreeform || visibleOptions.length !== input.options.length;
459
473
  return {
460
474
  id: event.id,
@@ -467,7 +481,10 @@ function buildCombinedAskUserQuestionPermission(event, input) {
467
481
  {
468
482
  question: input.question,
469
483
  header: QUESTION_RESPONSE_HEADER,
470
- options: visibleOptions.map((label) => ({ label })),
484
+ options: visibleOptions.map((option) => ({
485
+ label: option.label,
486
+ ...(option.description === undefined ? {} : { description: option.description }),
487
+ })),
471
488
  multiSelect: false,
472
489
  ...(allowOther ? { allowOther: true } : {}),
473
490
  },
@@ -486,7 +503,7 @@ function buildCombinedAskUserQuestionPermission(event, input) {
486
503
  answerHeader: QUESTION_RESPONSE_HEADER,
487
504
  commentHeader: QUESTION_COMMENT_HEADER,
488
505
  combinedAskUser: COMBINED_ASK_USER_METADATA,
489
- selectOptions: visibleOptions,
506
+ selectOptions: visibleOptions.map((option) => option.label),
490
507
  ...(allowOther ? { freeformSentinel: OMP_ASK_USER_FREEFORM_SENTINEL } : {}),
491
508
  },
492
509
  };
@@ -1325,6 +1325,7 @@ export declare const OmpRuntimeEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject
1325
1325
  title: z.ZodOptional<z.ZodString>;
1326
1326
  message: z.ZodOptional<z.ZodString>;
1327
1327
  options: z.ZodOptional<z.ZodArray<z.ZodString>>;
1328
+ optionDetails: z.ZodOptional<z.ZodUnknown>;
1328
1329
  placeholder: z.ZodOptional<z.ZodString>;
1329
1330
  url: z.ZodOptional<z.ZodString>;
1330
1331
  launchUrl: z.ZodOptional<z.ZodString>;
@@ -425,6 +425,7 @@ const OmpExtensionUiRequestSchema = z
425
425
  title: z.string().optional(),
426
426
  message: z.string().optional(),
427
427
  options: z.array(z.string()).optional(),
428
+ optionDetails: z.unknown().optional(),
428
429
  placeholder: z.string().optional(),
429
430
  url: z.string().optional(),
430
431
  launchUrl: z.string().optional(),