@opengeni/sdk 4.4.1 → 4.5.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 (57) hide show
  1. package/README.md +27 -0
  2. package/dist/adapters/next.js +2 -2
  3. package/dist/artifacts.js +4 -4
  4. package/dist/browser.d.ts +2 -0
  5. package/dist/browser.js +5 -3
  6. package/dist/chat/index.js +5 -5
  7. package/dist/{chunk-3BWTS2MJ.js → chunk-ARDVIZIJ.js} +2 -2
  8. package/dist/{chunk-PVWOBYAZ.js → chunk-BXMNDWAN.js} +256 -78
  9. package/dist/chunk-BXMNDWAN.js.map +1 -0
  10. package/dist/{chunk-IVHLADZ7.js → chunk-GRUMGFK6.js} +2 -2
  11. package/dist/{chunk-2RVPHF37.js → chunk-JBAGMSN2.js} +66 -10
  12. package/dist/chunk-JBAGMSN2.js.map +1 -0
  13. package/dist/{chunk-35S72HAE.js → chunk-U4JUWOZV.js} +5 -5
  14. package/dist/{chunk-BLID3DCD.js → chunk-V4AIZAFF.js} +1 -1
  15. package/dist/chunk-V4AIZAFF.js.map +1 -0
  16. package/dist/{chunk-ALXDFL6C.js → chunk-VSOXNL3T.js} +2 -2
  17. package/dist/{chunk-CT6P2W2C.js → chunk-WI3WUT5H.js} +2 -2
  18. package/dist/client.d.ts +24 -1
  19. package/dist/codex-realtime-controller.js +1 -1
  20. package/dist/core.d.ts +2 -0
  21. package/dist/core.js +5 -3
  22. package/dist/document-authority.js +3 -3
  23. package/dist/editable-artifacts.js +1 -1
  24. package/dist/index.d.ts +4 -2
  25. package/dist/index.js +35 -33
  26. package/dist/index.js.map +1 -1
  27. package/dist/read-retry.d.ts +61 -0
  28. package/dist/realtime.js +5 -5
  29. package/dist/session-proxy.d.ts +6 -1
  30. package/dist/session-proxy.js +2 -2
  31. package/dist/site-bridge-host.js +3 -3
  32. package/dist/site-browser-runtime.gen.d.ts +1 -1
  33. package/dist/site-document.js +1 -1
  34. package/dist/site-document.js.map +1 -1
  35. package/dist/site.js +3 -3
  36. package/dist/types.d.ts +40 -0
  37. package/dist/workspace-artifacts.d.ts +5 -0
  38. package/dist/workspace-live-stream.d.ts +7 -0
  39. package/package.json +3 -3
  40. package/src/browser.ts +2 -0
  41. package/src/client.ts +191 -73
  42. package/src/core.ts +2 -0
  43. package/src/index.ts +4 -0
  44. package/src/read-retry.ts +207 -0
  45. package/src/session-proxy.ts +95 -4
  46. package/src/site-browser-runtime.gen.ts +1 -1
  47. package/src/types.ts +38 -0
  48. package/src/workspace-artifacts.ts +6 -0
  49. package/src/workspace-live-stream.ts +12 -1
  50. package/dist/chunk-2RVPHF37.js.map +0 -1
  51. package/dist/chunk-BLID3DCD.js.map +0 -1
  52. package/dist/chunk-PVWOBYAZ.js.map +0 -1
  53. /package/dist/{chunk-3BWTS2MJ.js.map → chunk-ARDVIZIJ.js.map} +0 -0
  54. /package/dist/{chunk-IVHLADZ7.js.map → chunk-GRUMGFK6.js.map} +0 -0
  55. /package/dist/{chunk-35S72HAE.js.map → chunk-U4JUWOZV.js.map} +0 -0
  56. /package/dist/{chunk-ALXDFL6C.js.map → chunk-VSOXNL3T.js.map} +0 -0
  57. /package/dist/{chunk-CT6P2W2C.js.map → chunk-WI3WUT5H.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OpenGeniClient
3
- } from "./chunk-3BWTS2MJ.js";
3
+ } from "./chunk-ARDVIZIJ.js";
4
4
 
5
5
  // src/embedding-client.ts
6
6
  function hasStaticHeader(options, names) {
@@ -329,4 +329,4 @@ function usageQuery(query) {
329
329
  export {
330
330
  OpenGeniEmbeddingClient
331
331
  };
332
- //# sourceMappingURL=chunk-IVHLADZ7.js.map
332
+ //# sourceMappingURL=chunk-GRUMGFK6.js.map
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  OPENGENI_API_CONTRACT_HEADER,
15
15
  OPENGENI_API_CONTRACT_REVISION
16
- } from "./chunk-BLID3DCD.js";
16
+ } from "./chunk-V4AIZAFF.js";
17
17
  import {
18
18
  OpenGeniApiError,
19
19
  OpenGeniSetupError
@@ -277,7 +277,14 @@ var CREATE_FIELDS = /* @__PURE__ */ new Set([
277
277
  "initialMessage",
278
278
  "idempotencyKey",
279
279
  "resources",
280
- "startMode"
280
+ "startMode",
281
+ "modelContext"
282
+ ]);
283
+ var SESSION_APP_CREATE_FIELDS = /* @__PURE__ */ new Set([
284
+ "visibility",
285
+ "clientEventId",
286
+ "connectionAccounts",
287
+ "expectedNewSessionDraftRevision"
281
288
  ]);
282
289
  var MODEL_FIELDS = ["model", "reasoningEffort", "latencyMode"];
283
290
  var MAX_TRANSCRIPTION_BODY_BYTES = 25 * 1024 * 1024 + 64 * 1024;
@@ -865,7 +872,9 @@ function createSessionProxyHandler(target, options) {
865
872
  if (method !== "POST" || !options.createSession) {
866
873
  return errorJson(404, "route_not_allowed", "Not found.");
867
874
  }
868
- const input = createInput(await readJsonBody(request, maxBodyBytes), modelSelection);
875
+ const body2 = await readJsonBody(request, maxBodyBytes);
876
+ const input = createInput(body2, modelSelection, sessionAppEnabled);
877
+ const browser = browserCreateFields(body2, sessionAppEnabled);
869
878
  if (input.startMode === "realtime" && !realtimeVoiceEnabled) {
870
879
  return errorJson(404, "route_not_allowed", "Not found.");
871
880
  }
@@ -873,14 +882,19 @@ function createSessionProxyHandler(target, options) {
873
882
  if (hooked instanceof Response) return hooked;
874
883
  const created = withBrowserCreateChoices(
875
884
  toolServer ? withToolServer(hooked, toolServer, await toolToken()) : hooked,
876
- input
885
+ input,
886
+ browser
877
887
  );
878
888
  const extras = await messageExtras({
879
889
  delivery: "create",
880
890
  ...input.startMode ? { startMode: input.startMode } : {}
881
891
  });
882
892
  if (extras instanceof Response) return extras;
883
- const modelContext = joinContext(extras?.modelContext, created.modelContext);
893
+ const modelContext = joinContext(
894
+ extras?.modelContext,
895
+ created.modelContext,
896
+ browser.modelContext
897
+ );
884
898
  return json(
885
899
  await client.createSession(workspaceId, {
886
900
  ...created,
@@ -1544,9 +1558,9 @@ function pick(body, fields) {
1544
1558
  }
1545
1559
  return picked;
1546
1560
  }
1547
- function createInput(body, modelSelection) {
1561
+ function createInput(body, modelSelection, sessionApp) {
1548
1562
  for (const key of Object.keys(body ?? {})) {
1549
- if (!CREATE_FIELDS.has(key) && !(modelSelection && isModelField(key))) {
1563
+ if (!CREATE_FIELDS.has(key) && !(modelSelection && isModelField(key)) && !(sessionApp && SESSION_APP_CREATE_FIELDS.has(key))) {
1550
1564
  reject(
1551
1565
  400,
1552
1566
  "create_field_not_allowed",
@@ -1614,7 +1628,47 @@ function createResources(value) {
1614
1628
  };
1615
1629
  });
1616
1630
  }
1617
- function withBrowserCreateChoices(created, input) {
1631
+ function browserCreateFields(body, sessionApp) {
1632
+ const fields = {};
1633
+ const modelContext = body?.modelContext;
1634
+ if (modelContext !== void 0 && typeof modelContext !== "string") {
1635
+ reject(400, "invalid_model_context", "modelContext must be a string.");
1636
+ }
1637
+ if (modelContext?.trim()) fields.modelContext = modelContext;
1638
+ if (!sessionApp) return fields;
1639
+ const visibility = body?.visibility;
1640
+ if (visibility !== void 0 && visibility !== "workspace" && visibility !== "private") {
1641
+ reject(400, "invalid_visibility", "visibility must be workspace or private.");
1642
+ }
1643
+ const accounts = body?.connectionAccounts;
1644
+ if (accounts !== void 0 && (!Array.isArray(accounts) || accounts.length > 0)) {
1645
+ reject(
1646
+ 403,
1647
+ "connection_account_not_allowed",
1648
+ "The server chooses which connected accounts a chat uses."
1649
+ );
1650
+ }
1651
+ const clientEventId = body?.clientEventId;
1652
+ if (clientEventId !== void 0) {
1653
+ if (typeof clientEventId !== "string" || !clientEventId) {
1654
+ reject(400, "invalid_client_event_id", "clientEventId must be a non-empty string.");
1655
+ }
1656
+ fields.clientEventId = clientEventId;
1657
+ }
1658
+ const revision = body?.expectedNewSessionDraftRevision;
1659
+ if (revision !== void 0) {
1660
+ if (typeof revision !== "number" || !Number.isSafeInteger(revision) || revision < 0) {
1661
+ reject(
1662
+ 400,
1663
+ "invalid_draft_revision",
1664
+ "expectedNewSessionDraftRevision must be a non-negative integer."
1665
+ );
1666
+ }
1667
+ fields.expectedNewSessionDraftRevision = revision;
1668
+ }
1669
+ return fields;
1670
+ }
1671
+ function withBrowserCreateChoices(created, input, browser = {}) {
1618
1672
  const existing = created.resources ?? [];
1619
1673
  const attached = new Set(
1620
1674
  existing.flatMap((resource) => resource.kind === "file" ? [resource.fileId] : [])
@@ -1629,7 +1683,9 @@ function withBrowserCreateChoices(created, input) {
1629
1683
  ...added.length > 0 ? { resources: [...existing, ...added] } : {},
1630
1684
  ...input.model ? { model: input.model } : {},
1631
1685
  ...input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {},
1632
- ...input.latencyMode ? { latencyMode: input.latencyMode } : {}
1686
+ ...input.latencyMode ? { latencyMode: input.latencyMode } : {},
1687
+ ...created.clientEventId === void 0 && browser.clientEventId ? { clientEventId: browser.clientEventId } : {},
1688
+ ...created.expectedNewSessionDraftRevision === void 0 && browser.expectedNewSessionDraftRevision !== void 0 ? { expectedNewSessionDraftRevision: browser.expectedNewSessionDraftRevision } : {}
1633
1689
  };
1634
1690
  }
1635
1691
  async function transcriptionInput(request) {
@@ -1863,4 +1919,4 @@ export {
1863
1919
  createSessionProxyHandler,
1864
1920
  artifactViewerCapability
1865
1921
  };
1866
- //# sourceMappingURL=chunk-2RVPHF37.js.map
1922
+ //# sourceMappingURL=chunk-JBAGMSN2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/message-links.ts","../src/proxy.ts","../src/session-proxy-client.ts","../src/session-proxy.ts"],"sourcesContent":["/**\n * Links an agent writes into chat Markdown that point at Opengeni-owned objects.\n *\n * Agents write these forms (tool receipts and bundled Skills teach them):\n *\n * - `artifact:<file uuid>` — a retained workspace file (exports, published files, images).\n * - `sandbox:<path>[:<line>]` — a file in the session's sandbox or Connected Machine.\n * - `/workspaces/<ws>/artifacts/editable/<32-hex id>` — a live editable document,\n * workbook, or presentation.\n * - `/workspaces/<ws>/artifacts/<uuid>` — a saved Site / published HTML artifact.\n * - `/workspaces/<ws>/artifacts/files/<uuid>` — a retained file (console path form).\n *\n * None of them is a URL a browser can navigate on its own: the `/workspaces/...`\n * forms are Opengeni console routes, so inside another product they resolve\n * against that product's origin and 404. Parse them with {@link parseOpenGeniLink}\n * and route each target to the host's own UI (download, panel, page).\n */\nexport type OpenGeniLinkTarget =\n | { kind: \"file\"; fileId: string; workspaceId: string | null; fromSession?: string }\n | { kind: \"editable-artifact\"; artifactId: string; workspaceId: string; fromSession?: string }\n | { kind: \"site\"; artifactId: string; workspaceId: string; fromSession?: string }\n | { kind: \"sandbox-file\"; path: string; line: number | null };\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;\nconst EDITABLE_ID = /^[0-9a-f]{32}$/iu;\nconst WORKSPACE_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/u;\nconst SANDBOX_SCHEME = \"sandbox:\";\nconst LEGACY_WORKSPACE_PREFIX = \"/workspace/\";\nconst TRAILING_LINE = /:([0-9]+)$/u;\nconst TRAILING_INVALID_LINE = /:-(?:[0-9]+)$|:[0-9]+-[0-9]+$/u;\nconst CONTROL_CHARACTER = /[\\u0000-\\u001f\\u007f]/u;\n\n/** Application scheme names are case-insensitive, unlike their payloads. */\nexport function openGeniLinkScheme(href: string | undefined): \"artifact\" | \"sandbox\" | null {\n const scheme = /^([a-z]+):/iu.exec(href ?? \"\")?.[1]?.toLowerCase();\n return scheme === \"artifact\" || scheme === \"sandbox\" ? scheme : null;\n}\n\n/** Reserved references must never fall back to navigation on a host origin. */\nexport function isReservedOpenGeniLink(href: string | undefined): boolean {\n if (!href) return false;\n if (openGeniLinkScheme(href) || href.startsWith(LEGACY_WORKSPACE_PREFIX)) return true;\n // Decoding is for reservation only: encoded variants are not valid targets.\n try {\n return /^\\/workspaces\\/[^/]+\\/artifacts(?:\\/|[?#]|$)/u.test(decodeURIComponent(href));\n } catch {\n return /^\\/workspaces\\/[^/]+\\/artifacts/u.test(href);\n }\n}\n\n/**\n * Parse an Opengeni `sandbox:` href (plus the historical bare `/workspace/...`\n * form). The decoded path is intentionally opaque: target selection, path\n * policy, and filesystem authority belong to the session-aware host.\n */\nexport function parseSandboxLink(\n href: string | undefined,\n): { path: string; line: number | null } | null {\n if (!href) return null;\n const encodedLocation =\n openGeniLinkScheme(href) === \"sandbox\"\n ? href.slice(SANDBOX_SCHEME.length)\n : href.startsWith(LEGACY_WORKSPACE_PREFIX)\n ? href\n : null;\n if (!encodedLocation || encodedLocation.includes(\"?\") || encodedLocation.includes(\"#\")) {\n return null;\n }\n if (TRAILING_INVALID_LINE.test(encodedLocation)) return null;\n const lineMatch = TRAILING_LINE.exec(encodedLocation);\n const encodedPath = lineMatch ? encodedLocation.slice(0, -lineMatch[0].length) : encodedLocation;\n const line = lineMatch?.[1] ? Number(lineMatch[1]) : null;\n if (line !== null && (!Number.isSafeInteger(line) || line < 1)) return null;\n if (!encodedPath) return null;\n try {\n const path = decodeURIComponent(encodedPath);\n return path && !CONTROL_CHARACTER.test(path) ? { path, line } : null;\n } catch {\n return null;\n }\n}\n\n/** Return the retained-file id of an exact `artifact:<uuid>` reference. */\nexport function parseRetainedFileReference(href: string | undefined): string | null {\n if (openGeniLinkScheme(href) !== \"artifact\") return null;\n if (!href) return null;\n const id = href.slice(\"artifact:\".length);\n return UUID.test(id) ? id.toLowerCase() : null;\n}\n\n/**\n * Classify an agent-authored Markdown href. Returns `null` for ordinary links\n * (`https://…`, `mailto:`, relative host links), which render as-is.\n *\n * Only root-relative console paths are recognized; an absolute URL is always an\n * ordinary link, so a host's own `https://` routes are never reinterpreted.\n * A validated `?fromSession=<uuid>` return hint is preserved.\n */\nexport function parseOpenGeniLink(href: string | undefined): OpenGeniLinkTarget | null {\n if (!href) return null;\n const fileId = parseRetainedFileReference(href);\n if (fileId) return { kind: \"file\", fileId, workspaceId: null };\n if (openGeniLinkScheme(href) === \"sandbox\" || href.startsWith(LEGACY_WORKSPACE_PREFIX)) {\n const location = parseSandboxLink(href);\n return location ? { kind: \"sandbox-file\", ...location } : null;\n }\n if (!href.startsWith(\"/workspaces/\") || href.includes(\"#\")) return null;\n const separator = href.indexOf(\"?\");\n const pathname = separator < 0 ? href : href.slice(0, separator);\n const search = separator < 0 ? undefined : href.slice(separator + 1);\n let fromSession: string | undefined;\n if (search !== undefined) {\n const params = new URLSearchParams(search);\n const keys = [...params.keys()];\n if (keys.some((key) => key !== \"fromSession\") || keys.length > 1) return null;\n if (!UUID.test(params.get(\"fromSession\") ?? \"\")) return null;\n fromSession = params.get(\"fromSession\")!.toLowerCase();\n }\n const parts = pathname.split(\"/\");\n const workspaceId = parts[2] ?? \"\";\n if (parts[1] !== \"workspaces\" || parts[3] !== \"artifacts\" || !WORKSPACE_SEGMENT.test(workspaceId))\n return null;\n if (parts.length === 6 && parts[4] === \"editable\" && EDITABLE_ID.test(parts[5] ?? \"\")) {\n return {\n kind: \"editable-artifact\",\n artifactId: parts[5]!.toLowerCase(),\n workspaceId,\n ...(fromSession ? { fromSession } : {}),\n };\n }\n if (parts.length === 6 && parts[4] === \"files\" && UUID.test(parts[5] ?? \"\")) {\n return {\n kind: \"file\",\n fileId: parts[5]!.toLowerCase(),\n workspaceId,\n ...(fromSession ? { fromSession } : {}),\n };\n }\n if (parts.length === 5 && UUID.test(parts[4] ?? \"\")) {\n return {\n kind: \"site\",\n artifactId: parts[4]!.toLowerCase(),\n workspaceId,\n ...(fromSession ? { fromSession } : {}),\n };\n }\n return null;\n}\n\n/** The Opengeni console route for a target (the form agents write). */\nexport function openGeniConsolePath(\n target: OpenGeniLinkTarget,\n workspaceId: string,\n): string | null {\n const workspace = encodeURIComponent(\n target.kind === \"sandbox-file\" ? workspaceId : (target.workspaceId ?? workspaceId),\n );\n const search =\n target.kind !== \"sandbox-file\" && target.fromSession && UUID.test(target.fromSession)\n ? `?fromSession=${encodeURIComponent(target.fromSession)}`\n : \"\";\n switch (target.kind) {\n case \"file\":\n return `/workspaces/${workspace}/artifacts/files/${target.fileId}${search}`;\n case \"editable-artifact\":\n return `/workspaces/${workspace}/artifacts/editable/${target.artifactId}${search}`;\n case \"site\":\n return `/workspaces/${workspace}/artifacts/${target.artifactId}${search}`;\n case \"sandbox-file\":\n return null;\n }\n}\n\n/**\n * Request header naming the session an embedded artifact read belongs to.\n * `createSessionProxyHandler` only serves artifacts Opengeni lists for it.\n */\nexport const SESSION_SCOPE_HEADER = \"x-opengeni-session-id\";\n","import type { OpenGeniClient } from \"./client\";\nimport { sessionEventStreamCoveredThrough, type StreamSessionEventsOptions } from \"./stream\";\nimport type { SessionEvent } from \"./types\";\n\n/**\n * Proxy-through-your-own-API helpers.\n *\n * The intended pattern: a customer's server consumes the Opengeni event\n * stream with its own API key (`client.streamEvents(...)`) and re-emits it to\n * its browser clients over its own authenticated endpoint — the Opengeni key\n * never reaches the browser. The re-emitted wire format is identical to\n * Opengeni's own SSE stream (`id: <sequence>`, `event: <type>`,\n * `data: <event JSON>`), so the browser side can consume it with this same\n * SDK's streaming core (or a plain `EventSource`), including resume via\n * `?after=` / `Last-Event-ID`. An ordinary event uses its own sequence as the\n * SSE `id`; a compact event uses the server-owned sequence it covers through.\n */\n\n/** Format one event with the exact Opengeni data and resume-cursor semantics. */\nexport function formatSseEvent(event: SessionEvent): string {\n const streamedCoverage = sessionEventStreamCoveredThrough(event);\n const projectedCoverage = event.coveredThrough;\n const coveredThrough =\n streamedCoverage ??\n (typeof projectedCoverage === \"number\" &&\n Number.isSafeInteger(projectedCoverage) &&\n projectedCoverage >= event.sequence\n ? projectedCoverage\n : event.sequence);\n return `id: ${coveredThrough}\\nevent: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`;\n}\n\nexport type SseReStreamOptions = {\n /**\n * Emit `: ping` comment lines at this interval, keeping intermediaries from\n * idling the connection out. Disabled when omitted.\n */\n heartbeatMs?: number;\n /**\n * Called when the downstream consumer cancels (e.g. the browser\n * disconnected). Use it to abort the upstream Opengeni stream — an async\n * iterator that is mid-`await` cannot be interrupted by `return()` alone.\n */\n onCancel?: () => void;\n};\n\n/**\n * Re-emit a stream of session events as an SSE byte stream. Pull-based, so\n * upstream consumption follows downstream demand; cancelling the returned\n * stream fires `onCancel` and ends the upstream iterator.\n */\nexport function sessionEventsToSseStream(\n events: AsyncIterable<SessionEvent>,\n options: SseReStreamOptions = {},\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const iterator = events[Symbol.asyncIterator]();\n let heartbeat: ReturnType<typeof setInterval> | undefined;\n let cancelled = false;\n\n const stopHeartbeat = (): void => {\n if (heartbeat !== undefined) {\n clearInterval(heartbeat);\n heartbeat = undefined;\n }\n };\n\n return new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (options.heartbeatMs !== undefined) {\n heartbeat = setInterval(() => {\n try {\n controller.enqueue(encoder.encode(\": ping\\n\\n\"));\n } catch {\n stopHeartbeat();\n }\n }, options.heartbeatMs);\n }\n },\n pull: async (controller) => {\n let result: IteratorResult<SessionEvent, unknown>;\n try {\n result = await iterator.next();\n } catch (error) {\n stopHeartbeat();\n throw error;\n }\n if (cancelled) {\n return;\n }\n if (result.done) {\n stopHeartbeat();\n controller.close();\n return;\n }\n controller.enqueue(encoder.encode(formatSseEvent(result.value)));\n },\n cancel: () => {\n cancelled = true;\n stopHeartbeat();\n options.onCancel?.();\n // Fire-and-forget: if the iterator is suspended mid-await, return()\n // settles only after onCancel unblocks it; cancel must not hang on it.\n void Promise.resolve(iterator.return?.(undefined)).then(\n () => undefined,\n () => undefined,\n );\n },\n });\n}\n\n/** Wrap an event stream in a ready-to-return SSE `Response`. */\nexport function sessionEventsToSseResponse(\n events: AsyncIterable<SessionEvent>,\n options: SseReStreamOptions = {},\n): Response {\n return new Response(sessionEventsToSseStream(events, options), {\n headers: {\n \"Content-Type\": \"text/event-stream; charset=utf-8\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n },\n });\n}\n\n/**\n * Read the resume cursor a reconnecting SSE client sent: the `after` query\n * parameter, or the standard `Last-Event-ID` header. Re-emitted streams set\n * `id:` to the event sequence for ordinary events and the covered high-water\n * sequence for compact events. Returns 0 (full replay) when absent.\n */\nexport function resumeSequenceFromRequest(request: Request): number {\n const url = new URL(request.url);\n const raw = url.searchParams.get(\"after\") ?? request.headers.get(\"Last-Event-ID\");\n const parsed = raw === null ? 0 : Number(raw);\n return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 0;\n}\n\nexport type ProxySessionEventStreamOptions = Omit<StreamSessionEventsOptions, \"after\"> & {\n /**\n * Resume cursor. Pass a number, or the incoming browser `Request` to\n * honor its `?after=` / `Last-Event-ID` automatically.\n */\n after?: number | Request;\n /** See {@link SseReStreamOptions.heartbeatMs}. */\n heartbeatMs?: number;\n};\n\n/**\n * One-call proxy: consume the Opengeni stream server-side and return an SSE\n * `Response` for your own browser clients. Works anywhere WHATWG `Response`\n * is the handler return type (Hono, Next.js route handlers, Bun.serve,\n * Cloudflare Workers, ...).\n *\n * The upstream Opengeni connection is torn down when the downstream client\n * disconnects, and also when `options.signal` (e.g. the incoming request's\n * signal) aborts.\n */\nexport function proxySessionEventStream(\n client: OpenGeniClient,\n workspaceId: string,\n sessionId: string,\n options: ProxySessionEventStreamOptions = {},\n): Response {\n const { after, heartbeatMs, signal, ...streamOptions } = options;\n const upstream = new AbortController();\n if (signal?.aborted) {\n upstream.abort();\n } else {\n signal?.addEventListener(\"abort\", () => upstream.abort(), { once: true });\n }\n const resolvedAfter = after instanceof Request ? resumeSequenceFromRequest(after) : (after ?? 0);\n const events = client.streamEvents(workspaceId, sessionId, {\n ...streamOptions,\n after: resolvedAfter,\n signal: upstream.signal,\n });\n return sessionEventsToSseResponse(events, {\n ...(heartbeatMs !== undefined ? { heartbeatMs } : {}),\n onCancel: () => upstream.abort(),\n });\n}\n","import type { OpenGeniEmbeddingClient } from \"./embedding-client\";\nimport type { OpenGeniRequestOptions, FetchResponse } from \"./client\";\nimport type { AccessGrant } from \"./types\";\n\n/** Maximum actual UTF-8 bytes forwarded for one embedded Site HTML response. */\nexport const SESSION_PROXY_SITE_HTML_MAX_BYTES = 25 * 1024 * 1024;\n\n/** A streaming Site download exceeded the host proxy's actual-byte ceiling. */\nexport class SessionProxySiteHtmlTooLargeError extends Error {\n readonly code = \"site_html_too_large\";\n readonly limitBytes = SESSION_PROXY_SITE_HTML_MAX_BYTES;\n\n constructor() {\n super(`Site HTML exceeds the ${SESSION_PROXY_SITE_HTML_MAX_BYTES}-byte proxy limit.`);\n this.name = \"SessionProxySiteHtmlTooLargeError\";\n }\n}\n\n/** Server-only effective grant read; never derive external authority from access/me snapshots. */\nexport function getSessionProxyWorkspaceGrant(\n client: Pick<OpenGeniEmbeddingClient, \"requestJson\">,\n workspaceId: string,\n options: OpenGeniRequestOptions = {},\n): Promise<AccessGrant> {\n return client.requestJson(\n \"GET\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/access/grant`,\n undefined,\n {},\n options,\n );\n}\n\n/**\n * Exact association read. The API reauthorizes the source session on every\n * call. `retained` proves a generated image or video, or a published sandbox\n * file, originated in that session.\n */\nexport function getSessionProxyArtifactAssociation(\n client: Pick<OpenGeniEmbeddingClient, \"requestJson\">,\n workspaceId: string,\n sessionId: string,\n kind: \"editable\" | \"site\" | \"retained\",\n artifactId: string,\n options: OpenGeniRequestOptions = {},\n): Promise<{ sessionId: string; artifactId: string; kind: \"editable\" | \"site\" | \"retained\" }> {\n return client.requestJson(\n \"GET\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/sessions/${encodeURIComponent(sessionId)}/artifact-associations/${encodeURIComponent(artifactId)}`,\n undefined,\n { kind },\n options,\n );\n}\n\n/** Authenticated response stream for the server proxy; does not buffer Site HTML. */\nexport function downloadSessionProxySiteHtml(\n client: Pick<OpenGeniEmbeddingClient, \"requestJsonResponse\">,\n workspaceId: string,\n artifactId: string,\n options: { versionId: string; signal?: AbortSignal },\n): Promise<FetchResponse> {\n return client.requestJsonResponse(\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/published-artifacts/${encodeURIComponent(artifactId)}/html`,\n { versionId: options.versionId },\n options,\n );\n}\n","import { observedSessionSequence, SESSION_SEQUENCE_HEADER } from \"./session-sequence\";\nimport type { OpenGeniEmbeddingClient } from \"./embedding-client\";\nimport { OpenGeniApiError, OpenGeniSetupError } from \"./errors\";\nimport { chatDefaults, type Chats } from \"./chats\";\nimport { SESSION_SCOPE_HEADER } from \"./message-links\";\nimport type { WorkspaceIdOptions, WorkspaceIdTarget } from \"./tenant-workspaces\";\nimport { proxySessionEventStream } from \"./proxy\";\nimport { OPENGENI_API_CONTRACT_HEADER, OPENGENI_API_CONTRACT_REVISION } from \"./types\";\nimport type {\n AccessGrant,\n AccessContext,\n CreateSessionRequest,\n FileResourceRef,\n LatencyMode,\n ReasoningEffort,\n RetainedArtifactContent,\n SessionMcpCredentialUpdateInput,\n} from \"./types\";\nimport { mintToolToken, resolveToolTokenSecret } from \"./tool-auth\";\nimport {\n downloadSessionProxySiteHtml,\n getSessionProxyArtifactAssociation,\n getSessionProxyWorkspaceGrant,\n SESSION_PROXY_SITE_HTML_MAX_BYTES,\n SessionProxySiteHtmlTooLargeError,\n} from \"./session-proxy-client\";\nexport {\n downloadSessionProxySiteHtml,\n getSessionProxyArtifactAssociation,\n getSessionProxyWorkspaceGrant,\n SESSION_PROXY_SITE_HTML_MAX_BYTES,\n SessionProxySiteHtmlTooLargeError,\n} from \"./session-proxy-client\";\n\n/**\n * Packaged same-origin backend for the React conversation surfaces.\n *\n * Mount the handler at a catch-all route (for example `/api/opengeni/*`) and\n * point an unmodified browser `OpenGeniClient({ baseUrl: \"/api/opengeni\" })`\n * at it. Every request is authenticated by the host's `resolve` hook, pinned\n * to the resolved workspace, executed as the resolved external user through\n * `asUser` (never the organization key's own service authority), and limited\n * to the exact native routes `SessionConversation` and its hooks use. It is\n * an explicit dispatcher, not an arbitrary upstream proxy.\n */\n\ntype ProxyClient = OpenGeniEmbeddingClient;\n\n/** The `@opengeni/sdk/chat` `Opengeni` facade, structurally. */\ntype ProxyFacade = {\n readonly client: ProxyClient;\n readonly source: string;\n workspaceId(target: { tenant: string }): Promise<string>;\n workspaceIdFor?(target: WorkspaceIdTarget, options: WorkspaceIdOptions): Promise<string>;\n};\n\n/**\n * Who the authenticated request acts as, in your own ids. Never derive any of\n * it from the request body or path. `{ user, tenant }`: one workspace per\n * tenant. `{ user }`: one workspace per user. `{ user, workspaceId }`: your\n * own workspace. Tenant and per-user mapping require the `Opengeni` facade\n * from `@opengeni/sdk/chat`; workspaces are created on first use and Opengeni\n * adds the user on their first request.\n */\nexport type SessionProxyResolution = (\n | { workspaceId: string; tenant?: undefined }\n | { tenant: string; workspaceId?: undefined }\n | { tenant?: undefined; workspaceId?: undefined }\n) & {\n /** Host-authenticated external user id; every call runs through `asUser(user)`. */\n user: string;\n /** External identity source. Defaults to the facade's `source`, else `\"default\"`. */\n source?: string | undefined;\n /**\n * The user is an anonymous visitor your product has not signed in, for\n * example a website visitor keyed by a cookie. Visitors cannot upload\n * composer file attachments unless the handler sets `visitorUploads: true`;\n * everything else is unchanged.\n */\n visitor?: boolean | undefined;\n};\n\n/** Host auth hook: return the resolution, or a `Response` (for example 401) to reject. */\nexport type SessionProxyResolve = (\n request: Request,\n) => Promise<SessionProxyResolution | Response> | SessionProxyResolution | Response;\n\nexport type SessionProxyContext = {\n request: Request;\n workspaceId: string;\n user: string;\n source: string;\n /** The `asUser` client the proxy uses for this request. */\n client: ProxyClient;\n};\n\n/**\n * The only fields a browser may send when creating a session through the proxy,\n * besides `modelContext`, which the proxy appends after any context the hook\n * and `messageExtras` return, as it does for follow-up messages.\n * After the `createSession` hook returns, the proxy adds the attached files to\n * the created request (deduplicated by file id) and, when `modelSelection` is\n * not `false`, applies the browser's explicit model choices over the hook's,\n * exactly as follow-up messages carry them. Return a `Response` from the hook\n * to refuse an input.\n */\nexport type SessionProxyCreateInput = {\n /** Empty for a voice-first session; no initial user message is fabricated. */\n initialMessage: string;\n /** Available only while the proxy permits realtime voice. */\n startMode?: \"realtime\" | undefined;\n /** Browser retry key; replay is scoped to the acting user by the API. */\n idempotencyKey?: string | undefined;\n /** Files attached to the first message (uploaded through this proxy). */\n resources?: FileResourceRef[] | undefined;\n /** The user's model choice; only when `modelSelection` is not `false`. */\n model?: string | undefined;\n /** The user's reasoning choice; only when `modelSelection` is not `false`. */\n reasoningEffort?: ReasoningEffort | undefined;\n /** The user's latency choice; only when `modelSelection` is not `false`. */\n latencyMode?: LatencyMode | undefined;\n};\n\n/** Which browser action is about to forward a user message or response. */\nexport type SessionProxyMessageInput = {\n /** Absent for `create`. */\n sessionId?: string | undefined;\n /** An empty voice-first session shell, not an initial model-producing turn. */\n startMode?: \"realtime\" | undefined;\n /**\n * `realtime` is live voice: once when a call starts (refuse it, or rotate\n * MCP credentials), and before each batch of finalized transcripts and spoken\n * requests is saved (refuse it, or add `modelContext`).\n */\n delivery: \"create\" | \"send\" | \"steer\" | \"submit\" | \"realtime\";\n};\n\n/** Server-side additions the host attaches to one forwarded user message or response. */\nexport type SessionProxyMessageExtras = {\n /**\n * Model-visible context for this message (current page, time zone, today's\n * date). Placed before any context the browser sent. Not secret. Ignored for\n * approval decisions and human-input responses, which are not new messages,\n * and when a live voice call starts. Keep it stable for the same message:\n * a retried voice entry must carry the same context to be accepted.\n */\n modelContext?: string | undefined;\n /**\n * Header-only credential rotation for MCP servers already attached to the\n * session (for example a fresh short-lived per-user bearer), applied\n * atomically as the message or response is accepted. Ignored for `create`,\n * where the `createSession` hook sets the initial headers.\n */\n mcpCredentialUpdates?: SessionMcpCredentialUpdateInput[] | undefined;\n};\n\n/**\n * Your product's own MCP tool server, attached to every session this proxy\n * creates with a per-user bearer token. Verify it on every MCP request with\n * `verifyToolRequest` from `@opengeni/sdk/tool-auth`. Tools always act as the\n * chat's creator: in a shared chat, other members' messages do not change it.\n */\nexport type SessionProxyToolServer = {\n /**\n * Public HTTPS URL of your MCP endpoint, e.g. `https://app.example.com/api/mcp`.\n * Defaults to `OPENGENI_TOOL_SERVER_URL`, which `verifyToolRequest` also reads.\n */\n url?: string | undefined;\n /** Session MCP server id (model-facing tool prefix). Defaults to `\"app\"`. */\n id?: string | undefined;\n /** Display name. */\n name?: string | undefined;\n /**\n * Tools the user must approve before each call: list your write tools here\n * (unprefixed MCP tool names), or `true` for every tool. Others run directly.\n */\n approvals?: { ask: string[] | true } | undefined;\n /**\n * Tools the agent has from the first model request, so everyday reads (for\n * example search and get-by-id) need no `tool_search` round trip: unprefixed\n * MCP tool names, or `true` for every tool. Other tools stay searchable. Keep\n * the list short and stable: every listed schema is part of each request.\n */\n eager?: string[] | true | undefined;\n /** Token signing secret. Defaults to `OPENGENI_API_KEY`; `verifyToolRequest` must use the same. */\n secret?: string | undefined;\n /** Token lifetime in seconds. Defaults to 24 hours; refreshed on every message, approval, and answer. */\n ttlSeconds?: number | undefined;\n};\n\nexport type SessionProxyHandlerOptions = {\n /**\n * Private (default) uses personal Knowledge and session-only reach; shared uses\n * workspace Knowledge and reach. Isolated also gives each user their own tenant workspace.\n */\n chats?: Chats | undefined;\n /** Mandatory host auth hook, called on every request. */\n resolve: SessionProxyResolve;\n /**\n * Host CSRF/session policy for non-GET requests. Without it the proxy only\n * rejects `Sec-Fetch-Site: cross-site` mutations and requires JSON bodies;\n * cookie-authenticated hosts should supply their existing CSRF check.\n */\n authorizeMutation?: ((request: Request) => boolean | Promise<boolean>) | undefined;\n /**\n * Optional product-level session check (for example \"this ticket's session\n * belongs to this user\"). Opengeni still enforces membership and private\n * visibility on every call.\n */\n authorizeSession?:\n | ((sessionId: string, context: SessionProxyContext) => boolean | Promise<boolean>)\n | undefined;\n /**\n * Server-controlled session creation. The browser supplies only\n * {@link SessionProxyCreateInput}; this hook returns the complete create\n * request (agent, tools, MCP servers, Skills, instructions, model policy). Omit it\n * to disable browser-initiated creation entirely.\n */\n createSession?:\n | ((\n input: SessionProxyCreateInput,\n context: SessionProxyContext,\n ) => CreateSessionRequest | Response | Promise<CreateSessionRequest | Response>)\n | undefined;\n /**\n * Called before every forwarded user message (send, steer, composer submit,\n * and browser-started create), approval decision, human-input response, and\n * live voice start and transcript save (`delivery: \"realtime\"`).\n * Return server-owned `modelContext` (messages and voice transcripts only)\n * and MCP credential rotations, or a `Response` to reject the action.\n */\n beforeForwardMessage?:\n | ((\n input: SessionProxyMessageInput,\n context: SessionProxyContext,\n ) =>\n | SessionProxyMessageExtras\n | Response\n | undefined\n | Promise<SessionProxyMessageExtras | Response | undefined>)\n | undefined;\n /**\n * Attach your product's MCP tool server to every session the `createSession`\n * hook creates, authenticated as the resolved user. The proxy mints the\n * token, adds the `mcpServers` entry (with its `eager` tools, or every tool\n * when the hook lists explicit `tools`), and rotates the token on every send,\n * steer, submit, approval decision, and human-input answer.\n */\n toolServer?: SessionProxyToolServer | undefined;\n /** Mount prefix, e.g. `/api/opengeni`. Defaults to everything before the first `/v1/`. */\n basePath?: string | undefined;\n /** Maximum JSON request body. Defaults to 1 MiB. */\n maxBodyBytes?: number | undefined;\n /**\n * Expose composer file attachments (upload begin/complete, download URL) and\n * the media agents produce in a session: generated images, browser and\n * computer screenshots, published sandbox files, and generated video\n * playback. Workspace-level artifact reads must name their session in the\n * `x-opengeni-session-id` header (`SessionConversation` does this); the proxy\n * runs `authorizeSession` and only forwards an artifact Opengeni proves that\n * session produced. Defaults to true.\n */\n files?: boolean | undefined;\n /**\n * Let anonymous visitors (`resolve` returned `visitor: true`) upload composer\n * file attachments. Defaults to false: for a visitor the client config reports\n * file uploads off, so stock UIs hide the attach button, and the upload routes\n * are refused. Agent-produced media stays readable under `files`. Signed-in\n * users follow `files` alone.\n */\n visitorUploads?: boolean | undefined;\n /**\n * Forward composer voice input (`POST .../transcriptions`, one recording per\n * request) as the resolved user; Opengeni still requires that user's\n * `sessions:create` permission and the workspace's voice-input setting.\n * `false` reports voice input unavailable in the client config so stock UIs\n * hide the microphone. Defaults to true.\n */\n voiceInput?: boolean | undefined;\n /**\n * Forward live speech-to-speech voice for existing chats as the resolved\n * user: the voice model catalog and the call lifecycle routes under\n * `.../sessions/{id}/realtime`. Opengeni still requires that user's\n * `sessions:control` permission, binds the call to that user and browser,\n * runs spoken requests as ordinary steers of the chat, and meters\n * deployment-funded voice against the organization's credits. Defaults to\n * true. The stock conversation's voice button is opt-in: explicit `true`\n * reports `realtimeVoice: true` in the client config so `SessionConversation`\n * and `OpenGeniChat` show it (when a voice model is available), as does their\n * own `realtimeVoice` prop. `false` reports `realtimeVoice: false` so stock\n * UIs hide it, and refuses the routes.\n */\n realtimeVoice?: boolean | undefined;\n /**\n * Let the browser read a file from the session's sandbox (`POST .../fs/read`)\n * so `sandbox:` links in agent replies can be downloaded. Only `path`,\n * `encoding`, and `maxBytes` are forwarded; Opengeni still requires the\n * user's `files:read` permission on that session. Explicit opt-in, default\n * false. Reads are confined to its working directory, including on Connected\n * Machines; symlinked paths are refused.\n */\n sandboxFiles?: boolean | undefined;\n /**\n * Serve the embedded artifact viewer and inline Site previews: reads of the\n * editable artifacts and Sites a session produced, and live-ticket minting\n * for the editor. Explicit opt-in, default false.\n *\n * Every request must name its session in the `x-opengeni-session-id` header\n * (`SessionArtifactViewer` and `SessionConversation` do this). The proxy\n * runs `authorizeSession`, then only forwards an artifact Opengeni associates with\n * that session, so the browser cannot open other workspace artifacts through\n * it. Editing still requires the user's own `artifacts:publish` grant. Site\n * tool calls are not proxied.\n *\n * The editor's live socket is ticket-authenticated and connects to Opengeni\n * directly; the ticket binds the source session and the API revalidates its\n * authority while connected. `editableLiveUrl` overrides the derived URL.\n * Site HTML streams with backpressure and cancellation, with a 25 MiB\n * actual-byte ceiling (`SESSION_PROXY_SITE_HTML_MAX_BYTES`). Oversize streams\n * fail with `SessionProxySiteHtmlTooLargeError` / `site_html_too_large`;\n * headers cannot be replaced once streaming has begun.\n */\n artifacts?: boolean | { editableLiveUrl?: string | undefined } | undefined;\n /**\n * Read the workspace's Sites without naming a session: list, detail,\n * content and HTML of published artifacts the signed-in user may read, for\n * pages that belong to the workspace rather than to one chat (for example a\n * page several sessions keep up to date, shown with `SiteDetail`). Read-only:\n * publishing, rollback and status changes stay closed. Requests that send\n * `x-opengeni-session-id` keep the session-scoped `artifacts` checks.\n * Explicit opt-in, default false.\n */\n sites?: boolean | undefined;\n /**\n * Let the product's Excel add-in connect the open workbook for the signed-in\n * user: `POST /v1/workspaces/{ws}/office/workbook-tickets` and\n * `GET /v1/workspaces/{ws}/office/workbooks`. The workbook belongs to that\n * user in the resolved workspace; agents working for them there reach it with\n * `excel_run`. The ticket authenticates the add-in's WebSocket to\n * `/v1/office/workbooks/live`, which the host passes through to the Opengeni\n * API itself (see `@opengeni/sdk/office` and docs/excel-addin.md).\n * Explicit opt-in, default false.\n */\n office?: boolean | undefined;\n /**\n * Serve the packaged session app (`SessionApp` from\n * `@opengeni/react/session-app`, with `apiBaseUrl` set to this proxy) besides\n * the conversation components. Explicit opt-in, default false.\n *\n * Every route above keeps its rules (this proxy's `createSession` hook, the\n * message hooks, the model, upload, voice, artifact and file switches). On\n * top of them:\n *\n * - `GET /v1/access/me` and `GET /v1/workspaces` answer with the resolved\n * user's access to the resolved workspace only.\n * - Other `GET` routes in the resolved workspace, and in a chat the user may\n * open (`authorizeSession`), are read as the resolved user, so Opengeni's\n * permissions for that user decide what they see.\n * - A short list of the app's own writes passes as the resolved user:\n * pinning a chat, moving it to a project, managing projects and a chat's\n * tool approval settings. Every other write is refused.\n * - Catalog logos are served from the Opengeni API.\n * - Creating a chat also takes the app's own create fields: the id of its\n * first message and the new-chat draft revision it sent. It sends\n * `visibility` and `connectionAccounts` too; the server chooses both.\n */\n sessionApp?: boolean | undefined;\n /**\n * Chat list for `SessionList` / `OpenGeniChat` (`listSessionPage` only).\n * `\"mine\"` (default) lists sessions the resolved user created; `\"visible\"`\n * lists every session Opengeni lets that user read in the workspace (shared\n * chats included); `false` disables listing.\n */\n sessionList?: \"mine\" | \"visible\" | false | undefined;\n /** Let the user archive or restore their own chats. Defaults to true. */\n archive?: boolean | undefined;\n /**\n * Let the browser choose model, reasoning effort, and latency per message,\n * draft, or new chat (still limited by the workspace model catalog). When\n * false those choices are removed from messages and draft saves, and refused\n * on create. Saves use the actor's\n * server-owned draft policy (initially the session defaults). Submit must repeat\n * the saved policy unchanged as an integrity fence, not a new selection: the\n * API atomically checks the saved revision/content or replays the original\n * receipt. Hide the composer's model picker to match. Defaults to true.\n * Pass `true` explicitly to also show end users the stock model picker\n * (`SessionConversation`/`OpenGeniChat` hide it unless asked). The picker\n * lists the workspace's model catalog, so the workspace's allowed-model\n * settings decide which models end users see.\n */\n modelSelection?: boolean | undefined;\n /**\n * SSE heartbeat interval. Defaults to 5 seconds, under Bun.serve's default\n * 10-second `idleTimeout`, which otherwise closes a quiet event stream.\n */\n heartbeatMs?: number | undefined;\n};\n\n/**\n * Default SSE heartbeat. Bun.serve closes a connection that sends nothing for\n * 10 seconds by default, so a quiet stream (a long tool call, an idle chat)\n * would drop and reconnect every 10 seconds through a Bun or Hono-on-Bun host.\n */\nconst SESSION_PROXY_DEFAULT_HEARTBEAT_MS = 5_000;\n\nconst DEFAULT_MAX_BODY_BYTES = 1024 * 1024;\nconst SEGMENT = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;\nconst QUEUE_OPERATIONS: ReadonlySet<string> = new Set([\"move\", \"edit\", \"steer\", \"delete\"]);\nconst CREATE_FIELDS: ReadonlySet<string> = new Set([\n \"initialMessage\",\n \"idempotencyKey\",\n \"resources\",\n \"startMode\",\n \"modelContext\",\n]);\n/** Extra fields the packaged session app sends on create (see `browserCreateFields`). */\nconst SESSION_APP_CREATE_FIELDS: ReadonlySet<string> = new Set([\n \"visibility\",\n \"clientEventId\",\n \"connectionAccounts\",\n \"expectedNewSessionDraftRevision\",\n]);\nconst MODEL_FIELDS = [\"model\", \"reasoningEffort\", \"latencyMode\"] as const;\n/** The API's single-recording ceiling (25 MiB) plus multipart framing. */\nconst MAX_TRANSCRIPTION_BODY_BYTES = 25 * 1024 * 1024 + 64 * 1024;\n\nclass ProxyRejection extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n ) {\n super(message);\n }\n}\n\nfunction reject(status: number, code: string, message: string): never {\n throw new ProxyRejection(status, code, message);\n}\n\nfunction json(body: unknown, status = 200, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n ...headers,\n },\n });\n}\n\nfunction errorJson(status: number, code: string, message: string): Response {\n return json({ error: { code, message } }, status);\n}\n\nfunction isFacade(target: ProxyClient | ProxyFacade): target is ProxyFacade {\n return !(\"asUser\" in target) && \"client\" in target;\n}\n\n/**\n * Create the packaged session proxy. Returns a web-standard\n * `(Request) => Promise<Response>` for Next.js route handlers, Hono, Bun.serve,\n * Cloudflare Workers, and similar hosts.\n */\nexport function createSessionProxyHandler(\n target: ProxyClient | ProxyFacade,\n options: SessionProxyHandlerOptions,\n): (request: Request) => Promise<Response> {\n const service = isFacade(target) ? target.client : target;\n const defaultSource = isFacade(target) ? target.source : \"default\";\n // One rejected-key notice per handler (each handler holds one server key).\n const rejectedKeyNotice = { sent: false };\n const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;\n const filesEnabled = options.files ?? true;\n const voiceInputEnabled = options.voiceInput ?? true;\n const realtimeVoiceEnabled = options.realtimeVoice ?? true;\n const sandboxFilesEnabled = options.sandboxFiles === true;\n const artifactsEnabled = options.artifacts !== undefined && options.artifacts !== false;\n const sitesEnabled = options.sites === true;\n const officeEnabled = options.office === true;\n const sessionAppEnabled = options.sessionApp === true;\n const editableLiveUrl = artifactsEnabled\n ? liveSocketUrl(\n (typeof options.artifacts === \"object\" ? options.artifacts.editableLiveUrl : undefined) ??\n service.apiUrl(EDITABLE_ARTIFACT_LIVE_PATH),\n )\n : null;\n const modelSelection = options.modelSelection ?? true;\n const heartbeatMs = options.heartbeatMs ?? SESSION_PROXY_DEFAULT_HEARTBEAT_MS;\n const sessionList = options.sessionList ?? \"mine\";\n const archiveEnabled = options.archive ?? true;\n const chats = options.chats ?? \"private\";\n const defaults = chatDefaults(chats);\n const toolServer = options.toolServer ? normalizeToolServer(options.toolServer) : undefined;\n // Whether a session carries this proxy's tool server (attachments are immutable).\n const toolSessions = new Map<string, Promise<string | null>>();\n // Canonical subject per external user, for the \"mine\" list filter.\n const subjects = new Map<string, Promise<string>>();\n const subjectOf = (client: ProxyClient, key: string): Promise<string> => {\n let subject = subjects.get(key);\n if (!subject) {\n subject = client.getAccessContext().then((access) => access.subjectId);\n subject.catch(() => subjects.delete(key));\n if (subjects.size >= 1_000) subjects.delete(subjects.keys().next().value!);\n subjects.set(key, subject);\n }\n return subject;\n };\n\n return async (request) => {\n try {\n const method = request.method;\n if (!PROXY_METHODS.includes(method)) {\n return new Response(null, {\n status: 405,\n headers: { Allow: PROXY_METHODS.join(\", \") },\n });\n }\n const resolved = await options.resolve(request);\n if (resolved instanceof Response) return resolved;\n if (typeof resolved?.user !== \"string\" || !resolved.user) {\n // Never fall back to the organization key's service authority.\n return errorJson(401, \"user_required\", \"Authentication required.\");\n }\n const url = new URL(request.url);\n if (sessionAppEnabled && method === \"GET\") {\n // Catalog logos the session app shows beside connectors and tools.\n const asset = catalogAssetPath(url.pathname, options.basePath);\n if (asset) {\n try {\n const blob = await service.downloadCatalogAsset(asset, { signal: request.signal });\n return new Response(blob, {\n headers: { \"Content-Type\": blob.type, \"Cache-Control\": \"public, max-age=3600\" },\n });\n } catch {\n // Missing, malformed or not an image: the app shows its fallback mark.\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n }\n }\n const segments = routeSegments(url.pathname, options.basePath);\n if (!segments) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n\n if (method !== \"GET\") {\n const allowed = options.authorizeMutation\n ? await options.authorizeMutation(request)\n : request.headers.get(\"sec-fetch-site\") !== \"cross-site\";\n if (!allowed) return errorJson(403, \"mutation_denied\", \"Request denied.\");\n }\n const source = resolved.source ?? defaultSource;\n let workspaceId: string;\n // A tenant/workspaceId key that resolves to nothing must never fall\n // through to the per-user workspace: that is a host auth bug, not a choice.\n if (\n (\"workspaceId\" in resolved && !resolved.workspaceId && !resolved.tenant) ||\n (\"tenant\" in resolved && !resolved.tenant && !resolved.workspaceId) ||\n resolved.workspaceId === \"\" ||\n resolved.tenant === \"\"\n ) {\n throw new TypeError(\n \"resolve returned an empty tenant or workspaceId. Return a non-empty id, or omit the key for one workspace per user.\",\n );\n }\n if (chats === \"isolated\") {\n if (resolved.workspaceId || !isFacade(target) || !target.workspaceIdFor) {\n throw new TypeError(\n 'chats: \"isolated\" requires the Opengeni facade and a tenant or user resolution.',\n );\n }\n workspaceId = await target.workspaceIdFor(\n { tenant: resolved.tenant, user: resolved.user, source },\n { isolation: \"user\" },\n );\n } else if (resolved.workspaceId) {\n workspaceId = resolved.workspaceId;\n } else if (resolved.tenant && isFacade(target)) {\n workspaceId = await target.workspaceId({ tenant: resolved.tenant });\n } else if (\n !(\"tenant\" in resolved) &&\n !(\"workspaceId\" in resolved) &&\n isFacade(target) &&\n target.workspaceIdFor\n ) {\n // A user alone: their own workspace, keyed by the identity source.\n workspaceId = await target.workspaceIdFor(\n { user: resolved.user, source },\n { isolation: \"user\" },\n );\n } else {\n throw new TypeError(\n \"resolve must return a workspaceId (or a tenant or a user alone when given the Opengeni facade).\",\n );\n }\n // Visitors upload only when the host opts them in; reads stay under `files`.\n const uploadsEnabled =\n filesEnabled && (resolved.visitor !== true || options.visitorUploads === true);\n const client = service.asUser(resolved.user, { source });\n const context: SessionProxyContext = {\n request,\n workspaceId,\n user: resolved.user,\n source,\n client,\n };\n\n const call = { signal: request.signal };\n const toolToken = async () =>\n await mintToolToken({\n audience: toolServer!.url,\n user: resolved.user,\n tenant: resolved.tenant,\n workspaceId,\n source,\n secret: toolServer!.secret,\n ttlSeconds: toolServer!.ttlSeconds,\n });\n /** The creator's subject when the session carries this tool server, else null. */\n const toolServerOwner = (sessionId: string): Promise<string | null> => {\n const key = `${workspaceId}\\u0000${sessionId}`;\n let attached = toolSessions.get(key);\n if (!attached) {\n attached = client\n .getSession(workspaceId, sessionId, call)\n .then((session) =>\n (session.mcpServers ?? []).some(\n (server) => server.id === toolServer!.id && server.url === toolServer!.url,\n )\n ? (session.createdBy?.subjectId ?? null)\n : null,\n );\n attached.catch(() => toolSessions.delete(key));\n if (toolSessions.size >= 1_000) toolSessions.delete(toolSessions.keys().next().value!);\n toolSessions.set(key, attached);\n }\n return attached;\n };\n const messageExtras = async (\n input: SessionProxyMessageInput,\n ): Promise<SessionProxyMessageExtras | Response | undefined> => {\n const extras = options.beforeForwardMessage\n ? await options.beforeForwardMessage(input, context)\n : undefined;\n if (extras instanceof Response || !toolServer || !input.sessionId) return extras;\n const updates = extras?.mcpCredentialUpdates ?? [];\n // A host-supplied rotation for the same id wins; sessions created\n // without this tool server (or for an older URL) are left alone.\n if (updates.some((update) => update.id === toolServer.id)) return extras;\n // Only the chat's creator refreshes: tools keep acting as that user.\n const owner = await toolServerOwner(input.sessionId);\n if (!owner || owner !== (await subjectOf(client, `${source}\\u0000${resolved.user}`))) {\n return extras;\n }\n return {\n ...extras,\n mcpCredentialUpdates: [\n ...updates,\n {\n id: toolServer.id,\n headers: { Authorization: `Bearer ${await toolToken()}` },\n },\n ],\n };\n };\n /**\n * Best-effort standalone rotation before a voice call. Opengeni refuses\n * it while a turn is running; that turn's message already refreshed them.\n */\n const refreshRealtimeCredentials = async (\n sessionId: string,\n updates: SessionMcpCredentialUpdateInput[],\n ): Promise<void> => {\n if (updates.length === 0) return;\n try {\n const servers = (await client.getSession(workspaceId, sessionId, call)).mcpServers ?? [];\n const rotations = updates.flatMap((update) => {\n const server = servers.find((candidate) => candidate.id === update.id);\n return server\n ? [\n {\n id: update.id,\n expectedCredentialVersion: server.credentialVersion,\n expectedServerUrl: server.url,\n headers: update.headers,\n },\n ]\n : [];\n });\n if (rotations.length === 0) return;\n await client.rotateSessionMcpCredentials(workspaceId, sessionId, {\n operationKey: crypto.randomUUID(),\n updates: rotations,\n });\n } catch (error) {\n if (!(error instanceof OpenGeniApiError)) throw error;\n }\n };\n /** Browser input sanitized, then server-owned extras merged in. */\n const forwardMessage = async (\n value: unknown,\n input: SessionProxyMessageInput,\n ): Promise<Record<string, unknown> | Response> => {\n // Submit repeats the saved policy as a mandatory integrity fence. Never\n // replace it with a newer draft's policy: outcome-unknown retries must\n // retain the original receipt hash. The API rejects any new selection.\n const message = sanitizeMessage(value, modelSelection || input.delivery === \"submit\");\n const extras = await messageExtras(input);\n if (extras instanceof Response) return extras;\n const modelContext = joinContext(\n extras?.modelContext,\n typeof message.modelContext === \"string\" ? message.modelContext : undefined,\n );\n return {\n ...message,\n ...(modelContext ? { modelContext } : {}),\n ...(extras?.mcpCredentialUpdates?.length\n ? { mcpCredentialUpdates: extras.mcpCredentialUpdates }\n : {}),\n };\n };\n /** Responses reuse send hooks unchanged; only credentials are added. */\n const forwardResponse = async (\n value: unknown,\n input: SessionProxyMessageInput,\n ): Promise<Record<string, unknown> | Response> => {\n const payload = browserPayload(value);\n const extras = await messageExtras(input);\n if (extras instanceof Response) return extras;\n return {\n ...payload,\n ...(extras?.mcpCredentialUpdates?.length\n ? { mcpCredentialUpdates: extras.mcpCredentialUpdates }\n : {}),\n };\n };\n // Unknown additive query parameters on allowlisted reads pass through, so a\n // newer browser SDK keeps working; the route and method allowlist is exact.\n const query = Object.fromEntries(url.searchParams);\n const read = async (path: string) => {\n const body = await client.requestJson(\"GET\", path, undefined, query, call);\n // Keep the projection's read-consistency sequence for the browser hooks.\n const sequence = observedSessionSequence(body);\n return json(\n body,\n 200,\n sequence === undefined ? {} : { [SESSION_SEQUENCE_HEADER]: String(sequence) },\n );\n };\n const [root, ...rest] = segments;\n // Session app reads and its listed writes, as the resolved user. The\n // response passes through unread: JSON, an event stream or a file.\n const passThrough = async (path: string, body?: Record<string, unknown>) => {\n const search = new URLSearchParams(query).toString();\n const upstream = await client.fetchApi(client.apiUrl(search ? `${path}?${search}` : path), {\n method,\n headers: {\n Accept: request.headers.get(\"accept\") ?? \"application/json\",\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n signal: request.signal,\n });\n // Opengeni's own answer, errors included, with only neutral headers.\n const headers = new Headers({ \"Cache-Control\": \"no-store\" });\n for (const name of PASS_THROUGH_HEADERS) {\n const value = upstream.headers.get(name);\n if (value !== null) headers.set(name, value);\n }\n return new Response(upstream.body as BodyInit | null, {\n status: upstream.status,\n headers,\n });\n };\n // The app's bootstrap: only the resolved workspace, never the user's\n // other workspaces or the key's own authority.\n if (sessionAppEnabled && method === \"GET\" && root === \"workspaces\" && rest.length === 0) {\n const workspaces = await client.listWorkspaces();\n return json(workspaces.filter((workspace) => workspace.id === workspaceId));\n }\n if (\n sessionAppEnabled &&\n method === \"GET\" &&\n root === \"access\" &&\n rest.length === 1 &&\n rest[0] === \"me\"\n ) {\n // An external actor's access inventory is empty: its authority for this\n // workspace is the effective grant, so the app gets exactly that grant.\n const [access, grant] = await Promise.all([\n client.getAccessContext(),\n getSessionProxyWorkspaceGrant(client, workspaceId, call),\n ]);\n return json(scopedAccessContext(access, grant));\n }\n if (root === \"config\") {\n if (rest.length === 1 && rest[0] === \"client\" && method === \"GET\") {\n // The browser speaks this proxy's contract, not the upstream deployment's:\n // report the server SDK's revision so an Opengeni deploy never makes the\n // embedded page look stale (and never triggers a host reload).\n const config = await client.requestJson<Record<string, unknown>>(\n \"GET\",\n \"/v1/config/client\",\n undefined,\n { ...query, workspaceId },\n call,\n );\n let artifacts: Awaited<ReturnType<typeof artifactViewerCapability>> | null = null;\n if (editableLiveUrl) {\n try {\n // Successful effective-grant resolution negotiates the viewer's\n // narrow API support. Older APIs do not have this endpoint: that\n // 404 disables only artifacts, not ordinary conversation config.\n artifacts = {\n editableLiveUrl,\n cachePartition: await cachePartition(\n await getSessionProxyWorkspaceGrant(client, workspaceId, call),\n workspaceId,\n source,\n ),\n };\n } catch (error) {\n if (!(error instanceof OpenGeniApiError) || error.status !== 404) throw error;\n }\n }\n // Upstream proxy capabilities never authorize this host's routes.\n // Task usage limits are set by this host's server, never through the\n // browser boundary, so the producer capability is not forwarded.\n const {\n artifacts: _upstreamArtifacts,\n sessionUsageLimits: _upstreamUsageLimits,\n ...conversationConfig\n } = config;\n const upstreamVoice = config.voiceInput;\n if (upstreamVoice && typeof upstreamVoice === \"object\") {\n // Only one-shot recordings are forwarded, never resumable chunk uploads.\n const { resumable: _resumable, ...voice } = upstreamVoice as Record<string, unknown>;\n conversationConfig.voiceInput = voiceInputEnabled\n ? voice\n : { ...voice, available: false };\n }\n const upstreamUploads = config.fileUploads;\n if (!uploadsEnabled) {\n // The browser cannot upload through this proxy: stock UIs hide the attach control.\n conversationConfig.fileUploads = {\n ...(upstreamUploads && typeof upstreamUploads === \"object\" ? upstreamUploads : {}),\n enabled: false,\n };\n }\n return json({\n ...conversationConfig,\n apiContractRevision: OPENGENI_API_CONTRACT_REVISION,\n // The resolved workspace: a browser given only the proxy's baseUrl\n // reads it here instead of knowing any Opengeni id.\n workspaceId,\n sandboxFiles: sandboxFilesEnabled,\n // Stock UIs show Site previews and the artifact viewer only when\n // this proxy serves them; `false` keeps them from failing on click.\n artifacts: artifacts ?? false,\n // Whether the stock \"New chat\" and \"Archive\" actions can succeed.\n sessionCreation: options.createSession !== undefined,\n archive: archiveEnabled,\n // Explicit true also tells stock UIs to show the voice button, which\n // is otherwise opt-in on the embedded conversation.\n ...(realtimeVoiceEnabled\n ? options.realtimeVoice === true\n ? { realtimeVoice: true }\n : {}\n : { realtimeVoice: false }),\n // Explicit true also tells stock UIs to offer end users the model picker.\n ...(modelSelection\n ? options.modelSelection === true\n ? { modelSelection: true }\n : {}\n : { modelSelection: false }),\n });\n }\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n if (root !== \"workspaces\" || rest.length < 1) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n const [pathWorkspaceId, area, ...tail] = rest as [string, string | undefined, ...string[]];\n if (pathWorkspaceId !== workspaceId) {\n return errorJson(403, \"workspace_not_allowed\", \"This workspace is not available.\");\n }\n const base = `/v1/workspaces/${workspaceId}`;\n\n // Only the resolved user's own usage. No full roster, allowance config,\n // member selectors, or controls can pass through this browser boundary.\n if (area === \"usage\" && tail.length === 1 && tail[0] === \"me\" && method === \"GET\") {\n if (Object.keys(query).some((key) => key !== \"period\")) {\n return errorJson(400, \"invalid_usage_query\", \"Only period is accepted for own usage.\");\n }\n return await read(`${base}/usage/me`);\n }\n\n // Workspace reads and the live control stream used by <OpenGeniProvider>.\n if (area === undefined && method === \"GET\") return await read(base);\n if (area === \"model-catalog\" && tail.length === 0 && method === \"GET\") {\n return await read(`${base}/model-catalog`);\n }\n if (area === \"realtime-model-catalog\" && tail.length === 0 && method === \"GET\") {\n if (!realtimeVoiceEnabled) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n return await read(`${base}/realtime-model-catalog`);\n }\n if (area === \"live-events\" && tail.length === 1 && tail[0] === \"stream\" && method === \"GET\") {\n // Surface authorization failures as HTTP status before streaming.\n await client.requestJson(\"GET\", base, undefined, {}, call);\n return workspaceLiveStream(client, workspaceId, url.searchParams, request, heartbeatMs);\n }\n if (area === \"inference-control\" && tail.length === 0 && method === \"POST\") {\n // The conversation's paused-state UI only offers workspace Resume.\n const body = await readJsonBody(request, maxBodyBytes);\n if (body?.action !== \"resume\") {\n reject(403, \"control_not_allowed\", \"Only workspace resume is available.\");\n }\n return json(await client.requestJson(\"POST\", `${base}/inference-control`, body));\n }\n\n if (area === \"office\" && officeEnabled && tail.length === 1) {\n if (tail[0] === \"workbook-tickets\" && method === \"POST\") {\n return json(await client.requestJson(\"POST\", `${base}/office/workbook-tickets`, {}));\n }\n if (tail[0] === \"workbooks\" && method === \"GET\") {\n return await read(`${base}/office/workbooks`);\n }\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n\n if (area === \"files\" && filesEnabled && method === \"POST\") {\n if (tail[0] === \"uploads\" && !uploadsEnabled) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n if (tail.length === 1 && tail[0] === \"uploads\") {\n const body = await readJsonBody(request, maxBodyBytes);\n return json(\n await client.requestJson(\"POST\", `${base}/files/uploads`, pick(body, UPLOAD_FIELDS)),\n );\n }\n if (tail.length === 3 && tail[0] === \"uploads\" && tail[2] === \"complete\") {\n return json(\n await client.requestJson(\"POST\", `${base}/files/uploads/${tail[1]}/complete`),\n );\n }\n if (tail.length === 2 && tail[1] === \"download-url\") {\n return json(\n await client.requestJson(\n \"POST\",\n `${base}/files/${tail[0]}/download-url`,\n undefined,\n query,\n call,\n ),\n );\n }\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n\n if (area === \"artifacts\") {\n // Retained media a session produced: only an artifact Opengeni proves\n // that session produced, never an arbitrary workspace artifact.\n const [artifactId, ...artifactOp] = tail as [string | undefined, ...string[]];\n const route = `${method} ${artifactOp.join(\"/\")}`;\n if (\n !filesEnabled ||\n !artifactId ||\n !SEGMENT.test(artifactId) ||\n (route !== \"GET content\" && route !== \"POST playback-source\")\n ) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n const sessionId = request.headers.get(SESSION_SCOPE_HEADER)?.trim() ?? \"\";\n if (!SEGMENT.test(sessionId)) {\n reject(400, \"session_scope_required\", \"Artifact reads must name their session.\");\n }\n if (options.authorizeSession && !(await options.authorizeSession(sessionId, context))) {\n return errorJson(404, \"session_not_found\", \"Session not found.\");\n }\n await getSessionProxyArtifactAssociation(\n client,\n workspaceId,\n sessionId,\n \"retained\",\n artifactId,\n call,\n );\n if (route === \"POST playback-source\") {\n return json(\n await client.requestJson(\n \"POST\",\n `${base}/artifacts/${artifactId}/playback-source`,\n undefined,\n {},\n call,\n ),\n );\n }\n return retainedContent(\n await client.getRetainedArtifactContent(workspaceId, artifactId, {\n ...retainedRange(request),\n signal: request.signal,\n }),\n );\n }\n\n if (area === \"transcriptions\" && tail.length === 0 && method === \"POST\") {\n if (!voiceInputEnabled) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n return json(await client.transcribeAudio(workspaceId, await transcriptionInput(request)));\n }\n\n if (area === \"editable-artifacts\" || area === \"published-artifacts\") {\n if (\n area === \"published-artifacts\" &&\n sitesEnabled &&\n !request.headers.get(SESSION_SCOPE_HEADER)\n ) {\n // Workspace Sites under Opengeni's own read authorization for this user.\n const [siteId, ...siteOp] = tail as [string | undefined, ...string[]];\n const op = siteOp.join(\"/\");\n if (method !== \"GET\") return errorJson(404, \"route_not_allowed\", \"Not found.\");\n if (siteId === undefined) {\n return json(\n await client.requestJson(\n \"GET\",\n `${base}/published-artifacts`,\n undefined,\n pick(query, SITE_LIST_FIELDS) as Record<string, string>,\n call,\n ),\n );\n }\n if (!SEGMENT.test(siteId) || (op !== \"\" && op !== \"content\" && op !== \"html\")) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n const versionId = query.versionId;\n if (\n versionId !== undefined &&\n (typeof versionId !== \"string\" || !SEGMENT.test(versionId))\n ) {\n reject(400, \"version_invalid\", \"versionId is invalid.\");\n }\n if (op === \"html\") {\n if (typeof versionId !== \"string\") {\n reject(400, \"version_required\", \"versionId is required.\");\n }\n const html = await downloadSessionProxySiteHtml(client, workspaceId, siteId, {\n versionId: versionId as string,\n signal: request.signal,\n });\n return new Response(boundedSiteHtml(html.body, request.signal), {\n headers: SITE_HTML_HEADERS,\n });\n }\n const item = `${base}/published-artifacts/${siteId}`;\n return json(\n await client.requestJson(\n \"GET\",\n op === \"content\" ? `${item}/content` : item,\n undefined,\n op === \"content\" && typeof versionId === \"string\" ? { versionId } : {},\n call,\n ),\n );\n }\n if (!artifactsEnabled) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n const [artifactId, ...artifactOp] = tail as [string | undefined, ...string[]];\n const route = `${method} ${artifactOp.join(\"/\")}`;\n const editable = area === \"editable-artifacts\";\n const allowed = editable\n ? route === \"GET \" || route === \"POST live-ticket\"\n : route === \"GET \" || route === \"GET html\";\n if (!artifactId || !SEGMENT.test(artifactId) || !allowed) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n const sessionId = request.headers.get(SESSION_SCOPE_HEADER)?.trim() ?? \"\";\n if (!SEGMENT.test(sessionId)) {\n reject(400, \"session_scope_required\", \"Artifact reads must name their session.\");\n }\n if (options.authorizeSession && !(await options.authorizeSession(sessionId, context))) {\n return errorJson(404, \"session_not_found\", \"Session not found.\");\n }\n // No positive authorization cache: revocation must take effect even\n // between detail, HTML and ticket requests for the same artifact.\n await getSessionProxyArtifactAssociation(\n client,\n workspaceId,\n sessionId,\n editable ? \"editable\" : \"site\",\n artifactId,\n call,\n );\n const item = `${base}/${area}/${artifactId}`;\n if (route === \"GET \") {\n const replicaId = editable ? query.replicaId : undefined;\n return json(\n await client.requestJson(\n \"GET\",\n item,\n undefined,\n typeof replicaId === \"string\" ? { replicaId } : {},\n call,\n ),\n );\n }\n if (route === \"POST live-ticket\") {\n const body = await readJsonBody(request, maxBodyBytes);\n return json(\n await client.requestJson(\"POST\", `${item}/live-ticket`, {\n ...pick(body, TICKET_FIELDS),\n sourceSessionId: sessionId,\n }),\n 201,\n );\n }\n const versionId = query.versionId;\n if (typeof versionId !== \"string\" || !SEGMENT.test(versionId)) {\n reject(400, \"version_required\", \"versionId is required.\");\n }\n const html = await downloadSessionProxySiteHtml(client, workspaceId, artifactId, {\n versionId,\n signal: request.signal,\n });\n return new Response(boundedSiteHtml(html.body, request.signal), {\n headers: SITE_HTML_HEADERS,\n });\n }\n\n if (area !== \"sessions\") {\n if (sessionAppEnabled && area !== undefined && !PROXY_WORKSPACE_AREAS.has(area)) {\n const route = `${method} ${[area, ...tail].join(\"/\")}`;\n const path = `${base}/${[area, ...tail].join(\"/\")}`;\n if (method === \"GET\") return await passThrough(path);\n if (SESSION_APP_WORKSPACE_WRITES.some((pattern) => pattern.test(route))) {\n return await passThrough(path, await readJsonBody(request, maxBodyBytes, true));\n }\n }\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n\n if (tail.length === 0 && method === \"GET\") {\n if (!sessionList) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n if (query.view !== \"page\") {\n reject(400, \"page_view_required\", \"List sessions with listSessionPage.\");\n }\n const listQuery: Record<string, string> = { ...query };\n if (sessionList === \"mine\") {\n // Server-enforced creator filter; the browser cannot widen it.\n listQuery.createdByKind = \"subject\";\n listQuery.createdBySubjectId = await subjectOf(client, `${source}\\u0000${resolved.user}`);\n }\n const page = await client.requestJson<Record<string, unknown>>(\n \"GET\",\n `${base}/sessions`,\n undefined,\n listQuery,\n call,\n );\n // Pins are a separate personal projection this proxy does not manage.\n return json(sessionList === \"mine\" ? { ...page, pinned: [] } : page);\n }\n if (tail.length === 0) {\n if (method !== \"POST\" || !options.createSession) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n const body = await readJsonBody(request, maxBodyBytes);\n const input = createInput(body, modelSelection, sessionAppEnabled);\n const browser = browserCreateFields(body, sessionAppEnabled);\n if (input.startMode === \"realtime\" && !realtimeVoiceEnabled) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n const hooked = await options.createSession(input, context);\n if (hooked instanceof Response) return hooked;\n const created = withBrowserCreateChoices(\n toolServer ? withToolServer(hooked, toolServer, await toolToken()) : hooked,\n input,\n browser,\n );\n const extras = await messageExtras({\n delivery: \"create\",\n ...(input.startMode ? { startMode: input.startMode } : {}),\n });\n if (extras instanceof Response) return extras;\n const modelContext = joinContext(\n extras?.modelContext,\n created.modelContext,\n browser.modelContext,\n );\n return json(\n await client.createSession(workspaceId, {\n ...created,\n visibility: created.visibility ?? defaults.visibility,\n agentAccess: created.agentAccess ?? defaults.agentAccess,\n memoryScope: created.memoryScope ?? defaults.memoryScope,\n ...(modelContext ? { modelContext } : {}),\n }),\n );\n }\n\n const [sessionId, ...op] = tail as [string, ...string[]];\n if (options.authorizeSession && !(await options.authorizeSession(sessionId, context))) {\n return errorJson(404, \"session_not_found\", \"Session not found.\");\n }\n const session = `${base}/sessions/${sessionId}`;\n const route = `${method} ${op.join(\"/\")}`;\n const body = method === \"GET\" ? undefined : await readJsonBody(request, maxBodyBytes, true);\n const sanitize = (value: unknown) => sanitizeMessage(value, modelSelection);\n const saveDraftPolicy = async (message: Record<string, unknown>) => {\n if (modelSelection) return message;\n // Save requires explicit policy fields. Use this actor's durable draft,\n // not browser choices. The API's expectedRevision fence rejects races.\n const draft = await client.getComposerDraft(workspaceId, sessionId, call);\n return {\n ...message,\n model: draft.model,\n reasoningEffort: draft.reasoningEffort,\n latencyMode: draft.latencyMode,\n };\n };\n const forward = async (path: string, payload: Record<string, unknown> | Response) =>\n payload instanceof Response\n ? payload\n : json(await client.requestJson(\"POST\", path, payload));\n\n if (op[0] === \"realtime\") {\n if (!realtimeVoiceEnabled) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n const realtime = realtimeRoute(method, op.slice(1));\n if (!realtime) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n if (!body) reject(400, \"invalid_body\", \"A JSON object body is required.\");\n const path = `${session}/${op.join(\"/\")}`;\n if (realtime === \"begin\") {\n // The host may refuse a call; MCP credentials (including the tool\n // server's per-user token) are refreshed before voice can delegate.\n const extras = await messageExtras({\n sessionId,\n delivery: \"realtime\",\n });\n if (extras instanceof Response) return extras;\n await refreshRealtimeCredentials(sessionId, extras?.mcpCredentialUpdates ?? []);\n }\n let payload: Record<string, unknown> = body;\n if (realtime === \"sync\" && options.beforeForwardMessage && hasRealtimeMessages(body)) {\n const extras = await options.beforeForwardMessage(\n { sessionId, delivery: \"realtime\" },\n context,\n );\n if (extras instanceof Response) return extras;\n payload = withRealtimeContext(body, extras?.modelContext);\n }\n return json(await client.requestJson(method, path, payload));\n }\n\n switch (route) {\n case \"GET \":\n return await read(session);\n case \"PUT archive\": {\n if (!archiveEnabled) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n const archived = body?.archived;\n const expectedVersion = body?.expectedVersion;\n if (typeof archived !== \"boolean\") reject(400, \"invalid_body\", \"archived is required.\");\n return json(\n await client.requestJson(\"PUT\", `${session}/archive`, {\n archived,\n ...(typeof expectedVersion === \"number\" ? { expectedVersion } : {}),\n }),\n );\n }\n case \"PATCH \": {\n const title = body?.title;\n if (typeof title !== \"string\" || Object.keys(body ?? {}).length !== 1) {\n reject(400, \"invalid_body\", \"Only { title } may be updated.\");\n }\n return json(await client.requestJson(\"PATCH\", session, { title }));\n }\n case \"PUT attention\": {\n // Only \"I have read this\", for the resolved user's own read state:\n // an open conversation acknowledges replies the person watched.\n const through = body?.acknowledgedThroughSequence;\n const keys = Object.keys(body ?? {});\n if (\n body?.unread !== false ||\n keys.some((key) => key !== \"unread\" && key !== \"acknowledgedThroughSequence\") ||\n (through !== undefined &&\n (typeof through !== \"number\" || !Number.isSafeInteger(through) || through < 0))\n ) {\n reject(\n 400,\n \"invalid_body\",\n \"Only { unread: false, acknowledgedThroughSequence? } may be set.\",\n );\n }\n return json(\n await client.requestJson(\"PUT\", `${session}/attention`, {\n unread: false,\n ...(through !== undefined ? { acknowledgedThroughSequence: through } : {}),\n }),\n );\n }\n case \"GET events\":\n return await listEvents(client, `${session}/events`, query, call);\n case \"GET events/stream\":\n // Surface authorization failures as HTTP status before streaming.\n await client.getSession(workspaceId, sessionId, call);\n return proxySessionEventStream(client, workspaceId, sessionId, {\n after: request,\n signal: request.signal,\n heartbeatMs,\n });\n case \"POST events\": {\n const event = clientEvent(body);\n const payload =\n event.type === \"user.message\"\n ? await forwardMessage(event.payload, {\n sessionId,\n delivery: \"send\",\n })\n : await forwardResponse(event.payload, {\n sessionId,\n delivery: \"send\",\n });\n return await forward(\n `${session}/events`,\n payload instanceof Response ? payload : { ...event, payload },\n );\n }\n case \"POST steer\":\n return await forward(\n `${session}/steer`,\n await forwardMessage(body, { sessionId, delivery: \"steer\" }),\n );\n case \"GET queue\":\n return await read(`${session}/queue`);\n case \"GET composer-draft\":\n return await read(`${session}/composer-draft`);\n case \"PUT composer-draft\":\n return json(\n await client.requestJson(\n \"PUT\",\n `${session}/composer-draft`,\n await saveDraftPolicy(sanitize(body)),\n ),\n );\n case \"POST composer-draft/submit\": {\n const message = await forwardMessage(body, {\n sessionId,\n delivery: \"submit\",\n });\n return await forward(`${session}/composer-draft/submit`, message);\n }\n case \"POST control\": {\n if (body?.action !== \"pause\" && body?.action !== \"resume\") {\n reject(403, \"control_not_allowed\", \"Only pause and resume are available.\");\n }\n return json(await client.requestJson(\"POST\", `${session}/control`, body));\n }\n case \"GET human-input-requests\":\n return await read(`${session}/human-input-requests`);\n case \"GET goal\":\n return await read(`${session}/goal`);\n case \"PATCH goal\": {\n // Pause and resume only: the objective, limits and completion stay\n // with the agent and the product's own server. A browser rationale is\n // dropped, so end-user text never reaches the goal record.\n const status = body?.status;\n if (\n (status !== \"paused\" && status !== \"active\") ||\n Object.keys(body ?? {}).some((key) => key !== \"status\" && key !== \"rationale\")\n ) {\n reject(\n 403,\n \"goal_update_not_allowed\",\n \"Only { status: paused | active } is available.\",\n );\n }\n return json(await client.requestJson(\"PATCH\", `${session}/goal`, { status }));\n }\n case \"DELETE goal\":\n await client.deleteGoal(workspaceId, sessionId);\n return new Response(null, { status: 204 });\n case \"POST fs/read\":\n case \"POST fs/read-workspace\": {\n if (!sandboxFilesEnabled) return errorJson(404, \"route_not_allowed\", \"Not found.\");\n // A distinct route fails closed on older APIs that would strip the\n // additive workspaceOnly field and otherwise permit machine-wide reads.\n return json(\n await client.requestJson(\"POST\", `${session}/fs/read-workspace`, sandboxRead(body)),\n );\n }\n }\n if (op[0] === \"artifacts\" && (op.length === 2 || op[2] === \"content\") && method === \"GET\") {\n // Retained screenshots: the API matches the artifact to this session;\n // the proxy first proves the user can read the session itself.\n if (!filesEnabled || op.length > 3) {\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n }\n await client.getSession(workspaceId, sessionId, call);\n if (op.length === 2) return await read(`${session}/artifacts/${op[1]}`);\n return retainedContent(\n await client.getSessionRetainedArtifactContent(workspaceId, sessionId, op[1]!, {\n ...retainedRange(request),\n signal: request.signal,\n }),\n );\n }\n if (op.length === 2 && op[0] === \"human-input-requests\" && method === \"GET\") {\n return await read(`${session}/human-input-requests/${op[1]}`);\n }\n if (\n op.length === 3 &&\n op[0] === \"queue\" &&\n QUEUE_OPERATIONS.has(op[2]!) &&\n method === \"POST\"\n ) {\n return json(await client.requestJson(\"POST\", `${session}/queue/${op[1]}/${op[2]}`, body));\n }\n if (sessionAppEnabled && !PROXY_SESSION_OPERATIONS.has(op[0] ?? \"\")) {\n // authorizeSession above already admitted this chat.\n const path = `${session}/${op.join(\"/\")}`;\n if (method === \"GET\") return await passThrough(path);\n if (SESSION_APP_SESSION_WRITES.some((pattern) => pattern.test(route))) {\n return await passThrough(path, body);\n }\n }\n return errorJson(404, \"route_not_allowed\", \"Not found.\");\n } catch (error) {\n return errorResponse(error, rejectedKeyNotice);\n }\n };\n}\n\n/**\n * Methods any forwarded route uses. Module-level so the public API inventory\n * attributes a verb only to the routes that actually forward it.\n */\nconst PROXY_METHODS: readonly string[] = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"];\n\n/** Workspace areas this proxy serves itself; `sessionApp` never widens them. */\nconst PROXY_WORKSPACE_AREAS: ReadonlySet<string> = new Set([\n \"sessions\",\n \"usage\",\n \"model-catalog\",\n \"realtime-model-catalog\",\n \"live-events\",\n \"inference-control\",\n \"office\",\n \"files\",\n \"artifacts\",\n \"transcriptions\",\n \"editable-artifacts\",\n \"published-artifacts\",\n // Rosters, credentials, budgets and administration stay out of the browser\n // even when Opengeni would let the user read them.\n \"access\",\n \"allowance\",\n \"api-keys\",\n \"auth-runs\",\n \"credential-provider\",\n \"enrollments\",\n \"external-members\",\n \"identity-links\",\n \"insights\",\n \"member-candidates\",\n \"members\",\n \"session-tenancy\",\n \"subscription-usage-pools\",\n \"user-resource-authorities\",\n \"vault-providers\",\n \"vaults\",\n \"webhooks\",\n]);\n\n/** Chat routes this proxy serves itself; `sessionApp` never widens them. */\nconst PROXY_SESSION_OPERATIONS: ReadonlySet<string> = new Set([\n \"\",\n \"archive\",\n \"attention\",\n \"events\",\n \"steer\",\n \"queue\",\n \"composer-draft\",\n \"control\",\n \"human-input-requests\",\n \"goal\",\n \"realtime\",\n \"fs\",\n \"artifacts\",\n]);\n\n/** The session app's own writes in the workspace, as the resolved user. */\nconst SESSION_APP_WORKSPACE_WRITES: readonly RegExp[] = [\n /^PUT new-session-draft$/,\n /^POST channels$/,\n /^(PATCH|DELETE) channels\\/[^/]+$/,\n];\n\n/** The session app's own writes in a chat, as the resolved user. */\nconst SESSION_APP_SESSION_WRITES: readonly RegExp[] = [\n /^PUT pin$/,\n /^PUT channel$/,\n /^PUT tool-policy$/,\n /^PATCH mcp-servers\\/[^/]+\\/approval-policy$/,\n];\n\n/** Response headers a passed-through read or write keeps. */\nconst PASS_THROUGH_HEADERS = [\n \"content-type\",\n \"content-length\",\n \"content-disposition\",\n \"etag\",\n \"last-modified\",\n SESSION_SEQUENCE_HEADER,\n] as const;\n\n/** The user's access to the resolved workspace only, without key authority. */\n/**\n * The app's access context: the resolved workspace's effective grant only,\n * never the user's other workspaces or the key's own authority.\n */\nfunction scopedAccessContext(access: AccessContext, grant: AccessGrant): AccessContext {\n const { credential: _credential, ...rest } = access;\n return {\n ...rest,\n subjectId: grant.subjectId,\n workspaceGrants: [grant],\n accountGrants: access.accountGrants.filter(\n (accountGrant) => accountGrant.accountId === grant.accountId,\n ),\n defaultWorkspaceId: grant.workspaceId,\n defaultAccountId: grant.accountId,\n };\n}\n\n/** `catalog-assets/...` under this proxy's base path, or null. */\nfunction catalogAssetPath(pathname: string, basePath: string | undefined): string | null {\n const prefix = `${basePath !== undefined ? basePath.replace(/\\/+$/, \"\") : \"\"}/v1/catalog-assets/`;\n const start = basePath !== undefined ? 0 : pathname.indexOf(\"/v1/catalog-assets/\");\n if (start < 0 || !pathname.startsWith(prefix, start)) return null;\n const asset = pathname.slice(start + prefix.length);\n if (!/^[A-Za-z0-9_-][A-Za-z0-9_.-]*(\\/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*$/.test(asset)) return null;\n return `catalog-assets/${asset}`;\n}\n\nconst UPLOAD_FIELDS = [\"scope\", \"filename\", \"contentType\", \"sizeBytes\", \"sha256\"] as const;\n\ntype RealtimeRoute = \"begin\" | \"connect\" | \"heartbeat\" | \"end\" | \"activate\" | \"sync\";\nconst REALTIME_CONNECT_ROUTES: ReadonlySet<string> = new Set([\n \"webrtc\",\n \"websocket\",\n \"gateway\",\n \"supergrok\",\n]);\n/** Ledger entries that become (or join) messages and so accept `modelContext`. */\nconst REALTIME_MESSAGE_KINDS: ReadonlySet<string> = new Set([\n \"delegation_call\",\n \"user_transcript\",\n \"assistant_transcript\",\n]);\n\n/**\n * The live voice routes a browser call uses, after `realtime/`: begin, provider\n * connect, heartbeat, end, connection activation, and transcript sync. Bodies\n * pass to Opengeni, which validates them and binds the call to the acting user.\n */\nfunction realtimeRoute(method: string, rest: string[]): RealtimeRoute | null {\n if (rest.length === 0) return method === \"POST\" ? \"begin\" : null;\n if (rest.length === 1) {\n if (REALTIME_CONNECT_ROUTES.has(rest[0]!)) return method === \"POST\" ? \"connect\" : null;\n return method === \"DELETE\" ? \"end\" : null;\n }\n if (rest.length === 2 && rest[1] === \"heartbeat\") return method === \"PATCH\" ? \"heartbeat\" : null;\n if (rest.length === 2 && rest[1] === \"sync\") return method === \"POST\" ? \"sync\" : null;\n if (rest.length === 4 && rest[1] === \"connections\" && rest[3] === \"activate\") {\n return method === \"POST\" ? \"activate\" : null;\n }\n return null;\n}\n\nfunction hasRealtimeMessages(body: Record<string, unknown>): boolean {\n return (\n Array.isArray(body.entries) &&\n body.entries.some(\n (entry) =>\n entry !== null &&\n typeof entry === \"object\" &&\n REALTIME_MESSAGE_KINDS.has((entry as { kind?: unknown }).kind as string),\n )\n );\n}\n\n/** Server context goes before the browser's on each message-bearing entry. */\nfunction withRealtimeContext(\n body: Record<string, unknown>,\n serverContext: string | undefined,\n): Record<string, unknown> {\n if (!serverContext?.trim() || !Array.isArray(body.entries)) return body;\n return {\n ...body,\n entries: body.entries.map((entry: unknown) => {\n if (entry === null || typeof entry !== \"object\") return entry;\n const record = entry as Record<string, unknown>;\n if (!REALTIME_MESSAGE_KINDS.has(record.kind as string)) return entry;\n const modelContext = joinContext(\n serverContext,\n typeof record.modelContext === \"string\" ? record.modelContext : undefined,\n );\n return modelContext ? { ...record, modelContext } : entry;\n }),\n };\n}\n\ntype NormalizedToolServer = SessionProxyToolServer & {\n url: string;\n id: string;\n secret: string;\n};\n\nfunction normalizeToolServer(toolServer: SessionProxyToolServer): NormalizedToolServer {\n const configured =\n toolServer.url ??\n (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env\n ?.OPENGENI_TOOL_SERVER_URL;\n let url: URL;\n try {\n url = new URL(configured ?? \"\");\n } catch {\n throw new TypeError(\n \"toolServer.url (or OPENGENI_TOOL_SERVER_URL) must be an absolute https:// URL.\",\n );\n }\n if (url.protocol !== \"https:\") {\n // Opengeni calls the tool server from its own network; use a tunnel locally.\n throw new TypeError(\"toolServer.url must be an absolute https:// URL.\");\n }\n const id = toolServer.id ?? \"app\";\n if (!/^[A-Za-z0-9_-]+$/.test(id)) {\n throw new TypeError(\"toolServer.id may contain only letters, digits, _ and -.\");\n }\n const ask = toolServer.approvals?.ask;\n if (ask !== undefined && ask !== true && !(Array.isArray(ask) && ask.every(isToolName))) {\n throw new TypeError(\"toolServer.approvals.ask must be true or a list of tool names.\");\n }\n const eager = toolServer.eager;\n if (eager !== undefined && eager !== true && !(Array.isArray(eager) && eager.every(isToolName))) {\n throw new TypeError(\"toolServer.eager must be true or a list of tool names.\");\n }\n // Resolve now so a missing secret fails at startup, not on the first chat.\n return {\n ...toolServer,\n url: configured!,\n id,\n secret: resolveToolTokenSecret(toolServer.secret),\n };\n}\n\nfunction isToolName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\n/** Attach the product tool server with a fresh per-user token. */\nfunction withToolServer(\n created: CreateSessionRequest,\n toolServer: NormalizedToolServer,\n token: string,\n): CreateSessionRequest {\n const servers = created.mcpServers ?? [];\n if (servers.some((server) => server.id === toolServer.id)) {\n throw new TypeError(\n `createSession already attaches an MCP server with the toolServer id \"${toolServer.id}\".`,\n );\n }\n const ask = toolServer.approvals?.ask;\n const eager =\n toolServer.eager === true\n ? true\n : toolServer.eager?.length\n ? [...new Set(toolServer.eager)]\n : undefined;\n const tools = created.tools;\n return {\n ...created,\n mcpServers: [\n ...servers,\n {\n id: toolServer.id,\n ...(toolServer.name ? { name: toolServer.name } : {}),\n url: toolServer.url,\n headers: { Authorization: `Bearer ${token}` },\n ...(ask === true ? { requireApproval: true } : ask?.length ? { requireApproval: ask } : {}),\n ...(eager !== undefined ? { eager } : {}),\n },\n ],\n // Omitted tools keep workspace defaults; the attachment alone selects the\n // server, and its `eager` marker names the first-request tools. An explicit\n // allow-list without an `eager` choice gets every server tool on the first\n // request, as before.\n ...(Array.isArray(tools) && !tools.some((tool) => tool.id === toolServer.id)\n ? {\n tools: [...tools, { kind: \"mcp\" as const, id: toolServer.id, eager: eager ?? true }],\n }\n : {}),\n };\n}\n\nconst EDITABLE_ARTIFACT_LIVE_PATH = \"/v1/editable-artifacts/live\";\nconst SITE_LIST_FIELDS = [\"limit\", \"cursor\", \"status\"] as const;\nconst TICKET_FIELDS = [\n \"replicaId\",\n \"modality\",\n \"liveProtocolVersion\",\n \"kernelVersion\",\n \"modelSchemaVersion\",\n \"snapshotVersion\",\n \"commandProtocolVersion\",\n \"committedTransactionProtocolVersion\",\n] as const;\n// Same delivery contract as Opengeni's own route: the browser fetches the\n// HTML and renders it in a sandboxed frame; opening the URL downloads it.\nconst SITE_HTML_HEADERS = {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"private, no-store\",\n \"Content-Security-Policy\": \"sandbox allow-scripts\",\n \"Cross-Origin-Resource-Policy\": \"same-origin\",\n \"X-Content-Type-Options\": \"nosniff\",\n \"Content-Disposition\": 'attachment; filename=\"site.html\"',\n} as const;\n\nfunction liveSocketUrl(value: string): string {\n const url = new URL(value);\n if (url.protocol === \"https:\") url.protocol = \"wss:\";\n else if (url.protocol === \"http:\") url.protocol = \"ws:\";\n if (url.protocol !== \"wss:\" && url.protocol !== \"ws:\") {\n throw new TypeError(\"editableLiveUrl must be an HTTP(S) or WS(S) URL\");\n }\n return url.href;\n}\n\nfunction boundedSiteHtml(\n body: ReadableStream<Uint8Array> | null,\n signal: AbortSignal,\n): ReadableStream<Uint8Array> {\n const reader = body?.getReader();\n let bytes = 0;\n let settled = false;\n let controller: ReadableStreamDefaultController<Uint8Array>;\n const cleanup = () => signal.removeEventListener(\"abort\", abort);\n const cancel = async (reason: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n await reader?.cancel(reason).catch(() => undefined);\n reader?.releaseLock();\n };\n const abort = () => {\n if (settled) return;\n controller.error(signal.reason);\n void cancel(signal.reason);\n };\n return new ReadableStream<Uint8Array>(\n {\n start(value) {\n controller = value;\n if (signal.aborted) abort();\n else signal.addEventListener(\"abort\", abort, { once: true });\n },\n async pull(value) {\n if (settled) return;\n try {\n const chunk = await reader?.read();\n if (settled) return;\n if (!chunk || chunk.done) {\n settled = true;\n cleanup();\n reader?.releaseLock();\n value.close();\n return;\n }\n bytes += chunk.value.byteLength;\n if (bytes > SESSION_PROXY_SITE_HTML_MAX_BYTES) {\n const error = new SessionProxySiteHtmlTooLargeError();\n value.error(error);\n await cancel(error);\n return;\n }\n value.enqueue(chunk.value);\n } catch (error) {\n if (settled) return;\n value.error(error);\n await cancel(error);\n }\n },\n cancel,\n },\n // Read only when the downstream consumer requests a chunk.\n { highWaterMark: 0 },\n );\n}\n\n/**\n * The client-config `artifacts` capability a custom host proxy reports so\n * `SessionArtifactViewer` can open editable artifacts: the live socket URL\n * (ticket-authenticated, reached directly) and the proxied user's browser cache\n * partition. `client` acts as that user (for example `asUser(...)`).\n */\nexport async function artifactViewerCapability(input: {\n client: Pick<ProxyClient, \"getAccessContext\" | \"apiUrl\"> &\n Partial<Pick<ProxyClient, \"requestJson\">>;\n workspaceId: string;\n /** Stable namespace of the host's user identities, mixed into the partition. */\n source?: string | undefined;\n editableLiveUrl?: string | undefined;\n}): Promise<{\n editableLiveUrl: string;\n cachePartition: {\n accountId: string;\n principalId: string;\n authorizationEpoch: string;\n };\n}> {\n return {\n editableLiveUrl: liveSocketUrl(\n input.editableLiveUrl ?? input.client.apiUrl(EDITABLE_ARTIFACT_LIVE_PATH),\n ),\n cachePartition: await cachePartition(\n input.client.requestJson\n ? await getSessionProxyWorkspaceGrant(\n input.client as Pick<ProxyClient, \"requestJson\">,\n input.workspaceId,\n )\n : await legacyViewerGrant(input.client, input.workspaceId),\n input.workspaceId,\n input.source ?? \"default\",\n ),\n };\n}\n\n/** The editor's browser cache partition for this proxied user and workspace. */\nasync function cachePartition(\n grant: import(\"./types\").AccessGrant,\n workspaceId: string,\n source: string,\n): Promise<{\n accountId: string;\n principalId: string;\n authorizationEpoch: string;\n}> {\n if (grant.workspaceId !== workspaceId) {\n reject(403, \"workspace_not_allowed\", \"This workspace is not available.\");\n }\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(\n JSON.stringify({\n source,\n subjectId: grant.subjectId,\n accountId: grant.accountId,\n workspaceId,\n permissions: [...grant.permissions].sort(),\n // Effective external grants carry live identity/link revisions. Include\n // them even when a revoke/regrant restores an identical permission set.\n externalActor: grant.metadata?.externalActor ?? null,\n }),\n ),\n );\n return {\n accountId: grant.accountId,\n principalId: grant.subjectId,\n authorizationEpoch: `sha256:${[...new Uint8Array(digest)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`,\n };\n}\n\n/** Preserve custom capability clients that supplied only the original two methods. */\nasync function legacyViewerGrant(\n client: Pick<ProxyClient, \"getAccessContext\">,\n workspaceId: string,\n): Promise<import(\"./types\").AccessGrant> {\n const access = await client.getAccessContext();\n const grant = access.workspaceGrants.find((candidate) => candidate.workspaceId === workspaceId);\n if (!grant) reject(403, \"workspace_not_allowed\", \"This workspace is not available.\");\n return grant;\n}\n\n/** The browser's byte range, passed through unchanged when well formed. */\nfunction retainedRange(request: Request): { range?: string } {\n const range = request.headers.get(\"range\");\n if (range === null) return {};\n if (range.length > 128 || /[^\\x20-\\x7e]/.test(range)) {\n reject(400, \"invalid_range\", \"Range must be at most 128 printable ASCII bytes.\");\n }\n return { range };\n}\n\n/** One bounded retained-artifact page, with the range facts the browser SDK verifies. */\nfunction retainedContent(content: RetainedArtifactContent): Response {\n return new Response(content.bytes as Uint8Array<ArrayBuffer>, {\n status: content.status,\n headers: {\n \"Content-Type\": content.contentType,\n \"Content-Length\": String(content.contentLength),\n ...(content.contentRange ? { \"Content-Range\": content.contentRange } : {}),\n \"Accept-Ranges\": \"bytes\",\n \"Cache-Control\": \"private, no-store\",\n // Bytes for the conversation's own reader; never rendered on this origin.\n \"Content-Security-Policy\": \"sandbox\",\n \"Content-Disposition\": \"attachment\",\n \"Cross-Origin-Resource-Policy\": \"same-origin\",\n \"X-Content-Type-Options\": \"nosniff\",\n },\n });\n}\n\n/** Sandbox link download: one path, no route/target override. */\nfunction sandboxRead(body: Record<string, unknown> | undefined): Record<string, unknown> {\n const path = body?.path;\n const encoding = body?.encoding;\n const maxBytes = body?.maxBytes;\n if (typeof path !== \"string\" || !path || path.length > 4096) {\n reject(400, \"invalid_body\", \"path is required.\");\n }\n if (encoding !== undefined && encoding !== \"utf8\" && encoding !== \"base64\") {\n reject(400, \"invalid_body\", \"encoding must be utf8 or base64.\");\n }\n if (\n maxBytes !== undefined &&\n (typeof maxBytes !== \"number\" ||\n !Number.isSafeInteger(maxBytes) ||\n maxBytes < 1 ||\n maxBytes > 25 * 1024 * 1024)\n ) {\n reject(400, \"invalid_body\", \"maxBytes must be an integer from 1 to 26214400.\");\n }\n return {\n path,\n workspaceOnly: true,\n ...(encoding === undefined ? {} : { encoding }),\n ...(maxBytes === undefined ? {} : { maxBytes }),\n };\n}\n\n/** Native path segments after the mount prefix, starting at `v1`'s child; null when not a proxied path. */\nfunction routeSegments(pathname: string, basePath: string | undefined): string[] | null {\n let rest: string;\n if (basePath !== undefined) {\n const prefix = basePath.replace(/\\/+$/, \"\");\n if (!pathname.startsWith(`${prefix}/`)) return null;\n rest = pathname.slice(prefix.length);\n } else {\n const index = pathname.indexOf(\"/v1/\");\n if (index < 0) return null;\n rest = pathname.slice(index);\n }\n const raw = rest.replace(/\\/+$/, \"\").split(\"/\").slice(1);\n if (raw[0] !== \"v1\" || raw.length < 2) return null;\n const segments: string[] = [];\n for (const part of raw.slice(1)) {\n let decoded: string;\n try {\n decoded = decodeURIComponent(part);\n } catch {\n return null;\n }\n // Rejects empty, dot, and encoded-separator segments before any SDK path is built.\n if (!SEGMENT.test(decoded)) return null;\n segments.push(decoded);\n }\n return segments;\n}\n\nasync function readJsonBody(\n request: Request,\n maxBytes: number,\n optional = false,\n): Promise<Record<string, unknown> | undefined> {\n const bytes = await readBoundedBytes(request, maxBytes);\n if (bytes.byteLength === 0) {\n if (optional) return undefined;\n reject(400, \"invalid_body\", \"A JSON object body is required.\");\n }\n const contentType = request.headers.get(\"content-type\") ?? \"\";\n if (!/^application\\/json\\b/i.test(contentType)) {\n reject(415, \"unsupported_media_type\", \"Send application/json.\");\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(new TextDecoder().decode(bytes));\n } catch {\n reject(400, \"invalid_body\", \"Body is not valid JSON.\");\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n reject(400, \"invalid_body\", \"A JSON object body is required.\");\n }\n return parsed as Record<string, unknown>;\n}\n\nasync function readBoundedBytes(\n request: Request,\n maxBytes: number,\n): Promise<Uint8Array<ArrayBuffer>> {\n const declared = Number(request.headers.get(\"content-length\") ?? \"0\");\n if (declared > maxBytes) reject(413, \"body_too_large\", \"Request body is too large.\");\n const reader = request.body?.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n if (reader) {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > maxBytes) {\n void reader.cancel().catch(() => undefined);\n reject(413, \"body_too_large\", \"Request body is too large.\");\n }\n chunks.push(value);\n }\n }\n const bytes = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n}\n\nfunction pick(\n body: Record<string, unknown> | undefined,\n fields: readonly string[],\n): Record<string, unknown> {\n const picked: Record<string, unknown> = {};\n for (const field of fields) {\n if (body && Object.hasOwn(body, field)) picked[field] = body[field];\n }\n return picked;\n}\n\nfunction createInput(\n body: Record<string, unknown> | undefined,\n modelSelection: boolean,\n sessionApp: boolean,\n): SessionProxyCreateInput {\n for (const key of Object.keys(body ?? {})) {\n if (\n !CREATE_FIELDS.has(key) &&\n !(modelSelection && isModelField(key)) &&\n !(sessionApp && SESSION_APP_CREATE_FIELDS.has(key))\n ) {\n reject(\n 400,\n \"create_field_not_allowed\",\n `The server chooses session configuration; \"${key}\" cannot be set from the browser.`,\n );\n }\n }\n const initialMessage = body?.initialMessage;\n const idempotencyKey = body?.idempotencyKey;\n const startMode = body?.startMode;\n if (startMode !== undefined && startMode !== \"realtime\") {\n reject(400, \"invalid_start_mode\", \"startMode must be realtime when supplied.\");\n }\n if (startMode === \"realtime\" && initialMessage !== undefined && initialMessage !== \"\") {\n reject(\n 400,\n \"initial_message_not_allowed\",\n \"Voice-first creation does not send an initial message.\",\n );\n }\n if (startMode !== \"realtime\" && (typeof initialMessage !== \"string\" || !initialMessage.trim())) {\n reject(400, \"initial_message_required\", \"initialMessage is required.\");\n }\n if (idempotencyKey !== undefined && (typeof idempotencyKey !== \"string\" || !idempotencyKey)) {\n reject(400, \"invalid_idempotency_key\", \"idempotencyKey must be a non-empty string.\");\n }\n const resources = createResources(body?.resources);\n if (startMode === \"realtime\" && resources.length > 0) {\n reject(400, \"resource_not_allowed\", \"Keep attachments in the draft until a message is sent.\");\n }\n const policy: Pick<SessionProxyCreateInput, \"model\" | \"reasoningEffort\" | \"latencyMode\"> = {};\n for (const field of MODEL_FIELDS) {\n const value = body?.[field];\n if (value === undefined) continue;\n if (typeof value !== \"string\" || !value) {\n reject(400, \"invalid_model_policy\", `${field} must be a non-empty string.`);\n }\n (policy as Record<string, string>)[field] = value;\n }\n return {\n initialMessage: startMode === \"realtime\" ? \"\" : (initialMessage as string),\n ...(startMode === \"realtime\" ? { startMode } : {}),\n ...(idempotencyKey ? { idempotencyKey } : {}),\n ...(resources.length > 0 ? { resources } : {}),\n ...policy,\n };\n}\n\nfunction isModelField(key: string): boolean {\n return (MODEL_FIELDS as readonly string[]).includes(key);\n}\n\n/** First-message attachments: file references only, nothing else on them. */\nfunction createResources(value: unknown): FileResourceRef[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n reject(403, \"resource_not_allowed\", \"Only file attachments may be added from the browser.\");\n }\n return value.map((resource: unknown) => {\n const file = resource as Partial<FileResourceRef> | null;\n if (\n !file ||\n typeof file !== \"object\" ||\n file.kind !== \"file\" ||\n typeof file.fileId !== \"string\" ||\n !file.fileId ||\n (file.mountPath !== undefined && typeof file.mountPath !== \"string\")\n ) {\n reject(403, \"resource_not_allowed\", \"Only file attachments may be added from the browser.\");\n }\n return {\n kind: \"file\",\n fileId: file.fileId,\n ...(file.mountPath !== undefined ? { mountPath: file.mountPath } : {}),\n };\n });\n}\n\n/** Browser attachments are added; explicit browser model choices win, as for messages. */\ntype BrowserCreateFields = {\n modelContext?: string | undefined;\n clientEventId?: string | undefined;\n expectedNewSessionDraftRevision?: number | undefined;\n};\n\n/**\n * The browser's own context and the session app's create bookkeeping. Message\n * context is appended after the server's, as on follow-up messages. The session\n * app also sends the id of its first message event and the revision of the\n * new-chat draft it sent, so the API can clear that draft. It sends `visibility`\n * and an empty `connectionAccounts` too: the server chooses both, so those are\n * dropped, and any account selection is refused.\n */\nfunction browserCreateFields(\n body: Record<string, unknown> | undefined,\n sessionApp: boolean,\n): BrowserCreateFields {\n const fields: BrowserCreateFields = {};\n const modelContext = body?.modelContext;\n if (modelContext !== undefined && typeof modelContext !== \"string\") {\n reject(400, \"invalid_model_context\", \"modelContext must be a string.\");\n }\n if (modelContext?.trim()) fields.modelContext = modelContext;\n if (!sessionApp) return fields;\n const visibility = body?.visibility;\n if (visibility !== undefined && visibility !== \"workspace\" && visibility !== \"private\") {\n reject(400, \"invalid_visibility\", \"visibility must be workspace or private.\");\n }\n const accounts = body?.connectionAccounts;\n if (accounts !== undefined && (!Array.isArray(accounts) || accounts.length > 0)) {\n reject(\n 403,\n \"connection_account_not_allowed\",\n \"The server chooses which connected accounts a chat uses.\",\n );\n }\n const clientEventId = body?.clientEventId;\n if (clientEventId !== undefined) {\n if (typeof clientEventId !== \"string\" || !clientEventId) {\n reject(400, \"invalid_client_event_id\", \"clientEventId must be a non-empty string.\");\n }\n fields.clientEventId = clientEventId;\n }\n const revision = body?.expectedNewSessionDraftRevision;\n if (revision !== undefined) {\n if (typeof revision !== \"number\" || !Number.isSafeInteger(revision) || revision < 0) {\n reject(\n 400,\n \"invalid_draft_revision\",\n \"expectedNewSessionDraftRevision must be a non-negative integer.\",\n );\n }\n fields.expectedNewSessionDraftRevision = revision;\n }\n return fields;\n}\n\nfunction withBrowserCreateChoices(\n created: CreateSessionRequest,\n input: SessionProxyCreateInput,\n browser: BrowserCreateFields = {},\n): CreateSessionRequest {\n const existing = created.resources ?? [];\n const attached = new Set(\n existing.flatMap((resource) => (resource.kind === \"file\" ? [resource.fileId] : [])),\n );\n const added = (input.resources ?? []).filter((resource) => !attached.has(resource.fileId));\n return {\n ...created,\n // Preserve browser retry identity even when a simple host hook omits it;\n // an explicit server-owned key continues to take precedence.\n ...(created.idempotencyKey === undefined && input.idempotencyKey\n ? { idempotencyKey: input.idempotencyKey }\n : {}),\n ...(input.startMode === \"realtime\" ? { startMode: \"realtime\", initialMessage: undefined } : {}),\n ...(added.length > 0 ? { resources: [...existing, ...added] } : {}),\n ...(input.model ? { model: input.model } : {}),\n ...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),\n ...(input.latencyMode ? { latencyMode: input.latencyMode } : {}),\n ...(created.clientEventId === undefined && browser.clientEventId\n ? { clientEventId: browser.clientEventId }\n : {}),\n ...(created.expectedNewSessionDraftRevision === undefined &&\n browser.expectedNewSessionDraftRevision !== undefined\n ? { expectedNewSessionDraftRevision: browser.expectedNewSessionDraftRevision }\n : {}),\n };\n}\n\n/** One multipart recording: only the audio, its MIME type, and its duration pass. */\nasync function transcriptionInput(request: Request): Promise<{\n audio: File;\n mimeType: string;\n durationSeconds?: number;\n signal: AbortSignal;\n}> {\n const contentType = request.headers.get(\"content-type\") ?? \"\";\n if (!/^multipart\\/form-data\\b/i.test(contentType)) {\n reject(415, \"unsupported_media_type\", \"Send multipart/form-data.\");\n }\n const bytes = await readBoundedBytes(request, MAX_TRANSCRIPTION_BODY_BYTES);\n // Only the fields this route reads; structural, so DOM and React Native\n // typings of FormData both satisfy it.\n let form: { get(name: string): File | string | null };\n try {\n form = (await new Response(bytes, {\n headers: { \"Content-Type\": contentType },\n }).formData()) as unknown as { get(name: string): File | string | null };\n } catch {\n reject(400, \"invalid_audio\", \"The recording could not be read.\");\n }\n const audio = form.get(\"audio\");\n const mimeType = form.get(\"mimeType\");\n const duration = form.get(\"durationSeconds\");\n if (!(audio instanceof File)) reject(400, \"invalid_audio\", \"Audio file is required.\");\n const durationSeconds = typeof duration === \"string\" && duration ? Number(duration) : undefined;\n if (\n durationSeconds !== undefined &&\n !(Number.isFinite(durationSeconds) && durationSeconds >= 0)\n ) {\n reject(400, \"invalid_audio\", \"durationSeconds must be a non-negative number.\");\n }\n return {\n audio,\n mimeType: typeof mimeType === \"string\" && mimeType ? mimeType : audio.type,\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n signal: request.signal,\n };\n}\n\n/** Browser payloads cannot supply server-owned credential rotations. */\nfunction browserPayload(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n reject(400, \"invalid_body\", \"A JSON object body is required.\");\n }\n const input = { ...(value as Record<string, unknown>) };\n if (Object.hasOwn(input, \"mcpCredentialUpdates\")) {\n reject(403, \"credential_update_not_allowed\", \"MCP credentials are server-owned.\");\n }\n return input;\n}\n\n/** Browser message/draft input: no credential rotation, file resources only, optional model lock. */\nfunction sanitizeMessage(value: unknown, modelSelection: boolean): Record<string, unknown> {\n const input = browserPayload(value);\n if (input.resources !== undefined) {\n if (\n !Array.isArray(input.resources) ||\n input.resources.some(\n (resource) =>\n !resource ||\n typeof resource !== \"object\" ||\n (resource as { kind?: unknown }).kind !== \"file\",\n )\n ) {\n reject(403, \"resource_not_allowed\", \"Only file attachments may be added from the browser.\");\n }\n }\n if (!modelSelection) {\n for (const field of MODEL_FIELDS) delete input[field];\n }\n return input;\n}\n\nfunction clientEvent(body: Record<string, unknown> | undefined): Record<string, unknown> & {\n type: string;\n} {\n switch (body?.type) {\n case \"user.message\":\n case \"user.approvalDecision\":\n case \"user.humanInputResponse\":\n return body as Record<string, unknown> & { type: string };\n default:\n return reject(403, \"event_not_allowed\", \"This session event type is not available.\");\n }\n}\n\nfunction joinContext(...parts: Array<string | undefined>): string | undefined {\n const joined = parts\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(\"\\n\\n\");\n return joined || undefined;\n}\n\nasync function listEvents(\n client: ProxyClient,\n path: string,\n query: Record<string, string>,\n call: { signal: AbortSignal },\n): Promise<Response> {\n if (query.mode === \"forensic\") {\n reject(403, \"forensic_events_not_allowed\", \"Forensic event reads are not proxied.\");\n }\n const upstream = await client.requestJsonResponse(path, query, call);\n const headers: Record<string, string> = {};\n upstream.headers.forEach((value, name) => {\n const lower = name.toLowerCase();\n // Paging metadata only; the upstream contract revision stays behind the proxy.\n if (lower.startsWith(\"x-opengeni-\") && lower !== OPENGENI_API_CONTRACT_HEADER) {\n headers[name] = value;\n }\n });\n return new Response(await upstream.text(), {\n headers: {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n ...headers,\n },\n });\n}\n\n/** Re-emit the workspace control/interaction stream the React provider subscribes to. */\nfunction workspaceLiveStream(\n client: ProxyClient,\n workspaceId: string,\n params: URLSearchParams,\n request: Request,\n heartbeatMs: number,\n): Response {\n const cursor = (name: string): number => {\n const value = Number(params.get(name) ?? \"0\");\n return Number.isSafeInteger(value) && value > 0 ? value : 0;\n };\n const upstream = new AbortController();\n if (request.signal.aborted) upstream.abort();\n else\n request.signal.addEventListener(\"abort\", () => upstream.abort(), {\n once: true,\n });\n const events = client.streamWorkspaceLiveEvents(workspaceId, {\n controlAfter: cursor(\"controlAfter\"),\n interactionAfter: cursor(\"interactionAfter\"),\n signal: upstream.signal,\n });\n const iterator = events[Symbol.asyncIterator]();\n const encoder = new TextEncoder();\n let heartbeat: ReturnType<typeof setInterval> | undefined;\n const stop = () => {\n if (heartbeat !== undefined) clearInterval(heartbeat);\n heartbeat = undefined;\n };\n const body = new ReadableStream<Uint8Array>({\n start: (controller) => {\n heartbeat = setInterval(() => {\n try {\n controller.enqueue(encoder.encode(\": ping\\n\\n\"));\n } catch {\n stop();\n }\n }, heartbeatMs);\n },\n pull: async (controller) => {\n const next = await iterator.next().catch((error: unknown) => {\n stop();\n throw error;\n });\n if (next.done) {\n stop();\n controller.close();\n return;\n }\n const event = next.value;\n controller.enqueue(\n encoder.encode(\n `${\"sequence\" in event ? `id: ${event.sequence}\\n` : \"\"}event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`,\n ),\n );\n },\n cancel: () => {\n stop();\n upstream.abort();\n void Promise.resolve(iterator.return?.(undefined)).catch(() => undefined);\n },\n });\n return new Response(body, {\n headers: {\n \"Content-Type\": \"text/event-stream; charset=utf-8\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n },\n });\n}\n\n/**\n * The proxy always calls Opengeni with the server's own key, so an upstream\n * 401 means that key is wrong, expired or revoked, never that the end user is\n * signed out. Tell the developer once, in the server log, what to fix.\n */\nfunction warnRejectedApiKey(error: OpenGeniApiError, notice: { sent: boolean }): void {\n if (notice.sent) return;\n notice.sent = true;\n console.warn(\n `[@opengeni/sdk] Opengeni rejected the session proxy's API key (401${\n error.correlationId ? `, reference ${error.correlationId}` : \"\"\n }). It may be expired, revoked or mistyped: create a new key in Opengeni under ` +\n \"Organization settings > Developer and update OPENGENI_API_KEY on the server.\",\n );\n}\n\n/** Preserve Opengeni's error envelope so the browser SDK keeps codes, retryability, and outcome facts. */\nfunction errorResponse(error: unknown, rejectedKeyNotice: { sent: boolean }): Response {\n if (error instanceof ProxyRejection) return errorJson(error.status, error.code, error.message);\n if (error instanceof OpenGeniSetupError) {\n return json(\n {\n error: {\n code: error.code,\n message: error.message,\n retryable: false,\n ...(error.correlationId ? { requestId: error.correlationId } : {}),\n },\n },\n error.status,\n );\n }\n if (error instanceof OpenGeniApiError) {\n if (error.status === 401) warnRejectedApiKey(error, rejectedKeyNotice);\n const status = error.status >= 400 && error.status <= 599 ? error.status : 502;\n // A decoded upstream envelope is forwarded verbatim; the SDK only retains decodable bodies.\n if (error.body) {\n return new Response(error.body, {\n status,\n headers: {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n },\n });\n }\n return json(\n {\n error: {\n code: error.code ?? \"opengeni_api_error\",\n message: error.message,\n retryable: error.retryable,\n outcomeUnknown: error.outcomeUnknown,\n ...(error.correlationId ? { requestId: error.correlationId } : {}),\n ...(error.details ? { details: error.details } : {}),\n },\n },\n status,\n );\n }\n if (error instanceof Error && error.name === \"AbortError\") {\n return errorJson(499, \"aborted\", \"The request was aborted.\");\n }\n // The browser gets no details; the host's server log needs the cause\n // (for example a missing OPENGENI_API_KEY).\n console.error(\"[@opengeni/sdk] Session proxy request failed:\", error);\n return errorJson(500, \"proxy_error\", \"Request could not be completed.\");\n}\n"],"mappings":"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","names":["sessionId","session","body","route","op","versionId","html","item"]}
@@ -2493,10 +2493,6 @@ function safeError2(error) {
2493
2493
  }
2494
2494
 
2495
2495
  export {
2496
- CodexRealtimeMicrophoneError,
2497
- startCodexRealtimeWebrtc,
2498
- acquireCodexRealtimeMicrophone,
2499
- codexRealtimeMicrophoneHealthy,
2500
2496
  CODEX_REALTIME_INITIAL_ITEMS_MAX_COUNT,
2501
2497
  CODEX_REALTIME_INITIAL_ITEMS_MAX_TOKENS,
2502
2498
  CODEX_REALTIME_CONTEXT_APPEND_MAX_BYTES,
@@ -2511,6 +2507,10 @@ export {
2511
2507
  CODEX_REALTIME_V3_PENDING_MAX_ENTRIES,
2512
2508
  CODEX_REALTIME_V3_PENDING_MAX_BYTES,
2513
2509
  createCodexRealtimeV3Bridge,
2510
+ CodexRealtimeMicrophoneError,
2511
+ startCodexRealtimeWebrtc,
2512
+ acquireCodexRealtimeMicrophone,
2513
+ codexRealtimeMicrophoneHealthy,
2514
2514
  SESSION_REALTIME_MODELS,
2515
2515
  isSessionRealtimeModel,
2516
2516
  projectSessionRealtimeLifecycle,
@@ -2521,4 +2521,4 @@ export {
2521
2521
  hasStoredSessionRealtimeOwnerProof,
2522
2522
  createCodexRealtimeController
2523
2523
  };
2524
- //# sourceMappingURL=chunk-35S72HAE.js.map
2524
+ //# sourceMappingURL=chunk-U4JUWOZV.js.map
@@ -262,4 +262,4 @@ export {
262
262
  GENERATED_VIDEO_MAX_BYTES,
263
263
  KNOWN_USAGE_EVENT_TYPES
264
264
  };
265
- //# sourceMappingURL=chunk-BLID3DCD.js.map
265
+ //# sourceMappingURL=chunk-V4AIZAFF.js.map