@opengeni/sdk 0.48.0 → 0.57.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 (122) hide show
  1. package/README.md +147 -1
  2. package/dist/artifact-client.d.ts +20 -2
  3. package/dist/artifacts.d.ts +4 -0
  4. package/dist/artifacts.js +11 -0
  5. package/dist/artifacts.js.map +1 -0
  6. package/dist/{chunk-V5F253OG.js → chunk-GU6JF75T.js} +6 -3
  7. package/dist/chunk-GU6JF75T.js.map +1 -0
  8. package/dist/chunk-HJ3HHUT5.js +222 -0
  9. package/dist/chunk-HJ3HHUT5.js.map +1 -0
  10. package/dist/{chunk-KIHGPM7H.js → chunk-JDLDDRNE.js} +20 -14
  11. package/dist/chunk-JDLDDRNE.js.map +1 -0
  12. package/dist/chunk-JRPFWI6T.js +128 -0
  13. package/dist/chunk-JRPFWI6T.js.map +1 -0
  14. package/dist/{chunk-MBGBLVUV.js → chunk-PKQ377ED.js} +1725 -555
  15. package/dist/chunk-PKQ377ED.js.map +1 -0
  16. package/dist/chunk-ST5DDKJP.js +987 -0
  17. package/dist/chunk-ST5DDKJP.js.map +1 -0
  18. package/dist/chunk-VWE2QIVO.js +1162 -0
  19. package/dist/chunk-VWE2QIVO.js.map +1 -0
  20. package/dist/chunk-VYCTL62C.js +230 -0
  21. package/dist/chunk-VYCTL62C.js.map +1 -0
  22. package/dist/{chunk-DXDL7EEW.js → chunk-YKZME56C.js} +197 -113
  23. package/dist/chunk-YKZME56C.js.map +1 -0
  24. package/dist/client.d.ts +240 -16
  25. package/dist/codex-realtime-controller.d.ts +9 -6
  26. package/dist/codex-realtime-controller.js +2 -2
  27. package/dist/codex-realtime-lifecycle.d.ts +1 -1
  28. package/dist/codex-realtime-v3.d.ts +3 -3
  29. package/dist/codex-realtime.d.ts +1 -1
  30. package/dist/company-profile.d.ts +100 -0
  31. package/dist/core.d.ts +5 -5
  32. package/dist/core.js +10 -5
  33. package/dist/desktop.d.ts +9 -1
  34. package/dist/editable-artifact-resources.d.ts +96 -0
  35. package/dist/editable-artifacts/browser-session.d.ts +35 -0
  36. package/dist/editable-artifacts/controller.d.ts +60 -0
  37. package/dist/editable-artifacts/errors.d.ts +23 -0
  38. package/dist/editable-artifacts/http-live-transport.d.ts +46 -0
  39. package/dist/editable-artifacts/index.d.ts +19 -0
  40. package/dist/editable-artifacts/pool.d.ts +15 -0
  41. package/dist/editable-artifacts/session.d.ts +96 -0
  42. package/dist/editable-artifacts/storage.d.ts +72 -0
  43. package/dist/editable-artifacts/types.d.ts +416 -0
  44. package/dist/editable-artifacts/worker/browser-client.d.ts +80 -0
  45. package/dist/editable-artifacts/worker/browser-entry.d.ts +6 -0
  46. package/dist/editable-artifacts/worker/kernel-adapter.d.ts +45 -0
  47. package/dist/editable-artifacts/worker/rpc-protocol.d.ts +92 -0
  48. package/dist/editable-artifacts/worker/runtime.d.ts +66 -0
  49. package/dist/editable-artifacts/worker/wire-codec.d.ts +52 -0
  50. package/dist/editable-artifacts-worker.d.ts +8 -0
  51. package/dist/editable-artifacts-worker.js +1708 -0
  52. package/dist/editable-artifacts-worker.js.map +1 -0
  53. package/dist/editable-artifacts.d.ts +6 -0
  54. package/dist/editable-artifacts.js +5954 -0
  55. package/dist/editable-artifacts.js.map +1 -0
  56. package/dist/gateway-realtime-transport.d.ts +2 -1
  57. package/dist/gateway-realtime-transport.js +5 -3
  58. package/dist/index.d.ts +45 -35
  59. package/dist/index.js +134 -64
  60. package/dist/index.js.map +1 -1
  61. package/dist/interaction-revision-stream.d.ts +11 -0
  62. package/dist/interaction.d.ts +1484 -0
  63. package/dist/interaction.js +81 -0
  64. package/dist/interaction.js.map +1 -0
  65. package/dist/memory-slack-client.d.ts +13 -0
  66. package/dist/memory-slack-delivery.d.ts +99 -0
  67. package/dist/memory-slack.d.ts +4 -0
  68. package/dist/memory-slack.js +44 -0
  69. package/dist/memory-slack.js.map +1 -0
  70. package/dist/proxy.d.ts +3 -3
  71. package/dist/realtime.d.ts +14 -14
  72. package/dist/realtime.js +11 -7
  73. package/dist/realtime.js.map +1 -1
  74. package/dist/retained-artifacts.d.ts +12 -0
  75. package/dist/stream.d.ts +1 -1
  76. package/dist/terminal.d.ts +1 -1
  77. package/dist/types.d.ts +1347 -34
  78. package/dist/workspace-control-stream.d.ts +2 -2
  79. package/dist/workspace-live-stream.d.ts +14 -0
  80. package/dist/workspace-state.d.ts +1 -1
  81. package/package.json +29 -3
  82. package/src/artifact-client.ts +129 -0
  83. package/src/artifacts.ts +17 -0
  84. package/src/client.ts +3022 -910
  85. package/src/codex-realtime-controller.ts +25 -7
  86. package/src/codex-realtime-lifecycle.ts +1 -0
  87. package/src/company-profile.ts +92 -0
  88. package/src/desktop.ts +11 -1
  89. package/src/editable-artifact-resources.ts +119 -0
  90. package/src/editable-artifacts/browser-session.ts +176 -0
  91. package/src/editable-artifacts/controller.ts +2632 -0
  92. package/src/editable-artifacts/errors.ts +52 -0
  93. package/src/editable-artifacts/http-live-transport.ts +1449 -0
  94. package/src/editable-artifacts/index.ts +175 -0
  95. package/src/editable-artifacts/pool.ts +81 -0
  96. package/src/editable-artifacts/session.ts +778 -0
  97. package/src/editable-artifacts/storage.ts +1718 -0
  98. package/src/editable-artifacts/types.ts +499 -0
  99. package/src/editable-artifacts/worker/browser-client.ts +1167 -0
  100. package/src/editable-artifacts/worker/browser-entry.ts +57 -0
  101. package/src/editable-artifacts/worker/kernel-adapter.ts +1039 -0
  102. package/src/editable-artifacts/worker/rpc-protocol.ts +622 -0
  103. package/src/editable-artifacts/worker/runtime.ts +1204 -0
  104. package/src/editable-artifacts/worker/wire-codec.ts +852 -0
  105. package/src/editable-artifacts-worker.ts +8 -0
  106. package/src/editable-artifacts.ts +6 -0
  107. package/src/errors.ts +16 -2
  108. package/src/gateway-realtime-transport.ts +252 -109
  109. package/src/index.ts +215 -1
  110. package/src/interaction-revision-stream.ts +117 -0
  111. package/src/interaction.ts +2874 -0
  112. package/src/memory-slack-client.ts +71 -0
  113. package/src/memory-slack-delivery.ts +128 -0
  114. package/src/memory-slack.ts +19 -0
  115. package/src/realtime.ts +14 -4
  116. package/src/retained-artifacts.ts +326 -0
  117. package/src/types.ts +1636 -52
  118. package/src/workspace-live-stream.ts +137 -0
  119. package/dist/chunk-DXDL7EEW.js.map +0 -1
  120. package/dist/chunk-KIHGPM7H.js.map +0 -1
  121. package/dist/chunk-MBGBLVUV.js.map +0 -1
  122. package/dist/chunk-V5F253OG.js.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/artifact-client.ts","../src/proxy.ts","../src/mcp-output.ts","../src/desktop.ts","../src/terminal.ts","../src/workspace-instruction-policies.ts","../src/preference-registry.ts"],"sourcesContent":["import { OpenGeniClient as OpenGeniCoreClient } from \"./client\";\nimport type {\n CreateWorkspaceArtifactRequest,\n PublishWorkspaceArtifactVersionRequest,\n RollbackWorkspaceArtifactRequest,\n WorkspaceArtifactContentResponse,\n WorkspaceArtifactDetailResponse,\n WorkspaceArtifactListOptions,\n WorkspaceArtifactListResponse,\n WorkspaceArtifactMutationResponse,\n} from \"./workspace-artifacts\";\n\n/** Public SDK client. Artifact operations stay out of the console's eager core graph. */\nexport class OpenGeniClient extends OpenGeniCoreClient {\n async listWorkspaceArtifacts(\n workspaceId: string,\n options: WorkspaceArtifactListOptions = {},\n ): Promise<WorkspaceArtifactListResponse> {\n const query = new URLSearchParams();\n if (options.limit !== undefined) query.set(\"limit\", String(options.limit));\n if (options.cursor) query.set(\"cursor\", options.cursor);\n const suffix = query.size > 0 ? `?${query.toString()}` : \"\";\n return await this.requestJson<WorkspaceArtifactListResponse>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/published-artifacts${suffix}`,\n );\n }\n\n async getWorkspaceArtifact(\n workspaceId: string,\n artifactId: string,\n ): Promise<WorkspaceArtifactDetailResponse> {\n return await this.requestJson<WorkspaceArtifactDetailResponse>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/published-artifacts/${encodeURIComponent(artifactId)}`,\n );\n }\n\n async getWorkspaceArtifactContent(\n workspaceId: string,\n artifactId: string,\n versionId?: string,\n ): Promise<WorkspaceArtifactContentResponse> {\n const query = versionId ? `?versionId=${encodeURIComponent(versionId)}` : \"\";\n return await this.requestJson<WorkspaceArtifactContentResponse>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/published-artifacts/${encodeURIComponent(artifactId)}/content${query}`,\n );\n }\n\n async createWorkspaceArtifact(\n workspaceId: string,\n request: CreateWorkspaceArtifactRequest,\n ): Promise<WorkspaceArtifactMutationResponse> {\n return await this.requestJson<WorkspaceArtifactMutationResponse>(\n \"POST\",\n `/v1/workspaces/${workspaceId}/published-artifacts`,\n request,\n );\n }\n\n async publishWorkspaceArtifactVersion(\n workspaceId: string,\n artifactId: string,\n request: PublishWorkspaceArtifactVersionRequest,\n ): Promise<WorkspaceArtifactMutationResponse> {\n return await this.requestJson<WorkspaceArtifactMutationResponse>(\n \"POST\",\n `/v1/workspaces/${workspaceId}/published-artifacts/${encodeURIComponent(artifactId)}/versions`,\n request,\n );\n }\n\n async rollbackWorkspaceArtifact(\n workspaceId: string,\n artifactId: string,\n request: RollbackWorkspaceArtifactRequest,\n ): Promise<WorkspaceArtifactMutationResponse> {\n return await this.requestJson<WorkspaceArtifactMutationResponse>(\n \"POST\",\n `/v1/workspaces/${workspaceId}/published-artifacts/${encodeURIComponent(artifactId)}/rollback`,\n request,\n );\n }\n}\n","import type { OpenGeniClient } from \"./client\";\nimport 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`.\n */\n\n/** Format one event exactly as OpenGeni's API emits it over SSE. */\nexport function formatSseEvent(event: SessionEvent): string {\n return `id: ${event.sequence}\\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 (the re-emitted stream\n * sets `id:` to the sequence). 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","/**\n * A transport-tolerant MCP tool result.\n *\n * `value` is the canonical machine-readable payload after recognized MCP/JSON\n * envelopes are removed. `text` is the best presentation string without\n * discarding structured data. `raw` always retains the original evidence.\n */\nexport type NormalizedMcpOutput = Readonly<{\n raw: unknown;\n value: unknown;\n text: string;\n isError: boolean;\n}>;\n\nconst MAX_MCP_OUTPUT_DEPTH = 8;\nconst RESULT_ENVELOPE_KEYS = new Set([\"result\", \"isError\", \"jsonrpc\", \"id\", \"_meta\"]);\n\n/** Normalize common direct, JSON, and standard MCP result envelopes without throwing. */\nexport function normalizeMcpOutput(output: unknown): NormalizedMcpOutput {\n const normalized = normalizeValue(output, 0, new Set<object>());\n return {\n raw: output,\n value: normalized.value,\n text: normalized.text,\n isError: normalized.isError,\n };\n}\n\ntype NormalizedValue = Omit<NormalizedMcpOutput, \"raw\">;\n\nfunction normalizeValue(value: unknown, depth: number, ancestors: Set<object>): NormalizedValue {\n if (value === null || value === undefined) {\n return { value, text: \"\", isError: false };\n }\n if (typeof value === \"string\") {\n return normalizeText(value, depth, ancestors);\n }\n if (typeof value !== \"object\") {\n return { value, text: String(value), isError: false };\n }\n if (depth >= MAX_MCP_OUTPUT_DEPTH || ancestors.has(value)) {\n return { value, text: safeStringify(value), isError: false };\n }\n\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n return { value, text: safeStringify(value), isError: false };\n }\n\n const record = value as Record<string, unknown>;\n const envelopeError = record.isError === true;\n\n if (record.type === \"text\" && typeof record.text === \"string\") {\n const normalized = normalizeText(record.text, depth + 1, ancestors);\n return {\n value: normalized.value,\n text: record.text,\n isError: envelopeError || normalized.isError,\n };\n }\n\n if (\"structuredContent\" in record) {\n const normalized = normalizeValue(record.structuredContent, depth + 1, ancestors);\n return {\n value: normalized.value,\n text: firstMcpText(record.content) ?? normalized.text,\n isError: envelopeError || normalized.isError,\n };\n }\n\n if (isMcpContent(record.content)) {\n const text = firstMcpText(record.content);\n if (text !== null) {\n const normalized = normalizeText(text, depth + 1, ancestors);\n return {\n value: normalized.value,\n text,\n isError: envelopeError || normalized.isError,\n };\n }\n return {\n value,\n text: safeStringify(value),\n isError: envelopeError,\n };\n }\n\n if (isResultEnvelope(record)) {\n const normalized = normalizeValue(record.result, depth + 1, ancestors);\n return {\n value: normalized.value,\n text: normalized.text,\n isError: envelopeError || normalized.isError,\n };\n }\n\n return {\n value,\n text: safeStringify(value),\n isError: envelopeError,\n };\n } finally {\n ancestors.delete(value);\n }\n}\n\nfunction normalizeText(text: string, depth: number, ancestors: Set<object>): NormalizedValue {\n try {\n const parsed: unknown = JSON.parse(text);\n const normalized = normalizeValue(parsed, depth + 1, ancestors);\n return {\n value: normalized.value,\n text,\n isError: normalized.isError,\n };\n } catch {\n return { value: text, text, isError: false };\n }\n}\n\nfunction isMcpContent(value: unknown): value is readonly Record<string, unknown>[] {\n return (\n Array.isArray(value) &&\n value.some(\n (part) =>\n part !== null &&\n typeof part === \"object\" &&\n typeof (part as { type?: unknown }).type === \"string\",\n )\n );\n}\n\nfunction firstMcpText(value: unknown): string | null {\n if (!Array.isArray(value)) {\n return null;\n }\n for (const part of value) {\n if (\n part !== null &&\n typeof part === \"object\" &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n }\n return null;\n}\n\nfunction isResultEnvelope(record: Record<string, unknown>): boolean {\n return \"result\" in record && Object.keys(record).every((key) => RESULT_ENVELOPE_KEYS.has(key));\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? \"\";\n } catch {\n return String(value);\n }\n}\n","// Zero-dependency desktop (noVNC) transport contract.\n//\n// The actual `@novnc/novnc` RFB import is a browser-only DOM dependency and\n// lives in `@opengeni/react` (lazily imported, SSR-safe). The framework-agnostic\n// SDK ships only the transport CONTRACT: a URL assembler, the minimal RFB\n// surface the component drives, the connection state machine, and the\n// rotation/fence reducers — all pure and unit-testable, with no DOM and no deps.\n//\n// Channel A (terminal-as-events, files, git) needs NO new transport here: those\n// are event projections + the synchronous fs/git/terminal point queries on\n// `OpenGeniClient`. Only the desktop pixel plane (Channel B, direct-to-provider)\n// needs this.\n\nimport type { DesktopStreamCapability, StreamUrlRotatedPayload } from \"./types\";\n\n/**\n * Translate the negotiated desktop capability into the WebSocket URL the noVNC\n * RFB client connects to. The scoped provider token is ALREADY embedded in the\n * minted `url` (Modal tunnel host, Blaxel `bl_preview_token`, Daytona signed\n * preview) by `session.resolveExposedPort(6080)` — we do NOT append `cap.token`\n * as a query param (that double-auth was an adversarial-review bug: the box runs\n * `-nopw` in v1, so the RFB password is meaningless and the real auth is the\n * tunnel token in the host). We only normalize the scheme to `ws`/`wss` and, when\n * the minted URL points at a `vnc.html` viewer page, rewrite it to the\n * websockify socket path noVNC actually dials.\n */\nexport function desktopSocketUrl(cap: Pick<DesktopStreamCapability, \"url\">): string {\n if (!cap.url) {\n throw new Error(\"desktop capability has no url (transport is null)\");\n }\n const u = new URL(cap.url);\n // https → wss, http → ws (noVNC dials a WebSocket, not the HTTP viewer page).\n if (u.protocol === \"https:\") {\n u.protocol = \"wss:\";\n } else if (u.protocol === \"http:\") {\n u.protocol = \"ws:\";\n }\n // A minted `…/vnc.html` (or `…/vnc_lite.html`) viewer page → the websockify\n // socket the page itself would open (`…/websockify`). A bare host/path with no\n // viewer page is already the socket path; leave it untouched.\n if (/\\/vnc(_lite)?\\.html$/.test(u.pathname)) {\n u.pathname = u.pathname.replace(/\\/vnc(_lite)?\\.html$/, \"/websockify\");\n u.search = \"\";\n u.hash = \"\";\n }\n return u.toString();\n}\n\n/**\n * The minimal RFB surface the React component drives. Lets tests (and 3rd\n * parties swapping noVNC for a WebRTC client in v3) provide a fake without the\n * DOM. Matches `@novnc/novnc`'s RFB constructor + lifecycle.\n */\nexport interface DesktopRfbLike {\n viewOnly: boolean;\n scaleViewport: boolean;\n /**\n * 1:1 viewport clipping. We always drive this FALSE: with clipping on, noVNC\n * paints the framebuffer pixel-for-pixel and scrolls/crops to the container\n * (the \"zoomed in\" look). FALSE lets `scaleViewport` shrink the 1280x800 frame\n * to fit the panel (aspect-preserved). Declared so the hook can pin it instead\n * of relying on noVNC's default — `scaleViewport=true` forces clip off\n * internally, but a stale/partial state on reconnect could leave it on.\n */\n clipViewport: boolean;\n addEventListener(\n type: \"connect\" | \"disconnect\" | \"securityfailure\",\n cb: (e?: unknown) => void,\n ): void;\n removeEventListener?: (\n type: \"connect\" | \"disconnect\" | \"securityfailure\",\n cb: (e?: unknown) => void,\n ) => void;\n disconnect(): void;\n}\n\nexport type DesktopRfbFactory = (\n target: HTMLElement,\n url: string,\n opts: { credentials?: { password?: string | undefined } | undefined },\n) => DesktopRfbLike;\n\nexport type DesktopConnectionState =\n | \"idle\"\n | \"negotiating\"\n | \"connecting\"\n | \"connected\"\n | \"rotating\"\n | \"reconnecting\"\n | \"error\"\n | \"ended\";\n\nexport type DesktopStreamEvent =\n | { type: \"negotiated\" }\n | { type: \"connected\" }\n | { type: \"disconnected\" }\n | { type: \"rotate\" }\n | { type: \"fail\" }\n | { type: \"abort\" };\n\n/**\n * Pure reducer for the desktop connection lifecycle. The component owns the RFB\n * object + DOM; this owns the transitions so they are unit-testable. Mirrors the\n * Channel-A stream reducer discipline.\n */\nexport function nextDesktopState(\n current: DesktopConnectionState,\n ev: DesktopStreamEvent,\n): DesktopConnectionState {\n switch (ev.type) {\n case \"negotiated\":\n return \"connecting\";\n case \"connected\":\n return \"connected\";\n case \"rotate\":\n return current === \"connected\" ? \"rotating\" : current;\n case \"disconnected\":\n // A deliberate teardown (ended) stays ended; everything else reconnects.\n return current === \"ended\" ? \"ended\" : \"reconnecting\";\n case \"fail\":\n return \"error\";\n case \"abort\":\n return \"ended\";\n default:\n return current;\n }\n}\n\n// `DesktopStreamCapability` is the desktop cell of `SessionCapabilities`; alias\n// it for the rotation reducer below without depending on the whole doc.\nexport type DesktopStreamCapabilityLike = {\n url: string | null;\n token: string | null;\n expiresAt: string | null;\n};\n\n/**\n * Apply a `stream.url.rotated` event onto a desktop capability, fencing on\n * leaseEpoch (split-brain). A rotation minted under an epoch the client has\n * already advanced PAST is from a superseded owner and is dropped (returns\n * null); otherwise the fresh url/token/expiresAt are folded in.\n */\nexport function applyUrlRotation<T extends DesktopStreamCapabilityLike>(\n cap: T,\n payload: StreamUrlRotatedPayload,\n knownEpoch: number,\n): T | null {\n if (payload.leaseEpoch < knownEpoch) {\n return null;\n }\n return { ...cap, url: payload.url, token: payload.token, expiresAt: payload.expiresAt };\n}\n","// Zero-dependency interactive-terminal (ttyd PTY-over-websocket) transport\n// contract. Symmetric with `desktop.ts`: the SDK ships only the pure transport\n// CONTRACT (a URL assembler + the ttyd wire-protocol frame codec), with no DOM\n// and no deps. The actual WebSocket open + xterm attach lives in `@opengeni/react`\n// (`use-terminal-stream.ts`).\n//\n// The interactive terminal is a REAL PTY streamed over the SAME Modal raw-TLS\n// tunnel as the desktop noVNC, with the SAME scoped stream-token mechanism. The\n// box bakes `ttyd` on `TERMINAL_STREAM_PORT` (7681); `session.resolveExposedPort`\n// mints the tunnel URL. The Terminal capability cell carries transport \"pty-ws\" +\n// that url + the scoped token when the box is warm and a viewer is attached.\n\nimport type { TerminalCapability } from \"./types\";\n\n/**\n * Translate the negotiated `pty-ws` Terminal capability into the WebSocket URL\n * the ttyd client dials. The scoped provider token is ALREADY embedded in the\n * minted `url` (the Modal tunnel host) by `session.resolveExposedPort(7681)` —\n * we do NOT append `cap.token` (identical posture to the desktop: the gate is the\n * unguessable short-TTL tunnel URL + the server-recorded scoped stream token; ttyd\n * runs `--writable` with no `-c` credential in v1). We only normalize the scheme\n * to `ws`/`wss`; a bare host is already the ttyd websocket endpoint.\n */\nexport function terminalSocketUrl(cap: Pick<TerminalCapability, \"url\">): string {\n if (!cap.url) {\n throw new Error(\"terminal capability has no url (transport is not pty-ws)\");\n }\n const u = new URL(cap.url);\n // https → wss, http → ws (ttyd is dialed as a WebSocket, not an HTTP page).\n if (u.protocol === \"https:\") {\n u.protocol = \"wss:\";\n } else if (u.protocol === \"http:\") {\n u.protocol = \"ws:\";\n }\n return u.toString();\n}\n\n// ── ttyd wire protocol ───────────────────────────────────────────────────────\n// ttyd frames are a single ASCII command char + payload. These mirror ttyd's\n// `protocol.h` Command enum. Client→server and server→client share the byte 0/1/2\n// values but mean different things per direction (see below).\n\n/** ttyd subprotocol — REQUIRED on the WebSocket handshake or ttyd refuses it. */\nexport const TTYD_SUBPROTOCOL = \"tty\";\n\n/** Client→server command bytes (the first char of each outbound text frame). */\nexport const TtydClientCommand = {\n /** stdin: \"0\" + raw input bytes. */\n INPUT: \"0\",\n /** window resize: \"1\" + JSON.stringify({ columns, rows }). */\n RESIZE: \"1\",\n /** flow-control pause (back-pressure): \"2\". */\n PAUSE: \"2\",\n /** flow-control resume: \"3\". */\n RESUME: \"3\",\n} as const;\n\n/** Server→client command bytes (the first char of each inbound frame). */\nexport const TtydServerCommand = {\n /** stdout/stderr: \"0\" + raw output bytes (write the rest into xterm). */\n OUTPUT: \"0\",\n /** set the window title: \"1\" + title string. */\n SET_WINDOW_TITLE: \"1\",\n /** ttyd client preferences JSON: \"2\" + json (ignored by us). */\n SET_PREFERENCES: \"2\",\n} as const;\n\n/**\n * The ttyd handshake's first frame: an auth message. ttyd expects\n * `JSON.stringify({ AuthToken })` as the FIRST text frame on the socket. We send\n * an empty token — our gate is the tunnel URL + scoped stream token, NOT a ttyd\n * `-c` basic-auth credential (which the box does not set in v1). Optional ttyd\n * `columns`/`rows` can ride this frame to seed the PTY size before the first\n * resize. Pure (string-building only) so it stays unit-testable in the SDK.\n */\nexport function ttydAuthFrame(opts?: { columns?: number; rows?: number }): string {\n const frame: { AuthToken: string; columns?: number; rows?: number } = { AuthToken: \"\" };\n if (opts?.columns && opts.columns > 0) frame.columns = opts.columns;\n if (opts?.rows && opts.rows > 0) frame.rows = opts.rows;\n return JSON.stringify(frame);\n}\n\n/** Build a client→server INPUT (stdin) frame: \"0\" + data. */\nexport function ttydInputFrame(data: string): string {\n return TtydClientCommand.INPUT + data;\n}\n\n/** Build a client→server RESIZE frame: \"1\" + JSON.stringify({ columns, rows }). */\nexport function ttydResizeFrame(columns: number, rows: number): string {\n return TtydClientCommand.RESIZE + JSON.stringify({ columns, rows });\n}\n","export const WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS = 262_144;\n\nexport type WorkspaceInstructionPolicyKind = \"charter\" | \"policy\";\nexport type WorkspaceInstructionPolicyScope = \"global\" | \"role\";\nexport type WorkspaceInstructionPolicyProvenanceSource =\n | \"human\"\n | \"onboarding\"\n | \"knowledge_proposal\"\n | \"legacy_import\";\nexport type WorkspaceInstructionPolicyDraftProvenanceSource = Exclude<\n WorkspaceInstructionPolicyProvenanceSource,\n \"legacy_import\"\n>;\nexport type WorkspaceInstructionPolicyActivationType = \"activate\" | \"rollback\";\n\nexport function normalizeWorkspaceInstructionPolicyRoleKey(value: string): string {\n return value.normalize(\"NFKC\").trim().toLowerCase().replace(/\\s+/gu, \"-\").replace(/-+/g, \"-\");\n}\n\nexport type WorkspaceInstructionPolicyTarget = {\n kind: WorkspaceInstructionPolicyKind;\n scope: WorkspaceInstructionPolicyScope;\n roleKey: string | null;\n};\n\nexport type WorkspaceInstructionPolicyRevisionIdentity = {\n id: string;\n revision: number;\n contentHash: string;\n};\n\nexport type WorkspaceInstructionPolicyRevision = WorkspaceInstructionPolicyRevisionIdentity &\n WorkspaceInstructionPolicyTarget & {\n operationId: string;\n accountId: string;\n workspaceId: string;\n content: string;\n provenance: {\n source: WorkspaceInstructionPolicyProvenanceSource;\n sourceId: string | null;\n };\n supersedesRevisionId: string | null;\n createdBySubjectId: string;\n createdAt: string;\n };\n\nexport type WorkspaceInstructionPolicyHead = WorkspaceInstructionPolicyTarget & {\n workspaceId: string;\n revisionId: string;\n revision: number;\n contentHash: string;\n activationVersion: number;\n activatedAt: string;\n};\n\nexport type WorkspaceInstructionPolicyActivationEvent = WorkspaceInstructionPolicyTarget & {\n id: string;\n operationId: string;\n accountId: string;\n workspaceId: string;\n type: WorkspaceInstructionPolicyActivationType;\n activationVersion: number;\n oldRevision: WorkspaceInstructionPolicyRevisionIdentity | null;\n newRevision: WorkspaceInstructionPolicyRevisionIdentity;\n actorSubjectId: string;\n reason: string;\n createdAt: string;\n};\n\nexport type CreateWorkspaceInstructionPolicyDraftRequest = WorkspaceInstructionPolicyTarget & {\n operationId?: string;\n content: string;\n provenanceSource?: WorkspaceInstructionPolicyDraftProvenanceSource;\n provenanceSourceId?: string | null;\n supersedesRevisionId?: string | null;\n};\n\nexport type ImportLegacyWorkspaceInstructionPolicyDraftRequest = {\n operationId?: string;\n supersedesRevisionId?: string | null;\n};\n\nexport type WorkspaceInstructionPolicyListOptions = {\n kind?: WorkspaceInstructionPolicyKind;\n scope?: WorkspaceInstructionPolicyScope;\n roleKey?: string;\n afterRevision?: number;\n limit?: number;\n};\n\nexport type WorkspaceInstructionPolicyListResponse = {\n revisions: WorkspaceInstructionPolicyRevision[];\n activeHeads: WorkspaceInstructionPolicyHead[];\n activationEvents: WorkspaceInstructionPolicyActivationEvent[];\n nextAfterRevision: number | null;\n};\n\nexport type WorkspaceInstructionPolicyDiffRequest = {\n fromRevisionId: string;\n toRevisionId: string;\n};\n\nexport type WorkspaceInstructionPolicyDiffResponse = {\n from: WorkspaceInstructionPolicyRevision;\n to: WorkspaceInstructionPolicyRevision;\n format: \"unified\";\n diff: string;\n};\n\nexport type ActivateWorkspaceInstructionPolicyRequest = {\n operationId?: string;\n expectedCurrentRevisionId: string | null;\n expectedActivationVersion?: number;\n reason: string;\n};\n\nexport type RollbackWorkspaceInstructionPolicyRequest = {\n operationId?: string;\n targetRevisionId: string;\n expectedCurrentRevisionId: string;\n expectedActivationVersion?: number;\n reason: string;\n};\n\nexport type WorkspaceInstructionPolicyActivationResponse = {\n head: WorkspaceInstructionPolicyHead;\n event: WorkspaceInstructionPolicyActivationEvent;\n};\n\nexport type WorkspaceInstructionPolicyConflictResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_CONFLICT\";\n message: string;\n currentHead: WorkspaceInstructionPolicyHead | null;\n};\n\nexport type WorkspaceInstructionPolicyOperationReuseResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_OPERATION_REUSED\";\n message: string;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalSource = {\n id: string;\n version: string;\n confidenceBps: number;\n};\n\nexport type CreateWorkspaceInstructionPolicyOnboardingProposalRequest =\n WorkspaceInstructionPolicyTarget & {\n operationId?: string;\n content: string;\n sourceId: string;\n sourceVersion: string;\n confidenceBps: number;\n expectedCurrentRevisionId: string | null;\n expectedActivationVersion: number;\n };\n\nexport type WorkspaceInstructionPolicyOnboardingProposal = WorkspaceInstructionPolicyTarget & {\n id: string;\n operationId: string;\n accountId: string;\n workspaceId: string;\n source: WorkspaceInstructionPolicyOnboardingProposalSource;\n baseline: WorkspaceInstructionPolicyHead | null;\n draft: WorkspaceInstructionPolicyRevision;\n status: \"proposed\";\n createdBySubjectId: string;\n createdAt: string;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalListOptions = {\n limit?: number;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalListResponse = {\n proposals: WorkspaceInstructionPolicyOnboardingProposal[];\n truncated: boolean;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse = {\n code:\n | \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_EMPTY\"\n | \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_OVERSIZED\";\n message: string;\n maxChars: number;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalStaleResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_STALE\";\n message: string;\n currentHead: WorkspaceInstructionPolicyHead | null;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalConflictResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_CONFLICT\";\n message: string;\n existingProposalId: string;\n existingDraftRevisionId: string;\n};\n","export type PreferenceRegistryScope = \"organization\" | \"workspace\" | \"user\";\nexport type PreferenceRegistryStatus =\n | \"proposed\"\n | \"active\"\n | \"inactive\"\n | \"rejected\"\n | \"superseded\"\n | \"expired\";\nexport type PreferenceRegistryProvenanceSource =\n | \"human\"\n | \"onboarding\"\n | \"knowledge_proposal\"\n | \"imported_document\"\n | \"slack\"\n | \"meeting_transcript\"\n | \"call_transcript\";\nexport type PreferenceRegistryTrust =\n | \"untrusted_proposal\"\n | \"personal\"\n | \"workspace_managed\"\n | \"organization_managed\";\nexport type PreferenceRegistryConflictStrategy = \"override\" | \"merge\" | \"reject\" | \"inform\";\n\nexport function normalizePreferenceRegistryStableKey(value: string): string {\n return value.normalize(\"NFKC\").trim().toLowerCase().replace(/\\s+/gu, \"-\").replace(/-+/g, \"-\");\n}\n\nexport type PreferenceRegistryScopeTarget = {\n scope: PreferenceRegistryScope;\n workspaceId: string | null;\n subjectId: string | null;\n};\n\nexport type PreferenceRegistryPrecedence = {\n tier: PreferenceRegistryScope;\n rank: number;\n conflictStrategy: PreferenceRegistryConflictStrategy;\n conflictsWith: string[];\n};\n\nexport type PreferenceRegistryRevisionSummary = {\n id: string;\n preferenceId: string;\n revision: number;\n contentHash: string;\n title: string;\n description: string;\n precedence: PreferenceRegistryPrecedence;\n provenance: {\n source: PreferenceRegistryProvenanceSource;\n sourceId: string | null;\n trust: PreferenceRegistryTrust;\n };\n expiresAt: string | null;\n correctsRevisionId: string | null;\n createdBySubjectId: string;\n createdAt: string;\n};\n\nexport type PreferenceRegistryDescriptorProvenance = {\n source: PreferenceRegistryProvenanceSource;\n sourceIdHash: string | null;\n trust: PreferenceRegistryTrust;\n};\n\nexport type PreferenceRegistryRecord = {\n id: string;\n accountId: string;\n stableKey: string;\n target: PreferenceRegistryScopeTarget;\n status: PreferenceRegistryStatus;\n scopeVersion: number;\n activationVersion: number;\n activeRevision: PreferenceRegistryRevisionSummary | null;\n supersededByPreferenceId: string | null;\n createdBySubjectId: string;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type PreferenceRegistryEvent = {\n id: string;\n accountId: string;\n preferenceId: string;\n type:\n | \"proposal_created\"\n | \"activated\"\n | \"corrected\"\n | \"rejected\"\n | \"deactivated\"\n | \"superseded\"\n | \"scope_changed\";\n version: number;\n oldRevisionId: string | null;\n newRevisionId: string | null;\n oldTarget: PreferenceRegistryScopeTarget | null;\n newTarget: PreferenceRegistryScopeTarget | null;\n relatedPreferenceId: string | null;\n actorSubjectId: string;\n reason: string;\n createdAt: string;\n};\n\nexport type PreferenceRegistryDescriptor = {\n id: string;\n stableKey: string;\n title: string;\n description: string;\n scope: PreferenceRegistryScope;\n activeVersion: number;\n revisionId: string;\n contentHash: string;\n precedence: PreferenceRegistryPrecedence;\n provenance: PreferenceRegistryDescriptorProvenance;\n expiresAt: string | null;\n retrievalHandle: string;\n};\n\nexport type PreferenceRegistrySnapshot = {\n id: string;\n workspaceId: string;\n sessionId: string;\n turnId: string;\n attemptId: string;\n executionGeneration: number;\n initiatingHumanSubjectId: string;\n descriptorHash: string;\n descriptors: PreferenceRegistryDescriptor[];\n truncated: boolean;\n createdAt: string;\n};\n\nexport type PreferenceRegistryFullContent = {\n descriptor: PreferenceRegistryDescriptor;\n content: string;\n};\n\nexport type CreatePreferenceRegistryProposalRequest = {\n stableKey: string;\n scope: PreferenceRegistryScope;\n title: string;\n description: string;\n content: string;\n precedenceRank?: number;\n conflictStrategy?: PreferenceRegistryConflictStrategy;\n conflictsWith?: string[];\n expiresAt?: string | null;\n provenanceSource?: PreferenceRegistryProvenanceSource;\n provenanceSourceId?: string | null;\n};\n\nexport type ActivatePreferenceRegistryRevisionRequest = {\n revisionId: string;\n expectedCurrentRevisionId: string | null;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type CorrectPreferenceRegistryRequest = {\n expectedCurrentRevisionId: string;\n expectedScopeVersion: number;\n title: string;\n description: string;\n content: string;\n precedenceRank?: number;\n conflictStrategy?: PreferenceRegistryConflictStrategy;\n conflictsWith?: string[];\n expiresAt?: string | null;\n reason: string;\n};\n\nexport type DeactivatePreferenceRegistryRequest = {\n expectedCurrentRevisionId: string;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type ChangePreferenceRegistryScopeRequest = {\n scope: PreferenceRegistryScope;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type SupersedePreferenceRegistryRequest = {\n replacementPreferenceId: string;\n expectedCurrentRevisionId: string;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type RejectPreferenceRegistryProposalRequest = {\n revisionId: string;\n expectedScopeVersion: number;\n reason: string;\n};\nexport type PreferenceRegistryListOptions = {\n scope?: PreferenceRegistryScope;\n status?: PreferenceRegistryStatus;\n limit?: number;\n};\nexport type PreferenceRegistryListResponse = { preferences: PreferenceRegistryRecord[] };\nexport type PreferenceRegistryDetailResponse = {\n preference: PreferenceRegistryRecord;\n revisions: PreferenceRegistryRevisionSummary[];\n events: PreferenceRegistryEvent[];\n};\nexport type PreferenceRegistryMutationResponse = {\n preference: PreferenceRegistryRecord;\n event: PreferenceRegistryEvent;\n};\n"],"mappings":"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","names":["OpenGeniClient"]}
1
+ {"version":3,"sources":["../src/proxy.ts","../src/mcp-output.ts","../src/desktop.ts","../src/terminal.ts","../src/workspace-instruction-policies.ts","../src/company-profile.ts","../src/preference-registry.ts"],"sourcesContent":["import type { OpenGeniClient } from \"./client\";\nimport 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`.\n */\n\n/** Format one event exactly as OpenGeni's API emits it over SSE. */\nexport function formatSseEvent(event: SessionEvent): string {\n return `id: ${event.sequence}\\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 (the re-emitted stream\n * sets `id:` to the sequence). 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","/**\n * A transport-tolerant MCP tool result.\n *\n * `value` is the canonical machine-readable payload after recognized MCP/JSON\n * envelopes are removed. `text` is the best presentation string without\n * discarding structured data. `raw` always retains the original evidence.\n */\nexport type NormalizedMcpOutput = Readonly<{\n raw: unknown;\n value: unknown;\n text: string;\n isError: boolean;\n}>;\n\nconst MAX_MCP_OUTPUT_DEPTH = 8;\nconst RESULT_ENVELOPE_KEYS = new Set([\"result\", \"isError\", \"jsonrpc\", \"id\", \"_meta\"]);\n\n/** Normalize common direct, JSON, and standard MCP result envelopes without throwing. */\nexport function normalizeMcpOutput(output: unknown): NormalizedMcpOutput {\n const normalized = normalizeValue(output, 0, new Set<object>());\n return {\n raw: output,\n value: normalized.value,\n text: normalized.text,\n isError: normalized.isError,\n };\n}\n\ntype NormalizedValue = Omit<NormalizedMcpOutput, \"raw\">;\n\nfunction normalizeValue(value: unknown, depth: number, ancestors: Set<object>): NormalizedValue {\n if (value === null || value === undefined) {\n return { value, text: \"\", isError: false };\n }\n if (typeof value === \"string\") {\n return normalizeText(value, depth, ancestors);\n }\n if (typeof value !== \"object\") {\n return { value, text: String(value), isError: false };\n }\n if (depth >= MAX_MCP_OUTPUT_DEPTH || ancestors.has(value)) {\n return { value, text: safeStringify(value), isError: false };\n }\n\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n return { value, text: safeStringify(value), isError: false };\n }\n\n const record = value as Record<string, unknown>;\n const envelopeError = record.isError === true;\n\n if (record.type === \"text\" && typeof record.text === \"string\") {\n const normalized = normalizeText(record.text, depth + 1, ancestors);\n return {\n value: normalized.value,\n text: record.text,\n isError: envelopeError || normalized.isError,\n };\n }\n\n if (\"structuredContent\" in record) {\n const normalized = normalizeValue(record.structuredContent, depth + 1, ancestors);\n return {\n value: normalized.value,\n text: firstMcpText(record.content) ?? normalized.text,\n isError: envelopeError || normalized.isError,\n };\n }\n\n if (isMcpContent(record.content)) {\n const text = firstMcpText(record.content);\n if (text !== null) {\n const normalized = normalizeText(text, depth + 1, ancestors);\n return {\n value: normalized.value,\n text,\n isError: envelopeError || normalized.isError,\n };\n }\n return {\n value,\n text: safeStringify(value),\n isError: envelopeError,\n };\n }\n\n if (isResultEnvelope(record)) {\n const normalized = normalizeValue(record.result, depth + 1, ancestors);\n return {\n value: normalized.value,\n text: normalized.text,\n isError: envelopeError || normalized.isError,\n };\n }\n\n return {\n value,\n text: safeStringify(value),\n isError: envelopeError,\n };\n } finally {\n ancestors.delete(value);\n }\n}\n\nfunction normalizeText(text: string, depth: number, ancestors: Set<object>): NormalizedValue {\n try {\n const parsed: unknown = JSON.parse(text);\n const normalized = normalizeValue(parsed, depth + 1, ancestors);\n return {\n value: normalized.value,\n text,\n isError: normalized.isError,\n };\n } catch {\n return { value: text, text, isError: false };\n }\n}\n\nfunction isMcpContent(value: unknown): value is readonly Record<string, unknown>[] {\n return (\n Array.isArray(value) &&\n value.some(\n (part) =>\n part !== null &&\n typeof part === \"object\" &&\n typeof (part as { type?: unknown }).type === \"string\",\n )\n );\n}\n\nfunction firstMcpText(value: unknown): string | null {\n if (!Array.isArray(value)) {\n return null;\n }\n for (const part of value) {\n if (\n part !== null &&\n typeof part === \"object\" &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n }\n return null;\n}\n\nfunction isResultEnvelope(record: Record<string, unknown>): boolean {\n return \"result\" in record && Object.keys(record).every((key) => RESULT_ENVELOPE_KEYS.has(key));\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? \"\";\n } catch {\n return String(value);\n }\n}\n","// Zero-dependency desktop (noVNC) transport contract.\n//\n// The actual `@novnc/novnc` RFB import is a browser-only DOM dependency and\n// lives in `@opengeni/react` (lazily imported, SSR-safe). The framework-agnostic\n// SDK ships only the transport CONTRACT: a URL assembler, the minimal RFB\n// surface the component drives, the connection state machine, and the\n// rotation/fence reducers — all pure and unit-testable, with no DOM and no deps.\n//\n// Channel A (terminal-as-events, files, git) needs NO new transport here: those\n// are event projections + the synchronous fs/git/terminal point queries on\n// `OpenGeniClient`. Only the desktop pixel plane (Channel B, direct-to-provider)\n// needs this.\n\nimport type { DesktopStreamCapability, StreamUrlRotatedPayload } from \"./types\";\n\n/**\n * Translate the negotiated desktop capability into the WebSocket URL the noVNC\n * RFB client connects to. The scoped provider token is ALREADY embedded in the\n * minted `url` (Modal tunnel host, Blaxel `bl_preview_token`, Daytona signed\n * preview) by `session.resolveExposedPort(6080)` — we do NOT append `cap.token`\n * as a query param (that double-auth was an adversarial-review bug: the box runs\n * `-nopw` in v1, so the RFB password is meaningless and the real auth is the\n * tunnel token in the host). We only normalize the scheme to `ws`/`wss` and, when\n * the minted URL points at a `vnc.html` viewer page, rewrite it to the\n * websockify socket path noVNC actually dials.\n */\nexport function desktopSocketUrl(cap: Pick<DesktopStreamCapability, \"url\">): string {\n if (!cap.url) {\n throw new Error(\"desktop capability has no url (transport is null)\");\n }\n const u = new URL(cap.url);\n // https → wss, http → ws (noVNC dials a WebSocket, not the HTTP viewer page).\n if (u.protocol === \"https:\") {\n u.protocol = \"wss:\";\n } else if (u.protocol === \"http:\") {\n u.protocol = \"ws:\";\n }\n // A minted `…/vnc.html` (or `…/vnc_lite.html`) viewer page → the websockify\n // socket the page itself would open (`…/websockify`). A bare host/path with no\n // viewer page is already the socket path; leave it untouched.\n if (/\\/vnc(_lite)?\\.html$/.test(u.pathname)) {\n u.pathname = u.pathname.replace(/\\/vnc(_lite)?\\.html$/, \"/websockify\");\n u.search = \"\";\n u.hash = \"\";\n }\n return u.toString();\n}\n\n/**\n * The minimal RFB surface the React component drives. Lets tests (and 3rd\n * parties swapping noVNC for a WebRTC client in v3) provide a fake without the\n * DOM. Matches `@novnc/novnc`'s RFB constructor + lifecycle.\n */\nexport interface DesktopRfbLike {\n viewOnly: boolean;\n scaleViewport: boolean;\n /**\n * 1:1 viewport clipping. We always drive this FALSE: with clipping on, noVNC\n * paints the framebuffer pixel-for-pixel and scrolls/crops to the container\n * (the \"zoomed in\" look). FALSE lets `scaleViewport` shrink the 1280x800 frame\n * to fit the panel (aspect-preserved). Declared so the hook can pin it instead\n * of relying on noVNC's default — `scaleViewport=true` forces clip off\n * internally, but a stale/partial state on reconnect could leave it on.\n */\n clipViewport: boolean;\n addEventListener(\n type: \"connect\" | \"disconnect\" | \"securityfailure\",\n cb: (e?: unknown) => void,\n ): void;\n removeEventListener?: (\n type: \"connect\" | \"disconnect\" | \"securityfailure\",\n cb: (e?: unknown) => void,\n ) => void;\n /** Send clipboard text over the already-open RFB connection. */\n clipboardPasteFrom?(text: string): void;\n /** Send one RFB key event. A missing `down` emits a complete key press. */\n sendKey?(keysym: number, code: string, down?: boolean): void;\n /** Focus or release the RFB keyboard sink without reconnecting. */\n focus?(options?: FocusOptions): void;\n blur?(): void;\n disconnect(): void;\n}\n\nexport type DesktopRfbFactory = (\n target: HTMLElement,\n url: string,\n opts: {\n credentials?: { password?: string | undefined } | undefined;\n wsProtocols?: string[] | undefined;\n },\n) => DesktopRfbLike;\n\nexport type DesktopConnectionState =\n | \"idle\"\n | \"negotiating\"\n | \"connecting\"\n | \"connected\"\n | \"rotating\"\n | \"reconnecting\"\n | \"error\"\n | \"ended\";\n\nexport type DesktopStreamEvent =\n | { type: \"negotiated\" }\n | { type: \"connected\" }\n | { type: \"disconnected\" }\n | { type: \"rotate\" }\n | { type: \"fail\" }\n | { type: \"abort\" };\n\n/**\n * Pure reducer for the desktop connection lifecycle. The component owns the RFB\n * object + DOM; this owns the transitions so they are unit-testable. Mirrors the\n * Channel-A stream reducer discipline.\n */\nexport function nextDesktopState(\n current: DesktopConnectionState,\n ev: DesktopStreamEvent,\n): DesktopConnectionState {\n switch (ev.type) {\n case \"negotiated\":\n return \"connecting\";\n case \"connected\":\n return \"connected\";\n case \"rotate\":\n return current === \"connected\" ? \"rotating\" : current;\n case \"disconnected\":\n // A deliberate teardown (ended) stays ended; everything else reconnects.\n return current === \"ended\" ? \"ended\" : \"reconnecting\";\n case \"fail\":\n return \"error\";\n case \"abort\":\n return \"ended\";\n default:\n return current;\n }\n}\n\n// `DesktopStreamCapability` is the desktop cell of `SessionCapabilities`; alias\n// it for the rotation reducer below without depending on the whole doc.\nexport type DesktopStreamCapabilityLike = {\n url: string | null;\n token: string | null;\n expiresAt: string | null;\n};\n\n/**\n * Apply a `stream.url.rotated` event onto a desktop capability, fencing on\n * leaseEpoch (split-brain). A rotation minted under an epoch the client has\n * already advanced PAST is from a superseded owner and is dropped (returns\n * null); otherwise the fresh url/token/expiresAt are folded in.\n */\nexport function applyUrlRotation<T extends DesktopStreamCapabilityLike>(\n cap: T,\n payload: StreamUrlRotatedPayload,\n knownEpoch: number,\n): T | null {\n if (payload.leaseEpoch < knownEpoch) {\n return null;\n }\n return { ...cap, url: payload.url, token: payload.token, expiresAt: payload.expiresAt };\n}\n","// Zero-dependency interactive-terminal (ttyd PTY-over-websocket) transport\n// contract. Symmetric with `desktop.ts`: the SDK ships only the pure transport\n// CONTRACT (a URL assembler + the ttyd wire-protocol frame codec), with no DOM\n// and no deps. The actual WebSocket open + xterm attach lives in `@opengeni/react`\n// (`use-terminal-stream.ts`).\n//\n// The interactive terminal is a REAL PTY streamed over the SAME Modal raw-TLS\n// tunnel as the desktop noVNC, with the SAME scoped stream-token mechanism. The\n// box bakes `ttyd` on `TERMINAL_STREAM_PORT` (7681); `session.resolveExposedPort`\n// mints the tunnel URL. The Terminal capability cell carries transport \"pty-ws\" +\n// that url + the scoped token when the box is warm and a viewer is attached.\n\nimport type { TerminalCapability } from \"./types\";\n\n/**\n * Translate the negotiated `pty-ws` Terminal capability into the WebSocket URL\n * the ttyd client dials. The scoped provider token is ALREADY embedded in the\n * minted `url` (the Modal tunnel host) by `session.resolveExposedPort(7681)` —\n * we do NOT append `cap.token` (identical posture to the desktop: the gate is the\n * unguessable short-TTL tunnel URL + the server-recorded scoped stream token; ttyd\n * runs `--writable` with no `-c` credential in v1). We only normalize the scheme\n * to `ws`/`wss`; a bare host is already the ttyd websocket endpoint.\n */\nexport function terminalSocketUrl(cap: Pick<TerminalCapability, \"url\">): string {\n if (!cap.url) {\n throw new Error(\"terminal capability has no url (transport is not pty-ws)\");\n }\n const u = new URL(cap.url);\n // https → wss, http → ws (ttyd is dialed as a WebSocket, not an HTTP page).\n if (u.protocol === \"https:\") {\n u.protocol = \"wss:\";\n } else if (u.protocol === \"http:\") {\n u.protocol = \"ws:\";\n }\n return u.toString();\n}\n\n// ── ttyd wire protocol ───────────────────────────────────────────────────────\n// ttyd frames are a single ASCII command char + payload. These mirror ttyd's\n// `protocol.h` Command enum. Client→server and server→client share the byte 0/1/2\n// values but mean different things per direction (see below).\n\n/** ttyd subprotocol — REQUIRED on the WebSocket handshake or ttyd refuses it. */\nexport const TTYD_SUBPROTOCOL = \"tty\";\n\n/** Client→server command bytes (the first char of each outbound text frame). */\nexport const TtydClientCommand = {\n /** stdin: \"0\" + raw input bytes. */\n INPUT: \"0\",\n /** window resize: \"1\" + JSON.stringify({ columns, rows }). */\n RESIZE: \"1\",\n /** flow-control pause (back-pressure): \"2\". */\n PAUSE: \"2\",\n /** flow-control resume: \"3\". */\n RESUME: \"3\",\n} as const;\n\n/** Server→client command bytes (the first char of each inbound frame). */\nexport const TtydServerCommand = {\n /** stdout/stderr: \"0\" + raw output bytes (write the rest into xterm). */\n OUTPUT: \"0\",\n /** set the window title: \"1\" + title string. */\n SET_WINDOW_TITLE: \"1\",\n /** ttyd client preferences JSON: \"2\" + json (ignored by us). */\n SET_PREFERENCES: \"2\",\n} as const;\n\n/**\n * The ttyd handshake's first frame: an auth message. ttyd expects\n * `JSON.stringify({ AuthToken })` as the FIRST text frame on the socket. We send\n * an empty token — our gate is the tunnel URL + scoped stream token, NOT a ttyd\n * `-c` basic-auth credential (which the box does not set in v1). Optional ttyd\n * `columns`/`rows` can ride this frame to seed the PTY size before the first\n * resize. Pure (string-building only) so it stays unit-testable in the SDK.\n */\nexport function ttydAuthFrame(opts?: { columns?: number; rows?: number }): string {\n const frame: { AuthToken: string; columns?: number; rows?: number } = { AuthToken: \"\" };\n if (opts?.columns && opts.columns > 0) frame.columns = opts.columns;\n if (opts?.rows && opts.rows > 0) frame.rows = opts.rows;\n return JSON.stringify(frame);\n}\n\n/** Build a client→server INPUT (stdin) frame: \"0\" + data. */\nexport function ttydInputFrame(data: string): string {\n return TtydClientCommand.INPUT + data;\n}\n\n/** Build a client→server RESIZE frame: \"1\" + JSON.stringify({ columns, rows }). */\nexport function ttydResizeFrame(columns: number, rows: number): string {\n return TtydClientCommand.RESIZE + JSON.stringify({ columns, rows });\n}\n","export const WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS = 262_144;\n\nexport type WorkspaceInstructionPolicyKind = \"charter\" | \"policy\";\nexport type WorkspaceInstructionPolicyScope = \"global\" | \"role\";\nexport type WorkspaceInstructionPolicyProvenanceSource =\n | \"human\"\n | \"onboarding\"\n | \"knowledge_proposal\"\n | \"legacy_import\";\nexport type WorkspaceInstructionPolicyDraftProvenanceSource = Exclude<\n WorkspaceInstructionPolicyProvenanceSource,\n \"legacy_import\"\n>;\nexport type WorkspaceInstructionPolicyActivationType = \"activate\" | \"rollback\";\n\nexport function normalizeWorkspaceInstructionPolicyRoleKey(value: string): string {\n return value.normalize(\"NFKC\").trim().toLowerCase().replace(/\\s+/gu, \"-\").replace(/-+/g, \"-\");\n}\n\nexport type WorkspaceInstructionPolicyTarget = {\n kind: WorkspaceInstructionPolicyKind;\n scope: WorkspaceInstructionPolicyScope;\n roleKey: string | null;\n};\n\nexport type WorkspaceInstructionPolicyRevisionIdentity = {\n id: string;\n revision: number;\n contentHash: string;\n};\n\nexport type WorkspaceInstructionPolicyRevision = WorkspaceInstructionPolicyRevisionIdentity &\n WorkspaceInstructionPolicyTarget & {\n operationId: string;\n accountId: string;\n workspaceId: string;\n content: string;\n provenance: {\n source: WorkspaceInstructionPolicyProvenanceSource;\n sourceId: string | null;\n };\n supersedesRevisionId: string | null;\n createdBySubjectId: string;\n createdAt: string;\n };\n\nexport type WorkspaceInstructionPolicyHead = WorkspaceInstructionPolicyTarget & {\n workspaceId: string;\n revisionId: string;\n revision: number;\n contentHash: string;\n activationVersion: number;\n activatedAt: string;\n};\n\nexport type WorkspaceInstructionPolicyActivationEvent = WorkspaceInstructionPolicyTarget & {\n id: string;\n operationId: string;\n accountId: string;\n workspaceId: string;\n type: WorkspaceInstructionPolicyActivationType;\n activationVersion: number;\n oldRevision: WorkspaceInstructionPolicyRevisionIdentity | null;\n newRevision: WorkspaceInstructionPolicyRevisionIdentity;\n actorSubjectId: string;\n reason: string;\n createdAt: string;\n};\n\nexport type CreateWorkspaceInstructionPolicyDraftRequest = WorkspaceInstructionPolicyTarget & {\n operationId?: string;\n content: string;\n provenanceSource?: WorkspaceInstructionPolicyDraftProvenanceSource;\n provenanceSourceId?: string | null;\n supersedesRevisionId?: string | null;\n};\n\nexport type ImportLegacyWorkspaceInstructionPolicyDraftRequest = {\n operationId?: string;\n supersedesRevisionId?: string | null;\n};\n\nexport type WorkspaceInstructionPolicyListOptions = {\n kind?: WorkspaceInstructionPolicyKind;\n scope?: WorkspaceInstructionPolicyScope;\n roleKey?: string;\n afterRevision?: number;\n limit?: number;\n};\n\nexport type WorkspaceInstructionPolicyListResponse = {\n revisions: WorkspaceInstructionPolicyRevision[];\n activeHeads: WorkspaceInstructionPolicyHead[];\n activationEvents: WorkspaceInstructionPolicyActivationEvent[];\n nextAfterRevision: number | null;\n};\n\nexport type WorkspaceInstructionPolicyDiffRequest = {\n fromRevisionId: string;\n toRevisionId: string;\n};\n\nexport type WorkspaceInstructionPolicyDiffResponse = {\n from: WorkspaceInstructionPolicyRevision;\n to: WorkspaceInstructionPolicyRevision;\n format: \"unified\";\n diff: string;\n};\n\nexport type ActivateWorkspaceInstructionPolicyRequest = {\n operationId?: string;\n expectedCurrentRevisionId: string | null;\n expectedActivationVersion?: number;\n reason: string;\n};\n\nexport type RollbackWorkspaceInstructionPolicyRequest = {\n operationId?: string;\n targetRevisionId: string;\n expectedCurrentRevisionId: string;\n expectedActivationVersion?: number;\n reason: string;\n};\n\nexport type WorkspaceInstructionPolicyActivationResponse = {\n head: WorkspaceInstructionPolicyHead;\n event: WorkspaceInstructionPolicyActivationEvent;\n};\n\nexport type WorkspaceInstructionPolicyConflictResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_CONFLICT\";\n message: string;\n currentHead: WorkspaceInstructionPolicyHead | null;\n};\n\nexport type WorkspaceInstructionPolicyOperationReuseResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_OPERATION_REUSED\";\n message: string;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalSource = {\n id: string;\n version: string;\n confidenceBps: number;\n};\n\nexport type CreateWorkspaceInstructionPolicyOnboardingProposalRequest =\n WorkspaceInstructionPolicyTarget & {\n operationId?: string;\n content: string;\n sourceId: string;\n sourceVersion: string;\n confidenceBps: number;\n expectedCurrentRevisionId: string | null;\n expectedActivationVersion: number;\n };\n\nexport type WorkspaceInstructionPolicyOnboardingProposal = WorkspaceInstructionPolicyTarget & {\n id: string;\n operationId: string;\n accountId: string;\n workspaceId: string;\n source: WorkspaceInstructionPolicyOnboardingProposalSource;\n baseline: WorkspaceInstructionPolicyHead | null;\n draft: WorkspaceInstructionPolicyRevision;\n status: \"proposed\";\n createdBySubjectId: string;\n createdAt: string;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalListOptions = {\n limit?: number;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalListResponse = {\n proposals: WorkspaceInstructionPolicyOnboardingProposal[];\n truncated: boolean;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse = {\n code:\n | \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_EMPTY\"\n | \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_OVERSIZED\";\n message: string;\n maxChars: number;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalStaleResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_STALE\";\n message: string;\n currentHead: WorkspaceInstructionPolicyHead | null;\n};\n\nexport type WorkspaceInstructionPolicyOnboardingProposalConflictResponse = {\n code: \"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_CONFLICT\";\n message: string;\n existingProposalId: string;\n existingDraftRevisionId: string;\n};\n","export const COMPANY_PROFILE_SCALAR_MAX_CHARS = 2_048;\nexport const COMPANY_PROFILE_ENTRY_MAX_CHARS = 1_024;\nexport const COMPANY_PROFILE_ENTRY_MAX_COUNT = 16;\n\nexport type CompanyProfileEntry = { key: string; content: string };\nexport type CompanyProfileContent = {\n identity: string | null;\n mission: string | null;\n products: CompanyProfileEntry[];\n customers: CompanyProfileEntry[];\n goals: CompanyProfileEntry[];\n constraints: CompanyProfileEntry[];\n};\nexport type CompanyProfileRevisionIdentity = {\n id: string;\n revision: number;\n contentHash: string;\n};\nexport type CompanyProfileRevision = CompanyProfileRevisionIdentity & {\n operationId: string;\n accountId: string;\n intent: \"active\" | \"proposal\";\n profile: CompanyProfileContent;\n provenance: { source: \"human\" | \"durable_learning\" | \"migration\"; sourceId: string | null };\n supersedesRevisionId: string | null;\n createdBySubjectId: string;\n createdAt: string;\n};\nexport type CompanyProfileHead = {\n accountId: string;\n revisionId: string;\n revision: number;\n contentHash: string;\n activationVersion: number;\n activatedAt: string;\n};\nexport type CompanyProfileActivationEvent = {\n id: string;\n operationId: string;\n accountId: string;\n type: \"activate\" | \"rollback\";\n activationVersion: number;\n oldRevision: CompanyProfileRevisionIdentity | null;\n newRevision: CompanyProfileRevisionIdentity | null;\n actorSubjectId: string;\n reason: string;\n createdAt: string;\n};\nexport type CompanyProfileListOptions = { afterRevision?: number; limit?: number };\nexport type CompanyProfileListResponse = {\n current: CompanyProfileHead | null;\n activeRevision: CompanyProfileRevision | null;\n revisions: CompanyProfileRevision[];\n activationEvents: CompanyProfileActivationEvent[];\n nextAfterRevision: number | null;\n};\nexport type UpdateCompanyProfileRequest = {\n operationId?: string;\n profile: CompanyProfileContent;\n expectedCurrentRevisionId: string | null;\n expectedActivationVersion: number;\n reason: string;\n};\nexport type ActivateCompanyProfileRevisionRequest = {\n operationId?: string;\n expectedCurrentRevisionId: string | null;\n expectedActivationVersion: number;\n reason: string;\n};\nexport type RollbackCompanyProfileRequest = {\n operationId?: string;\n targetRevisionId: string;\n expectedCurrentRevisionId: string;\n expectedActivationVersion: number;\n reason: string;\n};\nexport type CompanyProfileMutationResponse = {\n revision: CompanyProfileRevision | null;\n head: CompanyProfileHead | null;\n event: CompanyProfileActivationEvent | null;\n};\nexport type CompanyProfileDiffRequest = { fromRevisionId: string; toRevisionId: string };\nexport type CompanyProfileDiffResponse = {\n from: CompanyProfileRevision;\n to: CompanyProfileRevision;\n format: \"unified_json\";\n diff: string;\n};\n\nexport function normalizeCompanyProfileStableKey(value: string): string {\n return value.normalize(\"NFKC\").trim().toLowerCase().replace(/\\s+/gu, \"-\").replace(/-+/g, \"-\");\n}\n","export type PreferenceRegistryScope = \"organization\" | \"workspace\" | \"user\";\nexport type PreferenceRegistryStatus =\n | \"proposed\"\n | \"active\"\n | \"inactive\"\n | \"rejected\"\n | \"superseded\"\n | \"expired\";\nexport type PreferenceRegistryProvenanceSource =\n | \"human\"\n | \"onboarding\"\n | \"knowledge_proposal\"\n | \"imported_document\"\n | \"slack\"\n | \"meeting_transcript\"\n | \"call_transcript\";\nexport type PreferenceRegistryTrust =\n | \"untrusted_proposal\"\n | \"personal\"\n | \"workspace_managed\"\n | \"organization_managed\";\nexport type PreferenceRegistryConflictStrategy = \"override\" | \"merge\" | \"reject\" | \"inform\";\n\nexport function normalizePreferenceRegistryStableKey(value: string): string {\n return value.normalize(\"NFKC\").trim().toLowerCase().replace(/\\s+/gu, \"-\").replace(/-+/g, \"-\");\n}\n\nexport type PreferenceRegistryScopeTarget = {\n scope: PreferenceRegistryScope;\n workspaceId: string | null;\n subjectId: string | null;\n};\n\nexport type PreferenceRegistryPrecedence = {\n tier: PreferenceRegistryScope;\n rank: number;\n conflictStrategy: PreferenceRegistryConflictStrategy;\n conflictsWith: string[];\n};\n\nexport type PreferenceRegistryRevisionSummary = {\n id: string;\n preferenceId: string;\n revision: number;\n contentHash: string;\n title: string;\n description: string;\n precedence: PreferenceRegistryPrecedence;\n provenance: {\n source: PreferenceRegistryProvenanceSource;\n sourceId: string | null;\n trust: PreferenceRegistryTrust;\n };\n expiresAt: string | null;\n correctsRevisionId: string | null;\n createdBySubjectId: string;\n createdAt: string;\n};\n\nexport type PreferenceRegistryDescriptorProvenance = {\n source: PreferenceRegistryProvenanceSource;\n sourceIdHash: string | null;\n trust: PreferenceRegistryTrust;\n};\n\nexport type PreferenceRegistryRecord = {\n id: string;\n accountId: string;\n stableKey: string;\n target: PreferenceRegistryScopeTarget;\n status: PreferenceRegistryStatus;\n scopeVersion: number;\n activationVersion: number;\n activeRevision: PreferenceRegistryRevisionSummary | null;\n supersededByPreferenceId: string | null;\n createdBySubjectId: string;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type PreferenceRegistryEvent = {\n id: string;\n accountId: string;\n preferenceId: string;\n type:\n | \"proposal_created\"\n | \"activated\"\n | \"corrected\"\n | \"rejected\"\n | \"deactivated\"\n | \"superseded\"\n | \"scope_changed\";\n version: number;\n oldRevisionId: string | null;\n newRevisionId: string | null;\n oldTarget: PreferenceRegistryScopeTarget | null;\n newTarget: PreferenceRegistryScopeTarget | null;\n relatedPreferenceId: string | null;\n actorSubjectId: string;\n reason: string;\n createdAt: string;\n};\n\nexport type PreferenceRegistryDescriptor = {\n id: string;\n stableKey: string;\n title: string;\n description: string;\n scope: PreferenceRegistryScope;\n activeVersion: number;\n revisionId: string;\n contentHash: string;\n precedence: PreferenceRegistryPrecedence;\n provenance: PreferenceRegistryDescriptorProvenance;\n expiresAt: string | null;\n retrievalHandle: string;\n};\n\nexport type PreferenceRegistrySnapshot = {\n id: string;\n workspaceId: string;\n sessionId: string;\n turnId: string;\n attemptId: string;\n executionGeneration: number;\n initiatingHumanSubjectId: string;\n descriptorHash: string;\n descriptors: PreferenceRegistryDescriptor[];\n truncated: boolean;\n createdAt: string;\n};\n\nexport type PreferenceRegistryFullContent = {\n descriptor: PreferenceRegistryDescriptor;\n content: string;\n};\n\nexport type CreatePreferenceRegistryProposalRequest = {\n stableKey: string;\n scope: PreferenceRegistryScope;\n title: string;\n description: string;\n content: string;\n precedenceRank?: number;\n conflictStrategy?: PreferenceRegistryConflictStrategy;\n conflictsWith?: string[];\n expiresAt?: string | null;\n provenanceSource?: PreferenceRegistryProvenanceSource;\n provenanceSourceId?: string | null;\n};\n\nexport type ActivatePreferenceRegistryRevisionRequest = {\n revisionId: string;\n expectedCurrentRevisionId: string | null;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type CorrectPreferenceRegistryRequest = {\n expectedCurrentRevisionId: string;\n expectedScopeVersion: number;\n title: string;\n description: string;\n content: string;\n precedenceRank?: number;\n conflictStrategy?: PreferenceRegistryConflictStrategy;\n conflictsWith?: string[];\n expiresAt?: string | null;\n reason: string;\n};\n\nexport type DeactivatePreferenceRegistryRequest = {\n expectedCurrentRevisionId: string;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type ChangePreferenceRegistryScopeRequest = {\n scope: PreferenceRegistryScope;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type SupersedePreferenceRegistryRequest = {\n replacementPreferenceId: string;\n expectedCurrentRevisionId: string;\n expectedScopeVersion: number;\n reason: string;\n};\n\nexport type RejectPreferenceRegistryProposalRequest = {\n revisionId: string;\n expectedScopeVersion: number;\n reason: string;\n};\nexport type PreferenceRegistryListOptions = {\n scope?: PreferenceRegistryScope;\n status?: PreferenceRegistryStatus;\n limit?: number;\n};\nexport type PreferenceRegistryListResponse = { preferences: PreferenceRegistryRecord[] };\nexport type PreferenceRegistryDetailResponse = {\n preference: PreferenceRegistryRecord;\n revisions: PreferenceRegistryRevisionSummary[];\n events: PreferenceRegistryEvent[];\n};\nexport type PreferenceRegistryMutationResponse = {\n preference: PreferenceRegistryRecord;\n event: PreferenceRegistryEvent;\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,11 @@
1
+ import type { WorkspaceInteractionRevisionEvent } from "./interaction.js";
2
+ import { type StreamSessionEventsOptions } from "./stream.js";
3
+ export type WorkspaceInteractionRevisionStreamTransport = {
4
+ openStream: (after: number, signal: AbortSignal | undefined) => Promise<ReadableStream<Uint8Array>>;
5
+ };
6
+ /**
7
+ * Reconnecting latest-revision stream. Revisions may skip because intermediate
8
+ * invalidations carry no independent evidence; every delivered value means
9
+ * "refetch any interaction resources older than this cursor".
10
+ */
11
+ export declare function streamWorkspaceInteractionRevisions(transport: WorkspaceInteractionRevisionStreamTransport, options?: StreamSessionEventsOptions): AsyncGenerator<WorkspaceInteractionRevisionEvent, void, void>;