@karlorz/codexhost-cli-win32-arm64 0.13.3-1 → 0.13.3-4

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.
@@ -22330,7 +22330,7 @@ function retainRendererHostResponses(client, hostId2, target) {
22330
22330
  if (typeof client.addRequestLifecycleListener !== "function" || typeof target.addEventListener !== "function" || typeof target.removeEventListener !== "function")
22331
22331
  return () => {
22332
22332
  };
22333
- const isRecord19 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
22333
+ const isRecord21 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
22334
22334
  const pending = /* @__PURE__ */ new Set();
22335
22335
  let retired = false;
22336
22336
  let unsubscribe = () => {
@@ -22346,15 +22346,15 @@ function retainRendererHostResponses(client, hostId2, target) {
22346
22346
  const ownOrigin = target.location?.origin;
22347
22347
  if (source === target && ownOrigin && ownOrigin !== "null" && origin !== ownOrigin)
22348
22348
  return;
22349
- if (!isRecord19(data) || data.type !== "mcp-response" || data.hostId !== hostId2)
22349
+ if (!isRecord21(data) || data.type !== "mcp-response" || data.hostId !== hostId2)
22350
22350
  return;
22351
22351
  const message2 = data.message;
22352
- if (!isRecord19(message2))
22352
+ if (!isRecord21(message2))
22353
22353
  return;
22354
22354
  const id2 = message2.id;
22355
22355
  if (typeof id2 !== "string" && typeof id2 !== "number" || !pending.has(id2))
22356
22356
  return;
22357
- const hasError = isRecord19(message2.error);
22357
+ const hasError = isRecord21(message2.error);
22358
22358
  if (!hasError && !Object.prototype.hasOwnProperty.call(message2, "result"))
22359
22359
  return;
22360
22360
  queueMicrotask(() => {
@@ -22368,7 +22368,7 @@ function retainRendererHostResponses(client, hostId2, target) {
22368
22368
  };
22369
22369
  target.addEventListener("message", receive);
22370
22370
  unsubscribe = client.addRequestLifecycleListener((event) => {
22371
- if (!isRecord19(event) || event.hostId !== hostId2)
22371
+ if (!isRecord21(event) || event.hostId !== hostId2)
22372
22372
  return;
22373
22373
  const id2 = event.id;
22374
22374
  if (typeof id2 !== "string" && typeof id2 !== "number")
@@ -22398,13 +22398,13 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22398
22398
  let selectedModel = null;
22399
22399
  let prewarmGeneration = 0;
22400
22400
  const externalPrewarms = /* @__PURE__ */ new Set();
22401
- const isRecord19 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
22401
+ const isRecord21 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
22402
22402
  const isUnsupportedPosixBridgeSpawn = (value2) => {
22403
22403
  const marker = "AbsolutePathBuf deserialized without a base path";
22404
22404
  if (typeof value2 === "string") {
22405
22405
  return value2.startsWith("Invalid request:") && value2.includes(marker);
22406
22406
  }
22407
- if (!isRecord19(value2))
22407
+ if (!isRecord21(value2))
22408
22408
  return false;
22409
22409
  if (typeof value2.message === "string" && value2.message.includes(marker)) {
22410
22410
  if (value2.code === -32600 || value2.message.startsWith("Invalid request:"))
@@ -22497,7 +22497,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22497
22497
  bridgeState = "idle";
22498
22498
  };
22499
22499
  const rememberExternalThread = (value2) => {
22500
- if (!isRecord19(value2) || typeof value2.id !== "string")
22500
+ if (!isRecord21(value2) || typeof value2.id !== "string")
22501
22501
  return;
22502
22502
  if (value2.modelProvider === "codexhost" || value2.cliVersion === "codexhost") {
22503
22503
  knownExternalThreadIds.add(value2.id);
@@ -22505,7 +22505,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22505
22505
  }
22506
22506
  };
22507
22507
  const observeBridgeResult = (request, result) => {
22508
- if (!request || !isRecord19(result))
22508
+ if (!request || !isRecord21(result))
22509
22509
  return;
22510
22510
  if (request.method === "thread/list" && Array.isArray(result.data)) {
22511
22511
  for (const thread of result.data)
@@ -22516,7 +22516,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22516
22516
  rememberExternalThread(result.thread);
22517
22517
  return;
22518
22518
  }
22519
- if (request.method === "codexhost/thread/inspect" && isRecord19(request.parameters) && typeof request.parameters.threadId === "string") {
22519
+ if (request.method === "codexhost/thread/inspect" && isRecord21(request.parameters) && typeof request.parameters.threadId === "string") {
22520
22520
  if (result.owner === "external") {
22521
22521
  knownExternalThreadIds.add(request.parameters.threadId);
22522
22522
  knownOfficialThreadIds.delete(request.parameters.threadId);
@@ -22526,18 +22526,18 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22526
22526
  }
22527
22527
  return;
22528
22528
  }
22529
- if (request.method === "thread/delete" && isRecord19(request.parameters) && typeof request.parameters.threadId === "string") {
22529
+ if (request.method === "thread/delete" && isRecord21(request.parameters) && typeof request.parameters.threadId === "string") {
22530
22530
  knownExternalThreadIds.delete(request.parameters.threadId);
22531
22531
  knownOfficialThreadIds.delete(request.parameters.threadId);
22532
22532
  }
22533
22533
  };
22534
22534
  const handleBridgeFrame = (value2) => {
22535
- if (!isRecord19(value2)) {
22535
+ if (!isRecord21(value2)) {
22536
22536
  failBridge("received a non-object app-server frame");
22537
22537
  return;
22538
22538
  }
22539
22539
  if (value2.method === bridgeReadyMethod && value2.id === void 0) {
22540
- if (isRecord19(value2.params) && value2.params.protocolVersion === 1) {
22540
+ if (isRecord21(value2.params) && value2.params.protocolVersion === 1) {
22541
22541
  bridgeState = "ready";
22542
22542
  if (bridgeReadyTimeout !== null)
22543
22543
  globalThis.clearTimeout(bridgeReadyTimeout);
@@ -22551,7 +22551,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22551
22551
  return;
22552
22552
  }
22553
22553
  if (typeof value2.method === "string" && value2.id === void 0) {
22554
- if (value2.method === "thread/started" && isRecord19(value2.params)) {
22554
+ if (value2.method === "thread/started" && isRecord21(value2.params)) {
22555
22555
  rememberExternalThread(value2.params.thread);
22556
22556
  }
22557
22557
  originalOnNotification.call(manager, value2.method, value2.params);
@@ -22602,13 +22602,13 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22602
22602
  }
22603
22603
  };
22604
22604
  const handleOuterNotification = (method, parameters) => {
22605
- if (method === "process/exited" && isRecord19(parameters) && parameters.processHandle === bridgeProcessHandle) {
22605
+ if (method === "process/exited" && isRecord21(parameters) && parameters.processHandle === bridgeProcessHandle) {
22606
22606
  const exitCode = typeof parameters.exitCode === "number" ? parameters.exitCode : "unknown";
22607
22607
  const stderr = typeof parameters.stderr === "string" ? parameters.stderr.trim() : "";
22608
22608
  failBridge(`process exited unexpectedly with code ${exitCode}${stderr ? `: ${stderr}` : ""}`, false);
22609
22609
  return true;
22610
22610
  }
22611
- if (method !== "process/outputDelta" || !isRecord19(parameters) || parameters.processHandle !== bridgeProcessHandle || parameters.stream !== "stdout" && parameters.stream !== "stderr" || typeof parameters.deltaBase64 !== "string") {
22611
+ if (method !== "process/outputDelta" || !isRecord21(parameters) || parameters.processHandle !== bridgeProcessHandle || parameters.stream !== "stdout" && parameters.stream !== "stderr" || typeof parameters.deltaBase64 !== "string") {
22612
22612
  return false;
22613
22613
  }
22614
22614
  if (parameters.capReached === true) {
@@ -22712,7 +22712,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22712
22712
  return bridgeInitialization;
22713
22713
  };
22714
22714
  const threadIdFromParameters = (parameters) => {
22715
- if (!isRecord19(parameters))
22715
+ if (!isRecord21(parameters))
22716
22716
  return null;
22717
22717
  const value2 = parameters.threadId ?? parameters.conversationId;
22718
22718
  return typeof value2 === "string" ? value2 : null;
@@ -22729,9 +22729,9 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22729
22729
  const resolution = initializeBridge().then(() => enqueueBridgeRequest("codexhost/thread/ownership/list", {
22730
22730
  threadIds: [threadId2]
22731
22731
  })).then((value2) => {
22732
- const ownerships = isRecord19(value2) && Array.isArray(value2.threads) ? value2.threads : null;
22732
+ const ownerships = isRecord21(value2) && Array.isArray(value2.threads) ? value2.threads : null;
22733
22733
  const ownership = ownerships?.[0];
22734
- if (!ownerships || !isRecord19(ownership) || ownerships.length !== 1 || ownership.threadId !== threadId2 || ownership.owner !== "external" && ownership.owner !== "codex") {
22734
+ if (!ownerships || !isRecord21(ownership) || ownerships.length !== 1 || ownership.threadId !== threadId2 || ownership.owner !== "external" && ownership.owner !== "codex") {
22735
22735
  throw transportError("Thread ownership lookup returned an invalid result");
22736
22736
  }
22737
22737
  if (ownership.owner === "external") {
@@ -22770,7 +22770,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22770
22770
  if (method === "thread/list")
22771
22771
  return true;
22772
22772
  if (method === "thread/start") {
22773
- return isRecord19(parameters) && typeof parameters.model === "string" && parameters.model.startsWith("codexhost/");
22773
+ return isRecord21(parameters) && typeof parameters.model === "string" && parameters.model.startsWith("codexhost/");
22774
22774
  }
22775
22775
  const threadId2 = threadIdFromParameters(parameters);
22776
22776
  if (threadId2 && knownExternalThreadIds.has(threadId2))
@@ -22780,7 +22780,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22780
22780
  return selectedModel !== null && (method.startsWith("thread/") || method.startsWith("turn/") || method.startsWith("review/"));
22781
22781
  };
22782
22782
  const routeThreadStart = (parameters) => {
22783
- if (!isRecord19(parameters) || parameters.ephemeral === true) {
22783
+ if (!isRecord21(parameters) || parameters.ephemeral === true) {
22784
22784
  return parameters;
22785
22785
  }
22786
22786
  return {
@@ -22813,12 +22813,12 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22813
22813
  return shouldUseBridge(method, routedParameters) ? sendBridged() : sendDirect();
22814
22814
  };
22815
22815
  const publishDraftWorkspace = (parameters) => {
22816
- if (!isRecord19(parameters) || parameters.ephemeral === true)
22816
+ if (!isRecord21(parameters) || parameters.ephemeral === true)
22817
22817
  return;
22818
22818
  const cwd = parameters.cwd;
22819
22819
  if (typeof cwd !== "string" || cwd.length === 0)
22820
22820
  return;
22821
- const drafts = isRecord19(target.__codexhostDraftWorkspacesV1) ? target.__codexhostDraftWorkspacesV1 : {};
22821
+ const drafts = isRecord21(target.__codexhostDraftWorkspacesV1) ? target.__codexhostDraftWorkspacesV1 : {};
22822
22822
  drafts[hostId2] = cwd;
22823
22823
  Object.defineProperty(target, "__codexhostDraftWorkspacesV1", {
22824
22824
  configurable: true,
@@ -22841,16 +22841,16 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22841
22841
  };
22842
22842
  const routedPrewarm = (parameters, options2) => {
22843
22843
  const routed = routeThreadStart(parameters);
22844
- const external = isRecord19(routed) && routed.ephemeral !== true && typeof routed.model === "string" && routed.model.startsWith("codexhost/");
22844
+ const external = isRecord21(routed) && routed.ephemeral !== true && typeof routed.model === "string" && routed.model.startsWith("codexhost/");
22845
22845
  const routedParameters = external ? { ...routed, codexhostPrewarm: true } : routed;
22846
22846
  const generation = prewarmGeneration;
22847
22847
  publishDraftWorkspace(routedParameters);
22848
22848
  const pending = shouldUseBridge("thread/start", routedParameters) ? routedSend("thread/start", routedParameters, options2) : options2 === void 0 ? originalPrewarm.call(bridge, routedParameters) : originalPrewarm.call(bridge, routedParameters, options2);
22849
- if (isRecord19(parameters) && parameters.ephemeral === true || typeof pending !== "object" && typeof pending !== "function" || pending === null || typeof Reflect.get(pending, "then") !== "function") {
22849
+ if (isRecord21(parameters) && parameters.ephemeral === true || typeof pending !== "object" && typeof pending !== "function" || pending === null || typeof Reflect.get(pending, "then") !== "function") {
22850
22850
  return pending;
22851
22851
  }
22852
22852
  return Promise.resolve(pending).then((result) => {
22853
- const threadId2 = external && isRecord19(result) && isRecord19(result.thread) && typeof result.thread.id === "string" ? result.thread.id : null;
22853
+ const threadId2 = external && isRecord21(result) && isRecord21(result.thread) && typeof result.thread.id === "string" ? result.thread.id : null;
22854
22854
  if (disposed || generation !== prewarmGeneration) {
22855
22855
  if (threadId2)
22856
22856
  discardExternalPrewarm(threadId2);
@@ -22866,7 +22866,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22866
22866
  bridge.prewarmThreadStart = routedPrewarm;
22867
22867
  const routedWindowMessage = (event) => {
22868
22868
  const message2 = event.data;
22869
- if (!isRecord19(message2) || message2.type !== "mcp-notification" || message2.hostId !== hostId2 || typeof message2.method !== "string") {
22869
+ if (!isRecord21(message2) || message2.type !== "mcp-notification" || message2.hostId !== hostId2 || typeof message2.method !== "string") {
22870
22870
  return;
22871
22871
  }
22872
22872
  handleOuterNotification(message2.method, message2.params);
@@ -23883,6 +23883,15 @@ var voices = /* @__PURE__ */ new Set([
23883
23883
  "sol",
23884
23884
  "cove"
23885
23885
  ]);
23886
+ function protocolId(value2) {
23887
+ return typeof value2 === "string" && value2.length > 0 && value2.length <= 256 ? value2 : void 0;
23888
+ }
23889
+ function userTurnId(event, turn) {
23890
+ return protocolId(turn.id) ?? protocolId(event.event_id);
23891
+ }
23892
+ function delegationTurnId(event, item) {
23893
+ return protocolId(item.user_bidi_turn_id) ?? protocolId(item.turn_id) ?? protocolId(item.turnId) ?? protocolId(event.turn_id) ?? (object3(event.turn) ? protocolId(event.turn.id) : void 0);
23894
+ }
23886
23895
  var ExternalVoice = class {
23887
23896
  constructor(options2) {
23888
23897
  this.options = options2;
@@ -23892,7 +23901,7 @@ var ExternalVoice = class {
23892
23901
  has(threadId2) {
23893
23902
  return this.#sessions.has(threadId2);
23894
23903
  }
23895
- async start(threadId2, params) {
23904
+ async start(threadId2, params, conversation) {
23896
23905
  if (this.has(threadId2)) throw new Error("This chat already has a voice call");
23897
23906
  if (!object3(params.transport) || params.transport.type !== "webrtc" || typeof params.transport.sdp !== "string" || !params.transport.sdp.startsWith("v=0") || params.transport.sdp.length > 256e3 || params.outputModality !== "audio") {
23898
23907
  throw new Error("External voice requires the native WebRTC audio call transport");
@@ -23900,7 +23909,12 @@ var ExternalVoice = class {
23900
23909
  if (params.voice != null && (typeof params.voice !== "string" || !voices.has(params.voice))) {
23901
23910
  throw new Error("Selected voice is unavailable for the external live-call protocol");
23902
23911
  }
23903
- const session = { controller: new AbortController(), seen: /* @__PURE__ */ new Set() };
23912
+ const session = {
23913
+ controller: new AbortController(),
23914
+ seen: /* @__PURE__ */ new Set(),
23915
+ tasks: /* @__PURE__ */ new Map(),
23916
+ pendingHandles: []
23917
+ };
23904
23918
  this.#sessions.set(threadId2, session);
23905
23919
  const requireActive = () => {
23906
23920
  if (session.controller.signal.aborted || this.#sessions.get(threadId2) !== session)
@@ -23910,6 +23924,7 @@ var ExternalVoice = class {
23910
23924
  session.creation = this.options.createCall({
23911
23925
  sdp: params.transport.sdp,
23912
23926
  ...typeof params.voice === "string" ? { voice: params.voice } : {},
23927
+ ...conversation && conversation.length > 0 ? { input: conversation } : {},
23913
23928
  signal: session.controller.signal,
23914
23929
  onEvent: (event) => {
23915
23930
  void this.#event(threadId2, session, event).catch(() => this.#fail(threadId2, session));
@@ -24004,6 +24019,7 @@ var ExternalVoice = class {
24004
24019
  return;
24005
24020
  }
24006
24021
  if (event.type === "turn.done" && object3(event.turn)) {
24022
+ const userTask = String(event.turn.role) === "user" && typeof event.turn.transcript === "string" ? this.#registerTask(session, userTurnId(event, event.turn), event.turn.transcript) : void 0;
24007
24023
  if (["user", "assistant"].includes(String(event.turn.role)) && typeof event.turn.transcript === "string") {
24008
24024
  await this.options.notify("thread/realtime/transcript/done", {
24009
24025
  threadId: threadId2,
@@ -24011,43 +24027,167 @@ var ExternalVoice = class {
24011
24027
  text: event.turn.transcript
24012
24028
  });
24013
24029
  }
24030
+ if (userTask) await this.#startTask(threadId2, session, userTask);
24014
24031
  return;
24015
24032
  }
24016
24033
  if (event.type !== "delegation.created" || !object3(event.item)) return;
24017
24034
  const item = event.item;
24018
- if (item.type !== "delegation" || item.target !== "client" || typeof item.id !== "string" || !item.id || item.id.length > 256)
24019
- return;
24020
- if (session.seen.has(item.id)) return;
24035
+ const delegationId = protocolId(item.id);
24036
+ if (item.type !== "delegation" || item.target !== "client" || !delegationId) return;
24037
+ if (session.seen.has(delegationId)) return;
24021
24038
  if (session.seen.size >= 512) {
24022
24039
  await this.#fail(threadId2, session);
24023
24040
  return;
24024
24041
  }
24025
- session.seen.add(item.id);
24026
- const text = Array.isArray(item.content) ? item.content.filter(object3).filter((part) => part.type === "input_text" && typeof part.text === "string").map((part) => part.text).join("").trim() : "";
24027
- if (!text || text.length > 32e3)
24028
- throw new Error("External voice delegation has no valid task text");
24042
+ session.seen.add(delegationId);
24043
+ const turnId = delegationTurnId(event, item);
24044
+ if (turnId) this.#attachHandle(session, turnId, delegationId);
24045
+ const text = Array.isArray(item.content) ? item.content.filter(object3).map(
24046
+ (part) => part.type === "input_text" && typeof part.text === "string" ? part.text : ""
24047
+ ).filter(Boolean).join("\n") : "";
24048
+ if (turnId && text) {
24049
+ const task = this.#registerTask(session, turnId, text);
24050
+ if (task) await this.#startTask(threadId2, session, task);
24051
+ }
24052
+ }
24053
+ #attachHandle(session, turnId, delegationId) {
24054
+ const byId = session.tasks.get(turnId);
24055
+ if (byId) {
24056
+ if (!byId.delegationId) {
24057
+ byId.delegationId = delegationId;
24058
+ if (byId.result) this.#speak(session, byId);
24059
+ }
24060
+ return;
24061
+ }
24062
+ if (session.pendingHandles.length < 512)
24063
+ session.pendingHandles.push({ id: delegationId, turnId });
24064
+ }
24065
+ #takePendingHandle(session, task) {
24066
+ if (task.delegationId) return;
24067
+ const byTurn = session.pendingHandles.findIndex((handle2) => handle2.turnId === task.id);
24068
+ if (byTurn < 0) return;
24069
+ const [handle] = session.pendingHandles.splice(byTurn, 1);
24070
+ if (handle) task.delegationId = handle.id;
24071
+ }
24072
+ #registerTask(session, turnId, text) {
24073
+ const transcript = text.trim();
24074
+ if (!transcript || transcript.length > 32e3) return;
24075
+ const id2 = turnId ?? `user-turn:${randomUUID2()}`;
24076
+ if (session.tasks.has(id2) || session.tasks.size >= 512) return;
24077
+ const task = { id: id2, text: transcript };
24078
+ session.tasks.set(id2, task);
24079
+ this.#takePendingHandle(session, task);
24080
+ return task;
24081
+ }
24082
+ async #startTask(threadId2, session, task) {
24083
+ if (session.controller.signal.aborted || this.#sessions.get(threadId2) !== session) return;
24029
24084
  let result;
24030
24085
  try {
24031
- result = await this.options.runTask(threadId2, text, session.controller.signal);
24086
+ result = await this.options.runTask(threadId2, task.text, session.controller.signal);
24032
24087
  } catch {
24033
24088
  result = "The selected agent could not complete this request. No completion is confirmed. Check the chat for its current task status.";
24034
24089
  }
24090
+ task.result = result;
24035
24091
  if (session.controller.signal.aborted || this.#sessions.get(threadId2) !== session) return;
24036
- const characters = [...result].slice(0, 8e3);
24092
+ this.#speak(session, task);
24093
+ }
24094
+ #speak(session, task) {
24095
+ const result = task.result;
24037
24096
  const call = session.call;
24038
- if (!call) return;
24097
+ if (!result || !call) return;
24098
+ const spokenFor = task.delegationId ?? null;
24099
+ if (task.spokenFor === spokenFor) return;
24100
+ task.spokenFor = spokenFor;
24101
+ const characters = [...result].slice(0, 8e3);
24102
+ const delegationId = task.delegationId;
24039
24103
  for (let offset = 0; offset < characters.length; offset += 120) {
24040
- call.send({
24041
- type: "delegation.context.append",
24042
- delegation_item_id: item.id,
24043
- channel: "speakable",
24044
- content: [{ type: "input_text", text: characters.slice(offset, offset + 120).join("") }]
24045
- });
24104
+ const chunk = characters.slice(offset, offset + 120).join("");
24105
+ call.send(
24106
+ delegationId ? {
24107
+ type: "delegation.context.append",
24108
+ delegation_item_id: delegationId,
24109
+ channel: "speakable",
24110
+ content: [{ type: "input_text", text: chunk }]
24111
+ } : {
24112
+ type: "session.context.append",
24113
+ content: [{ type: "input_text", text: chunk }]
24114
+ }
24115
+ );
24046
24116
  }
24047
24117
  }
24048
24118
  };
24049
24119
 
24120
+ // packages/host-runtime/src/external-voice-session-input.ts
24121
+ var MAX_MESSAGES = 32;
24122
+ var MAX_MESSAGE_CHARS = 2e3;
24123
+ var MAX_TOTAL_CHARS = 12e3;
24124
+ function isRecord3(value2) {
24125
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24126
+ }
24127
+ function userMessageText(item) {
24128
+ if (!Array.isArray(item.content)) return "";
24129
+ return item.content.filter(isRecord3).map((part) => part.type === "text" && typeof part.text === "string" ? part.text.trim() : "").filter((text) => text.length > 0).join("\n");
24130
+ }
24131
+ function clip(text) {
24132
+ return text.length <= MAX_MESSAGE_CHARS ? text : text.slice(0, MAX_MESSAGE_CHARS);
24133
+ }
24134
+ function liveMessage(role, text) {
24135
+ return {
24136
+ type: "message",
24137
+ role,
24138
+ content: [{ type: role === "user" ? "input_text" : "output_text", text: clip(text) }]
24139
+ };
24140
+ }
24141
+ function messageChars(message2) {
24142
+ const content = message2.content;
24143
+ if (!Array.isArray(content) || !isRecord3(content[0]) || typeof content[0].text !== "string") {
24144
+ return 0;
24145
+ }
24146
+ return content[0].text.length;
24147
+ }
24148
+ function voiceSessionInputFromTurns(turns) {
24149
+ const messages = [];
24150
+ for (const turn of turns) {
24151
+ if (!isRecord3(turn) || !Array.isArray(turn.items)) continue;
24152
+ for (const item of turn.items) {
24153
+ if (!isRecord3(item)) continue;
24154
+ if (item.type === "userMessage") {
24155
+ const text = userMessageText(item);
24156
+ if (text) messages.push(liveMessage("user", text));
24157
+ } else if (item.type === "agentMessage" && item.phase !== "commentary") {
24158
+ const text = typeof item.text === "string" ? item.text.trim() : "";
24159
+ if (text) messages.push(liveMessage("assistant", text));
24160
+ }
24161
+ }
24162
+ }
24163
+ const selected = [];
24164
+ let total = 0;
24165
+ for (const message2 of messages.slice(-MAX_MESSAGES).reverse()) {
24166
+ const size = messageChars(message2);
24167
+ if (total + size > MAX_TOTAL_CHARS) break;
24168
+ total += size;
24169
+ selected.push(message2);
24170
+ }
24171
+ return selected.reverse();
24172
+ }
24173
+
24050
24174
  // packages/host-runtime/src/external-voice-results.ts
24175
+ function isRecord4(value2) {
24176
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24177
+ }
24178
+ function speakableFromProjectedTurn(turn) {
24179
+ if (!isRecord4(turn) || !Array.isArray(turn.items)) return void 0;
24180
+ const messages = turn.items.filter(
24181
+ (item) => isRecord4(item) && item.type === "agentMessage" && typeof item.text === "string"
24182
+ );
24183
+ return speakableFromItems(messages);
24184
+ }
24185
+ function speakableFromItems(items) {
24186
+ const values = [...items];
24187
+ const finals = values.filter((item) => item.phase === "final_answer");
24188
+ const text = (finals.length ? finals : values.filter((item) => item.phase !== "commentary").slice(-1)).map((item) => item.text).join("\n").trim();
24189
+ return text.length > 0 ? text : void 0;
24190
+ }
24051
24191
  var ExternalVoiceResults = class {
24052
24192
  #pending = /* @__PURE__ */ new Map();
24053
24193
  watch(threadId2, turnId, signal) {
@@ -24067,7 +24207,7 @@ var ExternalVoiceResults = class {
24067
24207
  });
24068
24208
  });
24069
24209
  }
24070
- observe(threadId2, event) {
24210
+ observe(threadId2, event, projectedTurn) {
24071
24211
  if (event.type === "session.faulted") {
24072
24212
  for (const [turnId, pending2] of this.#pending) {
24073
24213
  if (pending2.threadId !== threadId2) continue;
@@ -24080,6 +24220,16 @@ var ExternalVoiceResults = class {
24080
24220
  if (!("turnId" in event)) return;
24081
24221
  const pending = this.#pending.get(event.turnId);
24082
24222
  if (!pending || pending.threadId !== threadId2) return;
24223
+ if (event.type === "item.started" && event.item.type === "agentMessage") {
24224
+ pending.items.set(event.item.itemId, {
24225
+ text: event.item.text,
24226
+ ...event.item.phase ? { phase: event.item.phase } : {}
24227
+ });
24228
+ }
24229
+ if (event.type === "item.updated" && event.update.type === "text.append") {
24230
+ const item = pending.items.get(event.itemId);
24231
+ if (item) item.text += event.update.text;
24232
+ }
24083
24233
  if (event.type === "item.completed" && event.snapshot.item.type === "agentMessage" && event.snapshot.outcome.status === "succeeded") {
24084
24234
  const item = event.snapshot.item;
24085
24235
  pending.items.set(item.itemId, {
@@ -24094,9 +24244,7 @@ var ExternalVoiceResults = class {
24094
24244
  pending.reject(new Error("External agent task did not complete"));
24095
24245
  return;
24096
24246
  }
24097
- const items = [...pending.items.values()];
24098
- const finals = items.filter((item) => item.phase === "final_answer");
24099
- const text = (finals.length ? finals : items.filter((item) => item.phase !== "commentary").slice(-1)).map((item) => item.text).join("\n").trim();
24247
+ const text = speakableFromItems(pending.items.values()) ?? speakableFromProjectedTurn(projectedTurn);
24100
24248
  if (!text) {
24101
24249
  pending.reject(new Error("External agent returned no spoken result"));
24102
24250
  return;
@@ -24810,7 +24958,8 @@ function configuredExternalVoiceGateway(environment) {
24810
24958
  model: typeof config2.experimental_realtime_ws_model === "string" ? config2.experimental_realtime_ws_model : "gpt-realtime",
24811
24959
  instructions: "Use natural Hong Kong Cantonese. Delegate every user question and task to the client, including simple arithmetic. The client agent owns all reasoning and task execution. Do not answer questions yourself or invent task results. Speak only verified client results; do not read private reasoning or machine identifiers.",
24812
24960
  audio: { output: { voice: input.voice ?? "cove" } },
24813
- delegation: { type: "client", ack_filler: false }
24961
+ delegation: { type: "client", ack_filler: false },
24962
+ ...input.input && input.input.length > 0 ? { initial_items: input.input } : {}
24814
24963
  })
24815
24964
  );
24816
24965
  const response = await fetch(`${url2.href.replace(/\/$/u, "")}/realtime/calls`, {
@@ -25400,20 +25549,20 @@ var CHECK_EVERY_MS = HOUR_MS;
25400
25549
  var MISSING_AFTER_MS = 6 * HOUR_MS;
25401
25550
  var FETCH_TIMEOUT_MS = 3e4;
25402
25551
  var MINIMUM_PRICED_MODELS = 1e3;
25403
- function isRecord3(value2) {
25552
+ function isRecord5(value2) {
25404
25553
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
25405
25554
  }
25406
25555
  function price(value2) {
25407
25556
  return typeof value2 === "number" && Number.isFinite(value2) && value2 >= 0 ? value2 : null;
25408
25557
  }
25409
25558
  function compactModelsDev(api) {
25410
- if (!isRecord3(api)) throw new Error("models.dev catalog must be an object");
25559
+ if (!isRecord5(api)) throw new Error("models.dev catalog must be an object");
25411
25560
  const providers = {};
25412
25561
  let count2 = 0;
25413
25562
  for (const [providerId, provider] of Object.entries(api)) {
25414
- if (!isRecord3(provider) || !isRecord3(provider.models)) continue;
25563
+ if (!isRecord5(provider) || !isRecord5(provider.models)) continue;
25415
25564
  for (const [modelId, model2] of Object.entries(provider.models)) {
25416
- if (!isRecord3(model2) || !isRecord3(model2.cost)) continue;
25565
+ if (!isRecord5(model2) || !isRecord5(model2.cost)) continue;
25417
25566
  const input = price(model2.cost.input);
25418
25567
  const output = price(model2.cost.output);
25419
25568
  if (input === null || output === null) continue;
@@ -25440,22 +25589,22 @@ function isEntry(value2) {
25440
25589
  return value2.length < 5 || value2[4] === true || typeof value2[4] === "string";
25441
25590
  }
25442
25591
  function parseModelPriceTable(value2) {
25443
- if (!isRecord3(value2) || !isRecord3(value2.providers)) return null;
25592
+ if (!isRecord5(value2) || !isRecord5(value2.providers)) return null;
25444
25593
  if (typeof value2.fetchedAtMs !== "number" || !Number.isSafeInteger(value2.fetchedAtMs)) {
25445
25594
  return null;
25446
25595
  }
25447
25596
  for (const models of Object.values(value2.providers)) {
25448
- if (!isRecord3(models) || !Object.values(models).every(isEntry)) return null;
25597
+ if (!isRecord5(models) || !Object.values(models).every(isEntry)) return null;
25449
25598
  }
25450
25599
  return value2;
25451
25600
  }
25452
25601
  function parseModelPriceOverrides(value2) {
25453
- if (!isRecord3(value2) || !isRecord3(value2.models)) {
25602
+ if (!isRecord5(value2) || !isRecord5(value2.models)) {
25454
25603
  throw new Error("Price overrides must contain a 'models' object");
25455
25604
  }
25456
25605
  const overrides = /* @__PURE__ */ new Map();
25457
25606
  for (const [key, entry] of Object.entries(value2.models)) {
25458
- if (key.length === 0 || !isRecord3(entry)) {
25607
+ if (key.length === 0 || !isRecord5(entry)) {
25459
25608
  throw new Error(`Price override '${key}' is invalid`);
25460
25609
  }
25461
25610
  for (const field of Object.keys(entry)) {
@@ -25811,7 +25960,7 @@ var ModelPriceCatalog = class {
25811
25960
  function errorMessage2(error51) {
25812
25961
  return error51 instanceof Error ? error51.message : String(error51);
25813
25962
  }
25814
- function isRecord4(value2) {
25963
+ function isRecord6(value2) {
25815
25964
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
25816
25965
  }
25817
25966
  async function readDocument(file2) {
@@ -25852,7 +26001,7 @@ async function updateModelPriceOverridesFile(file2, change) {
25852
26001
  );
25853
26002
  }
25854
26003
  const document = current.document ?? { models: {} };
25855
- const models = isRecord4(document.models) ? document.models : {};
26004
+ const models = isRecord6(document.models) ? document.models : {};
25856
26005
  const { key, price: price2, previousKey } = change;
25857
26006
  if (previousKey !== void 0 && !Object.hasOwn(models, previousKey)) {
25858
26007
  throw new ModelPriceOverridesError(`Custom price '${previousKey}' no longer exists`);
@@ -26118,7 +26267,7 @@ function rewriteDelegationMentionText(text) {
26118
26267
  const { text: stripped, mentions } = stripDelegationMentions(text);
26119
26268
  return mentions.length === 0 ? text : appendInstruction(stripped, mentions);
26120
26269
  }
26121
- function isRecord5(value2) {
26270
+ function isRecord7(value2) {
26122
26271
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
26123
26272
  }
26124
26273
  function rewriteDelegationMentionInput(input, skill) {
@@ -26126,7 +26275,7 @@ function rewriteDelegationMentionInput(input, skill) {
26126
26275
  const seen = /* @__PURE__ */ new Set();
26127
26276
  let lastTextIndex = -1;
26128
26277
  const rewritten = input.map((item, index) => {
26129
- if (!isRecord5(item) || item.type !== "text" || typeof item.text !== "string") return item;
26278
+ if (!isRecord7(item) || item.type !== "text" || typeof item.text !== "string") return item;
26130
26279
  lastTextIndex = index;
26131
26280
  const result = stripDelegationMentions(item.text);
26132
26281
  for (const mention of result.mentions) {
@@ -26138,14 +26287,14 @@ function rewriteDelegationMentionInput(input, skill) {
26138
26287
  });
26139
26288
  if (mentions.length === 0) return null;
26140
26289
  const target = rewritten[lastTextIndex];
26141
- if (isRecord5(target) && typeof target.text === "string") {
26290
+ if (isRecord7(target) && typeof target.text === "string") {
26142
26291
  rewritten[lastTextIndex] = {
26143
26292
  ...target,
26144
26293
  text: appendInstruction(target.text, mentions)
26145
26294
  };
26146
26295
  }
26147
26296
  const hasSkill = rewritten.some(
26148
- (item) => isRecord5(item) && item.type === "skill" && item.name === skill?.name
26297
+ (item) => isRecord7(item) && item.type === "skill" && item.name === skill?.name
26149
26298
  );
26150
26299
  if (skill && !hasSkill) rewritten.push({ type: "skill", name: skill.name, path: skill.path });
26151
26300
  return rewritten;
@@ -26251,11 +26400,11 @@ var usageFields = /* @__PURE__ */ new Set([
26251
26400
  "costSource",
26252
26401
  "unpricedModels"
26253
26402
  ]);
26254
- function isRecord6(value2) {
26403
+ function isRecord8(value2) {
26255
26404
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
26256
26405
  }
26257
26406
  function parseHostUsage(value2) {
26258
- if (!isRecord6(value2))
26407
+ if (!isRecord8(value2))
26259
26408
  throw new Error("Harness Usage must be an object");
26260
26409
  const keys = Object.keys(value2);
26261
26410
  if (keys.length === 0)
@@ -26301,7 +26450,7 @@ function parseHostUsage(value2) {
26301
26450
  }
26302
26451
  if (value2.sessionCacheUsage !== void 0) {
26303
26452
  const totals2 = value2.sessionCacheUsage;
26304
- if (!isRecord6(totals2) || Object.keys(totals2).some((key) => key !== "inputTokens" && key !== "cachedInputTokens") || typeof totals2.inputTokens !== "number" || !Number.isSafeInteger(totals2.inputTokens) || totals2.inputTokens < 0 || typeof totals2.cachedInputTokens !== "number" || !Number.isSafeInteger(totals2.cachedInputTokens) || totals2.cachedInputTokens < 0 || totals2.cachedInputTokens > totals2.inputTokens) {
26453
+ if (!isRecord8(totals2) || Object.keys(totals2).some((key) => key !== "inputTokens" && key !== "cachedInputTokens") || typeof totals2.inputTokens !== "number" || !Number.isSafeInteger(totals2.inputTokens) || totals2.inputTokens < 0 || typeof totals2.cachedInputTokens !== "number" || !Number.isSafeInteger(totals2.cachedInputTokens) || totals2.cachedInputTokens < 0 || totals2.cachedInputTokens > totals2.inputTokens) {
26305
26454
  throw new Error("Harness Usage 'sessionCacheUsage' must contain complete bounded token totals");
26306
26455
  }
26307
26456
  }
@@ -26357,7 +26506,7 @@ var requestFields = /* @__PURE__ */ new Set([
26357
26506
  "provider"
26358
26507
  ]);
26359
26508
  function parseHostUsageRequest(value2) {
26360
- if (!isRecord6(value2))
26509
+ if (!isRecord8(value2))
26361
26510
  throw new Error("Harness Usage request must be an object");
26362
26511
  for (const key of Object.keys(value2)) {
26363
26512
  if (!requestFields.has(key)) {
@@ -27764,7 +27913,7 @@ var TITLE_MAX_LENGTH = 150;
27764
27913
  var DESCRIPTION_MAX_LENGTH = 500;
27765
27914
  var SERVER_NAME_MAX_LENGTH = 80;
27766
27915
  var ELLIPSIS = "…";
27767
- function isRecord7(value2) {
27916
+ function isRecord9(value2) {
27768
27917
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
27769
27918
  }
27770
27919
  function boundedText(value2, field, maxLength) {
@@ -27818,7 +27967,7 @@ function responseError(message2) {
27818
27967
  function responsePersist(value2) {
27819
27968
  if (value2 === void 0 || value2 === null)
27820
27969
  return null;
27821
- if (!isRecord7(value2) || Object.keys(value2).length !== 1 || value2.persist !== "session" && value2.persist !== "always") {
27970
+ if (!isRecord9(value2) || Object.keys(value2).length !== 1 || value2.persist !== "session" && value2.persist !== "always") {
27822
27971
  throw responseError("contains malformed persist metadata");
27823
27972
  }
27824
27973
  return value2.persist;
@@ -27864,7 +28013,7 @@ function projectCodexApprovalRequest(input) {
27864
28013
  },
27865
28014
  denyResponse,
27866
28015
  parseResponse(result) {
27867
- if (!isRecord7(result) || typeof result.action !== "string") {
28016
+ if (!isRecord9(result) || typeof result.action !== "string") {
27868
28017
  throw responseError("missing action");
27869
28018
  }
27870
28019
  if (Object.keys(result).some((key) => key !== "action" && key !== "content" && key !== "_meta")) {
@@ -27872,7 +28021,7 @@ function projectCodexApprovalRequest(input) {
27872
28021
  }
27873
28022
  const selectedPersist = responsePersist(result._meta);
27874
28023
  if (result.action === "accept") {
27875
- if ("content" in result && (!isRecord7(result.content) || Object.keys(result.content).length !== 0)) {
28024
+ if ("content" in result && (!isRecord9(result.content) || Object.keys(result.content).length !== 0)) {
27876
28025
  throw responseError("contains non-empty accepted content");
27877
28026
  }
27878
28027
  if (selectedPersist === "session") {
@@ -27932,7 +28081,7 @@ function projectApprovalChoices(input) {
27932
28081
  },
27933
28082
  denyResponse,
27934
28083
  parseResponse(result) {
27935
- if (!isRecord7(result) || typeof result.action !== "string")
28084
+ if (!isRecord9(result) || typeof result.action !== "string")
27936
28085
  throw responseError("missing action");
27937
28086
  if (Object.keys(result).some((key) => !["action", "content", "_meta"].includes(key))) {
27938
28087
  throw responseError("contains unreviewed fields");
@@ -27947,7 +28096,7 @@ function projectApprovalChoices(input) {
27947
28096
  return denyResponse;
27948
28097
  }
27949
28098
  const content = result.content;
27950
- if (result.action !== "accept" || !isRecord7(content) || Object.keys(content).length !== 1 || !interaction.actions.some(({ id: id2 }) => id2 === content.actionId)) {
28099
+ if (result.action !== "accept" || !isRecord9(content) || Object.keys(content).length !== 1 || !interaction.actions.some(({ id: id2 }) => id2 === content.actionId)) {
27951
28100
  throw responseError("contains an undeclared approval choice");
27952
28101
  }
27953
28102
  return { type: "approval", actionId: content.actionId };
@@ -27956,7 +28105,7 @@ function projectApprovalChoices(input) {
27956
28105
  }
27957
28106
 
27958
28107
  // packages/protocol-core/dist/codex-question.js
27959
- function isRecord8(value2) {
28108
+ function isRecord10(value2) {
27960
28109
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
27961
28110
  }
27962
28111
  function responseError2(message2) {
@@ -28025,7 +28174,7 @@ function projectCodexQuestionRequest(input) {
28025
28174
  }
28026
28175
  },
28027
28176
  parseResponse(result) {
28028
- if (!isRecord8(result) || !isRecord8(result.answers)) {
28177
+ if (!isRecord10(result) || !isRecord10(result.answers)) {
28029
28178
  throw responseError2("missing answers object");
28030
28179
  }
28031
28180
  const rawAnswers = result.answers;
@@ -28038,7 +28187,7 @@ function projectCodexQuestionRequest(input) {
28038
28187
  const question = interaction.questions.find(({ id: id2 }) => id2 === questionId);
28039
28188
  if (!question)
28040
28189
  throw responseError2("contains an unknown Question ID");
28041
- if (!isRecord8(answerValue) || !Array.isArray(answerValue.answers)) {
28190
+ if (!isRecord10(answerValue) || !Array.isArray(answerValue.answers)) {
28042
28191
  throw responseError2("answer entry has no answers array");
28043
28192
  }
28044
28193
  const values = answerValue.answers;
@@ -28120,7 +28269,7 @@ function projectCodexThreadUsage(input) {
28120
28269
  }
28121
28270
 
28122
28271
  // packages/protocol-core/dist/codex-native-usage.js
28123
- function isRecord9(value2) {
28272
+ function isRecord11(value2) {
28124
28273
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
28125
28274
  }
28126
28275
  function nonNegativeSafeInteger(value2) {
@@ -28133,7 +28282,7 @@ function optionalReset(value2) {
28133
28282
  return nonNegativeSafeInteger(value2);
28134
28283
  }
28135
28284
  function parseRateLimitWindow(value2) {
28136
- if (!isRecord9(value2))
28285
+ if (!isRecord11(value2))
28137
28286
  return null;
28138
28287
  const usedPercent = finitePercent(value2.usedPercent);
28139
28288
  const windowDurationMins = nonNegativeSafeInteger(value2.windowDurationMins);
@@ -28144,7 +28293,7 @@ function parseRateLimitWindow(value2) {
28144
28293
  return { usedPercent, windowDurationMins, ...resetsAt !== void 0 ? { resetsAt } : {} };
28145
28294
  }
28146
28295
  function parseRateLimitCandidate(value2, options2 = {}) {
28147
- if (!isRecord9(value2))
28296
+ if (!isRecord11(value2))
28148
28297
  return null;
28149
28298
  if (options2.genericOnly && value2.limitId !== void 0 && value2.limitId !== null && value2.limitId !== "codex") {
28150
28299
  return null;
@@ -28154,16 +28303,16 @@ function parseRateLimitCandidate(value2, options2 = {}) {
28154
28303
  return primary || secondary ? { primary, secondary } : null;
28155
28304
  }
28156
28305
  function rateLimitCandidates(value2) {
28157
- if (!isRecord9(value2))
28306
+ if (!isRecord11(value2))
28158
28307
  return [];
28159
- const result = isRecord9(value2.result) ? value2.result : value2;
28160
- if (!isRecord9(result))
28308
+ const result = isRecord11(value2.result) ? value2.result : value2;
28309
+ if (!isRecord11(result))
28161
28310
  return [];
28162
28311
  const candidates = [];
28163
28312
  const base = parseRateLimitCandidate(result.rateLimits, { genericOnly: true });
28164
28313
  if (base)
28165
28314
  candidates.push(base);
28166
- const notificationParams = isRecord9(value2.params) ? value2.params : void 0;
28315
+ const notificationParams = isRecord11(value2.params) ? value2.params : void 0;
28167
28316
  const notificationSnapshot = parseRateLimitCandidate(notificationParams?.rateLimits, {
28168
28317
  genericOnly: true
28169
28318
  });
@@ -28207,14 +28356,14 @@ function parseAvailableCount(value2) {
28207
28356
  return void 0;
28208
28357
  }
28209
28358
  function rateLimitResetCreditsSummary(value2) {
28210
- if (!isRecord9(value2))
28359
+ if (!isRecord11(value2))
28211
28360
  return null;
28212
- const result = isRecord9(value2.result) ? value2.result : value2;
28213
- const fromResult = isRecord9(result) && isRecord9(result.rateLimitResetCredits) ? result.rateLimitResetCredits : null;
28361
+ const result = isRecord11(value2.result) ? value2.result : value2;
28362
+ const fromResult = isRecord11(result) && isRecord11(result.rateLimitResetCredits) ? result.rateLimitResetCredits : null;
28214
28363
  if (fromResult)
28215
28364
  return fromResult;
28216
- const params = isRecord9(value2.params) ? value2.params : void 0;
28217
- return isRecord9(params?.rateLimitResetCredits) ? params.rateLimitResetCredits : null;
28365
+ const params = isRecord11(value2.params) ? value2.params : void 0;
28366
+ return isRecord11(params?.rateLimitResetCredits) ? params.rateLimitResetCredits : null;
28218
28367
  }
28219
28368
  function observeCodexRateLimitResetCredits(value2) {
28220
28369
  const summary = rateLimitResetCreditsSummary(value2);
@@ -28226,7 +28375,7 @@ function observeCodexRateLimitResetCredits(value2) {
28226
28375
  const expiresAtUnix = [];
28227
28376
  if (Array.isArray(summary.credits)) {
28228
28377
  for (const credit of summary.credits) {
28229
- if (!isRecord9(credit))
28378
+ if (!isRecord11(credit))
28230
28379
  continue;
28231
28380
  if (credit.status !== void 0 && credit.status !== "available")
28232
28381
  continue;
@@ -28985,11 +29134,11 @@ function itemStatus(outcome) {
28985
29134
  return "inProgress";
28986
29135
  return outcome.status === "succeeded" ? "completed" : "failed";
28987
29136
  }
28988
- function isRecord10(value2) {
29137
+ function isRecord12(value2) {
28989
29138
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
28990
29139
  }
28991
29140
  function nestedString(value2, keys, preserveText = false) {
28992
- if (!isRecord10(value2))
29141
+ if (!isRecord12(value2))
28993
29142
  return void 0;
28994
29143
  for (const key of keys) {
28995
29144
  const field = value2[key];
@@ -29152,7 +29301,7 @@ function planFromTodoValue(value2) {
29152
29301
  const record4 = unwrapToolRecord(value2);
29153
29302
  if (!record4)
29154
29303
  return planFromChecklistText(typeof value2 === "string" ? value2 : null);
29155
- if (isRecord10(record4.TodosUpdated)) {
29304
+ if (isRecord12(record4.TodosUpdated)) {
29156
29305
  const nested = planFromTodoValue(record4.TodosUpdated);
29157
29306
  if (nested)
29158
29307
  return nested;
@@ -29167,7 +29316,7 @@ function planFromTodoValue(value2) {
29167
29316
  plan.push({ step: entry.trim(), status: "pending" });
29168
29317
  continue;
29169
29318
  }
29170
- if (!isRecord10(entry))
29319
+ if (!isRecord12(entry))
29171
29320
  continue;
29172
29321
  const step = nestedString(entry, ["content", "step", "text", "title", "description", "task"]);
29173
29322
  if (!step)
@@ -29222,7 +29371,7 @@ function unwrapToolRecord(value2) {
29222
29371
  }
29223
29372
  if (Array.isArray(value2))
29224
29373
  return { todos: value2 };
29225
- if (!isRecord10(value2))
29374
+ if (!isRecord12(value2))
29226
29375
  return null;
29227
29376
  for (const wrapper of ["input", "arguments", "params"]) {
29228
29377
  if (value2[wrapper] === void 0)
@@ -29339,6 +29488,18 @@ function projectItem(item, outcome, defaultCwd, includeCommandOutput = true, sen
29339
29488
  changes: projectFileChanges(item.changes),
29340
29489
  status: itemStatus(outcome)
29341
29490
  };
29491
+ case "generatedImage":
29492
+ return {
29493
+ id: item.itemId,
29494
+ type: "imageGeneration",
29495
+ status: itemStatus(outcome),
29496
+ savedPath: item.savedPath,
29497
+ result: "",
29498
+ revisedPrompt: item.revisedPrompt ?? null,
29499
+ inputImages: [],
29500
+ failure: null,
29501
+ transparentBackground: null
29502
+ };
29342
29503
  case "subagentDelegation": {
29343
29504
  const primary = item.subagents[0];
29344
29505
  const sameConfiguration = item.subagents.every((subagent) => subagent.model === primary?.model && subagent.reasoningEffort === primary?.reasoningEffort);
@@ -30132,7 +30293,7 @@ var CodexTurnProjector = class {
30132
30293
  };
30133
30294
 
30134
30295
  // packages/protocol-core/dist/thread-fork.js
30135
- function isRecord11(value2) {
30296
+ function isRecord13(value2) {
30136
30297
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
30137
30298
  }
30138
30299
  function optionalText2(params, name, options2 = {}) {
@@ -30155,7 +30316,7 @@ function optionalBoolean(params, name) {
30155
30316
  function decodeThreadForkRequest(request) {
30156
30317
  if (request.method !== "thread/fork")
30157
30318
  return null;
30158
- if (!isRecord11(request.params))
30319
+ if (!isRecord13(request.params))
30159
30320
  throw new Error("thread/fork params must be an object");
30160
30321
  const params = request.params;
30161
30322
  const threadId2 = optionalText2(params, "threadId");
@@ -30191,7 +30352,7 @@ function decodeThreadForkRequest(request) {
30191
30352
  function decodeThreadRevertRequest(request) {
30192
30353
  if (request.method !== "thread/revert")
30193
30354
  return null;
30194
- if (!isRecord11(request.params))
30355
+ if (!isRecord13(request.params))
30195
30356
  throw new Error("thread/revert params must be an object");
30196
30357
  const { threadId: threadId2, beforeTurnId } = request.params;
30197
30358
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -30205,7 +30366,7 @@ function decodeThreadRevertRequest(request) {
30205
30366
  function decodeThreadRollbackRequest(request) {
30206
30367
  if (request.method !== "thread/rollback")
30207
30368
  return null;
30208
- if (!isRecord11(request.params))
30369
+ if (!isRecord13(request.params))
30209
30370
  throw new Error("thread/rollback params must be an object");
30210
30371
  const { threadId: threadId2, numTurns } = request.params;
30211
30372
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -30306,13 +30467,13 @@ var THREAD_SOURCE_KINDS = /* @__PURE__ */ new Set([
30306
30467
  "subAgentOther",
30307
30468
  "unknown"
30308
30469
  ]);
30309
- function isRecord12(value2) {
30470
+ function isRecord14(value2) {
30310
30471
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
30311
30472
  }
30312
30473
  function paramsObject(request, method) {
30313
30474
  if (request.params === void 0 && method === "thread/list")
30314
30475
  return {};
30315
- if (!isRecord12(request.params))
30476
+ if (!isRecord14(request.params))
30316
30477
  throw new Error(`${method} params must be an object`);
30317
30478
  return request.params;
30318
30479
  }
@@ -30384,7 +30545,7 @@ function cursorPayload(value2) {
30384
30545
  };
30385
30546
  }
30386
30547
  function parseCursorPayload(value2) {
30387
- if (!isRecord12(value2) || value2.formatVersion !== 1)
30548
+ if (!isRecord14(value2) || value2.formatVersion !== 1)
30388
30549
  throw new Error("Host cursor is invalid");
30389
30550
  const { queryFingerprint: fingerprint, sortDirection: sortDirection2, officialCursor, officialDone } = value2;
30390
30551
  const { externalAnchor: externalAnchor2, externalDone } = value2;
@@ -30393,7 +30554,7 @@ function parseCursorPayload(value2) {
30393
30554
  }
30394
30555
  let anchor = null;
30395
30556
  if (externalAnchor2 !== null) {
30396
- if (!isRecord12(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
30557
+ if (!isRecord14(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
30397
30558
  throw new Error("Host cursor is invalid");
30398
30559
  }
30399
30560
  anchor = {
@@ -30431,7 +30592,7 @@ function decodeHostThreadListCursor(value2, expected) {
30431
30592
  return cursor;
30432
30593
  }
30433
30594
  function carriesHostThreadListCursor(request) {
30434
- if (request.method !== "thread/list" || !isRecord12(request.params))
30595
+ if (request.method !== "thread/list" || !isRecord14(request.params))
30435
30596
  return false;
30436
30597
  const cursor = request.params.cursor;
30437
30598
  return typeof cursor === "string" && (cursor.startsWith(HOST_CURSOR_PREFIX) || cursor.startsWith(SECTION_CURSOR_PREFIX));
@@ -30528,7 +30689,7 @@ function decodeSectionCursor(value2, queryFingerprint2) {
30528
30689
  } catch {
30529
30690
  throw new Error("thread/list cursor is invalid");
30530
30691
  }
30531
- if (!isRecord12(decoded) || decoded.formatVersion !== 1 || !Number.isSafeInteger(decoded.offset) || decoded.offset <= 0) {
30692
+ if (!isRecord14(decoded) || decoded.formatVersion !== 1 || !Number.isSafeInteger(decoded.offset) || decoded.offset <= 0) {
30532
30693
  throw new Error("thread/list cursor is invalid");
30533
30694
  }
30534
30695
  if (decoded.queryFingerprint !== queryFingerprint2) {
@@ -30592,7 +30753,7 @@ function decodeThreadMetadataUpdateRequest(request) {
30592
30753
  if (daybreakEnabled !== null)
30593
30754
  decoded.daybreakEnabled = daybreakEnabled;
30594
30755
  if (params.gitInfo !== void 0 && params.gitInfo !== null) {
30595
- if (!isRecord12(params.gitInfo)) {
30756
+ if (!isRecord14(params.gitInfo)) {
30596
30757
  throw new Error("thread/metadata/update params.gitInfo must be an object or null");
30597
30758
  }
30598
30759
  const gitInfo = {};
@@ -30612,10 +30773,10 @@ function decodeThreadMetadataUpdateRequest(request) {
30612
30773
  return decoded;
30613
30774
  }
30614
30775
  function observeDeletedProject(value2) {
30615
- if (!isRecord12(value2) || value2.method !== "project/changed" || "id" in value2)
30776
+ if (!isRecord14(value2) || value2.method !== "project/changed" || "id" in value2)
30616
30777
  return null;
30617
30778
  const params = value2.params;
30618
- if (!isRecord12(params) || params.changeType !== "deleted")
30779
+ if (!isRecord14(params) || params.changeType !== "deleted")
30619
30780
  return null;
30620
30781
  return typeof params.projectId === "string" && params.projectId.length > 0 ? params.projectId : null;
30621
30782
  }
@@ -30627,7 +30788,7 @@ function optionalCursor(value2, name) {
30627
30788
  return value2;
30628
30789
  }
30629
30790
  function decodeOfficialThreadListPage(value2) {
30630
- if (!isRecord12(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord12(row))) {
30791
+ if (!isRecord14(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord14(row))) {
30631
30792
  throw new Error("Official thread/list response is invalid");
30632
30793
  }
30633
30794
  return {
@@ -34278,7 +34439,7 @@ import { createHash as createHash7 } from "node:crypto";
34278
34439
  var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
34279
34440
  var DEFAULT_MESSAGE_LIMIT = 25;
34280
34441
  var MAX_MESSAGE_LIMIT = 100;
34281
- function isRecord13(value2) {
34442
+ function isRecord15(value2) {
34282
34443
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
34283
34444
  }
34284
34445
  function stringValue(value2) {
@@ -34287,12 +34448,12 @@ function stringValue(value2) {
34287
34448
  function textFromUserItem(item) {
34288
34449
  if (!Array.isArray(item.content)) return "";
34289
34450
  return item.content.flatMap(
34290
- (part) => isRecord13(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
34451
+ (part) => isRecord15(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
34291
34452
  ).join("\n");
34292
34453
  }
34293
34454
  function threadStatus(value2, running) {
34294
34455
  if (running) return "running";
34295
- if (isRecord13(value2)) {
34456
+ if (isRecord15(value2)) {
34296
34457
  if (value2.type === "active") return "running";
34297
34458
  }
34298
34459
  return "completed";
@@ -34309,10 +34470,10 @@ function allVisibleMessages(turns) {
34309
34470
  const turnId = stringValue(turn.id);
34310
34471
  if (!turnId || !Array.isArray(turn.items)) continue;
34311
34472
  const agentItems = turn.items.filter(
34312
- (item) => isRecord13(item) && item.type === "agentMessage"
34473
+ (item) => isRecord15(item) && item.type === "agentMessage"
34313
34474
  );
34314
34475
  for (const item of turn.items) {
34315
- if (!isRecord13(item)) continue;
34476
+ if (!isRecord15(item)) continue;
34316
34477
  const id2 = stringValue(item.id);
34317
34478
  if (!id2) continue;
34318
34479
  if (item.type === "userMessage") {
@@ -34387,7 +34548,7 @@ function projectDelegationThreadSnapshot(input) {
34387
34548
  const progress = latestTurnMessages.filter((message2) => message2.phase !== "final" && message2.text.trim()).map(({ id: id2, turnId, text }) => ({ id: id2, turnId, text }));
34388
34549
  const result = input.running ? { availability: "pending" } : final ? { availability: "available", text: final.text } : {
34389
34550
  availability: "unavailable",
34390
- ...isRecord13(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
34551
+ ...isRecord15(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
34391
34552
  };
34392
34553
  const offset = options2.view === "messages" ? decodeCursor(input.threadId, options2.cursor) : visible.length;
34393
34554
  const page = options2.view === "messages" ? [] : void 0;
@@ -37321,11 +37482,11 @@ function spawnOfficialAppServerConnection(input) {
37321
37482
  }
37322
37483
 
37323
37484
  // packages/host-runtime/src/account/codex-account-control.ts
37324
- function isRecord14(value2) {
37485
+ function isRecord16(value2) {
37325
37486
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
37326
37487
  }
37327
37488
  function currentCodexAccountFromOfficialRead(result) {
37328
- if (!isRecord14(result) || !isRecord14(result.account) || result.account.type !== "chatgpt") {
37489
+ if (!isRecord16(result) || !isRecord16(result.account) || result.account.type !== "chatgpt") {
37329
37490
  return null;
37330
37491
  }
37331
37492
  const email3 = external_exports.string().email().max(320).safeParse(result.account.email);
@@ -37361,7 +37522,7 @@ import { randomUUID as randomUUID14 } from "node:crypto";
37361
37522
  import { randomUUID as randomUUID13 } from "node:crypto";
37362
37523
  var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
37363
37524
  var MAX_RETIRED_IDS = 1024;
37364
- function isRecord15(value2) {
37525
+ function isRecord17(value2) {
37365
37526
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
37366
37527
  }
37367
37528
  var OfficialRequestBroker = class {
@@ -37404,7 +37565,7 @@ var OfficialRequestBroker = class {
37404
37565
  });
37405
37566
  }
37406
37567
  handle(value2) {
37407
- if (!isRecord15(value2) || typeof value2.id !== "string") return false;
37568
+ if (!isRecord17(value2) || typeof value2.id !== "string") return false;
37408
37569
  const pending = this.#pending.get(value2.id);
37409
37570
  if (!pending) return this.#retired.has(value2.id);
37410
37571
  clearTimeout(pending.timeout);
@@ -38165,11 +38326,11 @@ function createOwnedConnectionBackend(factory) {
38165
38326
  }
38166
38327
 
38167
38328
  // packages/host-runtime/src/route-observation.ts
38168
- function isRecord16(value2) {
38329
+ function isRecord18(value2) {
38169
38330
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
38170
38331
  }
38171
38332
  function classifyThreadPurpose(request) {
38172
- return isRecord16(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
38333
+ return isRecord18(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
38173
38334
  }
38174
38335
  var RequestRouteObservationTracker = class {
38175
38336
  #nextCreateOrdinal = 0;
@@ -38194,13 +38355,13 @@ var RequestRouteObservationTracker = class {
38194
38355
  this.#createByThreadId.set(threadId2, tracked);
38195
38356
  }
38196
38357
  bindOfficialResponse(response) {
38197
- if (!isRecord16(response) || !("id" in response)) return;
38358
+ if (!isRecord18(response) || !("id" in response)) return;
38198
38359
  const tracked = this.#pendingByRequestId.get(response.id);
38199
38360
  if (!tracked) return;
38200
38361
  this.#pendingByRequestId.delete(response.id);
38201
38362
  const result = response.result;
38202
- const thread = isRecord16(result) ? result.thread : null;
38203
- if (isRecord16(thread) && typeof thread.id === "string") {
38363
+ const thread = isRecord18(result) ? result.thread : null;
38364
+ if (isRecord18(thread) && typeof thread.id === "string") {
38204
38365
  this.#createByThreadId.set(thread.id, tracked);
38205
38366
  }
38206
38367
  }
@@ -38418,11 +38579,11 @@ var OfficialThreadListError = class extends Error {
38418
38579
  }
38419
38580
  rpcError;
38420
38581
  };
38421
- function isRecord17(value2) {
38582
+ function isRecord19(value2) {
38422
38583
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
38423
38584
  }
38424
38585
  function officialThreadListPageFromResponse(response) {
38425
- if (isRecord17(response.error)) {
38586
+ if (isRecord19(response.error)) {
38426
38587
  if (!Number.isSafeInteger(response.error.code) || typeof response.error.message !== "string") {
38427
38588
  throw new Error("Official thread/list error response is invalid");
38428
38589
  }
@@ -38987,14 +39148,14 @@ var THREAD_USAGE_UPDATED_METHOD = "codexhost/thread/usage/updated";
38987
39148
  function delay4(milliseconds) {
38988
39149
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
38989
39150
  }
38990
- function isRecord18(value2) {
39151
+ function isRecord20(value2) {
38991
39152
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
38992
39153
  }
38993
39154
  function officialThreadBusy(thread) {
38994
- if (thread && isRecord18(thread.status) && thread.status.type === "active") return true;
39155
+ if (thread && isRecord20(thread.status) && thread.status.type === "active") return true;
38995
39156
  const turns = thread && Array.isArray(thread.turns) ? thread.turns : [];
38996
39157
  const latestTurn = turns.at(-1);
38997
- return isRecord18(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running");
39158
+ return isRecord20(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running");
38998
39159
  }
38999
39160
  function errorMessage4(error51) {
39000
39161
  return error51 instanceof Error ? error51.message : String(error51);
@@ -39101,15 +39262,15 @@ function classifyCreateRequestRoute(request) {
39101
39262
  };
39102
39263
  }
39103
39264
  function routingParams(request) {
39104
- return isRecord18(request.params) ? request.params : {};
39265
+ return isRecord20(request.params) ? request.params : {};
39105
39266
  }
39106
39267
  function requestObject(request) {
39107
- if (!isRecord18(request.params)) throw new Error(`${request.method} params must be an object`);
39268
+ if (!isRecord20(request.params)) throw new Error(`${request.method} params must be an object`);
39108
39269
  return request.params;
39109
39270
  }
39110
39271
  function requestText(params) {
39111
39272
  if (!Array.isArray(params.input)) throw new Error("turn/start input must be an array");
39112
- const text = params.input.filter((item) => isRecord18(item) && item.type === "text").map((item) => item.text).filter((value2) => typeof value2 === "string").join("\n");
39273
+ const text = params.input.filter((item) => isRecord20(item) && item.type === "text").map((item) => item.text).filter((value2) => typeof value2 === "string").join("\n");
39113
39274
  if (!text) throw new Error("turn/start must contain text input");
39114
39275
  return text;
39115
39276
  }
@@ -39544,19 +39705,19 @@ var AppServerHost = class {
39544
39705
  for (const resolve of waiters) resolve();
39545
39706
  }
39546
39707
  #observeOfficialTurnStartResponse(value2) {
39547
- if (!isRecord18(value2) || !("id" in value2)) return;
39708
+ if (!isRecord20(value2) || !("id" in value2)) return;
39548
39709
  const threadId2 = this.#pendingOfficialTurnStarts.get(value2.id);
39549
39710
  if (!threadId2) return;
39550
39711
  this.#pendingOfficialTurnStarts.delete(value2.id);
39551
- const result = isRecord18(value2.result) ? value2.result : null;
39552
- const turn = result && isRecord18(result.turn) ? result.turn : null;
39712
+ const result = isRecord20(value2.result) ? value2.result : null;
39713
+ const turn = result && isRecord20(result.turn) ? result.turn : null;
39553
39714
  if (turn && typeof turn.id === "string") {
39554
39715
  this.#activeOfficialTurns.set(threadId2, turn.id);
39555
39716
  }
39556
39717
  this.#signalActiveWorkChanged();
39557
39718
  }
39558
39719
  #takeConsoleReply(value2) {
39559
- if (!isRecord18(value2) || typeof value2.id !== "string") return false;
39720
+ if (!isRecord20(value2) || typeof value2.id !== "string") return false;
39560
39721
  const reply2 = this.#consoleReplies.get(value2.id);
39561
39722
  if (!reply2) return false;
39562
39723
  this.#consoleReplies.delete(value2.id);
@@ -39602,10 +39763,10 @@ var AppServerHost = class {
39602
39763
  );
39603
39764
  try {
39604
39765
  const message2 = await reply2;
39605
- if (isRecord18(message2) && "result" in message2) {
39766
+ if (isRecord20(message2) && "result" in message2) {
39606
39767
  return { result: message2.result ?? null };
39607
39768
  }
39608
- const error51 = isRecord18(message2) && isRecord18(message2.error) ? message2.error : void 0;
39769
+ const error51 = isRecord20(message2) && isRecord20(message2.error) ? message2.error : void 0;
39609
39770
  return {
39610
39771
  error: {
39611
39772
  code: typeof error51?.code === "number" ? error51.code : -32603,
@@ -39631,7 +39792,7 @@ var AppServerHost = class {
39631
39792
  this.#diagnose(error51);
39632
39793
  continue;
39633
39794
  }
39634
- if (isRecord18(parsed2) && parsed2.method === "initialized" && !("id" in parsed2)) {
39795
+ if (isRecord20(parsed2) && parsed2.method === "initialized" && !("id" in parsed2)) {
39635
39796
  continue;
39636
39797
  }
39637
39798
  if (await this.#handleDesktopApprovalResponse(parsed2)) continue;
@@ -39653,7 +39814,7 @@ var AppServerHost = class {
39653
39814
  const options2 = this.#observedSessionUsage.requestOptions("initialize", params);
39654
39815
  const nativeParams = options2 ? { ...params, ...options2 } : params;
39655
39816
  const response = await this.#officialRuntime.initializeProtocol(nativeParams);
39656
- if (!isRecord18(response.error)) this.#observedSessionUsage.initialized(nativeParams);
39817
+ if (!isRecord20(response.error)) this.#observedSessionUsage.initialized(nativeParams);
39657
39818
  await this.#writer.json({ ...response, id: request.id });
39658
39819
  this.#nativeAccountObserver?.initialized(nativeGeneration);
39659
39820
  } catch (error51) {
@@ -39661,7 +39822,7 @@ var AppServerHost = class {
39661
39822
  }
39662
39823
  continue;
39663
39824
  }
39664
- const threadId2 = isRecord18(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
39825
+ const threadId2 = isRecord20(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
39665
39826
  this.#dispatchDesktopRequest(
39666
39827
  () => this.#desktopRequests.run(
39667
39828
  threadId2,
@@ -39709,7 +39870,7 @@ var AppServerHost = class {
39709
39870
  for (const guard of this.#replyGuards.get(id2) ?? []) guard.answered = true;
39710
39871
  }
39711
39872
  #noteDesktopReply(value2) {
39712
- if (isRecord18(value2) && "id" in value2 && !("method" in value2)) {
39873
+ if (isRecord20(value2) && "id" in value2 && !("method" in value2)) {
39713
39874
  this.#markDesktopRequestAnswered(value2.id);
39714
39875
  }
39715
39876
  }
@@ -40222,7 +40383,7 @@ var AppServerHost = class {
40222
40383
  return;
40223
40384
  }
40224
40385
  if (request.method === "thread/fork") {
40225
- const params = isRecord18(request.params) ? request.params : {};
40386
+ const params = isRecord20(request.params) ? request.params : {};
40226
40387
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
40227
40388
  if (resolution.kind === "error") {
40228
40389
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -40243,7 +40404,7 @@ var AppServerHost = class {
40243
40404
  }
40244
40405
  }
40245
40406
  if (request.method === "thread/revert") {
40246
- const params = isRecord18(request.params) ? request.params : {};
40407
+ const params = isRecord20(request.params) ? request.params : {};
40247
40408
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
40248
40409
  if (resolution.kind === "error") {
40249
40410
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -40264,7 +40425,7 @@ var AppServerHost = class {
40264
40425
  }
40265
40426
  }
40266
40427
  if (request.method === "thread/rollback") {
40267
- const params = isRecord18(request.params) ? request.params : {};
40428
+ const params = isRecord20(request.params) ? request.params : {};
40268
40429
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
40269
40430
  if (resolution.kind === "error") {
40270
40431
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -40422,7 +40583,7 @@ var AppServerHost = class {
40422
40583
  return;
40423
40584
  }
40424
40585
  }
40425
- if (request.method === "thread/backgroundTerminals/clean" && isRecord18(request.params) && typeof request.params.threadId === "string") {
40586
+ if (request.method === "thread/backgroundTerminals/clean" && isRecord20(request.params) && typeof request.params.threadId === "string") {
40426
40587
  const location = await this.#locateExternalThread(request.params.threadId);
40427
40588
  if (await this.#writeResolutionError(request, location)) return;
40428
40589
  if (location.kind === "external") {
@@ -40430,7 +40591,7 @@ var AppServerHost = class {
40430
40591
  return;
40431
40592
  }
40432
40593
  }
40433
- if (request.method.startsWith("thread/realtime/") && isRecord18(request.params) && typeof request.params.threadId === "string") {
40594
+ if (request.method.startsWith("thread/realtime/") && isRecord20(request.params) && typeof request.params.threadId === "string") {
40434
40595
  const resolution = await this.#resolveExternalThread(request.params.threadId);
40435
40596
  if (await this.#writeResolutionError(request, resolution)) return;
40436
40597
  if (resolution.kind === "external") {
@@ -40442,7 +40603,7 @@ var AppServerHost = class {
40442
40603
  return;
40443
40604
  }
40444
40605
  }
40445
- if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord18(request.params) && typeof request.params.threadId === "string") {
40606
+ if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord20(request.params) && typeof request.params.threadId === "string") {
40446
40607
  const location = await this.#locateExternalThread(request.params.threadId);
40447
40608
  if (await this.#writeResolutionError(request, location)) return;
40448
40609
  if (location.kind === "external") {
@@ -40461,10 +40622,10 @@ var AppServerHost = class {
40461
40622
  /** Native Codex Turns: turn `#` delegation chips into an explicit Skill-backed request. */
40462
40623
  async #rewriteOfficialDelegationMentions(request, frame) {
40463
40624
  if (request.method !== "turn/start" && request.method !== "turn/steer") return frame;
40464
- if (!isRecord18(request.params) || !Array.isArray(request.params.input)) return frame;
40625
+ if (!isRecord20(request.params) || !Array.isArray(request.params.input)) return frame;
40465
40626
  const input = request.params.input;
40466
40627
  if (!input.some(
40467
- (item) => isRecord18(item) && typeof item.text === "string" && item.text.includes(DELEGATION_MENTION_PATH_PREFIX)
40628
+ (item) => isRecord20(item) && typeof item.text === "string" && item.text.includes(DELEGATION_MENTION_PATH_PREFIX)
40468
40629
  )) {
40469
40630
  return frame;
40470
40631
  }
@@ -40477,7 +40638,7 @@ var AppServerHost = class {
40477
40638
  }
40478
40639
  async #forwardOfficialNonRequest(value2, frame) {
40479
40640
  if (this.#options.externalOnly) return;
40480
- const response = isRecord18(value2) ? value2 : null;
40641
+ const response = isRecord20(value2) ? value2 : null;
40481
40642
  const request = response && (typeof response.id === "string" || typeof response.id === "number") ? this.#officialServerRequests.get(response.id) : null;
40482
40643
  if (request !== void 0 && response) {
40483
40644
  this.#officialServerRequests.delete(response.id);
@@ -40497,13 +40658,13 @@ var AppServerHost = class {
40497
40658
  return;
40498
40659
  }
40499
40660
  try {
40500
- const options2 = isRecord18(request.params) ? this.#observedSessionUsage.requestOptions(request.method, request.params) : null;
40661
+ const options2 = isRecord20(request.params) ? this.#observedSessionUsage.requestOptions(request.method, request.params) : null;
40501
40662
  if (options2) {
40502
40663
  const original = parseJsonFrame(frame);
40503
- if (isRecord18(original))
40664
+ if (isRecord20(original))
40504
40665
  frame = encodeJsonFrame({
40505
40666
  ...original,
40506
- params: { ...isRecord18(original.params) ? original.params : {}, ...options2 }
40667
+ params: { ...isRecord20(original.params) ? original.params : {}, ...options2 }
40507
40668
  });
40508
40669
  }
40509
40670
  await this.#officialRuntime.sendFrame(frame);
@@ -40527,7 +40688,7 @@ var AppServerHost = class {
40527
40688
  const observedAtMs = Date.now();
40528
40689
  this.#observeOfficialTurnStartResponse(parsed2);
40529
40690
  let forwarded = parsed2;
40530
- if (isRecord18(parsed2) && typeof parsed2.method === "string" && "id" in parsed2) {
40691
+ if (isRecord20(parsed2) && typeof parsed2.method === "string" && "id" in parsed2) {
40531
40692
  const originalId = parsed2.id;
40532
40693
  if (typeof originalId === "string" || typeof originalId === "number") {
40533
40694
  const forwardedId = `codexhost:official:${++this.#nextOfficialServerRequestId}`;
@@ -40535,7 +40696,7 @@ var AppServerHost = class {
40535
40696
  forwarded = { ...parsed2, id: forwardedId };
40536
40697
  }
40537
40698
  }
40538
- const accountScopedNotification = isRecord18(parsed2) && typeof parsed2.method === "string" && (parsed2.method === "account/updated" || parsed2.method.startsWith("account/rateLimits/"));
40699
+ const accountScopedNotification = isRecord20(parsed2) && typeof parsed2.method === "string" && (parsed2.method === "account/updated" || parsed2.method.startsWith("account/rateLimits/"));
40539
40700
  if (accountScopedNotification) {
40540
40701
  if (parsed2.method === "account/updated") this.#officialRateLimits.reset(input.accountId);
40541
40702
  }
@@ -40547,7 +40708,7 @@ var AppServerHost = class {
40547
40708
  this.#diagnose(error51);
40548
40709
  }
40549
40710
  this.#routeObservationTracker.bindOfficialResponse(parsed2);
40550
- const privateTelemetry = isRecord18(parsed2) && typeof parsed2.method === "string" && !("id" in parsed2) && !this.#observedSessionUsage.shouldForwardNotification(parsed2);
40711
+ const privateTelemetry = isRecord20(parsed2) && typeof parsed2.method === "string" && !("id" in parsed2) && !this.#observedSessionUsage.shouldForwardNotification(parsed2);
40551
40712
  if (!privateTelemetry) {
40552
40713
  if (forwarded === parsed2) await this.#writer.frame(input.frame);
40553
40714
  else await this.#writer.json(forwarded);
@@ -40613,10 +40774,10 @@ var AppServerHost = class {
40613
40774
  }
40614
40775
  }
40615
40776
  async #observeOfficialTurnLifecycle(value2) {
40616
- if (!isRecord18(value2) || !isRecord18(value2.params)) return;
40777
+ if (!isRecord20(value2) || !isRecord20(value2.params)) return;
40617
40778
  const params = value2.params;
40618
40779
  if (value2.method === "turn/started" && typeof params.threadId === "string") {
40619
- const turn = isRecord18(params.turn) ? params.turn : null;
40780
+ const turn = isRecord20(params.turn) ? params.turn : null;
40620
40781
  if (turn && typeof turn.id === "string") {
40621
40782
  this.#forgetPendingOfficialTurnStarts(params.threadId);
40622
40783
  this.#activeOfficialTurns.set(params.threadId, turn.id);
@@ -40629,7 +40790,7 @@ var AppServerHost = class {
40629
40790
  const delegation = await this.#repository.getDelegationByChild(
40630
40791
  hostThreadIdSchema.parse(params.threadId)
40631
40792
  );
40632
- const turn = isRecord18(params.turn) ? params.turn : null;
40793
+ const turn = isRecord20(params.turn) ? params.turn : null;
40633
40794
  const status2 = turn?.status === "failed" ? "failed" : turn?.status === "interrupted" || turn?.status === "cancelled" ? "interrupted" : "completed";
40634
40795
  if (this.#pendingOfficialDelegationThreads.has(params.threadId)) {
40635
40796
  this.#pendingOfficialTerminalStatuses.set(params.threadId, status2);
@@ -40662,28 +40823,28 @@ var AppServerHost = class {
40662
40823
  }
40663
40824
  async #readOfficialThreadCwd(threadId2) {
40664
40825
  const response = await this.#requestOfficial("thread/read", { threadId: threadId2 });
40665
- if (isRecord18(response.error)) return void 0;
40666
- const result = isRecord18(response.result) ? response.result : null;
40667
- const thread = result && isRecord18(result.thread) ? result.thread : null;
40826
+ if (isRecord20(response.error)) return void 0;
40827
+ const result = isRecord20(response.result) ? response.result : null;
40828
+ const thread = result && isRecord20(result.thread) ? result.thread : null;
40668
40829
  return thread && typeof thread.cwd === "string" && thread.cwd.trim() ? thread.cwd : void 0;
40669
40830
  }
40670
40831
  async #inspectOfficialDelegationTarget(input) {
40671
40832
  const response = await this.#requestOfficial("model/list", {});
40672
- if (isRecord18(response.error)) {
40833
+ if (isRecord20(response.error)) {
40673
40834
  throw new DelegationControlError(
40674
40835
  "DELEGATION_FAILED",
40675
40836
  typeof response.error.message === "string" ? response.error.message : "Official Model catalog could not be read"
40676
40837
  );
40677
40838
  }
40678
- const result = isRecord18(response.result) ? response.result : null;
40839
+ const result = isRecord20(response.result) ? response.result : null;
40679
40840
  const data = result && Array.isArray(result.data) ? result.data : [];
40680
40841
  const thinkingById = /* @__PURE__ */ new Map();
40681
40842
  const models = data.flatMap((candidate) => {
40682
- if (!isRecord18(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
40843
+ if (!isRecord20(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
40683
40844
  return [];
40684
40845
  }
40685
40846
  const supportedThinkingOptionIds = Array.isArray(candidate.supportedReasoningEfforts) ? candidate.supportedReasoningEfforts.flatMap((option) => {
40686
- if (!isRecord18(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
40847
+ if (!isRecord20(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
40687
40848
  return [];
40688
40849
  }
40689
40850
  const id2 = harnessThinkingOptionIdSchema.safeParse(option.reasoningEffort);
@@ -40703,9 +40864,9 @@ var AppServerHost = class {
40703
40864
  ];
40704
40865
  });
40705
40866
  const defaultEntry = data.find(
40706
- (candidate) => isRecord18(candidate) && candidate.isDefault === true
40867
+ (candidate) => isRecord20(candidate) && candidate.isDefault === true
40707
40868
  );
40708
- const defaultModel = isRecord18(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
40869
+ const defaultModel = isRecord20(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
40709
40870
  return {
40710
40871
  harnessId: input.harnessId,
40711
40872
  inspection: {
@@ -40811,8 +40972,8 @@ var AppServerHost = class {
40811
40972
  ephemeral: false,
40812
40973
  historyMode: "paginated"
40813
40974
  });
40814
- const startedResult = isRecord18(started.result) ? started.result : null;
40815
- const thread = startedResult && isRecord18(startedResult.thread) ? startedResult.thread : null;
40975
+ const startedResult = isRecord20(started.result) ? started.result : null;
40976
+ const thread = startedResult && isRecord20(startedResult.thread) ? startedResult.thread : null;
40816
40977
  const threadId2 = thread && typeof thread.id === "string" ? thread.id : null;
40817
40978
  if (!threadId2) throw new Error("Official thread/start returned no Thread identity");
40818
40979
  this.#pendingOfficialDelegationThreads.add(threadId2);
@@ -40824,8 +40985,8 @@ var AppServerHost = class {
40824
40985
  ...nativeModelId ? { model: nativeModelId } : {},
40825
40986
  ...input.thinkingOptionId ? { effort: input.thinkingOptionId } : {}
40826
40987
  });
40827
- const turnResult = isRecord18(turn.result) ? turn.result : null;
40828
- const turnValue = turnResult && isRecord18(turnResult.turn) ? turnResult.turn : null;
40988
+ const turnResult = isRecord20(turn.result) ? turn.result : null;
40989
+ const turnValue = turnResult && isRecord20(turnResult.turn) ? turnResult.turn : null;
40829
40990
  const parsedTurnId = turnValue && typeof turnValue.id === "string" ? turnValue.id : null;
40830
40991
  if (!parsedTurnId) throw new Error("Official turn/start returned no Turn identity");
40831
40992
  turnId = parsedTurnId;
@@ -40895,11 +41056,11 @@ var AppServerHost = class {
40895
41056
  threadId: input.threadId,
40896
41057
  includeTurns: true
40897
41058
  });
40898
- if (isRecord18(current.error)) throw officialThreadReadError(current.error);
40899
- if (!isRecord18(current.result)) {
41059
+ if (isRecord20(current.error)) throw officialThreadReadError(current.error);
41060
+ if (!isRecord20(current.result)) {
40900
41061
  throw new DelegationControlError("INTERNAL_ERROR", "Official Thread read returned no result");
40901
41062
  }
40902
- const currentThread = isRecord18(current.result.thread) ? current.result.thread : null;
41063
+ const currentThread = isRecord20(current.result.thread) ? current.result.thread : null;
40903
41064
  if (officialThreadBusy(currentThread)) {
40904
41065
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
40905
41066
  }
@@ -40907,14 +41068,14 @@ var AppServerHost = class {
40907
41068
  threadId: input.threadId,
40908
41069
  excludeTurns: true
40909
41070
  });
40910
- if (isRecord18(resumed.error) || !isRecord18(resumed.result)) {
41071
+ if (isRecord20(resumed.error) || !isRecord20(resumed.result)) {
40911
41072
  throw new DelegationControlError(
40912
41073
  "DELEGATION_FAILED",
40913
- isRecord18(resumed.error) && typeof resumed.error.message === "string" ? resumed.error.message : "Official Thread resume failed",
41074
+ isRecord20(resumed.error) && typeof resumed.error.message === "string" ? resumed.error.message : "Official Thread resume failed",
40914
41075
  { notStarted: true }
40915
41076
  );
40916
41077
  }
40917
- const resumedThread = isRecord18(resumed.result.thread) ? resumed.result.thread : null;
41078
+ const resumedThread = isRecord20(resumed.result.thread) ? resumed.result.thread : null;
40918
41079
  if (!resumedThread || resumedThread.id !== input.threadId) {
40919
41080
  throw new DelegationControlError(
40920
41081
  "DELEGATION_FAILED",
@@ -40925,7 +41086,7 @@ var AppServerHost = class {
40925
41086
  if (officialThreadBusy(resumedThread)) {
40926
41087
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
40927
41088
  }
40928
- if (!isRecord18(resumedThread.status) || resumedThread.status.type !== "idle") {
41089
+ if (!isRecord20(resumedThread.status) || resumedThread.status.type !== "idle") {
40929
41090
  throw new DelegationControlError(
40930
41091
  "DELEGATION_FAILED",
40931
41092
  "Official Thread is not idle after resume",
@@ -40936,15 +41097,15 @@ var AppServerHost = class {
40936
41097
  threadId: input.threadId,
40937
41098
  input: [{ type: "text", text: input.message }]
40938
41099
  });
40939
- if (isRecord18(response.error)) {
41100
+ if (isRecord20(response.error)) {
40940
41101
  throw new DelegationControlError(
40941
41102
  "DELEGATION_FAILED",
40942
41103
  typeof response.error.message === "string" ? response.error.message : "Turn start failed",
40943
41104
  { notStarted: true }
40944
41105
  );
40945
41106
  }
40946
- const result = isRecord18(response.result) ? response.result : null;
40947
- const turn = result && isRecord18(result.turn) ? result.turn : null;
41107
+ const result = isRecord20(response.result) ? response.result : null;
41108
+ const turn = result && isRecord20(result.turn) ? result.turn : null;
40948
41109
  const turnId = turn && typeof turn.id === "string" ? turn.id : null;
40949
41110
  if (!turnId) throw new Error("Official turn/start returned no Turn identity");
40950
41111
  this.#activeOfficialTurns.set(input.threadId, turnId);
@@ -40966,13 +41127,13 @@ var AppServerHost = class {
40966
41127
  threadId: input.threadId,
40967
41128
  includeTurns: true
40968
41129
  });
40969
- if (isRecord18(current.error) || !isRecord18(current.result)) {
41130
+ if (isRecord20(current.error) || !isRecord20(current.result)) {
40970
41131
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
40971
41132
  }
40972
- const currentThread = isRecord18(current.result.thread) ? current.result.thread : null;
41133
+ const currentThread = isRecord20(current.result.thread) ? current.result.thread : null;
40973
41134
  const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
40974
41135
  const latestTurn = currentTurns.at(-1);
40975
- if (isRecord18(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
41136
+ if (isRecord20(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
40976
41137
  turnId = latestTurn.id;
40977
41138
  this.#activeOfficialTurns.set(input.threadId, turnId);
40978
41139
  } else {
@@ -40983,7 +41144,7 @@ var AppServerHost = class {
40983
41144
  threadId: input.threadId,
40984
41145
  turnId
40985
41146
  });
40986
- if (isRecord18(response.error)) {
41147
+ if (isRecord20(response.error)) {
40987
41148
  throw new DelegationControlError(
40988
41149
  "DELEGATION_FAILED",
40989
41150
  typeof response.error.message === "string" ? response.error.message : "Turn cancel failed"
@@ -40996,13 +41157,13 @@ var AppServerHost = class {
40996
41157
  threadId: input.threadId,
40997
41158
  includeTurns: true
40998
41159
  });
40999
- if (isRecord18(response.error)) throw officialThreadReadError(response.error);
41000
- const result = isRecord18(response.result) ? response.result : null;
41001
- const thread = result && isRecord18(result.thread) ? result.thread : null;
41160
+ if (isRecord20(response.error)) throw officialThreadReadError(response.error);
41161
+ const result = isRecord20(response.result) ? response.result : null;
41162
+ const thread = result && isRecord20(result.thread) ? result.thread : null;
41002
41163
  if (!thread)
41003
41164
  throw new DelegationControlError("INTERNAL_ERROR", "Official Thread read returned no Thread");
41004
- const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord18(turn)) : [];
41005
- const running = this.#activeOfficialTurns.has(input.threadId) || isRecord18(thread.status) && thread.status.type === "active";
41165
+ const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord20(turn)) : [];
41166
+ const running = this.#activeOfficialTurns.has(input.threadId) || isRecord20(thread.status) && thread.status.type === "active";
41006
41167
  const snapshot2 = projectDelegationThreadSnapshot({
41007
41168
  threadId: input.threadId,
41008
41169
  harnessId: "codex",
@@ -41050,7 +41211,7 @@ var AppServerHost = class {
41050
41211
  threads: result.data.flatMap((entry) => {
41051
41212
  if (typeof entry.id !== "string") return [];
41052
41213
  const record4 = records.find((candidate) => candidate.hostThreadId === entry.id);
41053
- const status2 = isRecord18(entry.status) && entry.status.type === "active" ? "running" : "completed";
41214
+ const status2 = isRecord20(entry.status) && entry.status.type === "active" ? "running" : "completed";
41054
41215
  return [
41055
41216
  {
41056
41217
  threadId: entry.id,
@@ -41217,7 +41378,7 @@ var AppServerHost = class {
41217
41378
  const exists2 = await this.#requestOfficial("project/read", {
41218
41379
  projectId: update.projectId
41219
41380
  }).then(
41220
- (response) => !isRecord18(response.error) && isRecord18(response.result) && isRecord18(response.result.project) && response.result.project.id === update.projectId,
41381
+ (response) => !isRecord20(response.error) && isRecord20(response.result) && isRecord20(response.result.project) && response.result.project.id === update.projectId,
41221
41382
  () => false
41222
41383
  );
41223
41384
  if (!exists2) {
@@ -42407,10 +42568,10 @@ var AppServerHost = class {
42407
42568
  ...typeof params.serviceTier === "string" ? { serviceTier: params.serviceTier } : {}
42408
42569
  });
42409
42570
  try {
42410
- if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord18(params.initialTurnsPage)) {
42571
+ if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord20(params.initialTurnsPage)) {
42411
42572
  throw new ExternalHistoryRequestError("initialTurnsPage must be an object");
42412
42573
  }
42413
- const initialPageParams = isRecord18(params.initialTurnsPage) ? params.initialTurnsPage : null;
42574
+ const initialPageParams = isRecord20(params.initialTurnsPage) ? params.initialTurnsPage : null;
42414
42575
  const initialTurnsPage = initialPageParams ? listExternalTurns(turns, initialPageParams) : null;
42415
42576
  const paginated = thread.record.historyMode === "paginated";
42416
42577
  const turnsBackwardsCursor = paginated ? listExternalTurns(turns, { limit: 1, itemsView: "notLoaded" }).backwardsCursor : null;
@@ -42506,7 +42667,11 @@ var AppServerHost = class {
42506
42667
  async #handleExternalVoiceRequest(request, thread) {
42507
42668
  try {
42508
42669
  if (request.method === "thread/realtime/start") {
42509
- await this.#externalVoice.start(thread.id, requestObject(request));
42670
+ await this.#externalVoice.start(
42671
+ thread.id,
42672
+ requestObject(request),
42673
+ voiceSessionInputFromTurns(thread.turns)
42674
+ );
42510
42675
  } else if (request.method === "thread/realtime/stop") {
42511
42676
  await this.#externalVoice.stop(thread.id);
42512
42677
  } else {
@@ -42751,9 +42916,7 @@ var AppServerHost = class {
42751
42916
  if (typeof requestedTurnId === "string")
42752
42917
  this.#externalSteering.interrupt(thread.id, requestedTurnId);
42753
42918
  if (typeof requestedTurnId !== "string" || !thread.running || thread.activeTurnId !== requestedTurnId) {
42754
- await this.#writer.json(
42755
- rpcError(request, -32074, "External turn/interrupt must reference the active Turn")
42756
- );
42919
+ await this.#writer.json(rpcEnvelope(request, { result: {} }));
42757
42920
  return;
42758
42921
  }
42759
42922
  const turnId = thread.activeTurnId;
@@ -43038,7 +43201,11 @@ var AppServerHost = class {
43038
43201
  thread.projectedTurns.delete(event.turnId);
43039
43202
  }
43040
43203
  for (const message2 of result.messages) await this.#writer.json(message2);
43041
- this.#externalVoiceResults.observe(thread.id, event);
43204
+ this.#externalVoiceResults.observe(
43205
+ thread.id,
43206
+ event,
43207
+ event.type === "turn.completed" ? result.completedTurn : void 0
43208
+ );
43042
43209
  if (event.type === "turn.completed") {
43043
43210
  await this.#setThreadStatus(
43044
43211
  thread,
@@ -43083,7 +43250,7 @@ var AppServerHost = class {
43083
43250
  const previousItems = new Map(
43084
43251
  child.turns.flatMap(
43085
43252
  (turn) => Array.isArray(turn.items) ? turn.items.flatMap(
43086
- (item) => isRecord18(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
43253
+ (item) => isRecord20(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
43087
43254
  ) : []
43088
43255
  )
43089
43256
  );
@@ -43096,7 +43263,7 @@ var AppServerHost = class {
43096
43263
  for (const turn of child.turns) {
43097
43264
  if (typeof turn.id !== "string" || !Array.isArray(turn.items)) continue;
43098
43265
  const changedItems = turn.items.filter(
43099
- (item) => isRecord18(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
43266
+ (item) => isRecord20(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
43100
43267
  );
43101
43268
  if (changedItems.length > 0) {
43102
43269
  await this.#writer.json({
@@ -43228,7 +43395,7 @@ var AppServerHost = class {
43228
43395
  }
43229
43396
  }
43230
43397
  async #handleDesktopApprovalResponse(value2) {
43231
- if (!isRecord18(value2) || !isHostApprovalRequestId(value2.id)) return false;
43398
+ if (!isRecord20(value2) || !isHostApprovalRequestId(value2.id)) return false;
43232
43399
  const requestId = value2.id;
43233
43400
  const pending = this.#pendingDesktopApprovals.get(requestId);
43234
43401
  if (!pending) return true;
@@ -43357,7 +43524,7 @@ var AppServerHost = class {
43357
43524
  }
43358
43525
  }
43359
43526
  async #handleDesktopQuestionResponse(value2) {
43360
- if (!isRecord18(value2) || !isHostQuestionRequestId(value2.id)) return false;
43527
+ if (!isRecord20(value2) || !isHostQuestionRequestId(value2.id)) return false;
43361
43528
  const requestId = value2.id;
43362
43529
  const pending = this.#pendingDesktopQuestions.get(requestId);
43363
43530
  if (!pending) return true;