@opengeni/sdk 3.3.2 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/README.md +1007 -72
  2. package/dist/adapters/express.d.ts +31 -0
  3. package/dist/adapters/express.js +87 -0
  4. package/dist/adapters/express.js.map +1 -0
  5. package/dist/adapters/hono.d.ts +16 -0
  6. package/dist/adapters/hono.js +8 -0
  7. package/dist/adapters/hono.js.map +1 -0
  8. package/dist/adapters/next.d.ts +29 -0
  9. package/dist/adapters/next.js +22 -0
  10. package/dist/adapters/next.js.map +1 -0
  11. package/dist/allowance-refusal.d.ts +2 -0
  12. package/dist/allowance-refusal.js +50 -0
  13. package/dist/allowance-refusal.js.map +1 -0
  14. package/dist/app-links.d.ts +42 -0
  15. package/dist/app-links.js +66 -0
  16. package/dist/app-links.js.map +1 -0
  17. package/dist/artifact-catalog.d.ts +40 -0
  18. package/dist/artifact-client.d.ts +20 -8
  19. package/dist/artifacts.d.ts +1 -1
  20. package/dist/artifacts.js +8 -6
  21. package/dist/automations.js +8 -2
  22. package/dist/automations.js.map +1 -1
  23. package/dist/azure-live-transport.d.ts +32 -0
  24. package/dist/browser.d.ts +7 -2
  25. package/dist/browser.js +27 -5
  26. package/dist/chat/fold.d.ts +75 -0
  27. package/dist/chat/handler.d.ts +41 -0
  28. package/dist/chat/http.d.ts +67 -0
  29. package/dist/chat/ids.d.ts +34 -0
  30. package/dist/chat/index.d.ts +9 -0
  31. package/dist/chat/index.js +1369 -0
  32. package/dist/chat/index.js.map +1 -0
  33. package/dist/chat/openai.d.ts +30 -0
  34. package/dist/chat/opengeni.d.ts +129 -0
  35. package/dist/chat/types.d.ts +207 -0
  36. package/dist/chat/vercel.d.ts +49 -0
  37. package/dist/chats.d.ts +8 -0
  38. package/dist/chunk-4AHR4KGA.js +301 -0
  39. package/dist/chunk-4AHR4KGA.js.map +1 -0
  40. package/dist/chunk-6GYGMLX4.js +332 -0
  41. package/dist/chunk-6GYGMLX4.js.map +1 -0
  42. package/dist/chunk-7EWT3PV6.js +368 -0
  43. package/dist/chunk-7EWT3PV6.js.map +1 -0
  44. package/dist/chunk-FTWVVPR6.js +1665 -0
  45. package/dist/chunk-FTWVVPR6.js.map +1 -0
  46. package/dist/{chunk-VYCTL62C.js → chunk-GZQSWAKD.js} +1 -1
  47. package/dist/chunk-GZQSWAKD.js.map +1 -0
  48. package/dist/chunk-KGEABAID.js +71 -0
  49. package/dist/chunk-KGEABAID.js.map +1 -0
  50. package/dist/{chunk-YKZME56C.js → chunk-KWADQ227.js} +3 -3
  51. package/dist/{chunk-YKZME56C.js.map → chunk-KWADQ227.js.map} +1 -1
  52. package/dist/{chunk-JUS2UYRP.js → chunk-NCU5OAN7.js} +27 -2
  53. package/dist/chunk-NCU5OAN7.js.map +1 -0
  54. package/dist/{chunk-YXQX7RQT.js → chunk-OI5YLASH.js} +73 -2
  55. package/dist/chunk-OI5YLASH.js.map +1 -0
  56. package/dist/chunk-OV3POE62.js +359 -0
  57. package/dist/chunk-OV3POE62.js.map +1 -0
  58. package/dist/chunk-P7UWKORG.js +561 -0
  59. package/dist/chunk-P7UWKORG.js.map +1 -0
  60. package/dist/chunk-QGEIL4TR.js +195 -0
  61. package/dist/chunk-QGEIL4TR.js.map +1 -0
  62. package/dist/{chunk-TRNI7KEO.js → chunk-S2NLS3ES.js} +3669 -1281
  63. package/dist/chunk-S2NLS3ES.js.map +1 -0
  64. package/dist/chunk-UM4ZXXJR.js +9 -0
  65. package/dist/chunk-UM4ZXXJR.js.map +1 -0
  66. package/dist/{chunk-QT3KFVDP.js → chunk-UME3X7CP.js} +28 -32
  67. package/dist/chunk-UME3X7CP.js.map +1 -0
  68. package/dist/chunk-VT4YM4XQ.js +210 -0
  69. package/dist/chunk-VT4YM4XQ.js.map +1 -0
  70. package/dist/chunk-WSYYXONG.js +1602 -0
  71. package/dist/chunk-WSYYXONG.js.map +1 -0
  72. package/dist/{chunk-C2H7HBNP.js → chunk-WVCJRSGJ.js} +119 -14
  73. package/dist/chunk-WVCJRSGJ.js.map +1 -0
  74. package/dist/chunk-X5ITQVXE.js +15 -0
  75. package/dist/chunk-X5ITQVXE.js.map +1 -0
  76. package/dist/chunk-XA7HVIHI.js +126 -0
  77. package/dist/chunk-XA7HVIHI.js.map +1 -0
  78. package/dist/{chunk-KKRO2VCP.js → chunk-YJCHB7R3.js} +60 -12
  79. package/dist/chunk-YJCHB7R3.js.map +1 -0
  80. package/dist/chunk-YKIHNLWD.js +153 -0
  81. package/dist/chunk-YKIHNLWD.js.map +1 -0
  82. package/dist/chunk-ZDUBPV33.js +277 -0
  83. package/dist/chunk-ZDUBPV33.js.map +1 -0
  84. package/dist/client.d.ts +1068 -118
  85. package/dist/codex-realtime-controller.d.ts +13 -0
  86. package/dist/codex-realtime-controller.js +4 -2
  87. package/dist/codex-realtime-v3-wire.d.ts +3 -2
  88. package/dist/codex-realtime.d.ts +5 -1
  89. package/dist/company-brain.d.ts +1 -11
  90. package/dist/core.d.ts +7 -2
  91. package/dist/core.js +25 -6
  92. package/dist/deprecation.d.ts +47 -0
  93. package/dist/document-authority-client.d.ts +24 -2
  94. package/dist/document-authority.js +7 -5
  95. package/dist/editable-artifacts/index.d.ts +1 -1
  96. package/dist/editable-artifacts/types.d.ts +12 -2
  97. package/dist/editable-artifacts.js +19 -3
  98. package/dist/editable-artifacts.js.map +1 -1
  99. package/dist/embedding-client.d.ts +129 -0
  100. package/dist/errors.d.ts +76 -1
  101. package/dist/external-vault-receiver.d.ts +203 -0
  102. package/dist/external-vault-receiver.js +564 -0
  103. package/dist/external-vault-receiver.js.map +1 -0
  104. package/dist/feedback.d.ts +23 -0
  105. package/dist/gateway-realtime-transport.js +1 -1
  106. package/dist/github-repositories.d.ts +10 -0
  107. package/dist/github-repositories.js +36 -0
  108. package/dist/github-repositories.js.map +1 -0
  109. package/dist/index.d.ts +62 -11
  110. package/dist/index.js +557 -338
  111. package/dist/index.js.map +1 -1
  112. package/dist/insights-usage.d.ts +33 -0
  113. package/dist/insights-usage.js +7 -0
  114. package/dist/insights-usage.js.map +1 -0
  115. package/dist/interaction.d.ts +165 -71
  116. package/dist/interaction.js +2 -2
  117. package/dist/knowledge.d.ts +7 -0
  118. package/dist/knowledge.js +20 -0
  119. package/dist/knowledge.js.map +1 -0
  120. package/dist/known-tools.d.ts +4 -0
  121. package/dist/message-links.d.ts +68 -0
  122. package/dist/model-context.d.ts +68 -0
  123. package/dist/model-display.d.ts +2 -0
  124. package/dist/model-display.js +17 -0
  125. package/dist/model-display.js.map +1 -0
  126. package/dist/model-picker-order.d.ts +1 -0
  127. package/dist/model-picker-order.js +10 -0
  128. package/dist/model-picker-order.js.map +1 -0
  129. package/dist/organization-integration-policy.d.ts +26 -0
  130. package/dist/organization-integration-policy.js +26 -0
  131. package/dist/organization-integration-policy.js.map +1 -0
  132. package/dist/pr-review-client.d.ts +1 -1
  133. package/dist/pr-review.d.ts +1 -1
  134. package/dist/pr-review.js.map +1 -1
  135. package/dist/preference-registry.d.ts +1 -1
  136. package/dist/prepared-mcp-setup.d.ts +5 -0
  137. package/dist/proxy.d.ts +13 -11
  138. package/dist/realtime.d.ts +1 -1
  139. package/dist/realtime.js +253 -7
  140. package/dist/realtime.js.map +1 -1
  141. package/dist/session-history-import.d.ts +22 -0
  142. package/dist/session-history-import.js +36 -0
  143. package/dist/session-history-import.js.map +1 -0
  144. package/dist/session-list-entries.d.ts +1 -0
  145. package/dist/session-list-entries.js +7 -0
  146. package/dist/session-list-entries.js.map +1 -0
  147. package/dist/session-message-search.d.ts +53 -0
  148. package/dist/session-proxy-client.d.ts +28 -0
  149. package/dist/session-proxy.d.ts +334 -0
  150. package/dist/session-proxy.js +24 -0
  151. package/dist/session-proxy.js.map +1 -0
  152. package/dist/session-titles.d.ts +2 -28
  153. package/dist/session-usage-limits.d.ts +10 -0
  154. package/dist/session-usage-limits.js +43 -0
  155. package/dist/session-usage-limits.js.map +1 -0
  156. package/dist/shared-catalog-loader.d.ts +34 -0
  157. package/dist/site-ai.d.ts +35 -0
  158. package/dist/site-bridge-host.d.ts +112 -0
  159. package/dist/site-bridge-host.js +286 -0
  160. package/dist/site-bridge-host.js.map +1 -0
  161. package/dist/site-browser-entry.d.ts +1 -0
  162. package/dist/site-browser-runtime.gen.d.ts +1 -0
  163. package/dist/site-data.d.ts +178 -0
  164. package/dist/site-document.d.ts +5 -0
  165. package/dist/site-document.js +20 -0
  166. package/dist/site-document.js.map +1 -0
  167. package/dist/site-document.test.d.ts +1 -0
  168. package/dist/site-http.d.ts +17 -0
  169. package/dist/site-sql.d.ts +31 -0
  170. package/dist/site-tool-bridge.d.ts +57 -0
  171. package/dist/site.d.ts +186 -0
  172. package/dist/site.js +63 -0
  173. package/dist/site.js.map +1 -0
  174. package/dist/skills.d.ts +75 -0
  175. package/dist/sse.d.ts +1 -1
  176. package/dist/stream.d.ts +2 -0
  177. package/dist/tenant-workspaces.d.ts +47 -0
  178. package/dist/tenant-workspaces.js +8 -0
  179. package/dist/tenant-workspaces.js.map +1 -0
  180. package/dist/tool-auth.d.ts +87 -0
  181. package/dist/tool-auth.js +23 -0
  182. package/dist/tool-auth.js.map +1 -0
  183. package/dist/tool-display-metadata.d.ts +3 -0
  184. package/dist/tools-37DCTCNZ.js +12 -0
  185. package/dist/tools-37DCTCNZ.js.map +1 -0
  186. package/dist/tools.d.ts +81 -0
  187. package/dist/transcription.d.ts +1 -1
  188. package/dist/types.d.ts +2807 -583
  189. package/dist/usage-allowances.d.ts +36 -0
  190. package/dist/usage-allowances.js +80 -0
  191. package/dist/usage-allowances.js.map +1 -0
  192. package/dist/vault-types.d.ts +324 -0
  193. package/dist/vaults-api.d.ts +65 -0
  194. package/dist/workspace-artifacts.d.ts +47 -5
  195. package/dist/workspace-instruction-policies.d.ts +2 -2
  196. package/dist/workspace-integrations.d.ts +74 -0
  197. package/dist/workspace-integrations.js +67 -0
  198. package/dist/workspace-integrations.js.map +1 -0
  199. package/dist/workspace-state.d.ts +8 -71
  200. package/package.json +103 -5
  201. package/src/adapters/express.ts +136 -0
  202. package/src/adapters/hono.ts +18 -0
  203. package/src/adapters/next.ts +42 -0
  204. package/src/allowance-refusal.ts +5 -0
  205. package/src/app-links.ts +117 -0
  206. package/src/artifact-catalog.ts +51 -0
  207. package/src/artifact-client.ts +40 -49
  208. package/src/artifacts.ts +1 -0
  209. package/src/automations-client.ts +8 -2
  210. package/src/azure-live-transport.ts +286 -0
  211. package/src/browser.ts +37 -0
  212. package/src/chat/fold.ts +431 -0
  213. package/src/chat/handler.ts +240 -0
  214. package/src/chat/http.ts +257 -0
  215. package/src/chat/ids.ts +85 -0
  216. package/src/chat/index.ts +88 -0
  217. package/src/chat/openai.ts +439 -0
  218. package/src/chat/opengeni.ts +737 -0
  219. package/src/chat/types.ts +219 -0
  220. package/src/chat/vercel.ts +204 -0
  221. package/src/chats.ts +16 -0
  222. package/src/client.ts +5697 -1833
  223. package/src/codex-realtime-controller.ts +163 -8
  224. package/src/codex-realtime-v3-wire.ts +4 -3
  225. package/src/codex-realtime-v3.ts +12 -3
  226. package/src/codex-realtime.ts +11 -3
  227. package/src/company-brain.ts +0 -40
  228. package/src/core.ts +20 -0
  229. package/src/deprecation.ts +149 -0
  230. package/src/document-authority-client.ts +104 -1
  231. package/src/editable-artifacts/controller.ts +36 -2
  232. package/src/editable-artifacts/index.ts +1 -0
  233. package/src/editable-artifacts/types.ts +29 -16
  234. package/src/embedding-client.ts +519 -0
  235. package/src/errors.ts +303 -4
  236. package/src/external-vault-receiver.ts +914 -0
  237. package/src/feedback.ts +20 -0
  238. package/src/gateway-realtime-transport.ts +3 -3
  239. package/src/github-repositories.ts +60 -0
  240. package/src/index.ts +603 -65
  241. package/src/insights-usage.ts +64 -0
  242. package/src/interaction.ts +315 -93
  243. package/src/knowledge.ts +72 -0
  244. package/src/known-tools.ts +279 -0
  245. package/src/message-links.ts +178 -0
  246. package/src/model-context.ts +113 -0
  247. package/src/model-display.ts +11 -0
  248. package/src/model-picker-order.ts +6 -0
  249. package/src/organization-integration-policy.ts +54 -0
  250. package/src/pr-review-client.ts +1 -1
  251. package/src/pr-review.ts +1 -1
  252. package/src/preference-registry.ts +2 -0
  253. package/src/prepared-mcp-setup.ts +123 -0
  254. package/src/proxy.ts +23 -12
  255. package/src/realtime.ts +15 -6
  256. package/src/session-history-import.ts +84 -0
  257. package/src/session-list-entries.ts +1 -0
  258. package/src/session-message-search.ts +47 -0
  259. package/src/session-proxy-client.ts +68 -0
  260. package/src/session-proxy.ts +2098 -0
  261. package/src/session-titles.ts +8 -82
  262. package/src/session-usage-limits.ts +71 -0
  263. package/src/shared-catalog-loader.ts +169 -0
  264. package/src/site-ai.ts +284 -0
  265. package/src/site-bridge-host.ts +422 -0
  266. package/src/site-browser-entry.ts +6 -0
  267. package/src/site-browser-runtime.gen.ts +2 -0
  268. package/src/site-data.ts +372 -0
  269. package/src/site-document.test.ts +64 -0
  270. package/src/site-document.ts +18 -0
  271. package/src/site-http.ts +171 -0
  272. package/src/site-sql.ts +153 -0
  273. package/src/site-tool-bridge.ts +401 -0
  274. package/src/site.ts +878 -0
  275. package/src/skills.ts +69 -0
  276. package/src/sse.ts +9 -3
  277. package/src/stream.ts +33 -10
  278. package/src/tenant-workspaces.ts +148 -0
  279. package/src/tool-auth.ts +301 -0
  280. package/src/tool-display-metadata.ts +27 -0
  281. package/src/tools.ts +452 -0
  282. package/src/transcription.ts +3 -0
  283. package/src/types.ts +3170 -582
  284. package/src/usage-allowances.ts +189 -0
  285. package/src/vault-types.ts +379 -0
  286. package/src/vaults-api.ts +339 -0
  287. package/src/workspace-artifacts.ts +55 -6
  288. package/src/workspace-instruction-policies.ts +2 -1
  289. package/src/workspace-integrations.ts +402 -0
  290. package/src/workspace-state.ts +8 -82
  291. package/dist/chunk-C2H7HBNP.js.map +0 -1
  292. package/dist/chunk-C4DJPZRU.js +0 -119
  293. package/dist/chunk-C4DJPZRU.js.map +0 -1
  294. package/dist/chunk-JUS2UYRP.js.map +0 -1
  295. package/dist/chunk-KKRO2VCP.js.map +0 -1
  296. package/dist/chunk-QT3KFVDP.js.map +0 -1
  297. package/dist/chunk-TRNI7KEO.js.map +0 -1
  298. package/dist/chunk-VYCTL62C.js.map +0 -1
  299. package/dist/chunk-YXQX7RQT.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OpenGeniApiError
3
- } from "./chunk-C4DJPZRU.js";
3
+ } from "./chunk-7EWT3PV6.js";
4
4
 
5
5
  // src/codex-realtime-v3-wire.ts
6
6
  var CODEX_REALTIME_INITIAL_ITEMS_MAX_COUNT = 128;
@@ -91,7 +91,7 @@ function parseCodexRealtimeV3Event(payload) {
91
91
  }
92
92
  };
93
93
  }
94
- if (type === "turn.done") {
94
+ if (type === "turn.done" || type === "transcript.segment") {
95
95
  const turn = record(event.turn);
96
96
  const turnIdField = boundedStringField(turn, "id", CODEX_REALTIME_V3_MAX_IDENTIFIER_BYTES);
97
97
  const transcriptField = boundedStringField(
@@ -395,6 +395,10 @@ function createCodexRealtimeV3Bridge(options) {
395
395
  clientAckThroughSequence = Math.max(clientAckThroughSequence ?? 0, entry.sequence);
396
396
  }
397
397
  }
398
+ if (options.events.readyState !== "open") {
399
+ publish();
400
+ continue;
401
+ }
398
402
  for (let index = 0; index < result.outbound.length; ) {
399
403
  const entry = result.outbound[index];
400
404
  if (sentSequences.has(entry.sequence)) {
@@ -539,7 +543,7 @@ function createCodexRealtimeV3Bridge(options) {
539
543
  }
540
544
  } else if (event.type === "output_audio.delta") {
541
545
  speaking = true;
542
- } else if (event.type === "turn.done") {
546
+ } else if (event.type === "turn.done" || event.type === "transcript.segment") {
543
547
  speaking = false;
544
548
  if (event.transcript.length > 0 && !finalizedTurnIds.has(event.turnId)) {
545
549
  const coveredByDelegationItemId = event.role === "user" && pendingDelegationUserTranscript !== null && normalizedTranscript(event.transcript) === normalizedTranscript(pendingDelegationUserTranscript.text) ? pendingDelegationUserTranscript.delegationItemId : null;
@@ -610,6 +614,7 @@ function finalTranscript(randomUUID, event, coveredByDelegationItemId, modelCont
610
614
  text: event.transcript,
611
615
  payload: {
612
616
  turnId: event.turnId,
617
+ ...event.type === "transcript.segment" ? { transcriptSource: "provider_fragments", grouping: "application_segment" } : {},
613
618
  ...coveredByDelegationItemId ? { coveredByDelegationItemId } : {}
614
619
  },
615
620
  ...modelContext ? { modelContext } : {}
@@ -872,8 +877,8 @@ async function startCodexRealtimeWebrtc(options) {
872
877
  { signal: options.signal }
873
878
  );
874
879
  throwIfAborted(options.signal);
875
- if (answer.version !== "v3" || answer.model !== "gpt-live-1-boulder-alpha" || !answer.sdp) {
876
- throw new Error("OpenGeni returned an incompatible Codex realtime answer");
880
+ if (answer.version !== "v3" || answer.model !== (options.expectedModel ?? "gpt-live-1-boulder-alpha") || !answer.sdp) {
881
+ throw new Error("Opengeni returned an incompatible Codex realtime answer");
877
882
  }
878
883
  await peerConnection.setRemoteDescription({
879
884
  type: "answer",
@@ -1093,7 +1098,23 @@ var SESSION_REALTIME_INBOUND_KINDS = /* @__PURE__ */ new Set([
1093
1098
  "error"
1094
1099
  ]);
1095
1100
  var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
1101
+ var REALTIME_REFUSAL_CODES = /* @__PURE__ */ new Set([
1102
+ "insufficient_credits",
1103
+ "allowance_exhausted",
1104
+ "monthly_model_cost_limit",
1105
+ "realtime_voice_unavailable"
1106
+ ]);
1107
+ function codexRealtimeRefusal(error) {
1108
+ if (!(error instanceof OpenGeniApiError) || !error.code) return null;
1109
+ if (!REALTIME_REFUSAL_CODES.has(error.code)) return null;
1110
+ const message = apiErrorMessage(error);
1111
+ return {
1112
+ code: error.code,
1113
+ message: message ?? (error.code === "insufficient_credits" ? "Live voice needs Opengeni credits. Add credits to continue." : "Live voice is unavailable right now.")
1114
+ };
1115
+ }
1096
1116
  function sessionRealtimeOwnerStorageNamespace(model) {
1117
+ if (model === "opengeni-azure/gpt-live-1") return "azure-live-owner";
1097
1118
  if (model === "gpt-live-1-boulder-alpha") return "codex-realtime-owner";
1098
1119
  if (model === "supergrok/grok-voice-think-fast-2.0") return "xai-realtime-owner";
1099
1120
  return "gateway-realtime-owner";
@@ -1151,7 +1172,8 @@ function createCodexRealtimeController(options) {
1151
1172
  connectionGeneration: 0,
1152
1173
  reconnectAttempt: 0,
1153
1174
  diagnostic: null,
1154
- error: null
1175
+ error: null,
1176
+ refusal: null
1155
1177
  };
1156
1178
  let active = null;
1157
1179
  let pendingAbort = null;
@@ -1168,6 +1190,7 @@ function createCodexRealtimeController(options) {
1168
1190
  let generation = 0;
1169
1191
  let reconnectAttempt = 0;
1170
1192
  let recoveryTerminal = false;
1193
+ let connectedInMode = false;
1171
1194
  let mutationTail = Promise.resolve();
1172
1195
  let connectionTask = null;
1173
1196
  const acceptedDelegationItemIds = new Set(
@@ -1420,6 +1443,10 @@ function createCodexRealtimeController(options) {
1420
1443
  if (closed || stopping || isAbortError(error)) return;
1421
1444
  const message = safeError2(error);
1422
1445
  if (error instanceof CodexRealtimeMicrophoneError) {
1446
+ if (error.code !== "track_ended" && !connectedInMode) {
1447
+ await endAfterFailure(microphoneFailureMessage(error), null);
1448
+ return;
1449
+ }
1423
1450
  if (error.code === "track_ended" && state.mode?.state === "active") {
1424
1451
  reconnectAttempt += 1;
1425
1452
  publish({
@@ -1439,6 +1466,11 @@ function createCodexRealtimeController(options) {
1439
1466
  transitionEnded("Realtime owner no longer exists");
1440
1467
  return;
1441
1468
  }
1469
+ const refusal = codexRealtimeRefusal(error);
1470
+ if (refusal) {
1471
+ await endForRefusal(refusal);
1472
+ return;
1473
+ }
1442
1474
  if (error instanceof OpenGeniApiError && error.status === 409 && error.retryable && owner) {
1443
1475
  try {
1444
1476
  const reconciled = await begin(owner, true, false);
@@ -1456,6 +1488,9 @@ function createCodexRealtimeController(options) {
1456
1488
  return;
1457
1489
  }
1458
1490
  }
1491
+ } else if (error instanceof OpenGeniApiError && !error.retryable && !connectedInMode) {
1492
+ await endAfterFailure(message, null);
1493
+ return;
1459
1494
  } else if (error instanceof OpenGeniApiError && !error.retryable) {
1460
1495
  stopTimers();
1461
1496
  if (!active) releaseMicrophone();
@@ -1574,6 +1609,13 @@ function createCodexRealtimeController(options) {
1574
1609
  });
1575
1610
  let connected;
1576
1611
  try {
1612
+ if (active?.transport.drain) {
1613
+ await active.transport.drain();
1614
+ await active.bridge.flush();
1615
+ }
1616
+ if (closed || stopping || abort.signal.aborted || pendingGeneration !== targetGeneration) {
1617
+ throw abort.signal.reason ?? new DOMException("Aborted", "AbortError");
1618
+ }
1577
1619
  const media = await ensureMicrophone(replaceMicrophone, abort.signal);
1578
1620
  const operationId = randomUUID();
1579
1621
  const commonTransportInput = {
@@ -1689,6 +1731,7 @@ function createCodexRealtimeController(options) {
1689
1731
  onFatal: (fatal) => onBridgeFatal(targetGeneration, bridge, fatal)
1690
1732
  });
1691
1733
  active = { generation: targetGeneration, transport: connected, bridge };
1734
+ connectedInMode = true;
1692
1735
  connected.setOutputMuted(state.outputMuted);
1693
1736
  recoveryTerminal = false;
1694
1737
  pendingAbort = null;
@@ -1759,6 +1802,7 @@ function createCodexRealtimeController(options) {
1759
1802
  return response.mode;
1760
1803
  };
1761
1804
  const heartbeat = async () => {
1805
+ let stopInstruction = null;
1762
1806
  await exclusive(async () => {
1763
1807
  const current = state.mode;
1764
1808
  if (!owner || !current || current.state !== "active") {
@@ -1779,6 +1823,30 @@ function createCodexRealtimeController(options) {
1779
1823
  return;
1780
1824
  }
1781
1825
  publish({ mode: result.mode, realtimeId: result.mode.id, error: null });
1826
+ stopInstruction = result.stop ?? null;
1827
+ });
1828
+ const instruction = stopInstruction;
1829
+ stopInstruction = null;
1830
+ if (instruction && !stopping && !closed) await endForRefusal(instruction);
1831
+ };
1832
+ const endForRefusal = async (refusal) => await endAfterFailure(refusal.message, refusal);
1833
+ const endAfterFailure = async (message, refusal) => {
1834
+ try {
1835
+ await controller.stop();
1836
+ } catch {
1837
+ stopping = false;
1838
+ closeBrowserResources();
1839
+ clearOwner();
1840
+ }
1841
+ recoveryTerminal = false;
1842
+ publish({
1843
+ status: "error",
1844
+ realtimeId: null,
1845
+ mode: null,
1846
+ bridge: null,
1847
+ diagnostic: diagnostic("terminal_stop", message, false),
1848
+ error: message,
1849
+ refusal
1782
1850
  });
1783
1851
  };
1784
1852
  const flush = async () => {
@@ -1828,6 +1896,7 @@ function createCodexRealtimeController(options) {
1828
1896
  closed = false;
1829
1897
  stopping = false;
1830
1898
  recoveryTerminal = false;
1899
+ connectedInMode = false;
1831
1900
  const record2 = {
1832
1901
  version: OWNER_RECORD_VERSION,
1833
1902
  workspaceId: options.workspaceId,
@@ -1838,11 +1907,12 @@ function createCodexRealtimeController(options) {
1838
1907
  };
1839
1908
  owner = record2;
1840
1909
  storage?.setItem(storageKey, JSON.stringify(record2));
1841
- publish({ status: "starting", error: null, diagnostic: null });
1910
+ publish({ status: "starting", error: null, diagnostic: null, refusal: null });
1842
1911
  try {
1843
1912
  await begin(record2, false);
1844
1913
  } catch (error) {
1845
1914
  closeBrowserResources(false);
1915
+ const refusal = codexRealtimeRefusal(error);
1846
1916
  const failedMode = state.mode;
1847
1917
  if (failedMode?.state === "active") {
1848
1918
  await handleConnectionFailure(error, "reconnect", false);
@@ -1852,9 +1922,11 @@ function createCodexRealtimeController(options) {
1852
1922
  status: "error",
1853
1923
  realtimeId: null,
1854
1924
  mode: null,
1855
- error: safeError2(error)
1925
+ error: refusal?.message ?? safeError2(error),
1926
+ ...refusal ? { refusal, diagnostic: diagnostic("terminal_stop", refusal.message, false) } : {}
1856
1927
  });
1857
1928
  }
1929
+ if (refusal) return;
1858
1930
  throw error;
1859
1931
  }
1860
1932
  },
@@ -1863,6 +1935,7 @@ function createCodexRealtimeController(options) {
1863
1935
  if (recoveryTerminal && state.mode?.state === "active") return;
1864
1936
  const record3 = readOwnerRecord(storage, storageKey, options);
1865
1937
  if (!record3) {
1938
+ if (state.status === "error" && !state.mode) return;
1866
1939
  transitionEnded();
1867
1940
  return;
1868
1941
  }
@@ -1883,7 +1956,7 @@ function createCodexRealtimeController(options) {
1883
1956
  if (lifecycle.state === "ended") {
1884
1957
  const record3 = readOwnerRecord(storage, storageKey, options);
1885
1958
  if (record3 && record3.operationId !== lifecycle.operationId) {
1886
- if (connectionTask || state.status === "active") return;
1959
+ if (connectionTask || state.status === "active" || state.status === "starting") return;
1887
1960
  closed = false;
1888
1961
  stopping = false;
1889
1962
  owner = record3;
@@ -1896,6 +1969,7 @@ function createCodexRealtimeController(options) {
1896
1969
  await connectionTask;
1897
1970
  return;
1898
1971
  }
1972
+ if (state.status === "error" && !state.mode) return;
1899
1973
  if (state.realtimeId === null || lifecycle.realtimeId === state.realtimeId) {
1900
1974
  transitionEnded(`Realtime ended: ${lifecycle.reason}`);
1901
1975
  }
@@ -1905,11 +1979,15 @@ function createCodexRealtimeController(options) {
1905
1979
  if (state.status === "active" && state.realtimeId === lifecycle.realtimeId) return;
1906
1980
  const record2 = readOwnerRecord(storage, storageKey, options);
1907
1981
  if (!record2 || record2.operationId !== lifecycle.operationId) {
1908
- closeBrowserResources();
1909
- owner = null;
1910
1982
  const leaseExpiresAt = Date.parse(lifecycle.leaseExpiresAt);
1911
1983
  const remainingLeaseMs = leaseExpiresAt - now().getTime();
1912
- if (Number.isFinite(remainingLeaseMs) && remainingLeaseMs <= 0) {
1984
+ const leaseExpired = Number.isFinite(remainingLeaseMs) && remainingLeaseMs <= 0;
1985
+ if (leaseExpired && lifecycle.realtimeId !== state.realtimeId && (connectionTask || state.status === "starting")) {
1986
+ return;
1987
+ }
1988
+ closeBrowserResources();
1989
+ owner = null;
1990
+ if (leaseExpired) {
1913
1991
  transitionEnded("Realtime lease expired");
1914
1992
  return;
1915
1993
  }
@@ -1979,6 +2057,7 @@ function createCodexRealtimeController(options) {
1979
2057
  connectionTask = null;
1980
2058
  void retiredTask?.catch(() => void 0);
1981
2059
  try {
2060
+ await active?.transport.drain?.();
1982
2061
  await active?.bridge.sealAndFlush();
1983
2062
  closeBrowserResources();
1984
2063
  let current = state.mode;
@@ -2248,8 +2327,33 @@ function stringValue2(value) {
2248
2327
  function isAbortError(error) {
2249
2328
  return error instanceof Error && error.name === "AbortError";
2250
2329
  }
2330
+ function microphoneFailureMessage(error) {
2331
+ switch (error.code) {
2332
+ case "permission_denied":
2333
+ return "Microphone access is blocked. Allow it in site settings, then try again.";
2334
+ case "device_not_found":
2335
+ return "No microphone was found. Connect one, then try again.";
2336
+ case "device_unavailable":
2337
+ return "Your microphone is busy or unavailable. Close other apps using it, then try again.";
2338
+ default:
2339
+ return /timed out/i.test(error.message) ? "Microphone access wasn't granted in time. Allow it when your browser asks, then try again." : "The microphone could not start. Try again.";
2340
+ }
2341
+ }
2342
+ function apiErrorMessage(error) {
2343
+ try {
2344
+ const body = JSON.parse(error.body);
2345
+ const nested = body.error && typeof body.error === "object" ? body.error : body;
2346
+ return typeof nested.message === "string" && nested.message ? nested.message : null;
2347
+ } catch {
2348
+ return null;
2349
+ }
2350
+ }
2251
2351
  function safeError2(error) {
2252
- return error instanceof Error ? error.message : "Codex realtime browser controller failed";
2352
+ if (error instanceof OpenGeniApiError) {
2353
+ const message = apiErrorMessage(error);
2354
+ if (message) return /[.!?]$/.test(message) ? message : `${message}.`;
2355
+ }
2356
+ return error instanceof Error ? error.message : "Live voice failed in this browser.";
2253
2357
  }
2254
2358
 
2255
2359
  export {
@@ -2273,9 +2377,10 @@ export {
2273
2377
  createCodexRealtimeV3Bridge,
2274
2378
  projectSessionRealtimeLifecycle,
2275
2379
  CODEX_REALTIME_NEGOTIATION_TIMEOUT_MS,
2380
+ codexRealtimeRefusal,
2276
2381
  sessionRealtimeOwnerStorageNamespace,
2277
2382
  sessionRealtimeOwnerStorageKey,
2278
2383
  hasStoredSessionRealtimeOwnerProof,
2279
2384
  createCodexRealtimeController
2280
2385
  };
2281
- //# sourceMappingURL=chunk-C2H7HBNP.js.map
2386
+ //# sourceMappingURL=chunk-WVCJRSGJ.js.map