@opengeni/sdk 4.0.2 → 5.0.3-canary.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.
- package/README.md +58 -9
- package/dist/artifact-client.d.ts +18 -8
- package/dist/artifacts.js +4 -4
- package/dist/browser.js +2 -2
- package/dist/chat/ids.d.ts +3 -3
- package/dist/chat/index.js +38 -51
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/opengeni.d.ts +10 -12
- package/dist/chat/types.d.ts +7 -3
- package/dist/{chunk-O23OOWJK.js → chunk-4YAL54F3.js} +2 -2
- package/dist/{chunk-UW22XVCT.js → chunk-ARGX7UY4.js} +97 -2
- package/dist/chunk-ARGX7UY4.js.map +1 -0
- package/dist/chunk-J5USCWPE.js +195 -0
- package/dist/chunk-J5USCWPE.js.map +1 -0
- package/dist/{chunk-WNEGCYCE.js → chunk-TARU5CD2.js} +1 -1
- package/dist/chunk-TARU5CD2.js.map +1 -0
- package/dist/{chunk-3IZMCD2K.js → chunk-TOB3B4ZJ.js} +28 -41
- package/dist/chunk-TOB3B4ZJ.js.map +1 -0
- package/dist/{chunk-2H7P45YQ.js → chunk-UQGHX4DI.js} +173 -7
- package/dist/chunk-UQGHX4DI.js.map +1 -0
- package/dist/client.d.ts +39 -4
- package/dist/core.js +3 -3
- package/dist/document-authority.js +3 -3
- package/dist/editable-artifacts.js +1 -1
- package/dist/embedding-client.d.ts +72 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +13 -8
- package/dist/index.js.map +1 -1
- package/dist/site-tool-bridge.d.ts +39 -0
- package/dist/site.d.ts +2 -0
- package/dist/site.js +7 -3
- package/dist/types.d.ts +23 -12
- package/package.json +3 -2
- package/src/artifact-client.ts +38 -63
- package/src/chat/ids.ts +3 -3
- package/src/chat/opengeni.ts +41 -57
- package/src/chat/types.ts +7 -3
- package/src/client.ts +253 -12
- package/src/embedding-client.ts +308 -0
- package/src/index.ts +16 -1
- package/src/site-tool-bridge.ts +141 -0
- package/src/site.ts +7 -0
- package/src/types.ts +18 -6
- package/dist/chunk-2H7P45YQ.js.map +0 -1
- package/dist/chunk-3IZMCD2K.js.map +0 -1
- package/dist/chunk-UW22XVCT.js.map +0 -1
- package/dist/chunk-WNEGCYCE.js.map +0 -1
- /package/dist/{chunk-O23OOWJK.js.map → chunk-4YAL54F3.js.map} +0 -0
package/dist/chat/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/chat/types.ts","../../src/chat/fold.ts","../../src/chat/ids.ts","../../src/chat/opengeni.ts","../../src/chat/http.ts","../../src/chat/openai.ts","../../src/chat/vercel.ts","../../src/chat/handler.ts"],"sourcesContent":["import type { FetchLike } from \"../client\";\nimport type {\n CreateSessionRequest,\n HumanInputAnswer,\n SessionEvent,\n Session,\n SessionSkill,\n ToolRef,\n} from \"../types\";\n\n/** Which other sessions the agent may reach from this one. */\nexport type ChatAgentAccess = \"session\" | \"user\" | \"workspace\";\n\n/**\n * Memory scope for the session: which memories the agent reads and where it\n * saves. `false` disables Memory tools. Omitted follows `agentAccess`.\n */\nexport type ChatMemory = \"session\" | \"user\" | \"workspace\" | false;\n\nexport type OpenGeniOptions = {\n /** Organization API key. Keep it on the server. */\n apiKey: string;\n /** The organization (account) id that owns every tenant workspace. */\n organizationId: string;\n /** Defaults to `https://app.opengeni.ai`. */\n baseUrl?: string | undefined;\n /**\n * The product identity used as the external-source label for tenant\n * workspaces and end users. Defaults to `\"app\"`.\n */\n source?: string | undefined;\n fetch?: FetchLike | undefined;\n /** Display name for a tenant workspace created on first use. Defaults to the tenant id. */\n workspaceName?: ((tenant: string) => string) | undefined;\n};\n\nexport type ChatTarget =\n | { tenant: string; workspaceId?: undefined }\n | { workspaceId: string; tenant?: undefined };\n\nexport type ChatOptions = ChatTarget & {\n /** Opaque end-user label inside the tenant. Required for `memory: \"user\"`. */\n user?: string | undefined;\n /** Stable conversation id; the session id is derived from it deterministically. */\n conversation: string;\n /** Defaults to `\"session\"`: the agent sees only this conversation. */\n agentAccess?: ChatAgentAccess | undefined;\n memory?: ChatMemory | undefined;\n model?: string | undefined;\n instructions?: string | undefined;\n skills?: SessionSkill[] | undefined;\n tools?: ToolRef[] | undefined;\n /**\n * Raw create-request passthrough (for example `sandboxBackend: \"none\"` for a\n * pure chat). Explicit values win over facade-derived ones; the message and\n * identity/idempotency fields always come from the facade.\n */\n create?: Partial<CreateSessionRequest> | undefined;\n};\n\n/** A turn stopped to wait for a human decision. */\nexport type ChatPending = {\n kind: \"approval\" | \"human_input\";\n /** The id to pass back through `chat.respond`. */\n requestId: string;\n /** Tool name for an approval; null for structured human input. */\n name: string | null;\n /** The producer's exact payload (approval entry or human-input request). */\n payload: unknown;\n};\n\nexport type ChatReplyStatus = \"completed\" | \"pending\" | \"cancelled\";\n\nexport type ChatReply = {\n text: string;\n sessionId: string;\n workspaceId: string;\n turnId: string | null;\n /** `pending` waits on `chat.respond`; `cancelled` carries the text produced before the cancel. */\n status: ChatReplyStatus;\n /** Set when the turn is waiting on `chat.respond` instead of finished. */\n pending: ChatPending | null;\n /** Every event consumed while folding this turn. */\n events: SessionEvent[];\n toString(): string;\n};\n\nexport type ChatToolStatus = \"started\" | \"completed\" | \"failed\";\n\nexport type ChatChunk =\n | { type: \"text\"; text: string }\n | {\n type: \"tool\";\n name: string;\n status: ChatToolStatus;\n callId?: string | undefined;\n input?: unknown;\n }\n | { type: \"pending\"; pending: ChatPending }\n | { type: \"done\"; reply: ChatReply };\n\nexport type ChatMessage = {\n role: \"user\" | \"assistant\";\n text: string;\n sequence: number;\n};\n\n/** Durable text and unresolved decisions restored when a chat is reopened. */\nexport type ChatSnapshot = {\n messages: ChatMessage[];\n pending: ChatPending[];\n status: Session[\"status\"] | null;\n};\n\nexport type ChatRespondInput =\n | { requestId: string; decision: \"approve\" | \"reject\"; message?: string | undefined }\n | { requestId: string; answers: HumanInputAnswer[] }\n | { requestId: string; skip: true };\n\n/** One earlier message from the product's own history, imported as context on the first send. */\nexport type ChatImportedMessage = { role: \"user\" | \"assistant\" | \"system\"; text: string };\n\nexport type ChatSendOptions = {\n signal?: AbortSignal | undefined;\n /** Supersede the current inference instead of queueing behind it. */\n steer?: boolean | undefined;\n /**\n * Earlier messages the product already holds, oldest first. Used only when\n * this send creates the session: they become the first message's\n * `modelContext` (skipped when `create.modelContext` was supplied), trimmed\n * from the oldest end to 30,000 characters. Never resent on later turns:\n * after the first message OpenGeni owns the history.\n */\n importedHistory?: ChatImportedMessage[] | undefined;\n};\n\nexport type ChatSessionListOptions = ChatTarget & {\n user?: string | undefined;\n limit?: number | undefined;\n};\n\n/** A turn ended without a usable reply, or the facade was misused. */\nexport class OpenGeniChatError extends Error {\n readonly code: string;\n readonly event: SessionEvent | null;\n\n constructor(code: string, message: string, event: SessionEvent | null = null) {\n super(message);\n this.name = \"OpenGeniChatError\";\n this.code = code;\n this.event = event;\n }\n}\n","import type { SessionEvent } from \"../types\";\nimport { OpenGeniChatError, type ChatChunk, type ChatPending, type ChatReply } from \"./types\";\n\n/**\n * Event folding shared by `send`, `stream`, and every protocol adapter.\n *\n * One fold covers one logical turn: text deltas accumulate into message\n * segments (a tool call closes the current segment, the completed event\n * reconciles it), tool call/output pairs become tool chunks, and the turn\n * settles on a terminal event or a human wait. Events that carry a different\n * turn id than the expected one are ignored so a queued follow-up never ends\n * early on the previous turn's settlement.\n */\n\nexport type ChatTurnTerminal = \"completed\" | \"failed\" | \"cancelled\" | \"pending\";\n\nexport type ChatFoldStep = {\n chunks: ChatChunk[];\n terminal: ChatTurnTerminal | null;\n};\n\n/** Incremental replay of unresolved requests, without retaining the event log. */\nexport class ChatPendingFold {\n private readonly requests = new Map<string, { pending: ChatPending; turnId: string | null }>();\n\n push(event: SessionEvent): void {\n const payload = asRecord(event.payload);\n if (event.type === \"session.requiresAction\") {\n for (const [key, request] of this.requests) {\n if (request.pending.kind === \"approval\") this.requests.delete(key);\n }\n for (const approval of Array.isArray(payload.approvals) ? payload.approvals : []) {\n const pending = approvalPending({ approvals: [approval] });\n if (pending) this.put(pending, event.turnId ?? null);\n }\n } else if (event.type === \"session.humanInput.requested\") {\n const pending = humanInputPending(payload);\n if (pending) this.put(pending, event.turnId ?? null);\n } else if (event.type === \"user.approvalDecision\") {\n this.requests.delete(`approval:${payload.approvalId}`);\n } else if (event.type === \"user.humanInputResponse\") {\n this.requests.delete(`human_input:${payload.requestId}`);\n } else if ([\"turn.completed\", \"turn.failed\", \"turn.cancelled\"].includes(event.type)) {\n for (const [key, request] of this.requests) {\n if (request.turnId === null || event.turnId == null || request.turnId === event.turnId) {\n this.requests.delete(key);\n }\n }\n }\n }\n\n pending(now = Date.now()): ChatPending[] {\n return [...this.requests.values()]\n .map((request) => request.pending)\n .filter((pending) => {\n if (pending.kind !== \"human_input\") return true;\n const expiresAt = asRecord(pending.payload).expiresAt;\n return expiresAt == null || (typeof expiresAt === \"string\" && Date.parse(expiresAt) > now);\n });\n }\n\n private put(pending: ChatPending, turnId: string | null): void {\n this.requests.set(`${pending.kind}:${pending.requestId}`, { pending, turnId });\n }\n}\n\ntype Segment = { text: string; open: boolean };\n\nexport class ChatTurnFold {\n readonly events: SessionEvent[] = [];\n turnId: string | null;\n pending: ChatPending | null = null;\n failure: SessionEvent | null = null;\n private readonly segments: Segment[] = [];\n private readonly openTools = new Map<string, string>();\n\n constructor(\n private readonly workspaceId: string,\n private readonly sessionId: string,\n expectedTurnId: string | null,\n ) {\n this.turnId = expectedTurnId;\n }\n\n get text(): string {\n return this.segments\n .map((segment) => segment.text)\n .filter((text) => text.length > 0)\n .join(\"\\n\\n\");\n }\n\n push(event: SessionEvent): ChatFoldStep {\n const eventTurnId = typeof event.turnId === \"string\" ? event.turnId : null;\n if (this.turnId && eventTurnId && eventTurnId !== this.turnId) {\n return { chunks: [], terminal: null };\n }\n if (!this.turnId && eventTurnId && isTurnScopedType(event.type)) {\n this.turnId = eventTurnId;\n }\n this.events.push(event);\n const payload = asRecord(event.payload);\n switch (event.type) {\n case \"agent.message.delta\": {\n const text = stringValue(payload.text);\n if (!text) return { chunks: [], terminal: null };\n const open = this.segments.at(-1);\n if (open?.open) {\n open.text += text;\n } else {\n return { chunks: [this.startSegment(text, true)], terminal: null };\n }\n return { chunks: [{ type: \"text\", text }], terminal: null };\n }\n case \"agent.message.completed\": {\n const text = stringValue(payload.text) ?? \"\";\n const target = this.segments.at(-1);\n if (!target || (!target.open && target.text && !text.startsWith(target.text))) {\n if (!text) return { chunks: [], terminal: null };\n return { chunks: [this.startSegment(text, false)], terminal: null };\n }\n target.open = false;\n if (text.length > target.text.length && text.startsWith(target.text)) {\n const remainder = text.slice(target.text.length);\n target.text = text;\n return { chunks: [{ type: \"text\", text: remainder }], terminal: null };\n }\n if (!target.text && text) {\n target.text = text;\n return { chunks: [{ type: \"text\", text }], terminal: null };\n }\n return { chunks: [], terminal: null };\n }\n case \"agent.toolCall.created\": {\n this.closeSegment();\n const name = stringValue(payload.name) ?? \"tool\";\n const callId = stringValue(payload.id);\n if (callId) this.openTools.set(callId, name);\n return {\n chunks: [\n {\n type: \"tool\",\n name,\n status: \"started\",\n ...(callId ? { callId } : {}),\n ...(\"arguments\" in payload ? { input: payload.arguments } : {}),\n },\n ],\n terminal: null,\n };\n }\n case \"agent.toolCall.output\": {\n const callId = stringValue(payload.id);\n const name = (callId ? this.openTools.get(callId) : undefined) ?? \"tool\";\n if (callId) this.openTools.delete(callId);\n return {\n chunks: [\n {\n type: \"tool\",\n name,\n status: isErrorOutput(payload) ? \"failed\" : \"completed\",\n ...(callId ? { callId } : {}),\n },\n ],\n terminal: null,\n };\n }\n case \"session.requiresAction\": {\n const pending = approvalPending(payload);\n if (!pending) return { chunks: [], terminal: null };\n this.closeSegment();\n this.pending = pending;\n return { chunks: [{ type: \"pending\", pending }], terminal: \"pending\" };\n }\n case \"session.humanInput.requested\": {\n const pending = humanInputPending(payload);\n if (!pending) return { chunks: [], terminal: null };\n this.closeSegment();\n this.pending = pending;\n return { chunks: [{ type: \"pending\", pending }], terminal: \"pending\" };\n }\n case \"turn.completed\":\n this.closeSegment();\n return { chunks: [], terminal: \"completed\" };\n case \"turn.failed\":\n this.closeSegment();\n this.failure = event;\n return { chunks: [], terminal: \"failed\" };\n case \"turn.cancelled\":\n this.closeSegment();\n return { chunks: [], terminal: \"cancelled\" };\n default:\n return { chunks: [], terminal: null };\n }\n }\n\n reply(terminal: ChatTurnTerminal): ChatReply {\n const text = this.text;\n return {\n text,\n sessionId: this.sessionId,\n workspaceId: this.workspaceId,\n turnId: this.turnId,\n status:\n terminal === \"pending\" ? \"pending\" : terminal === \"cancelled\" ? \"cancelled\" : \"completed\",\n pending: this.pending,\n events: [...this.events],\n toString: () => text,\n };\n }\n\n /** The error to throw for a `turn.failed` settlement. */\n failureError(): OpenGeniChatError {\n const payload = asRecord(this.failure?.payload);\n const code = stringValue(payload.code) ?? \"turn_failed\";\n const message =\n stringValue(payload.error) ?? stringValue(payload.message) ?? \"The turn failed.\";\n return new OpenGeniChatError(code, message, this.failure);\n }\n\n private closeSegment(): void {\n const open = this.segments.at(-1);\n if (open) open.open = false;\n }\n\n private startSegment(text: string, open: boolean): ChatChunk {\n // Match the separator used by `text` before exposing the next segment to\n // append-only consumers (React and both protocol adapters).\n const separator = this.segments.length > 0 ? \"\\n\\n\" : \"\";\n this.segments.push({ text, open });\n return { type: \"text\", text: separator + text };\n }\n}\n\nfunction isTurnScopedType(type: string): boolean {\n return type.startsWith(\"turn.\") || type.startsWith(\"agent.\") || type === \"user.message\";\n}\n\nexport function approvalPending(payload: Record<string, unknown>): ChatPending | null {\n const approvals = Array.isArray(payload.approvals) ? payload.approvals : [];\n const first = approvals[0];\n if (!first) return null;\n const raw = asRecord(first);\n const rawItem = asRecord(raw.rawItem);\n const requestId =\n stringValue(rawItem.callId) ??\n stringValue(rawItem.id) ??\n stringValue(raw.id) ??\n stringValue(raw.callId);\n if (!requestId) return null;\n return {\n kind: \"approval\",\n requestId,\n name: stringValue(raw.name) ?? stringValue(raw.toolName) ?? stringValue(rawItem.name) ?? null,\n payload: first,\n };\n}\n\nexport function humanInputPending(payload: Record<string, unknown>): ChatPending | null {\n const request = asRecord(payload.request);\n const requestId = stringValue(request.id);\n if (!requestId || !Array.isArray(request.questions)) return null;\n return { kind: \"human_input\", requestId, name: null, payload: payload.request };\n}\n\nexport function asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nexport function stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction isErrorOutput(payload: Record<string, unknown>): boolean {\n if (payload.error === true || payload.failed === true) return true;\n const output = payload.output;\n return (\n !!output && typeof output === \"object\" && (output as { isError?: unknown }).isError === true\n );\n}\n","/**\n * Deterministic chat identities. A conversation id maps to exactly one\n * session id per workspace, so any process can address the same session\n * without storing a mapping, and a double-submitted create collapses through\n * the idempotency key. With an end-user label the conversation id is\n * namespaced to that user, so one user cannot address another user's\n * conversation by guessing its id.\n */\n\n/** The end-user label a conversation is namespaced to: the product `source` plus the opaque user id. */\nexport type ChatUserLabel = { source: string; id: string };\n\n/** Fixed RFC 4122 namespace for chat session ids. Never change it. */\nexport const CHAT_SESSION_NAMESPACE = \"7c1e6d3a-5b2f-4e8a-9d4c-0f3b6a8e2c17\";\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/** RFC 4122 version 5 (SHA-1) UUID of `name` inside `namespace`. */\nexport async function uuidV5(name: string, namespace: string): Promise<string> {\n const namespaceBytes = parseUuid(namespace);\n const nameBytes = new TextEncoder().encode(name);\n const input = new Uint8Array(namespaceBytes.length + nameBytes.length);\n input.set(namespaceBytes, 0);\n input.set(nameBytes, namespaceBytes.length);\n const digest = new Uint8Array(await crypto.subtle.digest(\"SHA-1\", input)).slice(0, 16);\n digest[6] = ((digest[6] ?? 0) & 0x0f) | 0x50;\n digest[8] = ((digest[8] ?? 0) & 0x3f) | 0x80;\n return formatUuid(digest);\n}\n\n/**\n * The session id of `conversation` in `workspaceId`: RFC 4122 v5 of the JSON\n * tuple `[workspaceId, conversation]`, or `[workspaceId, source, id, conversation]`\n * when the conversation belongs to an end user. JSON encoding keeps the tuple\n * unambiguous: an id containing `:` or any other delimiter can never make two\n * different (user, conversation) pairs share a session.\n */\nexport async function chatSessionId(\n workspaceId: string,\n conversation: string,\n user?: ChatUserLabel | undefined,\n): Promise<string> {\n return await uuidV5(chatIdentityName(workspaceId, conversation, user), CHAT_SESSION_NAMESPACE);\n}\n\n/** The exact v5 name behind {@link chatSessionId}; exported for tests and audits. */\nexport function chatIdentityName(\n workspaceId: string,\n conversation: string,\n user?: ChatUserLabel | undefined,\n): string {\n return JSON.stringify(\n user ? [workspaceId, user.source, user.id, conversation] : [workspaceId, conversation],\n );\n}\n\n/**\n * The create idempotency key for a chat session: `chat:<sessionId>`. The\n * session id already encodes the workspace, user label, and conversation as an\n * unambiguous tuple, so the key inherits that and stays bounded.\n */\nexport function chatIdempotencyKey(sessionId: string): string {\n return `chat:${sessionId}`;\n}\n\nexport function isUuid(value: string): boolean {\n return UUID_PATTERN.test(value);\n}\n\nfunction parseUuid(value: string): Uint8Array {\n if (!UUID_PATTERN.test(value)) {\n throw new TypeError(`Invalid UUID namespace: ${value}`);\n }\n const hex = value.replace(/-/g, \"\");\n const bytes = new Uint8Array(16);\n for (let index = 0; index < 16; index += 1) {\n bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);\n }\n return bytes;\n}\n\nfunction formatUuid(bytes: Uint8Array): string {\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\n}\n","import { OpenGeniClient } from \"../client\";\nimport { OpenGeniApiError } from \"../errors\";\nimport type { CreateSessionRequest, Session, SessionEvent } from \"../types\";\nimport { ChatPendingFold, ChatTurnFold, asRecord, stringValue } from \"./fold\";\nimport { chatIdempotencyKey, chatSessionId } from \"./ids\";\nimport {\n OpenGeniChatError,\n type ChatChunk,\n type ChatImportedMessage,\n type ChatMessage,\n type ChatOptions,\n type ChatReply,\n type ChatRespondInput,\n type ChatSendOptions,\n type ChatSessionListOptions,\n type ChatSnapshot,\n type ChatTarget,\n type OpenGeniOptions,\n} from \"./types\";\n\nexport const DEFAULT_OPENGENI_BASE_URL = \"https://app.opengeni.ai\";\nexport const DEFAULT_CHAT_SOURCE = \"app\";\n\ntype SubmittedTurn = { after: number; turnId: string | null };\n\ntype BuildCreate = (\n text: string,\n importedHistory: ChatImportedMessage[] | undefined,\n) => CreateSessionRequest;\n\ntype ChatInit = {\n workspaceId: string;\n sessionId: string;\n conversation: string | null;\n session: Session | null;\n buildCreate: BuildCreate | null;\n};\n\n/** Upper bound on the `modelContext` built from `importedHistory`, header included. */\nexport const IMPORTED_HISTORY_MAX_CHARS = 30_000;\nconst IMPORTED_HISTORY_HEADER = \"Earlier conversation imported from the product, oldest first:\";\nconst IMPORTED_HISTORY_ROLES: ReadonlySet<string> = new Set([\"user\", \"assistant\", \"system\"]);\n\n/**\n * One-option-object entry point for products that already have a chat. Wraps\n * `OpenGeniClient` (exposed as `client`) with tenant workspaces, deterministic\n * conversation sessions, and text-first replies.\n */\nexport class OpenGeni {\n readonly client: OpenGeniClient;\n readonly organizationId: string;\n readonly source: string;\n readonly sessions: {\n /** Sessions of one tenant workspace, optionally filtered to one end user. */\n list: (options: ChatSessionListOptions) => Promise<Session[]>;\n };\n private readonly workspaceName: ((tenant: string) => string) | undefined;\n private readonly workspaces = new Map<string, Promise<string>>();\n\n constructor(options: OpenGeniOptions) {\n if (!options.apiKey) throw new TypeError(\"OpenGeni requires an apiKey.\");\n if (!options.organizationId) throw new TypeError(\"OpenGeni requires an organizationId.\");\n this.client = new OpenGeniClient({\n baseUrl: options.baseUrl ?? DEFAULT_OPENGENI_BASE_URL,\n apiKey: options.apiKey,\n ...(options.fetch ? { fetch: options.fetch } : {}),\n });\n this.organizationId = options.organizationId;\n this.source = options.source ?? DEFAULT_CHAT_SOURCE;\n this.workspaceName = options.workspaceName;\n this.sessions = { list: (listOptions) => this.listSessions(listOptions) };\n }\n\n /** The workspace id for a tenant (created on first use, cached per instance) or an explicit id. */\n async workspaceId(\n target: ChatTarget | { tenant?: string | undefined; workspaceId?: string | undefined },\n ): Promise<string> {\n if (target.workspaceId) return target.workspaceId;\n const tenant = target.tenant;\n if (!tenant) throw new TypeError(\"Pass either tenant or workspaceId.\");\n let pending = this.workspaces.get(tenant);\n if (!pending) {\n pending = this.client\n .ensureWorkspace({\n accountId: this.organizationId,\n externalSource: this.source,\n externalId: tenant,\n name: this.workspaceName?.(tenant) ?? tenant,\n })\n .then((response) => response.workspace.id);\n pending.catch(() => {\n this.workspaces.delete(tenant);\n });\n this.workspaces.set(tenant, pending);\n }\n return await pending;\n }\n\n /**\n * Address one conversation; the session is created lazily on the first send.\n * With a `user`, the conversation id is namespaced to that user (a different\n * user with the same conversation id reaches a different session).\n */\n async chat(options: ChatOptions): Promise<Chat> {\n if (!options.conversation) throw new TypeError(\"chat() requires a conversation id.\");\n const agentAccess = options.agentAccess ?? \"session\";\n const memoryScope =\n options.memory === false\n ? \"off\"\n : options.memory === undefined\n ? agentAccess\n : options.memory;\n if (memoryScope === \"user\" && !options.user) {\n throw new OpenGeniChatError(\n \"memory_scope_requires_user\",\n 'memory: \"user\" requires a user label so memories can be scoped to that end user.',\n );\n }\n const endUser = options.user ? { source: this.source, id: options.user } : undefined;\n const workspaceId = await this.workspaceId(options);\n const sessionId = await chatSessionId(workspaceId, options.conversation, endUser);\n const session = await this.findSession(workspaceId, sessionId);\n // Reopening an existing session re-verifies the label it was created with.\n // The tuple derivation already makes a collision impossible; this keeps a\n // relabelled or hand-addressed session from crossing users regardless.\n if (session && endUser && !sameEndUser(session.endUser ?? null, endUser)) {\n throw new OpenGeniChatError(\n \"conversation_not_authorized\",\n \"This conversation belongs to a different user.\",\n );\n }\n const buildCreate: BuildCreate = (text, importedHistory) => {\n const context =\n options.create?.modelContext === undefined && importedHistory\n ? formatImportedHistory(importedHistory)\n : undefined;\n return {\n agentAccess,\n memoryScope,\n ...(endUser ? { endUser } : {}),\n ...(options.model !== undefined ? { model: options.model } : {}),\n ...(options.instructions !== undefined ? { instructions: options.instructions } : {}),\n ...(options.skills !== undefined ? { skills: options.skills } : {}),\n ...(options.tools !== undefined ? { tools: options.tools } : {}),\n ...(context !== undefined ? { modelContext: context } : {}),\n ...(options.create ?? {}),\n initialMessage: text,\n requestedSessionId: sessionId,\n idempotencyKey: chatIdempotencyKey(sessionId),\n };\n };\n return new Chat(this, {\n workspaceId,\n sessionId,\n conversation: options.conversation,\n session,\n buildCreate,\n });\n }\n\n /**\n * Address an existing session by id (for example decoded from a response id).\n * `user` is the end user the caller authenticated: the session must carry\n * exactly that end-user label (`{ source, id }`) or the call throws\n * `conversation_not_authorized`. Pass `null` only from trusted server code\n * that vouches for the session itself; a session reached with `null` is not\n * checked against any user.\n */\n async chatBySessionId(target: {\n workspaceId: string;\n sessionId: string;\n user: string | null;\n }): Promise<Chat> {\n const session = await this.client.getSession(target.workspaceId, target.sessionId);\n if (\n target.user !== null &&\n !sameEndUser(session.endUser ?? null, { source: this.source, id: target.user })\n ) {\n throw new OpenGeniChatError(\n \"conversation_not_authorized\",\n \"This conversation belongs to a different user.\",\n );\n }\n return new Chat(this, {\n workspaceId: target.workspaceId,\n sessionId: target.sessionId,\n conversation: null,\n session,\n buildCreate: null,\n });\n }\n\n private async findSession(workspaceId: string, sessionId: string): Promise<Session | null> {\n try {\n return await this.client.getSession(workspaceId, sessionId);\n } catch (error) {\n if (error instanceof OpenGeniApiError && error.status === 404) return null;\n throw error;\n }\n }\n\n private async listSessions(options: ChatSessionListOptions): Promise<Session[]> {\n const workspaceId = await this.workspaceId(options);\n return await this.client.requestJson<Session[]>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/sessions`,\n undefined,\n {\n ...(options.limit !== undefined ? { limit: String(options.limit) } : {}),\n ...(options.user ? { endUserSource: this.source, endUserId: options.user } : {}),\n },\n );\n }\n}\n\n/** One conversation bound to one deterministic session. */\nexport class Chat {\n readonly workspaceId: string;\n readonly sessionId: string;\n /** The conversation id this chat was opened with; null when addressed by session id. */\n readonly conversation: string | null;\n private session: Session | null;\n private readonly buildCreate: BuildCreate | null;\n private pendingTurnId: string | null = null;\n\n constructor(\n private readonly og: OpenGeni,\n init: ChatInit,\n ) {\n this.workspaceId = init.workspaceId;\n this.sessionId = init.sessionId;\n this.conversation = init.conversation;\n this.session = init.session;\n this.buildCreate = init.buildCreate;\n }\n\n /** True once the session exists on the server. */\n get created(): boolean {\n return this.session !== null;\n }\n\n /** Send a message and wait for the agent's reply text. */\n async send(text: string, options: ChatSendOptions = {}): Promise<ChatReply> {\n return await settle(this.stream(text, options));\n }\n\n /** Send a message and observe the reply as it streams. Ends with a `done` chunk. */\n async *stream(\n text: string,\n options: ChatSendOptions = {},\n ): AsyncGenerator<ChatChunk, void, void> {\n const submitted = options.steer\n ? await this.submitSteer(text, options.importedHistory)\n : await this.submit(text, options.importedHistory);\n yield* this.streamTurn(submitted, options.signal);\n }\n\n /** Supersede the current inference with this message and wait for the reply. */\n async steer(text: string, options: Omit<ChatSendOptions, \"steer\"> = {}): Promise<ChatReply> {\n return await this.send(text, { ...options, steer: true });\n }\n\n /** Answer a pending approval or human-input request, then wait for the reply. */\n async respond(\n input: ChatRespondInput,\n options: Omit<ChatSendOptions, \"steer\"> = {},\n ): Promise<ChatReply> {\n return await settle(this.respondStream(input, options));\n }\n\n async *respondStream(\n input: ChatRespondInput,\n options: Omit<ChatSendOptions, \"steer\"> = {},\n ): AsyncGenerator<ChatChunk, void, void> {\n const submitted = await this.submitResponse(input);\n yield* this.streamTurn(submitted, options.signal);\n }\n\n /** User and assistant text in order, from the durable event log. */\n async history(): Promise<ChatMessage[]> {\n return (await this.snapshot()).messages;\n }\n\n /** Restore history and pending decisions from the complete ordered timeline. */\n async snapshot(): Promise<ChatSnapshot> {\n if (!this.session) return { messages: [], pending: [], status: null };\n const pending = new ChatPendingFold();\n let status = this.session.status;\n const messages: ChatMessage[] = [];\n let lastAssistantTurn: string | null = null;\n let after = 0;\n while (true) {\n const result = await this.og.client.listEventPage(this.workspaceId, this.sessionId, {\n after,\n includeTypes: [\n \"user.message\",\n \"agent.message.completed\",\n \"session.requiresAction\",\n \"session.humanInput.requested\",\n \"user.approvalDecision\",\n \"user.humanInputResponse\",\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"session.status.changed\",\n ],\n });\n for (const event of result.events) {\n pending.push(event);\n if (event.type === \"session.status.changed\") {\n const next = asRecord(event.payload).status;\n if (typeof next === \"string\") status = next as Session[\"status\"];\n }\n const text = stringValue(asRecord(event.payload).text);\n if (!text) continue;\n if (event.type === \"user.message\") {\n messages.push({ role: \"user\", text, sequence: event.sequence });\n lastAssistantTurn = null;\n continue;\n }\n if (event.type !== \"agent.message.completed\") continue;\n const turnId = typeof event.turnId === \"string\" ? event.turnId : null;\n const last = messages.at(-1);\n if (\n last?.role === \"assistant\" &&\n turnId !== null &&\n turnId === lastAssistantTurn &&\n text.startsWith(last.text)\n ) {\n last.text = text;\n last.sequence = event.sequence;\n continue;\n }\n messages.push({ role: \"assistant\", text, sequence: event.sequence });\n lastAssistantTurn = turnId;\n }\n if (!result.hasMore || result.nextAfter === null || result.events.length === 0) break;\n if (result.nextAfter <= after) {\n throw new OpenGeniChatError(\n \"history_cursor_stalled\",\n \"History pagination did not advance.\",\n );\n }\n after = result.nextAfter;\n }\n return { messages, pending: pending.pending(), status };\n }\n\n private async submit(\n text: string,\n importedHistory: ChatImportedMessage[] | undefined,\n ): Promise<SubmittedTurn> {\n if (!this.session) {\n if (!this.buildCreate) {\n throw new OpenGeniChatError(\"session_missing\", \"This session no longer exists.\");\n }\n const created = await this.og.client.createSession(\n this.workspaceId,\n this.buildCreate(text, importedHistory),\n );\n this.session = created;\n if (created.initialMessage === text) {\n return { after: 0, turnId: created.initialTurnId };\n }\n // The idempotent create replayed an earlier session; deliver this message too.\n }\n const event = await this.og.client.sendMessage(this.workspaceId, this.sessionId, text);\n return submittedFrom(event);\n }\n\n private async submitSteer(\n text: string,\n importedHistory: ChatImportedMessage[] | undefined,\n ): Promise<SubmittedTurn> {\n if (!this.session) return await this.submit(text, importedHistory);\n const result = await this.og.client.steerMessage(this.workspaceId, this.sessionId, text);\n return { after: result.accepted.sequence, turnId: result.turn.id ?? null };\n }\n\n private async submitResponse(input: ChatRespondInput): Promise<SubmittedTurn> {\n let event: SessionEvent;\n if (\"decision\" in input) {\n event = await this.og.client.sendApprovalDecision(this.workspaceId, this.sessionId, {\n approvalId: input.requestId,\n decision: input.decision,\n ...(input.message !== undefined ? { message: input.message } : {}),\n });\n } else if (\"answers\" in input) {\n event = await this.og.client.submitHumanInputResponse(\n this.workspaceId,\n this.sessionId,\n input.requestId,\n { outcome: \"answered\", answers: input.answers },\n );\n } else {\n event = await this.og.client.submitHumanInputResponse(\n this.workspaceId,\n this.sessionId,\n input.requestId,\n { outcome: \"skipped\" },\n );\n }\n const submitted = submittedFrom(event);\n return { ...submitted, turnId: submitted.turnId ?? this.pendingTurnId };\n }\n\n private async *streamTurn(\n submitted: SubmittedTurn,\n signal: AbortSignal | undefined,\n ): AsyncGenerator<ChatChunk, void, void> {\n const upstream = new AbortController();\n const onAbort = (): void => upstream.abort();\n if (signal?.aborted) upstream.abort();\n else signal?.addEventListener(\"abort\", onAbort, { once: true });\n const fold = new ChatTurnFold(this.workspaceId, this.sessionId, submitted.turnId);\n try {\n for await (const event of this.og.client.streamEvents(this.workspaceId, this.sessionId, {\n after: submitted.after,\n signal: upstream.signal,\n })) {\n const step = fold.push(event);\n for (const chunk of step.chunks) yield chunk;\n // Resuming one member of a parallel interruption group re-emits the\n // waiting status, but existing human-input requests are not recreated.\n // Recover the remaining decision instead of waiting forever for new text.\n if (\n !step.terminal &&\n event.type === \"session.status.changed\" &&\n asRecord(event.payload).status === \"requires_action\" &&\n (event.turnId == null || fold.turnId === null || event.turnId === fold.turnId)\n ) {\n const pending = (await this.snapshot()).pending[0];\n if (pending) {\n fold.pending = pending;\n this.pendingTurnId = fold.turnId;\n yield { type: \"pending\", pending };\n yield { type: \"done\", reply: fold.reply(\"pending\") };\n return;\n }\n }\n if (!step.terminal) continue;\n if (step.terminal === \"failed\") throw fold.failureError();\n this.pendingTurnId = step.terminal === \"pending\" ? fold.turnId : null;\n yield { type: \"done\", reply: fold.reply(step.terminal) };\n return;\n }\n if (signal?.aborted) throw abortError();\n throw new OpenGeniChatError(\n \"stream_ended\",\n \"The event stream ended before the turn settled.\",\n );\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n upstream.abort();\n }\n }\n}\n\nasync function settle(chunks: AsyncIterable<ChatChunk>): Promise<ChatReply> {\n for await (const chunk of chunks) {\n if (chunk.type === \"done\") return chunk.reply;\n }\n throw new OpenGeniChatError(\"stream_ended\", \"The event stream ended before the turn settled.\");\n}\n\nfunction submittedFrom(event: SessionEvent): SubmittedTurn {\n return {\n after: event.sequence,\n turnId: typeof event.turnId === \"string\" ? event.turnId : null,\n };\n}\n\n/**\n * `modelContext` for imported history: a header line plus one `role: text`\n * line per message, oldest first, trimmed from the oldest end to\n * {@link IMPORTED_HISTORY_MAX_CHARS}. Undefined when nothing usable remains.\n */\nexport function formatImportedHistory(messages: ChatImportedMessage[]): string | undefined {\n const lines = messages\n .filter(\n (message) =>\n IMPORTED_HISTORY_ROLES.has(message.role) &&\n typeof message.text === \"string\" &&\n message.text.trim().length > 0,\n )\n .map((message) => `${message.role}: ${message.text}`);\n if (lines.length === 0) return undefined;\n let budget = IMPORTED_HISTORY_MAX_CHARS - IMPORTED_HISTORY_HEADER.length;\n const kept: string[] = [];\n for (let index = lines.length - 1; index >= 0; index -= 1) {\n const line = lines[index]!;\n const cost = line.length + 1;\n if (cost <= budget) {\n kept.unshift(line);\n budget -= cost;\n continue;\n }\n // The newest line alone overflows: keep its tail so the most recent text survives.\n if (kept.length === 0 && budget > 1) kept.unshift(line.slice(line.length - (budget - 1)));\n break;\n }\n if (kept.length === 0) return undefined;\n return `${IMPORTED_HISTORY_HEADER}\\n${kept.join(\"\\n\")}`;\n}\n\nfunction abortError(): Error {\n const error = new Error(\"The chat request was aborted.\");\n error.name = \"AbortError\";\n return error;\n}\n\nfunction sameEndUser(\n left: { source: string; id: string } | null,\n right: { source: string; id: string },\n): boolean {\n return left !== null && left.source === right.source && left.id === right.id;\n}\n","import { OpenGeniApiError } from \"../errors\";\nimport type { OpenGeni } from \"./opengeni\";\nimport { OpenGeniChatError, type ChatImportedMessage, type ChatOptions } from \"./types\";\n\n/** Internal HTTP plumbing shared by the native handler and the protocol adapters. */\n\n/**\n * Header a client uses to name the conversation it is on. Every handler reads\n * the client conversation as: the host's resolution, else this header, else\n * the protocol's own field.\n */\nexport const CHAT_CONVERSATION_HEADER = \"x-opengeni-conversation\";\n\nconst CHAT_ERROR_STATUS: Readonly<Record<string, number>> = {\n memory_scope_requires_user: 400,\n conversation_not_authorized: 403,\n conversation_mismatch: 409,\n};\n\n/** What the host's auth hook returns: identity from the host, conversation optional per protocol. */\nexport type ChatResolution = Omit<ChatOptions, \"conversation\"> & {\n conversation?: string | undefined;\n};\n\n/**\n * The host's authentication hook. It receives the raw request and returns the\n * tenant/user/conversation the caller is allowed to use, or a `Response` to\n * reject the request. Never derive tenant or user from the request body.\n */\nexport type ChatResolve = (\n request: Request,\n) => Promise<ChatResolution | Response> | ChatResolution | Response;\n\nexport type ChatErrorSummary = { status: number; code: string; message: string };\n\nexport function jsonResponse(body: unknown, status = 200, headers: HeadersInit = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json; charset=utf-8\", ...headers },\n });\n}\n\nexport function errorResponse(status: number, message: string, code: string): Response {\n return jsonResponse(\n { error: { message, code, type: status >= 500 ? \"server_error\" : \"invalid_request_error\" } },\n status,\n );\n}\n\nexport async function readJsonObject(request: Request): Promise<Record<string, unknown> | null> {\n try {\n const parsed: unknown = await request.json();\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n}\n\nexport async function resolveChatRequest(\n request: Request,\n resolve: ChatResolve,\n): Promise<{ resolution: ChatResolution; response?: undefined } | { response: Response }> {\n const resolved = await resolve(request);\n if (resolved instanceof Response) return { response: resolved };\n return { resolution: resolved };\n}\n\n/** The client-supplied conversation: the header, else the protocol's own field. */\nexport function clientConversation(request: Request, protocolField: unknown): string | undefined {\n const header = request.headers.get(CHAT_CONVERSATION_HEADER);\n if (header) return header;\n return typeof protocolField === \"string\" && protocolField ? protocolField : undefined;\n}\n\n/**\n * Open a chat from a resolution plus the conversation the client supplied.\n * The host names the conversation, or the host names the user and the client\n * conversation id is namespaced to that user; anything else is a 400, because\n * an unscoped client id could address any conversation in the workspace.\n */\nexport async function openResolvedChat(\n og: OpenGeni,\n resolution: ChatResolution,\n clientConversationId: string | undefined,\n): Promise<\n { chat: Awaited<ReturnType<OpenGeni[\"chat\"]>>; response?: undefined } | { response: Response }\n> {\n if (!resolution.conversation && !resolution.user) {\n return {\n response: errorResponse(\n 400,\n \"Return a conversation from resolve, or a user so client conversation ids are scoped to that user.\",\n \"conversation_required\",\n ),\n };\n }\n const conversationId = resolution.conversation ?? clientConversationId;\n if (!conversationId) {\n return {\n response: errorResponse(\n 400,\n `A conversation id is required: send the ${CHAT_CONVERSATION_HEADER} header or the protocol's conversation field.`,\n \"conversation_required\",\n ),\n };\n }\n try {\n const chat = await og.chat({ ...resolution, conversation: conversationId } as ChatOptions);\n return { chat };\n } catch (error) {\n const summary = chatErrorSummary(error);\n return { response: errorResponse(summary.status, summary.message, summary.code) };\n }\n}\n\nexport function chatErrorSummary(error: unknown): ChatErrorSummary {\n if (error instanceof OpenGeniChatError) {\n const status = CHAT_ERROR_STATUS[error.code] ?? 502;\n return { status, code: error.code, message: error.message };\n }\n if (error instanceof OpenGeniApiError) {\n return {\n status: error.status >= 500 ? 502 : error.status,\n code: error.code ?? \"opengeni_api_error\",\n message: error.message,\n };\n }\n if (error instanceof Error && error.name === \"AbortError\") {\n return { status: 499, code: \"aborted\", message: \"The chat request was aborted.\" };\n }\n return { status: 500, code: \"internal_error\", message: \"Chat request failed.\" };\n}\n\nexport function sseHeaders(extra: Record<string, string> = {}): Record<string, string> {\n return {\n \"Content-Type\": \"text/event-stream; charset=utf-8\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n ...extra,\n };\n}\n\nexport function sseLine(data: string, event?: string): string {\n return `${event ? `event: ${event}\\n` : \"\"}data: ${data}\\n\\n`;\n}\n\n/**\n * Pull-based text-to-bytes stream over already-formatted SSE blocks. Upstream\n * consumption follows downstream demand; cancelling fires `onCancel` so the\n * producer can abort its OpenGeni stream.\n */\nexport function sseByteStream(\n blocks: AsyncIterable<string>,\n onCancel?: () => void,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const iterator = blocks[Symbol.asyncIterator]();\n let cancelled = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n const result = await iterator.next();\n if (cancelled) return;\n if (result.done) {\n controller.close();\n return;\n }\n controller.enqueue(encoder.encode(result.value));\n },\n cancel: () => {\n cancelled = true;\n onCancel?.();\n void Promise.resolve(iterator.return?.(undefined)).then(\n () => undefined,\n () => undefined,\n );\n },\n });\n}\n\n/** Text from an OpenAI-style message content: a string or `[{ type, text }]` parts. */\nexport function messageContentText(content: unknown, partTypes: string[]): string | null {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return null;\n const texts = content\n .map((part) => {\n if (!part || typeof part !== \"object\") return null;\n const record = part as Record<string, unknown>;\n return partTypes.includes(String(record.type)) && typeof record.text === \"string\"\n ? record.text\n : null;\n })\n .filter((text): text is string => text !== null);\n return texts.length > 0 ? texts.join(\"\\n\") : null;\n}\n\nfunction lastUserMessageIndex(messages: unknown[]): number {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message && typeof message === \"object\" && (message as { role?: unknown }).role === \"user\") {\n return index;\n }\n }\n return -1;\n}\n\nfunction messageText(\n message: unknown,\n partTypes: string[],\n partsField: \"parts\" | \"content\",\n): string | null {\n if (!message || typeof message !== \"object\") return null;\n const record = message as Record<string, unknown>;\n return (\n messageContentText(record[partsField], partTypes) ??\n messageContentText(record.content, partTypes)\n );\n}\n\n/** The last user-role message's text from an OpenAI/Vercel-style `messages` array. */\nexport function lastUserMessageText(\n messages: unknown,\n partTypes: string[],\n partsField: \"parts\" | \"content\",\n): string | null {\n if (!Array.isArray(messages)) return null;\n const index = lastUserMessageIndex(messages);\n return index < 0 ? null : messageText(messages[index], partTypes, partsField);\n}\n\n/**\n * Every user/assistant/system message before the last user message, as\n * imported history for the first create. Items without a role or text\n * (tool calls, files) are skipped.\n */\nexport function importedHistoryBefore(\n messages: unknown,\n partTypes: string[],\n partsField: \"parts\" | \"content\",\n): ChatImportedMessage[] {\n if (!Array.isArray(messages)) return [];\n const lastUser = lastUserMessageIndex(messages);\n if (lastUser < 0) return [];\n const imported: ChatImportedMessage[] = [];\n for (const message of messages.slice(0, lastUser)) {\n const role = (message as { role?: unknown } | null)?.role;\n if (role !== \"user\" && role !== \"assistant\" && role !== \"system\") continue;\n const text = messageText(message, partTypes, partsField);\n if (text) imported.push({ role, text });\n }\n return imported;\n}\n\nexport function unixSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import {\n chatErrorSummary,\n clientConversation,\n errorResponse,\n importedHistoryBefore,\n jsonResponse,\n lastUserMessageText,\n messageContentText,\n openResolvedChat,\n readJsonObject,\n resolveChatRequest,\n sseByteStream,\n sseHeaders,\n sseLine,\n type ChatResolve,\n} from \"./http\";\nimport { isUuid } from \"./ids\";\nimport type { Chat, OpenGeni } from \"./opengeni\";\nimport { OpenGeniChatError, type ChatChunk, type ChatReply } from \"./types\";\n\n/**\n * OpenAI-compatible adapters over the stable subset of the Chat Completions\n * and Responses wire formats. `model` and `user` in the body are echoed, never\n * trusted: identity comes from the host's `resolve` hook.\n */\n\nconst DEFAULT_MODEL_LABEL = \"opengeni\";\n\ntype ReplyExtension = {\n sessionId: string;\n workspaceId: string;\n turnId: string | null;\n status: ChatReply[\"status\"];\n pending: ChatReply[\"pending\"];\n};\n\nfunction replyExtension(reply: ChatReply): ReplyExtension {\n return {\n sessionId: reply.sessionId,\n workspaceId: reply.workspaceId,\n turnId: reply.turnId,\n status: reply.status,\n pending: reply.pending,\n };\n}\n\nfunction conversationFromBody(body: Record<string, unknown> | null): string | undefined {\n const conversation = body?.conversation;\n if (typeof conversation === \"string\" && conversation) return conversation;\n if (conversation && typeof conversation === \"object\") {\n const id = (conversation as { id?: unknown }).id;\n if (typeof id === \"string\" && id) return id;\n }\n return undefined;\n}\n\nfunction modelLabel(body: Record<string, unknown> | null): string {\n return typeof body?.model === \"string\" && body.model ? body.model : DEFAULT_MODEL_LABEL;\n}\n\nfunction wantsStream(body: Record<string, unknown> | null): boolean {\n return body?.stream === true;\n}\n\n// --- Chat Completions ---------------------------------------------------------\n\nconst CHAT_COMPLETION_PART_TYPES = [\"text\", \"input_text\"];\n\nfunction chatCompletionChunk(\n sessionId: string,\n model: string,\n created: number,\n delta: Record<string, unknown>,\n finishReason: \"stop\" | null,\n extension?: ReplyExtension,\n): string {\n return sseLine(\n JSON.stringify({\n id: `chatcmpl-${sessionId}`,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta, finish_reason: finishReason }],\n ...(extension ? { opengeni: extension } : {}),\n }),\n );\n}\n\nexport async function* chatCompletionBlocks(\n chat: Chat,\n chunks: AsyncIterable<ChatChunk>,\n model: string,\n): AsyncGenerator<string, void, void> {\n const created = Math.floor(Date.now() / 1000);\n yield chatCompletionChunk(\n chat.sessionId,\n model,\n created,\n { role: \"assistant\", content: \"\" },\n null,\n );\n try {\n for await (const chunk of chunks) {\n if (chunk.type === \"text\") {\n yield chatCompletionChunk(chat.sessionId, model, created, { content: chunk.text }, null);\n } else if (chunk.type === \"done\") {\n yield chatCompletionChunk(\n chat.sessionId,\n model,\n created,\n {},\n \"stop\",\n replyExtension(chunk.reply),\n );\n }\n }\n } catch (error) {\n const summary = chatErrorSummary(error);\n yield sseLine(\n JSON.stringify({\n error: { message: summary.message, code: summary.code, type: \"server_error\" },\n }),\n );\n }\n yield sseLine(\"[DONE]\");\n}\n\nexport function chatCompletionObject(reply: ChatReply, model: string): Record<string, unknown> {\n return {\n id: `chatcmpl-${reply.sessionId}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content: reply.text }, finish_reason: \"stop\" },\n ],\n opengeni: replyExtension(reply),\n };\n}\n\n/**\n * `POST /v1/chat/completions` shape: `{ messages, stream?, model?, user?, metadata? }`.\n * Conversation: the host's `resolve`, else the `x-opengeni-conversation` header,\n * else `metadata.conversation_id`; 400 when none. Only the last user message\n * is sent; the messages before it are imported once as context when this\n * request creates the session.\n */\nexport async function handleChatCompletionsRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const prompt =\n lastUserMessageText(body?.messages, CHAT_COMPLETION_PART_TYPES, \"content\")?.trim() ?? \"\";\n if (!prompt) {\n return errorResponse(400, \"The last user message has no text.\", \"message_required\");\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const metadata = body?.metadata;\n const metadataConversation =\n metadata && typeof metadata === \"object\"\n ? (metadata as { conversation_id?: unknown }).conversation_id\n : undefined;\n const opened = await openResolvedChat(\n og,\n resolved.resolution,\n clientConversation(request, metadataConversation),\n );\n if (opened.response) return opened.response;\n const model = modelLabel(body);\n const importedHistory = importedHistoryBefore(\n body?.messages,\n CHAT_COMPLETION_PART_TYPES,\n \"content\",\n );\n if (wantsStream(body)) {\n const chunks = opened.chat.stream(prompt, { signal: request.signal, importedHistory });\n return new Response(sseByteStream(chatCompletionBlocks(opened.chat, chunks, model)), {\n headers: sseHeaders(),\n });\n }\n try {\n const reply = await opened.chat.send(prompt, { signal: request.signal, importedHistory });\n return jsonResponse(chatCompletionObject(reply, model));\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n}\n\n// --- Responses ----------------------------------------------------------------\n\n/** Non-streaming response id; the session id alone addresses the conversation. */\nexport function encodeResponseId(sessionId: string, sequence: number): string {\n return `resp_${sessionId}_${sequence}`;\n}\n\nexport function decodeResponseId(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n // Streams allocate a UUID before the final event sequence is known. Keep\n // accepting existing sequence-based response ids for conversation continuity.\n const match = /^resp_([0-9a-f-]{36})(?:_(\\d+|[0-9a-f-]{36}))?$/i.exec(value);\n const sessionId = match?.[1];\n const suffix = match?.[2];\n if (suffix && !/^\\d+$/.test(suffix) && !isUuid(suffix)) return null;\n return sessionId && isUuid(sessionId) ? sessionId : null;\n}\n\ntype ResponseIdentity = { responseId: string; itemId: string; createdAt: number };\ntype ResponseStatus = \"in_progress\" | \"completed\" | \"incomplete\";\n\nfunction responseOutputItem(itemId: string, status: ResponseStatus, text: string | null) {\n return {\n type: \"message\",\n id: itemId,\n status,\n role: \"assistant\",\n content: text === null ? [] : [{ type: \"output_text\", text, annotations: [] }],\n };\n}\n\nfunction responseObject(\n reply: ChatReply | null,\n chat: Chat,\n model: string,\n status: ResponseStatus,\n previousResponseId: string | null,\n text: string,\n identity?: ResponseIdentity,\n): Record<string, unknown> {\n const sequence = reply?.events.at(-1)?.sequence ?? 0;\n return {\n id: identity?.responseId ?? encodeResponseId(chat.sessionId, sequence),\n object: \"response\",\n created_at: identity?.createdAt ?? Math.floor(Date.now() / 1000),\n status,\n model,\n previous_response_id: previousResponseId,\n output:\n status === \"in_progress\"\n ? []\n : [\n responseOutputItem(\n identity?.itemId ?? `msg_${chat.sessionId}_${sequence}`,\n status,\n text,\n ),\n ],\n output_text: text,\n ...(reply ? { opengeni: replyExtension(reply) } : {}),\n };\n}\n\nexport async function* responsesBlocks(\n chat: Chat,\n chunks: AsyncIterable<ChatChunk>,\n model: string,\n previousResponseId: string | null,\n): AsyncGenerator<string, void, void> {\n let sequenceNumber = 0;\n const requestId = crypto.randomUUID();\n const identity: ResponseIdentity = {\n responseId: `resp_${chat.sessionId}_${requestId}`,\n itemId: `msg_${chat.sessionId}_${requestId}`,\n createdAt: Math.floor(Date.now() / 1000),\n };\n const { itemId } = identity;\n const event = (type: string, data: Record<string, unknown>): string =>\n sseLine(JSON.stringify({ type, sequence_number: sequenceNumber++, ...data }), type);\n const initial = responseObject(\n null,\n chat,\n model,\n \"in_progress\",\n previousResponseId,\n \"\",\n identity,\n );\n yield event(\"response.created\", { response: initial });\n yield event(\"response.in_progress\", { response: initial });\n yield event(\"response.output_item.added\", {\n output_index: 0,\n item: responseOutputItem(itemId, \"in_progress\", null),\n });\n yield event(\"response.content_part.added\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n part: { type: \"output_text\", text: \"\", annotations: [] },\n });\n try {\n for await (const chunk of chunks) {\n if (chunk.type === \"text\") {\n yield event(\"response.output_text.delta\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n delta: chunk.text,\n logprobs: [],\n });\n } else if (chunk.type === \"done\") {\n const status = chunk.reply.status === \"completed\" ? \"completed\" : \"incomplete\";\n const item = responseOutputItem(itemId, status, chunk.reply.text);\n yield event(\"response.output_text.done\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n text: chunk.reply.text,\n logprobs: [],\n });\n yield event(\"response.content_part.done\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n part: item.content[0]!,\n });\n yield event(\"response.output_item.done\", { output_index: 0, item });\n yield event(`response.${status}`, {\n response: responseObject(\n chunk.reply,\n chat,\n model,\n status,\n previousResponseId,\n chunk.reply.text,\n identity,\n ),\n });\n }\n }\n } catch (error) {\n const summary = chatErrorSummary(error);\n yield event(\"error\", { code: summary.code, message: summary.message, param: null });\n }\n}\n\n/** Text of the Responses `input`: a string, or the last user item's `input_text` parts. */\nexport function responsesInputText(input: unknown): string | null {\n if (typeof input === \"string\") return input;\n if (!Array.isArray(input)) return null;\n const fromRole = lastUserMessageText(input, [\"input_text\", \"text\"], \"content\");\n if (fromRole !== null) return fromRole;\n const last = input.at(-1);\n return last && typeof last === \"object\"\n ? messageContentText((last as { content?: unknown }).content, [\"input_text\", \"text\"])\n : null;\n}\n\n/**\n * `POST /v1/responses` shape: `{ input, previous_response_id?, conversation?, stream?, model?, user? }`.\n * Conversation: the host's `resolve`, else the `x-opengeni-conversation`\n * header, else `conversation` / `conversation.id`. A `previous_response_id`\n * may continue the session it encodes only when the host named the user that\n * session belongs to (403 otherwise); when a conversation is named as well,\n * the two must agree (409). 400 when nothing names a conversation. Only the\n * last user item is sent; earlier array items are imported once as context\n * when this request creates the session.\n */\nexport async function handleResponsesRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const prompt = responsesInputText(body?.input)?.trim() ?? \"\";\n if (!prompt) return errorResponse(400, \"The input has no user text.\", \"message_required\");\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const previousResponseId =\n typeof body?.previous_response_id === \"string\" ? body.previous_response_id : null;\n const conversation = clientConversation(request, conversationFromBody(body));\n const previousSessionId = decodeResponseId(previousResponseId);\n const namedConversation =\n resolved.resolution.conversation ?? (resolved.resolution.user ? conversation : undefined);\n let chat: Chat;\n if (previousSessionId && !namedConversation) {\n if (!resolved.resolution.user) {\n return errorResponse(\n 400,\n \"Return a conversation from resolve, or a user so client conversation ids are scoped to that user.\",\n \"conversation_required\",\n );\n }\n try {\n const workspaceId = await og.workspaceId(resolved.resolution);\n chat = await og.chatBySessionId({\n workspaceId,\n sessionId: previousSessionId,\n user: resolved.resolution.user,\n });\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n } else {\n const opened = await openResolvedChat(og, resolved.resolution, conversation);\n if (opened.response) return opened.response;\n chat = opened.chat;\n if (previousSessionId && previousSessionId !== chat.sessionId) {\n const summary = chatErrorSummary(\n new OpenGeniChatError(\n \"conversation_mismatch\",\n \"previous_response_id belongs to a different conversation than the one named for this request.\",\n ),\n );\n return errorResponse(summary.status, summary.message, summary.code);\n }\n }\n const model = modelLabel(body);\n const importedHistory = importedHistoryBefore(\n body?.input,\n [\"input_text\", \"text\", \"output_text\"],\n \"content\",\n );\n if (wantsStream(body)) {\n const chunks = chat.stream(prompt, { signal: request.signal, importedHistory });\n return new Response(sseByteStream(responsesBlocks(chat, chunks, model, previousResponseId)), {\n headers: sseHeaders(),\n });\n }\n try {\n const reply = await chat.send(prompt, { signal: request.signal, importedHistory });\n return jsonResponse(\n responseObject(\n reply,\n chat,\n model,\n reply.status === \"completed\" ? \"completed\" : \"incomplete\",\n previousResponseId,\n reply.text,\n ),\n );\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n}\n","import { asRecord } from \"./fold\";\nimport {\n chatErrorSummary,\n clientConversation,\n errorResponse,\n importedHistoryBefore,\n lastUserMessageText,\n openResolvedChat,\n readJsonObject,\n resolveChatRequest,\n sseByteStream,\n sseHeaders,\n sseLine,\n type ChatResolve,\n} from \"./http\";\nimport type { OpenGeni } from \"./opengeni\";\nimport type { ChatChunk, ChatPending } from \"./types\";\n\n/**\n * Vercel AI SDK UI message stream (protocol v1, as consumed by `useChat` with\n * the default transport). Parts are `data: <json>` SSE lines terminated by\n * `data: [DONE]`, under the `x-vercel-ai-ui-message-stream: v1` header.\n */\n\nexport const UI_MESSAGE_STREAM_HEADER = \"x-vercel-ai-ui-message-stream\";\nexport const UI_MESSAGE_STREAM_VERSION = \"v1\";\n\nexport type UIMessageStreamOptions = {\n /** Assistant message id announced in the `start` part. Defaults to a random UUID. */\n messageId?: string | undefined;\n};\n\n/** Protocol parts for one reply, in order. */\nexport async function* uiMessageStreamParts(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions = {},\n): AsyncGenerator<Record<string, unknown>, void, void> {\n const messageId = options.messageId ?? crypto.randomUUID();\n const textId = `text_${messageId}`;\n let textOpen = false;\n const closeText = (): Record<string, unknown>[] => {\n if (!textOpen) return [];\n textOpen = false;\n return [{ type: \"text-end\", id: textId }];\n };\n yield { type: \"start\", messageId };\n yield { type: \"start-step\" };\n try {\n for await (const chunk of chunks) {\n switch (chunk.type) {\n case \"text\":\n if (!textOpen) {\n textOpen = true;\n yield { type: \"text-start\", id: textId };\n }\n yield { type: \"text-delta\", id: textId, delta: chunk.text };\n break;\n case \"tool\": {\n yield* closeText();\n const toolCallId = chunk.callId ?? `call_${crypto.randomUUID()}`;\n if (chunk.status === \"started\") {\n yield { type: \"tool-input-start\", toolCallId, toolName: chunk.name };\n yield {\n type: \"tool-input-available\",\n toolCallId,\n toolName: chunk.name,\n input: chunk.input ?? {},\n };\n } else {\n yield { type: \"tool-output-available\", toolCallId, output: { status: chunk.status } };\n }\n break;\n }\n case \"pending\":\n yield* closeText();\n yield* pendingParts(chunk.pending);\n break;\n case \"done\":\n yield* closeText();\n break;\n }\n }\n yield* closeText();\n yield { type: \"finish-step\" };\n yield { type: \"finish\" };\n } catch (error) {\n yield* closeText();\n yield { type: \"error\", errorText: chatErrorSummary(error).message };\n }\n}\n\nfunction* pendingParts(pending: ChatPending): Generator<Record<string, unknown>> {\n if (pending.kind === \"approval\") {\n const raw = asRecord(pending.payload);\n const rawItem = asRecord(raw.rawItem);\n yield {\n type: \"tool-input-available\",\n toolCallId: pending.requestId,\n toolName: pending.name ?? \"tool\",\n input: raw.arguments ?? rawItem.arguments ?? {},\n };\n yield {\n type: \"tool-approval-request\",\n toolCallId: pending.requestId,\n approvalId: pending.requestId,\n };\n return;\n }\n yield { type: \"data-opengeni-pending\", data: pending };\n}\n\nexport async function* uiMessageStreamBlocks(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions = {},\n): AsyncGenerator<string, void, void> {\n for await (const part of uiMessageStreamParts(chunks, options)) {\n yield sseLine(JSON.stringify(part));\n }\n yield sseLine(\"[DONE]\");\n}\n\nexport function chatChunksToUIMessageStream(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions & { onCancel?: (() => void) | undefined } = {},\n): ReadableStream<Uint8Array> {\n return sseByteStream(uiMessageStreamBlocks(chunks, options), options.onCancel);\n}\n\nexport function uiMessageStreamResponse(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions = {},\n): Response {\n return new Response(chatChunksToUIMessageStream(chunks, options), {\n headers: sseHeaders({ [UI_MESSAGE_STREAM_HEADER]: UI_MESSAGE_STREAM_VERSION }),\n });\n}\n\n/** Text of the last user `UIMessage` (`parts` of type `text`, joined). */\nexport function lastUIMessageText(messages: unknown): string | null {\n return lastUserMessageText(messages, [\"text\"], \"parts\");\n}\n\n/**\n * `useChat` request handler: body `{ id, messages, trigger, messageId }`.\n * Conversation: the host's `resolve`, else the `x-opengeni-conversation`\n * header, else the chat `id`. Only the last user message is sent; the\n * messages before it are imported once as context when this request creates\n * the session. `regenerate-message` steers instead of queueing.\n */\nexport async function handleVercelChatRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const prompt = lastUIMessageText(body?.messages)?.trim() ?? \"\";\n if (!prompt) {\n return errorResponse(400, \"The last user message has no text.\", \"message_required\");\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(\n og,\n resolved.resolution,\n clientConversation(request, body?.id),\n );\n if (opened.response) return opened.response;\n const steer = body?.trigger === \"regenerate-message\";\n const importedHistory = importedHistoryBefore(body?.messages, [\"text\"], \"parts\");\n return uiMessageStreamResponse(\n opened.chat.stream(prompt, { signal: request.signal, steer, importedHistory }),\n );\n}\n","import { parseSseStream } from \"../sse\";\nimport type { HumanInputAnswer } from \"../types\";\nimport {\n chatErrorSummary,\n clientConversation,\n errorResponse,\n jsonResponse,\n openResolvedChat,\n readJsonObject,\n resolveChatRequest,\n sseByteStream,\n sseHeaders,\n sseLine,\n type ChatResolve,\n} from \"./http\";\nimport { handleChatCompletionsRequest, handleResponsesRequest } from \"./openai\";\nimport type { OpenGeni } from \"./opengeni\";\nimport { OpenGeniChatError, type ChatChunk, type ChatRespondInput } from \"./types\";\nimport { handleVercelChatRequest } from \"./vercel\";\n\nexport { CHAT_CONVERSATION_HEADER, type ChatResolution, type ChatResolve } from \"./http\";\n\nexport type ChatHandlerFormat = \"native\" | \"vercel\" | \"openai-chat\" | \"openai-responses\";\n\nexport type ChatHandlerOptions = {\n /** Mandatory host auth hook; see {@link ChatResolve}. */\n resolve: ChatResolve;\n /** Default wire format; a request may override it with the format header. */\n format?: ChatHandlerFormat | undefined;\n};\n\n/** Per-request wire-format override header. */\nexport const CHAT_FORMAT_HEADER = \"x-opengeni-chat-format\";\n\nconst CHAT_FORMATS: ReadonlySet<string> = new Set([\n \"native\",\n \"vercel\",\n \"openai-chat\",\n \"openai-responses\",\n]);\n\nfunction methodNotAllowed(allow: string): Response {\n return new Response(\n JSON.stringify({ error: { message: `Use ${allow}.`, code: \"method_not_allowed\" } }),\n { status: 405, headers: { Allow: allow, \"Content-Type\": \"application/json; charset=utf-8\" } },\n );\n}\n\n/**\n * One request handler for a product's chat endpoint. `POST` with `{ message }`\n * streams the reply in the selected format; `POST .../respond` answers a\n * pending approval or human-input request and streams the continuation;\n * `GET` returns the conversation's history as JSON. Every other method is a\n * 405. The conversation is the host's resolution, else the\n * `x-opengeni-conversation` header, else the wire format's own field.\n */\nexport function createChatHandler(\n og: OpenGeni,\n options: ChatHandlerOptions,\n): (request: Request) => Promise<Response> {\n return async (request) => {\n const isRespond = new URL(request.url).pathname.replace(/\\/+$/, \"\").endsWith(\"/respond\");\n if (isRespond) {\n if (request.method !== \"POST\") return methodNotAllowed(\"POST\");\n return await handleNativeRespondRequest(og, request, options.resolve);\n }\n if (request.method === \"GET\") {\n return await handleNativeHistoryRequest(og, request, options.resolve);\n }\n if (request.method !== \"POST\") return methodNotAllowed(\"GET, POST\");\n const headerFormat = request.headers.get(CHAT_FORMAT_HEADER);\n if (headerFormat !== null && !CHAT_FORMATS.has(headerFormat)) {\n return errorResponse(400, `Unknown chat format: ${headerFormat}`, \"unknown_format\");\n }\n const format = (headerFormat as ChatHandlerFormat | null) ?? options.format ?? \"native\";\n switch (format) {\n case \"vercel\":\n return await handleVercelChatRequest(og, request, options.resolve);\n case \"openai-chat\":\n return await handleChatCompletionsRequest(og, request, options.resolve);\n case \"openai-responses\":\n return await handleResponsesRequest(og, request, options.resolve);\n default:\n return await handleNativeChatRequest(og, request, options.resolve);\n }\n };\n}\n\n/** `POST { message }` -> native SSE of {@link ChatChunk} (`event: chunk`). */\nexport async function handleNativeChatRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const message = typeof body?.message === \"string\" ? body.message.trim() : \"\";\n if (!message) {\n return errorResponse(400, \"Body must carry a non-empty message.\", \"message_required\");\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));\n if (opened.response) return opened.response;\n return chatChunksToSseResponse(opened.chat.stream(message, { signal: request.signal }));\n}\n\n/**\n * `GET` -> `{ conversation, sessionId, created, messages, pending, status }`: the user and\n * assistant text of the conversation so a client can restore it on reload\n * (`messages` is empty and `created` false before the first message).\n */\nexport async function handleNativeHistoryRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));\n if (opened.response) return opened.response;\n try {\n const snapshot = await opened.chat.snapshot();\n return jsonResponse({\n conversation: opened.chat.conversation,\n sessionId: opened.chat.sessionId,\n created: opened.chat.created,\n ...snapshot,\n });\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n}\n\n/** `POST .../respond { requestId, decision | answers | skip }` -> native SSE of the continuation. */\nexport async function handleNativeRespondRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const input = respondInputFromBody(body);\n if (!input) {\n return errorResponse(\n 400,\n \"Body must carry requestId plus decision, answers, or skip.\",\n \"respond_input_invalid\",\n );\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));\n if (opened.response) return opened.response;\n return chatChunksToSseResponse(opened.chat.respondStream(input, { signal: request.signal }));\n}\n\nexport function respondInputFromBody(\n body: Record<string, unknown> | null,\n): ChatRespondInput | null {\n const requestId = typeof body?.requestId === \"string\" ? body.requestId : \"\";\n if (!body || !requestId) return null;\n if (body.decision === \"approve\" || body.decision === \"reject\") {\n return {\n requestId,\n decision: body.decision,\n ...(typeof body.message === \"string\" ? { message: body.message } : {}),\n };\n }\n if (Array.isArray(body.answers)) {\n const answers = body.answers.filter(\n (answer): answer is HumanInputAnswer =>\n !!answer &&\n typeof answer === \"object\" &&\n typeof (answer as HumanInputAnswer).questionId === \"string\" &&\n Array.isArray((answer as HumanInputAnswer).values),\n );\n return { requestId, answers };\n }\n if (body.skip === true) return { requestId, skip: true };\n return null;\n}\n\n/** Native wire format: `event: chunk` per {@link ChatChunk}, `event: error` on failure. */\nexport async function* chatChunksToSseBlocks(\n chunks: AsyncIterable<ChatChunk>,\n): AsyncGenerator<string, void, void> {\n try {\n for await (const chunk of chunks) {\n yield sseLine(JSON.stringify(chunk), \"chunk\");\n }\n } catch (error) {\n const summary = chatErrorSummary(error);\n yield sseLine(JSON.stringify({ code: summary.code, message: summary.message }), \"error\");\n }\n}\n\nexport function chatChunksToSseStream(\n chunks: AsyncIterable<ChatChunk>,\n onCancel?: () => void,\n): ReadableStream<Uint8Array> {\n return sseByteStream(chatChunksToSseBlocks(chunks), onCancel);\n}\n\nexport function chatChunksToSseResponse(chunks: AsyncIterable<ChatChunk>): Response {\n return new Response(chatChunksToSseStream(chunks), {\n headers: sseHeaders({ [CHAT_FORMAT_HEADER]: \"native\" }),\n });\n}\n\n/** Browser-side reader for the native wire format. Throws {@link OpenGeniChatError} on `event: error`. */\nexport async function* parseChatChunkStream(\n stream: ReadableStream<Uint8Array>,\n): AsyncGenerator<ChatChunk, void, void> {\n for await (const message of parseSseStream(stream)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(message.data);\n } catch {\n continue;\n }\n if (message.event === \"error\") {\n const record = (parsed ?? {}) as { code?: unknown; message?: unknown };\n throw new OpenGeniChatError(\n typeof record.code === \"string\" ? record.code : \"chat_error\",\n typeof record.message === \"string\" ? record.message : \"Chat request failed.\",\n );\n }\n if (\n parsed &&\n typeof parsed === \"object\" &&\n typeof (parsed as { type?: unknown }).type === \"string\"\n ) {\n yield parsed as ChatChunk;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/chat/types.ts","../../src/chat/fold.ts","../../src/chat/ids.ts","../../src/chat/opengeni.ts","../../src/chat/http.ts","../../src/chat/openai.ts","../../src/chat/vercel.ts","../../src/chat/handler.ts"],"sourcesContent":["import type { FetchLike } from \"../client\";\nimport type {\n CreateSessionRequest,\n HumanInputAnswer,\n SessionEvent,\n Session,\n SessionSkill,\n ToolRef,\n} from \"../types\";\n\n/** Which other sessions the agent may reach from this one. */\nexport type ChatAgentAccess = \"session\" | \"user\" | \"workspace\";\n\n/**\n * Memory scope for the session: which memories the agent reads and where it\n * saves. `false` disables Memory tools. Omitted follows user/workspace agent\n * reach; session-only reach defaults to false. Task notes cover task-local data.\n */\nexport type ChatMemory = \"user\" | \"workspace\" | false;\n\nexport type OpenGeniOptions = {\n /** Organization API key. Keep it on the server. */\n apiKey: string;\n /** The organization (account) id that owns every tenant workspace. */\n organizationId: string;\n /** Defaults to `https://app.opengeni.ai`. */\n baseUrl?: string | undefined;\n /**\n * The product identity used as the external-source label for tenant\n * workspaces and end users. Defaults to `\"app\"`.\n */\n source?: string | undefined;\n fetch?: FetchLike | undefined;\n /** Display name for a tenant workspace created on first use. Defaults to the tenant id. */\n workspaceName?: ((tenant: string) => string) | undefined;\n};\n\nexport type ChatTarget =\n | { tenant: string; workspaceId?: undefined }\n | { workspaceId: string; tenant?: undefined };\n\nexport type ChatOptions = ChatTarget & {\n /** Host-authenticated external user; resolved through server-side asUser(). */\n user?: string | undefined;\n /** Stable conversation id; the session id is derived from it deterministically. */\n conversation: string;\n /** Prefer the actual OpenGeni session ID for shared or existing conversations.\n * The acting user is independent of the conversation's identity. */\n sessionId?: string | undefined;\n /** Defaults to `\"session\"`: the agent sees only this conversation. */\n agentAccess?: ChatAgentAccess | undefined;\n memory?: ChatMemory | undefined;\n model?: string | undefined;\n instructions?: string | undefined;\n skills?: SessionSkill[] | undefined;\n tools?: ToolRef[] | undefined;\n /**\n * Raw create-request passthrough (for example `sandboxBackend: \"none\"` for a\n * pure chat). Explicit values win over facade-derived ones; the message and\n * identity/idempotency fields always come from the facade.\n */\n create?: Partial<CreateSessionRequest> | undefined;\n};\n\n/** A turn stopped to wait for a human decision. */\nexport type ChatPending = {\n kind: \"approval\" | \"human_input\";\n /** The id to pass back through `chat.respond`. */\n requestId: string;\n /** Tool name for an approval; null for structured human input. */\n name: string | null;\n /** The producer's exact payload (approval entry or human-input request). */\n payload: unknown;\n};\n\nexport type ChatReplyStatus = \"completed\" | \"pending\" | \"cancelled\";\n\nexport type ChatReply = {\n text: string;\n sessionId: string;\n workspaceId: string;\n turnId: string | null;\n /** `pending` waits on `chat.respond`; `cancelled` carries the text produced before the cancel. */\n status: ChatReplyStatus;\n /** Set when the turn is waiting on `chat.respond` instead of finished. */\n pending: ChatPending | null;\n /** Every event consumed while folding this turn. */\n events: SessionEvent[];\n toString(): string;\n};\n\nexport type ChatToolStatus = \"started\" | \"completed\" | \"failed\";\n\nexport type ChatChunk =\n | { type: \"text\"; text: string }\n | {\n type: \"tool\";\n name: string;\n status: ChatToolStatus;\n callId?: string | undefined;\n input?: unknown;\n }\n | { type: \"pending\"; pending: ChatPending }\n | { type: \"done\"; reply: ChatReply };\n\nexport type ChatMessage = {\n role: \"user\" | \"assistant\";\n text: string;\n sequence: number;\n};\n\n/** Durable text and unresolved decisions restored when a chat is reopened. */\nexport type ChatSnapshot = {\n messages: ChatMessage[];\n pending: ChatPending[];\n status: Session[\"status\"] | null;\n};\n\nexport type ChatRespondInput =\n | { requestId: string; decision: \"approve\" | \"reject\"; message?: string | undefined }\n | { requestId: string; answers: HumanInputAnswer[] }\n | { requestId: string; skip: true };\n\n/** One earlier message from the product's own history, imported as context on the first send. */\nexport type ChatImportedMessage = { role: \"user\" | \"assistant\" | \"system\"; text: string };\n\nexport type ChatSendOptions = {\n signal?: AbortSignal | undefined;\n /** Supersede the current inference instead of queueing behind it. */\n steer?: boolean | undefined;\n /**\n * Earlier messages the product already holds, oldest first. Used only when\n * this send creates the session: they become the first message's\n * `modelContext` (skipped when `create.modelContext` was supplied), trimmed\n * from the oldest end to 30,000 characters. Never resent on later turns:\n * after the first message OpenGeni owns the history.\n */\n importedHistory?: ChatImportedMessage[] | undefined;\n};\n\nexport type ChatSessionListOptions = ChatTarget & {\n user?: string | undefined;\n limit?: number | undefined;\n};\n\n/** A turn ended without a usable reply, or the facade was misused. */\nexport class OpenGeniChatError extends Error {\n readonly code: string;\n readonly event: SessionEvent | null;\n\n constructor(code: string, message: string, event: SessionEvent | null = null) {\n super(message);\n this.name = \"OpenGeniChatError\";\n this.code = code;\n this.event = event;\n }\n}\n","import type { SessionEvent } from \"../types\";\nimport { OpenGeniChatError, type ChatChunk, type ChatPending, type ChatReply } from \"./types\";\n\n/**\n * Event folding shared by `send`, `stream`, and every protocol adapter.\n *\n * One fold covers one logical turn: text deltas accumulate into message\n * segments (a tool call closes the current segment, the completed event\n * reconciles it), tool call/output pairs become tool chunks, and the turn\n * settles on a terminal event or a human wait. Events that carry a different\n * turn id than the expected one are ignored so a queued follow-up never ends\n * early on the previous turn's settlement.\n */\n\nexport type ChatTurnTerminal = \"completed\" | \"failed\" | \"cancelled\" | \"pending\";\n\nexport type ChatFoldStep = {\n chunks: ChatChunk[];\n terminal: ChatTurnTerminal | null;\n};\n\n/** Incremental replay of unresolved requests, without retaining the event log. */\nexport class ChatPendingFold {\n private readonly requests = new Map<string, { pending: ChatPending; turnId: string | null }>();\n\n push(event: SessionEvent): void {\n const payload = asRecord(event.payload);\n if (event.type === \"session.requiresAction\") {\n for (const [key, request] of this.requests) {\n if (request.pending.kind === \"approval\") this.requests.delete(key);\n }\n for (const approval of Array.isArray(payload.approvals) ? payload.approvals : []) {\n const pending = approvalPending({ approvals: [approval] });\n if (pending) this.put(pending, event.turnId ?? null);\n }\n } else if (event.type === \"session.humanInput.requested\") {\n const pending = humanInputPending(payload);\n if (pending) this.put(pending, event.turnId ?? null);\n } else if (event.type === \"user.approvalDecision\") {\n this.requests.delete(`approval:${payload.approvalId}`);\n } else if (event.type === \"user.humanInputResponse\") {\n this.requests.delete(`human_input:${payload.requestId}`);\n } else if ([\"turn.completed\", \"turn.failed\", \"turn.cancelled\"].includes(event.type)) {\n for (const [key, request] of this.requests) {\n if (request.turnId === null || event.turnId == null || request.turnId === event.turnId) {\n this.requests.delete(key);\n }\n }\n }\n }\n\n pending(now = Date.now()): ChatPending[] {\n return [...this.requests.values()]\n .map((request) => request.pending)\n .filter((pending) => {\n if (pending.kind !== \"human_input\") return true;\n const expiresAt = asRecord(pending.payload).expiresAt;\n return expiresAt == null || (typeof expiresAt === \"string\" && Date.parse(expiresAt) > now);\n });\n }\n\n private put(pending: ChatPending, turnId: string | null): void {\n this.requests.set(`${pending.kind}:${pending.requestId}`, { pending, turnId });\n }\n}\n\ntype Segment = { text: string; open: boolean };\n\nexport class ChatTurnFold {\n readonly events: SessionEvent[] = [];\n turnId: string | null;\n pending: ChatPending | null = null;\n failure: SessionEvent | null = null;\n private readonly segments: Segment[] = [];\n private readonly openTools = new Map<string, string>();\n\n constructor(\n private readonly workspaceId: string,\n private readonly sessionId: string,\n expectedTurnId: string | null,\n ) {\n this.turnId = expectedTurnId;\n }\n\n get text(): string {\n return this.segments\n .map((segment) => segment.text)\n .filter((text) => text.length > 0)\n .join(\"\\n\\n\");\n }\n\n push(event: SessionEvent): ChatFoldStep {\n const eventTurnId = typeof event.turnId === \"string\" ? event.turnId : null;\n if (this.turnId && eventTurnId && eventTurnId !== this.turnId) {\n return { chunks: [], terminal: null };\n }\n if (!this.turnId && eventTurnId && isTurnScopedType(event.type)) {\n this.turnId = eventTurnId;\n }\n this.events.push(event);\n const payload = asRecord(event.payload);\n switch (event.type) {\n case \"agent.message.delta\": {\n const text = stringValue(payload.text);\n if (!text) return { chunks: [], terminal: null };\n const open = this.segments.at(-1);\n if (open?.open) {\n open.text += text;\n } else {\n return { chunks: [this.startSegment(text, true)], terminal: null };\n }\n return { chunks: [{ type: \"text\", text }], terminal: null };\n }\n case \"agent.message.completed\": {\n const text = stringValue(payload.text) ?? \"\";\n const target = this.segments.at(-1);\n if (!target || (!target.open && target.text && !text.startsWith(target.text))) {\n if (!text) return { chunks: [], terminal: null };\n return { chunks: [this.startSegment(text, false)], terminal: null };\n }\n target.open = false;\n if (text.length > target.text.length && text.startsWith(target.text)) {\n const remainder = text.slice(target.text.length);\n target.text = text;\n return { chunks: [{ type: \"text\", text: remainder }], terminal: null };\n }\n if (!target.text && text) {\n target.text = text;\n return { chunks: [{ type: \"text\", text }], terminal: null };\n }\n return { chunks: [], terminal: null };\n }\n case \"agent.toolCall.created\": {\n this.closeSegment();\n const name = stringValue(payload.name) ?? \"tool\";\n const callId = stringValue(payload.id);\n if (callId) this.openTools.set(callId, name);\n return {\n chunks: [\n {\n type: \"tool\",\n name,\n status: \"started\",\n ...(callId ? { callId } : {}),\n ...(\"arguments\" in payload ? { input: payload.arguments } : {}),\n },\n ],\n terminal: null,\n };\n }\n case \"agent.toolCall.output\": {\n const callId = stringValue(payload.id);\n const name = (callId ? this.openTools.get(callId) : undefined) ?? \"tool\";\n if (callId) this.openTools.delete(callId);\n return {\n chunks: [\n {\n type: \"tool\",\n name,\n status: isErrorOutput(payload) ? \"failed\" : \"completed\",\n ...(callId ? { callId } : {}),\n },\n ],\n terminal: null,\n };\n }\n case \"session.requiresAction\": {\n const pending = approvalPending(payload);\n if (!pending) return { chunks: [], terminal: null };\n this.closeSegment();\n this.pending = pending;\n return { chunks: [{ type: \"pending\", pending }], terminal: \"pending\" };\n }\n case \"session.humanInput.requested\": {\n const pending = humanInputPending(payload);\n if (!pending) return { chunks: [], terminal: null };\n this.closeSegment();\n this.pending = pending;\n return { chunks: [{ type: \"pending\", pending }], terminal: \"pending\" };\n }\n case \"turn.completed\":\n this.closeSegment();\n return { chunks: [], terminal: \"completed\" };\n case \"turn.failed\":\n this.closeSegment();\n this.failure = event;\n return { chunks: [], terminal: \"failed\" };\n case \"turn.cancelled\":\n this.closeSegment();\n return { chunks: [], terminal: \"cancelled\" };\n default:\n return { chunks: [], terminal: null };\n }\n }\n\n reply(terminal: ChatTurnTerminal): ChatReply {\n const text = this.text;\n return {\n text,\n sessionId: this.sessionId,\n workspaceId: this.workspaceId,\n turnId: this.turnId,\n status:\n terminal === \"pending\" ? \"pending\" : terminal === \"cancelled\" ? \"cancelled\" : \"completed\",\n pending: this.pending,\n events: [...this.events],\n toString: () => text,\n };\n }\n\n /** The error to throw for a `turn.failed` settlement. */\n failureError(): OpenGeniChatError {\n const payload = asRecord(this.failure?.payload);\n const code = stringValue(payload.code) ?? \"turn_failed\";\n const message =\n stringValue(payload.error) ?? stringValue(payload.message) ?? \"The turn failed.\";\n return new OpenGeniChatError(code, message, this.failure);\n }\n\n private closeSegment(): void {\n const open = this.segments.at(-1);\n if (open) open.open = false;\n }\n\n private startSegment(text: string, open: boolean): ChatChunk {\n // Match the separator used by `text` before exposing the next segment to\n // append-only consumers (React and both protocol adapters).\n const separator = this.segments.length > 0 ? \"\\n\\n\" : \"\";\n this.segments.push({ text, open });\n return { type: \"text\", text: separator + text };\n }\n}\n\nfunction isTurnScopedType(type: string): boolean {\n return type.startsWith(\"turn.\") || type.startsWith(\"agent.\") || type === \"user.message\";\n}\n\nexport function approvalPending(payload: Record<string, unknown>): ChatPending | null {\n const approvals = Array.isArray(payload.approvals) ? payload.approvals : [];\n const first = approvals[0];\n if (!first) return null;\n const raw = asRecord(first);\n const rawItem = asRecord(raw.rawItem);\n const requestId =\n stringValue(rawItem.callId) ??\n stringValue(rawItem.id) ??\n stringValue(raw.id) ??\n stringValue(raw.callId);\n if (!requestId) return null;\n return {\n kind: \"approval\",\n requestId,\n name: stringValue(raw.name) ?? stringValue(raw.toolName) ?? stringValue(rawItem.name) ?? null,\n payload: first,\n };\n}\n\nexport function humanInputPending(payload: Record<string, unknown>): ChatPending | null {\n const request = asRecord(payload.request);\n const requestId = stringValue(request.id);\n if (!requestId || !Array.isArray(request.questions)) return null;\n return { kind: \"human_input\", requestId, name: null, payload: payload.request };\n}\n\nexport function asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nexport function stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction isErrorOutput(payload: Record<string, unknown>): boolean {\n if (payload.error === true || payload.failed === true) return true;\n const output = payload.output;\n return (\n !!output && typeof output === \"object\" && (output as { isError?: unknown }).isError === true\n );\n}\n","/**\n * Deterministic chat identities. A conversation id maps to exactly one\n * session id per workspace, so any process can address the same session\n * without storing a mapping, and a double-submitted create collapses through\n * the idempotency key. The optional legacy label argument is retained only to\n * reproduce historical addresses. New chat calls do not use it: authorization\n * is independent of addressing, so collaborators can share a conversation.\n */\n\n/** The end-user label a conversation is namespaced to: the product `source` plus the opaque user id. */\nexport type ChatUserLabel = { source: string; id: string };\n\n/** Fixed RFC 4122 namespace for chat session ids. Never change it. */\nexport const CHAT_SESSION_NAMESPACE = \"7c1e6d3a-5b2f-4e8a-9d4c-0f3b6a8e2c17\";\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/** RFC 4122 version 5 (SHA-1) UUID of `name` inside `namespace`. */\nexport async function uuidV5(name: string, namespace: string): Promise<string> {\n const namespaceBytes = parseUuid(namespace);\n const nameBytes = new TextEncoder().encode(name);\n const input = new Uint8Array(namespaceBytes.length + nameBytes.length);\n input.set(namespaceBytes, 0);\n input.set(nameBytes, namespaceBytes.length);\n const digest = new Uint8Array(await crypto.subtle.digest(\"SHA-1\", input)).slice(0, 16);\n digest[6] = ((digest[6] ?? 0) & 0x0f) | 0x50;\n digest[8] = ((digest[8] ?? 0) & 0x3f) | 0x80;\n return formatUuid(digest);\n}\n\n/**\n * The session id of `conversation` in `workspaceId`: RFC 4122 v5 of the JSON\n * tuple `[workspaceId, conversation]`, or `[workspaceId, source, id, conversation]`\n * when the conversation belongs to an end user. JSON encoding keeps the tuple\n * unambiguous: an id containing `:` or any other delimiter can never make two\n * different (user, conversation) pairs share a session.\n */\nexport async function chatSessionId(\n workspaceId: string,\n conversation: string,\n user?: ChatUserLabel | undefined,\n): Promise<string> {\n return await uuidV5(chatIdentityName(workspaceId, conversation, user), CHAT_SESSION_NAMESPACE);\n}\n\n/** The exact v5 name behind {@link chatSessionId}; exported for tests and audits. */\nexport function chatIdentityName(\n workspaceId: string,\n conversation: string,\n user?: ChatUserLabel | undefined,\n): string {\n return JSON.stringify(\n user ? [workspaceId, user.source, user.id, conversation] : [workspaceId, conversation],\n );\n}\n\n/**\n * The create idempotency key for a chat session: `chat:<sessionId>`. The\n * session id already encodes the workspace, user label, and conversation as an\n * unambiguous tuple, so the key inherits that and stays bounded.\n */\nexport function chatIdempotencyKey(sessionId: string): string {\n return `chat:${sessionId}`;\n}\n\nexport function isUuid(value: string): boolean {\n return UUID_PATTERN.test(value);\n}\n\nfunction parseUuid(value: string): Uint8Array {\n if (!UUID_PATTERN.test(value)) {\n throw new TypeError(`Invalid UUID namespace: ${value}`);\n }\n const hex = value.replace(/-/g, \"\");\n const bytes = new Uint8Array(16);\n for (let index = 0; index < 16; index += 1) {\n bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);\n }\n return bytes;\n}\n\nfunction formatUuid(bytes: Uint8Array): string {\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\n}\n","import { OpenGeniEmbeddingClient as OpenGeniClient } from \"../embedding-client\";\nimport { OpenGeniApiError } from \"../errors\";\nimport type { CreateSessionRequest, Session, SessionEvent } from \"../types\";\nimport { ChatPendingFold, ChatTurnFold, asRecord, stringValue } from \"./fold\";\nimport { chatIdempotencyKey, chatSessionId } from \"./ids\";\nimport {\n OpenGeniChatError,\n type ChatChunk,\n type ChatImportedMessage,\n type ChatMessage,\n type ChatOptions,\n type ChatReply,\n type ChatRespondInput,\n type ChatSendOptions,\n type ChatSessionListOptions,\n type ChatSnapshot,\n type ChatTarget,\n type OpenGeniOptions,\n} from \"./types\";\n\nexport const DEFAULT_OPENGENI_BASE_URL = \"https://app.opengeni.ai\";\nexport const DEFAULT_CHAT_SOURCE = \"app\";\n\ntype SubmittedTurn = { after: number; turnId: string | null };\n\ntype BuildCreate = (\n text: string,\n importedHistory: ChatImportedMessage[] | undefined,\n) => CreateSessionRequest;\n\ntype ChatInit = {\n workspaceId: string;\n sessionId: string;\n conversation: string | null;\n session: Session | null;\n buildCreate: BuildCreate | null;\n};\n\n/** Upper bound on the `modelContext` built from `importedHistory`, header included. */\nexport const IMPORTED_HISTORY_MAX_CHARS = 30_000;\nconst IMPORTED_HISTORY_HEADER = \"Earlier conversation imported from the product, oldest first:\";\nconst IMPORTED_HISTORY_ROLES: ReadonlySet<string> = new Set([\"user\", \"assistant\", \"system\"]);\n\n/**\n * One-option-object entry point for products that already have a chat. Wraps\n * `OpenGeniClient` (exposed as `client`) with tenant workspaces, deterministic\n * conversation sessions, and text-first replies.\n */\nexport class OpenGeni {\n readonly client: OpenGeniClient;\n readonly organizationId: string;\n readonly source: string;\n readonly sessions: {\n /** Sessions visible to the selected canonical user, or explicit service caller. */\n list: (options: ChatSessionListOptions) => Promise<Session[]>;\n };\n private readonly workspaceName: ((tenant: string) => string) | undefined;\n private readonly workspaces = new Map<string, Promise<string>>();\n\n constructor(options: OpenGeniOptions) {\n if (!options.apiKey) throw new TypeError(\"OpenGeni requires an apiKey.\");\n if (!options.organizationId) throw new TypeError(\"OpenGeni requires an organizationId.\");\n this.client = new OpenGeniClient({\n baseUrl: options.baseUrl ?? DEFAULT_OPENGENI_BASE_URL,\n apiKey: options.apiKey,\n ...(options.fetch ? { fetch: options.fetch } : {}),\n });\n this.organizationId = options.organizationId;\n this.source = options.source ?? DEFAULT_CHAT_SOURCE;\n this.workspaceName = options.workspaceName;\n this.sessions = { list: (listOptions) => this.listSessions(listOptions) };\n }\n\n /** The workspace id for a tenant (created on first use, cached per instance) or an explicit id. */\n async workspaceId(\n target: ChatTarget | { tenant?: string | undefined; workspaceId?: string | undefined },\n ): Promise<string> {\n if (target.workspaceId) return target.workspaceId;\n const tenant = target.tenant;\n if (!tenant) throw new TypeError(\"Pass either tenant or workspaceId.\");\n let pending = this.workspaces.get(tenant);\n if (!pending) {\n pending = this.client\n .ensureWorkspace({\n accountId: this.organizationId,\n externalSource: this.source,\n externalId: tenant,\n name: this.workspaceName?.(tenant) ?? tenant,\n })\n .then((response) => response.workspace.id);\n pending.catch(() => {\n this.workspaces.delete(tenant);\n });\n this.workspaces.set(tenant, pending);\n }\n return await pending;\n }\n\n /**\n * Address one conversation; the session is created lazily on the first send.\n * Identity selects authority, not the conversation address. Workspace\n * membership must be provisioned by the host's explicit onboarding flow.\n * Legacy user-namespaced conversations remain accessible by their session ID.\n */\n async chat(options: ChatOptions): Promise<Chat> {\n if (!options.conversation) throw new TypeError(\"chat() requires a conversation id.\");\n const agentAccess = options.agentAccess ?? \"session\";\n const memoryScope =\n options.memory === false\n ? \"off\"\n : options.memory === undefined\n ? agentAccess === \"session\"\n ? \"off\"\n : agentAccess\n : options.memory;\n if (memoryScope === \"user\" && !options.user) {\n throw new OpenGeniChatError(\n \"memory_scope_requires_user\",\n 'memory: \"user\" requires an authenticated product user.',\n );\n }\n const client = options.user\n ? this.client.asUser(options.user, { source: this.source })\n : this.client;\n const workspaceId = await this.workspaceId(options);\n const sessionId = options.sessionId ?? (await chatSessionId(workspaceId, options.conversation));\n const session = await this.findSession(client, workspaceId, sessionId);\n const buildCreate: BuildCreate = (text, importedHistory) => {\n const context =\n options.create?.modelContext === undefined && importedHistory\n ? formatImportedHistory(importedHistory)\n : undefined;\n return {\n agentAccess,\n memoryScope,\n ...(options.model !== undefined ? { model: options.model } : {}),\n ...(options.instructions !== undefined ? { instructions: options.instructions } : {}),\n ...(options.skills !== undefined ? { skills: options.skills } : {}),\n ...(options.tools !== undefined ? { tools: options.tools } : {}),\n ...(context !== undefined ? { modelContext: context } : {}),\n ...(options.create ?? {}),\n initialMessage: text,\n requestedSessionId: sessionId,\n idempotencyKey: chatIdempotencyKey(sessionId),\n };\n };\n return new Chat(client, {\n workspaceId,\n sessionId,\n conversation: options.conversation,\n session,\n buildCreate,\n });\n }\n\n /**\n * Address an existing session with native API authorization. The same shared\n * session can be opened by different authorized users. Pass null only for an\n * explicitly service-owned operation; the API still enforces service access.\n */\n async chatBySessionId(target: {\n workspaceId: string;\n sessionId: string;\n user: string | null;\n }): Promise<Chat> {\n const client =\n target.user !== null ? this.client.asUser(target.user, { source: this.source }) : this.client;\n const session = await client.getSession(target.workspaceId, target.sessionId);\n return new Chat(client, {\n workspaceId: target.workspaceId,\n sessionId: target.sessionId,\n conversation: null,\n session,\n buildCreate: null,\n });\n }\n\n private async findSession(\n client: OpenGeniClient,\n workspaceId: string,\n sessionId: string,\n ): Promise<Session | null> {\n try {\n return await client.getSession(workspaceId, sessionId);\n } catch (error) {\n if (error instanceof OpenGeniApiError && error.status === 404) return null;\n throw error;\n }\n }\n\n private async listSessions(options: ChatSessionListOptions): Promise<Session[]> {\n const workspaceId = await this.workspaceId(options);\n const client = options.user\n ? this.client.asUser(options.user, { source: this.source })\n : this.client;\n return await client.requestJson<Session[]>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/sessions`,\n undefined,\n {\n ...(options.limit !== undefined ? { limit: String(options.limit) } : {}),\n },\n );\n }\n}\n\n/** One conversation bound to one deterministic session. */\nexport class Chat {\n readonly workspaceId: string;\n readonly sessionId: string;\n /** The conversation id this chat was opened with; null when addressed by session id. */\n readonly conversation: string | null;\n private session: Session | null;\n private readonly buildCreate: BuildCreate | null;\n private pendingTurnId: string | null = null;\n\n constructor(\n private readonly client: OpenGeniClient,\n init: ChatInit,\n ) {\n this.workspaceId = init.workspaceId;\n this.sessionId = init.sessionId;\n this.conversation = init.conversation;\n this.session = init.session;\n this.buildCreate = init.buildCreate;\n }\n\n /** True once the session exists on the server. */\n get created(): boolean {\n return this.session !== null;\n }\n\n /** Send a message and wait for the agent's reply text. */\n async send(text: string, options: ChatSendOptions = {}): Promise<ChatReply> {\n return await settle(this.stream(text, options));\n }\n\n /** Send a message and observe the reply as it streams. Ends with a `done` chunk. */\n async *stream(\n text: string,\n options: ChatSendOptions = {},\n ): AsyncGenerator<ChatChunk, void, void> {\n const submitted = options.steer\n ? await this.submitSteer(text, options.importedHistory)\n : await this.submit(text, options.importedHistory);\n yield* this.streamTurn(submitted, options.signal);\n }\n\n /** Supersede the current inference with this message and wait for the reply. */\n async steer(text: string, options: Omit<ChatSendOptions, \"steer\"> = {}): Promise<ChatReply> {\n return await this.send(text, { ...options, steer: true });\n }\n\n /** Answer a pending approval or human-input request, then wait for the reply. */\n async respond(\n input: ChatRespondInput,\n options: Omit<ChatSendOptions, \"steer\"> = {},\n ): Promise<ChatReply> {\n return await settle(this.respondStream(input, options));\n }\n\n async *respondStream(\n input: ChatRespondInput,\n options: Omit<ChatSendOptions, \"steer\"> = {},\n ): AsyncGenerator<ChatChunk, void, void> {\n const submitted = await this.submitResponse(input);\n yield* this.streamTurn(submitted, options.signal);\n }\n\n /** User and assistant text in order, from the durable event log. */\n async history(): Promise<ChatMessage[]> {\n return (await this.snapshot()).messages;\n }\n\n /** Restore history and pending decisions from the complete ordered timeline. */\n async snapshot(): Promise<ChatSnapshot> {\n if (!this.session) return { messages: [], pending: [], status: null };\n const pending = new ChatPendingFold();\n let status = this.session.status;\n const messages: ChatMessage[] = [];\n let lastAssistantTurn: string | null = null;\n let after = 0;\n while (true) {\n const result = await this.client.listEventPage(this.workspaceId, this.sessionId, {\n after,\n includeTypes: [\n \"user.message\",\n \"agent.message.completed\",\n \"session.requiresAction\",\n \"session.humanInput.requested\",\n \"user.approvalDecision\",\n \"user.humanInputResponse\",\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"session.status.changed\",\n ],\n });\n for (const event of result.events) {\n pending.push(event);\n if (event.type === \"session.status.changed\") {\n const next = asRecord(event.payload).status;\n if (typeof next === \"string\") status = next as Session[\"status\"];\n }\n const text = stringValue(asRecord(event.payload).text);\n if (!text) continue;\n if (event.type === \"user.message\") {\n messages.push({ role: \"user\", text, sequence: event.sequence });\n lastAssistantTurn = null;\n continue;\n }\n if (event.type !== \"agent.message.completed\") continue;\n const turnId = typeof event.turnId === \"string\" ? event.turnId : null;\n const last = messages.at(-1);\n if (\n last?.role === \"assistant\" &&\n turnId !== null &&\n turnId === lastAssistantTurn &&\n text.startsWith(last.text)\n ) {\n last.text = text;\n last.sequence = event.sequence;\n continue;\n }\n messages.push({ role: \"assistant\", text, sequence: event.sequence });\n lastAssistantTurn = turnId;\n }\n if (!result.hasMore || result.nextAfter === null || result.events.length === 0) break;\n if (result.nextAfter <= after) {\n throw new OpenGeniChatError(\n \"history_cursor_stalled\",\n \"History pagination did not advance.\",\n );\n }\n after = result.nextAfter;\n }\n return { messages, pending: pending.pending(), status };\n }\n\n private async submit(\n text: string,\n importedHistory: ChatImportedMessage[] | undefined,\n ): Promise<SubmittedTurn> {\n if (!this.session) {\n if (!this.buildCreate) {\n throw new OpenGeniChatError(\"session_missing\", \"This session no longer exists.\");\n }\n const created = await this.client.createSession(\n this.workspaceId,\n this.buildCreate(text, importedHistory),\n );\n this.session = created;\n if (created.initialMessage === text) {\n return { after: 0, turnId: created.initialTurnId };\n }\n // The idempotent create replayed an earlier session; deliver this message too.\n }\n const event = await this.client.sendMessage(this.workspaceId, this.sessionId, text);\n return submittedFrom(event);\n }\n\n private async submitSteer(\n text: string,\n importedHistory: ChatImportedMessage[] | undefined,\n ): Promise<SubmittedTurn> {\n if (!this.session) return await this.submit(text, importedHistory);\n const result = await this.client.steerMessage(this.workspaceId, this.sessionId, text);\n return { after: result.accepted.sequence, turnId: result.turn.id ?? null };\n }\n\n private async submitResponse(input: ChatRespondInput): Promise<SubmittedTurn> {\n let event: SessionEvent;\n if (\"decision\" in input) {\n event = await this.client.sendApprovalDecision(this.workspaceId, this.sessionId, {\n approvalId: input.requestId,\n decision: input.decision,\n ...(input.message !== undefined ? { message: input.message } : {}),\n });\n } else if (\"answers\" in input) {\n event = await this.client.submitHumanInputResponse(\n this.workspaceId,\n this.sessionId,\n input.requestId,\n { outcome: \"answered\", answers: input.answers },\n );\n } else {\n event = await this.client.submitHumanInputResponse(\n this.workspaceId,\n this.sessionId,\n input.requestId,\n { outcome: \"skipped\" },\n );\n }\n const submitted = submittedFrom(event);\n return { ...submitted, turnId: submitted.turnId ?? this.pendingTurnId };\n }\n\n private async *streamTurn(\n submitted: SubmittedTurn,\n signal: AbortSignal | undefined,\n ): AsyncGenerator<ChatChunk, void, void> {\n const upstream = new AbortController();\n const onAbort = (): void => upstream.abort();\n if (signal?.aborted) upstream.abort();\n else signal?.addEventListener(\"abort\", onAbort, { once: true });\n const fold = new ChatTurnFold(this.workspaceId, this.sessionId, submitted.turnId);\n try {\n for await (const event of this.client.streamEvents(this.workspaceId, this.sessionId, {\n after: submitted.after,\n signal: upstream.signal,\n })) {\n const step = fold.push(event);\n for (const chunk of step.chunks) yield chunk;\n // Resuming one member of a parallel interruption group re-emits the\n // waiting status, but existing human-input requests are not recreated.\n // Recover the remaining decision instead of waiting forever for new text.\n if (\n !step.terminal &&\n event.type === \"session.status.changed\" &&\n asRecord(event.payload).status === \"requires_action\" &&\n (event.turnId == null || fold.turnId === null || event.turnId === fold.turnId)\n ) {\n const pending = (await this.snapshot()).pending[0];\n if (pending) {\n fold.pending = pending;\n this.pendingTurnId = fold.turnId;\n yield { type: \"pending\", pending };\n yield { type: \"done\", reply: fold.reply(\"pending\") };\n return;\n }\n }\n if (!step.terminal) continue;\n if (step.terminal === \"failed\") throw fold.failureError();\n this.pendingTurnId = step.terminal === \"pending\" ? fold.turnId : null;\n yield { type: \"done\", reply: fold.reply(step.terminal) };\n return;\n }\n if (signal?.aborted) throw abortError();\n throw new OpenGeniChatError(\n \"stream_ended\",\n \"The event stream ended before the turn settled.\",\n );\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n upstream.abort();\n }\n }\n}\n\nasync function settle(chunks: AsyncIterable<ChatChunk>): Promise<ChatReply> {\n for await (const chunk of chunks) {\n if (chunk.type === \"done\") return chunk.reply;\n }\n throw new OpenGeniChatError(\"stream_ended\", \"The event stream ended before the turn settled.\");\n}\n\nfunction submittedFrom(event: SessionEvent): SubmittedTurn {\n return {\n after: event.sequence,\n turnId: typeof event.turnId === \"string\" ? event.turnId : null,\n };\n}\n\n/**\n * `modelContext` for imported history: a header line plus one `role: text`\n * line per message, oldest first, trimmed from the oldest end to\n * {@link IMPORTED_HISTORY_MAX_CHARS}. Undefined when nothing usable remains.\n */\nexport function formatImportedHistory(messages: ChatImportedMessage[]): string | undefined {\n const lines = messages\n .filter(\n (message) =>\n IMPORTED_HISTORY_ROLES.has(message.role) &&\n typeof message.text === \"string\" &&\n message.text.trim().length > 0,\n )\n .map((message) => `${message.role}: ${message.text}`);\n if (lines.length === 0) return undefined;\n let budget = IMPORTED_HISTORY_MAX_CHARS - IMPORTED_HISTORY_HEADER.length;\n const kept: string[] = [];\n for (let index = lines.length - 1; index >= 0; index -= 1) {\n const line = lines[index]!;\n const cost = line.length + 1;\n if (cost <= budget) {\n kept.unshift(line);\n budget -= cost;\n continue;\n }\n // The newest line alone overflows: keep its tail so the most recent text survives.\n if (kept.length === 0 && budget > 1) kept.unshift(line.slice(line.length - (budget - 1)));\n break;\n }\n if (kept.length === 0) return undefined;\n return `${IMPORTED_HISTORY_HEADER}\\n${kept.join(\"\\n\")}`;\n}\n\nfunction abortError(): Error {\n const error = new Error(\"The chat request was aborted.\");\n error.name = \"AbortError\";\n return error;\n}\n","import { OpenGeniApiError } from \"../errors\";\nimport type { OpenGeni } from \"./opengeni\";\nimport { OpenGeniChatError, type ChatImportedMessage, type ChatOptions } from \"./types\";\n\n/** Internal HTTP plumbing shared by the native handler and the protocol adapters. */\n\n/**\n * Header a client uses to name the conversation it is on. Every handler reads\n * the client conversation as: the host's resolution, else this header, else\n * the protocol's own field.\n */\nexport const CHAT_CONVERSATION_HEADER = \"x-opengeni-conversation\";\n\nconst CHAT_ERROR_STATUS: Readonly<Record<string, number>> = {\n memory_scope_requires_user: 400,\n conversation_not_authorized: 403,\n conversation_mismatch: 409,\n};\n\n/** What the host's auth hook returns: identity from the host, conversation optional per protocol. */\nexport type ChatResolution = Omit<ChatOptions, \"conversation\"> & {\n conversation?: string | undefined;\n};\n\n/**\n * The host's authentication hook. It receives the raw request and returns the\n * tenant/user/conversation the caller is allowed to use, or a `Response` to\n * reject the request. Never derive tenant or user from the request body.\n */\nexport type ChatResolve = (\n request: Request,\n) => Promise<ChatResolution | Response> | ChatResolution | Response;\n\nexport type ChatErrorSummary = { status: number; code: string; message: string };\n\nexport function jsonResponse(body: unknown, status = 200, headers: HeadersInit = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json; charset=utf-8\", ...headers },\n });\n}\n\nexport function errorResponse(status: number, message: string, code: string): Response {\n return jsonResponse(\n { error: { message, code, type: status >= 500 ? \"server_error\" : \"invalid_request_error\" } },\n status,\n );\n}\n\nexport async function readJsonObject(request: Request): Promise<Record<string, unknown> | null> {\n try {\n const parsed: unknown = await request.json();\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n}\n\nexport async function resolveChatRequest(\n request: Request,\n resolve: ChatResolve,\n): Promise<{ resolution: ChatResolution; response?: undefined } | { response: Response }> {\n const resolved = await resolve(request);\n if (resolved instanceof Response) return { response: resolved };\n return { resolution: resolved };\n}\n\n/** The client-supplied conversation: the header, else the protocol's own field. */\nexport function clientConversation(request: Request, protocolField: unknown): string | undefined {\n const header = request.headers.get(CHAT_CONVERSATION_HEADER);\n if (header) return header;\n return typeof protocolField === \"string\" && protocolField ? protocolField : undefined;\n}\n\n/**\n * Open a chat from a resolution plus the conversation the client supplied.\n * The host names the conversation, or the host names the user and the client\n * conversation id is namespaced to that user; anything else is a 400, because\n * an unscoped client id could address any conversation in the workspace.\n */\nexport async function openResolvedChat(\n og: OpenGeni,\n resolution: ChatResolution,\n clientConversationId: string | undefined,\n): Promise<\n { chat: Awaited<ReturnType<OpenGeni[\"chat\"]>>; response?: undefined } | { response: Response }\n> {\n if (!resolution.conversation && !resolution.user) {\n return {\n response: errorResponse(\n 400,\n \"Return a conversation from resolve, or a user so client conversation ids are scoped to that user.\",\n \"conversation_required\",\n ),\n };\n }\n const conversationId = resolution.conversation ?? clientConversationId;\n if (!conversationId) {\n return {\n response: errorResponse(\n 400,\n `A conversation id is required: send the ${CHAT_CONVERSATION_HEADER} header or the protocol's conversation field.`,\n \"conversation_required\",\n ),\n };\n }\n try {\n const chat = await og.chat({ ...resolution, conversation: conversationId } as ChatOptions);\n return { chat };\n } catch (error) {\n const summary = chatErrorSummary(error);\n return { response: errorResponse(summary.status, summary.message, summary.code) };\n }\n}\n\nexport function chatErrorSummary(error: unknown): ChatErrorSummary {\n if (error instanceof OpenGeniChatError) {\n const status = CHAT_ERROR_STATUS[error.code] ?? 502;\n return { status, code: error.code, message: error.message };\n }\n if (error instanceof OpenGeniApiError) {\n return {\n status: error.status >= 500 ? 502 : error.status,\n code: error.code ?? \"opengeni_api_error\",\n message: error.message,\n };\n }\n if (error instanceof Error && error.name === \"AbortError\") {\n return { status: 499, code: \"aborted\", message: \"The chat request was aborted.\" };\n }\n return { status: 500, code: \"internal_error\", message: \"Chat request failed.\" };\n}\n\nexport function sseHeaders(extra: Record<string, string> = {}): Record<string, string> {\n return {\n \"Content-Type\": \"text/event-stream; charset=utf-8\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n ...extra,\n };\n}\n\nexport function sseLine(data: string, event?: string): string {\n return `${event ? `event: ${event}\\n` : \"\"}data: ${data}\\n\\n`;\n}\n\n/**\n * Pull-based text-to-bytes stream over already-formatted SSE blocks. Upstream\n * consumption follows downstream demand; cancelling fires `onCancel` so the\n * producer can abort its OpenGeni stream.\n */\nexport function sseByteStream(\n blocks: AsyncIterable<string>,\n onCancel?: () => void,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const iterator = blocks[Symbol.asyncIterator]();\n let cancelled = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n const result = await iterator.next();\n if (cancelled) return;\n if (result.done) {\n controller.close();\n return;\n }\n controller.enqueue(encoder.encode(result.value));\n },\n cancel: () => {\n cancelled = true;\n onCancel?.();\n void Promise.resolve(iterator.return?.(undefined)).then(\n () => undefined,\n () => undefined,\n );\n },\n });\n}\n\n/** Text from an OpenAI-style message content: a string or `[{ type, text }]` parts. */\nexport function messageContentText(content: unknown, partTypes: string[]): string | null {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return null;\n const texts = content\n .map((part) => {\n if (!part || typeof part !== \"object\") return null;\n const record = part as Record<string, unknown>;\n return partTypes.includes(String(record.type)) && typeof record.text === \"string\"\n ? record.text\n : null;\n })\n .filter((text): text is string => text !== null);\n return texts.length > 0 ? texts.join(\"\\n\") : null;\n}\n\nfunction lastUserMessageIndex(messages: unknown[]): number {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message && typeof message === \"object\" && (message as { role?: unknown }).role === \"user\") {\n return index;\n }\n }\n return -1;\n}\n\nfunction messageText(\n message: unknown,\n partTypes: string[],\n partsField: \"parts\" | \"content\",\n): string | null {\n if (!message || typeof message !== \"object\") return null;\n const record = message as Record<string, unknown>;\n return (\n messageContentText(record[partsField], partTypes) ??\n messageContentText(record.content, partTypes)\n );\n}\n\n/** The last user-role message's text from an OpenAI/Vercel-style `messages` array. */\nexport function lastUserMessageText(\n messages: unknown,\n partTypes: string[],\n partsField: \"parts\" | \"content\",\n): string | null {\n if (!Array.isArray(messages)) return null;\n const index = lastUserMessageIndex(messages);\n return index < 0 ? null : messageText(messages[index], partTypes, partsField);\n}\n\n/**\n * Every user/assistant/system message before the last user message, as\n * imported history for the first create. Items without a role or text\n * (tool calls, files) are skipped.\n */\nexport function importedHistoryBefore(\n messages: unknown,\n partTypes: string[],\n partsField: \"parts\" | \"content\",\n): ChatImportedMessage[] {\n if (!Array.isArray(messages)) return [];\n const lastUser = lastUserMessageIndex(messages);\n if (lastUser < 0) return [];\n const imported: ChatImportedMessage[] = [];\n for (const message of messages.slice(0, lastUser)) {\n const role = (message as { role?: unknown } | null)?.role;\n if (role !== \"user\" && role !== \"assistant\" && role !== \"system\") continue;\n const text = messageText(message, partTypes, partsField);\n if (text) imported.push({ role, text });\n }\n return imported;\n}\n\nexport function unixSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import {\n chatErrorSummary,\n clientConversation,\n errorResponse,\n importedHistoryBefore,\n jsonResponse,\n lastUserMessageText,\n messageContentText,\n openResolvedChat,\n readJsonObject,\n resolveChatRequest,\n sseByteStream,\n sseHeaders,\n sseLine,\n type ChatResolve,\n} from \"./http\";\nimport { isUuid } from \"./ids\";\nimport type { Chat, OpenGeni } from \"./opengeni\";\nimport { OpenGeniChatError, type ChatChunk, type ChatReply } from \"./types\";\n\n/**\n * OpenAI-compatible adapters over the stable subset of the Chat Completions\n * and Responses wire formats. `model` and `user` in the body are echoed, never\n * trusted: identity comes from the host's `resolve` hook.\n */\n\nconst DEFAULT_MODEL_LABEL = \"opengeni\";\n\ntype ReplyExtension = {\n sessionId: string;\n workspaceId: string;\n turnId: string | null;\n status: ChatReply[\"status\"];\n pending: ChatReply[\"pending\"];\n};\n\nfunction replyExtension(reply: ChatReply): ReplyExtension {\n return {\n sessionId: reply.sessionId,\n workspaceId: reply.workspaceId,\n turnId: reply.turnId,\n status: reply.status,\n pending: reply.pending,\n };\n}\n\nfunction conversationFromBody(body: Record<string, unknown> | null): string | undefined {\n const conversation = body?.conversation;\n if (typeof conversation === \"string\" && conversation) return conversation;\n if (conversation && typeof conversation === \"object\") {\n const id = (conversation as { id?: unknown }).id;\n if (typeof id === \"string\" && id) return id;\n }\n return undefined;\n}\n\nfunction modelLabel(body: Record<string, unknown> | null): string {\n return typeof body?.model === \"string\" && body.model ? body.model : DEFAULT_MODEL_LABEL;\n}\n\nfunction wantsStream(body: Record<string, unknown> | null): boolean {\n return body?.stream === true;\n}\n\n// --- Chat Completions ---------------------------------------------------------\n\nconst CHAT_COMPLETION_PART_TYPES = [\"text\", \"input_text\"];\n\nfunction chatCompletionChunk(\n sessionId: string,\n model: string,\n created: number,\n delta: Record<string, unknown>,\n finishReason: \"stop\" | null,\n extension?: ReplyExtension,\n): string {\n return sseLine(\n JSON.stringify({\n id: `chatcmpl-${sessionId}`,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta, finish_reason: finishReason }],\n ...(extension ? { opengeni: extension } : {}),\n }),\n );\n}\n\nexport async function* chatCompletionBlocks(\n chat: Chat,\n chunks: AsyncIterable<ChatChunk>,\n model: string,\n): AsyncGenerator<string, void, void> {\n const created = Math.floor(Date.now() / 1000);\n yield chatCompletionChunk(\n chat.sessionId,\n model,\n created,\n { role: \"assistant\", content: \"\" },\n null,\n );\n try {\n for await (const chunk of chunks) {\n if (chunk.type === \"text\") {\n yield chatCompletionChunk(chat.sessionId, model, created, { content: chunk.text }, null);\n } else if (chunk.type === \"done\") {\n yield chatCompletionChunk(\n chat.sessionId,\n model,\n created,\n {},\n \"stop\",\n replyExtension(chunk.reply),\n );\n }\n }\n } catch (error) {\n const summary = chatErrorSummary(error);\n yield sseLine(\n JSON.stringify({\n error: { message: summary.message, code: summary.code, type: \"server_error\" },\n }),\n );\n }\n yield sseLine(\"[DONE]\");\n}\n\nexport function chatCompletionObject(reply: ChatReply, model: string): Record<string, unknown> {\n return {\n id: `chatcmpl-${reply.sessionId}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content: reply.text }, finish_reason: \"stop\" },\n ],\n opengeni: replyExtension(reply),\n };\n}\n\n/**\n * `POST /v1/chat/completions` shape: `{ messages, stream?, model?, user?, metadata? }`.\n * Conversation: the host's `resolve`, else the `x-opengeni-conversation` header,\n * else `metadata.conversation_id`; 400 when none. Only the last user message\n * is sent; the messages before it are imported once as context when this\n * request creates the session.\n */\nexport async function handleChatCompletionsRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const prompt =\n lastUserMessageText(body?.messages, CHAT_COMPLETION_PART_TYPES, \"content\")?.trim() ?? \"\";\n if (!prompt) {\n return errorResponse(400, \"The last user message has no text.\", \"message_required\");\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const metadata = body?.metadata;\n const metadataConversation =\n metadata && typeof metadata === \"object\"\n ? (metadata as { conversation_id?: unknown }).conversation_id\n : undefined;\n const opened = await openResolvedChat(\n og,\n resolved.resolution,\n clientConversation(request, metadataConversation),\n );\n if (opened.response) return opened.response;\n const model = modelLabel(body);\n const importedHistory = importedHistoryBefore(\n body?.messages,\n CHAT_COMPLETION_PART_TYPES,\n \"content\",\n );\n if (wantsStream(body)) {\n const chunks = opened.chat.stream(prompt, { signal: request.signal, importedHistory });\n return new Response(sseByteStream(chatCompletionBlocks(opened.chat, chunks, model)), {\n headers: sseHeaders(),\n });\n }\n try {\n const reply = await opened.chat.send(prompt, { signal: request.signal, importedHistory });\n return jsonResponse(chatCompletionObject(reply, model));\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n}\n\n// --- Responses ----------------------------------------------------------------\n\n/** Non-streaming response id; the session id alone addresses the conversation. */\nexport function encodeResponseId(sessionId: string, sequence: number): string {\n return `resp_${sessionId}_${sequence}`;\n}\n\nexport function decodeResponseId(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n // Streams allocate a UUID before the final event sequence is known. Keep\n // accepting existing sequence-based response ids for conversation continuity.\n const match = /^resp_([0-9a-f-]{36})(?:_(\\d+|[0-9a-f-]{36}))?$/i.exec(value);\n const sessionId = match?.[1];\n const suffix = match?.[2];\n if (suffix && !/^\\d+$/.test(suffix) && !isUuid(suffix)) return null;\n return sessionId && isUuid(sessionId) ? sessionId : null;\n}\n\ntype ResponseIdentity = { responseId: string; itemId: string; createdAt: number };\ntype ResponseStatus = \"in_progress\" | \"completed\" | \"incomplete\";\n\nfunction responseOutputItem(itemId: string, status: ResponseStatus, text: string | null) {\n return {\n type: \"message\",\n id: itemId,\n status,\n role: \"assistant\",\n content: text === null ? [] : [{ type: \"output_text\", text, annotations: [] }],\n };\n}\n\nfunction responseObject(\n reply: ChatReply | null,\n chat: Chat,\n model: string,\n status: ResponseStatus,\n previousResponseId: string | null,\n text: string,\n identity?: ResponseIdentity,\n): Record<string, unknown> {\n const sequence = reply?.events.at(-1)?.sequence ?? 0;\n return {\n id: identity?.responseId ?? encodeResponseId(chat.sessionId, sequence),\n object: \"response\",\n created_at: identity?.createdAt ?? Math.floor(Date.now() / 1000),\n status,\n model,\n previous_response_id: previousResponseId,\n output:\n status === \"in_progress\"\n ? []\n : [\n responseOutputItem(\n identity?.itemId ?? `msg_${chat.sessionId}_${sequence}`,\n status,\n text,\n ),\n ],\n output_text: text,\n ...(reply ? { opengeni: replyExtension(reply) } : {}),\n };\n}\n\nexport async function* responsesBlocks(\n chat: Chat,\n chunks: AsyncIterable<ChatChunk>,\n model: string,\n previousResponseId: string | null,\n): AsyncGenerator<string, void, void> {\n let sequenceNumber = 0;\n const requestId = crypto.randomUUID();\n const identity: ResponseIdentity = {\n responseId: `resp_${chat.sessionId}_${requestId}`,\n itemId: `msg_${chat.sessionId}_${requestId}`,\n createdAt: Math.floor(Date.now() / 1000),\n };\n const { itemId } = identity;\n const event = (type: string, data: Record<string, unknown>): string =>\n sseLine(JSON.stringify({ type, sequence_number: sequenceNumber++, ...data }), type);\n const initial = responseObject(\n null,\n chat,\n model,\n \"in_progress\",\n previousResponseId,\n \"\",\n identity,\n );\n yield event(\"response.created\", { response: initial });\n yield event(\"response.in_progress\", { response: initial });\n yield event(\"response.output_item.added\", {\n output_index: 0,\n item: responseOutputItem(itemId, \"in_progress\", null),\n });\n yield event(\"response.content_part.added\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n part: { type: \"output_text\", text: \"\", annotations: [] },\n });\n try {\n for await (const chunk of chunks) {\n if (chunk.type === \"text\") {\n yield event(\"response.output_text.delta\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n delta: chunk.text,\n logprobs: [],\n });\n } else if (chunk.type === \"done\") {\n const status = chunk.reply.status === \"completed\" ? \"completed\" : \"incomplete\";\n const item = responseOutputItem(itemId, status, chunk.reply.text);\n yield event(\"response.output_text.done\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n text: chunk.reply.text,\n logprobs: [],\n });\n yield event(\"response.content_part.done\", {\n item_id: itemId,\n output_index: 0,\n content_index: 0,\n part: item.content[0]!,\n });\n yield event(\"response.output_item.done\", { output_index: 0, item });\n yield event(`response.${status}`, {\n response: responseObject(\n chunk.reply,\n chat,\n model,\n status,\n previousResponseId,\n chunk.reply.text,\n identity,\n ),\n });\n }\n }\n } catch (error) {\n const summary = chatErrorSummary(error);\n yield event(\"error\", { code: summary.code, message: summary.message, param: null });\n }\n}\n\n/** Text of the Responses `input`: a string, or the last user item's `input_text` parts. */\nexport function responsesInputText(input: unknown): string | null {\n if (typeof input === \"string\") return input;\n if (!Array.isArray(input)) return null;\n const fromRole = lastUserMessageText(input, [\"input_text\", \"text\"], \"content\");\n if (fromRole !== null) return fromRole;\n const last = input.at(-1);\n return last && typeof last === \"object\"\n ? messageContentText((last as { content?: unknown }).content, [\"input_text\", \"text\"])\n : null;\n}\n\n/**\n * `POST /v1/responses` shape: `{ input, previous_response_id?, conversation?, stream?, model?, user? }`.\n * Conversation: the host's `resolve`, else the `x-opengeni-conversation`\n * header, else `conversation` / `conversation.id`. A `previous_response_id`\n * may continue the session it encodes only when the host named the user that\n * session belongs to (403 otherwise); when a conversation is named as well,\n * the two must agree (409). 400 when nothing names a conversation. Only the\n * last user item is sent; earlier array items are imported once as context\n * when this request creates the session.\n */\nexport async function handleResponsesRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const prompt = responsesInputText(body?.input)?.trim() ?? \"\";\n if (!prompt) return errorResponse(400, \"The input has no user text.\", \"message_required\");\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const previousResponseId =\n typeof body?.previous_response_id === \"string\" ? body.previous_response_id : null;\n const conversation = clientConversation(request, conversationFromBody(body));\n const previousSessionId = decodeResponseId(previousResponseId);\n const namedConversation =\n resolved.resolution.conversation ?? (resolved.resolution.user ? conversation : undefined);\n let chat: Chat;\n if (previousSessionId && !namedConversation) {\n if (!resolved.resolution.user) {\n return errorResponse(\n 400,\n \"Return a conversation from resolve, or a user so client conversation ids are scoped to that user.\",\n \"conversation_required\",\n );\n }\n try {\n const workspaceId = await og.workspaceId(resolved.resolution);\n chat = await og.chatBySessionId({\n workspaceId,\n sessionId: previousSessionId,\n user: resolved.resolution.user,\n });\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n } else {\n const opened = await openResolvedChat(og, resolved.resolution, conversation);\n if (opened.response) return opened.response;\n chat = opened.chat;\n if (previousSessionId && previousSessionId !== chat.sessionId) {\n const summary = chatErrorSummary(\n new OpenGeniChatError(\n \"conversation_mismatch\",\n \"previous_response_id belongs to a different conversation than the one named for this request.\",\n ),\n );\n return errorResponse(summary.status, summary.message, summary.code);\n }\n }\n const model = modelLabel(body);\n const importedHistory = importedHistoryBefore(\n body?.input,\n [\"input_text\", \"text\", \"output_text\"],\n \"content\",\n );\n if (wantsStream(body)) {\n const chunks = chat.stream(prompt, { signal: request.signal, importedHistory });\n return new Response(sseByteStream(responsesBlocks(chat, chunks, model, previousResponseId)), {\n headers: sseHeaders(),\n });\n }\n try {\n const reply = await chat.send(prompt, { signal: request.signal, importedHistory });\n return jsonResponse(\n responseObject(\n reply,\n chat,\n model,\n reply.status === \"completed\" ? \"completed\" : \"incomplete\",\n previousResponseId,\n reply.text,\n ),\n );\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n}\n","import { asRecord } from \"./fold\";\nimport {\n chatErrorSummary,\n clientConversation,\n errorResponse,\n importedHistoryBefore,\n lastUserMessageText,\n openResolvedChat,\n readJsonObject,\n resolveChatRequest,\n sseByteStream,\n sseHeaders,\n sseLine,\n type ChatResolve,\n} from \"./http\";\nimport type { OpenGeni } from \"./opengeni\";\nimport type { ChatChunk, ChatPending } from \"./types\";\n\n/**\n * Vercel AI SDK UI message stream (protocol v1, as consumed by `useChat` with\n * the default transport). Parts are `data: <json>` SSE lines terminated by\n * `data: [DONE]`, under the `x-vercel-ai-ui-message-stream: v1` header.\n */\n\nexport const UI_MESSAGE_STREAM_HEADER = \"x-vercel-ai-ui-message-stream\";\nexport const UI_MESSAGE_STREAM_VERSION = \"v1\";\n\nexport type UIMessageStreamOptions = {\n /** Assistant message id announced in the `start` part. Defaults to a random UUID. */\n messageId?: string | undefined;\n};\n\n/** Protocol parts for one reply, in order. */\nexport async function* uiMessageStreamParts(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions = {},\n): AsyncGenerator<Record<string, unknown>, void, void> {\n const messageId = options.messageId ?? crypto.randomUUID();\n const textId = `text_${messageId}`;\n let textOpen = false;\n const closeText = (): Record<string, unknown>[] => {\n if (!textOpen) return [];\n textOpen = false;\n return [{ type: \"text-end\", id: textId }];\n };\n yield { type: \"start\", messageId };\n yield { type: \"start-step\" };\n try {\n for await (const chunk of chunks) {\n switch (chunk.type) {\n case \"text\":\n if (!textOpen) {\n textOpen = true;\n yield { type: \"text-start\", id: textId };\n }\n yield { type: \"text-delta\", id: textId, delta: chunk.text };\n break;\n case \"tool\": {\n yield* closeText();\n const toolCallId = chunk.callId ?? `call_${crypto.randomUUID()}`;\n if (chunk.status === \"started\") {\n yield { type: \"tool-input-start\", toolCallId, toolName: chunk.name };\n yield {\n type: \"tool-input-available\",\n toolCallId,\n toolName: chunk.name,\n input: chunk.input ?? {},\n };\n } else {\n yield { type: \"tool-output-available\", toolCallId, output: { status: chunk.status } };\n }\n break;\n }\n case \"pending\":\n yield* closeText();\n yield* pendingParts(chunk.pending);\n break;\n case \"done\":\n yield* closeText();\n break;\n }\n }\n yield* closeText();\n yield { type: \"finish-step\" };\n yield { type: \"finish\" };\n } catch (error) {\n yield* closeText();\n yield { type: \"error\", errorText: chatErrorSummary(error).message };\n }\n}\n\nfunction* pendingParts(pending: ChatPending): Generator<Record<string, unknown>> {\n if (pending.kind === \"approval\") {\n const raw = asRecord(pending.payload);\n const rawItem = asRecord(raw.rawItem);\n yield {\n type: \"tool-input-available\",\n toolCallId: pending.requestId,\n toolName: pending.name ?? \"tool\",\n input: raw.arguments ?? rawItem.arguments ?? {},\n };\n yield {\n type: \"tool-approval-request\",\n toolCallId: pending.requestId,\n approvalId: pending.requestId,\n };\n return;\n }\n yield { type: \"data-opengeni-pending\", data: pending };\n}\n\nexport async function* uiMessageStreamBlocks(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions = {},\n): AsyncGenerator<string, void, void> {\n for await (const part of uiMessageStreamParts(chunks, options)) {\n yield sseLine(JSON.stringify(part));\n }\n yield sseLine(\"[DONE]\");\n}\n\nexport function chatChunksToUIMessageStream(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions & { onCancel?: (() => void) | undefined } = {},\n): ReadableStream<Uint8Array> {\n return sseByteStream(uiMessageStreamBlocks(chunks, options), options.onCancel);\n}\n\nexport function uiMessageStreamResponse(\n chunks: AsyncIterable<ChatChunk>,\n options: UIMessageStreamOptions = {},\n): Response {\n return new Response(chatChunksToUIMessageStream(chunks, options), {\n headers: sseHeaders({ [UI_MESSAGE_STREAM_HEADER]: UI_MESSAGE_STREAM_VERSION }),\n });\n}\n\n/** Text of the last user `UIMessage` (`parts` of type `text`, joined). */\nexport function lastUIMessageText(messages: unknown): string | null {\n return lastUserMessageText(messages, [\"text\"], \"parts\");\n}\n\n/**\n * `useChat` request handler: body `{ id, messages, trigger, messageId }`.\n * Conversation: the host's `resolve`, else the `x-opengeni-conversation`\n * header, else the chat `id`. Only the last user message is sent; the\n * messages before it are imported once as context when this request creates\n * the session. `regenerate-message` steers instead of queueing.\n */\nexport async function handleVercelChatRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const prompt = lastUIMessageText(body?.messages)?.trim() ?? \"\";\n if (!prompt) {\n return errorResponse(400, \"The last user message has no text.\", \"message_required\");\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(\n og,\n resolved.resolution,\n clientConversation(request, body?.id),\n );\n if (opened.response) return opened.response;\n const steer = body?.trigger === \"regenerate-message\";\n const importedHistory = importedHistoryBefore(body?.messages, [\"text\"], \"parts\");\n return uiMessageStreamResponse(\n opened.chat.stream(prompt, { signal: request.signal, steer, importedHistory }),\n );\n}\n","import { parseSseStream } from \"../sse\";\nimport type { HumanInputAnswer } from \"../types\";\nimport {\n chatErrorSummary,\n clientConversation,\n errorResponse,\n jsonResponse,\n openResolvedChat,\n readJsonObject,\n resolveChatRequest,\n sseByteStream,\n sseHeaders,\n sseLine,\n type ChatResolve,\n} from \"./http\";\nimport { handleChatCompletionsRequest, handleResponsesRequest } from \"./openai\";\nimport type { OpenGeni } from \"./opengeni\";\nimport { OpenGeniChatError, type ChatChunk, type ChatRespondInput } from \"./types\";\nimport { handleVercelChatRequest } from \"./vercel\";\n\nexport { CHAT_CONVERSATION_HEADER, type ChatResolution, type ChatResolve } from \"./http\";\n\nexport type ChatHandlerFormat = \"native\" | \"vercel\" | \"openai-chat\" | \"openai-responses\";\n\nexport type ChatHandlerOptions = {\n /** Mandatory host auth hook; see {@link ChatResolve}. */\n resolve: ChatResolve;\n /** Default wire format; a request may override it with the format header. */\n format?: ChatHandlerFormat | undefined;\n};\n\n/** Per-request wire-format override header. */\nexport const CHAT_FORMAT_HEADER = \"x-opengeni-chat-format\";\n\nconst CHAT_FORMATS: ReadonlySet<string> = new Set([\n \"native\",\n \"vercel\",\n \"openai-chat\",\n \"openai-responses\",\n]);\n\nfunction methodNotAllowed(allow: string): Response {\n return new Response(\n JSON.stringify({ error: { message: `Use ${allow}.`, code: \"method_not_allowed\" } }),\n { status: 405, headers: { Allow: allow, \"Content-Type\": \"application/json; charset=utf-8\" } },\n );\n}\n\n/**\n * One request handler for a product's chat endpoint. `POST` with `{ message }`\n * streams the reply in the selected format; `POST .../respond` answers a\n * pending approval or human-input request and streams the continuation;\n * `GET` returns the conversation's history as JSON. Every other method is a\n * 405. The conversation is the host's resolution, else the\n * `x-opengeni-conversation` header, else the wire format's own field.\n */\nexport function createChatHandler(\n og: OpenGeni,\n options: ChatHandlerOptions,\n): (request: Request) => Promise<Response> {\n return async (request) => {\n const isRespond = new URL(request.url).pathname.replace(/\\/+$/, \"\").endsWith(\"/respond\");\n if (isRespond) {\n if (request.method !== \"POST\") return methodNotAllowed(\"POST\");\n return await handleNativeRespondRequest(og, request, options.resolve);\n }\n if (request.method === \"GET\") {\n return await handleNativeHistoryRequest(og, request, options.resolve);\n }\n if (request.method !== \"POST\") return methodNotAllowed(\"GET, POST\");\n const headerFormat = request.headers.get(CHAT_FORMAT_HEADER);\n if (headerFormat !== null && !CHAT_FORMATS.has(headerFormat)) {\n return errorResponse(400, `Unknown chat format: ${headerFormat}`, \"unknown_format\");\n }\n const format = (headerFormat as ChatHandlerFormat | null) ?? options.format ?? \"native\";\n switch (format) {\n case \"vercel\":\n return await handleVercelChatRequest(og, request, options.resolve);\n case \"openai-chat\":\n return await handleChatCompletionsRequest(og, request, options.resolve);\n case \"openai-responses\":\n return await handleResponsesRequest(og, request, options.resolve);\n default:\n return await handleNativeChatRequest(og, request, options.resolve);\n }\n };\n}\n\n/** `POST { message }` -> native SSE of {@link ChatChunk} (`event: chunk`). */\nexport async function handleNativeChatRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const message = typeof body?.message === \"string\" ? body.message.trim() : \"\";\n if (!message) {\n return errorResponse(400, \"Body must carry a non-empty message.\", \"message_required\");\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));\n if (opened.response) return opened.response;\n return chatChunksToSseResponse(opened.chat.stream(message, { signal: request.signal }));\n}\n\n/**\n * `GET` -> `{ conversation, sessionId, created, messages, pending, status }`: the user and\n * assistant text of the conversation so a client can restore it on reload\n * (`messages` is empty and `created` false before the first message).\n */\nexport async function handleNativeHistoryRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));\n if (opened.response) return opened.response;\n try {\n const snapshot = await opened.chat.snapshot();\n return jsonResponse({\n conversation: opened.chat.conversation,\n sessionId: opened.chat.sessionId,\n created: opened.chat.created,\n ...snapshot,\n });\n } catch (error) {\n const summary = chatErrorSummary(error);\n return errorResponse(summary.status, summary.message, summary.code);\n }\n}\n\n/** `POST .../respond { requestId, decision | answers | skip }` -> native SSE of the continuation. */\nexport async function handleNativeRespondRequest(\n og: OpenGeni,\n request: Request,\n resolve: ChatResolve,\n): Promise<Response> {\n const body = await readJsonObject(request);\n const input = respondInputFromBody(body);\n if (!input) {\n return errorResponse(\n 400,\n \"Body must carry requestId plus decision, answers, or skip.\",\n \"respond_input_invalid\",\n );\n }\n const resolved = await resolveChatRequest(request, resolve);\n if (resolved.response) return resolved.response;\n const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));\n if (opened.response) return opened.response;\n return chatChunksToSseResponse(opened.chat.respondStream(input, { signal: request.signal }));\n}\n\nexport function respondInputFromBody(\n body: Record<string, unknown> | null,\n): ChatRespondInput | null {\n const requestId = typeof body?.requestId === \"string\" ? body.requestId : \"\";\n if (!body || !requestId) return null;\n if (body.decision === \"approve\" || body.decision === \"reject\") {\n return {\n requestId,\n decision: body.decision,\n ...(typeof body.message === \"string\" ? { message: body.message } : {}),\n };\n }\n if (Array.isArray(body.answers)) {\n const answers = body.answers.filter(\n (answer): answer is HumanInputAnswer =>\n !!answer &&\n typeof answer === \"object\" &&\n typeof (answer as HumanInputAnswer).questionId === \"string\" &&\n Array.isArray((answer as HumanInputAnswer).values),\n );\n return { requestId, answers };\n }\n if (body.skip === true) return { requestId, skip: true };\n return null;\n}\n\n/** Native wire format: `event: chunk` per {@link ChatChunk}, `event: error` on failure. */\nexport async function* chatChunksToSseBlocks(\n chunks: AsyncIterable<ChatChunk>,\n): AsyncGenerator<string, void, void> {\n try {\n for await (const chunk of chunks) {\n yield sseLine(JSON.stringify(chunk), \"chunk\");\n }\n } catch (error) {\n const summary = chatErrorSummary(error);\n yield sseLine(JSON.stringify({ code: summary.code, message: summary.message }), \"error\");\n }\n}\n\nexport function chatChunksToSseStream(\n chunks: AsyncIterable<ChatChunk>,\n onCancel?: () => void,\n): ReadableStream<Uint8Array> {\n return sseByteStream(chatChunksToSseBlocks(chunks), onCancel);\n}\n\nexport function chatChunksToSseResponse(chunks: AsyncIterable<ChatChunk>): Response {\n return new Response(chatChunksToSseStream(chunks), {\n headers: sseHeaders({ [CHAT_FORMAT_HEADER]: \"native\" }),\n });\n}\n\n/** Browser-side reader for the native wire format. Throws {@link OpenGeniChatError} on `event: error`. */\nexport async function* parseChatChunkStream(\n stream: ReadableStream<Uint8Array>,\n): AsyncGenerator<ChatChunk, void, void> {\n for await (const message of parseSseStream(stream)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(message.data);\n } catch {\n continue;\n }\n if (message.event === \"error\") {\n const record = (parsed ?? {}) as { code?: unknown; message?: unknown };\n throw new OpenGeniChatError(\n typeof record.code === \"string\" ? record.code : \"chat_error\",\n typeof record.message === \"string\" ? record.message : \"Chat request failed.\",\n );\n }\n if (\n parsed &&\n typeof parsed === \"object\" &&\n typeof (parsed as { type?: unknown }).type === \"string\"\n ) {\n yield parsed as ChatChunk;\n }\n }\n}\n"],"mappings":"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","names":[]}
|