@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
package/src/errors.ts CHANGED
@@ -1,4 +1,9 @@
1
- /** Error for a non-2xx OpenGeni API response. */
1
+ import {
2
+ parseSessionUsageLimitReachedRefusal,
3
+ type ParsedSessionUsageLimitReachedRefusal,
4
+ } from "@opengeni/contracts/session-usage-limit-refusal";
5
+
6
+ /** Error for a non-2xx Opengeni API response. */
2
7
  export class OpenGeniApiError extends Error {
3
8
  readonly status: number;
4
9
  readonly code: string | undefined;
@@ -29,8 +34,8 @@ export class OpenGeniApiError extends Error {
29
34
  const displayMessage =
30
35
  options.displayMessage ??
31
36
  (gatewayFailure && fromResponse
32
- ? (decoded?.message ?? "OpenGeni is temporarily unavailable — retry.")
33
- : `OpenGeni API ${status}: ${message}`);
37
+ ? (decoded?.message ?? "Opengeni is temporarily unavailable — retry.")
38
+ : `Opengeni API ${status}: ${message}`);
34
39
  super(correlationId ? `${displayMessage} Reference: ${correlationId}.` : displayMessage);
35
40
  this.name = "OpenGeniApiError";
36
41
  this.status = status;
@@ -49,6 +54,200 @@ export class OpenGeniApiError extends Error {
49
54
  }
50
55
  }
51
56
 
57
+ /** Deployment or organization setup must be completed before private chats can be created. */
58
+ export class OpenGeniSetupError extends OpenGeniApiError {
59
+ constructor(error: OpenGeniApiError) {
60
+ super(error.status, error.body, {
61
+ code: "OPENGENI_SETUP_REQUIRED",
62
+ retryable: false,
63
+ correlationId: error.correlationId,
64
+ displayMessage:
65
+ "Private chats require organization_private_session_settings.enabled (migration 0323). " +
66
+ "An organization owner or admin can enable Only me chats in the web app under Organization settings > Security & data, " +
67
+ "or use updateOrganizationPrivateSessionSettings from @opengeni/sdk/organization-private-session-settings " +
68
+ "with enabled: true, the current expectedVersion and a stable operationId " +
69
+ "(PATCH /v1/organizations/:organizationId/private-session-settings; an organization key needs workspace:admin). " +
70
+ "If platform readiness is unavailable, ask the deployment operator to activate session tenancy first.",
71
+ });
72
+ this.name = "OpenGeniSetupError";
73
+ }
74
+ }
75
+
76
+ /** A settled usage ceiling refuses the next call; retry after reset or an authorized grant. */
77
+ export class OpenGeniAllowanceExhaustedError extends OpenGeniApiError {
78
+ readonly scope: "workspace" | "member";
79
+ readonly resetsAt: string | null;
80
+ readonly subjectId: string | undefined;
81
+
82
+ constructor(
83
+ status: number,
84
+ body: string,
85
+ options: ConstructorParameters<typeof OpenGeniApiError>[2] = {},
86
+ ) {
87
+ super(status, body, {
88
+ ...options,
89
+ code: "allowance_exhausted",
90
+ retryable: false,
91
+ outcomeUnknown: false,
92
+ });
93
+ this.name = "OpenGeniAllowanceExhaustedError";
94
+ const refusal = allowanceExhaustedFields(body);
95
+ this.scope = refusal?.scope ?? "workspace";
96
+ this.resetsAt = refusal?.resetsAt ?? null;
97
+ this.subjectId = refusal?.subjectId;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * The task's root usage limit is reached: recorded API-equivalent model usage
103
+ * is at or above the limit. Not a credit or billing failure and not retryable
104
+ * by waiting; a person can raise or remove the limit, then send again.
105
+ */
106
+ export class OpenGeniSessionUsageLimitReachedError extends OpenGeniApiError {
107
+ readonly rootSessionId: string | undefined;
108
+ readonly limitMicros: number | undefined;
109
+ readonly usedMicros: number | undefined;
110
+
111
+ constructor(
112
+ status: number,
113
+ body: string,
114
+ options: ConstructorParameters<typeof OpenGeniApiError>[2] = {},
115
+ ) {
116
+ super(status, body, {
117
+ ...options,
118
+ code: "session_usage_limit_reached",
119
+ retryable: false,
120
+ outcomeUnknown: false,
121
+ });
122
+ this.name = "OpenGeniSessionUsageLimitReachedError";
123
+ const refusal = sessionUsageLimitReachedFields(body);
124
+ this.rootSessionId = refusal?.rootSessionId;
125
+ this.limitMicros = refusal?.limitMicros;
126
+ this.usedMicros = refusal?.usedMicros;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * The server did not accept or confirm a requested task usage limit, so it
132
+ * predates usage limits (or limits are not enabled there). `sessionId` is null
133
+ * when the server rejected the create before creating anything; otherwise the
134
+ * session exists without a confirmed limit and no initial work was started by
135
+ * this SDK's request (an older server rejects it up front).
136
+ */
137
+ export class OpenGeniSessionUsageLimitUnsupportedError extends Error {
138
+ readonly code = "session_usage_limit_unsupported";
139
+ readonly sessionId: string | null;
140
+
141
+ constructor(message: string, options: { sessionId?: string | null; cause?: unknown } = {}) {
142
+ super(message, options.cause === undefined ? undefined : { cause: options.cause });
143
+ this.name = "OpenGeniSessionUsageLimitUnsupportedError";
144
+ this.sessionId = options.sessionId ?? null;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * True only when a create was refused because the server rejected the
150
+ * `startMode` field itself: servers that predate usage limits accept only
151
+ * `realtime` there. Matches the session create route's 422 validation
152
+ * envelope (`Invalid session create request: <fields> failed schema
153
+ * validation`) and a 400 request-body envelope whose issues name `startMode`.
154
+ * Any other validation error stays an ordinary API error.
155
+ */
156
+ export function rejectsStartModeField(error: OpenGeniApiError): boolean {
157
+ if (error.status !== 400 && error.status !== 422) return false;
158
+ let parsed: unknown;
159
+ try {
160
+ parsed = JSON.parse(error.body);
161
+ } catch {
162
+ return false;
163
+ }
164
+ if (!parsed || typeof parsed !== "object") return false;
165
+ const record = parsed as Record<string, unknown>;
166
+ const envelope =
167
+ record.error && typeof record.error === "object"
168
+ ? (record.error as Record<string, unknown>)
169
+ : record;
170
+ const message = typeof envelope.message === "string" ? envelope.message : "";
171
+ const fields = /^Invalid session create request: (.+) failed schema validation$/.exec(message);
172
+ if (
173
+ envelope.code === "INVALID_SESSION_CREATE_REQUEST" &&
174
+ fields?.[1]?.split(/,\s*/).includes("startMode")
175
+ ) {
176
+ return true;
177
+ }
178
+ const details =
179
+ envelope.details && typeof envelope.details === "object"
180
+ ? (envelope.details as Record<string, unknown>)
181
+ : null;
182
+ const issues = Array.isArray(details?.issues) ? details.issues : [];
183
+ return issues.some((issue) => {
184
+ if (!issue || typeof issue !== "object") return false;
185
+ const path = (issue as Record<string, unknown>).path;
186
+ return (
187
+ path === "startMode" || (Array.isArray(path) && path.length === 1 && path[0] === "startMode")
188
+ );
189
+ });
190
+ }
191
+
192
+ /** The committed limit differs from the one requested: never report success. */
193
+ export function sessionUsageLimitNotConfirmed(
194
+ sessionId: string,
195
+ ): OpenGeniSessionUsageLimitUnsupportedError {
196
+ return new OpenGeniSessionUsageLimitUnsupportedError(
197
+ "The server did not confirm the requested usage limit; it may not support usage limits. Read the limit again before relying on it.",
198
+ { sessionId },
199
+ );
200
+ }
201
+
202
+ /** Parse a session usage limit refusal from an API error envelope body. */
203
+ export function sessionUsageLimitReachedFields(
204
+ body: string,
205
+ ): ParsedSessionUsageLimitReachedRefusal | null {
206
+ try {
207
+ const parsed: unknown = JSON.parse(body);
208
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
209
+ const root = parsed as Record<string, unknown>;
210
+ return parseSessionUsageLimitReachedRefusal(
211
+ root.error && typeof root.error === "object" && !Array.isArray(root.error)
212
+ ? root.error
213
+ : root,
214
+ );
215
+ } catch {
216
+ return null;
217
+ }
218
+ }
219
+
220
+ /** Accept both the API error envelope and the standalone admission refusal. */
221
+ export function allowanceExhaustedFields(body: string): {
222
+ scope: "workspace" | "member";
223
+ resetsAt: string | null;
224
+ subjectId?: string;
225
+ } | null {
226
+ try {
227
+ const parsed: unknown = JSON.parse(body);
228
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
229
+ const root = parsed as Record<string, unknown>;
230
+ const error =
231
+ root.error && typeof root.error === "object" && !Array.isArray(root.error)
232
+ ? (root.error as Record<string, unknown>)
233
+ : root;
234
+ if (error.code !== "allowance_exhausted") return null;
235
+ const fields =
236
+ error.details && typeof error.details === "object" && !Array.isArray(error.details)
237
+ ? (error.details as Record<string, unknown>)
238
+ : error;
239
+ if (fields.scope !== "workspace" && fields.scope !== "member") return null;
240
+ if (fields.resetsAt !== null && typeof fields.resetsAt !== "string") return null;
241
+ return {
242
+ scope: fields.scope,
243
+ resetsAt: fields.resetsAt,
244
+ ...(typeof fields.subjectId === "string" ? { subjectId: fields.subjectId } : {}),
245
+ };
246
+ } catch {
247
+ return null;
248
+ }
249
+ }
250
+
52
251
  export type OpenGeniSecureContextRequiredReason = "insecure_context" | "web_crypto_unavailable";
53
252
 
54
253
  /**
@@ -64,7 +263,7 @@ export class OpenGeniSecureContextRequiredError extends Error {
64
263
  constructor(reason: OpenGeniSecureContextRequiredReason) {
65
264
  super(
66
265
  reason === "insecure_context"
67
- ? "Couldn’t attach this file because OpenGeni is open over HTTP. Attachments require a secure HTTPS connection. Open the secure site or configure HTTPS for this deployment."
266
+ ? "Couldn’t attach this file because Opengeni is open over HTTP. Attachments require a secure HTTPS connection. Open the secure site or configure HTTPS for this deployment."
68
267
  : "Couldn’t attach this file because secure browser cryptography is unavailable. Attachments require HTTPS and Web Crypto support. Open a secure site in a supported browser or configure HTTPS for this deployment.",
69
268
  );
70
269
  this.name = "OpenGeniSecureContextRequiredError";
@@ -160,7 +359,7 @@ export class OpenGeniApiContractMismatchError extends Error {
160
359
  readonly actual: string;
161
360
 
162
361
  constructor(expected: string, actual: string) {
163
- super(`OpenGeni API contract mismatch: client expects ${expected}, API serves ${actual}`);
362
+ super(`Opengeni API contract mismatch: client expects ${expected}, API serves ${actual}`);
164
363
  this.name = "OpenGeniApiContractMismatchError";
165
364
  this.expected = expected;
166
365
  this.actual = actual;
@@ -175,6 +374,83 @@ export class OpenGeniStreamError extends Error {
175
374
  }
176
375
  }
177
376
 
377
+ /**
378
+ * Brand-neutral end-user copy for a failed SDK operation. Error.message, body,
379
+ * details and typed fields remain unchanged for diagnostics and host policy.
380
+ * Never use this to rewrite user, assistant or tool content.
381
+ */
382
+ export function formatErrorMessage(
383
+ error: unknown,
384
+ fallback = "The request could not be completed.",
385
+ ): string {
386
+ if (error instanceof OpenGeniApiError) {
387
+ let message: string;
388
+ if (error.outcomeUnknown) {
389
+ message = "The request could not be confirmed. Check its status before retrying.";
390
+ } else if (
391
+ error instanceof OpenGeniSetupError ||
392
+ error.code === "OPENGENI_SETUP_REQUIRED" ||
393
+ error.code === "SESSION_TENANCY_NOT_ACTIVATED"
394
+ ) {
395
+ message = "Private conversations are unavailable. Ask an administrator to enable them.";
396
+ } else if (error.details?.code === "not_available_for_viewer") {
397
+ message = "This Site's assistant is not available for this viewer.";
398
+ } else if (error.details?.code === "site_budget_exhausted") {
399
+ message = "This Site's assistant has reached its usage limit for now.";
400
+ } else if (error.details?.code === "site_budget_busy") {
401
+ message = "This Site's assistant is busy. Try again in a moment.";
402
+ } else if (error.details?.code === "site_platform_brake_engaged") {
403
+ message = "This Site's assistant is paused for visitors right now.";
404
+ } else if (error.code === "allowance_exhausted") {
405
+ message = "Usage limit reached. Wait for the reset or ask an administrator for more usage.";
406
+ } else if (error instanceof OpenGeniSessionListCursorError) {
407
+ message = "The conversation list changed. Refresh and try again.";
408
+ } else if (error.status === 401) {
409
+ message = "Sign in to continue.";
410
+ } else if (error.status === 403) {
411
+ message = "You don’t have permission to do that.";
412
+ } else if (error.status === 404) {
413
+ message = "The requested item is unavailable.";
414
+ } else if (error.status === 402 || error.code === "payment_required") {
415
+ message = "There are not enough credits to continue.";
416
+ } else if (error.status === 429 || error.code === "rate_limited") {
417
+ message = error.retryable
418
+ ? "Too many requests. Wait a moment and try again."
419
+ : "This request is unavailable. Ask an administrator for help.";
420
+ } else if (error.status === 409) {
421
+ message = "The request conflicts with the current state. Refresh and try again.";
422
+ } else if (error.status === 400 || error.status === 422) {
423
+ message = "The request could not be accepted. Check your input and try again.";
424
+ } else if (error.status === 408 || error.status === 425 || error.status === 0) {
425
+ message = error.retryable
426
+ ? "The connection could not be completed. Try again later."
427
+ : fallback;
428
+ } else if (error.status >= 500) {
429
+ message = error.retryable
430
+ ? "The service is temporarily unavailable. Try again later."
431
+ : "The service is unavailable. Ask an administrator for help.";
432
+ } else {
433
+ message = fallback;
434
+ }
435
+ return error.correlationId ? `${message} Reference: ${error.correlationId}.` : message;
436
+ }
437
+ if (
438
+ error instanceof OpenGeniSecureContextRequiredError ||
439
+ (error instanceof Error && "code" in error && error.code === "secure_context_required")
440
+ ) {
441
+ return "reason" in error && error.reason === "insecure_context"
442
+ ? "Attachments require HTTPS. Open this page over a secure connection."
443
+ : "Attachments require secure browser cryptography. Use a supported browser over HTTPS.";
444
+ }
445
+ if (error instanceof OpenGeniApiContractMismatchError) {
446
+ return "This page is out of date. Reload it before trying again.";
447
+ }
448
+ if (error instanceof OpenGeniStreamError) {
449
+ return "The live connection could not be restored. Refresh to check the latest state.";
450
+ }
451
+ return fallback;
452
+ }
453
+
178
454
  export function isAbortError(error: unknown): boolean {
179
455
  return (
180
456
  (error instanceof DOMException && error.name === "AbortError") ||