@opengeni/sdk 0.57.0 → 1.0.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 (291) hide show
  1. package/README.md +1017 -26
  2. package/dist/accounts.d.ts +153 -0
  3. package/dist/accounts.js +307 -0
  4. package/dist/accounts.js.map +1 -0
  5. package/dist/adapters/express.d.ts +31 -0
  6. package/dist/adapters/express.js +87 -0
  7. package/dist/adapters/express.js.map +1 -0
  8. package/dist/adapters/hono.d.ts +16 -0
  9. package/dist/adapters/hono.js +8 -0
  10. package/dist/adapters/hono.js.map +1 -0
  11. package/dist/adapters/next.d.ts +29 -0
  12. package/dist/adapters/next.js +22 -0
  13. package/dist/adapters/next.js.map +1 -0
  14. package/dist/allowance-refusal.d.ts +2 -0
  15. package/dist/allowance-refusal.js +50 -0
  16. package/dist/allowance-refusal.js.map +1 -0
  17. package/dist/artifact-catalog.d.ts +31 -0
  18. package/dist/artifact-client.d.ts +23 -11
  19. package/dist/artifacts.d.ts +1 -1
  20. package/dist/artifacts.js +7 -5
  21. package/dist/automations-client.d.ts +17 -0
  22. package/dist/automations.d.ts +3 -0
  23. package/dist/automations.js +84 -0
  24. package/dist/automations.js.map +1 -0
  25. package/dist/browser.d.ts +11 -0
  26. package/dist/browser.js +47 -0
  27. package/dist/browser.js.map +1 -0
  28. package/dist/chat/fold.d.ts +75 -0
  29. package/dist/chat/handler.d.ts +41 -0
  30. package/dist/chat/http.d.ts +67 -0
  31. package/dist/chat/ids.d.ts +34 -0
  32. package/dist/chat/index.d.ts +9 -0
  33. package/dist/chat/index.js +1694 -0
  34. package/dist/chat/index.js.map +1 -0
  35. package/dist/chat/openai.d.ts +30 -0
  36. package/dist/chat/opengeni.d.ts +128 -0
  37. package/dist/chat/types.d.ts +207 -0
  38. package/dist/chat/vercel.d.ts +49 -0
  39. package/dist/chats.d.ts +8 -0
  40. package/dist/{chunk-JDLDDRNE.js → chunk-2UXZUCEZ.js} +291 -34
  41. package/dist/chunk-2UXZUCEZ.js.map +1 -0
  42. package/dist/chunk-4SMEOV3P.js +246 -0
  43. package/dist/chunk-4SMEOV3P.js.map +1 -0
  44. package/dist/{chunk-JRPFWI6T.js → chunk-AH5D5Q5V.js} +31 -35
  45. package/dist/chunk-AH5D5Q5V.js.map +1 -0
  46. package/dist/chunk-APXVSSSY.js +301 -0
  47. package/dist/chunk-APXVSSSY.js.map +1 -0
  48. package/dist/chunk-DUVIYER4.js +639 -0
  49. package/dist/chunk-DUVIYER4.js.map +1 -0
  50. package/dist/{chunk-PKQ377ED.js → chunk-FG3OO5LM.js} +2686 -611
  51. package/dist/chunk-FG3OO5LM.js.map +1 -0
  52. package/dist/chunk-GZYZT22T.js +260 -0
  53. package/dist/chunk-GZYZT22T.js.map +1 -0
  54. package/dist/chunk-HMGADJGZ.js +150 -0
  55. package/dist/chunk-HMGADJGZ.js.map +1 -0
  56. package/dist/{chunk-YKZME56C.js → chunk-KWADQ227.js} +3 -3
  57. package/dist/{chunk-YKZME56C.js.map → chunk-KWADQ227.js.map} +1 -1
  58. package/dist/chunk-LY2K6ELJ.js +126 -0
  59. package/dist/chunk-LY2K6ELJ.js.map +1 -0
  60. package/dist/chunk-MOTJYIYL.js +340 -0
  61. package/dist/chunk-MOTJYIYL.js.map +1 -0
  62. package/dist/{chunk-ST5DDKJP.js → chunk-NC57YMUO.js} +121 -3
  63. package/dist/chunk-NC57YMUO.js.map +1 -0
  64. package/dist/chunk-RWKB6YZG.js +1270 -0
  65. package/dist/chunk-RWKB6YZG.js.map +1 -0
  66. package/dist/chunk-U6CV2SXO.js +195 -0
  67. package/dist/chunk-U6CV2SXO.js.map +1 -0
  68. package/dist/chunk-UM4ZXXJR.js +9 -0
  69. package/dist/chunk-UM4ZXXJR.js.map +1 -0
  70. package/dist/chunk-V6GIY62B.js +229 -0
  71. package/dist/chunk-V6GIY62B.js.map +1 -0
  72. package/dist/chunk-WU6GQG25.js +268 -0
  73. package/dist/chunk-WU6GQG25.js.map +1 -0
  74. package/dist/{chunk-VWE2QIVO.js → chunk-XNG7YGR3.js} +23 -6
  75. package/dist/chunk-XNG7YGR3.js.map +1 -0
  76. package/dist/{chunk-HJ3HHUT5.js → chunk-YIKA2QT4.js} +33 -2
  77. package/dist/chunk-YIKA2QT4.js.map +1 -0
  78. package/dist/chunk-ZKPY6YAJ.js +135 -0
  79. package/dist/chunk-ZKPY6YAJ.js.map +1 -0
  80. package/dist/client.d.ts +740 -94
  81. package/dist/codex-realtime-controller.d.ts +3 -0
  82. package/dist/codex-realtime-controller.js +2 -2
  83. package/dist/codex-realtime-v3.d.ts +13 -2
  84. package/dist/company-brain.d.ts +22 -0
  85. package/dist/company-profile.d.ts +14 -1
  86. package/dist/core.d.ts +9 -3
  87. package/dist/core.js +25 -6
  88. package/dist/deprecation.d.ts +47 -0
  89. package/dist/document-authority-client.d.ts +51 -0
  90. package/dist/document-authority.d.ts +2 -0
  91. package/dist/document-authority.js +12 -0
  92. package/dist/document-authority.js.map +1 -0
  93. package/dist/editable-artifacts/browser-session.d.ts +7 -3
  94. package/dist/editable-artifacts/controller.d.ts +4 -1
  95. package/dist/editable-artifacts/errors.d.ts +1 -1
  96. package/dist/editable-artifacts/http-live-transport.d.ts +6 -2
  97. package/dist/editable-artifacts/index.d.ts +2 -0
  98. package/dist/editable-artifacts/open-failure.d.ts +9 -0
  99. package/dist/editable-artifacts/types.d.ts +6 -3
  100. package/dist/editable-artifacts/worker/kernel-adapter.d.ts +1 -1
  101. package/dist/editable-artifacts-worker.js +44 -17
  102. package/dist/editable-artifacts-worker.js.map +1 -1
  103. package/dist/editable-artifacts.js +240 -121
  104. package/dist/editable-artifacts.js.map +1 -1
  105. package/dist/embedding-client.d.ts +129 -0
  106. package/dist/errors.d.ts +36 -1
  107. package/dist/feedback.d.ts +23 -0
  108. package/dist/gateway-realtime-transport.js +1 -1
  109. package/dist/github-repositories.d.ts +10 -0
  110. package/dist/github-repositories.js +36 -0
  111. package/dist/github-repositories.js.map +1 -0
  112. package/dist/index.d.ts +56 -11
  113. package/dist/index.js +242 -125
  114. package/dist/index.js.map +1 -1
  115. package/dist/interaction.d.ts +84 -1
  116. package/dist/interaction.js +6 -1
  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/message-links.d.ts +68 -0
  121. package/dist/model-context.d.ts +68 -0
  122. package/dist/model-display.d.ts +2 -0
  123. package/dist/model-display.js +15 -0
  124. package/dist/model-display.js.map +1 -0
  125. package/dist/model-picker-order.d.ts +1 -0
  126. package/dist/model-picker-order.js +10 -0
  127. package/dist/model-picker-order.js.map +1 -0
  128. package/dist/organization-integration-policy.d.ts +26 -0
  129. package/dist/organization-integration-policy.js +26 -0
  130. package/dist/organization-integration-policy.js.map +1 -0
  131. package/dist/organization-private-session-settings.d.ts +6 -0
  132. package/dist/organization-private-session-settings.js +22 -0
  133. package/dist/organization-private-session-settings.js.map +1 -0
  134. package/dist/organization-user-setup.d.ts +8 -0
  135. package/dist/organization-user-setup.js +16 -0
  136. package/dist/organization-user-setup.js.map +1 -0
  137. package/dist/pr-review-client.d.ts +16 -0
  138. package/dist/pr-review.d.ts +4 -0
  139. package/dist/pr-review.js +62 -0
  140. package/dist/pr-review.js.map +1 -0
  141. package/dist/preference-registry.d.ts +9 -1
  142. package/dist/proxy.d.ts +7 -5
  143. package/dist/realtime.d.ts +3 -1
  144. package/dist/realtime.js +6 -6
  145. package/dist/realtime.js.map +1 -1
  146. package/dist/retained-artifacts.d.ts +5 -1
  147. package/dist/session-history-import.d.ts +22 -0
  148. package/dist/session-history-import.js +36 -0
  149. package/dist/session-history-import.js.map +1 -0
  150. package/dist/session-list-entries.d.ts +1 -0
  151. package/dist/session-list-entries.js +7 -0
  152. package/dist/session-list-entries.js.map +1 -0
  153. package/dist/session-message-search.d.ts +53 -0
  154. package/dist/session-proxy-client.d.ts +24 -0
  155. package/dist/session-proxy.d.ts +245 -0
  156. package/dist/session-proxy.js +24 -0
  157. package/dist/session-proxy.js.map +1 -0
  158. package/dist/session-titles.d.ts +2 -0
  159. package/dist/site-browser-entry.d.ts +1 -0
  160. package/dist/site-browser-runtime.gen.d.ts +1 -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 +16 -0
  166. package/dist/site-tool-bridge.d.ts +44 -0
  167. package/dist/site.d.ts +101 -0
  168. package/dist/site.js +49 -0
  169. package/dist/site.js.map +1 -0
  170. package/dist/skills.d.ts +75 -0
  171. package/dist/stream.d.ts +2 -0
  172. package/dist/tenant-workspaces.d.ts +47 -0
  173. package/dist/tenant-workspaces.js +8 -0
  174. package/dist/tenant-workspaces.js.map +1 -0
  175. package/dist/tool-auth.d.ts +87 -0
  176. package/dist/tool-auth.js +23 -0
  177. package/dist/tool-auth.js.map +1 -0
  178. package/dist/tool-display-metadata.d.ts +3 -0
  179. package/dist/tools-FXBLUWAE.js +12 -0
  180. package/dist/tools-FXBLUWAE.js.map +1 -0
  181. package/dist/tools.d.ts +61 -0
  182. package/dist/types.d.ts +2863 -424
  183. package/dist/usage-allowances.d.ts +36 -0
  184. package/dist/usage-allowances.js +80 -0
  185. package/dist/usage-allowances.js.map +1 -0
  186. package/dist/workspace-artifacts.d.ts +33 -5
  187. package/dist/workspace-instruction-policies.d.ts +24 -2
  188. package/dist/workspace-integrations.d.ts +74 -0
  189. package/dist/workspace-integrations.js +65 -0
  190. package/dist/workspace-integrations.js.map +1 -0
  191. package/dist/workspace-learning.d.ts +124 -0
  192. package/dist/workspace-state.d.ts +8 -71
  193. package/package.json +108 -3
  194. package/src/accounts.ts +443 -0
  195. package/src/adapters/express.ts +136 -0
  196. package/src/adapters/hono.ts +18 -0
  197. package/src/adapters/next.ts +42 -0
  198. package/src/allowance-refusal.ts +5 -0
  199. package/src/artifact-catalog.ts +41 -0
  200. package/src/artifact-client.ts +43 -52
  201. package/src/artifacts.ts +7 -1
  202. package/src/automations-client.ts +124 -0
  203. package/src/automations.ts +15 -0
  204. package/src/browser.ts +54 -0
  205. package/src/chat/fold.ts +431 -0
  206. package/src/chat/handler.ts +240 -0
  207. package/src/chat/http.ts +257 -0
  208. package/src/chat/ids.ts +85 -0
  209. package/src/chat/index.ts +87 -0
  210. package/src/chat/openai.ts +439 -0
  211. package/src/chat/opengeni.ts +722 -0
  212. package/src/chat/types.ts +219 -0
  213. package/src/chat/vercel.ts +204 -0
  214. package/src/chats.ts +16 -0
  215. package/src/client.ts +4084 -515
  216. package/src/codex-realtime-controller.ts +235 -5
  217. package/src/codex-realtime-v3.ts +162 -31
  218. package/src/codex-realtime.ts +1 -1
  219. package/src/company-brain.ts +59 -0
  220. package/src/company-profile.ts +17 -1
  221. package/src/core.ts +23 -1
  222. package/src/deprecation.ts +149 -0
  223. package/src/document-authority-client.ts +219 -0
  224. package/src/document-authority.ts +17 -0
  225. package/src/editable-artifacts/browser-session.ts +36 -22
  226. package/src/editable-artifacts/controller.ts +102 -47
  227. package/src/editable-artifacts/errors.ts +2 -0
  228. package/src/editable-artifacts/http-live-transport.ts +62 -37
  229. package/src/editable-artifacts/index.ts +6 -0
  230. package/src/editable-artifacts/open-failure.ts +79 -0
  231. package/src/editable-artifacts/storage.ts +31 -40
  232. package/src/editable-artifacts/types.ts +6 -3
  233. package/src/editable-artifacts/worker/kernel-adapter.ts +23 -7
  234. package/src/editable-artifacts/worker/runtime.ts +26 -13
  235. package/src/editable-artifacts/worker/wire-codec.ts +23 -5
  236. package/src/embedding-client.ts +519 -0
  237. package/src/errors.ts +169 -2
  238. package/src/feedback.ts +20 -0
  239. package/src/gateway-realtime-transport.ts +3 -3
  240. package/src/github-repositories.ts +60 -0
  241. package/src/index.ts +561 -41
  242. package/src/interaction.ts +276 -4
  243. package/src/knowledge.ts +72 -0
  244. package/src/message-links.ts +178 -0
  245. package/src/model-context.ts +112 -0
  246. package/src/model-display.ts +10 -0
  247. package/src/model-picker-order.ts +6 -0
  248. package/src/organization-integration-policy.ts +54 -0
  249. package/src/organization-private-session-settings.ts +33 -0
  250. package/src/organization-user-setup.ts +31 -0
  251. package/src/pr-review-client.ts +92 -0
  252. package/src/pr-review.ts +17 -0
  253. package/src/preference-registry.ts +11 -0
  254. package/src/proxy.ts +17 -6
  255. package/src/realtime.ts +1 -0
  256. package/src/retained-artifacts.ts +101 -0
  257. package/src/session-history-import.ts +84 -0
  258. package/src/session-list-entries.ts +1 -0
  259. package/src/session-message-search.ts +47 -0
  260. package/src/session-proxy-client.ts +64 -0
  261. package/src/session-proxy.ts +1473 -0
  262. package/src/session-titles.ts +10 -0
  263. package/src/site-browser-entry.ts +6 -0
  264. package/src/site-browser-runtime.gen.ts +2 -0
  265. package/src/site-document.test.ts +64 -0
  266. package/src/site-document.ts +18 -0
  267. package/src/site-http.ts +162 -0
  268. package/src/site-tool-bridge.ts +146 -0
  269. package/src/site.ts +585 -0
  270. package/src/skills.ts +69 -0
  271. package/src/sse.ts +8 -2
  272. package/src/stream.ts +38 -4
  273. package/src/tenant-workspaces.ts +148 -0
  274. package/src/tool-auth.ts +301 -0
  275. package/src/tool-display-metadata.ts +19 -0
  276. package/src/tools.ts +396 -0
  277. package/src/types.ts +3346 -501
  278. package/src/usage-allowances.ts +189 -0
  279. package/src/workspace-artifacts.ts +40 -6
  280. package/src/workspace-instruction-policies.ts +26 -1
  281. package/src/workspace-integrations.ts +402 -0
  282. package/src/workspace-learning.ts +138 -0
  283. package/src/workspace-state.ts +8 -82
  284. package/dist/chunk-GU6JF75T.js +0 -119
  285. package/dist/chunk-GU6JF75T.js.map +0 -1
  286. package/dist/chunk-HJ3HHUT5.js.map +0 -1
  287. package/dist/chunk-JDLDDRNE.js.map +0 -1
  288. package/dist/chunk-JRPFWI6T.js.map +0 -1
  289. package/dist/chunk-PKQ377ED.js.map +0 -1
  290. package/dist/chunk-ST5DDKJP.js.map +0 -1
  291. package/dist/chunk-VWE2QIVO.js.map +0 -1
@@ -1,3 +1,10 @@
1
+ import {
2
+ jitteredDelay,
3
+ parseSseStream,
4
+ runBeforeLive,
5
+ streamSessionEvents,
6
+ withStreamInactivityTimeout
7
+ } from "./chunk-APXVSSSY.js";
1
8
  import {
2
9
  COMPUTER_SCREENSHOT_MAX_BYTES,
3
10
  GENERATED_VIDEO_MAX_BYTES,
@@ -5,276 +12,105 @@ import {
5
12
  OPENGENI_API_CONTRACT_REVISION,
6
13
  OPENGENI_CORRELATION_HEADER,
7
14
  RETAINED_OUTPUT_MAX_PAGE_BYTES
8
- } from "./chunk-HJ3HHUT5.js";
15
+ } from "./chunk-YIKA2QT4.js";
16
+ import {
17
+ OpenGeniInteractionClient,
18
+ decodeComputerFrameMetadataHeader,
19
+ parseBrowserFrameMetadata
20
+ } from "./chunk-NC57YMUO.js";
9
21
  import {
22
+ OpenGeniAllowanceExhaustedError,
10
23
  OpenGeniApiContractMismatchError,
11
24
  OpenGeniApiError,
25
+ OpenGeniSecureContextRequiredError,
12
26
  OpenGeniSessionListCursorError,
27
+ OpenGeniSetupError,
13
28
  OpenGeniStreamError,
29
+ allowanceExhaustedFields,
14
30
  isAbortError,
15
31
  isRetryableStreamError
16
- } from "./chunk-GU6JF75T.js";
17
- import {
18
- OpenGeniInteractionClient
19
- } from "./chunk-ST5DDKJP.js";
20
-
21
- // src/sse.ts
22
- async function* parseSseStream(stream) {
23
- const reader = stream.getReader();
24
- const decoder = new TextDecoder();
25
- let buffer = "";
26
- let id;
27
- let event;
28
- let dataLines = null;
29
- const dispatch = () => {
30
- const message = dataLines === null ? null : {
31
- ...id !== void 0 ? { id } : {},
32
- ...event !== void 0 ? { event } : {},
33
- data: dataLines.join("\n")
34
- };
35
- id = void 0;
36
- event = void 0;
37
- dataLines = null;
38
- return message;
39
- };
40
- const handleLine = (line) => {
41
- if (line === "") {
42
- return dispatch();
43
- }
44
- if (line.startsWith(":")) {
45
- return null;
46
- }
47
- const colon = line.indexOf(":");
48
- const field = colon === -1 ? line : line.slice(0, colon);
49
- let value = colon === -1 ? "" : line.slice(colon + 1);
50
- if (value.startsWith(" ")) {
51
- value = value.slice(1);
52
- }
53
- if (field === "data") {
54
- (dataLines ??= []).push(value);
55
- } else if (field === "event") {
56
- event = value;
57
- } else if (field === "id") {
58
- id = value;
59
- }
60
- return null;
61
- };
62
- try {
63
- while (true) {
64
- const { done, value } = await reader.read();
65
- if (done) {
66
- break;
67
- }
68
- buffer += decoder.decode(value, { stream: true });
69
- let newline = buffer.indexOf("\n");
70
- while (newline !== -1) {
71
- let line = buffer.slice(0, newline);
72
- buffer = buffer.slice(newline + 1);
73
- if (line.endsWith("\r")) {
74
- line = line.slice(0, -1);
75
- }
76
- const message = handleLine(line);
77
- if (message) {
78
- yield message;
79
- }
80
- newline = buffer.indexOf("\n");
81
- }
82
- }
83
- } finally {
84
- await reader.cancel().catch(() => {
85
- });
86
- reader.releaseLock();
87
- }
88
- }
32
+ } from "./chunk-V6GIY62B.js";
89
33
 
90
- // src/stream.ts
91
- async function* streamSessionEvents(transport, options = {}) {
92
- const signal = options.signal;
93
- const reconnect = options.reconnect ?? true;
94
- const baseDelayMs = options.reconnectDelayMs ?? 500;
95
- const maxDelayMs = options.maxReconnectDelayMs ?? 1e4;
96
- const jitterRatio = options.reconnectJitterRatio ?? 0.2;
97
- const beforeLiveTimeoutMs = options.beforeLiveTimeoutMs ?? 15e3;
98
- const heartbeatTimeoutMs = options.heartbeatTimeoutMs ?? 45e3;
99
- const maxAttempts = options.maxReconnectAttempts ?? Number.POSITIVE_INFINITY;
100
- let cursor = options.after ?? 0;
101
- let failedAttempts = 0;
102
- let delayMs = baseDelayMs;
103
- let everConnected = false;
104
- while (true) {
105
- if (signal?.aborted) break;
106
- options.onStateChange?.(everConnected || failedAttempts > 0 ? "reconnecting" : "connecting");
107
- const cursorAtOpen = cursor;
108
- try {
109
- const body = await transport.openStream(cursor, signal);
110
- everConnected = true;
111
- failedAttempts = 0;
112
- delayMs = baseDelayMs;
113
- try {
114
- options.onOpen?.();
115
- } catch {
116
- }
117
- await runBeforeLive(options.beforeLive, beforeLiveTimeoutMs, signal);
118
- options.onStateChange?.("live");
119
- for await (const message of parseSseStream(
120
- withStreamInactivityTimeout(body, heartbeatTimeoutMs, signal)
121
- )) {
122
- if (signal?.aborted) {
123
- return;
124
- }
125
- const event = parseSessionEvent(message.data);
126
- if (!event || event.sequence <= cursor) {
127
- continue;
128
- }
129
- if (event.sequence > cursor + 1) {
130
- for await (const missed of backfillEvents(transport, cursor, event.sequence - 1)) {
131
- cursor = missed.sequence;
132
- yield missed;
133
- if (signal?.aborted) {
134
- return;
135
- }
136
- }
137
- }
138
- cursor = event.sequence;
139
- yield event;
140
- }
141
- if (!reconnect) {
142
- return;
143
- }
144
- if (cursor === cursorAtOpen) {
145
- await sleep(jitteredDelay(baseDelayMs, jitterRatio), signal);
146
- }
147
- continue;
148
- } catch (error) {
149
- if (signal?.aborted || isAbortError(error)) {
150
- return;
151
- }
152
- if (!reconnect || !isRetryableStreamError(error)) {
153
- throw error;
154
- }
155
- failedAttempts += 1;
156
- if (failedAttempts > maxAttempts) {
157
- throw new OpenGeniStreamError(
158
- `event stream gave up after ${maxAttempts} consecutive failed reconnect attempts: ${error instanceof Error ? error.message : String(error)}`
159
- );
160
- }
161
- }
162
- await sleep(jitteredDelay(delayMs, jitterRatio), signal);
163
- delayMs = Math.min(Math.max(delayMs * 2, baseDelayMs), maxDelayMs);
164
- }
165
- }
166
- async function runBeforeLive(beforeLive, timeoutMs, signal) {
167
- if (!beforeLive) return;
168
- let timer;
169
- let abortListener;
170
- const timeout = new Promise((_resolve, reject) => {
171
- timer = setTimeout(
172
- () => reject(new TypeError(`stream reconciliation timed out after ${timeoutMs}ms`)),
173
- timeoutMs
174
- );
175
- if (signal) {
176
- abortListener = () => reject(new DOMException("Aborted", "AbortError"));
177
- signal.addEventListener("abort", abortListener, { once: true });
178
- }
179
- });
180
- try {
181
- await Promise.race([Promise.resolve().then(beforeLive), timeout]);
182
- } finally {
183
- if (timer !== void 0) clearTimeout(timer);
184
- if (signal && abortListener) signal.removeEventListener("abort", abortListener);
185
- }
34
+ // src/deprecation.ts
35
+ var ID_SEGMENT = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\d+|[A-Za-z0-9_-]{20,})$/i;
36
+ function routeKey(path) {
37
+ return path.split("/").map((segment) => ID_SEGMENT.test(segment) ? ":id" : segment).join("/");
186
38
  }
187
- function jitteredDelay(delayMs, ratio) {
188
- if (delayMs <= 0 || ratio <= 0) return delayMs;
189
- const boundedRatio = Math.min(ratio, 1);
190
- const spread = delayMs * boundedRatio;
191
- return Math.max(0, delayMs - spread + Math.random() * spread * 2);
39
+ function parseDeprecationDate(value) {
40
+ const trimmed = value.trim();
41
+ const structured = /^@(-?\d+)$/.exec(trimmed);
42
+ if (structured) return new Date(Number(structured[1]) * 1e3);
43
+ const parsed = Date.parse(trimmed);
44
+ return Number.isNaN(parsed) ? null : new Date(parsed);
192
45
  }
193
- function withStreamInactivityTimeout(stream, timeoutMs, signal) {
194
- if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {
195
- throw new RangeError("stream heartbeat timeout must be a positive safe integer");
196
- }
197
- const reader = stream.getReader();
198
- return new ReadableStream({
199
- pull: async (controller) => {
200
- let timer;
201
- let abortListener;
202
- try {
203
- const result = await Promise.race([
204
- reader.read(),
205
- new Promise((_resolve, reject) => {
206
- timer = setTimeout(
207
- () => reject(new TypeError(`event stream heartbeat timed out after ${timeoutMs}ms`)),
208
- timeoutMs
209
- );
210
- if (signal) {
211
- abortListener = () => reject(new DOMException("Aborted", "AbortError"));
212
- signal.addEventListener("abort", abortListener, { once: true });
213
- }
214
- })
215
- ]);
216
- if (result.done) controller.close();
217
- else controller.enqueue(result.value);
218
- } catch (error) {
219
- void reader.cancel(error).catch(() => {
220
- });
221
- controller.error(error);
222
- } finally {
223
- if (timer !== void 0) clearTimeout(timer);
224
- if (signal && abortListener) signal.removeEventListener("abort", abortListener);
225
- }
226
- },
227
- cancel: async (reason) => {
228
- await reader.cancel(reason);
229
- }
230
- });
231
- }
232
- async function* backfillEvents(transport, fromExclusive, toInclusive) {
233
- let cursor = fromExclusive;
234
- while (cursor < toInclusive) {
235
- const page = await transport.listEvents(cursor, Math.min(500, toInclusive - cursor));
236
- const advancing = page.filter((event) => event.sequence > cursor && event.sequence <= toInclusive).sort((a, b) => a.sequence - b.sequence);
237
- if (advancing.length === 0) {
238
- throw new OpenGeniStreamError(
239
- `event replay backfill stalled: expected sequences ${cursor + 1}..${toInclusive} but the replay endpoint returned none of them`
240
- );
241
- }
242
- for (const event of advancing) {
243
- if (event.sequence !== cursor + 1) {
244
- throw new OpenGeniStreamError(
245
- `event replay backfill is missing sequence ${cursor + 1} (replay endpoint skipped to ${event.sequence}); refusing to deliver with a gap`
246
- );
247
- }
248
- cursor = event.sequence;
249
- yield event;
46
+ function parseLinks(value) {
47
+ const links = /* @__PURE__ */ new Map();
48
+ if (!value) return links;
49
+ for (const match of value.matchAll(/<([^>]*)>\s*((?:;\s*[^;,]+)*)/g)) {
50
+ const rel = /;\s*rel="?([^";,]+)"?/i.exec(match[2] ?? "")?.[1];
51
+ if (!rel) continue;
52
+ for (const name of rel.toLowerCase().split(/\s+/)) {
53
+ if (!links.has(name)) links.set(name, match[1]);
250
54
  }
251
55
  }
56
+ return links;
252
57
  }
253
- function parseSessionEvent(data) {
254
- let parsed;
58
+ function parseDeprecationNotice(method, url, headers) {
59
+ const deprecation = headers.get("deprecation");
60
+ const sunsetHeader = headers.get("sunset");
61
+ if (!deprecation && !sunsetHeader) return null;
62
+ let path = url;
255
63
  try {
256
- parsed = JSON.parse(data);
64
+ path = new URL(url, "http://opengeni.invalid").pathname;
257
65
  } catch {
258
- return null;
259
- }
260
- if (typeof parsed !== "object" || parsed === null || typeof parsed.sequence !== "number" || typeof parsed.type !== "string" || typeof parsed.id !== "string") {
261
- return null;
262
66
  }
263
- return parsed;
67
+ const sunset = sunsetHeader ? Date.parse(sunsetHeader) : Number.NaN;
68
+ const links = parseLinks(headers.get("link"));
69
+ return {
70
+ method: method.toUpperCase(),
71
+ route: routeKey(path),
72
+ path,
73
+ deprecatedAt: deprecation ? parseDeprecationDate(deprecation) : null,
74
+ sunset: Number.isNaN(sunset) ? null : new Date(sunset),
75
+ link: links.get("deprecation") ?? links.get("sunset") ?? null,
76
+ successor: links.get("successor-version") ?? null
77
+ };
264
78
  }
265
- async function sleep(delayMs, signal) {
266
- if (signal?.aborted || delayMs <= 0) {
267
- return;
268
- }
269
- await new Promise((resolve) => {
270
- const timer = setTimeout(done, delayMs);
271
- function done() {
272
- clearTimeout(timer);
273
- signal?.removeEventListener("abort", done);
274
- resolve();
79
+ var warnedRoutes = /* @__PURE__ */ new Set();
80
+ function warnDeprecationOnce(notice) {
81
+ const key = `${notice.method} ${notice.route}`;
82
+ if (warnedRoutes.has(key)) return;
83
+ warnedRoutes.add(key);
84
+ const sunset = notice.sunset ? ` and will be removed after ${notice.sunset.toISOString()}` : "";
85
+ const notes = notice.link ? ` Migration notes: ${notice.link}.` : "";
86
+ console.warn(
87
+ `[@opengeni/sdk] ${key} is deprecated${sunset}.${notes} Upgrade @opengeni/sdk, or pass onDeprecation to handle this notice.`
88
+ );
89
+ }
90
+ function withDeprecationNotices(fetchImpl, handler) {
91
+ if (handler === false) return fetchImpl;
92
+ const notify = handler ?? warnDeprecationOnce;
93
+ const seen = /* @__PURE__ */ new Set();
94
+ return async (input, init) => {
95
+ const response = await fetchImpl(input, init);
96
+ try {
97
+ const headers = response.headers;
98
+ if (headers && (headers.get("deprecation") || headers.get("sunset"))) {
99
+ const method = init?.method ?? (typeof Request !== "undefined" && input instanceof Request ? input.method : "GET");
100
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
101
+ const notice = parseDeprecationNotice(method, url, headers);
102
+ if (notice) {
103
+ const key = `${notice.method} ${notice.route}`;
104
+ if (!seen.has(key)) {
105
+ seen.add(key);
106
+ notify(notice);
107
+ }
108
+ }
109
+ }
110
+ } catch {
275
111
  }
276
- signal?.addEventListener("abort", done, { once: true });
277
- });
112
+ return response;
113
+ };
278
114
  }
279
115
 
280
116
  // src/workspace-control-stream.ts
@@ -312,7 +148,7 @@ async function* streamWorkspaceControlEvents(transport, options = {}) {
312
148
  yield event;
313
149
  }
314
150
  if (!reconnect) return;
315
- if (cursor === cursorAtOpen) await sleep2(jitteredDelay(baseDelayMs, jitterRatio), signal);
151
+ if (cursor === cursorAtOpen) await sleep(jitteredDelay(baseDelayMs, jitterRatio), signal);
316
152
  continue;
317
153
  } catch (error) {
318
154
  if (signal?.aborted || isAbortError(error)) return;
@@ -324,7 +160,7 @@ async function* streamWorkspaceControlEvents(transport, options = {}) {
324
160
  );
325
161
  }
326
162
  }
327
- await sleep2(jitteredDelay(delayMs, jitterRatio), signal);
163
+ await sleep(jitteredDelay(delayMs, jitterRatio), signal);
328
164
  delayMs = Math.min(Math.max(delayMs * 2, baseDelayMs), maxDelayMs);
329
165
  }
330
166
  }
@@ -340,7 +176,7 @@ function parseWorkspaceControlEvent(data) {
340
176
  }
341
177
  return value;
342
178
  }
343
- async function sleep2(delayMs, signal) {
179
+ async function sleep(delayMs, signal) {
344
180
  if (signal?.aborted || delayMs <= 0) return;
345
181
  await new Promise((resolve) => {
346
182
  const timer = setTimeout(done, delayMs);
@@ -388,7 +224,7 @@ async function* streamWorkspaceInteractionRevisions(transport, options = {}) {
388
224
  yield event;
389
225
  }
390
226
  if (!reconnect) return;
391
- if (cursor === cursorAtOpen) await sleep3(jitteredDelay(baseDelayMs, jitterRatio), signal);
227
+ if (cursor === cursorAtOpen) await sleep2(jitteredDelay(baseDelayMs, jitterRatio), signal);
392
228
  continue;
393
229
  } catch (error) {
394
230
  if (signal?.aborted || isAbortError(error)) return;
@@ -400,7 +236,7 @@ async function* streamWorkspaceInteractionRevisions(transport, options = {}) {
400
236
  );
401
237
  }
402
238
  }
403
- await sleep3(jitteredDelay(delayMs, jitterRatio), signal);
239
+ await sleep2(jitteredDelay(delayMs, jitterRatio), signal);
404
240
  delayMs = Math.min(Math.max(delayMs * 2, baseDelayMs), maxDelayMs);
405
241
  }
406
242
  }
@@ -419,7 +255,7 @@ function parseWorkspaceInteractionRevision(data) {
419
255
  function isRecord(value) {
420
256
  return typeof value === "object" && value !== null && !Array.isArray(value);
421
257
  }
422
- async function sleep3(delayMs, signal) {
258
+ async function sleep2(delayMs, signal) {
423
259
  if (signal?.aborted || delayMs <= 0) return;
424
260
  await new Promise((resolve) => {
425
261
  const timer = setTimeout(done, delayMs);
@@ -475,7 +311,7 @@ async function* streamWorkspaceLiveEvents(transport, options = {}) {
475
311
  }
476
312
  if (!reconnect) return;
477
313
  if (`${controlCursor}:${interactionCursor}` === cursorsAtOpen) {
478
- await sleep4(jitteredDelay(baseDelayMs, jitterRatio), signal);
314
+ await sleep3(jitteredDelay(baseDelayMs, jitterRatio), signal);
479
315
  }
480
316
  continue;
481
317
  } catch (error) {
@@ -488,7 +324,7 @@ async function* streamWorkspaceLiveEvents(transport, options = {}) {
488
324
  );
489
325
  }
490
326
  }
491
- await sleep4(jitteredDelay(delayMs, jitterRatio), signal);
327
+ await sleep3(jitteredDelay(delayMs, jitterRatio), signal);
492
328
  delayMs = Math.min(Math.max(delayMs * 2, baseDelayMs), maxDelayMs);
493
329
  }
494
330
  }
@@ -511,7 +347,7 @@ function parseWorkspaceLiveEvent(data) {
511
347
  function isRecord2(value) {
512
348
  return typeof value === "object" && value !== null && !Array.isArray(value);
513
349
  }
514
- async function sleep4(delayMs, signal) {
350
+ async function sleep3(delayMs, signal) {
515
351
  if (signal?.aborted || delayMs <= 0) return;
516
352
  await new Promise((resolve) => {
517
353
  const timer = setTimeout(done, delayMs);
@@ -534,6 +370,45 @@ var MAX_VIDEO_BYTES = 512 * 1024 * 1024;
534
370
  var MAX_DIMENSION = 16384;
535
371
  var MAX_PIXELS = 67108864;
536
372
  var MAX_RANGE_BYTES = 1024 * 1024;
373
+ var MAX_SANDBOX_FILE_BYTES = 25 * 1024 * 1024 - 1;
374
+ function parseRetainedWorkspaceFileReference(value, expectedWorkspaceId) {
375
+ if (!recordWithKeys(value, WORKSPACE_FILE_REFERENCE_KEYS)) return null;
376
+ const artifact = value;
377
+ if (artifact.available !== true || artifact.kind !== "file" || typeof artifact.artifactId !== "string" || !UUID.test(artifact.artifactId) || typeof artifact.contentType !== "string" || !/^[a-z0-9][a-z0-9!#$&^_.+-]{0,62}\/[a-z0-9][a-z0-9!#$&^_.+-]{0,62}$/.test(
378
+ artifact.contentType
379
+ ) || !safeIntegerBetween(artifact.originalBytes, 1, MAX_SANDBOX_FILE_BYTES) || typeof artifact.sha256 !== "string" || !SHA256.test(artifact.sha256) || typeof artifact.retainedAt !== "string" || artifact.retainedAt.length > 64 || !ISO_DATETIME_WITH_OFFSET.test(artifact.retainedAt) || !Number.isFinite(Date.parse(artifact.retainedAt)) || !recordWithKeys(artifact.retention, RETENTION_KEYS) || !recordWithKeys(artifact.retrieval, RETRIEVAL_KEYS)) {
380
+ return null;
381
+ }
382
+ const retention = artifact.retention;
383
+ if (retention.policy !== "workspace_file" || retention.expiresAt !== null) return null;
384
+ const retrieval = artifact.retrieval;
385
+ if (retrieval.method !== "GET" || retrieval.acceptRanges !== "bytes" || retrieval.maxRangeBytes !== MAX_RANGE_BYTES || typeof retrieval.path !== "string" || retrieval.path.length > 256) {
386
+ return null;
387
+ }
388
+ const match = WORKSPACE_PATH.exec(retrieval.path);
389
+ if (!match || !UUID.test(match[1] ?? "") || match[2] !== artifact.artifactId || expectedWorkspaceId !== void 0 && match[1] !== expectedWorkspaceId) {
390
+ return null;
391
+ }
392
+ return value;
393
+ }
394
+ function parseSandboxFileArtifactReceipt(value, expectedWorkspaceId) {
395
+ if (typeof value === "string" && value.length <= 8192) {
396
+ try {
397
+ return parseSandboxFileArtifactReceipt(JSON.parse(value), expectedWorkspaceId);
398
+ } catch {
399
+ return null;
400
+ }
401
+ }
402
+ if (!recordWithKeys(value, SANDBOX_FILE_RECEIPT_KEYS)) return null;
403
+ const artifact = parseRetainedWorkspaceFileReference(value.artifact, expectedWorkspaceId);
404
+ const pathSegments = typeof value.sandboxPath === "string" ? value.sandboxPath.split("/") : [];
405
+ if (value.type !== "sandbox_file" || typeof value.sandboxPath !== "string" || !value.sandboxPath.startsWith("/workspace/") || value.sandboxPath.length > 4096 || value.sandboxPath.includes("\0") || pathSegments.some(
406
+ (segment, index) => index > 1 && (!segment || segment === "." || segment === "..")
407
+ ) || typeof value.filename !== "string" || value.filename.length < 1 || value.filename.length > 1024 || pathSegments.at(-1) !== value.filename || !artifact) {
408
+ return null;
409
+ }
410
+ return value;
411
+ }
537
412
  function parseRetainedGeneratedImageReference(value, expectedWorkspaceId) {
538
413
  if (!recordWithKeys(value, GENERATED_IMAGE_REFERENCE_KEYS)) return null;
539
414
  const artifact = value;
@@ -654,10 +529,22 @@ var GENERATED_IMAGE_REFERENCE_KEYS = /* @__PURE__ */ new Set([
654
529
  "retention",
655
530
  "retrieval"
656
531
  ]);
532
+ var WORKSPACE_FILE_REFERENCE_KEYS = /* @__PURE__ */ new Set([
533
+ "available",
534
+ "artifactId",
535
+ "kind",
536
+ "contentType",
537
+ "originalBytes",
538
+ "sha256",
539
+ "retainedAt",
540
+ "retention",
541
+ "retrieval"
542
+ ]);
657
543
  var DIMENSION_KEYS = /* @__PURE__ */ new Set(["width", "height"]);
658
544
  var RETENTION_KEYS = /* @__PURE__ */ new Set(["policy", "expiresAt"]);
659
545
  var RETRIEVAL_KEYS = /* @__PURE__ */ new Set(["method", "path", "acceptRanges", "maxRangeBytes"]);
660
546
  var GENERATED_IMAGE_RECEIPT_KEYS = /* @__PURE__ */ new Set(["type", "artifact", "sandboxPath"]);
547
+ var SANDBOX_FILE_RECEIPT_KEYS = /* @__PURE__ */ new Set(["type", "sandboxPath", "filename", "artifact"]);
661
548
  var GENERATED_VIDEO_RECEIPT_KEYS = /* @__PURE__ */ new Set([
662
549
  "type",
663
550
  "schemaVersion",
@@ -698,25 +585,158 @@ function safeIntegerBetween(value, min, max) {
698
585
 
699
586
  // src/client.ts
700
587
  function sessionListQuery(options) {
701
- const { limit, parentSessionId } = options;
588
+ const { limit, parentSessionId, scopeSubjectId } = options;
589
+ const query = {};
590
+ if (options.originSiteId) query.originSiteId = options.originSiteId;
591
+ if (limit !== void 0) query.limit = String(limit);
592
+ if (parentSessionId !== void 0) query.parentSessionId = parentSessionId ?? "null";
593
+ if (scopeSubjectId !== void 0) query.scopeSubjectId = scopeSubjectId;
594
+ return query;
595
+ }
596
+ var SESSION_PAGE_FILTER_KEYS = [
597
+ "originSiteId",
598
+ "channelId",
599
+ "createdBy",
600
+ "updatedFrom",
601
+ "updatedBefore",
602
+ "createdFrom",
603
+ "createdBefore"
604
+ ];
605
+ var SESSION_PAGE_STRING_QUERY_KEYS = [
606
+ "updatedFrom",
607
+ "updatedBefore",
608
+ "createdFrom",
609
+ "createdBefore",
610
+ "sortBy",
611
+ "archiveStatus"
612
+ ];
613
+ function hasSessionPageFilters(options) {
614
+ return Boolean(options.needsYouOnly) || SESSION_PAGE_FILTER_KEYS.some((key) => options[key] !== void 0);
615
+ }
616
+ function unsupportedSessionPage(feature) {
617
+ return new Error(`The connected Opengeni API does not support ${feature}`);
618
+ }
619
+ function sessionPath(workspaceId, sessionId) {
620
+ return `/v1/workspaces/${workspaceId}/sessions/${sessionId}`;
621
+ }
622
+ function defaultApiContractMode(options) {
623
+ if (options.apiContract) return options.apiContract;
624
+ const browser = typeof window !== "undefined" && typeof document !== "undefined";
625
+ return browser && !options.apiKey ? "strict" : "compatible";
626
+ }
627
+ function createSingleFlightReadEntry(generation, onRequestStart) {
628
+ let resolve;
629
+ let reject;
630
+ const promise = new Promise((entryResolve, entryReject) => {
631
+ resolve = entryResolve;
632
+ reject = entryReject;
633
+ });
634
+ return {
635
+ controller: new AbortController(),
636
+ consumers: 0,
637
+ generation,
638
+ promise,
639
+ resolve,
640
+ reject,
641
+ started: false,
642
+ listeners: new Set(onRequestStart ? [onRequestStart] : [])
643
+ };
644
+ }
645
+ function assertNoMessageTools(input) {
646
+ if (Object.prototype.hasOwnProperty.call(input, "tools")) {
647
+ throw new TypeError(
648
+ "Message-level tools are not supported; update the session tool policy before sending."
649
+ );
650
+ }
651
+ }
652
+ function normalizeScheduledTaskMachineTarget(request) {
653
+ if (!("agentConfig" in request) || !request.agentConfig?.machineTarget) {
654
+ return request;
655
+ }
656
+ const { workingDir, ...machineTarget } = request.agentConfig.machineTarget;
657
+ if (workingDir === void 0) {
658
+ return request;
659
+ }
660
+ const normalizedWorkingDir = workingDir.trim();
661
+ return {
662
+ ...request,
663
+ agentConfig: {
664
+ ...request.agentConfig,
665
+ machineTarget: {
666
+ ...machineTarget,
667
+ ...normalizedWorkingDir ? { workingDir: normalizedWorkingDir } : {}
668
+ }
669
+ }
670
+ };
671
+ }
672
+ function createLazyToolsFacade(transport) {
702
673
  return {
703
- ...limit === void 0 ? {} : { limit: String(limit) },
704
- ...parentSessionId === void 0 ? {} : { parentSessionId: parentSessionId ?? "null" }
674
+ forWorkspace(workspaceId) {
675
+ const normalizedWorkspaceId = workspaceId.trim();
676
+ if (!normalizedWorkspaceId) throw new TypeError("workspaceId is required");
677
+ let workspaceTools;
678
+ const load = () => workspaceTools ??= import("./tools-FXBLUWAE.js").then(
679
+ ({ OpenGeniToolsClient }) => new OpenGeniToolsClient(transport).forWorkspace(normalizedWorkspaceId)
680
+ );
681
+ const node = (path) => new Proxy(
682
+ async (...args) => {
683
+ let target = await load();
684
+ for (const segment of path) {
685
+ target = target[segment];
686
+ }
687
+ if (typeof target !== "function")
688
+ throw new TypeError("Opengeni tool path is not callable");
689
+ return await Reflect.apply(target, void 0, args);
690
+ },
691
+ {
692
+ get: (_target, property) => {
693
+ if (property === "then") return void 0;
694
+ if (typeof property !== "string") return void 0;
695
+ return node([...path, property]);
696
+ }
697
+ }
698
+ );
699
+ return new Proxy(/* @__PURE__ */ Object.create(null), {
700
+ get: (_target, property) => {
701
+ if (property === "then") return void 0;
702
+ if (typeof property !== "string") return void 0;
703
+ return node([property]);
704
+ }
705
+ });
706
+ }
705
707
  };
706
708
  }
707
709
  var OpenGeniClient = class {
710
+ externalActorHeader;
711
+ serviceInitiatorHeader;
712
+ serviceContextHeader;
708
713
  baseUrl;
709
714
  options;
710
715
  fetchImpl;
711
- readInFlight = /* @__PURE__ */ new Map();
712
- readTrailing = /* @__PURE__ */ new Map();
716
+ sessionCommandTimeoutMs;
717
+ apiContractStrict;
718
+ active = /* @__PURE__ */ new Map();
719
+ generations = /* @__PURE__ */ new Map();
720
+ queued = /* @__PURE__ */ new Map();
713
721
  /** Resource-oriented Browser/Computer facade over this exact authenticated client. */
714
722
  interaction;
723
+ /** Dynamic typed tool facade backed by the canonical workspace gateway. */
724
+ tools;
715
725
  constructor(options) {
716
726
  this.baseUrl = options.baseUrl.replace(/\/+$/, "");
717
727
  this.options = options;
718
- this.fetchImpl = options.fetch ?? ((input, init) => fetch(input, init));
728
+ this.fetchImpl = withDeprecationNotices(
729
+ options.fetch ?? ((input, init) => fetch(input, init)),
730
+ options.onDeprecation
731
+ );
732
+ const sessionCommandTimeoutMs = options.sessionCommandTimeoutMs ?? 15e3;
733
+ if (!Number.isFinite(sessionCommandTimeoutMs) || sessionCommandTimeoutMs <= 0) {
734
+ throw new RangeError("sessionCommandTimeoutMs must be a finite positive number");
735
+ }
736
+ this.sessionCommandTimeoutMs = sessionCommandTimeoutMs;
737
+ this.apiContractStrict = defaultApiContractMode(options) === "strict";
719
738
  this.interaction = new OpenGeniInteractionClient(this);
739
+ this.tools = createLazyToolsFacade(this);
720
740
  }
721
741
  // --- Session lifecycle ---------------------------------------------------
722
742
  /** Make one finalization attempt for a recording; callers may retry retained audio. */
@@ -749,7 +769,7 @@ var OpenGeniClient = class {
749
769
  if (input.signal?.aborted) throw error;
750
770
  throw mutationTransportError(correlationId);
751
771
  }
752
- assertApiContractResponse(response);
772
+ assertApiContractResponse(response, this.apiContractStrict);
753
773
  if (!response.ok)
754
774
  throw await apiErrorFromResponse(response, {
755
775
  method: "POST",
@@ -838,7 +858,7 @@ var OpenGeniClient = class {
838
858
  if (input.signal?.aborted) throw error;
839
859
  throw mutationTransportError(correlationId);
840
860
  }
841
- assertApiContractResponse(response);
861
+ assertApiContractResponse(response, this.apiContractStrict);
842
862
  if (!response.ok)
843
863
  throw await apiErrorFromResponse(response, {
844
864
  method: "PUT",
@@ -895,14 +915,17 @@ var OpenGeniClient = class {
895
915
  async createSession(workspaceId, request) {
896
916
  return await this.requestJson(
897
917
  "POST",
898
- `/v1/workspaces/${workspaceId}/sessions`,
918
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/sessions`,
899
919
  request
900
920
  );
901
921
  }
902
- async getNewSessionDraft(workspaceId) {
922
+ async getNewSessionDraft(workspaceId, options = {}) {
903
923
  return await this.requestJson(
904
924
  "GET",
905
- `/v1/workspaces/${workspaceId}/new-session-draft`
925
+ `/v1/workspaces/${workspaceId}/new-session-draft`,
926
+ void 0,
927
+ {},
928
+ options
906
929
  );
907
930
  }
908
931
  async saveNewSessionDraft(workspaceId, request) {
@@ -912,14 +935,117 @@ var OpenGeniClient = class {
912
935
  request
913
936
  );
914
937
  }
938
+ /** The workspace's HTTP credential provider, or null when none is configured. */
939
+ async getWorkspaceCredentialProvider(workspaceId) {
940
+ return this.requestJson("GET", `/v1/workspaces/${workspaceId}/credential-provider`);
941
+ }
942
+ /**
943
+ * Create or update the workspace credential provider. The signing secret is
944
+ * returned only when the provider is first created; store it then.
945
+ */
946
+ async putWorkspaceCredentialProvider(workspaceId, request) {
947
+ return this.requestJson("PUT", `/v1/workspaces/${workspaceId}/credential-provider`, request);
948
+ }
949
+ async deleteWorkspaceCredentialProvider(workspaceId) {
950
+ await this.requestVoid("DELETE", `/v1/workspaces/${workspaceId}/credential-provider`);
951
+ }
952
+ async listWorkspaceWebhooks(workspaceId) {
953
+ return this.requestJson("GET", `/v1/workspaces/${workspaceId}/webhooks`);
954
+ }
955
+ /** Create a webhook. The signing secret is returned only in this response. */
956
+ async createWorkspaceWebhook(workspaceId, request) {
957
+ return this.requestJson("POST", `/v1/workspaces/${workspaceId}/webhooks`, request);
958
+ }
959
+ async updateWorkspaceWebhook(workspaceId, webhookId, request) {
960
+ return this.requestJson(
961
+ "PATCH",
962
+ `/v1/workspaces/${workspaceId}/webhooks/${webhookId}`,
963
+ request
964
+ );
965
+ }
966
+ async deleteWorkspaceWebhook(workspaceId, webhookId) {
967
+ await this.requestVoid("DELETE", `/v1/workspaces/${workspaceId}/webhooks/${webhookId}`);
968
+ }
969
+ async listWorkspaceWebhookDeliveries(workspaceId, webhookId, options = {}) {
970
+ return this.requestJson(
971
+ "GET",
972
+ `/v1/workspaces/${workspaceId}/webhooks/${webhookId}/deliveries`,
973
+ void 0,
974
+ options.limit !== void 0 ? { limit: String(options.limit) } : {}
975
+ );
976
+ }
977
+ /** Queue a delivered or failed delivery again with a fresh attempt budget. */
978
+ async redeliverWorkspaceWebhookDelivery(workspaceId, webhookId, deliveryId) {
979
+ return this.requestJson(
980
+ "POST",
981
+ `/v1/workspaces/${workspaceId}/webhooks/${webhookId}/deliveries/${deliveryId}/redeliver`
982
+ );
983
+ }
984
+ /** Images this deployment lets a workspace choose as its default sandbox image. */
985
+ async listWorkspaceSandboxImages(workspaceId) {
986
+ return this.requestJson("GET", `/v1/workspaces/${workspaceId}/sandbox-images`);
987
+ }
988
+ /** Submit general feedback or a session/turn rating. Retain the key when retrying. */
989
+ async createFeedback(workspaceId, request) {
990
+ return this.requestJson("POST", `/v1/workspaces/${workspaceId}/feedback`, request);
991
+ }
992
+ /** Only this principal's submissions. No session filter means general feedback only. */
993
+ async listOwnFeedback(workspaceId, options = {}) {
994
+ const query = new URLSearchParams();
995
+ if (options.sessionId) query.set("sessionId", options.sessionId);
996
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
997
+ if (options.includeTurns !== void 0) query.set("includeTurns", String(options.includeTurns));
998
+ return this.requestJson(
999
+ "GET",
1000
+ `/v1/workspaces/${workspaceId}/feedback${query.size ? `?${query}` : ""}`
1001
+ );
1002
+ }
915
1003
  async getSession(workspaceId, sessionId, options = {}) {
916
- const path = `/v1/workspaces/${workspaceId}/sessions/${sessionId}`;
917
- return await this.singleFlightRead(path, () => this.requestJson("GET", path), options);
1004
+ const path = sessionPath(workspaceId, sessionId);
1005
+ return await this.sharedRead(
1006
+ path,
1007
+ (signal) => this.requestJson("GET", path, void 0, {}, { signal }),
1008
+ options
1009
+ );
1010
+ }
1011
+ /** Exact model-visible prefix captured from the latest provider request. */
1012
+ async getSessionModelContext(workspaceId, sessionId) {
1013
+ return await this.requestJson(
1014
+ "GET",
1015
+ `${sessionPath(workspaceId, sessionId)}/model-context`
1016
+ );
918
1017
  }
919
1018
  async updateSession(workspaceId, sessionId, request) {
1019
+ return await this.requestJson("PATCH", sessionPath(workspaceId, sessionId), request);
1020
+ }
1021
+ /** Replace the complete ordered Variable Set selection at a quiescent turn boundary. */
1022
+ async updateSessionVariableSets(workspaceId, sessionId, request) {
920
1023
  return await this.requestJson(
921
- "PATCH",
922
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}`,
1024
+ "PUT",
1025
+ `${sessionPath(workspaceId, sessionId)}/variable-sets`,
1026
+ request
1027
+ );
1028
+ }
1029
+ /** Whether this exact authenticated principal may atomically create a private session. */
1030
+ async getSessionTenancyCreateCapabilities(workspaceId) {
1031
+ return await this.requestJson(
1032
+ "GET",
1033
+ `/v1/workspaces/${workspaceId}/session-tenancy/capabilities`
1034
+ );
1035
+ }
1036
+ /** Change an owned, fully quiescent session between private and workspace visibility. */
1037
+ async updateSessionVisibility(workspaceId, sessionId, request) {
1038
+ return await this.requestJson(
1039
+ "PUT",
1040
+ `${sessionPath(workspaceId, sessionId)}/visibility`,
1041
+ request
1042
+ );
1043
+ }
1044
+ /** Create an independent same-workspace fork with explicit destination visibility. */
1045
+ async forkSession(workspaceId, sessionId, request) {
1046
+ return await this.requestJson(
1047
+ "POST",
1048
+ `${sessionPath(workspaceId, sessionId)}/forks`,
923
1049
  request
924
1050
  );
925
1051
  }
@@ -927,7 +1053,20 @@ var OpenGeniClient = class {
927
1053
  async updateSessionToolPolicy(workspaceId, sessionId, request) {
928
1054
  return await this.requestJson(
929
1055
  "PUT",
930
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/tool-policy`,
1056
+ `${sessionPath(workspaceId, sessionId)}/tool-policy`,
1057
+ request
1058
+ );
1059
+ }
1060
+ /**
1061
+ * Replace the session's agent configuration (capabilities, identity,
1062
+ * instructions alias, renderer). Omitted fields keep their current values.
1063
+ * Uses the tool-policy version (409 when stale) and applies from the next
1064
+ * turn. A legacy session converts from its current effective state.
1065
+ */
1066
+ async updateSessionAgent(workspaceId, sessionId, request) {
1067
+ return await this.requestJson(
1068
+ "PUT",
1069
+ `${sessionPath(workspaceId, sessionId)}/agent`,
931
1070
  request
932
1071
  );
933
1072
  }
@@ -939,12 +1078,45 @@ var OpenGeniClient = class {
939
1078
  async updateSessionMcpApprovalPolicy(workspaceId, sessionId, serverId, request) {
940
1079
  return await this.requestJson(
941
1080
  "PATCH",
942
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/mcp-servers/${encodeURIComponent(serverId)}/approval-policy`,
1081
+ `${sessionPath(workspaceId, sessionId)}/mcp-servers/${encodeURIComponent(serverId)}/approval-policy`,
943
1082
  request
944
1083
  );
945
1084
  }
1085
+ /** Search durable visible user/assistant text, including unloaded history.
1086
+ * Pages may be empty with hasMore=true. Never fall back to title search on
1087
+ * older servers. Use listEventPage before/after the returned sequence for context.
1088
+ */
1089
+ async searchSessionMessages(workspaceId, request, options = {}) {
1090
+ return this.requestJson(
1091
+ "GET",
1092
+ `/v1/workspaces/${workspaceId}/session-message-search`,
1093
+ void 0,
1094
+ {
1095
+ query: request.query,
1096
+ ...request.sessionId !== void 0 ? { sessionId: request.sessionId } : {},
1097
+ ...request.groupBy !== void 0 ? { groupBy: request.groupBy } : {},
1098
+ ...request.archiveStatus !== void 0 ? { archiveStatus: request.archiveStatus } : {},
1099
+ ...request.limit !== void 0 ? { limit: String(request.limit) } : {},
1100
+ ...request.cursor !== void 0 ? { cursor: request.cursor } : {}
1101
+ },
1102
+ options
1103
+ );
1104
+ }
1105
+ /** Read one selected search result's complete visible text when <=12,000
1106
+ * UTF-16 units. Stale, duplicate or non-message references fail with 404.
1107
+ * The response never includes audit payload fields such as modelContext.
1108
+ */
1109
+ async getSessionMessagePreview(workspaceId, sessionId, reference, options = {}) {
1110
+ return this.requestJson(
1111
+ "GET",
1112
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/sessions/${encodeURIComponent(sessionId)}/events/${encodeURIComponent(reference.eventId)}/message-preview`,
1113
+ void 0,
1114
+ { sequence: String(reference.sequence) },
1115
+ options
1116
+ );
1117
+ }
946
1118
  async listSessions(workspaceId, options = {}) {
947
- if (options.search?.trim()) {
1119
+ if (options.search?.trim() || options.originSiteId) {
948
1120
  const page = await this.listSessionPage(workspaceId, options);
949
1121
  return [...page.pinned, ...page.sessions];
950
1122
  }
@@ -955,22 +1127,75 @@ var OpenGeniClient = class {
955
1127
  sessionListQuery(options)
956
1128
  );
957
1129
  }
1130
+ /** Running and stopping commands only; settled results remain in session history. */
1131
+ async listSessionBackgroundCommands(workspaceId, sessionId, options = {}) {
1132
+ return await this.requestJson(
1133
+ "GET",
1134
+ `${sessionPath(workspaceId, sessionId)}/background-commands`,
1135
+ void 0,
1136
+ {},
1137
+ options
1138
+ );
1139
+ }
1140
+ async cancelSessionBackgroundCommand(workspaceId, sessionId, commandId) {
1141
+ return await this.requestJson(
1142
+ "DELETE",
1143
+ `${sessionPath(workspaceId, sessionId)}/background-commands/${commandId}`
1144
+ );
1145
+ }
958
1146
  /** Pin-aware ordinary-session page with a stable keyset cursor. */
959
1147
  async listSessionPage(workspaceId, options = {}) {
1148
+ const response = await this.requestSessionPage(
1149
+ `/v1/workspaces/${workspaceId}/sessions`,
1150
+ options
1151
+ );
1152
+ if ("projection" in response) throw unsupportedSessionPage("full session details");
1153
+ return response;
1154
+ }
1155
+ /** Compact rail records; safely projects full pages from older APIs. */
1156
+ async listSessionSummaryPage(workspaceId, options = {}) {
1157
+ const response = await this.requestSessionPage(
1158
+ `/v1/workspaces/${workspaceId}/sessions`,
1159
+ options,
1160
+ true
1161
+ );
1162
+ if ("projection" in response) return response;
1163
+ const { sessionListEntry } = await import("./session-list-entries.js");
1164
+ return {
1165
+ ...response,
1166
+ projection: "summary",
1167
+ pinned: response.pinned.map(sessionListEntry),
1168
+ sessions: response.sessions.map(sessionListEntry)
1169
+ };
1170
+ }
1171
+ async requestSessionPage(path, options, summary = false) {
960
1172
  const search = options.search?.trim();
961
- let response;
1173
+ let result;
962
1174
  try {
963
- response = await this.requestJson(
1175
+ const query = { view: "page", ...sessionListQuery(options) };
1176
+ if (summary) query.projection = "summary";
1177
+ if (options.cursor !== void 0) query.cursor = options.cursor;
1178
+ if (search) query.search = search;
1179
+ if (options.channelId !== void 0) query.channelId = options.channelId ?? "null";
1180
+ if (options.createdBy) {
1181
+ query.createdByKind = options.createdBy.kind;
1182
+ query.createdBySubjectId = options.createdBy.subjectId;
1183
+ }
1184
+ for (const key of SESSION_PAGE_STRING_QUERY_KEYS) {
1185
+ const value = options[key];
1186
+ if (value) query[key] = value;
1187
+ }
1188
+ if (options.pinsOnly) query.pinsOnly = "true";
1189
+ if (options.includeTotals) query.includeTotals = "true";
1190
+ if (options.needsYouOnly) query.needsYouOnly = "true";
1191
+ if (options.includePinned === false) query.includePinned = "false";
1192
+ if (options.archivedOnly) query.archivedOnly = "true";
1193
+ result = await this.requestJson(
964
1194
  "GET",
965
- `/v1/workspaces/${workspaceId}/sessions`,
1195
+ path,
966
1196
  void 0,
967
- {
968
- view: "page",
969
- ...sessionListQuery(options),
970
- ...options.cursor !== void 0 ? { cursor: options.cursor } : {},
971
- ...search ? { search } : {},
972
- ...options.pinsOnly ? { pinsOnly: "true" } : {}
973
- }
1197
+ query,
1198
+ { signal: options.signal }
974
1199
  );
975
1200
  } catch (error) {
976
1201
  if (error instanceof OpenGeniApiError && error.status === 410) {
@@ -984,78 +1209,222 @@ var OpenGeniClient = class {
984
1209
  }
985
1210
  throw error;
986
1211
  }
987
- if (Array.isArray(response)) {
988
- if (options.cursor) {
989
- throw new Error("The connected OpenGeni API does not support stable session-page cursors");
990
- }
991
- if (search) {
992
- throw new Error("The connected OpenGeni API does not support session search");
993
- }
994
- if (options.pinsOnly) {
995
- throw new Error("The connected OpenGeni API does not support pins-only session lists");
996
- }
1212
+ const response = result;
1213
+ const legacy = Array.isArray(response);
1214
+ const filtered = hasSessionPageFilters(options);
1215
+ if (options.sortBy !== void 0 && (legacy || response.sortBy !== options.sortBy) || options.archiveStatus !== void 0 && (legacy || response.archiveStatus !== options.archiveStatus)) {
1216
+ throw unsupportedSessionPage("the requested session sorting/archive filter");
1217
+ }
1218
+ if (legacy) {
1219
+ const unsupported = options.includeTotals ? "complete session totals" : options.cursor ? "stable session-page cursors" : search ? "session search" : options.pinsOnly ? "pins-only session lists" : options.archivedOnly ? "archived session lists" : filtered ? "filtered session lists" : null;
1220
+ if (unsupported) throw unsupportedSessionPage(unsupported);
997
1221
  return { pinned: [], sessions: response, nextCursor: null };
998
1222
  }
1223
+ if (options.includeTotals && response.totals === void 0)
1224
+ throw unsupportedSessionPage("complete session totals");
1225
+ if (options.needsYouOnly && response.needsYouOnly !== true)
1226
+ throw unsupportedSessionPage("attention session filtering");
1227
+ if (filtered && response.filtersApplied !== true) {
1228
+ throw unsupportedSessionPage("filtered session lists");
1229
+ }
1230
+ if (options.originSiteId && (!response.originSiteId || options.originSiteId !== "current" && response.originSiteId !== options.originSiteId)) {
1231
+ throw unsupportedSessionPage("Site-filtered session lists");
1232
+ }
999
1233
  return response;
1000
1234
  }
1001
1235
  /** Compact, bounded workspace agent hierarchy page. */
1002
1236
  async listAgentTopology(workspaceId, options = {}) {
1003
- const search = options.search?.trim();
1237
+ const query = options.query?.trim() || options.search?.trim();
1238
+ if (query && options.subject) {
1239
+ throw new TypeError("listAgentTopology query cannot be combined with an exact subject");
1240
+ }
1241
+ const params = sessionListQuery(options);
1242
+ if (options.rootSessionId) params.rootSessionId = options.rootSessionId;
1243
+ if (options.cursor) params.cursor = options.cursor;
1244
+ if (query) params.query = query;
1245
+ if (options.statuses?.length) params.statuses = options.statuses.join(",");
1246
+ if (options.activeOnly !== void 0) params.activeOnly = options.activeOnly ? "true" : "false";
1247
+ if (options.recentHours !== void 0) params.recentHours = String(options.recentHours);
1248
+ if (options.subject) {
1249
+ params.subjectNamespace = options.subject.namespace;
1250
+ params.subjectType = options.subject.type;
1251
+ params.subjectKey = options.subject.canonicalKey;
1252
+ }
1253
+ if (options.claimLimit !== void 0) params.claimLimit = String(options.claimLimit);
1004
1254
  return await this.requestJson(
1005
1255
  "GET",
1006
1256
  `/v1/workspaces/${workspaceId}/agent-topology`,
1007
1257
  void 0,
1008
- {
1009
- ...options.limit !== void 0 ? { limit: String(options.limit) } : {},
1010
- ...options.parentSessionId === void 0 ? {} : { parentSessionId: options.parentSessionId ?? "null" },
1011
- ...options.cursor ? { cursor: options.cursor } : {},
1012
- ...search ? { search } : {}
1013
- }
1258
+ params
1014
1259
  );
1015
1260
  }
1016
1261
  /** Set this authenticated member's personal workspace pin for a session. */
1017
1262
  async updateSessionPin(workspaceId, sessionId, request) {
1018
1263
  return await this.requestJson(
1019
1264
  "PUT",
1020
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/pin`,
1265
+ `${sessionPath(workspaceId, sessionId)}/pin`,
1266
+ request
1267
+ );
1268
+ }
1269
+ /** Set this authenticated member's explicit read/actively-working state. */
1270
+ async updateSessionAttention(workspaceId, sessionId, request) {
1271
+ return await this.requestJson(
1272
+ "PUT",
1273
+ `${sessionPath(workspaceId, sessionId)}/attention`,
1274
+ request
1275
+ );
1276
+ }
1277
+ /** Archive or restore this authenticated member's root chat. */
1278
+ async updateSessionArchive(workspaceId, sessionId, request) {
1279
+ return await this.requestJson(
1280
+ "PUT",
1281
+ `${sessionPath(workspaceId, sessionId)}/archive`,
1021
1282
  request
1022
1283
  );
1023
1284
  }
1024
- async getSessionLineage(workspaceId, sessionId) {
1025
- const path = `/v1/workspaces/${workspaceId}/sessions/${sessionId}/lineage`;
1026
- return await this.singleFlightRead(
1285
+ /** Permanently delete one quiescent root session and its full descendant tree. */
1286
+ async deleteSession(workspaceId, sessionId) {
1287
+ return await this.requestJson(
1288
+ "DELETE",
1289
+ sessionPath(workspaceId, sessionId)
1290
+ );
1291
+ }
1292
+ async getSessionLineage(workspaceId, sessionId, options = {}) {
1293
+ const path = `${sessionPath(workspaceId, sessionId)}/lineage`;
1294
+ return await this.sharedRead(
1027
1295
  path,
1028
- () => this.requestJson("GET", path)
1296
+ (signal) => this.requestJson("GET", path, void 0, {}, { signal }),
1297
+ options
1029
1298
  );
1030
1299
  }
1031
- singleFlightRead(key, read, options = {}) {
1032
- const existing = this.readInFlight.get(key);
1033
- if (existing) {
1034
- if (!options.fresh) return existing;
1035
- const queued = this.readTrailing.get(key);
1036
- if (queued) return queued;
1037
- const trailing = existing.then(
1038
- () => this.singleFlightRead(key, read),
1039
- () => this.singleFlightRead(key, read)
1300
+ sharedRead(key, read, options = {}) {
1301
+ if (options.signal?.aborted) {
1302
+ return Promise.reject(
1303
+ options.signal.reason ?? new DOMException("Request aborted", "AbortError")
1040
1304
  );
1041
- this.readTrailing.set(key, trailing);
1042
- const clear = () => {
1043
- if (this.readTrailing.get(key) === trailing) this.readTrailing.delete(key);
1044
- };
1045
- void trailing.then(clear, clear);
1046
- return trailing;
1047
1305
  }
1048
- const promise = read().finally(() => {
1049
- if (this.readInFlight.get(key) === promise) this.readInFlight.delete(key);
1306
+ const existing = this.active.get(key);
1307
+ if (existing) {
1308
+ if (!options.fresh) {
1309
+ this.observeRead(existing, options.onRequestStart);
1310
+ return this.consumeSharedRead(key, existing, options.signal);
1311
+ }
1312
+ const requiredGeneration = existing.generation + 1;
1313
+ const queued2 = this.queued.get(key);
1314
+ if (queued2 && queued2.generation >= requiredGeneration) {
1315
+ this.observeRead(queued2, options.onRequestStart);
1316
+ return this.consumeSharedRead(key, queued2, options.signal);
1317
+ }
1318
+ const predecessor = queued2?.promise ?? existing.promise;
1319
+ return this.queueRead(key, predecessor, requiredGeneration, read, options);
1320
+ }
1321
+ const queued = this.queued.get(key);
1322
+ if (queued && (!options.fresh || !queued.started)) {
1323
+ this.observeRead(queued, options.onRequestStart);
1324
+ return this.consumeSharedRead(key, queued, options.signal);
1325
+ }
1326
+ if (queued) {
1327
+ return this.queueRead(key, queued.promise, queued.generation + 1, read, options);
1328
+ }
1329
+ const generation = (this.generations.get(key) ?? 0) + 1;
1330
+ const entry = createSingleFlightReadEntry(generation, options.onRequestStart);
1331
+ const consumed = this.consumeSharedRead(key, entry, options.signal);
1332
+ this.launchRead(key, entry, read);
1333
+ return consumed;
1334
+ }
1335
+ queueRead(key, predecessor, generation, read, options) {
1336
+ const entry = createSingleFlightReadEntry(generation, options.onRequestStart);
1337
+ const consumed = this.consumeSharedRead(key, entry, options.signal);
1338
+ this.queued.set(key, entry);
1339
+ const launch = () => this.launchRead(key, entry, read);
1340
+ void predecessor.then(launch, launch);
1341
+ const clear = () => {
1342
+ if (this.queued.get(key) !== entry) return;
1343
+ this.queued.delete(key);
1344
+ if (!this.active.has(key)) this.generations.delete(key);
1345
+ };
1346
+ void entry.promise.then(clear, clear);
1347
+ return consumed;
1348
+ }
1349
+ launchRead(key, entry, read) {
1350
+ if (entry.controller.signal.aborted) return;
1351
+ entry.started = true;
1352
+ this.generations.set(key, entry.generation);
1353
+ this.active.set(key, entry);
1354
+ try {
1355
+ entry.stamp = this.options.beginSharedRead?.();
1356
+ } catch {
1357
+ }
1358
+ for (const listener of entry.listeners) {
1359
+ try {
1360
+ listener(entry.stamp);
1361
+ } catch {
1362
+ }
1363
+ }
1364
+ entry.listeners.clear();
1365
+ const settle = () => {
1366
+ if (this.active.get(key) !== entry) return;
1367
+ this.active.delete(key);
1368
+ if (!this.queued.has(key)) this.generations.delete(key);
1369
+ };
1370
+ let request;
1371
+ try {
1372
+ request = read(entry.controller.signal);
1373
+ } catch (error) {
1374
+ settle();
1375
+ entry.reject(error);
1376
+ return;
1377
+ }
1378
+ void request.then(
1379
+ (value) => {
1380
+ settle();
1381
+ entry.resolve(value);
1382
+ },
1383
+ (error) => {
1384
+ settle();
1385
+ entry.reject(error);
1386
+ }
1387
+ );
1388
+ }
1389
+ consumeSharedRead(key, entry, signal) {
1390
+ entry.consumers += 1;
1391
+ let released = false;
1392
+ const release = () => {
1393
+ if (released) return;
1394
+ released = true;
1395
+ entry.consumers -= 1;
1396
+ if (!signal?.aborted || entry.consumers > 0) return;
1397
+ const reason = signal.reason;
1398
+ entry.controller.abort(reason);
1399
+ if (this.active.get(key) === entry) this.active.delete(key);
1400
+ if (this.queued.get(key) === entry) this.queued.delete(key);
1401
+ if (!this.active.has(key) && !this.queued.has(key)) this.generations.delete(key);
1402
+ entry.reject(reason);
1403
+ };
1404
+ signal?.addEventListener("abort", release, { once: true });
1405
+ const consumed = awaitWithAbort(entry.promise, signal);
1406
+ return consumed.finally(() => {
1407
+ signal?.removeEventListener("abort", release);
1408
+ release();
1050
1409
  });
1051
- this.readInFlight.set(key, promise);
1052
- return promise;
1410
+ }
1411
+ observeRead(entry, listener) {
1412
+ if (!listener) return;
1413
+ if (!entry.started) {
1414
+ entry.listeners.add(listener);
1415
+ return;
1416
+ }
1417
+ if (entry.stamp === void 0) return;
1418
+ try {
1419
+ listener(entry.stamp);
1420
+ } catch {
1421
+ }
1053
1422
  }
1054
1423
  /** Negotiate one server-mediated connected-Codex GPT-Live V3 WebRTC call. */
1055
1424
  async negotiateCodexRealtimeWebrtc(workspaceId, sessionId, request, options = {}) {
1056
1425
  return await this.requestJson(
1057
1426
  "POST",
1058
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime/webrtc`,
1427
+ `${sessionPath(workspaceId, sessionId)}/realtime/webrtc`,
1059
1428
  request,
1060
1429
  {},
1061
1430
  { signal: options.signal }
@@ -1065,7 +1434,7 @@ var OpenGeniClient = class {
1065
1434
  async negotiateGatewayRealtime(workspaceId, sessionId, request, options = {}) {
1066
1435
  return await this.requestJson(
1067
1436
  "POST",
1068
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime/gateway`,
1437
+ `${sessionPath(workspaceId, sessionId)}/realtime/gateway`,
1069
1438
  request,
1070
1439
  {},
1071
1440
  { signal: options.signal }
@@ -1075,7 +1444,7 @@ var OpenGeniClient = class {
1075
1444
  async negotiateXaiSubscriptionRealtime(workspaceId, sessionId, request, options = {}) {
1076
1445
  return await this.requestJson(
1077
1446
  "POST",
1078
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime/supergrok`,
1447
+ `${sessionPath(workspaceId, sessionId)}/realtime/supergrok`,
1079
1448
  request,
1080
1449
  {},
1081
1450
  { signal: options.signal }
@@ -1085,7 +1454,7 @@ var OpenGeniClient = class {
1085
1454
  async activateCodexRealtimeConnection(workspaceId, sessionId, realtimeId, connectionId, request, options = {}) {
1086
1455
  return await this.requestJson(
1087
1456
  "POST",
1088
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime/${realtimeId}/connections/${connectionId}/activate`,
1457
+ `${sessionPath(workspaceId, sessionId)}/realtime/${realtimeId}/connections/${connectionId}/activate`,
1089
1458
  request,
1090
1459
  {},
1091
1460
  { signal: options.signal }
@@ -1095,7 +1464,7 @@ var OpenGeniClient = class {
1095
1464
  async beginSessionRealtime(workspaceId, sessionId, request) {
1096
1465
  return await this.requestJson(
1097
1466
  "POST",
1098
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime`,
1467
+ `${sessionPath(workspaceId, sessionId)}/realtime`,
1099
1468
  request
1100
1469
  );
1101
1470
  }
@@ -1103,7 +1472,7 @@ var OpenGeniClient = class {
1103
1472
  async heartbeatSessionRealtime(workspaceId, sessionId, realtimeId, request) {
1104
1473
  return await this.requestJson(
1105
1474
  "PATCH",
1106
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime/${realtimeId}/heartbeat`,
1475
+ `${sessionPath(workspaceId, sessionId)}/realtime/${realtimeId}/heartbeat`,
1107
1476
  request
1108
1477
  );
1109
1478
  }
@@ -1111,7 +1480,7 @@ var OpenGeniClient = class {
1111
1480
  async syncSessionRealtimeLedger(workspaceId, sessionId, realtimeId, request) {
1112
1481
  return await this.requestJson(
1113
1482
  "POST",
1114
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime/${realtimeId}/sync`,
1483
+ `${sessionPath(workspaceId, sessionId)}/realtime/${realtimeId}/sync`,
1115
1484
  request
1116
1485
  );
1117
1486
  }
@@ -1119,25 +1488,27 @@ var OpenGeniClient = class {
1119
1488
  async endSessionRealtime(workspaceId, sessionId, realtimeId, request) {
1120
1489
  return await this.requestJson(
1121
1490
  "DELETE",
1122
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/realtime/${realtimeId}`,
1491
+ `${sessionPath(workspaceId, sessionId)}/realtime/${realtimeId}`,
1123
1492
  request
1124
1493
  );
1125
1494
  }
1126
1495
  async listTurns(workspaceId, sessionId, options = {}) {
1127
1496
  return await this.requestJson(
1128
1497
  "GET",
1129
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/turns`,
1498
+ `${sessionPath(workspaceId, sessionId)}/turns`,
1130
1499
  void 0,
1131
1500
  {
1132
1501
  ...options.limit !== void 0 ? { limit: String(options.limit) } : {},
1133
1502
  ...options.latestStarted ? { latestStarted: "1" } : {}
1134
- }
1503
+ },
1504
+ { signal: options.signal }
1135
1505
  );
1136
1506
  }
1137
1507
  /** Newest turn that durably emitted `turn.started`, or null before any admission. */
1138
- async getLatestStartedTurn(workspaceId, sessionId) {
1508
+ async getLatestStartedTurn(workspaceId, sessionId, options = {}) {
1139
1509
  const turns = await this.listTurns(workspaceId, sessionId, {
1140
- latestStarted: true
1510
+ latestStarted: true,
1511
+ signal: options.signal
1141
1512
  });
1142
1513
  return turns[0] ?? null;
1143
1514
  }
@@ -1159,6 +1530,24 @@ var OpenGeniClient = class {
1159
1530
  { signal: options.signal }
1160
1531
  );
1161
1532
  }
1533
+ /** Ask one authoritative Connected Machine runner to drain accepted work and
1534
+ * install the exact signed version promoted for its channel. Progress is read
1535
+ * from `listMachines`; completion requires the successor build identity. */
1536
+ async updateMachineAgent(workspaceId, enrollmentId) {
1537
+ return await this.requestJson(
1538
+ "POST",
1539
+ `/v1/workspaces/${workspaceId}/machines/${enrollmentId}/update`
1540
+ );
1541
+ }
1542
+ /** Revision-fenced update of a Connected Machine's optional command memory
1543
+ * policy. Null byte limits preserve unrestricted machine access. */
1544
+ async updateMachineOperationPolicy(workspaceId, enrollmentId, request) {
1545
+ return await this.requestJson(
1546
+ "PATCH",
1547
+ `/v1/workspaces/${workspaceId}/machines/${enrollmentId}/operation-policy`,
1548
+ request
1549
+ );
1550
+ }
1162
1551
  /**
1163
1552
  * Read the downsampled (~1/min) metrics series for ONE machine over a time
1164
1553
  * window (default 1h). The samples are oldest-first (a left-to-right chart).
@@ -1175,8 +1564,9 @@ var OpenGeniClient = class {
1175
1564
  /**
1176
1565
  * Remove one connected self-hosted machine enrollment. The control-plane
1177
1566
  * operation works while the agent is offline, revokes future reconnects,
1178
- * retains history, and returns a typed blocker when active route/lease or
1179
- * recovery dependencies make removal unsafe. `idempotencyKey` is replay-safe.
1567
+ * retains history, and atomically detaches idle dependent sessions (a
1568
+ * machine-home session becomes `backend:none`). Active turns, live leases,
1569
+ * and recovery work remain typed blockers. `idempotencyKey` is replay-safe.
1180
1570
  */
1181
1571
  async removeEnrollment(workspaceId, enrollmentId, request = {}) {
1182
1572
  return await this.requestJson(
@@ -1213,7 +1603,8 @@ var OpenGeniClient = class {
1213
1603
  `/v1/workspaces/${workspaceId}/enrollments/device/approve`,
1214
1604
  {
1215
1605
  userCode: request.userCode,
1216
- allowScreenControl: request.allowScreenControl ?? false
1606
+ allowScreenControl: request.allowScreenControl ?? false,
1607
+ ...request.scope ? { scope: request.scope } : {}
1217
1608
  }
1218
1609
  );
1219
1610
  }
@@ -1249,7 +1640,7 @@ var OpenGeniClient = class {
1249
1640
  async swapActiveSandbox(workspaceId, sessionId, request) {
1250
1641
  return await this.requestJson(
1251
1642
  "POST",
1252
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/active-sandbox`,
1643
+ `${sessionPath(workspaceId, sessionId)}/active-sandbox`,
1253
1644
  request
1254
1645
  );
1255
1646
  }
@@ -1260,6 +1651,8 @@ var OpenGeniClient = class {
1260
1651
  `/v1/workspaces/${workspaceId}/scheduled-tasks`,
1261
1652
  void 0,
1262
1653
  {
1654
+ ...options.offset !== void 0 ? { offset: String(options.offset) } : {},
1655
+ ...options.sessionId ? { sessionId: options.sessionId } : {},
1263
1656
  ...options.limit !== void 0 ? { limit: String(options.limit) } : {}
1264
1657
  }
1265
1658
  );
@@ -1270,6 +1663,18 @@ var OpenGeniClient = class {
1270
1663
  `/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}`
1271
1664
  );
1272
1665
  }
1666
+ /**
1667
+ * Channels a person may choose as a scheduled task's fixed Slack destination:
1668
+ * active, non-shared channels the selected OpenGeni bot already belongs to.
1669
+ */
1670
+ async listScheduledTaskSlackChannels(workspaceId, connectionId, cursor) {
1671
+ const query = new URLSearchParams({ connectionId });
1672
+ if (cursor) query.set("cursor", cursor);
1673
+ return await this.requestJson(
1674
+ "GET",
1675
+ `/v1/workspaces/${workspaceId}/scheduled-task-slack-channels?${query}`
1676
+ );
1677
+ }
1273
1678
  // --- Events: replay, send, stream ----------------------------------------
1274
1679
  /**
1275
1680
  * Return the events from one bounded page. With no cursor, this uses the safe
@@ -1292,7 +1697,7 @@ var OpenGeniClient = class {
1292
1697
  const listOptions = options.resultMode === "compact" ? null : options;
1293
1698
  const correlationId = crypto.randomUUID();
1294
1699
  const response = await this.fetchImpl(
1295
- this.url(`/v1/workspaces/${workspaceId}/sessions/${sessionId}/events`, {
1700
+ this.url(`${sessionPath(workspaceId, sessionId)}/events`, {
1296
1701
  ...listOptions?.after !== void 0 ? { after: String(listOptions.after) } : {},
1297
1702
  ...listOptions?.before !== void 0 ? { before: String(listOptions.before) } : {},
1298
1703
  ...listOptions?.limit !== void 0 ? { limit: String(listOptions.limit) } : {},
@@ -1312,7 +1717,7 @@ var OpenGeniClient = class {
1312
1717
  headers: { ...this.headers(correlationId), Accept: "application/json" }
1313
1718
  }
1314
1719
  );
1315
- assertApiContractResponse(response);
1720
+ assertApiContractResponse(response, this.apiContractStrict);
1316
1721
  if (!response.ok) {
1317
1722
  throw await apiErrorFromResponse(response, {
1318
1723
  method: "GET",
@@ -1373,14 +1778,15 @@ var OpenGeniClient = class {
1373
1778
  }
1374
1779
  /** POST a user/control event to the session. Returns the accepted event. */
1375
1780
  async sendEvent(workspaceId, sessionId, event) {
1376
- return await this.requestJson(
1781
+ return await this.requestSessionCommand(
1377
1782
  "POST",
1378
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/events`,
1783
+ `${sessionPath(workspaceId, sessionId)}/events`,
1379
1784
  event
1380
1785
  );
1381
1786
  }
1382
1787
  async sendMessage(workspaceId, sessionId, message) {
1383
1788
  const input = typeof message === "string" ? { text: message } : message;
1789
+ assertNoMessageTools(input);
1384
1790
  const { clientEventId, ...payload } = input;
1385
1791
  return await this.sendEvent(workspaceId, sessionId, {
1386
1792
  type: "user.message",
@@ -1407,7 +1813,7 @@ var OpenGeniClient = class {
1407
1813
  async listHumanInputRequests(workspaceId, sessionId, options = {}) {
1408
1814
  const result = await this.requestJson(
1409
1815
  "GET",
1410
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/human-input-requests`,
1816
+ `${sessionPath(workspaceId, sessionId)}/human-input-requests`,
1411
1817
  void 0,
1412
1818
  options.status ? { status: options.status } : void 0
1413
1819
  );
@@ -1416,7 +1822,7 @@ var OpenGeniClient = class {
1416
1822
  async getHumanInputRequest(workspaceId, sessionId, requestId) {
1417
1823
  return await this.requestJson(
1418
1824
  "GET",
1419
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/human-input-requests/${requestId}`
1825
+ `${sessionPath(workspaceId, sessionId)}/human-input-requests/${requestId}`
1420
1826
  );
1421
1827
  }
1422
1828
  async submitHumanInputResponse(workspaceId, sessionId, requestId, response, options = {}) {
@@ -1446,7 +1852,7 @@ var OpenGeniClient = class {
1446
1852
  }
1447
1853
  /** Open one raw SSE connection (no reconnect). Most callers want `streamEvents`. */
1448
1854
  async openEventStream(workspaceId, sessionId, options = {}) {
1449
- const url = this.url(`/v1/workspaces/${workspaceId}/sessions/${sessionId}/events/stream`, {
1855
+ const url = this.url(`${sessionPath(workspaceId, sessionId)}/events/stream`, {
1450
1856
  after: String(options.after ?? 0)
1451
1857
  });
1452
1858
  const correlationId = crypto.randomUUID();
@@ -1455,7 +1861,7 @@ var OpenGeniClient = class {
1455
1861
  headers: { ...this.headers(correlationId), Accept: "text/event-stream" },
1456
1862
  ...options.signal ? { signal: options.signal } : {}
1457
1863
  });
1458
- assertApiContractResponse(response);
1864
+ assertApiContractResponse(response, this.apiContractStrict);
1459
1865
  if (!response.ok) {
1460
1866
  throw await apiErrorFromResponse(response, {
1461
1867
  method: "GET",
@@ -1469,57 +1875,86 @@ var OpenGeniClient = class {
1469
1875
  }
1470
1876
  // --- Turn queue ------------------------------------------------------------
1471
1877
  async getQueue(workspaceId, sessionId) {
1472
- const path = `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue`;
1473
- return await this.singleFlightRead(
1878
+ const path = `${sessionPath(workspaceId, sessionId)}/queue`;
1879
+ return await this.sharedRead(
1474
1880
  path,
1475
- () => this.requestJson("GET", path)
1881
+ () => this.requestSessionCommand("GET", path)
1476
1882
  );
1477
1883
  }
1478
1884
  async moveQueueItem(workspaceId, sessionId, turnId, request) {
1479
- return await this.requestJson(
1885
+ return await this.requestSessionCommand(
1480
1886
  "POST",
1481
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/move`,
1887
+ `${sessionPath(workspaceId, sessionId)}/queue/${turnId}/move`,
1482
1888
  request
1483
1889
  );
1484
1890
  }
1485
1891
  async editQueueItem(workspaceId, sessionId, turnId, request) {
1486
- return await this.requestJson(
1892
+ return await this.requestSessionCommand(
1487
1893
  "POST",
1488
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/edit`,
1894
+ `${sessionPath(workspaceId, sessionId)}/queue/${turnId}/edit`,
1489
1895
  request
1490
1896
  );
1491
1897
  }
1492
1898
  async steerQueueItem(workspaceId, sessionId, turnId, request) {
1493
- return await this.requestJson(
1899
+ return await this.requestSessionCommand(
1494
1900
  "POST",
1495
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/steer`,
1901
+ `${sessionPath(workspaceId, sessionId)}/queue/${turnId}/steer`,
1496
1902
  request
1497
1903
  );
1498
1904
  }
1499
1905
  async deleteQueueItem(workspaceId, sessionId, turnId, request) {
1500
- return await this.requestJson(
1906
+ return await this.requestSessionCommand(
1501
1907
  "POST",
1502
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/delete`,
1908
+ `${sessionPath(workspaceId, sessionId)}/queue/${turnId}/delete`,
1503
1909
  request
1504
1910
  );
1505
1911
  }
1506
- async getComposerDraft(workspaceId, sessionId) {
1507
- return await this.requestJson(
1912
+ async getComposerDraft(workspaceId, sessionId, options = {}) {
1913
+ return await this.requestSessionCommand(
1508
1914
  "GET",
1509
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/composer-draft`
1915
+ `${sessionPath(workspaceId, sessionId)}/composer-draft`,
1916
+ void 0,
1917
+ options
1510
1918
  );
1511
1919
  }
1512
1920
  async saveComposerDraft(workspaceId, sessionId, request) {
1513
- return await this.requestJson(
1921
+ return await this.requestSessionCommand(
1514
1922
  "PUT",
1515
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/composer-draft`,
1923
+ `${sessionPath(workspaceId, sessionId)}/composer-draft`,
1924
+ request
1925
+ );
1926
+ }
1927
+ async submitComposerDraft(workspaceId, sessionId, request) {
1928
+ return await this.requestSessionCommand(
1929
+ "POST",
1930
+ `${sessionPath(workspaceId, sessionId)}/composer-draft/submit`,
1931
+ request
1932
+ );
1933
+ }
1934
+ /** Inspect bounded checkpoint recovery eligibility without changing session state. */
1935
+ async getSandboxRecovery(workspaceId, sessionId) {
1936
+ return this.requestJson("GET", `${sessionPath(workspaceId, sessionId)}/sandbox-recovery`);
1937
+ }
1938
+ /** Restore only the explicitly selected checkpoint; never retry a command. */
1939
+ async recoverSandbox(workspaceId, sessionId, request) {
1940
+ return this.requestSessionCommand(
1941
+ "POST",
1942
+ `${sessionPath(workspaceId, sessionId)}/sandbox-recovery`,
1943
+ request
1944
+ );
1945
+ }
1946
+ /** Retry the exact failed turn. Keep clientEventId unchanged on transport retries. */
1947
+ async retrySession(workspaceId, sessionId, request) {
1948
+ return await this.requestSessionCommand(
1949
+ "POST",
1950
+ `${sessionPath(workspaceId, sessionId)}/retry`,
1516
1951
  request
1517
1952
  );
1518
1953
  }
1519
1954
  async controlSession(workspaceId, sessionId, request) {
1520
- return await this.requestJson(
1955
+ return await this.requestSessionCommand(
1521
1956
  "POST",
1522
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/control`,
1957
+ `${sessionPath(workspaceId, sessionId)}/control`,
1523
1958
  request
1524
1959
  );
1525
1960
  }
@@ -1544,6 +1979,9 @@ var OpenGeniClient = class {
1544
1979
  ...options.expectedControlEtag ? { expectedControlEtag: options.expectedControlEtag } : {}
1545
1980
  });
1546
1981
  }
1982
+ async setWorkspacePauseTimer(workspaceId, request) {
1983
+ return await this.requestJson("POST", `/v1/workspaces/${workspaceId}/pause-timer`, request);
1984
+ }
1547
1985
  async setWorkspaceInferenceState(workspaceId, request) {
1548
1986
  return await this.requestJson(
1549
1987
  "POST",
@@ -1567,7 +2005,7 @@ var OpenGeniClient = class {
1567
2005
  headers: { ...this.headers(correlationId), Accept: "application/json" }
1568
2006
  }
1569
2007
  );
1570
- assertApiContractResponse(response);
2008
+ assertApiContractResponse(response, this.apiContractStrict);
1571
2009
  if (!response.ok) {
1572
2010
  throw await apiErrorFromResponse(response, {
1573
2011
  method: "GET",
@@ -1622,7 +2060,7 @@ var OpenGeniClient = class {
1622
2060
  ...options.signal ? { signal: options.signal } : {}
1623
2061
  }
1624
2062
  );
1625
- assertApiContractResponse(response);
2063
+ assertApiContractResponse(response, this.apiContractStrict);
1626
2064
  if (!response.ok) {
1627
2065
  throw await apiErrorFromResponse(response, {
1628
2066
  method: "GET",
@@ -1657,7 +2095,7 @@ var OpenGeniClient = class {
1657
2095
  ...options.signal ? { signal: options.signal } : {}
1658
2096
  }
1659
2097
  );
1660
- assertApiContractResponse(response);
2098
+ assertApiContractResponse(response, this.apiContractStrict);
1661
2099
  if (!response.ok) {
1662
2100
  throw await apiErrorFromResponse(response, {
1663
2101
  method: "GET",
@@ -1675,40 +2113,69 @@ var OpenGeniClient = class {
1675
2113
  */
1676
2114
  async steerMessage(workspaceId, sessionId, message) {
1677
2115
  const input = typeof message === "string" ? { text: message } : message;
1678
- return await this.requestJson(
2116
+ assertNoMessageTools(input);
2117
+ return await this.requestSessionCommand(
1679
2118
  "POST",
1680
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/steer`,
2119
+ `${sessionPath(workspaceId, sessionId)}/steer`,
1681
2120
  input
1682
2121
  );
1683
2122
  }
1684
2123
  // --- Goals -------------------------------------------------------------------
1685
2124
  /** The session's goal. 404s when the session never had one. */
1686
- async getGoal(workspaceId, sessionId) {
1687
- const path = `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal`;
1688
- return await this.singleFlightRead(path, () => this.requestJson("GET", path));
2125
+ async getGoal(workspaceId, sessionId, options = {}) {
2126
+ const path = `${sessionPath(workspaceId, sessionId)}/goal`;
2127
+ return await this.sharedRead(
2128
+ path,
2129
+ (signal) => this.requestJson("GET", path, void 0, {}, { signal }),
2130
+ options
2131
+ );
1689
2132
  }
1690
2133
  async updateGoal(workspaceId, sessionId, request) {
1691
2134
  return await this.requestJson(
1692
2135
  "PATCH",
1693
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal`,
2136
+ `${sessionPath(workspaceId, sessionId)}/goal`,
1694
2137
  request
1695
2138
  );
1696
2139
  }
1697
2140
  async listGoalRevisions(workspaceId, sessionId) {
1698
2141
  return await this.requestJson(
1699
2142
  "GET",
1700
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal/revisions`
2143
+ `${sessionPath(workspaceId, sessionId)}/goal/revisions`
2144
+ );
2145
+ }
2146
+ async listGoalRevisionPage(workspaceId, sessionId, options = {}) {
2147
+ const query = new URLSearchParams();
2148
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
2149
+ if (options.before !== void 0) query.set("before", options.before);
2150
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
2151
+ return await this.requestJson(
2152
+ "GET",
2153
+ `${sessionPath(workspaceId, sessionId)}/goal/revisions/page${suffix}`
2154
+ );
2155
+ }
2156
+ async rejectGoalRevision(workspaceId, sessionId, revisionId, request) {
2157
+ return await this.requestJson(
2158
+ "POST",
2159
+ `${sessionPath(workspaceId, sessionId)}/goal/revisions/${revisionId}/reject`,
2160
+ request
2161
+ );
2162
+ }
2163
+ async rollbackGoalRevision(workspaceId, sessionId, revisionId, request) {
2164
+ return await this.requestJson(
2165
+ "POST",
2166
+ `${sessionPath(workspaceId, sessionId)}/goal/revisions/${revisionId}/rollback`,
2167
+ request
1701
2168
  );
1702
2169
  }
1703
2170
  async applyGoalRevision(workspaceId, sessionId, revisionId, request) {
1704
2171
  return await this.requestJson(
1705
2172
  "POST",
1706
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal/revisions/${revisionId}/apply`,
2173
+ `${sessionPath(workspaceId, sessionId)}/goal/revisions/${revisionId}/apply`,
1707
2174
  request
1708
2175
  );
1709
2176
  }
1710
2177
  async deleteGoal(workspaceId, sessionId) {
1711
- await this.requestVoid("DELETE", `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal`);
2178
+ await this.requestVoid("DELETE", `${sessionPath(workspaceId, sessionId)}/goal`);
1712
2179
  }
1713
2180
  /** Pause the goal loop: the session stops self-continuing until resumed. */
1714
2181
  async pauseGoal(workspaceId, sessionId, options = {}) {
@@ -1730,17 +2197,15 @@ var OpenGeniClient = class {
1730
2197
  * context — the destructive intent is explicit on the wire.
1731
2198
  */
1732
2199
  async clearSessionContext(workspaceId, sessionId) {
1733
- await this.requestVoid(
1734
- "POST",
1735
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/context/clear`,
1736
- { confirm: true }
1737
- );
2200
+ await this.requestVoid("POST", `${sessionPath(workspaceId, sessionId)}/context/clear`, {
2201
+ confirm: true
2202
+ });
1738
2203
  }
1739
2204
  /** Request one durable portable compaction at the next safe model boundary. */
1740
2205
  async compactSessionContext(workspaceId, sessionId) {
1741
2206
  return await this.requestJson(
1742
2207
  "POST",
1743
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/context/compact`,
2208
+ `${sessionPath(workspaceId, sessionId)}/context/compact`,
1744
2209
  {}
1745
2210
  );
1746
2211
  }
@@ -1752,7 +2217,7 @@ var OpenGeniClient = class {
1752
2217
  async fsList(workspaceId, sessionId, request = {}, options = {}) {
1753
2218
  return await this.requestJson(
1754
2219
  "POST",
1755
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/list`,
2220
+ `${sessionPath(workspaceId, sessionId)}/fs/list`,
1756
2221
  request,
1757
2222
  {},
1758
2223
  options
@@ -1762,7 +2227,7 @@ var OpenGeniClient = class {
1762
2227
  async fsListBatch(workspaceId, sessionId, request, options = {}) {
1763
2228
  return await this.requestJson(
1764
2229
  "POST",
1765
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/list-batch`,
2230
+ `${sessionPath(workspaceId, sessionId)}/fs/list-batch`,
1766
2231
  request,
1767
2232
  {},
1768
2233
  options
@@ -1772,7 +2237,17 @@ var OpenGeniClient = class {
1772
2237
  async fsRead(workspaceId, sessionId, request, options = {}) {
1773
2238
  return await this.requestJson(
1774
2239
  "POST",
1775
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/read`,
2240
+ request.workspaceOnly ? `${sessionPath(workspaceId, sessionId)}/fs/read-workspace` : `${sessionPath(workspaceId, sessionId)}/fs/read`,
2241
+ request,
2242
+ {},
2243
+ options
2244
+ );
2245
+ }
2246
+ /** Publish one exact sandbox file into permanent workspace artifact storage. */
2247
+ async publishSandboxFileArtifact(workspaceId, sessionId, request, options = {}) {
2248
+ return await this.requestJson(
2249
+ "POST",
2250
+ `${sessionPath(workspaceId, sessionId)}/artifacts/publish`,
1776
2251
  request,
1777
2252
  {},
1778
2253
  options
@@ -1782,7 +2257,7 @@ var OpenGeniClient = class {
1782
2257
  async fsWrite(workspaceId, sessionId, request) {
1783
2258
  return await this.requestJson(
1784
2259
  "POST",
1785
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/write`,
2260
+ `${sessionPath(workspaceId, sessionId)}/fs/write`,
1786
2261
  request
1787
2262
  );
1788
2263
  }
@@ -1790,7 +2265,7 @@ var OpenGeniClient = class {
1790
2265
  async fsDelete(workspaceId, sessionId, request) {
1791
2266
  return await this.requestJson(
1792
2267
  "POST",
1793
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/delete`,
2268
+ `${sessionPath(workspaceId, sessionId)}/fs/delete`,
1794
2269
  request
1795
2270
  );
1796
2271
  }
@@ -1798,7 +2273,7 @@ var OpenGeniClient = class {
1798
2273
  async fsMove(workspaceId, sessionId, request) {
1799
2274
  return await this.requestJson(
1800
2275
  "POST",
1801
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/move`,
2276
+ `${sessionPath(workspaceId, sessionId)}/fs/move`,
1802
2277
  request
1803
2278
  );
1804
2279
  }
@@ -1806,7 +2281,7 @@ var OpenGeniClient = class {
1806
2281
  async fsMkdir(workspaceId, sessionId, request) {
1807
2282
  return await this.requestJson(
1808
2283
  "POST",
1809
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/mkdir`,
2284
+ `${sessionPath(workspaceId, sessionId)}/fs/mkdir`,
1810
2285
  request
1811
2286
  );
1812
2287
  }
@@ -1814,7 +2289,7 @@ var OpenGeniClient = class {
1814
2289
  async gitStatus(workspaceId, sessionId, request = {}, options = {}) {
1815
2290
  return await this.requestJson(
1816
2291
  "POST",
1817
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/status`,
2292
+ `${sessionPath(workspaceId, sessionId)}/git/status`,
1818
2293
  request,
1819
2294
  {},
1820
2295
  options
@@ -1824,7 +2299,7 @@ var OpenGeniClient = class {
1824
2299
  async gitDiff(workspaceId, sessionId, request = {}, options = {}) {
1825
2300
  return await this.requestJson(
1826
2301
  "POST",
1827
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/diff`,
2302
+ `${sessionPath(workspaceId, sessionId)}/git/diff`,
1828
2303
  request,
1829
2304
  {},
1830
2305
  options
@@ -1834,7 +2309,7 @@ var OpenGeniClient = class {
1834
2309
  async gitReadBatch(workspaceId, sessionId, request, options = {}) {
1835
2310
  return await this.requestJson(
1836
2311
  "POST",
1837
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/read-batch`,
2312
+ `${sessionPath(workspaceId, sessionId)}/git/read-batch`,
1838
2313
  request,
1839
2314
  {},
1840
2315
  options
@@ -1844,7 +2319,7 @@ var OpenGeniClient = class {
1844
2319
  async gitLog(workspaceId, sessionId, request = {}) {
1845
2320
  return await this.requestJson(
1846
2321
  "POST",
1847
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/log`,
2322
+ `${sessionPath(workspaceId, sessionId)}/git/log`,
1848
2323
  request
1849
2324
  );
1850
2325
  }
@@ -1852,7 +2327,7 @@ var OpenGeniClient = class {
1852
2327
  async gitShow(workspaceId, sessionId, request) {
1853
2328
  return await this.requestJson(
1854
2329
  "POST",
1855
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/show`,
2330
+ `${sessionPath(workspaceId, sessionId)}/git/show`,
1856
2331
  request
1857
2332
  );
1858
2333
  }
@@ -1863,7 +2338,7 @@ var OpenGeniClient = class {
1863
2338
  async getWorkspaceCapture(workspaceId, sessionId, options = {}) {
1864
2339
  return await this.requestJson(
1865
2340
  "GET",
1866
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/workspace/capture`,
2341
+ `${sessionPath(workspaceId, sessionId)}/workspace/capture`,
1867
2342
  void 0,
1868
2343
  {},
1869
2344
  options
@@ -1877,7 +2352,7 @@ var OpenGeniClient = class {
1877
2352
  if (revision !== void 0) query.revision = String(revision);
1878
2353
  return await this.requestJson(
1879
2354
  "GET",
1880
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/workspace/capture/file`,
2355
+ `${sessionPath(workspaceId, sessionId)}/workspace/capture/file`,
1881
2356
  void 0,
1882
2357
  query,
1883
2358
  options
@@ -1887,7 +2362,7 @@ var OpenGeniClient = class {
1887
2362
  async terminalExec(workspaceId, sessionId, request) {
1888
2363
  return await this.requestJson(
1889
2364
  "POST",
1890
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/exec`,
2365
+ `${sessionPath(workspaceId, sessionId)}/terminal/exec`,
1891
2366
  request
1892
2367
  );
1893
2368
  }
@@ -1896,7 +2371,7 @@ var OpenGeniClient = class {
1896
2371
  async terminalPtyOpen(workspaceId, sessionId, request = {}) {
1897
2372
  return await this.requestJson(
1898
2373
  "POST",
1899
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty`,
2374
+ `${sessionPath(workspaceId, sessionId)}/terminal/pty`,
1900
2375
  request
1901
2376
  );
1902
2377
  }
@@ -1904,7 +2379,7 @@ var OpenGeniClient = class {
1904
2379
  async terminalPtyWrite(workspaceId, sessionId, request) {
1905
2380
  await this.requestVoid(
1906
2381
  "POST",
1907
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty/write`,
2382
+ `${sessionPath(workspaceId, sessionId)}/terminal/pty/write`,
1908
2383
  request
1909
2384
  );
1910
2385
  }
@@ -1912,7 +2387,7 @@ var OpenGeniClient = class {
1912
2387
  async terminalPtyResize(workspaceId, sessionId, request) {
1913
2388
  await this.requestVoid(
1914
2389
  "POST",
1915
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty/resize`,
2390
+ `${sessionPath(workspaceId, sessionId)}/terminal/pty/resize`,
1916
2391
  request
1917
2392
  );
1918
2393
  }
@@ -1920,7 +2395,7 @@ var OpenGeniClient = class {
1920
2395
  async terminalPtyClose(workspaceId, sessionId, request) {
1921
2396
  await this.requestVoid(
1922
2397
  "POST",
1923
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty/close`,
2398
+ `${sessionPath(workspaceId, sessionId)}/terminal/pty/close`,
1924
2399
  request
1925
2400
  );
1926
2401
  }
@@ -1938,7 +2413,7 @@ var OpenGeniClient = class {
1938
2413
  async getStreamCapabilities(workspaceId, sessionId, options = {}) {
1939
2414
  return await this.requestJson(
1940
2415
  "GET",
1941
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/stream-capabilities`,
2416
+ `${sessionPath(workspaceId, sessionId)}/stream-capabilities`,
1942
2417
  void 0,
1943
2418
  {},
1944
2419
  options
@@ -1950,7 +2425,7 @@ var OpenGeniClient = class {
1950
2425
  async acknowledgeStream(workspaceId, sessionId, request = {}) {
1951
2426
  return await this.requestJson(
1952
2427
  "POST",
1953
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/stream-capabilities/acknowledge`,
2428
+ `${sessionPath(workspaceId, sessionId)}/stream-capabilities/acknowledge`,
1954
2429
  request
1955
2430
  );
1956
2431
  }
@@ -1963,7 +2438,7 @@ var OpenGeniClient = class {
1963
2438
  async attachViewer(workspaceId, sessionId, request = {}) {
1964
2439
  return await this.requestJson(
1965
2440
  "POST",
1966
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/viewers`,
2441
+ `${sessionPath(workspaceId, sessionId)}/viewers`,
1967
2442
  request
1968
2443
  );
1969
2444
  }
@@ -1973,16 +2448,13 @@ var OpenGeniClient = class {
1973
2448
  async heartbeatViewer(workspaceId, sessionId, viewerId, request) {
1974
2449
  return await this.requestJson(
1975
2450
  "POST",
1976
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/viewers/${viewerId}/heartbeat`,
2451
+ `${sessionPath(workspaceId, sessionId)}/viewers/${viewerId}/heartbeat`,
1977
2452
  request
1978
2453
  );
1979
2454
  }
1980
2455
  /** Detach a viewer (delete this holder; idempotent delete-my-row). */
1981
2456
  async detachViewer(workspaceId, sessionId, viewerId) {
1982
- await this.requestVoid(
1983
- "DELETE",
1984
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/viewers/${viewerId}`
1985
- );
2457
+ await this.requestVoid("DELETE", `${sessionPath(workspaceId, sessionId)}/viewers/${viewerId}`);
1986
2458
  }
1987
2459
  // --- Browser / Computer interaction resources --------------------------------
1988
2460
  streamWorkspaceInteractionRevisions(workspaceId, options = {}) {
@@ -2014,7 +2486,7 @@ var OpenGeniClient = class {
2014
2486
  ...options.signal ? { signal: options.signal } : {}
2015
2487
  }
2016
2488
  );
2017
- assertApiContractResponse(response);
2489
+ assertApiContractResponse(response, this.apiContractStrict);
2018
2490
  if (!response.ok) {
2019
2491
  throw await apiErrorFromResponse(response, {
2020
2492
  method: "GET",
@@ -2369,6 +2841,54 @@ var OpenGeniClient = class {
2369
2841
  options
2370
2842
  );
2371
2843
  }
2844
+ async captureBrowserTarget(workspaceId, browserSessionId, targetId, options = {}, captureOptions = {}) {
2845
+ const query = new URLSearchParams();
2846
+ if (captureOptions.fullPage !== void 0) {
2847
+ if (typeof captureOptions.fullPage !== "boolean") {
2848
+ throw new TypeError("browser screenshot fullPage must be a boolean");
2849
+ }
2850
+ query.set("fullPage", String(captureOptions.fullPage));
2851
+ }
2852
+ if (captureOptions.format !== void 0) {
2853
+ if (captureOptions.format !== "jpeg" && captureOptions.format !== "png") {
2854
+ throw new TypeError("browser screenshot format must be jpeg or png");
2855
+ }
2856
+ query.set("format", captureOptions.format);
2857
+ }
2858
+ if (captureOptions.quality !== void 0) {
2859
+ if (!Number.isSafeInteger(captureOptions.quality) || captureOptions.quality < 1 || captureOptions.quality > 100) {
2860
+ throw new RangeError("browser screenshot quality must be an integer from 1 to 100");
2861
+ }
2862
+ query.set("quality", String(captureOptions.quality));
2863
+ }
2864
+ const suffix = query.size > 0 ? `?${query}` : "";
2865
+ const response = await this.requestResponse(
2866
+ "GET",
2867
+ `/v1/workspaces/${workspaceId}/browser-sessions/${encodeURIComponent(browserSessionId)}/targets/${encodeURIComponent(targetId)}/screenshot${suffix}`,
2868
+ {},
2869
+ options
2870
+ );
2871
+ const mediaType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
2872
+ const header = response.headers.get("x-opengeni-browser-frame");
2873
+ if (mediaType !== "image/jpeg" && mediaType !== "image/png" || !header || header.length > 64 * 1024) {
2874
+ await cancelResponseBody(response, "browser frame metadata is invalid");
2875
+ throw new OpenGeniApiError(502, "browser frame metadata is invalid");
2876
+ }
2877
+ let metadata;
2878
+ try {
2879
+ metadata = parseBrowserFrameMetadata(
2880
+ JSON.parse(atob(header.replace(/-/gu, "+").replace(/_/gu, "/")))
2881
+ );
2882
+ } catch {
2883
+ await cancelResponseBody(response, "browser frame metadata is invalid");
2884
+ throw new OpenGeniApiError(502, "browser frame metadata is invalid");
2885
+ }
2886
+ const data = await readBoundedResponseBytes(response, 24 * 1024 * 1024, null);
2887
+ if (metadata.browserSessionId !== browserSessionId || metadata.targetId !== targetId || metadata.mediaType !== mediaType) {
2888
+ throw new OpenGeniApiError(502, "browser frame evidence does not match its request");
2889
+ }
2890
+ return { ...metadata, data };
2891
+ }
2372
2892
  async closeBrowserTarget(workspaceId, browserSessionId, targetId, options = {}) {
2373
2893
  return await this.requestJson(
2374
2894
  "DELETE",
@@ -2387,6 +2907,32 @@ var OpenGeniClient = class {
2387
2907
  options
2388
2908
  );
2389
2909
  }
2910
+ async getBrowserTargetState(workspaceId, browserSessionId, targetId, options = {}) {
2911
+ const state = await this.requestJson(
2912
+ "GET",
2913
+ `/v1/workspaces/${workspaceId}/browser-sessions/${encodeURIComponent(browserSessionId)}/targets/${encodeURIComponent(targetId)}/state`,
2914
+ void 0,
2915
+ {},
2916
+ options
2917
+ );
2918
+ if (state.browserSessionId !== browserSessionId || state.targetId !== targetId) {
2919
+ throw new OpenGeniApiError(502, "browser target state belongs to another binding");
2920
+ }
2921
+ return state;
2922
+ }
2923
+ async readBrowserDom(workspaceId, browserSessionId, targetId, request, options = {}) {
2924
+ const result = await this.requestJson(
2925
+ "POST",
2926
+ `/v1/workspaces/${workspaceId}/browser-sessions/${encodeURIComponent(browserSessionId)}/targets/${encodeURIComponent(targetId)}/dom-read`,
2927
+ request,
2928
+ {},
2929
+ options
2930
+ );
2931
+ if (result.browserSessionId !== browserSessionId || result.targetId !== targetId || result.kind !== request.kind || result.targetGeneration !== request.expectedTargetGeneration || result.documentGeneration !== request.expectedDocumentGeneration || result.frameId !== request.expectedFrameId) {
2932
+ throw new OpenGeniApiError(502, "browser DOM read belongs to another binding");
2933
+ }
2934
+ return result;
2935
+ }
2390
2936
  async actInBrowser(workspaceId, browserSessionId, request, options = {}) {
2391
2937
  return await this.requestJson(
2392
2938
  "POST",
@@ -2501,6 +3047,15 @@ var OpenGeniClient = class {
2501
3047
  options
2502
3048
  );
2503
3049
  }
3050
+ async getComputerInputPosture(workspaceId, computerSessionId, options = {}) {
3051
+ return await this.requestJson(
3052
+ "GET",
3053
+ `/v1/workspaces/${workspaceId}/computer-sessions/${encodeURIComponent(computerSessionId)}/input-posture`,
3054
+ void 0,
3055
+ {},
3056
+ options
3057
+ );
3058
+ }
2504
3059
  async createComputerSession(workspaceId, request, options = {}) {
2505
3060
  return await this.requestJson(
2506
3061
  "POST",
@@ -2528,6 +3083,42 @@ var OpenGeniClient = class {
2528
3083
  options
2529
3084
  );
2530
3085
  }
3086
+ async captureComputerTarget(workspaceId, computerSessionId, targetId, options = {}) {
3087
+ const response = await this.requestResponse(
3088
+ "GET",
3089
+ `/v1/workspaces/${workspaceId}/computer-sessions/${encodeURIComponent(computerSessionId)}/targets/${encodeURIComponent(targetId)}/screenshot`,
3090
+ {},
3091
+ options
3092
+ );
3093
+ const mediaType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
3094
+ if (mediaType !== "image/jpeg" && mediaType !== "image/png") {
3095
+ await cancelResponseBody(response, "computer frame media type is invalid");
3096
+ throw new OpenGeniApiError(502, "computer frame media type is invalid");
3097
+ }
3098
+ const metadataHeader = response.headers.get("x-opengeni-computer-frame");
3099
+ if (!metadataHeader || metadataHeader.length > 32 * 1024) {
3100
+ await cancelResponseBody(response, "computer frame metadata is invalid");
3101
+ throw new OpenGeniApiError(502, "computer frame metadata is invalid");
3102
+ }
3103
+ let metadata;
3104
+ try {
3105
+ metadata = decodeComputerFrameMetadataHeader(metadataHeader);
3106
+ } catch {
3107
+ await cancelResponseBody(response, "computer frame metadata is invalid");
3108
+ throw new OpenGeniApiError(502, "computer frame metadata is invalid");
3109
+ }
3110
+ const bytes = await readBoundedResponseBytes(response, 256 * 1024, null);
3111
+ const mismatchReason = computerFrameEvidenceMismatchReason(metadata, {
3112
+ computerSessionId,
3113
+ targetId,
3114
+ mediaType,
3115
+ sha256: await sha256Hex(bytes)
3116
+ });
3117
+ if (mismatchReason) {
3118
+ throw new OpenGeniApiError(502, "computer frame evidence does not match its request");
3119
+ }
3120
+ return { ...metadata, data: bytes };
3121
+ }
2531
3122
  async actInComputer(workspaceId, computerSessionId, request, options = {}) {
2532
3123
  return await this.requestJson(
2533
3124
  "POST",
@@ -2547,13 +3138,20 @@ var OpenGeniClient = class {
2547
3138
  );
2548
3139
  }
2549
3140
  async attachComputerSession(workspaceId, computerSessionId, request, options = {}) {
2550
- return await this.requestJson(
3141
+ const attachment = await this.requestJson(
2551
3142
  "POST",
2552
3143
  `/v1/workspaces/${workspaceId}/computer-sessions/${encodeURIComponent(computerSessionId)}/attachments`,
2553
3144
  request,
2554
3145
  {},
2555
3146
  options
2556
3147
  );
3148
+ if (attachment.stream.kind === "direct_rfb") {
3149
+ return {
3150
+ ...attachment,
3151
+ stream: { ...attachment.stream, inputAllowed: attachment.stream.inputAllowed === true }
3152
+ };
3153
+ }
3154
+ return attachment;
2557
3155
  }
2558
3156
  async heartbeatComputerSession(workspaceId, computerSessionId, options = {}) {
2559
3157
  return await this.requestJson(
@@ -2580,10 +3178,18 @@ var OpenGeniClient = class {
2580
3178
  * reasoning efforts, MCP servers, file-upload limits, and how the client is
2581
3179
  * expected to authenticate. Drives a composer's model picker without prior
2582
3180
  * knowledge of the host setup; safe to call before any auth is established.
3181
+ * Authenticated calls resolve the caller's default workspace, or the exact
3182
+ * `workspaceId` option, using the same selection rules as fresh session create.
2583
3183
  */
2584
- async getClientConfig() {
2585
- const config = await this.requestJson("GET", "/v1/config/client");
2586
- if (config.apiContractRevision !== OPENGENI_API_CONTRACT_REVISION) {
3184
+ async getClientConfig(options = {}) {
3185
+ const config = await this.requestJson(
3186
+ "GET",
3187
+ "/v1/config/client",
3188
+ void 0,
3189
+ options.workspaceId === void 0 ? {} : { workspaceId: options.workspaceId },
3190
+ options
3191
+ );
3192
+ if (this.apiContractStrict && config.apiContractRevision !== OPENGENI_API_CONTRACT_REVISION) {
2587
3193
  throw new OpenGeniApiContractMismatchError(
2588
3194
  OPENGENI_API_CONTRACT_REVISION,
2589
3195
  String(config.apiContractRevision || "(missing)")
@@ -2592,36 +3198,712 @@ var OpenGeniClient = class {
2592
3198
  return config;
2593
3199
  }
2594
3200
  /** Authenticated model definitions plus workspace-specific selectability. */
2595
- async getWorkspaceModelCatalog(workspaceId) {
3201
+ async getWorkspaceModelCatalog(workspaceId, options = {}) {
2596
3202
  return await this.requestJson(
2597
3203
  "GET",
2598
- `/v1/workspaces/${workspaceId}/model-catalog`
3204
+ `/v1/workspaces/${workspaceId}/model-catalog`,
3205
+ void 0,
3206
+ {},
3207
+ options
2599
3208
  );
2600
3209
  }
2601
- /** Authenticated realtime voice models and credential readiness. */
2602
- async getWorkspaceRealtimeModelCatalog(workspaceId) {
3210
+ /** List workspace-owned unpinned Vercel AI Gateway model slugs. */
3211
+ async listWorkspaceGatewayCustomModels(workspaceId) {
2603
3212
  return await this.requestJson(
2604
3213
  "GET",
2605
- `/v1/workspaces/${workspaceId}/realtime-model-catalog`
3214
+ `/v1/workspaces/${workspaceId}/gateway-custom-models`
2606
3215
  );
2607
3216
  }
2608
- /** The caller's access context: subject, account + workspace grants, defaults. */
2609
- async getAccessContext() {
2610
- return await this.requestJson("GET", "/v1/access/me");
3217
+ /** Add one exact upstream Vercel AI Gateway slug. */
3218
+ async createWorkspaceGatewayCustomModel(workspaceId, request) {
3219
+ return await this.requestJson(
3220
+ "POST",
3221
+ `/v1/workspaces/${workspaceId}/gateway-custom-models`,
3222
+ request
3223
+ );
2611
3224
  }
2612
- /** Active organization memberships proven by the current managed-human session. */
2613
- async listOrganizationMemberships() {
3225
+ /** Remove one workspace custom Gateway model by its stable row id. */
3226
+ async deleteWorkspaceGatewayCustomModel(workspaceId, customModelId, request) {
3227
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(
3228
+ customModelId
3229
+ )) {
3230
+ throw new TypeError("customModelId must be a UUID");
3231
+ }
3232
+ await this.requestVoid(
3233
+ "DELETE",
3234
+ `/v1/workspaces/${workspaceId}/gateway-custom-models/${encodeURIComponent(customModelId)}`,
3235
+ request
3236
+ );
3237
+ }
3238
+ /** List workspace-owned unpinned OpenRouter model slugs. */
3239
+ async listWorkspaceOpenRouterCustomModels(workspaceId) {
2614
3240
  return await this.requestJson(
2615
3241
  "GET",
2616
- "/v1/organization-memberships"
3242
+ `/v1/workspaces/${workspaceId}/openrouter-custom-models`
2617
3243
  );
2618
3244
  }
2619
- async listWorkspaces() {
2620
- return await this.requestJson("GET", "/v1/workspaces");
3245
+ /** Add one exact upstream OpenRouter slug. */
3246
+ async createWorkspaceOpenRouterCustomModel(workspaceId, request) {
3247
+ return await this.requestJson(
3248
+ "POST",
3249
+ `/v1/workspaces/${workspaceId}/openrouter-custom-models`,
3250
+ request
3251
+ );
3252
+ }
3253
+ /** Remove one workspace custom OpenRouter model by its stable row id. */
3254
+ async deleteWorkspaceOpenRouterCustomModel(workspaceId, customModelId, request) {
3255
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(
3256
+ customModelId
3257
+ )) {
3258
+ throw new TypeError("customModelId must be a UUID");
3259
+ }
3260
+ await this.requestVoid(
3261
+ "DELETE",
3262
+ `/v1/workspaces/${workspaceId}/openrouter-custom-models/${encodeURIComponent(customModelId)}`,
3263
+ request
3264
+ );
3265
+ }
3266
+ /** Read metadata for one organization-owned model-provider connection. */
3267
+ async getWorkspaceClaudeSubscriptionUsage(workspaceId) {
3268
+ return this.requestJson(
3269
+ "GET",
3270
+ `/v1/workspaces/${workspaceId}/model-providers/claude_subscription/usage`
3271
+ );
3272
+ }
3273
+ async listClaudeSubscriptionAccounts(workspaceId) {
3274
+ return this.requestJson("GET", `/v1/workspaces/${workspaceId}/claude/accounts`);
3275
+ }
3276
+ async activateClaudeSubscriptionAccount(workspaceId, accountId) {
3277
+ return this.requestJson(
3278
+ "POST",
3279
+ `/v1/workspaces/${workspaceId}/claude/accounts/${encodeURIComponent(accountId)}/activate`,
3280
+ {}
3281
+ );
3282
+ }
3283
+ async setClaudeSubscriptionRotationSettings(workspaceId, request) {
3284
+ return this.requestJson("PATCH", `/v1/workspaces/${workspaceId}/claude/settings`, request);
3285
+ }
3286
+ async setClaudeSubscriptionAccountAllocator(workspaceId, accountId, request) {
3287
+ return this.requestJson(
3288
+ "PATCH",
3289
+ `/v1/workspaces/${workspaceId}/claude/accounts/${encodeURIComponent(accountId)}/allocator`,
3290
+ request
3291
+ );
3292
+ }
3293
+ async renameClaudeSubscriptionAccount(workspaceId, accountId, label) {
3294
+ return this.requestJson(
3295
+ "PATCH",
3296
+ `/v1/workspaces/${workspaceId}/claude/accounts/${encodeURIComponent(accountId)}`,
3297
+ { label }
3298
+ );
3299
+ }
3300
+ async disconnectClaudeSubscriptionAccount(workspaceId, accountId) {
3301
+ return this.requestJson(
3302
+ "DELETE",
3303
+ `/v1/workspaces/${workspaceId}/claude/accounts/${encodeURIComponent(accountId)}`,
3304
+ {}
3305
+ );
3306
+ }
3307
+ async getClaudeSubscriptionAccountUsage(workspaceId, accountId) {
3308
+ return this.requestJson(
3309
+ "GET",
3310
+ `/v1/workspaces/${workspaceId}/claude/accounts/${encodeURIComponent(accountId)}/usage`
3311
+ );
3312
+ }
3313
+ async refreshClaudeSubscriptionAccountUsage(workspaceId, accountId) {
3314
+ return this.requestJson(
3315
+ "POST",
3316
+ `/v1/workspaces/${workspaceId}/claude/accounts/${encodeURIComponent(accountId)}/usage/refresh`,
3317
+ {}
3318
+ );
3319
+ }
3320
+ async listOrganizationClaudeSubscriptionAccounts(organizationId) {
3321
+ return this.requestJson("GET", `/v1/organizations/${organizationId}/claude/accounts`);
3322
+ }
3323
+ async activateOrganizationClaudeSubscriptionAccount(organizationId, accountId) {
3324
+ return this.requestJson(
3325
+ "POST",
3326
+ `/v1/organizations/${organizationId}/claude/accounts/${encodeURIComponent(accountId)}/activate`,
3327
+ {}
3328
+ );
3329
+ }
3330
+ async setOrganizationClaudeSubscriptionRotationSettings(organizationId, request) {
3331
+ return this.requestJson(
3332
+ "PATCH",
3333
+ `/v1/organizations/${organizationId}/claude/settings`,
3334
+ request
3335
+ );
3336
+ }
3337
+ async setOrganizationClaudeSubscriptionAccountAllocator(organizationId, accountId, request) {
3338
+ return this.requestJson(
3339
+ "PATCH",
3340
+ `/v1/organizations/${organizationId}/claude/accounts/${encodeURIComponent(accountId)}/allocator`,
3341
+ request
3342
+ );
3343
+ }
3344
+ async renameOrganizationClaudeSubscriptionAccount(organizationId, accountId, label) {
3345
+ return this.requestJson(
3346
+ "PATCH",
3347
+ `/v1/organizations/${organizationId}/claude/accounts/${encodeURIComponent(accountId)}`,
3348
+ { label }
3349
+ );
3350
+ }
3351
+ async disconnectOrganizationClaudeSubscriptionAccount(organizationId, accountId) {
3352
+ return this.requestJson(
3353
+ "DELETE",
3354
+ `/v1/organizations/${organizationId}/claude/accounts/${encodeURIComponent(accountId)}`,
3355
+ {}
3356
+ );
3357
+ }
3358
+ async getOrganizationClaudeSubscriptionAccountUsage(organizationId, accountId) {
3359
+ return this.requestJson(
3360
+ "GET",
3361
+ `/v1/organizations/${organizationId}/claude/accounts/${encodeURIComponent(accountId)}/usage`
3362
+ );
3363
+ }
3364
+ async refreshOrganizationClaudeSubscriptionAccountUsage(organizationId, accountId) {
3365
+ return this.requestJson(
3366
+ "POST",
3367
+ `/v1/organizations/${organizationId}/claude/accounts/${encodeURIComponent(accountId)}/usage/refresh`,
3368
+ {}
3369
+ );
3370
+ }
3371
+ async connectClaudeSubscriptionSetupToken(workspaceId, request) {
3372
+ return this.requestJson(
3373
+ "POST",
3374
+ `/v1/workspaces/${workspaceId}/claude/accounts/setup-token`,
3375
+ request
3376
+ );
3377
+ }
3378
+ async connectOrganizationClaudeSubscriptionSetupToken(organizationId, request) {
3379
+ return this.requestJson(
3380
+ "POST",
3381
+ `/v1/organizations/${organizationId}/claude/accounts/setup-token`,
3382
+ request
3383
+ );
3384
+ }
3385
+ /** Sign in with model and profile access; no inference request is made. */
3386
+ async startWorkspaceClaudeSubscriptionOAuth(workspaceId, request = {}) {
3387
+ return this.requestJson(
3388
+ "POST",
3389
+ `/v1/workspaces/${workspaceId}/model-providers/claude_subscription/oauth/start`,
3390
+ request
3391
+ );
3392
+ }
3393
+ async completeWorkspaceClaudeSubscriptionOAuth(workspaceId, request) {
3394
+ return this.requestJson(
3395
+ "POST",
3396
+ `/v1/workspaces/${workspaceId}/model-providers/claude_subscription/oauth/complete`,
3397
+ request
3398
+ );
3399
+ }
3400
+ async startOrganizationClaudeSubscriptionOAuth(organizationId, request = {}) {
3401
+ return this.requestJson(
3402
+ "POST",
3403
+ `/v1/organizations/${organizationId}/model-providers/claude_subscription/oauth/start`,
3404
+ request
3405
+ );
3406
+ }
3407
+ async completeOrganizationClaudeSubscriptionOAuth(organizationId, request) {
3408
+ return this.requestJson(
3409
+ "POST",
3410
+ `/v1/organizations/${organizationId}/model-providers/claude_subscription/oauth/complete`,
3411
+ request
3412
+ );
3413
+ }
3414
+ async refreshWorkspaceClaudeSubscriptionUsage(workspaceId) {
3415
+ return this.requestJson(
3416
+ "POST",
3417
+ `/v1/workspaces/${workspaceId}/model-providers/claude_subscription/usage/refresh`,
3418
+ {}
3419
+ );
3420
+ }
3421
+ async getOrganizationClaudeSubscriptionUsage(organizationId) {
3422
+ return this.requestJson(
3423
+ "GET",
3424
+ `/v1/organizations/${organizationId}/model-providers/claude_subscription/usage`
3425
+ );
3426
+ }
3427
+ async refreshOrganizationClaudeSubscriptionUsage(organizationId) {
3428
+ return this.requestJson(
3429
+ "POST",
3430
+ `/v1/organizations/${organizationId}/model-providers/claude_subscription/usage/refresh`,
3431
+ {}
3432
+ );
3433
+ }
3434
+ /** Read metadata for one organization-owned model-provider connection. */
3435
+ async getOrganizationModelProviderConnection(organizationId, providerKind) {
3436
+ return await this.requestJson(
3437
+ "GET",
3438
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}`
3439
+ );
3440
+ }
3441
+ /** Connect or rotate one organization-owned provider credential. */
3442
+ async upsertOrganizationModelProviderConnection(organizationId, providerKind, request) {
3443
+ return await this.requestJson(
3444
+ "PUT",
3445
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}`,
3446
+ request
3447
+ );
3448
+ }
3449
+ /** Revoke one organization-owned provider credential. */
3450
+ async revokeOrganizationModelProviderConnection(organizationId, providerKind, request) {
3451
+ return await this.requestJson(
3452
+ "DELETE",
3453
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}`,
3454
+ request
3455
+ );
3456
+ }
3457
+ /** List workspace-owned Claude model slugs. */
3458
+ async listWorkspaceClaudeCustomModels(workspaceId, providerKind) {
3459
+ return await this.requestJson(
3460
+ "GET",
3461
+ `/v1/workspaces/${workspaceId}/model-providers/${providerKind}/custom-models`
3462
+ );
3463
+ }
3464
+ /** Add an immutable workspace-owned Claude model generation. */
3465
+ async createWorkspaceClaudeCustomModel(workspaceId, providerKind, request) {
3466
+ return await this.requestJson(
3467
+ "POST",
3468
+ `/v1/workspaces/${workspaceId}/model-providers/${providerKind}/custom-models`,
3469
+ request
3470
+ );
3471
+ }
3472
+ /** Retire a workspace-owned Claude model generation. */
3473
+ async deleteWorkspaceClaudeCustomModel(workspaceId, providerKind, customModelId, request) {
3474
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(
3475
+ customModelId
3476
+ ))
3477
+ throw new TypeError("customModelId must be a UUID");
3478
+ await this.requestVoid(
3479
+ "DELETE",
3480
+ `/v1/workspaces/${workspaceId}/model-providers/${providerKind}/custom-models/${encodeURIComponent(customModelId)}`,
3481
+ request
3482
+ );
3483
+ }
3484
+ /** List organization-owned exact upstream model slugs. */
3485
+ async listOrganizationProviderCustomModels(organizationId, providerKind) {
3486
+ return await this.requestJson(
3487
+ "GET",
3488
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}/custom-models`
3489
+ );
3490
+ }
3491
+ /** Add one organization-owned exact upstream model slug. */
3492
+ async createOrganizationProviderCustomModel(organizationId, providerKind, request) {
3493
+ return await this.requestJson(
3494
+ "POST",
3495
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}/custom-models`,
3496
+ request
3497
+ );
3498
+ }
3499
+ /** Retire one organization-owned custom model. */
3500
+ async deleteOrganizationProviderCustomModel(organizationId, providerKind, customModelId, request) {
3501
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(
3502
+ customModelId
3503
+ )) {
3504
+ throw new TypeError("customModelId must be a UUID");
3505
+ }
3506
+ return await this.requestJson(
3507
+ "DELETE",
3508
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}/custom-models/${encodeURIComponent(customModelId)}`,
3509
+ request
3510
+ );
3511
+ }
3512
+ /** Read the workspace's hard provider/model allowlist. */
3513
+ async getWorkspaceModelAccessPolicy(workspaceId) {
3514
+ return await this.requestJson(
3515
+ "GET",
3516
+ `/v1/workspaces/${workspaceId}/model-policy`
3517
+ );
3518
+ }
3519
+ /** Fully replace the workspace's hard provider/model allowlist. */
3520
+ async updateWorkspaceModelAccessPolicy(workspaceId, request) {
3521
+ return await this.requestJson(
3522
+ "PUT",
3523
+ `/v1/workspaces/${workspaceId}/model-policy`,
3524
+ request
3525
+ );
3526
+ }
3527
+ /** Authenticated realtime voice models and credential readiness. */
3528
+ async getWorkspaceRealtimeModelCatalog(workspaceId, options = {}) {
3529
+ return await this.requestJson(
3530
+ "GET",
3531
+ `/v1/workspaces/${workspaceId}/realtime-model-catalog`,
3532
+ void 0,
3533
+ {},
3534
+ options
3535
+ );
3536
+ }
3537
+ /**
3538
+ * The caller's subject, grants, defaults, and optional direct API-key authority.
3539
+ * `credential.effectiveWorkspacePermissions` expands workspace admin only for
3540
+ * legacy keys; explicit policies retain exactly their selected grants. Full
3541
+ * organization keys can provision shared workspaces, external members, and
3542
+ * `asUser` sessions; user requests additionally need live membership.
3543
+ * Organization-key scope excludes Personal workspaces. Neither key kind bypasses
3544
+ * session visibility or the explicit `secrets:read` permission requirement. Credential
3545
+ * metadata is omitted for `asUser`/external actors, humans, delegated tokens,
3546
+ * other caller contexts, and older servers.
3547
+ */
3548
+ async getAccessContext() {
3549
+ return await this.requestJson("GET", "/v1/access/me");
3550
+ }
3551
+ /** Active organization memberships proven by the current managed-human session. */
3552
+ async listOrganizationMemberships() {
3553
+ return await this.requestJson(
3554
+ "GET",
3555
+ "/v1/organization-memberships"
3556
+ );
3557
+ }
3558
+ /** Bounded owner-only personal-resource authority page for one exact resource kind. */
3559
+ async listUserResourceAuthorities(workspaceId, options) {
3560
+ const query = new URLSearchParams({
3561
+ scope: "user",
3562
+ resourceKind: options.resourceKind
3563
+ });
3564
+ if (options.cursor) query.set("cursor", options.cursor);
3565
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
3566
+ return await this.requestJson(
3567
+ "GET",
3568
+ `/v1/workspaces/${workspaceId}/user-resource-authorities?${query.toString()}`
3569
+ );
3570
+ }
3571
+ /** Revoke an owner grant through the exact workspace it targets. */
3572
+ async revokeUserResourceGrant(workspaceId, grantId) {
3573
+ return await this.requestJson(
3574
+ "DELETE",
3575
+ `/v1/workspaces/${workspaceId}/user-resource-authorities/grants/${grantId}?scope=user`
3576
+ );
3577
+ }
3578
+ /** Create a new organization owned by the current managed human. */
3579
+ async createOrganization(request) {
3580
+ return await this.requestJson("POST", "/v1/organizations", request);
3581
+ }
3582
+ /** Create another organization owned by the current managed human. */
3583
+ async createAdditionalOrganization(request) {
3584
+ return await this.requestJson(
3585
+ "POST",
3586
+ "/v1/organizations/additional",
3587
+ request
3588
+ );
3589
+ }
3590
+ /** Pending and historical invitations addressed to the current managed human. */
3591
+ async listOrganizationInvitations(options = {}) {
3592
+ const query = new URLSearchParams();
3593
+ if (options.cursor) query.set("cursor", options.cursor);
3594
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
3595
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
3596
+ return await this.requestJson(
3597
+ "GET",
3598
+ `/v1/organization-invitations${suffix}`
3599
+ );
3600
+ }
3601
+ /** Admin-only deterministic page of invitations for one organization. */
3602
+ async listOrganizationInvitationsForOrganization(organizationId, options = {}) {
3603
+ const query = new URLSearchParams();
3604
+ if (options.cursor) query.set("cursor", options.cursor);
3605
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
3606
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
3607
+ return await this.requestJson(
3608
+ "GET",
3609
+ `/v1/organizations/${organizationId}/invitations${suffix}`
3610
+ );
3611
+ }
3612
+ async createOrganizationInvitation(organizationId, request) {
3613
+ return await this.requestJson(
3614
+ "POST",
3615
+ `/v1/organizations/${organizationId}/invitations`,
3616
+ request
3617
+ );
3618
+ }
3619
+ async acceptOrganizationInvitation(invitationId, request) {
3620
+ return await this.requestJson(
3621
+ "POST",
3622
+ `/v1/organization-invitations/${invitationId}/accept`,
3623
+ request
3624
+ );
3625
+ }
3626
+ async revokeOrganizationInvitation(organizationId, invitationId, request) {
3627
+ return await this.requestJson(
3628
+ "POST",
3629
+ `/v1/organizations/${organizationId}/invitations/${invitationId}/revoke`,
3630
+ request
3631
+ );
3632
+ }
3633
+ async listOrganizationAdministrationMembers(organizationId) {
3634
+ return await this.requestJson(
3635
+ "GET",
3636
+ `/v1/organizations/${organizationId}/members`
3637
+ );
3638
+ }
3639
+ /** @deprecated Use listOrganizationAdministrationMembers for its privacy-safe projection. */
3640
+ async listOrganizationMembers(organizationId) {
3641
+ return await this.listOrganizationAdministrationMembers(organizationId);
3642
+ }
3643
+ /** Canonical organization identity and every non-personal workspace access roster. */
3644
+ async getOrganizationAdministrationOverview(organizationId) {
3645
+ return await this.requestJson(
3646
+ "GET",
3647
+ `/v1/organizations/${organizationId}/overview`
3648
+ );
3649
+ }
3650
+ /** Create a shared workspace and grant its creator explicit workspace-admin access. */
3651
+ async createOrganizationWorkspace(organizationId, request) {
3652
+ return await this.requestJson(
3653
+ "POST",
3654
+ `/v1/organizations/${organizationId}/workspaces`,
3655
+ request
3656
+ );
3657
+ }
3658
+ /** Rename one shared workspace under an exact optimistic-concurrency fence. */
3659
+ async updateOrganizationWorkspace(organizationId, workspaceId, request) {
3660
+ return await this.requestJson(
3661
+ "PATCH",
3662
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}`,
3663
+ request
3664
+ );
3665
+ }
3666
+ async updateOrganizationWorkspaceSettings(organizationId, workspaceId, request) {
3667
+ return await this.requestJson(
3668
+ "PATCH",
3669
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}/settings`,
3670
+ request
3671
+ );
3672
+ }
3673
+ /**
3674
+ * Delete an organization (shared) workspace. Accepts an organization owner
3675
+ * session or an organization API key with `workspace:admin` (for tenant
3676
+ * offboarding); never deletes a Personal workspace. 409 until quiescent.
3677
+ */
3678
+ async deleteOrganizationWorkspace(organizationId, workspaceId) {
3679
+ await this.requestVoid(
3680
+ "DELETE",
3681
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}`
3682
+ );
3683
+ }
3684
+ async putOrganizationWorkspaceMember(organizationId, workspaceId, membershipId, request) {
3685
+ return await this.requestJson(
3686
+ "PUT",
3687
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}/members/${membershipId}`,
3688
+ request
3689
+ );
3690
+ }
3691
+ async revokeOrganizationWorkspaceMember(organizationId, workspaceId, membershipId, request) {
3692
+ return await this.requestJson(
3693
+ "POST",
3694
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}/members/${membershipId}/revoke`,
3695
+ request
3696
+ );
3697
+ }
3698
+ /** Rename the organization under an exact optimistic-concurrency fence. */
3699
+ async updateOrganizationName(organizationId, request) {
3700
+ return await this.requestJson(
3701
+ "PATCH",
3702
+ `/v1/organizations/${organizationId}`,
3703
+ request
3704
+ );
3705
+ }
3706
+ async updateOrganizationMember(organizationId, membershipId, request) {
3707
+ return await this.requestJson(
3708
+ "PATCH",
3709
+ `/v1/organizations/${organizationId}/members/${membershipId}`,
3710
+ request
3711
+ );
3712
+ }
3713
+ async getOrganizationRetentionPolicy(organizationId) {
3714
+ return await this.requestJson(
3715
+ "GET",
3716
+ `/v1/organizations/${organizationId}/retention-policy`
3717
+ );
3718
+ }
3719
+ async updateOrganizationRetentionPolicy(organizationId, request) {
3720
+ return await this.requestJson(
3721
+ "PATCH",
3722
+ `/v1/organizations/${organizationId}/retention-policy`,
3723
+ request
3724
+ );
3725
+ }
3726
+ async getOrganizationRecovery(organizationId) {
3727
+ return await this.requestJson(
3728
+ "GET",
3729
+ `/v1/organizations/${organizationId}/recovery`
3730
+ );
3731
+ }
3732
+ async configureOrganizationRecoveryPolicy(organizationId, request) {
3733
+ return await this.requestJson(
3734
+ "PUT",
3735
+ `/v1/organizations/${organizationId}/recovery/policy`,
3736
+ request
3737
+ );
3738
+ }
3739
+ async acceptOrganizationRecoveryCustody(organizationId, request) {
3740
+ return await this.requestJson(
3741
+ "POST",
3742
+ `/v1/organizations/${organizationId}/recovery/policy/accept`,
3743
+ request
3744
+ );
3745
+ }
3746
+ async disableOrganizationRecoveryPolicy(organizationId, request) {
3747
+ return await this.requestJson(
3748
+ "POST",
3749
+ `/v1/organizations/${organizationId}/recovery/policy/disable`,
3750
+ request
3751
+ );
3752
+ }
3753
+ async startOrganizationRecoveryOperation(organizationId, request) {
3754
+ return await this.requestJson(
3755
+ "POST",
3756
+ `/v1/organizations/${organizationId}/recovery/operations`,
3757
+ request
3758
+ );
3759
+ }
3760
+ async approveOrganizationRecoveryOperation(organizationId, recoveryOperationId, request) {
3761
+ return await this.requestJson(
3762
+ "POST",
3763
+ `/v1/organizations/${organizationId}/recovery/operations/${recoveryOperationId}/approve`,
3764
+ request
3765
+ );
3766
+ }
3767
+ async cancelOrganizationRecoveryOperation(organizationId, recoveryOperationId, request) {
3768
+ return await this.requestJson(
3769
+ "POST",
3770
+ `/v1/organizations/${organizationId}/recovery/operations/${recoveryOperationId}/cancel`,
3771
+ request
3772
+ );
3773
+ }
3774
+ async executeOrganizationRecoveryOperation(organizationId, recoveryOperationId, request) {
3775
+ return await this.requestJson(
3776
+ "POST",
3777
+ `/v1/organizations/${organizationId}/recovery/operations/${recoveryOperationId}/execute`,
3778
+ request
3779
+ );
3780
+ }
3781
+ async searchPublicSkills(workspaceId, query) {
3782
+ return this.requestJson(
3783
+ "GET",
3784
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/skills/search?q=${encodeURIComponent(query)}`
3785
+ );
3786
+ }
3787
+ async listWorkspaces() {
3788
+ return await this.requestJson("GET", "/v1/workspaces");
3789
+ }
3790
+ /** Uses this client's fixed actor and standard contract/error/abort handling.
3791
+ * Disconnect revokes OpenGeni connection access, not upstream provider consent. */
3792
+ connectTransport() {
3793
+ const root = (workspaceId) => `/v1/workspaces/${encodeURIComponent(workspaceId)}/connect`;
3794
+ return {
3795
+ catalog: (workspaceId, options) => this.requestJson("GET", `${root(workspaceId)}/catalog`, void 0, void 0, options),
3796
+ accounts: (workspaceId, options) => this.requestJson("GET", `${root(workspaceId)}/accounts`, void 0, void 0, options),
3797
+ pending: (workspaceId, options) => this.requestJson("GET", `${root(workspaceId)}/attempts`, void 0, void 0, options),
3798
+ begin: (workspaceId, input, options) => this.requestJson("POST", `${root(workspaceId)}/attempts`, input, void 0, options),
3799
+ get: (workspaceId, id, options) => this.requestJson(
3800
+ "GET",
3801
+ `${root(workspaceId)}/attempts/${encodeURIComponent(id)}`,
3802
+ void 0,
3803
+ void 0,
3804
+ options
3805
+ ),
3806
+ advance: (workspaceId, id, input, options) => this.requestJson(
3807
+ "POST",
3808
+ `${root(workspaceId)}/attempts/${encodeURIComponent(id)}/advance`,
3809
+ input,
3810
+ void 0,
3811
+ options
3812
+ ),
3813
+ cancel: (workspaceId, id, input, options) => this.requestJson(
3814
+ "POST",
3815
+ `${root(workspaceId)}/attempts/${encodeURIComponent(id)}/cancel`,
3816
+ input,
3817
+ void 0,
3818
+ options
3819
+ ),
3820
+ disconnect: async (workspaceId, id, options) => {
3821
+ if (id.startsWith("social:")) {
3822
+ const connectionId = id.slice("social:".length);
3823
+ if (!/^[0-9a-f-]{36}$/i.test(connectionId)) throw new Error("Invalid social account ID");
3824
+ await this.disconnectSocialConnection(workspaceId, connectionId);
3825
+ return;
3826
+ }
3827
+ if (id.startsWith("lens-registration:")) {
3828
+ const registrationId = id.slice("lens-registration:".length);
3829
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(registrationId))
3830
+ throw new Error("Invalid Lens registration ID");
3831
+ await this.requestJson(
3832
+ "DELETE",
3833
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/pr-review/registrations/${registrationId}`,
3834
+ void 0,
3835
+ void 0,
3836
+ options
3837
+ );
3838
+ return;
3839
+ }
3840
+ if (id.startsWith("github-installation:")) {
3841
+ const installationId = id.slice("github-installation:".length);
3842
+ if (!/^[1-9][0-9]*$/.test(installationId) || !Number.isSafeInteger(Number(installationId)))
3843
+ throw new Error("Invalid GitHub installation ID");
3844
+ await this.requestJson(
3845
+ "DELETE",
3846
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/github/installations/${installationId}`,
3847
+ void 0,
3848
+ void 0,
3849
+ options
3850
+ );
3851
+ return;
3852
+ }
3853
+ const expectedVersion = options?.expectedVersion;
3854
+ if (expectedVersion !== void 0 && (!Number.isSafeInteger(expectedVersion) || expectedVersion < 1)) {
3855
+ throw new Error("invalid expected connection version");
3856
+ }
3857
+ const query = expectedVersion === void 0 ? "" : `?expectedVersion=${expectedVersion}`;
3858
+ await this.requestJson(
3859
+ "DELETE",
3860
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/connections/${encodeURIComponent(id)}${query}`,
3861
+ void 0,
3862
+ void 0,
3863
+ options
3864
+ );
3865
+ }
3866
+ };
3867
+ }
3868
+ /** Browse first-party Atlassian sources without choosing or starting sync. */
3869
+ async browseAtlassianSources(workspaceId, connectionId) {
3870
+ return this.requestJson(
3871
+ "GET",
3872
+ `/v1/workspaces/${workspaceId}/connections/atlassian/${connectionId}/browse`
3873
+ );
3874
+ }
3875
+ async saveAtlassianSources(workspaceId, connectionId, request) {
3876
+ return this.requestJson(
3877
+ "POST",
3878
+ `/v1/workspaces/${workspaceId}/connections/atlassian/${connectionId}/source`,
3879
+ request
3880
+ );
3881
+ }
3882
+ async setAtlassianLifecycle(workspaceId, connectionId, request) {
3883
+ return this.requestJson(
3884
+ "PATCH",
3885
+ `/v1/workspaces/${workspaceId}/connections/atlassian/${connectionId}/lifecycle`,
3886
+ request
3887
+ );
3888
+ }
3889
+ /** Begin durable setup. Completion requirements are provider-specific. */
3890
+ async beginConnect(workspaceId, request) {
3891
+ return this.requestJson("POST", `/v1/workspaces/${workspaceId}/connect/attempts`, request);
2621
3892
  }
2622
3893
  async createWorkspace(request) {
2623
3894
  return await this.requestJson("POST", "/v1/workspaces", request);
2624
3895
  }
3896
+ /**
3897
+ * Create an organization workspace once for a stable external tenant
3898
+ * identity, or return the existing workspace without overwriting it.
3899
+ */
3900
+ async ensureWorkspace(request) {
3901
+ return await this.requestJson(
3902
+ "PUT",
3903
+ "/v1/workspaces/external",
3904
+ request
3905
+ );
3906
+ }
2625
3907
  async getWorkspace(workspaceId) {
2626
3908
  return await this.requestJson("GET", `/v1/workspaces/${workspaceId}`);
2627
3909
  }
@@ -2660,8 +3942,25 @@ var OpenGeniClient = class {
2660
3942
  if (options.limit !== void 0) params.set("limit", String(options.limit));
2661
3943
  const query = params.toString();
2662
3944
  return await this.requestJson(
2663
- "GET",
2664
- `/v1/workspaces/${workspaceId}/instruction-policies${query ? `?${query}` : ""}`
3945
+ "GET",
3946
+ `/v1/workspaces/${workspaceId}/instruction-policies${query ? `?${query}` : ""}`
3947
+ );
3948
+ }
3949
+ /** Inspect the bounded, permission-filtered governed-learning timeline. */
3950
+ async getWorkspaceLearningHistory(workspaceId, options = {}) {
3951
+ const params = new URLSearchParams();
3952
+ if (options.limit !== void 0) params.set("limit", String(options.limit));
3953
+ const query = params.toString();
3954
+ return await this.requestJson(
3955
+ "GET",
3956
+ `/v1/workspaces/${workspaceId}/learning${query ? `?${query}` : ""}`
3957
+ );
3958
+ }
3959
+ async undoGovernedLearningActivation(workspaceId, activationReceiptId, request = {}) {
3960
+ return await this.requestJson(
3961
+ "POST",
3962
+ `/v1/workspaces/${workspaceId}/learning/activations/${encodeURIComponent(activationReceiptId)}/undo`,
3963
+ request
2665
3964
  );
2666
3965
  }
2667
3966
  async getWorkspaceInstructionPolicyRevision(workspaceId, revisionId) {
@@ -2670,11 +3969,12 @@ var OpenGeniClient = class {
2670
3969
  `/v1/workspaces/${workspaceId}/instruction-policies/${encodeURIComponent(revisionId)}`
2671
3970
  );
2672
3971
  }
2673
- async createWorkspaceInstructionPolicyDraft(workspaceId, request) {
2674
- return await this.requestJson(
3972
+ async createWorkspaceInstructionPolicyDraft(workspaceId, request, options = {}) {
3973
+ return await this.requestSessionCommand(
2675
3974
  "POST",
2676
3975
  `/v1/workspaces/${workspaceId}/instruction-policies/drafts`,
2677
- request
3976
+ request,
3977
+ options
2678
3978
  );
2679
3979
  }
2680
3980
  /** List the newest immutable onboarding proposals and their inactive policy drafts. */
@@ -2713,11 +4013,12 @@ var OpenGeniClient = class {
2713
4013
  `/v1/workspaces/${workspaceId}/instruction-policies/diff?${params}`
2714
4014
  );
2715
4015
  }
2716
- async activateWorkspaceInstructionPolicyRevision(workspaceId, revisionId, request) {
2717
- return await this.requestJson(
4016
+ async activateWorkspaceInstructionPolicyRevision(workspaceId, revisionId, request, options = {}) {
4017
+ return await this.requestSessionCommand(
2718
4018
  "POST",
2719
4019
  `/v1/workspaces/${workspaceId}/instruction-policies/${encodeURIComponent(revisionId)}/activate`,
2720
- request
4020
+ request,
4021
+ options
2721
4022
  );
2722
4023
  }
2723
4024
  async rollbackWorkspaceInstructionPolicyRevision(workspaceId, request) {
@@ -2745,6 +4046,19 @@ var OpenGeniClient = class {
2745
4046
  `/v1/workspaces/${workspaceId}/company-profile/revisions/${encodeURIComponent(revisionId)}`
2746
4047
  );
2747
4048
  }
4049
+ async getCompanyProfileAgentPolicy(workspaceId) {
4050
+ return await this.requestJson(
4051
+ "GET",
4052
+ `/v1/workspaces/${workspaceId}/company-profile/agent-policy`
4053
+ );
4054
+ }
4055
+ async updateCompanyProfileAgentPolicy(workspaceId, request) {
4056
+ return await this.requestJson(
4057
+ "PATCH",
4058
+ `/v1/workspaces/${workspaceId}/company-profile/agent-policy`,
4059
+ request
4060
+ );
4061
+ }
2748
4062
  async updateCompanyProfile(workspaceId, request) {
2749
4063
  return await this.requestJson(
2750
4064
  "PUT",
@@ -2868,9 +4182,16 @@ var OpenGeniClient = class {
2868
4182
  );
2869
4183
  return response.members;
2870
4184
  }
4185
+ /** Active organization members who can be added to this workspace. */
4186
+ async listWorkspaceMemberCandidates(workspaceId) {
4187
+ const response = await this.requestJson(
4188
+ "GET",
4189
+ `/v1/workspaces/${workspaceId}/member-candidates`
4190
+ );
4191
+ return response.members;
4192
+ }
2871
4193
  /**
2872
- * Add an already-registered user by email. 404s when no user with that email
2873
- * exists (email invites for unknown users are deferred).
4194
+ * Add one active member selected from the workspace candidate inventory.
2874
4195
  */
2875
4196
  async addWorkspaceMember(workspaceId, request) {
2876
4197
  return await this.requestJson(
@@ -2950,14 +4271,14 @@ var OpenGeniClient = class {
2950
4271
  return await this.requestJson(
2951
4272
  "POST",
2952
4273
  `/v1/workspaces/${workspaceId}/scheduled-tasks`,
2953
- request
4274
+ normalizeScheduledTaskMachineTarget(request)
2954
4275
  );
2955
4276
  }
2956
4277
  async updateScheduledTask(workspaceId, taskId, request) {
2957
4278
  return await this.requestJson(
2958
4279
  "PATCH",
2959
4280
  `/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}`,
2960
- request
4281
+ normalizeScheduledTaskMachineTarget(request)
2961
4282
  );
2962
4283
  }
2963
4284
  async pauseScheduledTask(workspaceId, taskId) {
@@ -3000,6 +4321,23 @@ var OpenGeniClient = class {
3000
4321
  }
3001
4322
  );
3002
4323
  }
4324
+ /**
4325
+ * Re-freeze a task's connectors, connector accounts and OpenGeni tool policy
4326
+ * with the signed-in caller's current authority. Pass the `executionDigest`
4327
+ * of the task whose `policyDrift` was reviewed; a changed task returns 409.
4328
+ */
4329
+ async refreshScheduledTaskAccess(workspaceId, taskId, request) {
4330
+ return await this.requestJson(
4331
+ "POST",
4332
+ `/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}/refresh-access`,
4333
+ request
4334
+ );
4335
+ }
4336
+ /** Schedules the caller can act on whose latest run could not use a connector. */
4337
+ async listScheduledTaskAccessAttention(workspaceId) {
4338
+ const response = await this.requestJson("GET", `/v1/workspaces/${workspaceId}/scheduled-tasks/attention`);
4339
+ return response.tasks;
4340
+ }
3003
4341
  // --- VariableSets --------------------------------------------------------------
3004
4342
  // Generic reads return name/version metadata only. Plaintext uses one
3005
4343
  // dedicated permissioned endpoint.
@@ -3009,6 +4347,14 @@ var OpenGeniClient = class {
3009
4347
  `/v1/workspaces/${workspaceId}/variable-sets`
3010
4348
  );
3011
4349
  }
4350
+ /** Resolve only caller-supplied attachment ids without enumerating the catalog. */
4351
+ async resolveVariableSetAttachments(workspaceId, request) {
4352
+ return await this.requestJson(
4353
+ "POST",
4354
+ `/v1/workspaces/${workspaceId}/variable-sets/resolve-attachments`,
4355
+ request
4356
+ );
4357
+ }
3012
4358
  async createVariableSet(workspaceId, request) {
3013
4359
  return await this.requestJson(
3014
4360
  "POST",
@@ -3076,6 +4422,13 @@ var OpenGeniClient = class {
3076
4422
  request
3077
4423
  );
3078
4424
  }
4425
+ async reorderChannels(workspaceId, request) {
4426
+ return await this.requestJson(
4427
+ "PUT",
4428
+ `/v1/workspaces/${workspaceId}/channels/order`,
4429
+ request
4430
+ );
4431
+ }
3079
4432
  async deleteChannel(workspaceId, channelId) {
3080
4433
  await this.requestJson(
3081
4434
  "DELETE",
@@ -3086,7 +4439,7 @@ var OpenGeniClient = class {
3086
4439
  async updateSessionChannel(workspaceId, sessionId, request) {
3087
4440
  return await this.requestJson(
3088
4441
  "PUT",
3089
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/channel`,
4442
+ `${sessionPath(workspaceId, sessionId)}/channel`,
3090
4443
  request
3091
4444
  );
3092
4445
  }
@@ -3237,6 +4590,7 @@ var OpenGeniClient = class {
3237
4590
  if (input.timeoutMs !== void 0 && (!Number.isFinite(input.timeoutMs) || input.timeoutMs <= 0)) {
3238
4591
  throw new Error("File upload timeout must be a positive number");
3239
4592
  }
4593
+ assertBrowserFileUploadSecureContext();
3240
4594
  const withTimeout = async (timeoutMs, operation) => {
3241
4595
  const controller = new AbortController();
3242
4596
  let timeout;
@@ -3262,6 +4616,7 @@ var OpenGeniClient = class {
3262
4616
  {
3263
4617
  filename: input.filename,
3264
4618
  contentType: input.contentType,
4619
+ ...input.scope ? { scope: input.scope } : {},
3265
4620
  sizeBytes,
3266
4621
  sha256
3267
4622
  },
@@ -3297,10 +4652,23 @@ var OpenGeniClient = class {
3297
4652
  async (signal) => await this.completeFileUpload(workspaceId, upload.uploadId, { signal })
3298
4653
  );
3299
4654
  }
3300
- async getFile(workspaceId, fileId) {
4655
+ async listFiles(workspaceId, options = {}) {
4656
+ const query = new URLSearchParams();
4657
+ if (options.scope) query.set("scope", options.scope);
4658
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
4659
+ if (options.cursor) query.set("cursor", options.cursor);
4660
+ return this.requestJson(
4661
+ "GET",
4662
+ `/v1/workspaces/${workspaceId}/files${query.size ? `?${query}` : ""}`
4663
+ );
4664
+ }
4665
+ async getFile(workspaceId, fileId, options = {}) {
3301
4666
  return await this.requestJson(
3302
4667
  "GET",
3303
- `/v1/workspaces/${workspaceId}/files/${fileId}`
4668
+ `/v1/workspaces/${workspaceId}/files/${fileId}${options.sessionId ? `?sessionId=${encodeURIComponent(options.sessionId)}` : ""}`,
4669
+ void 0,
4670
+ {},
4671
+ options
3304
4672
  );
3305
4673
  }
3306
4674
  /** Read provider-neutral retained evidence metadata; never returns a storage location. */
@@ -3323,24 +4691,24 @@ var OpenGeniClient = class {
3323
4691
  async getSessionRetainedArtifact(workspaceId, sessionId, artifactId) {
3324
4692
  return await this.requestJson(
3325
4693
  "GET",
3326
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/artifacts/${artifactId}`
4694
+ `${sessionPath(workspaceId, sessionId)}/artifacts/${artifactId}`
3327
4695
  );
3328
4696
  }
3329
4697
  async getSessionRetainedArtifactContent(workspaceId, sessionId, artifactId, options = {}) {
3330
4698
  return await this.getRetainedArtifactContentAtPath(
3331
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/artifacts/${artifactId}/content`,
4699
+ `${sessionPath(workspaceId, sessionId)}/artifacts/${artifactId}/content`,
3332
4700
  options
3333
4701
  );
3334
4702
  }
3335
- /** Assemble one permanent generated-image receipt from bounded authenticated ranges. */
4703
+ /** Assemble one permanent image or file artifact from bounded authenticated ranges. */
3336
4704
  async downloadRetainedArtifact(workspaceId, artifact, options = {}) {
3337
- assertRetainedGeneratedImageReceipt(workspaceId, artifact);
4705
+ assertRetainedWorkspaceArtifactReceipt(workspaceId, artifact);
3338
4706
  const bytes = await this.downloadRetainedArtifactBytes(artifact, options);
3339
4707
  return { artifact, bytes };
3340
4708
  }
3341
- /** Mint a short-lived, zero-copy browser source for a validated generated image. */
4709
+ /** Mint a short-lived, zero-copy browser source for a validated workspace artifact. */
3342
4710
  async createRetainedArtifactDownloadUrl(workspaceId, artifact, options = {}) {
3343
- assertRetainedGeneratedImageReceipt(workspaceId, artifact);
4711
+ assertRetainedWorkspaceArtifactReceipt(workspaceId, artifact);
3344
4712
  const download = await this.createFileDownloadUrl(workspaceId, artifact.artifactId, options);
3345
4713
  assertSafeArtifactDownloadUrl(download);
3346
4714
  return download;
@@ -3349,7 +4717,8 @@ var OpenGeniClient = class {
3349
4717
  async downloadRetainedScreenshot(workspaceId, sessionId, artifactId, options = {}) {
3350
4718
  const metadata = await this.getSessionRetainedArtifact(workspaceId, sessionId, artifactId);
3351
4719
  if (!metadata.available) return { metadata, bytes: null };
3352
- if (metadata.kind !== "computer_screenshot" || metadata.contentType !== "image/png" || !metadata.dimensions || metadata.originalBytes <= 0 || metadata.originalBytes > COMPUTER_SCREENSHOT_MAX_BYTES) {
4720
+ const supportedScreenshot = (metadata.kind === "computer_screenshot" || metadata.kind === "browser_screenshot") && ["image/png", "image/jpeg", "image/webp"].includes(metadata.contentType);
4721
+ if (!supportedScreenshot || !metadata.dimensions || metadata.originalBytes <= 0 || metadata.originalBytes > COMPUTER_SCREENSHOT_MAX_BYTES) {
3353
4722
  throw new OpenGeniApiError(502, "retained screenshot metadata is invalid");
3354
4723
  }
3355
4724
  const bytes = await this.downloadRetainedArtifactBytes(metadata, options);
@@ -3410,7 +4779,7 @@ var OpenGeniClient = class {
3410
4779
  ...options.signal ? { signal: options.signal } : {}
3411
4780
  });
3412
4781
  try {
3413
- assertApiContractResponse(response);
4782
+ assertApiContractResponse(response, this.apiContractStrict);
3414
4783
  } catch (error) {
3415
4784
  await cancelResponseBody(response, "retained artifact API contract mismatch");
3416
4785
  throw error;
@@ -3454,7 +4823,7 @@ var OpenGeniClient = class {
3454
4823
  async createFileDownloadUrl(workspaceId, fileId, options = {}) {
3455
4824
  return await this.requestJson(
3456
4825
  "POST",
3457
- `/v1/workspaces/${workspaceId}/files/${fileId}/download-url`,
4826
+ `/v1/workspaces/${workspaceId}/files/${fileId}/download-url${options.sessionId ? `?sessionId=${encodeURIComponent(options.sessionId)}` : ""}`,
3458
4827
  void 0,
3459
4828
  {},
3460
4829
  options
@@ -3511,12 +4880,6 @@ var OpenGeniClient = class {
3511
4880
  request
3512
4881
  );
3513
4882
  }
3514
- async listDocumentBases(workspaceId) {
3515
- return await this.requestJson(
3516
- "GET",
3517
- `/v1/workspaces/${workspaceId}/document-bases`
3518
- );
3519
- }
3520
4883
  async getDocumentBase(workspaceId, baseId) {
3521
4884
  return await this.requestJson(
3522
4885
  "GET",
@@ -3537,6 +4900,13 @@ var OpenGeniClient = class {
3537
4900
  `/v1/workspaces/${workspaceId}/document-bases/${baseId}/documents`
3538
4901
  );
3539
4902
  }
4903
+ /** Read the immutable source file through the Document's effective authority. */
4904
+ async getDocumentOriginalFile(workspaceId, documentId) {
4905
+ return await this.requestJson(
4906
+ "GET",
4907
+ `/v1/workspaces/${workspaceId}/documents/${documentId}/original-file`
4908
+ );
4909
+ }
3540
4910
  /**
3541
4911
  * Drop raw text or an already-uploaded file into the workspace's Default
3542
4912
  * base. When curation is enabled, it may name, summarize, categorize, and
@@ -3561,13 +4931,6 @@ var OpenGeniClient = class {
3561
4931
  request
3562
4932
  );
3563
4933
  }
3564
- /** Retry indexing for a failed document. */
3565
- async reindexDocument(workspaceId, baseId, documentId) {
3566
- return await this.requestJson(
3567
- "POST",
3568
- `/v1/workspaces/${workspaceId}/document-bases/${baseId}/documents/${documentId}/reindex`
3569
- );
3570
- }
3571
4934
  /**
3572
4935
  * Delete a document from a base. Removes the document row and its indexed
3573
4936
  * chunks while leaving the uploaded file asset available for other uses.
@@ -3578,61 +4941,109 @@ var OpenGeniClient = class {
3578
4941
  `/v1/workspaces/${workspaceId}/document-bases/${baseId}/documents/${documentId}`
3579
4942
  );
3580
4943
  }
3581
- async searchDocuments(workspaceId, baseId, request) {
3582
- return await this.requestJson(
4944
+ /** Unified retained sources, findings and groups. Only published entries are returned by default. */
4945
+ async listKnowledgeEntries(workspaceId, request = {}) {
4946
+ return this.requestJson(
3583
4947
  "POST",
3584
- `/v1/workspaces/${workspaceId}/document-bases/${baseId}/search`,
4948
+ `/v1/workspaces/${workspaceId}/knowledge/entries/search`,
3585
4949
  request
3586
4950
  );
3587
4951
  }
3588
- async searchKnowledge(workspaceId, request) {
3589
- return await this.requestJson(
4952
+ async getKnowledgeEntry(workspaceId, entryId, options = {}) {
4953
+ const search = new URLSearchParams();
4954
+ if (options.revisionId !== void 0) search.set("revisionId", options.revisionId);
4955
+ if (options.view !== void 0) search.set("view", options.view);
4956
+ const query = search.toString();
4957
+ return this.requestJson(
4958
+ "GET",
4959
+ `/v1/workspaces/${workspaceId}/knowledge/entries/${entryId}${query ? `?${query}` : ""}`
4960
+ );
4961
+ }
4962
+ /** Open the original file associated with an accessible retained source revision. */
4963
+ async createKnowledgeFileDownloadUrl(workspaceId, entryId, revisionId) {
4964
+ return this.requestJson(
3590
4965
  "POST",
3591
- `/v1/workspaces/${workspaceId}/knowledge/search`,
3592
- request
4966
+ `/v1/workspaces/${workspaceId}/knowledge/entries/${entryId}/file/download-url`,
4967
+ revisionId ? { revisionId } : {}
3593
4968
  );
3594
4969
  }
3595
- async listKnowledgeMemories(workspaceId, request = {}) {
3596
- const params = new URLSearchParams();
3597
- if (request.query) params.set("query", request.query);
3598
- if (request.status) params.set("status", request.status);
3599
- if (request.kind) params.set("kind", request.kind);
3600
- if (request.scope) params.set("scope", request.scope);
3601
- if (request.limit) params.set("limit", String(request.limit));
3602
- const query = params.toString();
3603
- return await this.requestJson(
3604
- "GET",
3605
- `/v1/workspaces/${workspaceId}/knowledge/memories${query ? `?${query}` : ""}`
4970
+ async saveKnowledgeEntry(workspaceId, request) {
4971
+ return this.requestJson("POST", `/v1/workspaces/${workspaceId}/knowledge/entries`, request);
4972
+ }
4973
+ async reviewKnowledgeEntry(workspaceId, request) {
4974
+ const { entryId, ...body } = request;
4975
+ return this.requestJson(
4976
+ "POST",
4977
+ `/v1/workspaces/${workspaceId}/knowledge/entries/${entryId}/review`,
4978
+ body
3606
4979
  );
3607
4980
  }
3608
- async getKnowledgeMemory(workspaceId, memoryId) {
3609
- return await this.requestJson(
4981
+ async listKnowledgeReviewBatches(workspaceId, options = {}) {
4982
+ const query = new URLSearchParams();
4983
+ for (const [key, value] of Object.entries(options))
4984
+ if (value !== void 0) query.set(key, String(value));
4985
+ return this.requestJson(
3610
4986
  "GET",
3611
- `/v1/workspaces/${workspaceId}/knowledge/memories/${memoryId}`
4987
+ `/v1/workspaces/${workspaceId}/knowledge/review-groups?${query}`
3612
4988
  );
3613
4989
  }
3614
- async createKnowledgeMemory(workspaceId, request) {
3615
- return await this.requestJson(
4990
+ /** Atomically review up to 100 selected entries, including their pending dependencies. */
4991
+ async reviewKnowledgeEntries(workspaceId, request) {
4992
+ return this.requestJson(
3616
4993
  "POST",
3617
- `/v1/workspaces/${workspaceId}/knowledge/memories`,
4994
+ `/v1/workspaces/${workspaceId}/knowledge/entries/review`,
3618
4995
  request
3619
4996
  );
3620
4997
  }
3621
- async updateKnowledgeMemory(workspaceId, memoryId, request) {
3622
- return await this.requestJson(
3623
- "PATCH",
3624
- `/v1/workspaces/${workspaceId}/knowledge/memories/${memoryId}`,
4998
+ async listKnowledgeEntryHistory(workspaceId, entryId, beforeRevision) {
4999
+ return this.requestJson(
5000
+ "GET",
5001
+ `/v1/workspaces/${workspaceId}/knowledge/entries/${entryId}/history${beforeRevision ? `?beforeRevision=${beforeRevision}` : ""}`
5002
+ );
5003
+ }
5004
+ async restoreKnowledgeEntry(workspaceId, request) {
5005
+ const { entryId, ...body } = request;
5006
+ return this.requestJson(
5007
+ "POST",
5008
+ `/v1/workspaces/${workspaceId}/knowledge/entries/${entryId}/restore`,
5009
+ body
5010
+ );
5011
+ }
5012
+ async archiveKnowledgeEntry(workspaceId, entryId, request) {
5013
+ return this.requestJson(
5014
+ "POST",
5015
+ `/v1/workspaces/${workspaceId}/knowledge/entries/${entryId}/archive`,
3625
5016
  request
3626
5017
  );
3627
5018
  }
3628
- /** Hybrid (semantic + keyword) search over the workspace's agent-visible memory. */
3629
- async searchWorkspaceMemories(workspaceId, request) {
3630
- return await this.requestJson(
5019
+ async getAgentLearningSettings(workspaceId, scope, source) {
5020
+ return this.requestJson("POST", `/v1/workspaces/${workspaceId}/agent-learning/read`, {
5021
+ scope,
5022
+ source
5023
+ });
5024
+ }
5025
+ async saveAgentLearningSettings(workspaceId, request) {
5026
+ return this.requestJson("POST", `/v1/workspaces/${workspaceId}/agent-learning`, request);
5027
+ }
5028
+ async listAgentLearningOverrides(workspaceId, scope) {
5029
+ return this.requestJson(
5030
+ "GET",
5031
+ `/v1/workspaces/${workspaceId}/agent-learning/overrides?scope=${scope}`
5032
+ );
5033
+ }
5034
+ async reviewAgentInstruction(workspaceId, request) {
5035
+ return this.requestJson(
3631
5036
  "POST",
3632
- `/v1/workspaces/${workspaceId}/knowledge/memories/search`,
5037
+ `/v1/workspaces/${workspaceId}/agent-learning/instructions/review`,
3633
5038
  request
3634
5039
  );
3635
5040
  }
5041
+ async listAgentInstructionReviews(workspaceId, cursor) {
5042
+ return this.requestJson(
5043
+ "GET",
5044
+ `/v1/workspaces/${workspaceId}/agent-learning/instructions/reviews${cursor ? `?cursor=${encodeURIComponent(cursor)}` : ""}`
5045
+ );
5046
+ }
3636
5047
  /** Deep-merge a settings patch into the workspace (preserves unknown keys). */
3637
5048
  async updateWorkspaceSettings(workspaceId, request) {
3638
5049
  return await this.requestJson(
@@ -3648,102 +5059,126 @@ var OpenGeniClient = class {
3648
5059
  request
3649
5060
  );
3650
5061
  }
3651
- // --- Capability packs ------------------------------------------------------------------
3652
- /** Built-in + registered packs, with the workspace's installations. */
3653
- async listPacks(workspaceId) {
3654
- return await this.requestJson("GET", `/v1/workspaces/${workspaceId}/packs`);
5062
+ /** Resolve pinned components, Variable Set, and Rig requirements before installation. */
5063
+ // --- Capabilities -------------------------------------------------------------------------
5064
+ async listCapabilities(workspaceId) {
5065
+ return await this.requestJson(
5066
+ "GET",
5067
+ `/v1/workspaces/${workspaceId}/capabilities`
5068
+ );
3655
5069
  }
3656
- /** Register (or replace) a workspace-scoped pack from a manifest. */
3657
- async registerPack(workspaceId, manifest) {
5070
+ /** Add a manual capability catalog item (e.g. a remote MCP server). */
5071
+ async createCapability(workspaceId, request) {
3658
5072
  return await this.requestJson(
3659
5073
  "POST",
3660
- `/v1/workspaces/${workspaceId}/packs`,
3661
- manifest
5074
+ `/v1/workspaces/${workspaceId}/capabilities`,
5075
+ request
3662
5076
  );
3663
5077
  }
3664
- async getPack(workspaceId, packId) {
5078
+ async getConnectorToolPermissions(workspaceId, capabilityId, options = {}) {
3665
5079
  return await this.requestJson(
3666
5080
  "GET",
3667
- `/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}`
5081
+ `/v1/workspaces/${workspaceId}/capabilities/${encodeURIComponent(capabilityId)}/tool-permissions`,
5082
+ void 0,
5083
+ {},
5084
+ options
3668
5085
  );
3669
5086
  }
3670
- async enablePack(workspaceId, packId, request = {}) {
5087
+ async updateConnectorToolPermissions(workspaceId, capabilityId, request, options = {}) {
3671
5088
  return await this.requestJson(
3672
- "POST",
3673
- `/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}/enable`,
3674
- request
5089
+ "PATCH",
5090
+ `/v1/workspaces/${workspaceId}/capabilities/${encodeURIComponent(capabilityId)}/tool-permissions`,
5091
+ request,
5092
+ {},
5093
+ options
3675
5094
  );
3676
5095
  }
3677
- /** Resolve pinned components, Variable Set, and Rig requirements before installation. */
3678
- async previewPackInstallation(workspaceId, packId, request = {}) {
5096
+ async enableCapability(workspaceId, capabilityId, request = {}) {
3679
5097
  return await this.requestJson(
3680
5098
  "POST",
3681
- `/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}/installation-preview`,
5099
+ `/v1/workspaces/${workspaceId}/capabilities/${encodeURIComponent(capabilityId)}/enable`,
3682
5100
  request
3683
5101
  );
3684
5102
  }
3685
- /** Install, update, or repair a Pack from an exact previewed manifest. */
3686
- async installPack(workspaceId, packId, request) {
5103
+ async disableCapability(workspaceId, capabilityId) {
3687
5104
  return await this.requestJson(
3688
5105
  "POST",
3689
- `/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}/install`,
3690
- request
5106
+ `/v1/workspaces/${workspaceId}/capabilities/${encodeURIComponent(capabilityId)}/disable`
3691
5107
  );
3692
5108
  }
3693
- /** Preview which Pack-owned components will be retained by other owners. */
3694
- async previewPackUninstall(workspaceId, packId) {
3695
- return await this.requestJson(
5109
+ /** Read-only, permission-filtered workspace or session output discovery. */
5110
+ async listArtifactCatalog(workspaceId, options = {}) {
5111
+ const query = new URLSearchParams();
5112
+ for (const key of [
5113
+ "sourceSessionId",
5114
+ "q",
5115
+ "kind",
5116
+ "sort",
5117
+ "status",
5118
+ "limit",
5119
+ "cursor"
5120
+ ]) {
5121
+ if (options[key] !== void 0) query.set(key, String(options[key]));
5122
+ }
5123
+ const suffix = query.size ? `?${query.toString()}` : "";
5124
+ return this.requestJson(
3696
5125
  "GET",
3697
- `/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}/uninstall-preview`
3698
- );
3699
- }
3700
- /** Safely release Pack ownership and disable only now-ownerless components. */
3701
- async uninstallPack(workspaceId, packId, request) {
3702
- return await this.requestJson(
3703
- "DELETE",
3704
- `/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}/installation`,
3705
- request
3706
- );
3707
- }
3708
- /** Unregister a workspace-scoped pack (built-in packs cannot be deleted). */
3709
- async deletePack(workspaceId, packId) {
3710
- await this.requestVoid(
3711
- "DELETE",
3712
- `/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}`
5126
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/artifact-catalog${suffix}`,
5127
+ void 0,
5128
+ void 0,
5129
+ options
3713
5130
  );
3714
5131
  }
3715
- async listPackInstallations(workspaceId) {
5132
+ async listWorkspaceArtifacts(workspaceId, options = {}) {
5133
+ const query = new URLSearchParams();
5134
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
5135
+ if (options.cursor) query.set("cursor", options.cursor);
5136
+ if (options.status) query.set("status", options.status);
5137
+ if (options.sourceSessionId) query.set("sourceSessionId", options.sourceSessionId);
5138
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
3716
5139
  return await this.requestJson(
3717
5140
  "GET",
3718
- `/v1/workspaces/${workspaceId}/packs/installations`
5141
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/published-artifacts${suffix}`,
5142
+ void 0,
5143
+ void 0,
5144
+ options
3719
5145
  );
3720
5146
  }
3721
- // --- Capabilities -------------------------------------------------------------------------
3722
- async listCapabilities(workspaceId) {
5147
+ async getWorkspaceArtifact(workspaceId, artifactId, options = {}) {
3723
5148
  return await this.requestJson(
3724
5149
  "GET",
3725
- `/v1/workspaces/${workspaceId}/capabilities`
5150
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/published-artifacts/${encodeURIComponent(artifactId)}`,
5151
+ void 0,
5152
+ void 0,
5153
+ options
3726
5154
  );
3727
5155
  }
3728
- /** Add a manual capability catalog item (e.g. a remote MCP server). */
3729
- async createCapability(workspaceId, request) {
3730
- return await this.requestJson(
3731
- "POST",
3732
- `/v1/workspaces/${workspaceId}/capabilities`,
3733
- request
5156
+ /** Display-only HTML delivery: do not download the retained source bundle to render a Site. */
5157
+ async getWorkspaceArtifactHtml(workspaceId, artifactId, options) {
5158
+ const response = await this.requestResponse(
5159
+ "GET",
5160
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/published-artifacts/${encodeURIComponent(artifactId)}/html`,
5161
+ { versionId: options.versionId },
5162
+ options
3734
5163
  );
5164
+ return response.text();
3735
5165
  }
3736
- async enableCapability(workspaceId, capabilityId, request = {}) {
5166
+ async rollbackWorkspaceArtifact(workspaceId, artifactId, request, options = {}) {
3737
5167
  return await this.requestJson(
3738
5168
  "POST",
3739
- `/v1/workspaces/${workspaceId}/capabilities/${encodeURIComponent(capabilityId)}/enable`,
3740
- request
5169
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/published-artifacts/${encodeURIComponent(artifactId)}/rollback`,
5170
+ request,
5171
+ void 0,
5172
+ options
3741
5173
  );
3742
5174
  }
3743
- async disableCapability(workspaceId, capabilityId) {
5175
+ async setWorkspaceArtifactStatus(workspaceId, artifactId, request, options = {}) {
3744
5176
  return await this.requestJson(
3745
- "POST",
3746
- `/v1/workspaces/${workspaceId}/capabilities/${encodeURIComponent(capabilityId)}/disable`
5177
+ "PATCH",
5178
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}/published-artifacts/${encodeURIComponent(artifactId)}/status`,
5179
+ request,
5180
+ void 0,
5181
+ options
3747
5182
  );
3748
5183
  }
3749
5184
  /** Search the official MCP registry for installable capabilities. */
@@ -3758,6 +5193,26 @@ var OpenGeniClient = class {
3758
5193
  }
3759
5194
  );
3760
5195
  }
5196
+ async discoverPlugins(workspaceId, options = {}) {
5197
+ return this.requestJson(
5198
+ "GET",
5199
+ `/v1/workspaces/${workspaceId}/capabilities/discovery/plugins`,
5200
+ void 0,
5201
+ {
5202
+ ...options.id ? { id: options.id } : {},
5203
+ ...options.query ? { query: options.query } : {},
5204
+ ...options.provider ? { provider: options.provider } : {},
5205
+ ...options.offset !== void 0 ? { offset: String(options.offset) } : {}
5206
+ }
5207
+ );
5208
+ }
5209
+ async inspectMcpAuthentication(workspaceId, url) {
5210
+ return await this.requestJson(
5211
+ "POST",
5212
+ `/v1/workspaces/${workspaceId}/capabilities/discovery/mcp-auth`,
5213
+ { url }
5214
+ );
5215
+ }
3761
5216
  /** List installed protocol-neutral OpenAPI and GraphQL Integrations. */
3762
5217
  async listApiIntegrations(workspaceId) {
3763
5218
  return await this.requestJson(
@@ -3885,6 +5340,11 @@ var OpenGeniClient = class {
3885
5340
  request
3886
5341
  );
3887
5342
  }
5343
+ async getInstalledPluginDetails(workspaceId, pluginKey) {
5344
+ return this.requestJson("GET", `/v1/workspaces/${workspaceId}/plugins/details`, void 0, {
5345
+ pluginKey
5346
+ });
5347
+ }
3888
5348
  async listInstalledPlugins(workspaceId) {
3889
5349
  return await this.requestJson(
3890
5350
  "GET",
@@ -3934,6 +5394,54 @@ var OpenGeniClient = class {
3934
5394
  `/v1/workspaces/${workspaceId}/skills`
3935
5395
  );
3936
5396
  }
5397
+ /** Shared authored/installed catalog metadata. File bodies are read on demand. */
5398
+ async listWorkspaceSkills(workspaceId, options = {}) {
5399
+ const query = new URLSearchParams();
5400
+ if (options.cursor !== void 0) query.set("cursor", options.cursor);
5401
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
5402
+ if (options.sessionId !== void 0) query.set("sessionId", options.sessionId);
5403
+ const suffix = query.size ? `?${query.toString()}` : "";
5404
+ return this.requestJson("GET", `/v1/workspaces/${workspaceId}/skills/content${suffix}`);
5405
+ }
5406
+ async readWorkspaceSkill(workspaceId, skillId, revisionId) {
5407
+ const query = revisionId ? `?revisionId=${encodeURIComponent(revisionId)}` : "";
5408
+ return this.requestJson(
5409
+ "GET",
5410
+ `/v1/workspaces/${workspaceId}/skills/content/${encodeURIComponent(skillId)}${query}`
5411
+ );
5412
+ }
5413
+ async saveWorkspaceSkill(workspaceId, request) {
5414
+ return this.requestJson("POST", `/v1/workspaces/${workspaceId}/skills/content/save`, request);
5415
+ }
5416
+ /** Permanently remove a personal/workspace Skill and all its saved revisions. */
5417
+ async removeWorkspaceSkill(workspaceId, skillId, request) {
5418
+ return this.requestJson(
5419
+ "POST",
5420
+ `/v1/workspaces/${workspaceId}/skills/content/${encodeURIComponent(skillId)}/remove`,
5421
+ request
5422
+ );
5423
+ }
5424
+ async approveWorkspaceSkill(workspaceId, skillId, request) {
5425
+ return this.requestJson(
5426
+ "POST",
5427
+ `/v1/workspaces/${workspaceId}/skills/content/${encodeURIComponent(skillId)}/approve`,
5428
+ request
5429
+ );
5430
+ }
5431
+ async restoreWorkspaceSkill(workspaceId, skillId, request) {
5432
+ return this.requestJson(
5433
+ "POST",
5434
+ `/v1/workspaces/${workspaceId}/skills/content/${encodeURIComponent(skillId)}/restore`,
5435
+ request
5436
+ );
5437
+ }
5438
+ async rejectWorkspaceSkill(workspaceId, skillId, request) {
5439
+ return this.requestJson(
5440
+ "POST",
5441
+ `/v1/workspaces/${workspaceId}/skills/content/${encodeURIComponent(skillId)}/reject`,
5442
+ request
5443
+ );
5444
+ }
3937
5445
  /** Install one exact reviewed curated-library Skill through the Skill domain. */
3938
5446
  async installLibrarySkill(workspaceId, libraryId, request) {
3939
5447
  return await this.requestJson(
@@ -3957,6 +5465,17 @@ var OpenGeniClient = class {
3957
5465
  );
3958
5466
  }
3959
5467
  // --- Connections -------------------------------------------------------------------------------
5468
+ /** This authenticated user's accounts across the organization, plus current-workspace shared accounts.
5469
+ * Inactive accounts are opt-in for settings display; execution pickers keep the active default. */
5470
+ async listOwnConnectionAccounts(workspaceId, options = {}) {
5471
+ const response = await this.requestJson(
5472
+ "GET",
5473
+ `/v1/workspaces/${workspaceId}/connections/accounts`,
5474
+ void 0,
5475
+ options.includeInactive === true ? { includeInactive: "true" } : {}
5476
+ );
5477
+ return response.connections;
5478
+ }
3960
5479
  async listConnections(workspaceId) {
3961
5480
  const response = await this.requestJson(
3962
5481
  "GET",
@@ -3964,6 +5483,66 @@ var OpenGeniClient = class {
3964
5483
  );
3965
5484
  return response.connections;
3966
5485
  }
5486
+ /** Secret-free status for the caller's exact personal GitHub connection. */
5487
+ async personalGitHubStatus(workspaceId) {
5488
+ return await this.requestJson(
5489
+ "GET",
5490
+ `/v1/workspaces/${workspaceId}/connections/github`
5491
+ );
5492
+ }
5493
+ /** Start the dedicated personal GitHub authorization-code + PKCE flow. */
5494
+ async startPersonalGitHubOAuth(workspaceId, request = {}) {
5495
+ return await this.requestJson(
5496
+ "POST",
5497
+ `/v1/workspaces/${workspaceId}/connections/github/oauth/start`,
5498
+ request
5499
+ );
5500
+ }
5501
+ /** Re-authorize one exact personal GitHub Connection generation in place. */
5502
+ async reconnectPersonalGitHub(workspaceId, connectionId, request = {}) {
5503
+ return await this.requestJson(
5504
+ "POST",
5505
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/reconnect`,
5506
+ request
5507
+ );
5508
+ }
5509
+ /** Revoke one exact generation through an idempotent owner-only disconnect. */
5510
+ async disconnectPersonalGitHub(workspaceId, connectionId, request) {
5511
+ const response = await this.requestJson(
5512
+ "DELETE",
5513
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}`,
5514
+ request
5515
+ );
5516
+ return response.connection;
5517
+ }
5518
+ /** Browse one bounded page of repositories visible to one exact owner connection. */
5519
+ async listPersonalGitHubRepositories(workspaceId, connectionId, options = {}) {
5520
+ return await this.requestJson(
5521
+ "GET",
5522
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/repositories`,
5523
+ void 0,
5524
+ {
5525
+ ...options.cursor !== void 0 ? { cursor: String(options.cursor) } : {},
5526
+ ...options.limit !== void 0 ? { limit: String(options.limit) } : {}
5527
+ }
5528
+ );
5529
+ }
5530
+ /** Atomically replace the exact owner connection's selected repository set. */
5531
+ async replacePersonalGitHubRepositorySelections(workspaceId, connectionId, request) {
5532
+ return await this.requestJson(
5533
+ "PUT",
5534
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/repositories`,
5535
+ request
5536
+ );
5537
+ }
5538
+ /** Revalidate every selected repository without accepting provider URLs from the caller. */
5539
+ async verifyPersonalGitHubRepositorySelections(workspaceId, connectionId, request) {
5540
+ return await this.requestJson(
5541
+ "POST",
5542
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/repositories/verify`,
5543
+ request
5544
+ );
5545
+ }
3967
5546
  /** List the secret-free Slack team -> OpenGeni tenant routing authority. */
3968
5547
  async listSlackInstallationBindings(workspaceId) {
3969
5548
  const response = await this.requestJson(
@@ -4016,6 +5595,20 @@ var OpenGeniClient = class {
4016
5595
  `/v1/workspaces/${workspaceId}/integrations/slack/reaction-channels?${query}`
4017
5596
  );
4018
5597
  }
5598
+ async listOpenGeniSlackChannelRoutes(workspaceId, connectionId) {
5599
+ const query = new URLSearchParams({ connectionId });
5600
+ return await this.requestJson(
5601
+ "GET",
5602
+ `/v1/workspaces/${workspaceId}/integrations/slack/channel-routes?${query}`
5603
+ );
5604
+ }
5605
+ async updateOpenGeniSlackChannelRoutes(workspaceId, request) {
5606
+ await this.requestJson(
5607
+ "PUT",
5608
+ `/v1/workspaces/${workspaceId}/integrations/slack/channel-routes`,
5609
+ request
5610
+ );
5611
+ }
4019
5612
  async updateConnection(workspaceId, connectionId, request) {
4020
5613
  const response = await this.requestJson(
4021
5614
  "PATCH",
@@ -4087,6 +5680,20 @@ var OpenGeniClient = class {
4087
5680
  catalogAssetUrl(logoAssetPath) {
4088
5681
  return logoAssetPath ? `${this.baseUrl}/v1/${logoAssetPath}` : null;
4089
5682
  }
5683
+ /** Read a passive catalog mark through this client's authenticated transport.
5684
+ * Useful when an embedding backend protects even public upstream assets. */
5685
+ async downloadCatalogAsset(logoAssetPath, options = {}) {
5686
+ if (!/^catalog-assets\/[a-zA-Z0-9_./-]+$/.test(logoAssetPath) || logoAssetPath.split("/").some((part) => !part || part === "." || part === ".."))
5687
+ throw new TypeError("A catalog asset path is required");
5688
+ const response = await this.requestResponse("GET", `/v1/${logoAssetPath}`, {}, options);
5689
+ const type = response.headers.get("content-type")?.split(";")[0] ?? "";
5690
+ if (!type.startsWith("image/")) {
5691
+ await response.body?.cancel();
5692
+ throw new Error("The catalog asset is not an image");
5693
+ }
5694
+ const bytes = await readBoundedResponseBytes(response, 2e6, null);
5695
+ return new Blob([Uint8Array.from(bytes)], { type });
5696
+ }
4090
5697
  // --- GitHub ----------------------------------------------------------------------------------
4091
5698
  /** GitHub App server configuration plus truthful workspace binding status. */
4092
5699
  async getGitHubApp(workspaceId, options = {}) {
@@ -4107,6 +5714,21 @@ var OpenGeniClient = class {
4107
5714
  `/v1/workspaces/${workspaceId}/github/repositories`
4108
5715
  );
4109
5716
  }
5717
+ /** Effective confirmation policy for each GitHub identity available to this caller. */
5718
+ async getGitHubActionPolicies(workspaceId) {
5719
+ return await this.requestJson(
5720
+ "GET",
5721
+ `/v1/workspaces/${workspaceId}/github/action-policies`
5722
+ );
5723
+ }
5724
+ /** Change one GitHub action group without broadening review or merge policy. */
5725
+ async updateGitHubActionPolicy(workspaceId, request) {
5726
+ return await this.requestJson(
5727
+ "PATCH",
5728
+ `/v1/workspaces/${workspaceId}/github/action-policies`,
5729
+ request
5730
+ );
5731
+ }
4110
5732
  /** Re-sync the installation's repository list from GitHub. */
4111
5733
  async syncGitHubRepositories(workspaceId) {
4112
5734
  return await this.requestJson(
@@ -4152,12 +5774,192 @@ var OpenGeniClient = class {
4152
5774
  `/v1/workspaces/${workspaceId}/api-keys/${apiKeyId}`
4153
5775
  );
4154
5776
  }
5777
+ async listOrganizationApiKeys(organizationId) {
5778
+ const response = await this.requestJson(
5779
+ "GET",
5780
+ `/v1/organizations/${organizationId}/api-keys`
5781
+ );
5782
+ return response.apiKeys;
5783
+ }
5784
+ /** The returned `token` is shown once; only its prefix is stored. */
5785
+ async createOrganizationApiKey(organizationId, request) {
5786
+ return await this.requestJson(
5787
+ "POST",
5788
+ `/v1/organizations/${organizationId}/api-keys`,
5789
+ request
5790
+ );
5791
+ }
5792
+ /** Revoke an organization-scoped API key. Returns the revoked key. */
5793
+ async deleteOrganizationApiKey(organizationId, apiKeyId) {
5794
+ return await this.requestJson(
5795
+ "DELETE",
5796
+ `/v1/organizations/${organizationId}/api-keys/${apiKeyId}`
5797
+ );
5798
+ }
5799
+ // --- Connected agents (organization MCP server) ------------------------------------------------
5800
+ /**
5801
+ * Agents people connected to the organization MCP server (`/v1/mcp`).
5802
+ * Everyone sees their own; owners and admins see everyone's. Browser only:
5803
+ * keys and agents are refused, so an agent can't widen its own access.
5804
+ */
5805
+ async listOrganizationMcpConnections(organizationId) {
5806
+ return await this.requestJson(
5807
+ "GET",
5808
+ `/v1/organizations/${organizationId}/mcp-connections`
5809
+ );
5810
+ }
5811
+ /** Change what a connected agent can do and where; its next request uses it. Only its person. */
5812
+ async updateOrganizationMcpConnection(organizationId, connectionId, request) {
5813
+ return await this.requestJson(
5814
+ "PATCH",
5815
+ `/v1/organizations/${organizationId}/mcp-connections/${connectionId}`,
5816
+ request
5817
+ );
5818
+ }
5819
+ /** Disconnect an agent: every token it holds is refused from now on. */
5820
+ async deleteOrganizationMcpConnection(organizationId, connectionId) {
5821
+ await this.requestVoid(
5822
+ "DELETE",
5823
+ `/v1/organizations/${organizationId}/mcp-connections/${connectionId}`
5824
+ );
5825
+ }
5826
+ /** Service accounts: organization identities with no person behind them. */
5827
+ async listOrganizationServiceAccounts(organizationId) {
5828
+ return await this.requestJson(
5829
+ "GET",
5830
+ `/v1/organizations/${organizationId}/service-accounts`
5831
+ );
5832
+ }
5833
+ async getOrganizationServiceAccount(organizationId, serviceAccountId) {
5834
+ return await this.requestJson(
5835
+ "GET",
5836
+ `/v1/organizations/${organizationId}/service-accounts/${serviceAccountId}`
5837
+ );
5838
+ }
5839
+ /** Create a service account; give it keys with `createOrganizationApiKey({ serviceAccountId })`. */
5840
+ async createOrganizationServiceAccount(organizationId, request) {
5841
+ return await this.requestJson(
5842
+ "POST",
5843
+ `/v1/organizations/${organizationId}/service-accounts`,
5844
+ request
5845
+ );
5846
+ }
5847
+ /** Rename it or change its role; making it a member narrows its keys at once. */
5848
+ async updateOrganizationServiceAccount(organizationId, serviceAccountId, request) {
5849
+ return await this.requestJson(
5850
+ "PATCH",
5851
+ `/v1/organizations/${organizationId}/service-accounts/${serviceAccountId}`,
5852
+ request
5853
+ );
5854
+ }
5855
+ /** Delete a service account; every key it holds is revoked at once. */
5856
+ async deleteOrganizationServiceAccount(organizationId, serviceAccountId) {
5857
+ await this.requestVoid(
5858
+ "DELETE",
5859
+ `/v1/organizations/${organizationId}/service-accounts/${serviceAccountId}`
5860
+ );
5861
+ }
5862
+ /** The pending sign-in an agent started; read by the web app's sign-in page. */
5863
+ async getMcpConnectionRequest(requestToken) {
5864
+ return await this.requestJson(
5865
+ "GET",
5866
+ `/v1/mcp-connections/requests/${encodeURIComponent(requestToken)}`
5867
+ );
5868
+ }
5869
+ /** Allow or deny an agent's sign-in. Returns where to send the browser next. */
5870
+ async answerMcpConnectionRequest(requestToken, decision) {
5871
+ return await this.requestJson(
5872
+ "POST",
5873
+ `/v1/mcp-connections/requests/${encodeURIComponent(requestToken)}`,
5874
+ decision
5875
+ );
5876
+ }
5877
+ // --- Organization-wide sessions ----------------------------------------------------------------
5878
+ /**
5879
+ * One page of sessions across every shared workspace of the organization the
5880
+ * caller may read within its live workspace scope (an organization API key or
5881
+ * organization owner). Each row carries its `workspaceId`; read events,
5882
+ * history, and files through the ordinary workspace methods. Personal
5883
+ * workspaces are never included and private sessions stay invisible.
5884
+ */
5885
+ async listOrganizationSessions(organizationId, options = {}) {
5886
+ return await this.requestJson(
5887
+ "GET",
5888
+ `/v1/organizations/${organizationId}/sessions`,
5889
+ void 0,
5890
+ {
5891
+ ...options.limit === void 0 ? {} : { limit: String(options.limit) },
5892
+ ...options.cursor === void 0 ? {} : { cursor: options.cursor },
5893
+ ...options.scopeSubjectId ? { scopeSubjectId: options.scopeSubjectId } : {},
5894
+ ...options.status === void 0 ? {} : { status: options.status }
5895
+ },
5896
+ { signal: options.signal }
5897
+ );
5898
+ }
5899
+ /**
5900
+ * Every session `listOrganizationSessions` would return, following
5901
+ * `nextCursor` page by page until the organization is exhausted. A page may
5902
+ * be shorter than `limit` while more pages remain, so callers must not treat
5903
+ * a short page as the end.
5904
+ */
5905
+ async *iterateOrganizationSessions(organizationId, options = {}) {
5906
+ let cursor;
5907
+ do {
5908
+ const page = await this.listOrganizationSessions(
5909
+ organizationId,
5910
+ { ...options, ...cursor === void 0 ? {} : { cursor } }
5911
+ );
5912
+ for (const session of page.sessions) {
5913
+ yield session;
5914
+ }
5915
+ cursor = page.nextCursor ?? void 0;
5916
+ } while (cursor !== void 0);
5917
+ }
4155
5918
  // --- Billing (account-scoped) --------------------------------------------------------------------
4156
5919
  async getBilling(options = {}) {
4157
5920
  return await this.requestJson("GET", "/v1/billing", void 0, {
4158
5921
  ...options.accountId !== void 0 ? { accountId: options.accountId } : {}
4159
5922
  });
4160
5923
  }
5924
+ async getOrganizationUsageSummary(options, requestOptions = {}) {
5925
+ return await this.requestJson(
5926
+ "GET",
5927
+ "/v1/billing/usage-summary",
5928
+ void 0,
5929
+ {
5930
+ accountId: options.accountId,
5931
+ period: options.period ?? "month"
5932
+ },
5933
+ requestOptions
5934
+ );
5935
+ }
5936
+ async getOrganizationModelUsage(options, requestOptions = {}) {
5937
+ return await this.requestJson(
5938
+ "GET",
5939
+ "/v1/billing/usage-models",
5940
+ void 0,
5941
+ {
5942
+ accountId: options.accountId,
5943
+ period: options.period ?? "month",
5944
+ ...options.afterWorkspaceId ? { afterWorkspaceId: options.afterWorkspaceId } : {}
5945
+ },
5946
+ requestOptions
5947
+ );
5948
+ }
5949
+ async getOrganizationUsageWorkspacePage(options, requestOptions = {}) {
5950
+ return await this.requestJson(
5951
+ "GET",
5952
+ "/v1/billing/usage-workspaces",
5953
+ void 0,
5954
+ {
5955
+ accountId: options.accountId,
5956
+ period: options.period ?? "month",
5957
+ until: options.until,
5958
+ ...options.afterWorkspaceId ? { afterWorkspaceId: options.afterWorkspaceId } : {}
5959
+ },
5960
+ requestOptions
5961
+ );
5962
+ }
4161
5963
  async getBillingUsage(options = {}) {
4162
5964
  return await this.requestJson("GET", "/v1/billing/usage", void 0, {
4163
5965
  ...options.accountId !== void 0 ? { accountId: options.accountId } : {},
@@ -4172,8 +5974,11 @@ var OpenGeniClient = class {
4172
5974
  {
4173
5975
  range: options.range ?? "week",
4174
5976
  ...options.provider !== void 0 ? { provider: options.provider } : {},
4175
- ...options.model !== void 0 ? { model: options.model } : {}
4176
- }
5977
+ ...options.model !== void 0 ? { model: options.model } : {},
5978
+ ...options.rootSessionId !== void 0 ? { rootSessionId: options.rootSessionId } : {},
5979
+ ...options.sessionId !== void 0 ? { sessionId: options.sessionId } : {}
5980
+ },
5981
+ { signal: options.signal }
4177
5982
  );
4178
5983
  }
4179
5984
  async getBillingEntitlements(options = {}) {
@@ -4190,15 +5995,104 @@ var OpenGeniClient = class {
4190
5995
  async createBillingCheckout(request) {
4191
5996
  return await this.requestJson("POST", "/v1/billing/checkout", request);
4192
5997
  }
5998
+ /**
5999
+ * Where one checkout stands, and whether its credits reached the balance.
6000
+ * Poll it after the customer returns from Stripe Checkout.
6001
+ */
6002
+ async getBillingCheckout(checkoutSessionId, options = {}) {
6003
+ return await this.requestJson(
6004
+ "GET",
6005
+ `/v1/billing/checkout/${encodeURIComponent(checkoutSessionId)}`,
6006
+ void 0,
6007
+ {
6008
+ ...options.accountId !== void 0 ? { accountId: options.accountId } : {}
6009
+ }
6010
+ );
6011
+ }
6012
+ /** Open Stripe's hosted portal for invoices and payment information. */
6013
+ async createBillingPortalSession(request = {}) {
6014
+ return await this.requestJson(
6015
+ "POST",
6016
+ "/v1/billing/portal",
6017
+ request
6018
+ );
6019
+ }
6020
+ // --- Embedding transport -----------------------------------------------------
6021
+ /** The URL of an API path on this client's base (relative when the base is relative). */
6022
+ apiUrl(path) {
6023
+ if (!path.startsWith("/")) throw new TypeError("API path must start with /");
6024
+ return `${this.baseUrl}${path}`;
6025
+ }
6026
+ /**
6027
+ * A client of the same class that adds `headers` to every request, keeping
6028
+ * this client's base URL, fetch, credentials, and actor attribution. Used to
6029
+ * scope a surface (for example an artifact viewer) to one host context.
6030
+ */
6031
+ withHeaders(headers) {
6032
+ const extra = { ...headers };
6033
+ const base = this.options.headers;
6034
+ const Client = this.constructor;
6035
+ const client = new Client({
6036
+ ...this.options,
6037
+ headers: () => ({ ...typeof base === "function" ? base() : base, ...extra })
6038
+ });
6039
+ if (this.externalActorHeader !== void 0) {
6040
+ client.externalActorHeader = this.externalActorHeader;
6041
+ }
6042
+ client.serviceInitiatorHeader = this.serviceInitiatorHeader;
6043
+ client.serviceContextHeader = this.serviceContextHeader;
6044
+ return client;
6045
+ }
6046
+ /**
6047
+ * Fetch an absolute URL under this client's base URL through its fetch and
6048
+ * headers. For transports the SDK builds itself (the editable-artifact live
6049
+ * transport), so host authentication stays in one place. A URL outside the
6050
+ * base is refused: credentials never leave the configured API.
6051
+ */
6052
+ async fetchApi(input, init = {}) {
6053
+ const origin = typeof globalThis.location?.href === "string" ? globalThis.location.href : void 0;
6054
+ const base = new URL(this.baseUrl.endsWith("/") ? this.baseUrl : `${this.baseUrl}/`, origin);
6055
+ const target = new URL(input, base);
6056
+ if (target.origin !== base.origin || !`${target.pathname}/`.startsWith(base.pathname)) {
6057
+ throw new TypeError("fetchApi only reaches this client's API base URL");
6058
+ }
6059
+ const headers = new Headers(init.headers);
6060
+ for (const [name, value] of Object.entries(this.headers())) {
6061
+ if (!headers.has(name)) headers.set(name, value);
6062
+ }
6063
+ return await this.fetchImpl(target.href, { ...init, headers });
6064
+ }
4193
6065
  // --- Internals -------------------------------------------------------------
4194
6066
  headers(correlationId) {
4195
6067
  const extra = typeof this.options.headers === "function" ? this.options.headers() : this.options.headers;
4196
- return {
6068
+ const headers = {
4197
6069
  ...this.options.apiKey ? { Authorization: `Bearer ${this.options.apiKey}` } : {},
4198
6070
  ...extra,
4199
6071
  [OPENGENI_API_CONTRACT_HEADER]: OPENGENI_API_CONTRACT_REVISION,
4200
6072
  ...correlationId ? { [OPENGENI_CORRELATION_HEADER]: correlationId } : {}
4201
6073
  };
6074
+ const headerNames = Object.keys(headers).map((key) => key.toLowerCase());
6075
+ const hasUser = this.externalActorHeader !== void 0 || headerNames.includes("x-opengeni-external-actor");
6076
+ const hasService = this.serviceInitiatorHeader !== void 0 || headerNames.includes("x-opengeni-service-initiator") || headerNames.includes("x-opengeni-service-context");
6077
+ if (hasUser && hasService)
6078
+ throw new Error("asUser and asService attribution headers are mutually exclusive");
6079
+ if (this.externalActorHeader) {
6080
+ for (const key of Object.keys(headers)) {
6081
+ if (key.toLowerCase() === "x-opengeni-external-actor") delete headers[key];
6082
+ }
6083
+ headers["x-opengeni-external-actor"] = this.externalActorHeader;
6084
+ }
6085
+ if (this.serviceInitiatorHeader !== void 0) {
6086
+ for (const key of Object.keys(headers)) {
6087
+ const name = key.toLowerCase();
6088
+ if (name === "x-opengeni-service-initiator" || name === "x-opengeni-service-context")
6089
+ delete headers[key];
6090
+ }
6091
+ headers["x-opengeni-service-initiator"] = this.serviceInitiatorHeader;
6092
+ if (this.serviceContextHeader !== void 0)
6093
+ headers["x-opengeni-service-context"] = this.serviceContextHeader;
6094
+ }
6095
+ return headers;
4202
6096
  }
4203
6097
  url(path, query = {}) {
4204
6098
  const params = new URLSearchParams(query).toString();
@@ -4266,6 +6160,13 @@ var OpenGeniClient = class {
4266
6160
  `/v1/workspaces/${workspaceId}/codex/accounts`
4267
6161
  );
4268
6162
  }
6163
+ /** Session-authorized retry choices plus the current accepted account. */
6164
+ async listSessionCodexAccounts(workspaceId, sessionId) {
6165
+ return await this.requestJson(
6166
+ "GET",
6167
+ `${sessionPath(workspaceId, sessionId)}/codex-accounts`
6168
+ );
6169
+ }
4269
6170
  /** Switch the workspace ACTIVE Codex account (the one unpinned sessions use). */
4270
6171
  async activateCodexAccount(workspaceId, accountId) {
4271
6172
  return await this.requestJson(
@@ -4317,15 +6218,77 @@ var OpenGeniClient = class {
4317
6218
  { label }
4318
6219
  );
4319
6220
  }
4320
- /** Pin (or unpin via "auto") a session's Codex account. Applies on the next turn. */
6221
+ /** Pin/unpin a Codex account. Overrides a capacity-blocked turn; otherwise applies next turn. */
4321
6222
  async pinSessionCodexAccount(workspaceId, sessionId, target) {
6223
+ return await this.requestJson("POST", `${sessionPath(workspaceId, sessionId)}/codex-account`, { target });
6224
+ }
6225
+ // --- SuperGrok/xAI connected subscriptions ------------------------------------------------------
6226
+ /** Organization subscription management requires an administrator browser session. */
6227
+ async getModelConnectionAccess(target) {
6228
+ return await this.requestJson(
6229
+ "GET",
6230
+ `/v1/${target.scope}/${encodeURIComponent(target.scopeId)}/model-connections/${target.kind}/${encodeURIComponent(target.connectionId)}/access`
6231
+ );
6232
+ }
6233
+ async updateModelConnectionAccess(target, policy) {
6234
+ return await this.requestJson(
6235
+ "PUT",
6236
+ `/v1/${target.scope}/${encodeURIComponent(target.scopeId)}/model-connections/${target.kind}/${encodeURIComponent(target.connectionId)}/access`,
6237
+ policy
6238
+ );
6239
+ }
6240
+ async listOrganizationSuperGrokAccounts(organizationId) {
6241
+ return await this.requestJson("GET", `/v1/organizations/${organizationId}/supergrok/accounts`);
6242
+ }
6243
+ async organizationSupergrokConnectStart(organizationId) {
4322
6244
  return await this.requestJson(
4323
6245
  "POST",
4324
- `/v1/workspaces/${workspaceId}/sessions/${sessionId}/codex-account`,
4325
- { target }
6246
+ `/v1/organizations/${organizationId}/supergrok/connect/start`,
6247
+ {}
6248
+ );
6249
+ }
6250
+ async organizationSupergrokConnectPoll(organizationId, state) {
6251
+ return await this.requestJson(
6252
+ "POST",
6253
+ `/v1/organizations/${organizationId}/supergrok/connect/poll`,
6254
+ { state }
6255
+ );
6256
+ }
6257
+ async activateOrganizationSuperGrokAccount(organizationId, accountId) {
6258
+ return await this.requestJson(
6259
+ "POST",
6260
+ `/v1/organizations/${organizationId}/supergrok/accounts/${accountId}/activate`,
6261
+ {}
6262
+ );
6263
+ }
6264
+ async setOrganizationSuperGrokRotationSettings(organizationId, patch) {
6265
+ return await this.requestJson(
6266
+ "PATCH",
6267
+ `/v1/organizations/${organizationId}/supergrok/settings`,
6268
+ patch
6269
+ );
6270
+ }
6271
+ async setOrganizationSuperGrokAccountAllocator(organizationId, accountId, input) {
6272
+ return await this.requestJson(
6273
+ "PATCH",
6274
+ `/v1/organizations/${organizationId}/supergrok/accounts/${accountId}/allocator`,
6275
+ input
6276
+ );
6277
+ }
6278
+ async renameOrganizationSuperGrokAccount(organizationId, accountId, label) {
6279
+ return await this.requestJson(
6280
+ "PATCH",
6281
+ `/v1/organizations/${organizationId}/supergrok/accounts/${accountId}`,
6282
+ { label }
6283
+ );
6284
+ }
6285
+ async disconnectOrganizationSuperGrokAccount(organizationId, accountId) {
6286
+ return await this.requestJson(
6287
+ "DELETE",
6288
+ `/v1/organizations/${organizationId}/supergrok/accounts/${accountId}`,
6289
+ {}
4326
6290
  );
4327
6291
  }
4328
- // --- SuperGrok/xAI connected subscriptions ------------------------------------------------------
4329
6292
  async supergrokStatus(workspaceId) {
4330
6293
  return await this.requestJson(
4331
6294
  "GET",
@@ -4384,50 +6347,89 @@ var OpenGeniClient = class {
4384
6347
  return await this.requestJson("DELETE", `/v1/workspaces/${workspaceId}/supergrok/accounts/${accountId}`, {});
4385
6348
  }
4386
6349
  /** Contract-checked JSON transport shared by opt-in typed SDK clients. */
6350
+ async requestSessionCommand(method, path, body, options = {}) {
6351
+ return await this.requestJson(
6352
+ method,
6353
+ path,
6354
+ body,
6355
+ {},
6356
+ {
6357
+ signal: options.signal,
6358
+ timeoutMs: options.timeoutMs ?? this.sessionCommandTimeoutMs
6359
+ }
6360
+ );
6361
+ }
6362
+ /** Contract-checked JSON transport shared by opt-in typed SDK clients. */
4387
6363
  async requestJson(method, path, body, query = {}, options = {}) {
4388
6364
  const correlationId = crypto.randomUUID();
4389
- let response;
6365
+ const abort = requestAbortSignal(options);
4390
6366
  try {
4391
- response = await this.fetchImpl(this.url(path, query), {
4392
- method,
4393
- headers: {
4394
- ...this.headers(correlationId),
4395
- Accept: "application/json",
4396
- ...body !== void 0 ? { "Content-Type": "application/json" } : {}
4397
- },
4398
- ...body !== void 0 ? { body: JSON.stringify(body) } : {},
4399
- ...options.signal ? { signal: options.signal } : {}
4400
- });
4401
- } catch (error) {
4402
- if (isMutationMethod(method)) {
4403
- throw mutationTransportError(correlationId);
6367
+ if (abort.signal?.aborted) {
6368
+ throw abort.signal.reason ?? new DOMException("Request aborted", "AbortError");
4404
6369
  }
4405
- throw error;
4406
- }
4407
- assertApiContractResponse(response);
4408
- if (!response.ok) {
4409
- throw await apiErrorFromResponse(response, { method, correlationId });
4410
- }
4411
- await assertJsonResponse(response, { method, correlationId });
4412
- try {
4413
- return await response.json();
4414
- } catch (error) {
4415
- if (isMutationMethod(method)) {
4416
- throw mutationTransportError(correlationId);
6370
+ const headers = this.headers(correlationId);
6371
+ let response;
6372
+ try {
6373
+ response = await awaitWithAbort(
6374
+ this.fetchImpl(this.url(path, query), {
6375
+ method,
6376
+ headers: {
6377
+ ...headers,
6378
+ Accept: "application/json",
6379
+ ...body !== void 0 ? { "Content-Type": "application/json" } : {}
6380
+ },
6381
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {},
6382
+ ...abort.signal ? { signal: abort.signal } : {}
6383
+ }),
6384
+ abort.signal
6385
+ );
6386
+ } catch (error) {
6387
+ if (options.signal?.aborted) throw error;
6388
+ if (isMutationMethod(method)) {
6389
+ throw mutationTransportError(correlationId);
6390
+ }
6391
+ throw error;
4417
6392
  }
4418
- throw error;
6393
+ assertApiContractResponse(response, this.apiContractStrict);
6394
+ try {
6395
+ if (!response.ok) {
6396
+ throw await awaitWithAbort(
6397
+ apiErrorFromResponse(response, { method, correlationId }),
6398
+ abort.signal
6399
+ );
6400
+ }
6401
+ if (options.responseType === "void") {
6402
+ await awaitWithAbort(
6403
+ cancelResponseBody(response, "discarding void API response"),
6404
+ abort.signal
6405
+ );
6406
+ return void 0;
6407
+ }
6408
+ await awaitWithAbort(assertJsonResponse(response, { method, correlationId }), abort.signal);
6409
+ return await awaitWithAbort(response.json(), abort.signal);
6410
+ } catch (error) {
6411
+ if (options.signal?.aborted) throw error;
6412
+ if (error instanceof OpenGeniApiError) throw error;
6413
+ if (isMutationMethod(method)) {
6414
+ throw mutationTransportError(correlationId);
6415
+ }
6416
+ throw error;
6417
+ }
6418
+ } finally {
6419
+ abort.dispose();
4419
6420
  }
4420
6421
  }
4421
6422
  /** Authenticated, contract-checked response for bounded streaming downloads. */
4422
6423
  async requestResponse(method, path, query = {}, options = {}) {
4423
6424
  const correlationId = crypto.randomUUID();
6425
+ const headers = this.headers(correlationId);
4424
6426
  let response;
4425
6427
  try {
4426
6428
  response = await this.fetchImpl(this.url(path, query), {
4427
6429
  method,
4428
6430
  headers: {
4429
- ...this.headers(correlationId),
4430
- Accept: "application/octet-stream"
6431
+ ...headers,
6432
+ Accept: options.accept ?? "application/octet-stream"
4431
6433
  },
4432
6434
  ...options.signal ? { signal: options.signal } : {}
4433
6435
  });
@@ -4435,21 +6437,22 @@ var OpenGeniClient = class {
4435
6437
  if (isMutationMethod(method)) throw mutationTransportError(correlationId);
4436
6438
  throw error;
4437
6439
  }
4438
- assertApiContractResponse(response);
6440
+ assertApiContractResponse(response, this.apiContractStrict);
4439
6441
  if (!response.ok) {
4440
6442
  throw await apiErrorFromResponse(response, { method, correlationId });
4441
6443
  }
4442
6444
  return response;
4443
6445
  }
4444
- /** Like `requestJson` for endpoints that respond with no body (204). */
6446
+ /** Contract-checked transport shared by opt-in typed SDK clients for 204 responses. */
4445
6447
  async requestVoid(method, path, body) {
4446
6448
  const correlationId = crypto.randomUUID();
6449
+ const headers = this.headers(correlationId);
4447
6450
  let response;
4448
6451
  try {
4449
6452
  response = await this.fetchImpl(this.url(path), {
4450
6453
  method,
4451
6454
  headers: {
4452
- ...this.headers(correlationId),
6455
+ ...headers,
4453
6456
  Accept: "application/json",
4454
6457
  ...body !== void 0 ? { "Content-Type": "application/json" } : {}
4455
6458
  },
@@ -4461,13 +6464,14 @@ var OpenGeniClient = class {
4461
6464
  }
4462
6465
  throw error;
4463
6466
  }
4464
- assertApiContractResponse(response);
6467
+ assertApiContractResponse(response, this.apiContractStrict);
4465
6468
  if (!response.ok) {
4466
6469
  throw await apiErrorFromResponse(response, { method, correlationId });
4467
6470
  }
4468
6471
  }
4469
6472
  };
4470
- function assertApiContractResponse(response) {
6473
+ function assertApiContractResponse(response, strict) {
6474
+ if (!strict) return;
4471
6475
  const actual = response.headers.get(OPENGENI_API_CONTRACT_HEADER);
4472
6476
  if (actual && actual !== OPENGENI_API_CONTRACT_REVISION) {
4473
6477
  throw new OpenGeniApiContractMismatchError(OPENGENI_API_CONTRACT_REVISION, actual);
@@ -4533,11 +6537,62 @@ function filenameForAudioMimeType(mimeType) {
4533
6537
  }
4534
6538
  }
4535
6539
  var API_ERROR_MAX_BYTES = 16 * 1024;
6540
+ function requestAbortSignal(options) {
6541
+ const timeoutMs = options.timeoutMs ?? 0;
6542
+ if (timeoutMs <= 0) {
6543
+ return { signal: options.signal, dispose: () => void 0 };
6544
+ }
6545
+ const controller = new AbortController();
6546
+ const onCallerAbort = () => controller.abort(options.signal?.reason);
6547
+ if (options.signal?.aborted) {
6548
+ onCallerAbort();
6549
+ } else {
6550
+ options.signal?.addEventListener("abort", onCallerAbort, { once: true });
6551
+ }
6552
+ const timer = setTimeout(
6553
+ () => controller.abort(new DOMException("Request timed out", "TimeoutError")),
6554
+ timeoutMs
6555
+ );
6556
+ return {
6557
+ signal: controller.signal,
6558
+ dispose: () => {
6559
+ clearTimeout(timer);
6560
+ options.signal?.removeEventListener("abort", onCallerAbort);
6561
+ }
6562
+ };
6563
+ }
6564
+ async function awaitWithAbort(promise, signal) {
6565
+ if (!signal) return await promise;
6566
+ if (signal.aborted) {
6567
+ throw signal.reason ?? new DOMException("Request aborted", "AbortError");
6568
+ }
6569
+ return await new Promise((resolve, reject) => {
6570
+ const onAbort = () => {
6571
+ cleanup();
6572
+ reject(signal.reason ?? new DOMException("Request aborted", "AbortError"));
6573
+ };
6574
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
6575
+ signal.addEventListener("abort", onAbort, { once: true });
6576
+ promise.then(
6577
+ (value) => {
6578
+ cleanup();
6579
+ resolve(value);
6580
+ },
6581
+ (cause) => {
6582
+ cleanup();
6583
+ reject(cause);
6584
+ }
6585
+ );
6586
+ });
6587
+ }
4536
6588
  async function apiErrorFromResponse(response, context) {
4537
- return new OpenGeniApiError(response.status, await readBoundedJsonErrorBody(response), {
6589
+ const body = await readBoundedJsonErrorBody(response);
6590
+ const ErrorType = allowanceExhaustedFields(body) ? OpenGeniAllowanceExhaustedError : OpenGeniApiError;
6591
+ const error = new ErrorType(response.status, body, {
4538
6592
  correlationId: response.headers.get(OPENGENI_CORRELATION_HEADER) ?? context.correlationId,
4539
6593
  mutation: isMutationMethod(context.method)
4540
6594
  });
6595
+ return error.status >= 400 && error.status < 500 && (error.code === "SESSION_TENANCY_NOT_ACTIVATED" || error.code === "OPENGENI_SETUP_REQUIRED") ? new OpenGeniSetupError(error) : error;
4541
6596
  }
4542
6597
  async function assertJsonResponse(response, context) {
4543
6598
  if (isJsonContentType(response.headers.get("content-type"))) return;
@@ -4547,7 +6602,7 @@ async function assertJsonResponse(response, context) {
4547
6602
  retryable: true,
4548
6603
  correlationId: response.headers.get(OPENGENI_CORRELATION_HEADER) ?? context.correlationId,
4549
6604
  outcomeUnknown: isMutationMethod(context.method),
4550
- displayMessage: "OpenGeni is temporarily unavailable \u2014 retry."
6605
+ displayMessage: "Opengeni is temporarily unavailable \u2014 retry."
4551
6606
  });
4552
6607
  }
4553
6608
  async function readBoundedJsonErrorBody(response) {
@@ -4580,9 +6635,19 @@ function mutationTransportError(correlationId) {
4580
6635
  correlationId,
4581
6636
  outcomeUnknown: true,
4582
6637
  mutation: true,
4583
- displayMessage: "OpenGeni could not confirm the request \u2014 reconcile before retrying."
6638
+ displayMessage: "Opengeni could not confirm the request \u2014 reconcile before retrying."
4584
6639
  });
4585
6640
  }
6641
+ function assertBrowserFileUploadSecureContext() {
6642
+ const secureContext = typeof window !== "undefined" ? window.isSecureContext : typeof globalThis.isSecureContext === "boolean" ? globalThis.isSecureContext : void 0;
6643
+ if (secureContext === void 0) return;
6644
+ if (!secureContext) {
6645
+ throw new OpenGeniSecureContextRequiredError("insecure_context");
6646
+ }
6647
+ if (typeof globalThis.crypto === "undefined" || typeof globalThis.crypto.subtle?.digest !== "function") {
6648
+ throw new OpenGeniSecureContextRequiredError("web_crypto_unavailable");
6649
+ }
6650
+ }
4586
6651
  async function sha256ForUpload(body) {
4587
6652
  const bytes = typeof body === "string" ? new TextEncoder().encode(body) : body instanceof Blob ? new Uint8Array(await body.arrayBuffer()) : new Uint8Array(body);
4588
6653
  const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
@@ -4593,12 +6658,21 @@ async function sha256Hex(bytes) {
4593
6658
  const digest = await globalThis.crypto.subtle.digest("SHA-256", owned.buffer);
4594
6659
  return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
4595
6660
  }
6661
+ function computerFrameEvidenceMismatchReason(metadata, expected) {
6662
+ if (metadata.computerSessionId !== expected.computerSessionId) {
6663
+ return "frame_session_mismatch";
6664
+ }
6665
+ if (metadata.targetId !== expected.targetId) return "frame_target_mismatch";
6666
+ if (metadata.mediaType !== expected.mediaType) return "frame_media_mismatch";
6667
+ if (metadata.sha256 !== expected.sha256) return "frame_digest_mismatch";
6668
+ return null;
6669
+ }
4596
6670
  async function cancelResponseBody(response, reason) {
4597
6671
  await response.body?.cancel(reason).catch(() => void 0);
4598
6672
  }
4599
- function assertRetainedGeneratedImageReceipt(workspaceId, artifact) {
4600
- if (!parseRetainedGeneratedImageReference(artifact, workspaceId)) {
4601
- throw new OpenGeniApiError(502, "retained generated image receipt is invalid");
6673
+ function assertRetainedWorkspaceArtifactReceipt(workspaceId, artifact) {
6674
+ if (!parseRetainedGeneratedImageReference(artifact, workspaceId) && !parseRetainedWorkspaceFileReference(artifact, workspaceId)) {
6675
+ throw new OpenGeniApiError(502, "retained workspace artifact receipt is invalid");
4602
6676
  }
4603
6677
  }
4604
6678
  function assertSafeArtifactDownloadUrl(value) {
@@ -4669,12 +6743,13 @@ async function readBoundedResponseBytes(response, maxBytes, expectedBytes) {
4669
6743
  }
4670
6744
 
4671
6745
  export {
4672
- parseSseStream,
4673
- streamSessionEvents,
6746
+ parseDeprecationNotice,
4674
6747
  streamWorkspaceControlEvents,
4675
6748
  streamWorkspaceInteractionRevisions,
4676
6749
  streamWorkspaceLiveEvents,
4677
6750
  parseWorkspaceLiveEvent,
6751
+ parseRetainedWorkspaceFileReference,
6752
+ parseSandboxFileArtifactReceipt,
4678
6753
  parseRetainedGeneratedImageReference,
4679
6754
  generatedImageSandboxPathMatches,
4680
6755
  parseGeneratedImageReceipt,
@@ -4683,4 +6758,4 @@ export {
4683
6758
  parseMediaGenerationResult,
4684
6759
  OpenGeniClient
4685
6760
  };
4686
- //# sourceMappingURL=chunk-PKQ377ED.js.map
6761
+ //# sourceMappingURL=chunk-FG3OO5LM.js.map