@getpaseo/server 0.1.26 → 0.1.28

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 (166) hide show
  1. package/dist/server/client/daemon-client.d.ts +1 -1
  2. package/dist/server/client/daemon-client.d.ts.map +1 -1
  3. package/dist/server/client/daemon-client.js +1 -1
  4. package/dist/server/client/daemon-client.js.map +1 -1
  5. package/dist/server/server/agent/agent-response-loop.js +1 -1
  6. package/dist/server/server/agent/agent-response-loop.js.map +1 -1
  7. package/dist/server/server/agent/provider-launch-config.d.ts +14 -2
  8. package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
  9. package/dist/server/server/agent/provider-launch-config.js +30 -8
  10. package/dist/server/server/agent/provider-launch-config.js.map +1 -1
  11. package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
  12. package/dist/server/server/agent/provider-manifest.js +10 -5
  13. package/dist/server/server/agent/provider-manifest.js.map +1 -1
  14. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -1
  15. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +2 -0
  16. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -1
  17. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -1
  18. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +2 -0
  19. package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
  20. package/dist/server/server/agent/providers/claude-agent.d.ts +3 -1
  21. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
  22. package/dist/server/server/agent/providers/claude-agent.js +5 -1
  23. package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
  24. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  25. package/dist/server/server/agent/providers/codex-app-server-agent.js +146 -46
  26. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  27. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -1
  28. package/dist/server/server/agent/providers/codex-rollout-timeline.js +77 -9
  29. package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -1
  30. package/dist/server/server/agent/providers/opencode-agent.d.ts +1 -0
  31. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  32. package/dist/server/server/agent/providers/opencode-agent.js +115 -43
  33. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  34. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +1 -0
  35. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
  36. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +8 -0
  37. package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
  38. package/dist/server/server/agent/tts-manager.d.ts +8 -1
  39. package/dist/server/server/agent/tts-manager.d.ts.map +1 -1
  40. package/dist/server/server/agent/tts-manager.js +215 -108
  41. package/dist/server/server/agent/tts-manager.js.map +1 -1
  42. package/dist/server/server/bootstrap.d.ts +2 -2
  43. package/dist/server/server/bootstrap.d.ts.map +1 -1
  44. package/dist/server/server/bootstrap.js +26 -5
  45. package/dist/server/server/bootstrap.js.map +1 -1
  46. package/dist/server/server/persisted-config.d.ts +25 -0
  47. package/dist/server/server/persisted-config.d.ts.map +1 -1
  48. package/dist/server/server/persisted-config.js +6 -0
  49. package/dist/server/server/persisted-config.js.map +1 -1
  50. package/dist/server/server/session.d.ts +22 -19
  51. package/dist/server/server/session.d.ts.map +1 -1
  52. package/dist/server/server/session.js +305 -294
  53. package/dist/server/server/session.js.map +1 -1
  54. package/dist/server/server/speech/providers/local/runtime.d.ts +2 -0
  55. package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -1
  56. package/dist/server/server/speech/providers/local/runtime.js +7 -0
  57. package/dist/server/server/speech/providers/local/runtime.js.map +1 -1
  58. package/dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
  59. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +2 -0
  60. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -1
  61. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -1
  62. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts +13 -0
  63. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts.map +1 -0
  64. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +23 -0
  65. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js.map +1 -0
  66. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts +32 -0
  67. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts.map +1 -0
  68. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js +107 -0
  69. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js.map +1 -0
  70. package/dist/server/server/speech/providers/openai/runtime.d.ts +2 -0
  71. package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -1
  72. package/dist/server/server/speech/providers/openai/runtime.js +2 -0
  73. package/dist/server/server/speech/providers/openai/runtime.js.map +1 -1
  74. package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -1
  75. package/dist/server/server/speech/speech-config-resolver.js +35 -14
  76. package/dist/server/server/speech/speech-config-resolver.js.map +1 -1
  77. package/dist/server/server/speech/speech-runtime.d.ts +3 -1
  78. package/dist/server/server/speech/speech-runtime.d.ts.map +1 -1
  79. package/dist/server/server/speech/speech-runtime.js +39 -6
  80. package/dist/server/server/speech/speech-runtime.js.map +1 -1
  81. package/dist/server/server/speech/speech-types.d.ts +1 -0
  82. package/dist/server/server/speech/speech-types.d.ts.map +1 -1
  83. package/dist/server/server/speech/turn-detection-provider.d.ts +22 -0
  84. package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -0
  85. package/dist/server/server/speech/turn-detection-provider.js +2 -0
  86. package/dist/server/server/speech/turn-detection-provider.js.map +1 -0
  87. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.d.ts +16 -0
  88. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.d.ts.map +1 -0
  89. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.js +35 -0
  90. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.js.map +1 -0
  91. package/dist/server/server/voice/voice-turn-controller.d.ts +34 -0
  92. package/dist/server/server/voice/voice-turn-controller.d.ts.map +1 -0
  93. package/dist/server/server/voice/voice-turn-controller.js +161 -0
  94. package/dist/server/server/voice/voice-turn-controller.js.map +1 -0
  95. package/dist/server/server/websocket-server.d.ts +3 -0
  96. package/dist/server/server/websocket-server.d.ts.map +1 -1
  97. package/dist/server/server/websocket-server.js +5 -1
  98. package/dist/server/server/websocket-server.js.map +1 -1
  99. package/dist/server/server/workspace-registry.d.ts +2 -0
  100. package/dist/server/server/workspace-registry.d.ts.map +1 -1
  101. package/dist/server/server/workspace-registry.js +11 -4
  102. package/dist/server/server/workspace-registry.js.map +1 -1
  103. package/dist/server/shared/messages.d.ts +97 -0
  104. package/dist/server/shared/messages.d.ts.map +1 -1
  105. package/dist/server/shared/messages.js +7 -0
  106. package/dist/server/shared/messages.js.map +1 -1
  107. package/dist/server/shared/tool-call-display.d.ts.map +1 -1
  108. package/dist/server/shared/tool-call-display.js +59 -33
  109. package/dist/server/shared/tool-call-display.js.map +1 -1
  110. package/dist/src/server/agent/agent-response-loop.js +1 -1
  111. package/dist/src/server/agent/agent-response-loop.js.map +1 -1
  112. package/dist/src/server/agent/provider-launch-config.js +30 -8
  113. package/dist/src/server/agent/provider-launch-config.js.map +1 -1
  114. package/dist/src/server/agent/provider-manifest.js +10 -5
  115. package/dist/src/server/agent/provider-manifest.js.map +1 -1
  116. package/dist/src/server/agent/providers/claude/tool-call-detail-parser.js +2 -0
  117. package/dist/src/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -1
  118. package/dist/src/server/agent/providers/claude/tool-call-mapper.js +2 -0
  119. package/dist/src/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
  120. package/dist/src/server/agent/providers/claude-agent.js +5 -1
  121. package/dist/src/server/agent/providers/claude-agent.js.map +1 -1
  122. package/dist/src/server/agent/providers/codex-app-server-agent.js +146 -46
  123. package/dist/src/server/agent/providers/codex-app-server-agent.js.map +1 -1
  124. package/dist/src/server/agent/providers/codex-rollout-timeline.js +77 -9
  125. package/dist/src/server/agent/providers/codex-rollout-timeline.js.map +1 -1
  126. package/dist/src/server/agent/providers/opencode-agent.js +115 -43
  127. package/dist/src/server/agent/providers/opencode-agent.js.map +1 -1
  128. package/dist/src/server/agent/providers/tool-call-mapper-utils.js +8 -0
  129. package/dist/src/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
  130. package/dist/src/server/agent/tts-manager.js +215 -108
  131. package/dist/src/server/agent/tts-manager.js.map +1 -1
  132. package/dist/src/server/bootstrap.js +26 -5
  133. package/dist/src/server/bootstrap.js.map +1 -1
  134. package/dist/src/server/persisted-config.js +6 -0
  135. package/dist/src/server/persisted-config.js.map +1 -1
  136. package/dist/src/server/session.js +305 -294
  137. package/dist/src/server/session.js.map +1 -1
  138. package/dist/src/server/speech/providers/local/runtime.js +7 -0
  139. package/dist/src/server/speech/providers/local/runtime.js.map +1 -1
  140. package/dist/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -1
  141. package/dist/src/server/speech/providers/local/sherpa/silero-vad-provider.js +23 -0
  142. package/dist/src/server/speech/providers/local/sherpa/silero-vad-provider.js.map +1 -0
  143. package/dist/src/server/speech/providers/local/sherpa/silero-vad-session.js +107 -0
  144. package/dist/src/server/speech/providers/local/sherpa/silero-vad-session.js.map +1 -0
  145. package/dist/src/server/speech/providers/openai/runtime.js +2 -0
  146. package/dist/src/server/speech/providers/openai/runtime.js.map +1 -1
  147. package/dist/src/server/speech/speech-config-resolver.js +35 -14
  148. package/dist/src/server/speech/speech-config-resolver.js.map +1 -1
  149. package/dist/src/server/speech/speech-runtime.js +39 -6
  150. package/dist/src/server/speech/speech-runtime.js.map +1 -1
  151. package/dist/src/server/speech/turn-detection-provider.js +2 -0
  152. package/dist/src/server/speech/turn-detection-provider.js.map +1 -0
  153. package/dist/src/server/voice/fixed-duration-pcm-ring-buffer.js +35 -0
  154. package/dist/src/server/voice/fixed-duration-pcm-ring-buffer.js.map +1 -0
  155. package/dist/src/server/voice/voice-turn-controller.js +161 -0
  156. package/dist/src/server/voice/voice-turn-controller.js.map +1 -0
  157. package/dist/src/server/websocket-server.js +5 -1
  158. package/dist/src/server/websocket-server.js.map +1 -1
  159. package/dist/src/server/workspace-registry.js +11 -4
  160. package/dist/src/server/workspace-registry.js.map +1 -1
  161. package/dist/src/shared/messages.js +7 -0
  162. package/dist/src/shared/messages.js.map +1 -1
  163. package/dist/src/shared/tool-call-display.js +59 -33
  164. package/dist/src/shared/tool-call-display.js.map +1 -1
  165. package/package.json +7 -7
  166. package/src/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
@@ -2,14 +2,14 @@ import { execSync, spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { existsSync } from "node:fs";
4
4
  import fs from "node:fs/promises";
5
- import { createRequire } from "node:module";
6
5
  import os from "node:os";
7
6
  import path from "node:path";
8
7
  import readline from "node:readline";
9
8
  import { z } from "zod";
10
9
  import { loadCodexPersistedTimeline } from "./codex-rollout-timeline.js";
11
10
  import { mapCodexRolloutToolCall, mapCodexToolCallFromThreadItem, } from "./codex/tool-call-mapper.js";
12
- import { applyProviderEnv, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
11
+ import { applyProviderEnv, findExecutable, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
12
+ import { extractCodexTerminalSessionId, nonEmptyString } from "./tool-call-mapper-utils.js";
13
13
  const DEFAULT_TIMEOUT_MS = 14 * 24 * 60 * 60 * 1000;
14
14
  const TURN_START_TIMEOUT_MS = 90 * 1000;
15
15
  const CODEX_PROVIDER = "codex";
@@ -87,49 +87,12 @@ function mergeCodexConfiguredDefaults(primary, fallback) {
87
87
  thinkingOptionId: primary.thinkingOptionId ?? fallback.thinkingOptionId,
88
88
  };
89
89
  }
90
- const CODEX_TARGET_TRIPLE = {
91
- linux: { x64: "x86_64-unknown-linux-musl", arm64: "aarch64-unknown-linux-musl" },
92
- darwin: { x64: "x86_64-apple-darwin", arm64: "aarch64-apple-darwin" },
93
- win32: { x64: "x86_64-pc-windows-msvc", arm64: "aarch64-pc-windows-msvc" },
94
- };
95
- const CODEX_PLATFORM_PACKAGE = {
96
- "x86_64-unknown-linux-musl": "@openai/codex-linux-x64",
97
- "aarch64-unknown-linux-musl": "@openai/codex-linux-arm64",
98
- "x86_64-apple-darwin": "@openai/codex-darwin-x64",
99
- "aarch64-apple-darwin": "@openai/codex-darwin-arm64",
100
- "x86_64-pc-windows-msvc": "@openai/codex-win32-x64",
101
- "aarch64-pc-windows-msvc": "@openai/codex-win32-arm64",
102
- };
103
- function resolveBundledCodexBinary() {
104
- const targetTriple = CODEX_TARGET_TRIPLE[process.platform]?.[process.arch];
105
- if (!targetTriple) {
106
- return null;
107
- }
108
- const platformPackage = CODEX_PLATFORM_PACKAGE[targetTriple];
109
- if (!platformPackage) {
110
- return null;
111
- }
112
- const binaryName = process.platform === "win32" ? "codex.exe" : "codex";
113
- try {
114
- const require = createRequire(import.meta.url);
115
- const packageJsonPath = require.resolve(`${platformPackage}/package.json`);
116
- const vendorRoot = path.join(path.dirname(packageJsonPath), "vendor");
117
- const binaryPath = path.join(vendorRoot, targetTriple, "codex", binaryName);
118
- if (existsSync(binaryPath)) {
119
- return binaryPath;
120
- }
121
- }
122
- catch {
123
- // Platform package not installed
124
- }
125
- return null;
126
- }
127
90
  function resolveCodexBinary() {
128
- const bundled = resolveBundledCodexBinary();
129
- if (bundled) {
130
- return bundled;
91
+ const found = findExecutable("codex");
92
+ if (found) {
93
+ return found;
131
94
  }
132
- throw new Error(`Bundled Codex binary not found for platform ${process.platform}-${process.arch}. Ensure the @openai/codex package and its platform-specific optional dependency are installed.`);
95
+ throw new Error("Codex binary not found. Install the Codex CLI (https://github.com/openai/codex) and ensure it is available in your shell PATH.");
133
96
  }
134
97
  function resolveCodexLaunchPrefix(runtimeSettings) {
135
98
  return resolveProviderCommandPrefix(runtimeSettings?.command, resolveCodexBinary);
@@ -425,7 +388,11 @@ class CodexAppServerClient {
425
388
  this.nextId = 1;
426
389
  this.disposed = false;
427
390
  this.stderrBuffer = "";
391
+ this.resolveExitPromise = null;
428
392
  this.rl = readline.createInterface({ input: child.stdout });
393
+ this.exitPromise = new Promise((resolve) => {
394
+ this.resolveExitPromise = resolve;
395
+ });
429
396
  this.rl.on("line", (line) => this.handleLine(line));
430
397
  child.stderr.on("data", (chunk) => {
431
398
  this.stderrBuffer += chunk.toString();
@@ -444,6 +411,8 @@ class CodexAppServerClient {
444
411
  }
445
412
  this.pending.clear();
446
413
  this.disposed = true;
414
+ this.resolveExitPromise?.();
415
+ this.resolveExitPromise = null;
447
416
  });
448
417
  }
449
418
  setNotificationHandler(handler) {
@@ -481,11 +450,13 @@ class CodexAppServerClient {
481
450
  this.disposed = true;
482
451
  this.rl.close();
483
452
  try {
484
- this.child.kill();
453
+ this.child.stdin.end();
485
454
  }
486
455
  catch {
487
456
  // ignore
488
457
  }
458
+ terminateChildProcessTree(this.child);
459
+ await this.exitPromise;
489
460
  }
490
461
  async handleLine(line) {
491
462
  if (!line.trim())
@@ -539,6 +510,26 @@ class CodexAppServerClient {
539
510
  }
540
511
  }
541
512
  }
513
+ function terminateChildProcessTree(child) {
514
+ if (child.killed) {
515
+ return;
516
+ }
517
+ if (process.platform !== "win32" && typeof child.pid === "number" && child.pid > 0) {
518
+ try {
519
+ process.kill(-child.pid, "SIGTERM");
520
+ return;
521
+ }
522
+ catch {
523
+ // Fall back to the direct child when no separate process group exists.
524
+ }
525
+ }
526
+ try {
527
+ child.kill("SIGTERM");
528
+ }
529
+ catch {
530
+ // ignore
531
+ }
532
+ }
542
533
  function toAgentUsage(tokenUsage) {
543
534
  if (!tokenUsage || typeof tokenUsage !== "object")
544
535
  return undefined;
@@ -869,6 +860,26 @@ function mapCodexPatchNotificationToToolCall(params) {
869
860
  }
870
861
  return params.running ? toRunningToolCall(mapped) : mapped;
871
862
  }
863
+ function mapCodexTerminalInteractionToToolCall(params) {
864
+ const processId = nonEmptyString(params.processId ?? undefined);
865
+ const callId = processId
866
+ ? `terminal-session-${processId}`
867
+ : nonEmptyString(params.fallbackCallId ?? undefined) ?? "terminal-interaction";
868
+ const label = nonEmptyString(params.command ?? undefined);
869
+ return {
870
+ type: "tool_call",
871
+ callId,
872
+ name: "terminal",
873
+ status: "completed",
874
+ error: null,
875
+ detail: {
876
+ type: "plain_text",
877
+ ...(label ? { label } : {}),
878
+ icon: "square_terminal",
879
+ },
880
+ ...(processId ? { metadata: { processId } } : {}),
881
+ };
882
+ }
872
883
  function threadItemToTimeline(item, options) {
873
884
  if (!item || typeof item !== "object")
874
885
  return null;
@@ -1065,6 +1076,21 @@ const CodexEventExecCommandOutputDeltaNotificationSchema = z.object({
1065
1076
  })
1066
1077
  .passthrough(),
1067
1078
  }).passthrough();
1079
+ const CodexEventTerminalInteractionNotificationSchema = z.object({
1080
+ msg: z
1081
+ .object({
1082
+ type: z.literal("terminal_interaction"),
1083
+ call_id: z.string().optional(),
1084
+ process_id: z.union([z.string(), z.number()]).optional(),
1085
+ stdin: z.string().optional(),
1086
+ })
1087
+ .passthrough(),
1088
+ }).passthrough();
1089
+ const ItemCommandExecutionTerminalInteractionNotificationSchema = z.object({
1090
+ itemId: z.string().optional(),
1091
+ processId: z.union([z.string(), z.number()]).optional(),
1092
+ stdin: z.string().optional(),
1093
+ }).passthrough();
1068
1094
  const CodexEventPatchApplyBeginNotificationSchema = z.object({
1069
1095
  msg: z
1070
1096
  .object({
@@ -1204,6 +1230,35 @@ const CodexNotificationSchema = z.union([
1204
1230
  method: z.literal("codex/event/exec_command_output_delta"),
1205
1231
  params: z.unknown(),
1206
1232
  }).transform(({ method, params }) => ({ kind: "invalid_payload", method, params })),
1233
+ z.object({
1234
+ method: z.literal("codex/event/terminal_interaction"),
1235
+ params: CodexEventTerminalInteractionNotificationSchema,
1236
+ }).transform(({ params }) => ({
1237
+ kind: "terminal_interaction",
1238
+ source: "codex_event",
1239
+ callId: params.msg.call_id ?? null,
1240
+ processId: typeof params.msg.process_id === "number"
1241
+ ? String(params.msg.process_id)
1242
+ : params.msg.process_id ?? null,
1243
+ stdin: params.msg.stdin ?? null,
1244
+ })),
1245
+ z.object({ method: z.literal("codex/event/terminal_interaction"), params: z.unknown() }).transform(({ method, params }) => ({ kind: "invalid_payload", method, params })),
1246
+ z.object({
1247
+ method: z.literal("item/commandExecution/terminalInteraction"),
1248
+ params: ItemCommandExecutionTerminalInteractionNotificationSchema,
1249
+ }).transform(({ params }) => ({
1250
+ kind: "terminal_interaction",
1251
+ source: "item",
1252
+ callId: params.itemId ?? null,
1253
+ processId: typeof params.processId === "number"
1254
+ ? String(params.processId)
1255
+ : params.processId ?? null,
1256
+ stdin: params.stdin ?? null,
1257
+ })),
1258
+ z.object({
1259
+ method: z.literal("item/commandExecution/terminalInteraction"),
1260
+ params: z.unknown(),
1261
+ }).transform(({ method, params }) => ({ kind: "invalid_payload", method, params })),
1207
1262
  z.object({
1208
1263
  method: z.literal("codex/event/patch_apply_begin"),
1209
1264
  params: CodexEventPatchApplyBeginNotificationSchema,
@@ -1356,6 +1411,8 @@ class CodexAppServerAgentSession {
1356
1411
  this.pendingReasoning = new Map();
1357
1412
  this.pendingCommandOutputDeltas = new Map();
1358
1413
  this.pendingFileChangeOutputDeltas = new Map();
1414
+ this.terminalCommandByProcessId = new Map();
1415
+ this.emittedTerminalInteractionKeys = new Set();
1359
1416
  this.emittedExecCommandStartedCallIds = new Set();
1360
1417
  this.emittedExecCommandCompletedCallIds = new Set();
1361
1418
  this.emittedItemStartedIds = new Set();
@@ -2087,7 +2144,6 @@ class CodexAppServerAgentSession {
2087
2144
  this.pendingCommandOutputDeltas.clear();
2088
2145
  this.pendingFileChangeOutputDeltas.clear();
2089
2146
  this.warnedIncompleteEditToolCallIds.clear();
2090
- this.eventQueue?.end();
2091
2147
  return;
2092
2148
  }
2093
2149
  if (parsed.kind === "plan_updated") {
@@ -2150,11 +2206,13 @@ class CodexAppServerAgentSession {
2150
2206
  }
2151
2207
  if (parsed.kind === "exec_command_completed") {
2152
2208
  const bufferedOutput = this.consumeOutputDelta(this.pendingCommandOutputDeltas, parsed.callId);
2209
+ const resolvedOutput = parsed.output ?? bufferedOutput;
2210
+ this.rememberTerminalProcessForCommand(parsed.command, resolvedOutput);
2153
2211
  const timelineItem = mapCodexExecNotificationToToolCall({
2154
2212
  callId: parsed.callId,
2155
2213
  command: parsed.command,
2156
2214
  cwd: parsed.cwd ?? this.config.cwd ?? null,
2157
- output: parsed.output ?? bufferedOutput,
2215
+ output: resolvedOutput,
2158
2216
  exitCode: parsed.exitCode,
2159
2217
  success: parsed.success,
2160
2218
  stderr: parsed.stderr,
@@ -2166,6 +2224,23 @@ class CodexAppServerAgentSession {
2166
2224
  }
2167
2225
  return;
2168
2226
  }
2227
+ if (parsed.kind === "terminal_interaction") {
2228
+ const interactionKey = [
2229
+ parsed.processId ?? "",
2230
+ parsed.stdin ?? "",
2231
+ ].join("\u0000");
2232
+ if (!this.shouldEmitTerminalInteractionKey(interactionKey)) {
2233
+ return;
2234
+ }
2235
+ const timelineItem = mapCodexTerminalInteractionToToolCall({
2236
+ processId: parsed.processId,
2237
+ fallbackCallId: parsed.callId,
2238
+ command: (parsed.processId ? this.terminalCommandByProcessId.get(parsed.processId) : undefined) ??
2239
+ null,
2240
+ });
2241
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
2242
+ return;
2243
+ }
2169
2244
  if (parsed.kind === "patch_apply_started") {
2170
2245
  if (parsed.callId) {
2171
2246
  this.pendingFileChangeOutputDeltas.delete(parsed.callId);
@@ -2331,6 +2406,30 @@ class CodexAppServerAgentSession {
2331
2406
  store.delete(id);
2332
2407
  return buffered.join("");
2333
2408
  }
2409
+ rememberTerminalProcessForCommand(command, output) {
2410
+ const normalizedCommand = normalizeCodexCommandValue(command);
2411
+ if (!normalizedCommand) {
2412
+ return;
2413
+ }
2414
+ const displayCommand = typeof normalizedCommand === "string"
2415
+ ? normalizedCommand
2416
+ : normalizedCommand.join(" ").trim();
2417
+ if (!displayCommand) {
2418
+ return;
2419
+ }
2420
+ const processId = extractCodexTerminalSessionId(output ?? undefined);
2421
+ if (!processId) {
2422
+ return;
2423
+ }
2424
+ this.terminalCommandByProcessId.set(processId, displayCommand);
2425
+ }
2426
+ shouldEmitTerminalInteractionKey(key) {
2427
+ if (this.emittedTerminalInteractionKeys.has(key)) {
2428
+ return false;
2429
+ }
2430
+ this.emittedTerminalInteractionKeys.add(key);
2431
+ return true;
2432
+ }
2334
2433
  warnOnIncompleteEditToolCall(item, source, payload) {
2335
2434
  if (!isEditToolCallWithoutContent(item)) {
2336
2435
  return;
@@ -2467,6 +2566,7 @@ export class CodexAppServerAgentClient {
2467
2566
  launchPrefix
2468
2567
  }, "Spawning Codex app server");
2469
2568
  return spawn(launchPrefix.command, [...launchPrefix.args, "app-server"], {
2569
+ detached: process.platform !== "win32",
2470
2570
  stdio: ["pipe", "pipe", "pipe"],
2471
2571
  env: applyProviderEnv(process.env, this.runtimeSettings),
2472
2572
  });