@opengeni/sdk 3.3.2 → 3.7.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +80 -6
  2. package/dist/artifact-client.d.ts +4 -2
  3. package/dist/artifacts.d.ts +1 -1
  4. package/dist/artifacts.js +6 -6
  5. package/dist/browser.d.ts +5 -2
  6. package/dist/browser.js +14 -4
  7. package/dist/{chunk-YXQX7RQT.js → chunk-2E2BFEEN.js} +2 -2
  8. package/dist/{chunk-JUS2UYRP.js → chunk-3QDQTYOE.js} +3 -1
  9. package/dist/chunk-3QDQTYOE.js.map +1 -0
  10. package/dist/{chunk-C2H7HBNP.js → chunk-7S2MZ65L.js} +6 -6
  11. package/dist/chunk-FMLDFJ2Q.js +246 -0
  12. package/dist/chunk-FMLDFJ2Q.js.map +1 -0
  13. package/dist/{chunk-TRNI7KEO.js → chunk-IQTEPOI3.js} +228 -26
  14. package/dist/chunk-IQTEPOI3.js.map +1 -0
  15. package/dist/chunk-IRAEPLXG.js +350 -0
  16. package/dist/chunk-IRAEPLXG.js.map +1 -0
  17. package/dist/{chunk-QT3KFVDP.js → chunk-MPGVC7EO.js} +10 -2
  18. package/dist/chunk-MPGVC7EO.js.map +1 -0
  19. package/dist/{chunk-C4DJPZRU.js → chunk-OO5LPTO7.js} +14 -1
  20. package/dist/chunk-OO5LPTO7.js.map +1 -0
  21. package/dist/{chunk-KKRO2VCP.js → chunk-QTBAMHEF.js} +2 -2
  22. package/dist/client.d.ts +51 -11
  23. package/dist/codex-realtime-controller.js +2 -2
  24. package/dist/core.d.ts +5 -2
  25. package/dist/core.js +17 -7
  26. package/dist/document-authority.js +5 -5
  27. package/dist/editable-artifacts.js +4 -4
  28. package/dist/errors.d.ts +12 -0
  29. package/dist/github-repositories.d.ts +10 -0
  30. package/dist/github-repositories.js +36 -0
  31. package/dist/github-repositories.js.map +1 -0
  32. package/dist/index.d.ts +13 -6
  33. package/dist/index.js +99 -52
  34. package/dist/index.js.map +1 -1
  35. package/dist/interaction.js +2 -2
  36. package/dist/model-context.d.ts +49 -0
  37. package/dist/model-picker-order.d.ts +1 -0
  38. package/dist/model-picker-order.js +10 -0
  39. package/dist/model-picker-order.js.map +1 -0
  40. package/dist/proxy.d.ts +7 -5
  41. package/dist/realtime.js +2 -2
  42. package/dist/session-titles.d.ts +2 -28
  43. package/dist/site.d.ts +93 -0
  44. package/dist/site.js +35 -0
  45. package/dist/site.js.map +1 -0
  46. package/dist/stream.d.ts +2 -0
  47. package/dist/tools-FSTY4FAY.js +12 -0
  48. package/dist/tools-FSTY4FAY.js.map +1 -0
  49. package/dist/tools.d.ts +61 -0
  50. package/dist/types.d.ts +231 -9
  51. package/dist/workspace-artifacts.d.ts +26 -1
  52. package/package.json +14 -2
  53. package/src/artifact-client.ts +16 -1
  54. package/src/artifacts.ts +1 -0
  55. package/src/browser.ts +16 -0
  56. package/src/client.ts +332 -22
  57. package/src/core.ts +16 -0
  58. package/src/errors.ts +23 -0
  59. package/src/github-repositories.ts +60 -0
  60. package/src/index.ts +94 -1
  61. package/src/model-context.ts +69 -0
  62. package/src/model-picker-order.ts +6 -0
  63. package/src/proxy.ts +17 -6
  64. package/src/session-titles.ts +8 -82
  65. package/src/site.ts +544 -0
  66. package/src/stream.ts +29 -8
  67. package/src/tools.ts +396 -0
  68. package/src/types.ts +287 -10
  69. package/src/workspace-artifacts.ts +33 -2
  70. package/dist/chunk-C4DJPZRU.js.map +0 -1
  71. package/dist/chunk-JUS2UYRP.js.map +0 -1
  72. package/dist/chunk-QT3KFVDP.js.map +0 -1
  73. package/dist/chunk-TRNI7KEO.js.map +0 -1
  74. /package/dist/{chunk-YXQX7RQT.js.map → chunk-2E2BFEEN.js.map} +0 -0
  75. /package/dist/{chunk-C2H7HBNP.js.map → chunk-7S2MZ65L.js.map} +0 -0
  76. /package/dist/{chunk-KKRO2VCP.js.map → chunk-QTBAMHEF.js.map} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { OpenGeniDocumentAuthorityClient } from "./document-authority-client";
2
+ import type { FetchResponse } from "./client";
2
3
  import type {
3
4
  CreateEditableArtifactMaterializationRequest,
4
5
  CreateEditableArtifactResourceRequest,
@@ -16,6 +17,7 @@ import type {
16
17
  CreateWorkspaceArtifactRequest,
17
18
  PublishWorkspaceArtifactVersionRequest,
18
19
  RollbackWorkspaceArtifactRequest,
20
+ SetWorkspaceArtifactStatusRequest,
19
21
  WorkspaceArtifactContentResponse,
20
22
  WorkspaceArtifactDetailResponse,
21
23
  WorkspaceArtifactListOptions,
@@ -132,7 +134,7 @@ export class OpenGeniClient extends OpenGeniDocumentAuthorityClient {
132
134
  artifactId: string,
133
135
  jobId: string,
134
136
  options: ReadEditableArtifactMaterializationOptions,
135
- ): Promise<Response> {
137
+ ): Promise<FetchResponse> {
136
138
  return await this.requestResponse(
137
139
  "GET",
138
140
  `/v1/workspaces/${encodeURIComponent(workspaceId)}/editable-artifacts/${encodeURIComponent(artifactId)}/materializations/${encodeURIComponent(jobId)}/download`,
@@ -148,6 +150,7 @@ export class OpenGeniClient extends OpenGeniDocumentAuthorityClient {
148
150
  const query = new URLSearchParams();
149
151
  if (options.limit !== undefined) query.set("limit", String(options.limit));
150
152
  if (options.cursor) query.set("cursor", options.cursor);
153
+ if (options.status) query.set("status", options.status);
151
154
  const suffix = query.size > 0 ? `?${query.toString()}` : "";
152
155
  return await this.requestJson<WorkspaceArtifactListResponse>(
153
156
  "GET",
@@ -211,4 +214,16 @@ export class OpenGeniClient extends OpenGeniDocumentAuthorityClient {
211
214
  request,
212
215
  );
213
216
  }
217
+
218
+ async setWorkspaceArtifactStatus(
219
+ workspaceId: string,
220
+ artifactId: string,
221
+ request: SetWorkspaceArtifactStatusRequest,
222
+ ): Promise<WorkspaceArtifactMutationResponse> {
223
+ return await this.requestJson<WorkspaceArtifactMutationResponse>(
224
+ "PATCH",
225
+ `/v1/workspaces/${workspaceId}/published-artifacts/${encodeURIComponent(artifactId)}/status`,
226
+ request,
227
+ );
228
+ }
214
229
  }
package/src/artifacts.ts CHANGED
@@ -16,6 +16,7 @@ export type {
16
16
  } from "./editable-artifact-resources";
17
17
  export type {
18
18
  FetchLike,
19
+ FetchResponse,
19
20
  GetSessionOptions,
20
21
  OpenGeniClientOptions,
21
22
  OpenGeniRequestOptions,
package/src/browser.ts CHANGED
@@ -1,7 +1,21 @@
1
1
  /** Browser-console client. Optional SDK surfaces must not enter this eager graph. */
2
2
  export { OpenGeniClient as OpenGeniBrowserClient } from "./client";
3
+ export {
4
+ OpenGeniToolCallError,
5
+ OpenGeniToolReapprovalRequiredError,
6
+ OpenGeniToolsClient,
7
+ } from "./tools";
8
+ export type {
9
+ OpenGeniGeneratedTools,
10
+ OpenGeniDynamicToolNode,
11
+ OpenGeniToolCallOptions,
12
+ OpenGeniToolFunction,
13
+ OpenGeniToolsFacade,
14
+ OpenGeniWorkspaceTools,
15
+ } from "./tools";
3
16
  export type {
4
17
  FetchLike,
18
+ FetchResponse,
5
19
  GetSessionOptions,
6
20
  OpenGeniClientOptions,
7
21
  OpenGeniRequestOptions,
@@ -13,9 +27,11 @@ export type {
13
27
  export {
14
28
  OpenGeniApiContractMismatchError,
15
29
  OpenGeniApiError,
30
+ OpenGeniSecureContextRequiredError,
16
31
  OpenGeniSessionListCursorError,
17
32
  OpenGeniStreamError,
18
33
  isRetryableStreamError,
19
34
  } from "./errors";
35
+ export type { OpenGeniSecureContextRequiredReason } from "./errors";
20
36
  export { resolveWorkspaceVoiceInputEnabled } from "./transcription";
21
37
  export { OPENGENI_API_CONTRACT_HEADER, OPENGENI_API_CONTRACT_REVISION } from "./types";
package/src/client.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  import {
2
2
  OpenGeniApiContractMismatchError,
3
3
  OpenGeniApiError,
4
+ OpenGeniSecureContextRequiredError,
4
5
  OpenGeniSessionListCursorError,
5
6
  } from "./errors";
7
+ import type { OpenGeniToolsFacade, OpenGeniToolTransport, OpenGeniWorkspaceTools } from "./tools";
6
8
  import {
7
9
  streamSessionEvents,
8
10
  type SessionEventStreamTransport,
9
11
  type StreamSessionEventsOptions,
10
12
  } from "./stream";
13
+ import type { SessionModelContextResponse } from "./model-context";
11
14
  import {
12
15
  streamWorkspaceControlEvents,
13
16
  type WorkspaceControlStreamTransport,
@@ -169,6 +172,22 @@ import type {
169
172
  ClientConfig,
170
173
  WorkspaceModelAccessPolicy,
171
174
  WorkspaceModelCatalogResponse,
175
+ WorkspaceGatewayCustomModel,
176
+ WorkspaceGatewayCustomModelsResponse,
177
+ CreateWorkspaceGatewayCustomModelRequest,
178
+ DeleteWorkspaceGatewayCustomModelRequest,
179
+ WorkspaceOpenRouterCustomModel,
180
+ WorkspaceOpenRouterCustomModelsResponse,
181
+ CreateWorkspaceOpenRouterCustomModelRequest,
182
+ DeleteWorkspaceOpenRouterCustomModelRequest,
183
+ OrganizationModelProviderKind,
184
+ OrganizationModelProviderConnection,
185
+ UpsertOrganizationModelProviderConnectionRequest,
186
+ RevokeOrganizationModelProviderConnectionRequest,
187
+ OrganizationProviderCustomModel,
188
+ OrganizationProviderCustomModelsResponse,
189
+ CreateOrganizationProviderCustomModelRequest,
190
+ DeleteOrganizationProviderCustomModelRequest,
172
191
  WorkspaceRealtimeModelCatalogResponse,
173
192
  ClientSessionEventInput,
174
193
  UserMessageEventInput,
@@ -261,6 +280,8 @@ import type {
261
280
  AcceptOrganizationRecoveryCustodyRequest,
262
281
  ConfigureOrganizationRecoveryPolicyRequest,
263
282
  CreateOrganizationInvitationRequest,
283
+ CreateAdditionalOrganizationRequest,
284
+ CreateAdditionalOrganizationResponse,
264
285
  CreateOrganizationRequest,
265
286
  CreateOrganizationResponse,
266
287
  CreateOrganizationWorkspaceRequest,
@@ -563,7 +584,22 @@ function sessionListQuery(options: {
563
584
  };
564
585
  }
565
586
 
566
- export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
587
+ /**
588
+ * Web-standard fetch response accepted by the SDK.
589
+ *
590
+ * The project global `Response` type includes Bun's non-standard `textStream()`
591
+ * method and the newer `bytes()` method. Fetch implementations such as Expo do
592
+ * not necessarily provide either member, and the SDK does not use them, so
593
+ * they must not be part of the adapter boundary.
594
+ */
595
+ export type FetchResponse = Omit<Response, "bytes" | "clone" | "textStream"> & {
596
+ clone(): FetchResponse;
597
+ };
598
+
599
+ export type FetchLike = (
600
+ input: string | URL | Request,
601
+ init?: RequestInit,
602
+ ) => Promise<FetchResponse>;
567
603
 
568
604
  export type WorkspaceControlEventPage = {
569
605
  events: WorkspaceControlEvent[];
@@ -740,6 +776,46 @@ function normalizeScheduledTaskMachineTarget<
740
776
  * WHATWG `fetch` + streams, so it runs in Node 18+, Bun, Deno, browsers, and
741
777
  * edge runtimes.
742
778
  */
779
+ function createLazyToolsFacade(transport: OpenGeniToolTransport): OpenGeniToolsFacade {
780
+ return {
781
+ forWorkspace(workspaceId: string): OpenGeniWorkspaceTools {
782
+ const normalizedWorkspaceId = workspaceId.trim();
783
+ if (!normalizedWorkspaceId) throw new TypeError("workspaceId is required");
784
+ let workspaceTools: Promise<OpenGeniWorkspaceTools> | undefined;
785
+ const load = (): Promise<OpenGeniWorkspaceTools> =>
786
+ (workspaceTools ??= import("./tools").then(({ OpenGeniToolsClient }) =>
787
+ new OpenGeniToolsClient(transport).forWorkspace(normalizedWorkspaceId),
788
+ ));
789
+ const node = (path: readonly string[]): OpenGeniWorkspaceTools =>
790
+ new Proxy(
791
+ (async (...args: unknown[]) => {
792
+ let target: unknown = await load();
793
+ for (const segment of path) {
794
+ target = (target as Record<string, unknown>)[segment];
795
+ }
796
+ if (typeof target !== "function")
797
+ throw new TypeError("OpenGeni tool path is not callable");
798
+ return await Reflect.apply(target, undefined, args);
799
+ }) as unknown as OpenGeniWorkspaceTools,
800
+ {
801
+ get: (_target, property) => {
802
+ if (property === "then") return undefined;
803
+ if (typeof property !== "string") return undefined;
804
+ return node([...path, property]);
805
+ },
806
+ },
807
+ );
808
+ return new Proxy(Object.create(null) as OpenGeniWorkspaceTools, {
809
+ get: (_target, property) => {
810
+ if (property === "then") return undefined;
811
+ if (typeof property !== "string") return undefined;
812
+ return node([property]);
813
+ },
814
+ });
815
+ },
816
+ };
817
+ }
818
+
743
819
  export class OpenGeniClient {
744
820
  private readonly baseUrl: string;
745
821
  private readonly options: OpenGeniClientOptions;
@@ -750,6 +826,8 @@ export class OpenGeniClient {
750
826
  private readonly queued = new Map<string, SingleFlightReadEntry>();
751
827
  /** Resource-oriented Browser/Computer facade over this exact authenticated client. */
752
828
  readonly interaction: OpenGeniInteractionClient;
829
+ /** Dynamic typed tool facade backed by the canonical workspace gateway. */
830
+ readonly tools: OpenGeniToolsFacade;
753
831
 
754
832
  constructor(options: OpenGeniClientOptions) {
755
833
  this.baseUrl = options.baseUrl.replace(/\/+$/, "");
@@ -762,6 +840,7 @@ export class OpenGeniClient {
762
840
  }
763
841
  this.sessionCommandTimeoutMs = sessionCommandTimeoutMs;
764
842
  this.interaction = new OpenGeniInteractionClient(this);
843
+ this.tools = createLazyToolsFacade(this);
765
844
  }
766
845
 
767
846
  // --- Session lifecycle ---------------------------------------------------
@@ -789,7 +868,7 @@ export class OpenGeniClient {
789
868
  if (input.durationSeconds !== undefined) {
790
869
  form.append("durationSeconds", String(input.durationSeconds));
791
870
  }
792
- let response: Response;
871
+ let response: FetchResponse;
793
872
  try {
794
873
  response = await this.fetchImpl(this.url(`/v1/workspaces/${workspaceId}/transcriptions`), {
795
874
  method: "POST",
@@ -888,7 +967,7 @@ export class OpenGeniClient {
888
967
  input: UploadTranscriptionRecordingChunkInput,
889
968
  ): Promise<UploadTranscriptionRecordingChunkResponse> {
890
969
  const correlationId = crypto.randomUUID();
891
- let response: Response;
970
+ let response: FetchResponse;
892
971
  try {
893
972
  response = await this.fetchImpl(
894
973
  this.url(
@@ -1030,6 +1109,17 @@ export class OpenGeniClient {
1030
1109
  );
1031
1110
  }
1032
1111
 
1112
+ /** Exact model-visible prefix captured from the latest provider request. */
1113
+ async getSessionModelContext(
1114
+ workspaceId: string,
1115
+ sessionId: string,
1116
+ ): Promise<SessionModelContextResponse> {
1117
+ return await this.requestJson<SessionModelContextResponse>(
1118
+ "GET",
1119
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/model-context`,
1120
+ );
1121
+ }
1122
+
1033
1123
  async updateSession(
1034
1124
  workspaceId: string,
1035
1125
  sessionId: string,
@@ -1639,7 +1729,11 @@ export class OpenGeniClient {
1639
1729
  async listTurns(
1640
1730
  workspaceId: string,
1641
1731
  sessionId: string,
1642
- options: { limit?: number; latestStarted?: boolean; signal?: AbortSignal | undefined } = {},
1732
+ options: {
1733
+ limit?: number;
1734
+ latestStarted?: boolean;
1735
+ signal?: AbortSignal | undefined;
1736
+ } = {},
1643
1737
  ): Promise<SessionTurn[]> {
1644
1738
  return await this.requestJson<SessionTurn[]>(
1645
1739
  "GET",
@@ -4045,6 +4139,172 @@ export class OpenGeniClient {
4045
4139
  );
4046
4140
  }
4047
4141
 
4142
+ /** List workspace-owned unpinned Vercel AI Gateway model slugs. */
4143
+ async listWorkspaceGatewayCustomModels(
4144
+ workspaceId: string,
4145
+ ): Promise<WorkspaceGatewayCustomModelsResponse> {
4146
+ return await this.requestJson<WorkspaceGatewayCustomModelsResponse>(
4147
+ "GET",
4148
+ `/v1/workspaces/${workspaceId}/gateway-custom-models`,
4149
+ );
4150
+ }
4151
+
4152
+ /** Add one exact upstream Vercel AI Gateway slug. */
4153
+ async createWorkspaceGatewayCustomModel(
4154
+ workspaceId: string,
4155
+ request: CreateWorkspaceGatewayCustomModelRequest,
4156
+ ): Promise<WorkspaceGatewayCustomModel> {
4157
+ return await this.requestJson<WorkspaceGatewayCustomModel>(
4158
+ "POST",
4159
+ `/v1/workspaces/${workspaceId}/gateway-custom-models`,
4160
+ request,
4161
+ );
4162
+ }
4163
+
4164
+ /** Remove one workspace custom Gateway model by its stable row id. */
4165
+ async deleteWorkspaceGatewayCustomModel(
4166
+ workspaceId: string,
4167
+ customModelId: string,
4168
+ request: DeleteWorkspaceGatewayCustomModelRequest,
4169
+ ): Promise<void> {
4170
+ if (
4171
+ !/^[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(
4172
+ customModelId,
4173
+ )
4174
+ ) {
4175
+ throw new TypeError("customModelId must be a UUID");
4176
+ }
4177
+ await this.requestVoid(
4178
+ "DELETE",
4179
+ `/v1/workspaces/${workspaceId}/gateway-custom-models/${encodeURIComponent(customModelId)}`,
4180
+ request,
4181
+ );
4182
+ }
4183
+
4184
+ /** List workspace-owned unpinned OpenRouter model slugs. */
4185
+ async listWorkspaceOpenRouterCustomModels(
4186
+ workspaceId: string,
4187
+ ): Promise<WorkspaceOpenRouterCustomModelsResponse> {
4188
+ return await this.requestJson<WorkspaceOpenRouterCustomModelsResponse>(
4189
+ "GET",
4190
+ `/v1/workspaces/${workspaceId}/openrouter-custom-models`,
4191
+ );
4192
+ }
4193
+
4194
+ /** Add one exact upstream OpenRouter slug. */
4195
+ async createWorkspaceOpenRouterCustomModel(
4196
+ workspaceId: string,
4197
+ request: CreateWorkspaceOpenRouterCustomModelRequest,
4198
+ ): Promise<WorkspaceOpenRouterCustomModel> {
4199
+ return await this.requestJson<WorkspaceOpenRouterCustomModel>(
4200
+ "POST",
4201
+ `/v1/workspaces/${workspaceId}/openrouter-custom-models`,
4202
+ request,
4203
+ );
4204
+ }
4205
+
4206
+ /** Remove one workspace custom OpenRouter model by its stable row id. */
4207
+ async deleteWorkspaceOpenRouterCustomModel(
4208
+ workspaceId: string,
4209
+ customModelId: string,
4210
+ request: DeleteWorkspaceOpenRouterCustomModelRequest,
4211
+ ): Promise<void> {
4212
+ if (
4213
+ !/^[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(
4214
+ customModelId,
4215
+ )
4216
+ ) {
4217
+ throw new TypeError("customModelId must be a UUID");
4218
+ }
4219
+ await this.requestVoid(
4220
+ "DELETE",
4221
+ `/v1/workspaces/${workspaceId}/openrouter-custom-models/${encodeURIComponent(customModelId)}`,
4222
+ request,
4223
+ );
4224
+ }
4225
+
4226
+ /** Read metadata for one organization-owned model-provider connection. */
4227
+ async getOrganizationModelProviderConnection(
4228
+ organizationId: string,
4229
+ providerKind: OrganizationModelProviderKind,
4230
+ ): Promise<OrganizationModelProviderConnection | null> {
4231
+ return await this.requestJson<OrganizationModelProviderConnection | null>(
4232
+ "GET",
4233
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}`,
4234
+ );
4235
+ }
4236
+
4237
+ /** Connect or rotate one organization-owned provider credential. */
4238
+ async upsertOrganizationModelProviderConnection(
4239
+ organizationId: string,
4240
+ providerKind: OrganizationModelProviderKind,
4241
+ request: UpsertOrganizationModelProviderConnectionRequest,
4242
+ ): Promise<OrganizationModelProviderConnection> {
4243
+ return await this.requestJson<OrganizationModelProviderConnection>(
4244
+ "PUT",
4245
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}`,
4246
+ request,
4247
+ );
4248
+ }
4249
+
4250
+ /** Revoke one organization-owned provider credential. */
4251
+ async revokeOrganizationModelProviderConnection(
4252
+ organizationId: string,
4253
+ providerKind: OrganizationModelProviderKind,
4254
+ request: RevokeOrganizationModelProviderConnectionRequest,
4255
+ ): Promise<OrganizationModelProviderConnection> {
4256
+ return await this.requestJson<OrganizationModelProviderConnection>(
4257
+ "DELETE",
4258
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}`,
4259
+ request,
4260
+ );
4261
+ }
4262
+
4263
+ /** List organization-owned exact upstream model slugs. */
4264
+ async listOrganizationProviderCustomModels(
4265
+ organizationId: string,
4266
+ providerKind: OrganizationModelProviderKind,
4267
+ ): Promise<OrganizationProviderCustomModelsResponse> {
4268
+ return await this.requestJson<OrganizationProviderCustomModelsResponse>(
4269
+ "GET",
4270
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}/custom-models`,
4271
+ );
4272
+ }
4273
+
4274
+ /** Add one organization-owned exact upstream model slug. */
4275
+ async createOrganizationProviderCustomModel(
4276
+ organizationId: string,
4277
+ providerKind: OrganizationModelProviderKind,
4278
+ request: CreateOrganizationProviderCustomModelRequest,
4279
+ ): Promise<OrganizationProviderCustomModel> {
4280
+ return await this.requestJson<OrganizationProviderCustomModel>(
4281
+ "POST",
4282
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}/custom-models`,
4283
+ request,
4284
+ );
4285
+ }
4286
+
4287
+ /** Retire one organization-owned custom model. */
4288
+ async deleteOrganizationProviderCustomModel(
4289
+ organizationId: string,
4290
+ providerKind: OrganizationModelProviderKind,
4291
+ customModelId: string,
4292
+ request: DeleteOrganizationProviderCustomModelRequest,
4293
+ ): Promise<OrganizationProviderCustomModel> {
4294
+ if (
4295
+ !/^[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(
4296
+ customModelId,
4297
+ )
4298
+ ) {
4299
+ throw new TypeError("customModelId must be a UUID");
4300
+ }
4301
+ return await this.requestJson<OrganizationProviderCustomModel>(
4302
+ "DELETE",
4303
+ `/v1/organizations/${organizationId}/model-providers/${providerKind}/custom-models/${encodeURIComponent(customModelId)}`,
4304
+ request,
4305
+ );
4306
+ }
4307
+
4048
4308
  /** Read the workspace's hard provider/model allowlist. */
4049
4309
  async getWorkspaceModelAccessPolicy(workspaceId: string): Promise<WorkspaceModelAccessPolicy> {
4050
4310
  return await this.requestJson<WorkspaceModelAccessPolicy>(
@@ -4140,6 +4400,17 @@ export class OpenGeniClient {
4140
4400
  return await this.requestJson<CreateOrganizationResponse>("POST", "/v1/organizations", request);
4141
4401
  }
4142
4402
 
4403
+ /** Create another organization owned by the current managed human. */
4404
+ async createAdditionalOrganization(
4405
+ request: CreateAdditionalOrganizationRequest,
4406
+ ): Promise<CreateAdditionalOrganizationResponse> {
4407
+ return await this.requestJson<CreateAdditionalOrganizationResponse>(
4408
+ "POST",
4409
+ "/v1/organizations/additional",
4410
+ request,
4411
+ );
4412
+ }
4413
+
4143
4414
  /** Pending and historical invitations addressed to the current managed human. */
4144
4415
  async listOrganizationInvitations(
4145
4416
  options: { cursor?: string; limit?: number } = {},
@@ -4229,7 +4500,7 @@ export class OpenGeniClient {
4229
4500
  );
4230
4501
  }
4231
4502
 
4232
- /** Create a shared workspace without implicitly granting the actor access. */
4503
+ /** Create a shared workspace and grant its creator explicit workspace-admin access. */
4233
4504
  async createOrganizationWorkspace(
4234
4505
  organizationId: string,
4235
4506
  request: CreateOrganizationWorkspaceRequest,
@@ -4266,6 +4537,14 @@ export class OpenGeniClient {
4266
4537
  );
4267
4538
  }
4268
4539
 
4540
+ /** Delete a shared workspace through organization-administrator authority. */
4541
+ async deleteOrganizationWorkspace(organizationId: string, workspaceId: string): Promise<void> {
4542
+ await this.requestVoid(
4543
+ "DELETE",
4544
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}`,
4545
+ );
4546
+ }
4547
+
4269
4548
  async putOrganizationWorkspaceMember(
4270
4549
  organizationId: string,
4271
4550
  workspaceId: string,
@@ -4594,11 +4873,13 @@ export class OpenGeniClient {
4594
4873
  async createWorkspaceInstructionPolicyDraft(
4595
4874
  workspaceId: string,
4596
4875
  request: CreateWorkspaceInstructionPolicyDraftRequest,
4876
+ options: OpenGeniRequestOptions = {},
4597
4877
  ): Promise<WorkspaceInstructionPolicyRevision> {
4598
- return await this.requestJson<WorkspaceInstructionPolicyRevision>(
4878
+ return await this.requestSessionCommand<WorkspaceInstructionPolicyRevision>(
4599
4879
  "POST",
4600
4880
  `/v1/workspaces/${workspaceId}/instruction-policies/drafts`,
4601
4881
  request,
4882
+ options,
4602
4883
  );
4603
4884
  }
4604
4885
 
@@ -4658,11 +4939,13 @@ export class OpenGeniClient {
4658
4939
  workspaceId: string,
4659
4940
  revisionId: string,
4660
4941
  request: ActivateWorkspaceInstructionPolicyRequest,
4942
+ options: OpenGeniRequestOptions = {},
4661
4943
  ): Promise<WorkspaceInstructionPolicyActivationResponse> {
4662
- return await this.requestJson<WorkspaceInstructionPolicyActivationResponse>(
4944
+ return await this.requestSessionCommand<WorkspaceInstructionPolicyActivationResponse>(
4663
4945
  "POST",
4664
4946
  `/v1/workspaces/${workspaceId}/instruction-policies/${encodeURIComponent(revisionId)}/activate`,
4665
4947
  request,
4948
+ options,
4666
4949
  );
4667
4950
  }
4668
4951
 
@@ -5478,6 +5761,7 @@ export class OpenGeniClient {
5478
5761
  ) {
5479
5762
  throw new Error("File upload timeout must be a positive number");
5480
5763
  }
5764
+ assertBrowserFileUploadSecureContext();
5481
5765
  const withTimeout = async <T>(
5482
5766
  timeoutMs: number,
5483
5767
  operation: (signal: AbortSignal) => Promise<T>,
@@ -7360,7 +7644,7 @@ export class OpenGeniClient {
7360
7644
  const correlationId = crypto.randomUUID();
7361
7645
  const abort = requestAbortSignal(options);
7362
7646
  try {
7363
- let response: Response;
7647
+ let response: FetchResponse;
7364
7648
  try {
7365
7649
  response = await awaitWithAbort(
7366
7650
  this.fetchImpl(this.url(path, query), {
@@ -7383,14 +7667,18 @@ export class OpenGeniClient {
7383
7667
  throw error;
7384
7668
  }
7385
7669
  assertApiContractResponse(response);
7386
- if (!response.ok) {
7387
- throw await apiErrorFromResponse(response, { method, correlationId });
7388
- }
7389
- await assertJsonResponse(response, { method, correlationId });
7390
7670
  try {
7391
- return (await response.json()) as T;
7671
+ if (!response.ok) {
7672
+ throw await awaitWithAbort(
7673
+ apiErrorFromResponse(response, { method, correlationId }),
7674
+ abort.signal,
7675
+ );
7676
+ }
7677
+ await awaitWithAbort(assertJsonResponse(response, { method, correlationId }), abort.signal);
7678
+ return (await awaitWithAbort(response.json(), abort.signal)) as T;
7392
7679
  } catch (error) {
7393
7680
  if (options.signal?.aborted) throw error;
7681
+ if (error instanceof OpenGeniApiError) throw error;
7394
7682
  if (isMutationMethod(method)) {
7395
7683
  throw mutationTransportError(correlationId);
7396
7684
  }
@@ -7407,9 +7695,9 @@ export class OpenGeniClient {
7407
7695
  path: string,
7408
7696
  query: Record<string, string> = {},
7409
7697
  options: OpenGeniRequestOptions = {},
7410
- ): Promise<Response> {
7698
+ ): Promise<FetchResponse> {
7411
7699
  const correlationId = crypto.randomUUID();
7412
- let response: Response;
7700
+ let response: FetchResponse;
7413
7701
  try {
7414
7702
  response = await this.fetchImpl(this.url(path, query), {
7415
7703
  method,
@@ -7433,7 +7721,7 @@ export class OpenGeniClient {
7433
7721
  /** Contract-checked transport shared by opt-in typed SDK clients for 204 responses. */
7434
7722
  async requestVoid(method: string, path: string, body?: unknown): Promise<void> {
7435
7723
  const correlationId = crypto.randomUUID();
7436
- let response: Response;
7724
+ let response: FetchResponse;
7437
7725
  try {
7438
7726
  response = await this.fetchImpl(this.url(path), {
7439
7727
  method,
@@ -7457,7 +7745,7 @@ export class OpenGeniClient {
7457
7745
  }
7458
7746
  }
7459
7747
 
7460
- function assertApiContractResponse(response: Response): void {
7748
+ function assertApiContractResponse(response: FetchResponse): void {
7461
7749
  const actual = response.headers.get(OPENGENI_API_CONTRACT_HEADER);
7462
7750
  if (actual && actual !== OPENGENI_API_CONTRACT_REVISION) {
7463
7751
  throw new OpenGeniApiContractMismatchError(OPENGENI_API_CONTRACT_REVISION, actual);
@@ -7640,7 +7928,7 @@ type ApiErrorRequestContext = {
7640
7928
  };
7641
7929
 
7642
7930
  async function apiErrorFromResponse(
7643
- response: Response,
7931
+ response: FetchResponse,
7644
7932
  context: ApiErrorRequestContext,
7645
7933
  ): Promise<OpenGeniApiError> {
7646
7934
  return new OpenGeniApiError(response.status, await readBoundedJsonErrorBody(response), {
@@ -7650,7 +7938,7 @@ async function apiErrorFromResponse(
7650
7938
  }
7651
7939
 
7652
7940
  async function assertJsonResponse(
7653
- response: Response,
7941
+ response: FetchResponse,
7654
7942
  context: ApiErrorRequestContext,
7655
7943
  ): Promise<void> {
7656
7944
  if (isJsonContentType(response.headers.get("content-type"))) return;
@@ -7664,7 +7952,7 @@ async function assertJsonResponse(
7664
7952
  });
7665
7953
  }
7666
7954
 
7667
- async function readBoundedJsonErrorBody(response: Response): Promise<string> {
7955
+ async function readBoundedJsonErrorBody(response: FetchResponse): Promise<string> {
7668
7956
  if (!isJsonContentType(response.headers.get("content-type"))) {
7669
7957
  await cancelResponseBody(response, "discarding API error body");
7670
7958
  return "";
@@ -7701,6 +7989,28 @@ function mutationTransportError(correlationId: string): OpenGeniApiError {
7701
7989
  });
7702
7990
  }
7703
7991
 
7992
+ function assertBrowserFileUploadSecureContext(): void {
7993
+ const secureContext =
7994
+ typeof window !== "undefined"
7995
+ ? window.isSecureContext
7996
+ : typeof globalThis.isSecureContext === "boolean"
7997
+ ? globalThis.isSecureContext
7998
+ : undefined;
7999
+ // The framework-agnostic SDK also runs in Node, Bun, Deno, and edge
8000
+ // runtimes. Preserve their existing upload behavior; this typed HTTPS error
8001
+ // is only meaningful where the browser exposes a secure-context state.
8002
+ if (secureContext === undefined) return;
8003
+ if (!secureContext) {
8004
+ throw new OpenGeniSecureContextRequiredError("insecure_context");
8005
+ }
8006
+ if (
8007
+ typeof globalThis.crypto === "undefined" ||
8008
+ typeof globalThis.crypto.subtle?.digest !== "function"
8009
+ ) {
8010
+ throw new OpenGeniSecureContextRequiredError("web_crypto_unavailable");
8011
+ }
8012
+ }
8013
+
7704
8014
  async function sha256ForUpload(body: Blob | ArrayBuffer | string): Promise<string> {
7705
8015
  const bytes =
7706
8016
  typeof body === "string"
@@ -7742,7 +8052,7 @@ function computerFrameEvidenceMismatchReason(
7742
8052
  return null;
7743
8053
  }
7744
8054
 
7745
- async function cancelResponseBody(response: Response, reason: string): Promise<void> {
8055
+ async function cancelResponseBody(response: FetchResponse, reason: string): Promise<void> {
7746
8056
  await response.body?.cancel(reason).catch(() => undefined);
7747
8057
  }
7748
8058
 
@@ -7811,7 +8121,7 @@ function parseBoundedContentLength(value: string | null): number | null {
7811
8121
  }
7812
8122
 
7813
8123
  async function readBoundedResponseBytes(
7814
- response: Response,
8124
+ response: FetchResponse,
7815
8125
  maxBytes: number,
7816
8126
  expectedBytes: number | null,
7817
8127
  ): Promise<Uint8Array> {
package/src/core.ts CHANGED
@@ -1,7 +1,21 @@
1
1
  /** Backward-compatible non-artifact client surface. */
2
2
  export { OpenGeniDocumentAuthorityClient as OpenGeniCoreClient } from "./document-authority-client";
3
+ export {
4
+ OpenGeniToolCallError,
5
+ OpenGeniToolReapprovalRequiredError,
6
+ OpenGeniToolsClient,
7
+ } from "./tools";
8
+ export type {
9
+ OpenGeniGeneratedTools,
10
+ OpenGeniDynamicToolNode,
11
+ OpenGeniToolCallOptions,
12
+ OpenGeniToolFunction,
13
+ OpenGeniToolsFacade,
14
+ OpenGeniWorkspaceTools,
15
+ } from "./tools";
3
16
  export type {
4
17
  FetchLike,
18
+ FetchResponse,
5
19
  GetSessionOptions,
6
20
  OpenGeniClientOptions,
7
21
  OpenGeniRequestOptions,
@@ -13,9 +27,11 @@ export type {
13
27
  export {
14
28
  OpenGeniApiContractMismatchError,
15
29
  OpenGeniApiError,
30
+ OpenGeniSecureContextRequiredError,
16
31
  OpenGeniSessionListCursorError,
17
32
  OpenGeniStreamError,
18
33
  isRetryableStreamError,
19
34
  } from "./errors";
35
+ export type { OpenGeniSecureContextRequiredReason } from "./errors";
20
36
  export { resolveWorkspaceVoiceInputEnabled } from "./transcription";
21
37
  export { OPENGENI_API_CONTRACT_HEADER, OPENGENI_API_CONTRACT_REVISION } from "./types";