@opengeni/sdk 3.3.2-canary.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/README.md +1007 -72
  2. package/dist/adapters/express.d.ts +31 -0
  3. package/dist/adapters/express.js +87 -0
  4. package/dist/adapters/express.js.map +1 -0
  5. package/dist/adapters/hono.d.ts +16 -0
  6. package/dist/adapters/hono.js +8 -0
  7. package/dist/adapters/hono.js.map +1 -0
  8. package/dist/adapters/next.d.ts +29 -0
  9. package/dist/adapters/next.js +22 -0
  10. package/dist/adapters/next.js.map +1 -0
  11. package/dist/allowance-refusal.d.ts +2 -0
  12. package/dist/allowance-refusal.js +50 -0
  13. package/dist/allowance-refusal.js.map +1 -0
  14. package/dist/app-links.d.ts +42 -0
  15. package/dist/app-links.js +66 -0
  16. package/dist/app-links.js.map +1 -0
  17. package/dist/artifact-catalog.d.ts +40 -0
  18. package/dist/artifact-client.d.ts +20 -8
  19. package/dist/artifacts.d.ts +1 -1
  20. package/dist/artifacts.js +8 -6
  21. package/dist/automations.js +8 -2
  22. package/dist/automations.js.map +1 -1
  23. package/dist/azure-live-transport.d.ts +32 -0
  24. package/dist/browser.d.ts +6 -2
  25. package/dist/browser.js +25 -5
  26. package/dist/chat/fold.d.ts +75 -0
  27. package/dist/chat/handler.d.ts +41 -0
  28. package/dist/chat/http.d.ts +67 -0
  29. package/dist/chat/ids.d.ts +34 -0
  30. package/dist/chat/index.d.ts +9 -0
  31. package/dist/chat/index.js +1369 -0
  32. package/dist/chat/index.js.map +1 -0
  33. package/dist/chat/openai.d.ts +30 -0
  34. package/dist/chat/opengeni.d.ts +129 -0
  35. package/dist/chat/types.d.ts +207 -0
  36. package/dist/chat/vercel.d.ts +49 -0
  37. package/dist/chats.d.ts +8 -0
  38. package/dist/chunk-4AHR4KGA.js +301 -0
  39. package/dist/chunk-4AHR4KGA.js.map +1 -0
  40. package/dist/chunk-6GYGMLX4.js +332 -0
  41. package/dist/chunk-6GYGMLX4.js.map +1 -0
  42. package/dist/chunk-7EWT3PV6.js +368 -0
  43. package/dist/chunk-7EWT3PV6.js.map +1 -0
  44. package/dist/chunk-FTWVVPR6.js +1665 -0
  45. package/dist/chunk-FTWVVPR6.js.map +1 -0
  46. package/dist/{chunk-VYCTL62C.js → chunk-GZQSWAKD.js} +1 -1
  47. package/dist/chunk-GZQSWAKD.js.map +1 -0
  48. package/dist/chunk-KGEABAID.js +71 -0
  49. package/dist/chunk-KGEABAID.js.map +1 -0
  50. package/dist/{chunk-YKZME56C.js → chunk-KWADQ227.js} +3 -3
  51. package/dist/{chunk-YKZME56C.js.map → chunk-KWADQ227.js.map} +1 -1
  52. package/dist/{chunk-E5BNEG2D.js → chunk-NCU5OAN7.js} +27 -2
  53. package/dist/chunk-NCU5OAN7.js.map +1 -0
  54. package/dist/{chunk-BESZFWMU.js → chunk-OI5YLASH.js} +73 -2
  55. package/dist/chunk-OI5YLASH.js.map +1 -0
  56. package/dist/chunk-OV3POE62.js +359 -0
  57. package/dist/chunk-OV3POE62.js.map +1 -0
  58. package/dist/chunk-P7UWKORG.js +561 -0
  59. package/dist/chunk-P7UWKORG.js.map +1 -0
  60. package/dist/chunk-QGEIL4TR.js +195 -0
  61. package/dist/chunk-QGEIL4TR.js.map +1 -0
  62. package/dist/{chunk-GY6RQPCG.js → chunk-S2NLS3ES.js} +3598 -1278
  63. package/dist/chunk-S2NLS3ES.js.map +1 -0
  64. package/dist/chunk-UM4ZXXJR.js +9 -0
  65. package/dist/chunk-UM4ZXXJR.js.map +1 -0
  66. package/dist/{chunk-TFCLHRZK.js → chunk-UME3X7CP.js} +28 -32
  67. package/dist/chunk-UME3X7CP.js.map +1 -0
  68. package/dist/chunk-VT4YM4XQ.js +210 -0
  69. package/dist/chunk-VT4YM4XQ.js.map +1 -0
  70. package/dist/chunk-WSYYXONG.js +1602 -0
  71. package/dist/chunk-WSYYXONG.js.map +1 -0
  72. package/dist/{chunk-6NEPJ7NC.js → chunk-WVCJRSGJ.js} +119 -14
  73. package/dist/chunk-WVCJRSGJ.js.map +1 -0
  74. package/dist/chunk-X5ITQVXE.js +15 -0
  75. package/dist/chunk-X5ITQVXE.js.map +1 -0
  76. package/dist/chunk-XA7HVIHI.js +126 -0
  77. package/dist/chunk-XA7HVIHI.js.map +1 -0
  78. package/dist/{chunk-QTBAMHEF.js → chunk-YJCHB7R3.js} +60 -12
  79. package/dist/chunk-YJCHB7R3.js.map +1 -0
  80. package/dist/chunk-YKIHNLWD.js +153 -0
  81. package/dist/chunk-YKIHNLWD.js.map +1 -0
  82. package/dist/chunk-ZDUBPV33.js +277 -0
  83. package/dist/chunk-ZDUBPV33.js.map +1 -0
  84. package/dist/client.d.ts +1056 -118
  85. package/dist/codex-realtime-controller.d.ts +13 -0
  86. package/dist/codex-realtime-controller.js +4 -2
  87. package/dist/codex-realtime-v3-wire.d.ts +3 -2
  88. package/dist/codex-realtime.d.ts +5 -1
  89. package/dist/company-brain.d.ts +1 -11
  90. package/dist/core.d.ts +6 -2
  91. package/dist/core.js +23 -6
  92. package/dist/deprecation.d.ts +47 -0
  93. package/dist/document-authority-client.d.ts +24 -2
  94. package/dist/document-authority.js +7 -5
  95. package/dist/editable-artifacts/index.d.ts +1 -1
  96. package/dist/editable-artifacts/types.d.ts +12 -2
  97. package/dist/editable-artifacts.js +19 -3
  98. package/dist/editable-artifacts.js.map +1 -1
  99. package/dist/embedding-client.d.ts +129 -0
  100. package/dist/errors.d.ts +64 -1
  101. package/dist/external-vault-receiver.d.ts +203 -0
  102. package/dist/external-vault-receiver.js +564 -0
  103. package/dist/external-vault-receiver.js.map +1 -0
  104. package/dist/feedback.d.ts +23 -0
  105. package/dist/gateway-realtime-transport.js +1 -1
  106. package/dist/github-repositories.d.ts +10 -0
  107. package/dist/github-repositories.js +36 -0
  108. package/dist/github-repositories.js.map +1 -0
  109. package/dist/index.d.ts +61 -11
  110. package/dist/index.js +555 -338
  111. package/dist/index.js.map +1 -1
  112. package/dist/insights-usage.d.ts +33 -0
  113. package/dist/insights-usage.js +7 -0
  114. package/dist/insights-usage.js.map +1 -0
  115. package/dist/interaction.d.ts +165 -71
  116. package/dist/interaction.js +2 -2
  117. package/dist/knowledge.d.ts +7 -0
  118. package/dist/knowledge.js +20 -0
  119. package/dist/knowledge.js.map +1 -0
  120. package/dist/known-tools.d.ts +4 -0
  121. package/dist/message-links.d.ts +68 -0
  122. package/dist/model-context.d.ts +68 -0
  123. package/dist/model-display.d.ts +2 -0
  124. package/dist/model-display.js +17 -0
  125. package/dist/model-display.js.map +1 -0
  126. package/dist/organization-integration-policy.d.ts +26 -0
  127. package/dist/organization-integration-policy.js +26 -0
  128. package/dist/organization-integration-policy.js.map +1 -0
  129. package/dist/pr-review-client.d.ts +1 -1
  130. package/dist/pr-review.d.ts +1 -1
  131. package/dist/pr-review.js.map +1 -1
  132. package/dist/preference-registry.d.ts +1 -1
  133. package/dist/prepared-mcp-setup.d.ts +5 -0
  134. package/dist/proxy.d.ts +13 -11
  135. package/dist/realtime.d.ts +1 -1
  136. package/dist/realtime.js +253 -7
  137. package/dist/realtime.js.map +1 -1
  138. package/dist/session-history-import.d.ts +22 -0
  139. package/dist/session-history-import.js +36 -0
  140. package/dist/session-history-import.js.map +1 -0
  141. package/dist/session-list-entries.d.ts +1 -0
  142. package/dist/session-list-entries.js +7 -0
  143. package/dist/session-list-entries.js.map +1 -0
  144. package/dist/session-message-search.d.ts +53 -0
  145. package/dist/session-proxy-client.d.ts +28 -0
  146. package/dist/session-proxy.d.ts +334 -0
  147. package/dist/session-proxy.js +24 -0
  148. package/dist/session-proxy.js.map +1 -0
  149. package/dist/session-titles.d.ts +2 -28
  150. package/dist/session-usage-limits.d.ts +10 -0
  151. package/dist/session-usage-limits.js +43 -0
  152. package/dist/session-usage-limits.js.map +1 -0
  153. package/dist/shared-catalog-loader.d.ts +34 -0
  154. package/dist/site-ai.d.ts +35 -0
  155. package/dist/site-bridge-host.d.ts +112 -0
  156. package/dist/site-bridge-host.js +286 -0
  157. package/dist/site-bridge-host.js.map +1 -0
  158. package/dist/site-browser-entry.d.ts +1 -0
  159. package/dist/site-browser-runtime.gen.d.ts +1 -0
  160. package/dist/site-data.d.ts +178 -0
  161. package/dist/site-document.d.ts +5 -0
  162. package/dist/site-document.js +20 -0
  163. package/dist/site-document.js.map +1 -0
  164. package/dist/site-document.test.d.ts +1 -0
  165. package/dist/site-http.d.ts +17 -0
  166. package/dist/site-sql.d.ts +31 -0
  167. package/dist/site-tool-bridge.d.ts +57 -0
  168. package/dist/site.d.ts +186 -0
  169. package/dist/site.js +63 -0
  170. package/dist/site.js.map +1 -0
  171. package/dist/skills.d.ts +75 -0
  172. package/dist/sse.d.ts +1 -1
  173. package/dist/stream.d.ts +2 -0
  174. package/dist/tenant-workspaces.d.ts +47 -0
  175. package/dist/tenant-workspaces.js +8 -0
  176. package/dist/tenant-workspaces.js.map +1 -0
  177. package/dist/tool-auth.d.ts +87 -0
  178. package/dist/tool-auth.js +23 -0
  179. package/dist/tool-auth.js.map +1 -0
  180. package/dist/tool-display-metadata.d.ts +3 -0
  181. package/dist/tools-37DCTCNZ.js +12 -0
  182. package/dist/tools-37DCTCNZ.js.map +1 -0
  183. package/dist/tools.d.ts +81 -0
  184. package/dist/transcription.d.ts +1 -1
  185. package/dist/types.d.ts +2785 -592
  186. package/dist/usage-allowances.d.ts +36 -0
  187. package/dist/usage-allowances.js +80 -0
  188. package/dist/usage-allowances.js.map +1 -0
  189. package/dist/vault-types.d.ts +324 -0
  190. package/dist/vaults-api.d.ts +65 -0
  191. package/dist/workspace-artifacts.d.ts +47 -5
  192. package/dist/workspace-instruction-policies.d.ts +2 -2
  193. package/dist/workspace-integrations.d.ts +74 -0
  194. package/dist/workspace-integrations.js +67 -0
  195. package/dist/workspace-integrations.js.map +1 -0
  196. package/dist/workspace-state.d.ts +8 -71
  197. package/package.json +99 -5
  198. package/src/adapters/express.ts +136 -0
  199. package/src/adapters/hono.ts +18 -0
  200. package/src/adapters/next.ts +42 -0
  201. package/src/allowance-refusal.ts +5 -0
  202. package/src/app-links.ts +117 -0
  203. package/src/artifact-catalog.ts +51 -0
  204. package/src/artifact-client.ts +40 -49
  205. package/src/artifacts.ts +1 -0
  206. package/src/automations-client.ts +8 -2
  207. package/src/azure-live-transport.ts +286 -0
  208. package/src/browser.ts +35 -0
  209. package/src/chat/fold.ts +431 -0
  210. package/src/chat/handler.ts +240 -0
  211. package/src/chat/http.ts +257 -0
  212. package/src/chat/ids.ts +85 -0
  213. package/src/chat/index.ts +88 -0
  214. package/src/chat/openai.ts +439 -0
  215. package/src/chat/opengeni.ts +737 -0
  216. package/src/chat/types.ts +219 -0
  217. package/src/chat/vercel.ts +204 -0
  218. package/src/chats.ts +16 -0
  219. package/src/client.ts +5595 -1847
  220. package/src/codex-realtime-controller.ts +163 -8
  221. package/src/codex-realtime-v3-wire.ts +4 -3
  222. package/src/codex-realtime-v3.ts +12 -3
  223. package/src/codex-realtime.ts +11 -3
  224. package/src/company-brain.ts +0 -40
  225. package/src/core.ts +18 -0
  226. package/src/deprecation.ts +149 -0
  227. package/src/document-authority-client.ts +104 -1
  228. package/src/editable-artifacts/controller.ts +36 -2
  229. package/src/editable-artifacts/index.ts +1 -0
  230. package/src/editable-artifacts/types.ts +29 -16
  231. package/src/embedding-client.ts +519 -0
  232. package/src/errors.ts +281 -5
  233. package/src/external-vault-receiver.ts +914 -0
  234. package/src/feedback.ts +20 -0
  235. package/src/gateway-realtime-transport.ts +3 -3
  236. package/src/github-repositories.ts +60 -0
  237. package/src/index.ts +592 -65
  238. package/src/insights-usage.ts +64 -0
  239. package/src/interaction.ts +315 -93
  240. package/src/knowledge.ts +72 -0
  241. package/src/known-tools.ts +279 -0
  242. package/src/message-links.ts +178 -0
  243. package/src/model-context.ts +113 -0
  244. package/src/model-display.ts +11 -0
  245. package/src/organization-integration-policy.ts +54 -0
  246. package/src/pr-review-client.ts +1 -1
  247. package/src/pr-review.ts +1 -1
  248. package/src/preference-registry.ts +2 -0
  249. package/src/prepared-mcp-setup.ts +123 -0
  250. package/src/proxy.ts +23 -12
  251. package/src/realtime.ts +15 -6
  252. package/src/session-history-import.ts +84 -0
  253. package/src/session-list-entries.ts +1 -0
  254. package/src/session-message-search.ts +47 -0
  255. package/src/session-proxy-client.ts +68 -0
  256. package/src/session-proxy.ts +2098 -0
  257. package/src/session-titles.ts +8 -82
  258. package/src/session-usage-limits.ts +71 -0
  259. package/src/shared-catalog-loader.ts +169 -0
  260. package/src/site-ai.ts +284 -0
  261. package/src/site-bridge-host.ts +422 -0
  262. package/src/site-browser-entry.ts +6 -0
  263. package/src/site-browser-runtime.gen.ts +2 -0
  264. package/src/site-data.ts +372 -0
  265. package/src/site-document.test.ts +64 -0
  266. package/src/site-document.ts +18 -0
  267. package/src/site-http.ts +171 -0
  268. package/src/site-sql.ts +153 -0
  269. package/src/site-tool-bridge.ts +401 -0
  270. package/src/site.ts +878 -0
  271. package/src/skills.ts +69 -0
  272. package/src/sse.ts +9 -3
  273. package/src/stream.ts +33 -10
  274. package/src/tenant-workspaces.ts +148 -0
  275. package/src/tool-auth.ts +301 -0
  276. package/src/tool-display-metadata.ts +27 -0
  277. package/src/tools.ts +452 -0
  278. package/src/transcription.ts +3 -0
  279. package/src/types.ts +3142 -594
  280. package/src/usage-allowances.ts +189 -0
  281. package/src/vault-types.ts +379 -0
  282. package/src/vaults-api.ts +339 -0
  283. package/src/workspace-artifacts.ts +55 -6
  284. package/src/workspace-instruction-policies.ts +2 -1
  285. package/src/workspace-integrations.ts +402 -0
  286. package/src/workspace-state.ts +8 -82
  287. package/dist/chunk-6NEPJ7NC.js.map +0 -1
  288. package/dist/chunk-BESZFWMU.js.map +0 -1
  289. package/dist/chunk-E5BNEG2D.js.map +0 -1
  290. package/dist/chunk-GY6RQPCG.js.map +0 -1
  291. package/dist/chunk-OO5LPTO7.js +0 -132
  292. package/dist/chunk-OO5LPTO7.js.map +0 -1
  293. package/dist/chunk-QTBAMHEF.js.map +0 -1
  294. package/dist/chunk-TFCLHRZK.js.map +0 -1
  295. package/dist/chunk-VYCTL62C.js.map +0 -1
@@ -0,0 +1,1369 @@
1
+ import {
2
+ CHAT_SESSION_NAMESPACE,
3
+ chatIdempotencyKey,
4
+ chatIdentityName,
5
+ chatSessionId,
6
+ createWorkspaceIdResolver,
7
+ isUuid,
8
+ uuidV5
9
+ } from "../chunk-XA7HVIHI.js";
10
+ import {
11
+ OpenGeniEmbeddingClient
12
+ } from "../chunk-6GYGMLX4.js";
13
+ import "../chunk-UME3X7CP.js";
14
+ import "../chunk-OI5YLASH.js";
15
+ import {
16
+ chatDefaults
17
+ } from "../chunk-UM4ZXXJR.js";
18
+ import {
19
+ ChatPendingFold,
20
+ ChatTurnFold,
21
+ OpenGeniChatError,
22
+ approvalPending,
23
+ asRecord,
24
+ humanInputPending,
25
+ stringValue
26
+ } from "../chunk-OV3POE62.js";
27
+ import "../chunk-S2NLS3ES.js";
28
+ import "../chunk-X5ITQVXE.js";
29
+ import {
30
+ parseSseStream
31
+ } from "../chunk-4AHR4KGA.js";
32
+ import "../chunk-NCU5OAN7.js";
33
+ import "../chunk-YJCHB7R3.js";
34
+ import {
35
+ OpenGeniApiError,
36
+ OpenGeniSetupError
37
+ } from "../chunk-7EWT3PV6.js";
38
+
39
+ // src/chat/opengeni.ts
40
+ var DEFAULT_OPENGENI_BASE_URL = "https://app.opengeni.ai";
41
+ var DEFAULT_CHAT_SOURCE = "app";
42
+ var MISSING_API_KEY_MESSAGE = "Opengeni requires an apiKey. Set OPENGENI_API_KEY in the server environment.";
43
+ async function missingApiKeyFetch() {
44
+ throw new TypeError(MISSING_API_KEY_MESSAGE);
45
+ }
46
+ var IMPORTED_HISTORY_MAX_CHARS = 3e4;
47
+ var MODEL_CONTEXT_MAX_CHARS = 32768;
48
+ var IMPORTED_HISTORY_HEADER = "Earlier conversation imported from the product, oldest first:";
49
+ var IMPORTED_HISTORY_ROLES = /* @__PURE__ */ new Set(["user", "assistant", "system"]);
50
+ var OpenGeni = class {
51
+ client;
52
+ /**
53
+ * The organization id: the one passed to the constructor, else the one
54
+ * derived from the API key once {@link resolveOrganizationId} (or any
55
+ * workspace lookup) has run. An empty string before that; prefer
56
+ * `await og.resolveOrganizationId()`.
57
+ */
58
+ organizationId;
59
+ source;
60
+ sessions;
61
+ resolveWorkspaceId;
62
+ implicitAgentAdmission;
63
+ pendingOrganizationId;
64
+ constructor(options) {
65
+ this.client = new OpenGeniEmbeddingClient({
66
+ // An empty value (a blank `OPENGENI_API_BASE_URL=` in .env) means the default.
67
+ baseUrl: options.baseUrl?.trim() || DEFAULT_OPENGENI_BASE_URL,
68
+ // A missing key fails each request, not construction: a module-scope
69
+ // `new Opengeni({ apiKey: process.env.OPENGENI_API_KEY! })` must not
70
+ // break `next build` (or any import) where the secret only exists at
71
+ // runtime.
72
+ ...options.apiKey ? { apiKey: options.apiKey, ...options.fetch ? { fetch: options.fetch } : {} } : { fetch: missingApiKeyFetch }
73
+ });
74
+ this.organizationId = options.organizationId?.trim() ?? "";
75
+ this.source = options.source ?? DEFAULT_CHAT_SOURCE;
76
+ this.resolveWorkspaceId = createWorkspaceIdResolver(this.client, {
77
+ organizationId: () => this.resolveOrganizationId(),
78
+ source: this.source,
79
+ workspaceName: options.workspaceName,
80
+ memberPermissions: options.memberPermissions
81
+ });
82
+ this.sessions = { list: (listOptions) => this.listSessions(listOptions) };
83
+ }
84
+ /**
85
+ * The organization that owns every workspace this facade creates. Uses the
86
+ * constructor's `organizationId`, else reads it once from the API key
87
+ * (`GET /v1/access/me`) and caches it.
88
+ */
89
+ async resolveOrganizationId() {
90
+ if (this.organizationId) return this.organizationId;
91
+ if (!this.pendingOrganizationId) {
92
+ const pending = this.client.getAccessContext().then((access) => {
93
+ const credential = access.credential;
94
+ if (credential && credential.kind !== "organization_api_key") {
95
+ throw new TypeError(
96
+ "Opengeni needs an organization API key to create workspaces; this is a workspace key."
97
+ );
98
+ }
99
+ const organizationId = credential?.accountId ?? access.defaultAccountId;
100
+ if (!organizationId) {
101
+ throw new TypeError(
102
+ "Could not derive the organization from this API key. Pass organizationId."
103
+ );
104
+ }
105
+ this.organizationId = organizationId;
106
+ return organizationId;
107
+ });
108
+ pending.catch(() => {
109
+ if (this.pendingOrganizationId === pending) this.pendingOrganizationId = void 0;
110
+ });
111
+ this.pendingOrganizationId = pending;
112
+ }
113
+ return await this.pendingOrganizationId;
114
+ }
115
+ /**
116
+ * Translate your own ids to the Opengeni workspace id, creating the
117
+ * workspace on first use (cached per instance):
118
+ * `{ tenant }` is one workspace per tenant, `{ user }` (no tenant) is one
119
+ * workspace per user, and `{ workspaceId }` is returned as is. Opengeni adds
120
+ * a tenant workspace's users on their first request; a per-user workspace
121
+ * gets its one owner from the SDK and admits nobody else.
122
+ */
123
+ async workspaceId(target) {
124
+ if (target.workspaceId === "" || target.tenant === "") {
125
+ throw new TypeError("tenant and workspaceId must be non-empty ids.");
126
+ }
127
+ if (target.workspaceId) return target.workspaceId;
128
+ if (target.tenant) {
129
+ return await this.workspaceIdFor({ tenant: target.tenant }, { isolation: "tenant" });
130
+ }
131
+ if ("tenant" in target || "workspaceId" in target) {
132
+ throw new TypeError(
133
+ "tenant or workspaceId is undefined. Pass a non-empty id, or omit the key for one workspace per user."
134
+ );
135
+ }
136
+ const user = "user" in target ? target.user : void 0;
137
+ if (user) {
138
+ return await this.workspaceIdFor({ user }, { isolation: "user" });
139
+ }
140
+ throw new TypeError("Pass tenant, user, or workspaceId.");
141
+ }
142
+ /**
143
+ * Resolve a tenant workspace or a user's own workspace (user isolation, per
144
+ * tenant when one is given). A user's own workspace is provisioned with that
145
+ * user as its only explicit member.
146
+ */
147
+ async workspaceIdFor(target, options) {
148
+ return await this.resolveWorkspaceId(target, options);
149
+ }
150
+ /** `chats: "isolated"` keeps its tenant-plus-user workspace; a user alone gets their own. */
151
+ async isolatedWorkspaceId(target) {
152
+ if (target.workspaceId) {
153
+ throw new TypeError('chats: "isolated" requires a tenant or user, not a workspaceId.');
154
+ }
155
+ return await this.workspaceIdFor(
156
+ { tenant: target.tenant, user: target.user },
157
+ { isolation: "user" }
158
+ );
159
+ }
160
+ /**
161
+ * Address one conversation; the session is created lazily on the first send.
162
+ * Identity selects authority, not the conversation address. The workspace
163
+ * is the tenant's, the user's own (user only), or the explicit id; Opengeni
164
+ * adds the user to it on their first request.
165
+ * Legacy user-namespaced conversations remain accessible by their session ID.
166
+ */
167
+ async chat(options) {
168
+ if (!options.conversation) throw new TypeError("chat() requires a conversation id.");
169
+ if (options.chats === "private" && !options.user) {
170
+ throw new OpenGeniChatError(
171
+ "chats_requires_user",
172
+ 'chats: "private" requires an authenticated product user. Pass user or use chats: "shared".'
173
+ );
174
+ }
175
+ const legacy = options.chats === void 0 && !options.user;
176
+ const defaults = legacy ? {
177
+ visibility: "workspace",
178
+ agentAccess: "session",
179
+ memoryScope: "off"
180
+ } : chatDefaults(options.chats ?? "private");
181
+ const explicitAgent = options.agent !== void 0 || options.create?.agent !== void 0;
182
+ const agentAccess = options.agentAccess ?? defaults.agentAccess;
183
+ const memoryScope = options.memory === false ? "off" : options.memory ?? (legacy ? agentAccess === "session" ? "off" : agentAccess : defaults.memoryScope);
184
+ if (memoryScope === "user" && !options.user) {
185
+ throw new OpenGeniChatError(
186
+ "memory_scope_requires_user",
187
+ 'memory: "user" requires an authenticated product user.'
188
+ );
189
+ }
190
+ const client = options.user ? this.client.asUser(options.user, { source: this.source }) : this.client;
191
+ const workspaceId = options.chats === "isolated" ? await this.isolatedWorkspaceId(options) : await this.workspaceId(options);
192
+ const sessionId = options.sessionId ?? await chatSessionId(workspaceId, options.conversation);
193
+ const session = await this.findSession(client, workspaceId, sessionId);
194
+ const buildCreate = (text, send) => {
195
+ const { modelContext: createContext, ...create } = options.create ?? {};
196
+ const messageContext = send.modelContext?.trim() || void 0;
197
+ const reserved = messageContext ? messageContext.length + 2 : 0;
198
+ const baseContext = createContext ?? (send.importedHistory ? formatImportedHistory(
199
+ send.importedHistory,
200
+ Math.min(IMPORTED_HISTORY_MAX_CHARS, MODEL_CONTEXT_MAX_CHARS - reserved)
201
+ ) : void 0);
202
+ const context = [baseContext, messageContext].filter(Boolean).join("\n\n") || void 0;
203
+ return {
204
+ ...options.model !== void 0 ? { model: options.model } : {},
205
+ ...options.instructions !== void 0 ? { instructions: options.instructions } : {},
206
+ ...options.skills !== void 0 ? { skills: options.skills } : {},
207
+ ...options.tools !== void 0 ? { tools: options.tools } : {},
208
+ ...create,
209
+ visibility: create.visibility ?? defaults.visibility,
210
+ agentAccess: create.agentAccess ?? agentAccess,
211
+ memoryScope: create.memoryScope ?? memoryScope,
212
+ agent: {
213
+ capabilities: create.agent?.capabilities ?? options.agent?.capabilities,
214
+ identity: create.agent?.identity !== void 0 ? create.agent.identity : options.agent?.identity,
215
+ instructions: create.agent?.instructions ?? options.agent?.instructions,
216
+ renderer: create.agent?.renderer ?? options.agent?.renderer ?? "markdown"
217
+ },
218
+ ...context !== void 0 ? { modelContext: context } : {},
219
+ ...messagePolicy(send),
220
+ initialMessage: text,
221
+ requestedSessionId: sessionId,
222
+ idempotencyKey: chatIdempotencyKey(sessionId)
223
+ };
224
+ };
225
+ return new Chat(client, {
226
+ workspaceId,
227
+ sessionId,
228
+ conversation: options.conversation,
229
+ session,
230
+ buildCreate,
231
+ submitCreate: (request) => this.createChatSession(client, workspaceId, request, explicitAgent)
232
+ });
233
+ }
234
+ async createChatSession(client, workspaceId, request, explicitAgent) {
235
+ const { agent, ...withoutAgent } = request;
236
+ const implicitAgent = !explicitAgent && this.implicitAgentAdmission !== false;
237
+ try {
238
+ return await client.createSession(
239
+ workspaceId,
240
+ explicitAgent || implicitAgent ? { ...withoutAgent, agent } : withoutAgent
241
+ );
242
+ } catch (error) {
243
+ if (!(error instanceof OpenGeniApiError) || error.status !== 422 || !(error.code === "agent_config_not_enabled" || error.code === "SESSION_CREATE_REJECTED" && error.details?.code === "agent_config_not_enabled") || error.outcomeUnknown)
244
+ throw error;
245
+ if (explicitAgent) {
246
+ throw new OpenGeniApiError(error.status, error.body, {
247
+ code: error.code,
248
+ retryable: false,
249
+ correlationId: error.correlationId,
250
+ displayMessage: "Explicit agent configuration requires the deployment operator to set OPENGENI_AGENT_CONFIG_ADMISSION_ENABLED=true. The SDK has kept your agent settings unchanged."
251
+ });
252
+ }
253
+ if (!implicitAgent) throw error;
254
+ this.implicitAgentAdmission = false;
255
+ return await client.createSession(workspaceId, withoutAgent);
256
+ }
257
+ }
258
+ /**
259
+ * Address an existing session with native API authorization. The same shared
260
+ * session can be opened by different authorized users. Pass null only for an
261
+ * explicitly service-owned operation; the API still enforces service access.
262
+ */
263
+ async chatBySessionId(target) {
264
+ const client = target.user !== null ? this.client.asUser(target.user, { source: this.source }) : this.client;
265
+ const session = await client.getSession(target.workspaceId, target.sessionId);
266
+ return new Chat(client, {
267
+ workspaceId: target.workspaceId,
268
+ sessionId: target.sessionId,
269
+ conversation: null,
270
+ session,
271
+ buildCreate: null
272
+ });
273
+ }
274
+ async findSession(client, workspaceId, sessionId) {
275
+ try {
276
+ return await client.getSession(workspaceId, sessionId);
277
+ } catch (error) {
278
+ if (error instanceof OpenGeniApiError && error.status === 404) return null;
279
+ throw error;
280
+ }
281
+ }
282
+ async listSessions(options) {
283
+ const workspaceId = options.chats === "isolated" ? await this.isolatedWorkspaceId(options) : await this.workspaceId(options);
284
+ const client = options.user ? this.client.asUser(options.user, { source: this.source }) : this.client;
285
+ return await client.requestJson(
286
+ "GET",
287
+ `/v1/workspaces/${workspaceId}/sessions`,
288
+ void 0,
289
+ {
290
+ ...options.limit !== void 0 ? { limit: String(options.limit) } : {}
291
+ }
292
+ );
293
+ }
294
+ };
295
+ var Chat = class {
296
+ constructor(client, init) {
297
+ this.client = client;
298
+ this.workspaceId = init.workspaceId;
299
+ this.sessionId = init.sessionId;
300
+ this.conversation = init.conversation;
301
+ this.session = init.session;
302
+ this.buildCreate = init.buildCreate;
303
+ this.submitCreate = init.submitCreate ?? ((request) => this.client.createSession(this.workspaceId, request));
304
+ }
305
+ workspaceId;
306
+ sessionId;
307
+ /** The conversation id this chat was opened with; null when addressed by session id. */
308
+ conversation;
309
+ session;
310
+ buildCreate;
311
+ submitCreate;
312
+ pendingTurnId = null;
313
+ /** True once the session exists on the server. */
314
+ get created() {
315
+ return this.session !== null;
316
+ }
317
+ /** Send a message and wait for the agent's reply text. */
318
+ async send(text, options = {}) {
319
+ return await settle(this.stream(text, options));
320
+ }
321
+ /** Send a message and observe the reply as it streams. Ends with a `done` chunk. */
322
+ async *stream(text, options = {}) {
323
+ const submitted = options.steer ? await this.submitSteer(text, options) : await this.submit(text, options);
324
+ yield* this.streamTurn(submitted, options.signal);
325
+ }
326
+ /** Supersede the current inference with this message and wait for the reply. */
327
+ async steer(text, options = {}) {
328
+ return await this.send(text, { ...options, steer: true });
329
+ }
330
+ /** Answer a pending approval or human-input request, then wait for the reply. */
331
+ async respond(input, options = {}) {
332
+ return await settle(this.respondStream(input, options));
333
+ }
334
+ async *respondStream(input, options = {}) {
335
+ const submitted = await this.submitResponse(input);
336
+ yield* this.streamTurn(submitted, options.signal);
337
+ }
338
+ /** User and assistant text in order, from the durable event log. */
339
+ async history() {
340
+ return (await this.snapshot()).messages;
341
+ }
342
+ /** Restore history and pending decisions from the complete ordered timeline. */
343
+ async snapshot() {
344
+ if (!this.session) return { messages: [], pending: [], status: null };
345
+ const pending = new ChatPendingFold();
346
+ let status = this.session.status;
347
+ const messages = [];
348
+ let lastAssistantTurn = null;
349
+ let heldCommentary = null;
350
+ const releaseHeldCommentary = (turnId) => {
351
+ if (!heldCommentary || heldCommentary.turnId !== turnId) return;
352
+ const held = heldCommentary;
353
+ heldCommentary = null;
354
+ const index = messages.findIndex((message2) => message2.sequence > held.sequence);
355
+ const message = { role: "assistant", text: held.text, sequence: held.sequence };
356
+ if (index === -1) messages.push(message);
357
+ else messages.splice(index, 0, message);
358
+ };
359
+ let after = 0;
360
+ while (true) {
361
+ const result = await this.client.listEventPage(this.workspaceId, this.sessionId, {
362
+ after,
363
+ includeTypes: [
364
+ "user.message",
365
+ "agent.message.completed",
366
+ "session.requiresAction",
367
+ "session.humanInput.requested",
368
+ "user.approvalDecision",
369
+ "user.humanInputResponse",
370
+ "turn.completed",
371
+ "turn.failed",
372
+ "turn.cancelled",
373
+ "session.status.changed"
374
+ ]
375
+ });
376
+ for (const event of result.events) {
377
+ pending.push(event);
378
+ if (event.type === "session.status.changed") {
379
+ const next = asRecord(event.payload).status;
380
+ if (typeof next === "string") status = next;
381
+ }
382
+ const turnId = typeof event.turnId === "string" ? event.turnId : null;
383
+ if (event.type === "turn.completed" || event.type === "turn.failed" || event.type === "turn.cancelled" || event.type === "session.requiresAction" || event.type === "session.humanInput.requested") {
384
+ releaseHeldCommentary(turnId);
385
+ }
386
+ const text = stringValue(asRecord(event.payload).text);
387
+ if (!text) continue;
388
+ if (event.type === "user.message") {
389
+ messages.push({ role: "user", text, sequence: event.sequence });
390
+ lastAssistantTurn = null;
391
+ continue;
392
+ }
393
+ if (event.type !== "agent.message.completed") continue;
394
+ if (asRecord(event.payload).phase === "commentary") {
395
+ heldCommentary = { turnId, text, sequence: event.sequence };
396
+ continue;
397
+ }
398
+ if (heldCommentary?.turnId === turnId) heldCommentary = null;
399
+ const last = messages.at(-1);
400
+ if (last?.role === "assistant" && turnId !== null && turnId === lastAssistantTurn && text.startsWith(last.text)) {
401
+ last.text = text;
402
+ last.sequence = event.sequence;
403
+ continue;
404
+ }
405
+ messages.push({ role: "assistant", text, sequence: event.sequence });
406
+ lastAssistantTurn = turnId;
407
+ }
408
+ if (!result.hasMore || result.nextAfter === null || result.events.length === 0) break;
409
+ if (result.nextAfter <= after) {
410
+ throw new OpenGeniChatError(
411
+ "history_cursor_stalled",
412
+ "History pagination did not advance."
413
+ );
414
+ }
415
+ after = result.nextAfter;
416
+ }
417
+ return { messages, pending: pending.pending(), status };
418
+ }
419
+ async submit(text, send) {
420
+ if (!this.session) {
421
+ if (!this.buildCreate) {
422
+ throw new OpenGeniChatError("session_missing", "This session no longer exists.");
423
+ }
424
+ const created = await this.submitCreate(this.buildCreate(text, send));
425
+ this.session = created;
426
+ if (created.initialMessage === text) {
427
+ return { after: 0, turnId: created.initialTurnId };
428
+ }
429
+ }
430
+ const event = await this.client.sendMessage(
431
+ this.workspaceId,
432
+ this.sessionId,
433
+ messageInput(text, send)
434
+ );
435
+ return submittedFrom(event);
436
+ }
437
+ async submitSteer(text, send) {
438
+ if (!this.session) return await this.submit(text, send);
439
+ const result = await this.client.steerMessage(
440
+ this.workspaceId,
441
+ this.sessionId,
442
+ messageInput(text, send)
443
+ );
444
+ return { after: result.accepted.sequence, turnId: result.turn.id ?? null };
445
+ }
446
+ async submitResponse(input) {
447
+ let event;
448
+ if ("decision" in input) {
449
+ event = await this.client.sendApprovalDecision(this.workspaceId, this.sessionId, {
450
+ approvalId: input.requestId,
451
+ decision: input.decision,
452
+ ...input.message !== void 0 ? { message: input.message } : {}
453
+ });
454
+ } else if ("answers" in input) {
455
+ event = await this.client.submitHumanInputResponse(
456
+ this.workspaceId,
457
+ this.sessionId,
458
+ input.requestId,
459
+ { outcome: "answered", answers: input.answers }
460
+ );
461
+ } else {
462
+ event = await this.client.submitHumanInputResponse(
463
+ this.workspaceId,
464
+ this.sessionId,
465
+ input.requestId,
466
+ { outcome: "skipped" }
467
+ );
468
+ }
469
+ const submitted = submittedFrom(event);
470
+ return { ...submitted, turnId: submitted.turnId ?? this.pendingTurnId };
471
+ }
472
+ async *streamTurn(submitted, signal) {
473
+ const upstream = new AbortController();
474
+ const onAbort = () => upstream.abort();
475
+ if (signal?.aborted) upstream.abort();
476
+ else signal?.addEventListener("abort", onAbort, { once: true });
477
+ const fold = new ChatTurnFold(this.workspaceId, this.sessionId, submitted.turnId);
478
+ const events = this.client.streamEvents(this.workspaceId, this.sessionId, {
479
+ after: submitted.after,
480
+ signal: upstream.signal
481
+ });
482
+ try {
483
+ while (true) {
484
+ const next = await events.next();
485
+ if (next.done) break;
486
+ const event = next.value;
487
+ const step = fold.push(event);
488
+ for (const chunk of step.chunks) yield chunk;
489
+ if (!step.terminal && event.type === "session.status.changed" && asRecord(event.payload).status === "requires_action" && (event.turnId == null || fold.turnId === null || event.turnId === fold.turnId)) {
490
+ const pending = (await this.snapshot()).pending[0];
491
+ if (pending) {
492
+ fold.pending = pending;
493
+ this.pendingTurnId = fold.turnId;
494
+ yield { type: "pending", pending };
495
+ yield { type: "done", reply: fold.reply("pending") };
496
+ return;
497
+ }
498
+ }
499
+ if (!step.terminal) continue;
500
+ if (step.terminal === "failed") throw fold.failureError();
501
+ this.pendingTurnId = step.terminal === "pending" ? fold.turnId : null;
502
+ yield { type: "done", reply: fold.reply(step.terminal) };
503
+ return;
504
+ }
505
+ if (signal?.aborted) throw abortError();
506
+ throw new OpenGeniChatError(
507
+ "stream_ended",
508
+ "The event stream ended before the turn settled."
509
+ );
510
+ } finally {
511
+ signal?.removeEventListener("abort", onAbort);
512
+ upstream.abort();
513
+ void Promise.resolve(events.return(void 0)).catch(() => void 0);
514
+ }
515
+ }
516
+ };
517
+ async function settle(chunks) {
518
+ for await (const chunk of chunks) {
519
+ if (chunk.type === "done") return chunk.reply;
520
+ }
521
+ throw new OpenGeniChatError("stream_ended", "The event stream ended before the turn settled.");
522
+ }
523
+ function messagePolicy(send) {
524
+ return {
525
+ ...send.model !== void 0 ? { model: send.model } : {},
526
+ ...send.reasoningEffort !== void 0 ? { reasoningEffort: send.reasoningEffort } : {},
527
+ ...send.latencyMode !== void 0 ? { latencyMode: send.latencyMode } : {}
528
+ };
529
+ }
530
+ function messageInput(text, send) {
531
+ const modelContext = send.modelContext?.trim();
532
+ return { text, ...messagePolicy(send), ...modelContext ? { modelContext } : {} };
533
+ }
534
+ function submittedFrom(event) {
535
+ return {
536
+ after: event.sequence,
537
+ turnId: typeof event.turnId === "string" ? event.turnId : null
538
+ };
539
+ }
540
+ function formatImportedHistory(messages, maxChars = IMPORTED_HISTORY_MAX_CHARS) {
541
+ const lines = messages.filter(
542
+ (message) => IMPORTED_HISTORY_ROLES.has(message.role) && typeof message.text === "string" && message.text.trim().length > 0
543
+ ).map((message) => `${message.role}: ${message.text}`);
544
+ if (lines.length === 0) return void 0;
545
+ let budget = Math.min(maxChars, IMPORTED_HISTORY_MAX_CHARS) - IMPORTED_HISTORY_HEADER.length;
546
+ const kept = [];
547
+ for (let index = lines.length - 1; index >= 0; index -= 1) {
548
+ const line = lines[index];
549
+ const cost = line.length + 1;
550
+ if (cost <= budget) {
551
+ kept.unshift(line);
552
+ budget -= cost;
553
+ continue;
554
+ }
555
+ if (kept.length === 0 && budget > 1) kept.unshift(line.slice(line.length - (budget - 1)));
556
+ break;
557
+ }
558
+ if (kept.length === 0) return void 0;
559
+ return `${IMPORTED_HISTORY_HEADER}
560
+ ${kept.join("\n")}`;
561
+ }
562
+ function abortError() {
563
+ const error = new Error("The chat request was aborted.");
564
+ error.name = "AbortError";
565
+ return error;
566
+ }
567
+
568
+ // src/chat/http.ts
569
+ var CHAT_CONVERSATION_HEADER = "x-opengeni-conversation";
570
+ var CHAT_ERROR_STATUS = {
571
+ memory_scope_requires_user: 400,
572
+ conversation_not_authorized: 403,
573
+ conversation_mismatch: 409
574
+ };
575
+ function jsonResponse(body, status = 200, headers = {}) {
576
+ return new Response(JSON.stringify(body), {
577
+ status,
578
+ headers: { "Content-Type": "application/json; charset=utf-8", ...headers }
579
+ });
580
+ }
581
+ function errorResponse(status, message, code) {
582
+ return jsonResponse(
583
+ { error: { message, code, type: status >= 500 ? "server_error" : "invalid_request_error" } },
584
+ status
585
+ );
586
+ }
587
+ async function readJsonObject(request) {
588
+ try {
589
+ const parsed = await request.json();
590
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
591
+ } catch {
592
+ return null;
593
+ }
594
+ }
595
+ async function resolveChatRequest(request, resolve) {
596
+ const resolved = await resolve(request);
597
+ if (resolved instanceof Response) return { response: resolved };
598
+ return { resolution: resolved };
599
+ }
600
+ function clientConversation(request, protocolField) {
601
+ const header = request.headers.get(CHAT_CONVERSATION_HEADER);
602
+ if (header) return header;
603
+ return typeof protocolField === "string" && protocolField ? protocolField : void 0;
604
+ }
605
+ async function openResolvedChat(og, resolution, clientConversationId) {
606
+ if (!resolution.conversation && !resolution.user) {
607
+ return {
608
+ response: errorResponse(
609
+ 400,
610
+ "Return a conversation from resolve, or a user so client conversation ids are scoped to that user.",
611
+ "conversation_required"
612
+ )
613
+ };
614
+ }
615
+ const conversationId = resolution.conversation ?? clientConversationId;
616
+ if (!conversationId) {
617
+ return {
618
+ response: errorResponse(
619
+ 400,
620
+ `A conversation id is required: send the ${CHAT_CONVERSATION_HEADER} header or the protocol's conversation field.`,
621
+ "conversation_required"
622
+ )
623
+ };
624
+ }
625
+ try {
626
+ const chat = await og.chat({ ...resolution, conversation: conversationId });
627
+ return { chat };
628
+ } catch (error) {
629
+ const summary = chatErrorSummary(error);
630
+ return { response: errorResponse(summary.status, summary.message, summary.code) };
631
+ }
632
+ }
633
+ function chatErrorSummary(error) {
634
+ if (error instanceof OpenGeniChatError) {
635
+ const status = CHAT_ERROR_STATUS[error.code] ?? 502;
636
+ return { status, code: error.code, message: error.message };
637
+ }
638
+ if (error instanceof OpenGeniApiError) {
639
+ return {
640
+ status: error.status >= 500 ? 502 : error.status,
641
+ code: error.code ?? "opengeni_api_error",
642
+ message: error.message
643
+ };
644
+ }
645
+ if (error instanceof Error && error.name === "AbortError") {
646
+ return { status: 499, code: "aborted", message: "The chat request was aborted." };
647
+ }
648
+ return { status: 500, code: "internal_error", message: "Chat request failed." };
649
+ }
650
+ function sseHeaders(extra = {}) {
651
+ return {
652
+ "Content-Type": "text/event-stream; charset=utf-8",
653
+ "Cache-Control": "no-cache, no-transform",
654
+ Connection: "keep-alive",
655
+ ...extra
656
+ };
657
+ }
658
+ function sseLine(data, event) {
659
+ return `${event ? `event: ${event}
660
+ ` : ""}data: ${data}
661
+
662
+ `;
663
+ }
664
+ function sseByteStream(blocks, onCancel) {
665
+ const encoder = new TextEncoder();
666
+ const iterator = blocks[Symbol.asyncIterator]();
667
+ let cancelled = false;
668
+ return new ReadableStream({
669
+ pull: async (controller) => {
670
+ const result = await iterator.next();
671
+ if (cancelled) return;
672
+ if (result.done) {
673
+ controller.close();
674
+ return;
675
+ }
676
+ controller.enqueue(encoder.encode(result.value));
677
+ },
678
+ cancel: () => {
679
+ cancelled = true;
680
+ onCancel?.();
681
+ void Promise.resolve(iterator.return?.(void 0)).then(
682
+ () => void 0,
683
+ () => void 0
684
+ );
685
+ }
686
+ });
687
+ }
688
+ function messageContentText(content, partTypes) {
689
+ if (typeof content === "string") return content;
690
+ if (!Array.isArray(content)) return null;
691
+ const texts = content.map((part) => {
692
+ if (!part || typeof part !== "object") return null;
693
+ const record = part;
694
+ return partTypes.includes(String(record.type)) && typeof record.text === "string" ? record.text : null;
695
+ }).filter((text) => text !== null);
696
+ return texts.length > 0 ? texts.join("\n") : null;
697
+ }
698
+ function lastUserMessageIndex(messages) {
699
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
700
+ const message = messages[index];
701
+ if (message && typeof message === "object" && message.role === "user") {
702
+ return index;
703
+ }
704
+ }
705
+ return -1;
706
+ }
707
+ function messageText(message, partTypes, partsField) {
708
+ if (!message || typeof message !== "object") return null;
709
+ const record = message;
710
+ return messageContentText(record[partsField], partTypes) ?? messageContentText(record.content, partTypes);
711
+ }
712
+ function lastUserMessageText(messages, partTypes, partsField) {
713
+ if (!Array.isArray(messages)) return null;
714
+ const index = lastUserMessageIndex(messages);
715
+ return index < 0 ? null : messageText(messages[index], partTypes, partsField);
716
+ }
717
+ function importedHistoryBefore(messages, partTypes, partsField) {
718
+ if (!Array.isArray(messages)) return [];
719
+ const lastUser = lastUserMessageIndex(messages);
720
+ if (lastUser < 0) return [];
721
+ const imported = [];
722
+ for (const message of messages.slice(0, lastUser)) {
723
+ const role = message?.role;
724
+ if (role !== "user" && role !== "assistant" && role !== "system") continue;
725
+ const text = messageText(message, partTypes, partsField);
726
+ if (text) imported.push({ role, text });
727
+ }
728
+ return imported;
729
+ }
730
+
731
+ // src/chat/openai.ts
732
+ var DEFAULT_MODEL_LABEL = "opengeni";
733
+ function replyExtension(reply) {
734
+ return {
735
+ sessionId: reply.sessionId,
736
+ workspaceId: reply.workspaceId,
737
+ turnId: reply.turnId,
738
+ status: reply.status,
739
+ pending: reply.pending
740
+ };
741
+ }
742
+ function conversationFromBody(body) {
743
+ const conversation = body?.conversation;
744
+ if (typeof conversation === "string" && conversation) return conversation;
745
+ if (conversation && typeof conversation === "object") {
746
+ const id = conversation.id;
747
+ if (typeof id === "string" && id) return id;
748
+ }
749
+ return void 0;
750
+ }
751
+ function modelLabel(body) {
752
+ return typeof body?.model === "string" && body.model ? body.model : DEFAULT_MODEL_LABEL;
753
+ }
754
+ function wantsStream(body) {
755
+ return body?.stream === true;
756
+ }
757
+ var CHAT_COMPLETION_PART_TYPES = ["text", "input_text"];
758
+ function chatCompletionChunk(sessionId, model, created, delta, finishReason, extension) {
759
+ return sseLine(
760
+ JSON.stringify({
761
+ id: `chatcmpl-${sessionId}`,
762
+ object: "chat.completion.chunk",
763
+ created,
764
+ model,
765
+ choices: [{ index: 0, delta, finish_reason: finishReason }],
766
+ ...extension ? { opengeni: extension } : {}
767
+ })
768
+ );
769
+ }
770
+ async function* chatCompletionBlocks(chat, chunks, model) {
771
+ const created = Math.floor(Date.now() / 1e3);
772
+ yield chatCompletionChunk(
773
+ chat.sessionId,
774
+ model,
775
+ created,
776
+ { role: "assistant", content: "" },
777
+ null
778
+ );
779
+ try {
780
+ for await (const chunk of chunks) {
781
+ if (chunk.type === "text") {
782
+ yield chatCompletionChunk(chat.sessionId, model, created, { content: chunk.text }, null);
783
+ } else if (chunk.type === "done") {
784
+ yield chatCompletionChunk(
785
+ chat.sessionId,
786
+ model,
787
+ created,
788
+ {},
789
+ "stop",
790
+ replyExtension(chunk.reply)
791
+ );
792
+ }
793
+ }
794
+ } catch (error) {
795
+ const summary = chatErrorSummary(error);
796
+ yield sseLine(
797
+ JSON.stringify({
798
+ error: { message: summary.message, code: summary.code, type: "server_error" }
799
+ })
800
+ );
801
+ }
802
+ yield sseLine("[DONE]");
803
+ }
804
+ function chatCompletionObject(reply, model) {
805
+ return {
806
+ id: `chatcmpl-${reply.sessionId}`,
807
+ object: "chat.completion",
808
+ created: Math.floor(Date.now() / 1e3),
809
+ model,
810
+ choices: [
811
+ { index: 0, message: { role: "assistant", content: reply.text }, finish_reason: "stop" }
812
+ ],
813
+ opengeni: replyExtension(reply)
814
+ };
815
+ }
816
+ async function handleChatCompletionsRequest(og, request, resolve) {
817
+ const body = await readJsonObject(request);
818
+ const prompt = lastUserMessageText(body?.messages, CHAT_COMPLETION_PART_TYPES, "content")?.trim() ?? "";
819
+ if (!prompt) {
820
+ return errorResponse(400, "The last user message has no text.", "message_required");
821
+ }
822
+ const resolved = await resolveChatRequest(request, resolve);
823
+ if (resolved.response) return resolved.response;
824
+ const metadata = body?.metadata;
825
+ const metadataConversation = metadata && typeof metadata === "object" ? metadata.conversation_id : void 0;
826
+ const opened = await openResolvedChat(
827
+ og,
828
+ resolved.resolution,
829
+ clientConversation(request, metadataConversation)
830
+ );
831
+ if (opened.response) return opened.response;
832
+ const model = modelLabel(body);
833
+ const importedHistory = importedHistoryBefore(
834
+ body?.messages,
835
+ CHAT_COMPLETION_PART_TYPES,
836
+ "content"
837
+ );
838
+ if (wantsStream(body)) {
839
+ const chunks = opened.chat.stream(prompt, { signal: request.signal, importedHistory });
840
+ return new Response(sseByteStream(chatCompletionBlocks(opened.chat, chunks, model)), {
841
+ headers: sseHeaders()
842
+ });
843
+ }
844
+ try {
845
+ const reply = await opened.chat.send(prompt, { signal: request.signal, importedHistory });
846
+ return jsonResponse(chatCompletionObject(reply, model));
847
+ } catch (error) {
848
+ const summary = chatErrorSummary(error);
849
+ return errorResponse(summary.status, summary.message, summary.code);
850
+ }
851
+ }
852
+ function encodeResponseId(sessionId, sequence) {
853
+ return `resp_${sessionId}_${sequence}`;
854
+ }
855
+ function decodeResponseId(value) {
856
+ if (typeof value !== "string") return null;
857
+ const match = /^resp_([0-9a-f-]{36})(?:_(\d+|[0-9a-f-]{36}))?$/i.exec(value);
858
+ const sessionId = match?.[1];
859
+ const suffix = match?.[2];
860
+ if (suffix && !/^\d+$/.test(suffix) && !isUuid(suffix)) return null;
861
+ return sessionId && isUuid(sessionId) ? sessionId : null;
862
+ }
863
+ function responseOutputItem(itemId, status, text) {
864
+ return {
865
+ type: "message",
866
+ id: itemId,
867
+ status,
868
+ role: "assistant",
869
+ content: text === null ? [] : [{ type: "output_text", text, annotations: [] }]
870
+ };
871
+ }
872
+ function responseObject(reply, chat, model, status, previousResponseId, text, identity) {
873
+ const sequence = reply?.events.at(-1)?.sequence ?? 0;
874
+ return {
875
+ id: identity?.responseId ?? encodeResponseId(chat.sessionId, sequence),
876
+ object: "response",
877
+ created_at: identity?.createdAt ?? Math.floor(Date.now() / 1e3),
878
+ status,
879
+ model,
880
+ previous_response_id: previousResponseId,
881
+ output: status === "in_progress" ? [] : [
882
+ responseOutputItem(
883
+ identity?.itemId ?? `msg_${chat.sessionId}_${sequence}`,
884
+ status,
885
+ text
886
+ )
887
+ ],
888
+ output_text: text,
889
+ ...reply ? { opengeni: replyExtension(reply) } : {}
890
+ };
891
+ }
892
+ async function* responsesBlocks(chat, chunks, model, previousResponseId) {
893
+ let sequenceNumber = 0;
894
+ const requestId = crypto.randomUUID();
895
+ const identity = {
896
+ responseId: `resp_${chat.sessionId}_${requestId}`,
897
+ itemId: `msg_${chat.sessionId}_${requestId}`,
898
+ createdAt: Math.floor(Date.now() / 1e3)
899
+ };
900
+ const { itemId } = identity;
901
+ const event = (type, data) => sseLine(JSON.stringify({ type, sequence_number: sequenceNumber++, ...data }), type);
902
+ const initial = responseObject(
903
+ null,
904
+ chat,
905
+ model,
906
+ "in_progress",
907
+ previousResponseId,
908
+ "",
909
+ identity
910
+ );
911
+ yield event("response.created", { response: initial });
912
+ yield event("response.in_progress", { response: initial });
913
+ yield event("response.output_item.added", {
914
+ output_index: 0,
915
+ item: responseOutputItem(itemId, "in_progress", null)
916
+ });
917
+ yield event("response.content_part.added", {
918
+ item_id: itemId,
919
+ output_index: 0,
920
+ content_index: 0,
921
+ part: { type: "output_text", text: "", annotations: [] }
922
+ });
923
+ try {
924
+ for await (const chunk of chunks) {
925
+ if (chunk.type === "text") {
926
+ yield event("response.output_text.delta", {
927
+ item_id: itemId,
928
+ output_index: 0,
929
+ content_index: 0,
930
+ delta: chunk.text,
931
+ logprobs: []
932
+ });
933
+ } else if (chunk.type === "done") {
934
+ const status = chunk.reply.status === "completed" ? "completed" : "incomplete";
935
+ const item = responseOutputItem(itemId, status, chunk.reply.text);
936
+ yield event("response.output_text.done", {
937
+ item_id: itemId,
938
+ output_index: 0,
939
+ content_index: 0,
940
+ text: chunk.reply.text,
941
+ logprobs: []
942
+ });
943
+ yield event("response.content_part.done", {
944
+ item_id: itemId,
945
+ output_index: 0,
946
+ content_index: 0,
947
+ part: item.content[0]
948
+ });
949
+ yield event("response.output_item.done", { output_index: 0, item });
950
+ yield event(`response.${status}`, {
951
+ response: responseObject(
952
+ chunk.reply,
953
+ chat,
954
+ model,
955
+ status,
956
+ previousResponseId,
957
+ chunk.reply.text,
958
+ identity
959
+ )
960
+ });
961
+ }
962
+ }
963
+ } catch (error) {
964
+ const summary = chatErrorSummary(error);
965
+ yield event("error", { code: summary.code, message: summary.message, param: null });
966
+ }
967
+ }
968
+ function responsesInputText(input) {
969
+ if (typeof input === "string") return input;
970
+ if (!Array.isArray(input)) return null;
971
+ const fromRole = lastUserMessageText(input, ["input_text", "text"], "content");
972
+ if (fromRole !== null) return fromRole;
973
+ const last = input.at(-1);
974
+ return last && typeof last === "object" ? messageContentText(last.content, ["input_text", "text"]) : null;
975
+ }
976
+ async function handleResponsesRequest(og, request, resolve) {
977
+ const body = await readJsonObject(request);
978
+ const prompt = responsesInputText(body?.input)?.trim() ?? "";
979
+ if (!prompt) return errorResponse(400, "The input has no user text.", "message_required");
980
+ const resolved = await resolveChatRequest(request, resolve);
981
+ if (resolved.response) return resolved.response;
982
+ const previousResponseId = typeof body?.previous_response_id === "string" ? body.previous_response_id : null;
983
+ const conversation = clientConversation(request, conversationFromBody(body));
984
+ const previousSessionId = decodeResponseId(previousResponseId);
985
+ const namedConversation = resolved.resolution.conversation ?? (resolved.resolution.user ? conversation : void 0);
986
+ let chat;
987
+ if (previousSessionId && !namedConversation) {
988
+ if (!resolved.resolution.user) {
989
+ return errorResponse(
990
+ 400,
991
+ "Return a conversation from resolve, or a user so client conversation ids are scoped to that user.",
992
+ "conversation_required"
993
+ );
994
+ }
995
+ try {
996
+ const workspaceId = await og.workspaceId(resolved.resolution);
997
+ chat = await og.chatBySessionId({
998
+ workspaceId,
999
+ sessionId: previousSessionId,
1000
+ user: resolved.resolution.user
1001
+ });
1002
+ } catch (error) {
1003
+ const summary = chatErrorSummary(error);
1004
+ return errorResponse(summary.status, summary.message, summary.code);
1005
+ }
1006
+ } else {
1007
+ const opened = await openResolvedChat(og, resolved.resolution, conversation);
1008
+ if (opened.response) return opened.response;
1009
+ chat = opened.chat;
1010
+ if (previousSessionId && previousSessionId !== chat.sessionId) {
1011
+ const summary = chatErrorSummary(
1012
+ new OpenGeniChatError(
1013
+ "conversation_mismatch",
1014
+ "previous_response_id belongs to a different conversation than the one named for this request."
1015
+ )
1016
+ );
1017
+ return errorResponse(summary.status, summary.message, summary.code);
1018
+ }
1019
+ }
1020
+ const model = modelLabel(body);
1021
+ const importedHistory = importedHistoryBefore(
1022
+ body?.input,
1023
+ ["input_text", "text", "output_text"],
1024
+ "content"
1025
+ );
1026
+ if (wantsStream(body)) {
1027
+ const chunks = chat.stream(prompt, { signal: request.signal, importedHistory });
1028
+ return new Response(sseByteStream(responsesBlocks(chat, chunks, model, previousResponseId)), {
1029
+ headers: sseHeaders()
1030
+ });
1031
+ }
1032
+ try {
1033
+ const reply = await chat.send(prompt, { signal: request.signal, importedHistory });
1034
+ return jsonResponse(
1035
+ responseObject(
1036
+ reply,
1037
+ chat,
1038
+ model,
1039
+ reply.status === "completed" ? "completed" : "incomplete",
1040
+ previousResponseId,
1041
+ reply.text
1042
+ )
1043
+ );
1044
+ } catch (error) {
1045
+ const summary = chatErrorSummary(error);
1046
+ return errorResponse(summary.status, summary.message, summary.code);
1047
+ }
1048
+ }
1049
+
1050
+ // src/chat/vercel.ts
1051
+ var UI_MESSAGE_STREAM_HEADER = "x-vercel-ai-ui-message-stream";
1052
+ var UI_MESSAGE_STREAM_VERSION = "v1";
1053
+ async function* uiMessageStreamParts(chunks, options = {}) {
1054
+ const messageId = options.messageId ?? crypto.randomUUID();
1055
+ const textId = `text_${messageId}`;
1056
+ let textOpen = false;
1057
+ const closeText = () => {
1058
+ if (!textOpen) return [];
1059
+ textOpen = false;
1060
+ return [{ type: "text-end", id: textId }];
1061
+ };
1062
+ const framing = options.framing ?? true;
1063
+ if (framing) {
1064
+ yield { type: "start", messageId };
1065
+ yield { type: "start-step" };
1066
+ }
1067
+ try {
1068
+ for await (const chunk of chunks) {
1069
+ switch (chunk.type) {
1070
+ case "text":
1071
+ if (!textOpen) {
1072
+ textOpen = true;
1073
+ yield { type: "text-start", id: textId };
1074
+ }
1075
+ yield { type: "text-delta", id: textId, delta: chunk.text };
1076
+ break;
1077
+ case "tool": {
1078
+ if (!options.toolParts) break;
1079
+ yield* closeText();
1080
+ const toolCallId = chunk.callId ?? `call_${crypto.randomUUID()}`;
1081
+ const tool = { toolCallId, dynamic: true, providerExecuted: true };
1082
+ if (chunk.status === "started") {
1083
+ yield { type: "tool-input-start", ...tool, toolName: chunk.name };
1084
+ yield {
1085
+ type: "tool-input-available",
1086
+ ...tool,
1087
+ toolName: chunk.name,
1088
+ input: chunk.input ?? {}
1089
+ };
1090
+ } else if (chunk.status === "failed") {
1091
+ yield { type: "tool-output-error", ...tool, errorText: "The tool call failed." };
1092
+ } else {
1093
+ yield { type: "tool-output-available", ...tool, output: { status: chunk.status } };
1094
+ }
1095
+ break;
1096
+ }
1097
+ case "pending":
1098
+ yield* closeText();
1099
+ yield* pendingParts(chunk.pending);
1100
+ break;
1101
+ case "done":
1102
+ yield* closeText();
1103
+ break;
1104
+ }
1105
+ }
1106
+ yield* closeText();
1107
+ if (framing) {
1108
+ yield { type: "finish-step" };
1109
+ yield { type: "finish" };
1110
+ }
1111
+ } catch (error) {
1112
+ yield* closeText();
1113
+ yield { type: "error", errorText: chatErrorSummary(error).message };
1114
+ }
1115
+ }
1116
+ function* pendingParts(pending) {
1117
+ if (pending.kind === "approval") {
1118
+ const raw = asRecord(pending.payload);
1119
+ const rawItem = asRecord(raw.rawItem);
1120
+ yield {
1121
+ type: "tool-input-available",
1122
+ toolCallId: pending.requestId,
1123
+ toolName: pending.name ?? "tool",
1124
+ dynamic: true,
1125
+ providerExecuted: true,
1126
+ input: raw.arguments ?? rawItem.arguments ?? {}
1127
+ };
1128
+ yield {
1129
+ type: "tool-approval-request",
1130
+ toolCallId: pending.requestId,
1131
+ approvalId: pending.requestId
1132
+ };
1133
+ return;
1134
+ }
1135
+ yield { type: "data-opengeni-pending", data: pending };
1136
+ }
1137
+ async function* uiMessageStreamBlocks(chunks, options = {}) {
1138
+ for await (const part of uiMessageStreamParts(chunks, options)) {
1139
+ yield sseLine(JSON.stringify(part));
1140
+ }
1141
+ yield sseLine("[DONE]");
1142
+ }
1143
+ function chatChunksToUIMessageStream(chunks, options = {}) {
1144
+ return sseByteStream(uiMessageStreamBlocks(chunks, options), options.onCancel);
1145
+ }
1146
+ function uiMessageStreamResponse(chunks, options = {}) {
1147
+ return new Response(chatChunksToUIMessageStream(chunks, options), {
1148
+ headers: sseHeaders({ [UI_MESSAGE_STREAM_HEADER]: UI_MESSAGE_STREAM_VERSION })
1149
+ });
1150
+ }
1151
+ function lastUIMessageText(messages) {
1152
+ return lastUserMessageText(messages, ["text"], "parts");
1153
+ }
1154
+ async function handleVercelChatRequest(og, request, resolve, options = {}) {
1155
+ const body = await readJsonObject(request);
1156
+ const prompt = lastUIMessageText(body?.messages)?.trim() ?? "";
1157
+ if (!prompt) {
1158
+ return errorResponse(400, "The last user message has no text.", "message_required");
1159
+ }
1160
+ const resolved = await resolveChatRequest(request, resolve);
1161
+ if (resolved.response) return resolved.response;
1162
+ const opened = await openResolvedChat(
1163
+ og,
1164
+ resolved.resolution,
1165
+ clientConversation(request, body?.id)
1166
+ );
1167
+ if (opened.response) return opened.response;
1168
+ const steer = body?.trigger === "regenerate-message";
1169
+ const importedHistory = importedHistoryBefore(body?.messages, ["text"], "parts");
1170
+ return uiMessageStreamResponse(
1171
+ opened.chat.stream(prompt, { signal: request.signal, steer, importedHistory }),
1172
+ options.toolParts ? { toolParts: true } : {}
1173
+ );
1174
+ }
1175
+
1176
+ // src/chat/handler.ts
1177
+ var CHAT_FORMAT_HEADER = "x-opengeni-chat-format";
1178
+ var CHAT_FORMATS = /* @__PURE__ */ new Set([
1179
+ "native",
1180
+ "vercel",
1181
+ "openai-chat",
1182
+ "openai-responses"
1183
+ ]);
1184
+ function methodNotAllowed(allow) {
1185
+ return new Response(
1186
+ JSON.stringify({ error: { message: `Use ${allow}.`, code: "method_not_allowed" } }),
1187
+ { status: 405, headers: { Allow: allow, "Content-Type": "application/json; charset=utf-8" } }
1188
+ );
1189
+ }
1190
+ function createChatHandler(og, options) {
1191
+ return async (request) => {
1192
+ const isRespond = new URL(request.url).pathname.replace(/\/+$/, "").endsWith("/respond");
1193
+ if (isRespond) {
1194
+ if (request.method !== "POST") return methodNotAllowed("POST");
1195
+ return await handleNativeRespondRequest(og, request, options.resolve);
1196
+ }
1197
+ if (request.method === "GET") {
1198
+ return await handleNativeHistoryRequest(og, request, options.resolve);
1199
+ }
1200
+ if (request.method !== "POST") return methodNotAllowed("GET, POST");
1201
+ const headerFormat = request.headers.get(CHAT_FORMAT_HEADER);
1202
+ if (headerFormat !== null && !CHAT_FORMATS.has(headerFormat)) {
1203
+ return errorResponse(400, `Unknown chat format: ${headerFormat}`, "unknown_format");
1204
+ }
1205
+ const format = headerFormat ?? options.format ?? "native";
1206
+ switch (format) {
1207
+ case "vercel":
1208
+ return await handleVercelChatRequest(og, request, options.resolve, {
1209
+ toolParts: options.toolParts
1210
+ });
1211
+ case "openai-chat":
1212
+ return await handleChatCompletionsRequest(og, request, options.resolve);
1213
+ case "openai-responses":
1214
+ return await handleResponsesRequest(og, request, options.resolve);
1215
+ default:
1216
+ return await handleNativeChatRequest(og, request, options.resolve);
1217
+ }
1218
+ };
1219
+ }
1220
+ async function handleNativeChatRequest(og, request, resolve) {
1221
+ const body = await readJsonObject(request);
1222
+ const message = typeof body?.message === "string" ? body.message.trim() : "";
1223
+ if (!message) {
1224
+ return errorResponse(400, "Body must carry a non-empty message.", "message_required");
1225
+ }
1226
+ const resolved = await resolveChatRequest(request, resolve);
1227
+ if (resolved.response) return resolved.response;
1228
+ const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));
1229
+ if (opened.response) return opened.response;
1230
+ return chatChunksToSseResponse(opened.chat.stream(message, { signal: request.signal }));
1231
+ }
1232
+ async function handleNativeHistoryRequest(og, request, resolve) {
1233
+ const resolved = await resolveChatRequest(request, resolve);
1234
+ if (resolved.response) return resolved.response;
1235
+ const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));
1236
+ if (opened.response) return opened.response;
1237
+ try {
1238
+ const snapshot = await opened.chat.snapshot();
1239
+ return jsonResponse({
1240
+ conversation: opened.chat.conversation,
1241
+ sessionId: opened.chat.sessionId,
1242
+ created: opened.chat.created,
1243
+ ...snapshot
1244
+ });
1245
+ } catch (error) {
1246
+ const summary = chatErrorSummary(error);
1247
+ return errorResponse(summary.status, summary.message, summary.code);
1248
+ }
1249
+ }
1250
+ async function handleNativeRespondRequest(og, request, resolve) {
1251
+ const body = await readJsonObject(request);
1252
+ const input = respondInputFromBody(body);
1253
+ if (!input) {
1254
+ return errorResponse(
1255
+ 400,
1256
+ "Body must carry requestId plus decision, answers, or skip.",
1257
+ "respond_input_invalid"
1258
+ );
1259
+ }
1260
+ const resolved = await resolveChatRequest(request, resolve);
1261
+ if (resolved.response) return resolved.response;
1262
+ const opened = await openResolvedChat(og, resolved.resolution, clientConversation(request, null));
1263
+ if (opened.response) return opened.response;
1264
+ return chatChunksToSseResponse(opened.chat.respondStream(input, { signal: request.signal }));
1265
+ }
1266
+ function respondInputFromBody(body) {
1267
+ const requestId = typeof body?.requestId === "string" ? body.requestId : "";
1268
+ if (!body || !requestId) return null;
1269
+ if (body.decision === "approve" || body.decision === "reject") {
1270
+ return {
1271
+ requestId,
1272
+ decision: body.decision,
1273
+ ...typeof body.message === "string" ? { message: body.message } : {}
1274
+ };
1275
+ }
1276
+ if (Array.isArray(body.answers)) {
1277
+ const answers = body.answers.filter(
1278
+ (answer) => !!answer && typeof answer === "object" && typeof answer.questionId === "string" && Array.isArray(answer.values)
1279
+ );
1280
+ return { requestId, answers };
1281
+ }
1282
+ if (body.skip === true) return { requestId, skip: true };
1283
+ return null;
1284
+ }
1285
+ async function* chatChunksToSseBlocks(chunks) {
1286
+ try {
1287
+ for await (const chunk of chunks) {
1288
+ yield sseLine(JSON.stringify(chunk), "chunk");
1289
+ }
1290
+ } catch (error) {
1291
+ const summary = chatErrorSummary(error);
1292
+ yield sseLine(JSON.stringify({ code: summary.code, message: summary.message }), "error");
1293
+ }
1294
+ }
1295
+ function chatChunksToSseStream(chunks, onCancel) {
1296
+ return sseByteStream(chatChunksToSseBlocks(chunks), onCancel);
1297
+ }
1298
+ function chatChunksToSseResponse(chunks) {
1299
+ return new Response(chatChunksToSseStream(chunks), {
1300
+ headers: sseHeaders({ [CHAT_FORMAT_HEADER]: "native" })
1301
+ });
1302
+ }
1303
+ async function* parseChatChunkStream(stream) {
1304
+ for await (const message of parseSseStream(stream)) {
1305
+ let parsed;
1306
+ try {
1307
+ parsed = JSON.parse(message.data);
1308
+ } catch {
1309
+ continue;
1310
+ }
1311
+ if (message.event === "error") {
1312
+ const record = parsed ?? {};
1313
+ throw new OpenGeniChatError(
1314
+ typeof record.code === "string" ? record.code : "chat_error",
1315
+ typeof record.message === "string" ? record.message : "Chat request failed."
1316
+ );
1317
+ }
1318
+ if (parsed && typeof parsed === "object" && typeof parsed.type === "string") {
1319
+ yield parsed;
1320
+ }
1321
+ }
1322
+ }
1323
+ export {
1324
+ CHAT_CONVERSATION_HEADER,
1325
+ CHAT_FORMAT_HEADER,
1326
+ CHAT_SESSION_NAMESPACE,
1327
+ Chat,
1328
+ ChatTurnFold,
1329
+ DEFAULT_CHAT_SOURCE,
1330
+ DEFAULT_OPENGENI_BASE_URL,
1331
+ IMPORTED_HISTORY_MAX_CHARS,
1332
+ OpenGeni,
1333
+ OpenGeniChatError,
1334
+ OpenGeniSetupError,
1335
+ OpenGeni as Opengeni,
1336
+ UI_MESSAGE_STREAM_HEADER,
1337
+ UI_MESSAGE_STREAM_VERSION,
1338
+ approvalPending,
1339
+ chatChunksToSseBlocks,
1340
+ chatChunksToSseResponse,
1341
+ chatChunksToSseStream,
1342
+ chatChunksToUIMessageStream,
1343
+ chatCompletionBlocks,
1344
+ chatCompletionObject,
1345
+ chatIdempotencyKey,
1346
+ chatIdentityName,
1347
+ chatSessionId,
1348
+ createChatHandler,
1349
+ decodeResponseId,
1350
+ encodeResponseId,
1351
+ formatImportedHistory,
1352
+ handleChatCompletionsRequest,
1353
+ handleNativeChatRequest,
1354
+ handleNativeHistoryRequest,
1355
+ handleNativeRespondRequest,
1356
+ handleResponsesRequest,
1357
+ handleVercelChatRequest,
1358
+ humanInputPending,
1359
+ lastUIMessageText,
1360
+ parseChatChunkStream,
1361
+ respondInputFromBody,
1362
+ responsesBlocks,
1363
+ responsesInputText,
1364
+ uiMessageStreamBlocks,
1365
+ uiMessageStreamParts,
1366
+ uiMessageStreamResponse,
1367
+ uuidV5
1368
+ };
1369
+ //# sourceMappingURL=index.js.map