@opengeni/sdk 1.0.1 → 2.3.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 (92) hide show
  1. package/README.md +117 -2
  2. package/dist/artifacts.js +5 -5
  3. package/dist/automations-client.d.ts +17 -0
  4. package/dist/automations.d.ts +3 -0
  5. package/dist/automations.js +78 -0
  6. package/dist/automations.js.map +1 -0
  7. package/dist/{chunk-YGH5P47G.js → chunk-6IPZY27S.js} +744 -57
  8. package/dist/chunk-6IPZY27S.js.map +1 -0
  9. package/dist/{chunk-TYZ4JL4J.js → chunk-AGUKZAXR.js} +2 -2
  10. package/dist/{chunk-A5DC5WEM.js → chunk-C2H7HBNP.js} +22 -2
  11. package/dist/chunk-C2H7HBNP.js.map +1 -0
  12. package/dist/{chunk-GU6JF75T.js → chunk-C4DJPZRU.js} +1 -1
  13. package/dist/{chunk-GU6JF75T.js.map → chunk-C4DJPZRU.js.map} +1 -1
  14. package/dist/{chunk-ST5DDKJP.js → chunk-GW3EJ2GP.js} +52 -1
  15. package/dist/chunk-GW3EJ2GP.js.map +1 -0
  16. package/dist/{chunk-4DV37UUA.js → chunk-TW5MNHUX.js} +16 -2
  17. package/dist/chunk-TW5MNHUX.js.map +1 -0
  18. package/dist/{chunk-VWE2QIVO.js → chunk-XNG7YGR3.js} +23 -6
  19. package/dist/chunk-XNG7YGR3.js.map +1 -0
  20. package/dist/client.d.ts +159 -26
  21. package/dist/codex-realtime-controller.d.ts +1 -0
  22. package/dist/codex-realtime-controller.js +2 -2
  23. package/dist/company-brain.d.ts +32 -0
  24. package/dist/company-profile.d.ts +1 -1
  25. package/dist/core.js +4 -4
  26. package/dist/editable-artifacts/browser-session.d.ts +7 -3
  27. package/dist/editable-artifacts/controller.d.ts +4 -1
  28. package/dist/editable-artifacts/errors.d.ts +1 -1
  29. package/dist/editable-artifacts/http-live-transport.d.ts +6 -2
  30. package/dist/editable-artifacts/index.d.ts +2 -0
  31. package/dist/editable-artifacts/open-failure.d.ts +9 -0
  32. package/dist/editable-artifacts/types.d.ts +4 -3
  33. package/dist/editable-artifacts/worker/kernel-adapter.d.ts +1 -1
  34. package/dist/editable-artifacts-worker.js +44 -17
  35. package/dist/editable-artifacts-worker.js.map +1 -1
  36. package/dist/editable-artifacts.js +222 -119
  37. package/dist/editable-artifacts.js.map +1 -1
  38. package/dist/errors.d.ts +1 -1
  39. package/dist/index.d.ts +7 -4
  40. package/dist/index.js +61 -12
  41. package/dist/index.js.map +1 -1
  42. package/dist/interaction.d.ts +23 -0
  43. package/dist/interaction.js +4 -1
  44. package/dist/organization-private-session-settings.d.ts +6 -0
  45. package/dist/organization-private-session-settings.js +22 -0
  46. package/dist/organization-private-session-settings.js.map +1 -0
  47. package/dist/pr-review-client.d.ts +15 -0
  48. package/dist/pr-review.d.ts +4 -0
  49. package/dist/pr-review.js +56 -0
  50. package/dist/pr-review.js.map +1 -0
  51. package/dist/preference-registry.d.ts +8 -0
  52. package/dist/realtime.js +2 -2
  53. package/dist/retained-artifacts.d.ts +5 -1
  54. package/dist/types.d.ts +1023 -13
  55. package/dist/workspace-instruction-policies.d.ts +22 -0
  56. package/dist/workspace-learning.d.ts +124 -0
  57. package/package.json +14 -2
  58. package/src/automations-client.ts +118 -0
  59. package/src/automations.ts +15 -0
  60. package/src/client.ts +1049 -71
  61. package/src/codex-realtime-controller.ts +21 -0
  62. package/src/company-brain.ts +99 -0
  63. package/src/company-profile.ts +4 -1
  64. package/src/editable-artifacts/browser-session.ts +36 -22
  65. package/src/editable-artifacts/controller.ts +66 -45
  66. package/src/editable-artifacts/errors.ts +2 -0
  67. package/src/editable-artifacts/http-live-transport.ts +62 -37
  68. package/src/editable-artifacts/index.ts +6 -0
  69. package/src/editable-artifacts/open-failure.ts +79 -0
  70. package/src/editable-artifacts/storage.ts +31 -40
  71. package/src/editable-artifacts/types.ts +4 -3
  72. package/src/editable-artifacts/worker/kernel-adapter.ts +23 -7
  73. package/src/editable-artifacts/worker/runtime.ts +26 -13
  74. package/src/editable-artifacts/worker/wire-codec.ts +23 -5
  75. package/src/errors.ts +1 -1
  76. package/src/index.ts +134 -0
  77. package/src/interaction.ts +95 -0
  78. package/src/organization-private-session-settings.ts +33 -0
  79. package/src/pr-review-client.ts +84 -0
  80. package/src/pr-review.ts +15 -0
  81. package/src/preference-registry.ts +9 -0
  82. package/src/retained-artifacts.ts +101 -0
  83. package/src/stream.ts +13 -2
  84. package/src/types.ts +1174 -12
  85. package/src/workspace-instruction-policies.ts +24 -0
  86. package/src/workspace-learning.ts +138 -0
  87. package/dist/chunk-4DV37UUA.js.map +0 -1
  88. package/dist/chunk-A5DC5WEM.js.map +0 -1
  89. package/dist/chunk-ST5DDKJP.js.map +0 -1
  90. package/dist/chunk-VWE2QIVO.js.map +0 -1
  91. package/dist/chunk-YGH5P47G.js.map +0 -1
  92. /package/dist/{chunk-TYZ4JL4J.js.map → chunk-AGUKZAXR.js.map} +0 -0
package/src/client.ts CHANGED
@@ -163,14 +163,35 @@ import type {
163
163
  UninstallPluginResult,
164
164
  AddDocumentRequest,
165
165
  CreateKnowledgeDropRequest,
166
+ DocumentAuthorityReclassification,
167
+ DocumentDefaultCollectionBackfill,
168
+ DocumentDefaultCollectionBackfillAudit,
169
+ GetDocumentDefaultCollectionBackfillAuditOptions,
170
+ ListDocumentDefaultCollectionBackfillRunsResponse,
171
+ ListOrganizationDocumentAuthorityReclassificationsResponse,
172
+ ListDocumentAuthorityReclassificationsOptions,
173
+ ListDocumentAuthorityReclassificationsResponse,
166
174
  MoveDocumentRequest,
175
+ ReclassifyDocumentAuthorityRequest,
176
+ RunDocumentDefaultCollectionBackfillRequest,
167
177
  ClientConfig,
178
+ WorkspaceModelAccessPolicy,
168
179
  WorkspaceModelCatalogResponse,
169
180
  WorkspaceRealtimeModelCatalogResponse,
170
181
  ClientSessionEventInput,
182
+ UserMessageEventInput,
171
183
  CompactSessionContextResult,
172
184
  CompleteFileUploadResponse,
173
185
  ConnectionMetadata,
186
+ PersonalGitHubConnectionStatusResponse,
187
+ PersonalGitHubDisconnectRequest,
188
+ PersonalGitHubOAuthStartRequest,
189
+ PersonalGitHubOAuthStartResponse,
190
+ ListPersonalGitHubRepositoriesOptions,
191
+ ListPersonalGitHubRepositoriesResponse,
192
+ PersonalGitHubRepositorySelectionState,
193
+ ReplacePersonalGitHubRepositorySelectionsRequest,
194
+ VerifyPersonalGitHubRepositorySelectionsRequest,
174
195
  CreateApiKeyRequest,
175
196
  CreateApiKeyResponse,
176
197
  CreateCapabilityCatalogItemRequest,
@@ -178,11 +199,15 @@ import type {
178
199
  InstallLibrarySkillRequest,
179
200
  InstalledSkill,
180
201
  ListInstalledSkillsResponse,
202
+ CreateBillingPortalRequest,
203
+ CreateBillingPortalResponse,
181
204
  CreateCheckoutRequest,
182
205
  CreateCheckoutResponse,
183
206
  OpenGeniSlackBotInstallRequest,
184
207
  OpenGeniSlackBotInstallStart,
208
+ SlackChannelRouteListResponse,
185
209
  SlackReactionChannelListResponse,
210
+ UpdateSlackChannelRoutesRequest,
186
211
  FikenInstallRequest,
187
212
  FikenOAuthStartRequest,
188
213
  FikenOAuthStartResponse,
@@ -201,6 +226,7 @@ import type {
201
226
  CreateWorkspaceRequest,
202
227
  // Enrollment UX (design 11): the click-Grant approve-page lookup/deny + headless
203
228
  // enroll-token mint.
229
+ DeviceEnrollmentApproveRequest,
204
230
  DeviceEnrollmentApproveResponse,
205
231
  DeviceEnrollmentDenyResponse,
206
232
  DeviceEnrollmentLookupResponse,
@@ -226,6 +252,29 @@ import type {
226
252
  KnowledgeMemorySearchRequest,
227
253
  ListApiKeysResponse,
228
254
  ListManagedOrganizationMembershipsResponse,
255
+ ListUserResourceAuthoritiesOptions,
256
+ ListUserResourceAuthoritiesResponse,
257
+ IssueUserResourceGrantRequest,
258
+ UserResourceGrantMutationResponse,
259
+ RevokeUserResourceGrantResponse,
260
+ ListOrganizationInvitationsPageResponse,
261
+ ListOrganizationMembersResponse,
262
+ AcceptOrganizationInvitationRequest,
263
+ AcceptOrganizationInvitationResponse,
264
+ AddOrganizationWorkspaceMemberRequest,
265
+ CreateOrganizationInvitationRequest,
266
+ CreateOrganizationRequest,
267
+ CreateOrganizationResponse,
268
+ CreateOrganizationWorkspaceRequest,
269
+ OrganizationInvitation,
270
+ OrganizationAdministrationOverview,
271
+ OrganizationMember,
272
+ OrganizationRetentionPolicy,
273
+ OrganizationSummary,
274
+ RevokeOrganizationInvitationRequest,
275
+ UpdateOrganizationMemberRequest,
276
+ UpdateOrganizationNameRequest,
277
+ UpdateOrganizationRetentionPolicyRequest,
229
278
  ListPacksResponse,
230
279
  // Bring-your-own-compute: the Machines dashboard + per-machine metrics (M10).
231
280
  MachinesResponse,
@@ -233,6 +282,9 @@ import type {
233
282
  MachineMetricsSeriesResponse,
234
283
  RemoveEnrollmentRequest,
235
284
  RemoveEnrollmentResponse,
285
+ MachineOperationPolicy,
286
+ UpdateMachineOperationPolicyRequest,
287
+ UpdateMachineAgentResponse,
236
288
  // Bring-your-own-compute: the user-authenticated active-sandbox swap (M7).
237
289
  SwapActiveSandboxRequest,
238
290
  SwapActiveSandboxResponse,
@@ -246,8 +298,6 @@ import type {
246
298
  ApproveSlackUserLinkAccessRequest,
247
299
  PackInstallation,
248
300
  PackUninstallPreview,
249
- LatencyMode,
250
- ReasoningEffort,
251
301
  RetainedScreenshotDownload,
252
302
  RetainedScreenshotDownloadOptions,
253
303
  RetainedArtifactDownload,
@@ -262,16 +312,24 @@ import type {
262
312
  VideoGenerationPolicy,
263
313
  WorkspaceVideoGenerationSettings,
264
314
  RegisterCapabilityPackRequest,
265
- ResourceRef,
266
315
  PreviewPackInstallationRequest,
267
316
  PreviewSkillImportRequest,
268
317
  ScheduledTask,
269
318
  ScheduledTaskRun,
319
+ ForkSessionRequest,
320
+ ForkSessionResponse,
270
321
  Session,
322
+ SessionBackgroundCommandListResponse,
323
+ CancelSessionBackgroundCommandResult,
271
324
  SessionListResponse,
325
+ SessionTenancyCreateCapabilities,
272
326
  AgentTopologyPageResponse,
273
327
  UpdateSessionChannelRequest,
328
+ UpdateSessionAttentionRequest,
329
+ UpdateSessionArchiveRequest,
274
330
  UpdateSessionPinRequest,
331
+ UpdateSessionVisibilityRequest,
332
+ UpdateSessionVisibilityResponse,
275
333
  UninstallPackRequest,
276
334
  UninstallPackResult,
277
335
  SessionEvent,
@@ -281,24 +339,31 @@ import type {
281
339
  SessionEventPage,
282
340
  SessionGoal,
283
341
  SessionGoalRevision,
342
+ ListSessionGoalRevisionsOptions,
343
+ ListSessionGoalRevisionsResponse,
344
+ RejectSessionGoalRevisionRequest,
345
+ RejectSessionGoalRevisionResponse,
346
+ RollbackSessionGoalRevisionRequest,
284
347
  SessionHumanInputRequest,
285
348
  SessionLineageResponse,
286
349
  SessionRealtimeMutationResponse,
287
350
  SyncSessionRealtimeLedgerRequest,
288
351
  SyncSessionRealtimeLedgerResponse,
289
352
  RenewSessionRealtimeRequest,
290
- SessionMcpCredentialUpdateInput,
291
- SubmittedTimelineAnnotation,
292
353
  UpdateSessionMcpApprovalPolicyRequest,
293
354
  UpdateSessionMcpApprovalPolicyResponse,
294
355
  SessionQueueSnapshot,
295
356
  SessionQueueMutationResponse,
357
+ SessionCommandReceipt,
358
+ SessionPromptRouting,
296
359
  ComposerDraft,
297
360
  DeleteSessionQueueItemRequest,
298
361
  EditSessionQueueItemRequest,
299
362
  MoveSessionQueueItemRequest,
300
363
  NewSessionDraft,
301
364
  SaveComposerDraftRequest,
365
+ SubmitComposerDraftRequest,
366
+ SubmitComposerDraftResponse,
302
367
  SaveNewSessionDraftRequest,
303
368
  SteerSessionQueueItemRequest,
304
369
  SessionControlResponse,
@@ -321,6 +386,8 @@ import type {
321
386
  FsListBatchResponse,
322
387
  FsReadRequest,
323
388
  FsReadResponse,
389
+ PublishSandboxFileArtifactRequest,
390
+ SandboxFileArtifactReceipt,
324
391
  FsWriteRequest,
325
392
  FsWriteResponse,
326
393
  FsDeleteRequest,
@@ -349,7 +416,6 @@ import type {
349
416
  PtyWriteRequest,
350
417
  PtyResizeRequest,
351
418
  PtyCloseRequest,
352
- ToolRef,
353
419
  TranscribeAudioResponse,
354
420
  TranscriptionRecordingListResponse,
355
421
  TranscriptionRecordingResponse,
@@ -364,6 +430,7 @@ import type {
364
430
  UpdateVariableSetRequest,
365
431
  UpdateRigRequest,
366
432
  UpdateWorkspaceMemberRequest,
433
+ UpdateWorkspaceModelAccessPolicyRequest,
367
434
  UpdateWorkspaceRequest,
368
435
  UpdateWorkspaceSettingsRequest,
369
436
  SetWorkspaceDefaultRigRequest,
@@ -373,6 +440,7 @@ import type {
373
440
  VariableSetVariableMetadata,
374
441
  Channel,
375
442
  CreateChannelRequest,
443
+ ReorderChannelsRequest,
376
444
  UpdateChannelRequest,
377
445
  Rig,
378
446
  RigVersion,
@@ -397,7 +465,10 @@ import type {
397
465
  UninstallSkillResult,
398
466
  } from "./types";
399
467
  import { GENERATED_VIDEO_MAX_BYTES } from "./types";
400
- import { parseRetainedGeneratedImageReference } from "./retained-artifacts";
468
+ import {
469
+ parseRetainedGeneratedImageReference,
470
+ parseRetainedWorkspaceFileReference,
471
+ } from "./retained-artifacts";
401
472
  import type {
402
473
  ActivateWorkspaceInstructionPolicyRequest,
403
474
  CreateWorkspaceInstructionPolicyDraftRequest,
@@ -414,6 +485,16 @@ import type {
414
485
  WorkspaceInstructionPolicyOnboardingProposalListResponse,
415
486
  WorkspaceInstructionPolicyRevision,
416
487
  } from "./workspace-instruction-policies";
488
+ import type {
489
+ ActivateWorkspaceLearningPolicyRevisionRequest,
490
+ CreateWorkspaceLearningPolicyRevisionRequest,
491
+ GovernedLearningActivationUndoReceipt,
492
+ RollbackWorkspaceLearningPolicyRevisionRequest,
493
+ WorkspaceLearningHistoryOptions,
494
+ WorkspaceLearningHistoryResponse,
495
+ WorkspaceLearningPolicyMutationResponse,
496
+ WorkspaceLearningPolicyRevision,
497
+ } from "./workspace-learning";
417
498
  import type {
418
499
  ActivateCompanyProfileRevisionRequest,
419
500
  CompanyProfileDiffRequest,
@@ -430,6 +511,7 @@ import type {
430
511
  WorkspaceStateGetOptions,
431
512
  WorkspaceStateResponse,
432
513
  } from "./workspace-state";
514
+ import type { CompanyBrainOkfDownload, CompanyBrainOkfPackage } from "./company-brain";
433
515
  import type {
434
516
  ActivatePreferenceRegistryRevisionRequest,
435
517
  ChangePreferenceRegistryScopeRequest,
@@ -483,38 +565,42 @@ export type OpenGeniClientOptions = {
483
565
  headers?: Record<string, string> | (() => Record<string, string>);
484
566
  /** Custom fetch implementation. Defaults to the global `fetch`. */
485
567
  fetch?: FetchLike;
568
+ /** Positive deadline for interactive session commands. Defaults to 15 seconds. */
569
+ sessionCommandTimeoutMs?: number;
486
570
  };
487
571
 
488
572
  /** Per-request cancellation for operations whose caller owns an AbortSignal. */
489
573
  export type OpenGeniRequestOptions = {
490
574
  signal?: AbortSignal | undefined;
575
+ timeoutMs?: number | undefined;
491
576
  };
492
577
 
493
- export type SendMessageInput = {
494
- text: string;
495
- annotations?: SubmittedTimelineAnnotation[];
496
- /** Model-visible application context attached to this exact user message; omitted by standard timeline rendering. */
497
- modelContext?: string;
498
- resources?: ResourceRef[];
499
- tools?: ToolRef[];
500
- model?: string;
501
- reasoningEffort?: ReasoningEffort;
502
- latencyMode?: LatencyMode;
578
+ /** Follow-up prompt fields accepted by both queue and Steer. Session tools are updated separately. */
579
+ export type SendMessageInput = UserMessageEventInput["payload"] & {
503
580
  clientEventId?: string;
504
- controlEtag?: string;
505
- expectedDraftRevision?: number;
506
- mcpCredentialUpdates?: SessionMcpCredentialUpdateInput[];
507
581
  };
508
582
 
583
+ function assertNoMessageTools(input: object): void {
584
+ if (Object.prototype.hasOwnProperty.call(input, "tools")) {
585
+ throw new TypeError(
586
+ "Message-level tools are not supported; update the session tool policy before sending.",
587
+ );
588
+ }
589
+ }
590
+
509
591
  export type SteerMessageResult = {
510
592
  /** The accepted `user.message` event. */
511
593
  accepted: SessionEvent;
512
594
  /** The exact turn created for this message in the same server transaction. */
513
595
  turn: SessionTurn;
596
+ /** Durable proof that this exact operation committed. */
597
+ receipt: SessionCommandReceipt;
598
+ /** Server-owned destination at admission time. */
599
+ routing: SessionPromptRouting;
514
600
  /** Number of live attempts durably asked to stop by this atomic Steer. */
515
- interruptionCount?: number;
601
+ interruptionCount: number;
516
602
  /** True when this response came from the command's immutable idempotency receipt. */
517
- replay?: boolean;
603
+ replay: boolean;
518
604
  };
519
605
 
520
606
  export type TranscribeAudioInput = {
@@ -555,6 +641,7 @@ export class OpenGeniClient {
555
641
  private readonly baseUrl: string;
556
642
  private readonly options: OpenGeniClientOptions;
557
643
  private readonly fetchImpl: FetchLike;
644
+ private readonly sessionCommandTimeoutMs: number;
558
645
  private readonly readInFlight = new Map<string, Promise<unknown>>();
559
646
  private readonly readTrailing = new Map<string, Promise<unknown>>();
560
647
  /** Resource-oriented Browser/Computer facade over this exact authenticated client. */
@@ -565,6 +652,11 @@ export class OpenGeniClient {
565
652
  this.options = options;
566
653
  // Bind lazily so variable sets that polyfill fetch after module load work.
567
654
  this.fetchImpl = options.fetch ?? ((input, init) => fetch(input, init));
655
+ const sessionCommandTimeoutMs = options.sessionCommandTimeoutMs ?? 15_000;
656
+ if (!Number.isFinite(sessionCommandTimeoutMs) || sessionCommandTimeoutMs <= 0) {
657
+ throw new RangeError("sessionCommandTimeoutMs must be a finite positive number");
658
+ }
659
+ this.sessionCommandTimeoutMs = sessionCommandTimeoutMs;
568
660
  this.interaction = new OpenGeniInteractionClient(this);
569
661
  }
570
662
 
@@ -836,6 +928,42 @@ export class OpenGeniClient {
836
928
  );
837
929
  }
838
930
 
931
+ /** Whether this exact authenticated principal may atomically create a private session. */
932
+ async getSessionTenancyCreateCapabilities(
933
+ workspaceId: string,
934
+ ): Promise<SessionTenancyCreateCapabilities> {
935
+ return await this.requestJson<SessionTenancyCreateCapabilities>(
936
+ "GET",
937
+ `/v1/workspaces/${workspaceId}/session-tenancy/capabilities`,
938
+ );
939
+ }
940
+
941
+ /** Change an owned, fully quiescent session between private and workspace visibility. */
942
+ async updateSessionVisibility(
943
+ workspaceId: string,
944
+ sessionId: string,
945
+ request: UpdateSessionVisibilityRequest,
946
+ ): Promise<UpdateSessionVisibilityResponse> {
947
+ return await this.requestJson<UpdateSessionVisibilityResponse>(
948
+ "PUT",
949
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/visibility`,
950
+ request,
951
+ );
952
+ }
953
+
954
+ /** Create an independent same-workspace fork with explicit destination visibility. */
955
+ async forkSession(
956
+ workspaceId: string,
957
+ sessionId: string,
958
+ request: ForkSessionRequest,
959
+ ): Promise<ForkSessionResponse> {
960
+ return await this.requestJson<ForkSessionResponse>(
961
+ "POST",
962
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/forks`,
963
+ request,
964
+ );
965
+ }
966
+
839
967
  /** Replace the durable tool policy or explicitly adopt workspace defaults. */
840
968
  async updateSessionToolPolicy(
841
969
  workspaceId: string,
@@ -893,6 +1021,27 @@ export class OpenGeniClient {
893
1021
  );
894
1022
  }
895
1023
 
1024
+ async listSessionBackgroundCommands(
1025
+ workspaceId: string,
1026
+ sessionId: string,
1027
+ ): Promise<SessionBackgroundCommandListResponse> {
1028
+ return await this.requestJson<SessionBackgroundCommandListResponse>(
1029
+ "GET",
1030
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/background-commands`,
1031
+ );
1032
+ }
1033
+
1034
+ async cancelSessionBackgroundCommand(
1035
+ workspaceId: string,
1036
+ sessionId: string,
1037
+ commandId: string,
1038
+ ): Promise<CancelSessionBackgroundCommandResult> {
1039
+ return await this.requestJson<CancelSessionBackgroundCommandResult>(
1040
+ "DELETE",
1041
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/background-commands/${commandId}`,
1042
+ );
1043
+ }
1044
+
896
1045
  /** Pin-aware ordinary-session page with a stable keyset cursor. */
897
1046
  async listSessionPage(
898
1047
  workspaceId: string,
@@ -903,6 +1052,8 @@ export class OpenGeniClient {
903
1052
  search?: string;
904
1053
  /** Return only the complete personal pinned projection. */
905
1054
  pinsOnly?: boolean;
1055
+ /** Return archived root chats instead of the active session list. */
1056
+ archivedOnly?: boolean;
906
1057
  } = {},
907
1058
  ): Promise<SessionListResponse> {
908
1059
  const search = options.search?.trim();
@@ -918,6 +1069,7 @@ export class OpenGeniClient {
918
1069
  ...(options.cursor !== undefined ? { cursor: options.cursor } : {}),
919
1070
  ...(search ? { search } : {}),
920
1071
  ...(options.pinsOnly ? { pinsOnly: "true" } : {}),
1072
+ ...(options.archivedOnly ? { archivedOnly: "true" } : {}),
921
1073
  },
922
1074
  );
923
1075
  } catch (error) {
@@ -949,6 +1101,9 @@ export class OpenGeniClient {
949
1101
  if (options.pinsOnly) {
950
1102
  throw new Error("The connected OpenGeni API does not support pins-only session lists");
951
1103
  }
1104
+ if (options.archivedOnly) {
1105
+ throw new Error("The connected OpenGeni API does not support archived session lists");
1106
+ }
952
1107
  return { pinned: [], sessions: response, nextCursor: null };
953
1108
  }
954
1109
  return response;
@@ -993,6 +1148,43 @@ export class OpenGeniClient {
993
1148
  );
994
1149
  }
995
1150
 
1151
+ /** Set this authenticated member's explicit read/actively-working state. */
1152
+ async updateSessionAttention(
1153
+ workspaceId: string,
1154
+ sessionId: string,
1155
+ request: UpdateSessionAttentionRequest,
1156
+ ): Promise<Session> {
1157
+ return await this.requestJson<Session>(
1158
+ "PUT",
1159
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/attention`,
1160
+ request,
1161
+ );
1162
+ }
1163
+
1164
+ /** Archive or restore this authenticated member's root chat. */
1165
+ async updateSessionArchive(
1166
+ workspaceId: string,
1167
+ sessionId: string,
1168
+ request: UpdateSessionArchiveRequest,
1169
+ ): Promise<Session> {
1170
+ return await this.requestJson<Session>(
1171
+ "PUT",
1172
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/archive`,
1173
+ request,
1174
+ );
1175
+ }
1176
+
1177
+ /** Permanently delete one quiescent root session and its full descendant tree. */
1178
+ async deleteSession(
1179
+ workspaceId: string,
1180
+ sessionId: string,
1181
+ ): Promise<{ deletedSessionCount: number }> {
1182
+ return await this.requestJson<{ deletedSessionCount: number }>(
1183
+ "DELETE",
1184
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}`,
1185
+ );
1186
+ }
1187
+
996
1188
  async getSessionLineage(workspaceId: string, sessionId: string): Promise<SessionLineageResponse> {
997
1189
  const path = `/v1/workspaces/${workspaceId}/sessions/${sessionId}/lineage`;
998
1190
  return await this.singleFlightRead(path, () =>
@@ -1196,6 +1388,33 @@ export class OpenGeniClient {
1196
1388
  );
1197
1389
  }
1198
1390
 
1391
+ /** Ask one authoritative Connected Machine runner to drain accepted work and
1392
+ * install the exact signed version promoted for its channel. Progress is read
1393
+ * from `listMachines`; completion requires the successor build identity. */
1394
+ async updateMachineAgent(
1395
+ workspaceId: string,
1396
+ enrollmentId: string,
1397
+ ): Promise<UpdateMachineAgentResponse> {
1398
+ return await this.requestJson<UpdateMachineAgentResponse>(
1399
+ "POST",
1400
+ `/v1/workspaces/${workspaceId}/machines/${enrollmentId}/update`,
1401
+ );
1402
+ }
1403
+
1404
+ /** Revision-fenced update of a Connected Machine's optional command memory
1405
+ * policy. Null byte limits preserve unrestricted machine access. */
1406
+ async updateMachineOperationPolicy(
1407
+ workspaceId: string,
1408
+ enrollmentId: string,
1409
+ request: UpdateMachineOperationPolicyRequest,
1410
+ ): Promise<MachineOperationPolicy> {
1411
+ return await this.requestJson<MachineOperationPolicy>(
1412
+ "PATCH",
1413
+ `/v1/workspaces/${workspaceId}/machines/${enrollmentId}/operation-policy`,
1414
+ request,
1415
+ );
1416
+ }
1417
+
1199
1418
  /**
1200
1419
  * Read the downsampled (~1/min) metrics series for ONE machine over a time
1201
1420
  * window (default 1h). The samples are oldest-first (a left-to-right chart).
@@ -1217,8 +1436,9 @@ export class OpenGeniClient {
1217
1436
  /**
1218
1437
  * Remove one connected self-hosted machine enrollment. The control-plane
1219
1438
  * operation works while the agent is offline, revokes future reconnects,
1220
- * retains history, and returns a typed blocker when active route/lease or
1221
- * recovery dependencies make removal unsafe. `idempotencyKey` is replay-safe.
1439
+ * retains history, and atomically detaches idle dependent sessions (a
1440
+ * machine-home session becomes `backend:none`). Active turns, live leases,
1441
+ * and recovery work remain typed blockers. `idempotencyKey` is replay-safe.
1222
1442
  */
1223
1443
  async removeEnrollment(
1224
1444
  workspaceId: string,
@@ -1258,7 +1478,7 @@ export class OpenGeniClient {
1258
1478
  */
1259
1479
  async approveDeviceEnrollment(
1260
1480
  workspaceId: string,
1261
- request: { userCode: string; allowScreenControl?: boolean },
1481
+ request: DeviceEnrollmentApproveRequest,
1262
1482
  ): Promise<DeviceEnrollmentApproveResponse> {
1263
1483
  return await this.requestJson<DeviceEnrollmentApproveResponse>(
1264
1484
  "POST",
@@ -1266,6 +1486,7 @@ export class OpenGeniClient {
1266
1486
  {
1267
1487
  userCode: request.userCode,
1268
1488
  allowScreenControl: request.allowScreenControl ?? false,
1489
+ ...(request.scope ? { scope: request.scope } : {}),
1269
1490
  },
1270
1491
  );
1271
1492
  }
@@ -1498,7 +1719,7 @@ export class OpenGeniClient {
1498
1719
  sessionId: string,
1499
1720
  event: ClientSessionEventInput,
1500
1721
  ): Promise<SessionEvent> {
1501
- return await this.requestJson<SessionEvent>(
1722
+ return await this.requestSessionCommand<SessionEvent>(
1502
1723
  "POST",
1503
1724
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/events`,
1504
1725
  event,
@@ -1511,6 +1732,7 @@ export class OpenGeniClient {
1511
1732
  message: string | SendMessageInput,
1512
1733
  ): Promise<SessionEvent> {
1513
1734
  const input = typeof message === "string" ? { text: message } : message;
1735
+ assertNoMessageTools(input);
1514
1736
  const { clientEventId, ...payload } = input;
1515
1737
  return await this.sendEvent(workspaceId, sessionId, {
1516
1738
  type: "user.message",
@@ -1656,7 +1878,7 @@ export class OpenGeniClient {
1656
1878
  async getQueue(workspaceId: string, sessionId: string): Promise<SessionQueueSnapshot> {
1657
1879
  const path = `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue`;
1658
1880
  return await this.singleFlightRead(path, () =>
1659
- this.requestJson<SessionQueueSnapshot>("GET", path),
1881
+ this.requestSessionCommand<SessionQueueSnapshot>("GET", path),
1660
1882
  );
1661
1883
  }
1662
1884
 
@@ -1666,7 +1888,7 @@ export class OpenGeniClient {
1666
1888
  turnId: string,
1667
1889
  request: MoveSessionQueueItemRequest,
1668
1890
  ): Promise<SessionQueueMutationResponse> {
1669
- return await this.requestJson<SessionQueueMutationResponse>(
1891
+ return await this.requestSessionCommand<SessionQueueMutationResponse>(
1670
1892
  "POST",
1671
1893
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/move`,
1672
1894
  request,
@@ -1679,7 +1901,7 @@ export class OpenGeniClient {
1679
1901
  turnId: string,
1680
1902
  request: EditSessionQueueItemRequest,
1681
1903
  ): Promise<SessionQueueMutationResponse> {
1682
- return await this.requestJson<SessionQueueMutationResponse>(
1904
+ return await this.requestSessionCommand<SessionQueueMutationResponse>(
1683
1905
  "POST",
1684
1906
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/edit`,
1685
1907
  request,
@@ -1692,7 +1914,7 @@ export class OpenGeniClient {
1692
1914
  turnId: string,
1693
1915
  request: SteerSessionQueueItemRequest,
1694
1916
  ): Promise<SessionQueueMutationResponse> {
1695
- return await this.requestJson<SessionQueueMutationResponse>(
1917
+ return await this.requestSessionCommand<SessionQueueMutationResponse>(
1696
1918
  "POST",
1697
1919
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/steer`,
1698
1920
  request,
@@ -1705,7 +1927,7 @@ export class OpenGeniClient {
1705
1927
  turnId: string,
1706
1928
  request: DeleteSessionQueueItemRequest,
1707
1929
  ): Promise<SessionQueueMutationResponse> {
1708
- return await this.requestJson<SessionQueueMutationResponse>(
1930
+ return await this.requestSessionCommand<SessionQueueMutationResponse>(
1709
1931
  "POST",
1710
1932
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/delete`,
1711
1933
  request,
@@ -1713,7 +1935,7 @@ export class OpenGeniClient {
1713
1935
  }
1714
1936
 
1715
1937
  async getComposerDraft(workspaceId: string, sessionId: string): Promise<ComposerDraft> {
1716
- return await this.requestJson<ComposerDraft>(
1938
+ return await this.requestSessionCommand<ComposerDraft>(
1717
1939
  "GET",
1718
1940
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/composer-draft`,
1719
1941
  );
@@ -1724,13 +1946,25 @@ export class OpenGeniClient {
1724
1946
  sessionId: string,
1725
1947
  request: SaveComposerDraftRequest,
1726
1948
  ): Promise<ComposerDraft> {
1727
- return await this.requestJson<ComposerDraft>(
1949
+ return await this.requestSessionCommand<ComposerDraft>(
1728
1950
  "PUT",
1729
1951
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/composer-draft`,
1730
1952
  request,
1731
1953
  );
1732
1954
  }
1733
1955
 
1956
+ async submitComposerDraft(
1957
+ workspaceId: string,
1958
+ sessionId: string,
1959
+ request: SubmitComposerDraftRequest,
1960
+ ): Promise<SubmitComposerDraftResponse> {
1961
+ return await this.requestSessionCommand<SubmitComposerDraftResponse>(
1962
+ "POST",
1963
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/composer-draft/submit`,
1964
+ request,
1965
+ );
1966
+ }
1967
+
1734
1968
  async controlSession(
1735
1969
  workspaceId: string,
1736
1970
  sessionId: string,
@@ -1741,7 +1975,7 @@ export class OpenGeniClient {
1741
1975
  expectedControlEtag?: string;
1742
1976
  },
1743
1977
  ): Promise<SessionControlResponse> {
1744
- return await this.requestJson<SessionControlResponse>(
1978
+ return await this.requestSessionCommand<SessionControlResponse>(
1745
1979
  "POST",
1746
1980
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/control`,
1747
1981
  request,
@@ -1966,7 +2200,8 @@ export class OpenGeniClient {
1966
2200
  message: string | SendMessageInput,
1967
2201
  ): Promise<SteerMessageResult> {
1968
2202
  const input = typeof message === "string" ? { text: message } : message;
1969
- return await this.requestJson<SteerMessageResult>(
2203
+ assertNoMessageTools(input);
2204
+ return await this.requestSessionCommand<SteerMessageResult>(
1970
2205
  "POST",
1971
2206
  `/v1/workspaces/${workspaceId}/sessions/${sessionId}/steer`,
1972
2207
  input,
@@ -2000,6 +2235,47 @@ export class OpenGeniClient {
2000
2235
  );
2001
2236
  }
2002
2237
 
2238
+ async listGoalRevisionPage(
2239
+ workspaceId: string,
2240
+ sessionId: string,
2241
+ options: ListSessionGoalRevisionsOptions = {},
2242
+ ): Promise<ListSessionGoalRevisionsResponse> {
2243
+ const query = new URLSearchParams();
2244
+ if (options.limit !== undefined) query.set("limit", String(options.limit));
2245
+ if (options.before !== undefined) query.set("before", options.before);
2246
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
2247
+ return await this.requestJson<ListSessionGoalRevisionsResponse>(
2248
+ "GET",
2249
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal/revisions/page${suffix}`,
2250
+ );
2251
+ }
2252
+
2253
+ async rejectGoalRevision(
2254
+ workspaceId: string,
2255
+ sessionId: string,
2256
+ revisionId: string,
2257
+ request: RejectSessionGoalRevisionRequest,
2258
+ ): Promise<RejectSessionGoalRevisionResponse> {
2259
+ return await this.requestJson<RejectSessionGoalRevisionResponse>(
2260
+ "POST",
2261
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal/revisions/${revisionId}/reject`,
2262
+ request,
2263
+ );
2264
+ }
2265
+
2266
+ async rollbackGoalRevision(
2267
+ workspaceId: string,
2268
+ sessionId: string,
2269
+ revisionId: string,
2270
+ request: RollbackSessionGoalRevisionRequest,
2271
+ ): Promise<SessionGoal> {
2272
+ return await this.requestJson<SessionGoal>(
2273
+ "POST",
2274
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal/revisions/${revisionId}/rollback`,
2275
+ request,
2276
+ );
2277
+ }
2278
+
2003
2279
  async applyGoalRevision(
2004
2280
  workspaceId: string,
2005
2281
  sessionId: string,
@@ -2116,6 +2392,22 @@ export class OpenGeniClient {
2116
2392
  );
2117
2393
  }
2118
2394
 
2395
+ /** Publish one exact sandbox file into permanent workspace artifact storage. */
2396
+ async publishSandboxFileArtifact(
2397
+ workspaceId: string,
2398
+ sessionId: string,
2399
+ request: PublishSandboxFileArtifactRequest,
2400
+ options: OpenGeniRequestOptions = {},
2401
+ ): Promise<SandboxFileArtifactReceipt> {
2402
+ return await this.requestJson<SandboxFileArtifactReceipt>(
2403
+ "POST",
2404
+ `/v1/workspaces/${workspaceId}/sessions/${sessionId}/artifacts/publish`,
2405
+ request,
2406
+ {},
2407
+ options,
2408
+ );
2409
+ }
2410
+
2119
2411
  /** FileSystem: write a file (last-writer-wins; emits fs.changed). */
2120
2412
  async fsWrite(
2121
2413
  workspaceId: string,
@@ -3384,6 +3676,26 @@ export class OpenGeniClient {
3384
3676
  );
3385
3677
  }
3386
3678
 
3679
+ /** Read the workspace's hard provider/model allowlist. */
3680
+ async getWorkspaceModelAccessPolicy(workspaceId: string): Promise<WorkspaceModelAccessPolicy> {
3681
+ return await this.requestJson<WorkspaceModelAccessPolicy>(
3682
+ "GET",
3683
+ `/v1/workspaces/${workspaceId}/model-policy`,
3684
+ );
3685
+ }
3686
+
3687
+ /** Fully replace the workspace's hard provider/model allowlist. */
3688
+ async updateWorkspaceModelAccessPolicy(
3689
+ workspaceId: string,
3690
+ request: UpdateWorkspaceModelAccessPolicyRequest,
3691
+ ): Promise<WorkspaceModelAccessPolicy> {
3692
+ return await this.requestJson<WorkspaceModelAccessPolicy>(
3693
+ "PUT",
3694
+ `/v1/workspaces/${workspaceId}/model-policy`,
3695
+ request,
3696
+ );
3697
+ }
3698
+
3387
3699
  /** Authenticated realtime voice models and credential readiness. */
3388
3700
  async getWorkspaceRealtimeModelCatalog(
3389
3701
  workspaceId: string,
@@ -3407,6 +3719,258 @@ export class OpenGeniClient {
3407
3719
  );
3408
3720
  }
3409
3721
 
3722
+ /** Bounded owner-only personal-resource authority page for one exact resource kind. */
3723
+ async listUserResourceAuthorities(
3724
+ workspaceId: string,
3725
+ options: ListUserResourceAuthoritiesOptions,
3726
+ ): Promise<ListUserResourceAuthoritiesResponse> {
3727
+ const query = new URLSearchParams({
3728
+ scope: "user",
3729
+ resourceKind: options.resourceKind,
3730
+ });
3731
+ if (options.cursor) query.set("cursor", options.cursor);
3732
+ if (options.limit !== undefined) query.set("limit", String(options.limit));
3733
+ return await this.requestJson<ListUserResourceAuthoritiesResponse>(
3734
+ "GET",
3735
+ `/v1/workspaces/${workspaceId}/user-resource-authorities?${query.toString()}`,
3736
+ );
3737
+ }
3738
+
3739
+ /** Issue an exact-session or standing personal-resource grant. */
3740
+ async issueUserResourceGrant(
3741
+ workspaceId: string,
3742
+ authorityId: string,
3743
+ request: IssueUserResourceGrantRequest,
3744
+ ): Promise<UserResourceGrantMutationResponse> {
3745
+ return await this.requestJson<UserResourceGrantMutationResponse>(
3746
+ "POST",
3747
+ `/v1/workspaces/${workspaceId}/user-resource-authorities/${authorityId}/grants`,
3748
+ request,
3749
+ );
3750
+ }
3751
+
3752
+ /** Revoke an owner grant through the exact workspace it targets. */
3753
+ async revokeUserResourceGrant(
3754
+ workspaceId: string,
3755
+ grantId: string,
3756
+ ): Promise<RevokeUserResourceGrantResponse> {
3757
+ return await this.requestJson<RevokeUserResourceGrantResponse>(
3758
+ "DELETE",
3759
+ `/v1/workspaces/${workspaceId}/user-resource-authorities/grants/${grantId}?scope=user`,
3760
+ );
3761
+ }
3762
+
3763
+ /** Create a new organization owned by the current managed human. */
3764
+ async createOrganization(
3765
+ request: CreateOrganizationRequest,
3766
+ ): Promise<CreateOrganizationResponse> {
3767
+ return await this.requestJson<CreateOrganizationResponse>("POST", "/v1/organizations", request);
3768
+ }
3769
+
3770
+ /** Pending and historical invitations addressed to the current managed human. */
3771
+ async listOrganizationInvitations(
3772
+ options: { cursor?: string; limit?: number } = {},
3773
+ ): Promise<ListOrganizationInvitationsPageResponse> {
3774
+ const query = new URLSearchParams();
3775
+ if (options.cursor) query.set("cursor", options.cursor);
3776
+ if (options.limit !== undefined) query.set("limit", String(options.limit));
3777
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
3778
+ return await this.requestJson<ListOrganizationInvitationsPageResponse>(
3779
+ "GET",
3780
+ `/v1/organization-invitations${suffix}`,
3781
+ );
3782
+ }
3783
+
3784
+ /** Admin-only deterministic page of invitations for one organization. */
3785
+ async listOrganizationInvitationsForOrganization(
3786
+ organizationId: string,
3787
+ options: { cursor?: string; limit?: number } = {},
3788
+ ): Promise<ListOrganizationInvitationsPageResponse> {
3789
+ const query = new URLSearchParams();
3790
+ if (options.cursor) query.set("cursor", options.cursor);
3791
+ if (options.limit !== undefined) query.set("limit", String(options.limit));
3792
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
3793
+ return await this.requestJson<ListOrganizationInvitationsPageResponse>(
3794
+ "GET",
3795
+ `/v1/organizations/${organizationId}/invitations${suffix}`,
3796
+ );
3797
+ }
3798
+
3799
+ async createOrganizationInvitation(
3800
+ organizationId: string,
3801
+ request: CreateOrganizationInvitationRequest,
3802
+ ): Promise<OrganizationInvitation> {
3803
+ return await this.requestJson<OrganizationInvitation>(
3804
+ "POST",
3805
+ `/v1/organizations/${organizationId}/invitations`,
3806
+ request,
3807
+ );
3808
+ }
3809
+
3810
+ async acceptOrganizationInvitation(
3811
+ invitationId: string,
3812
+ request: AcceptOrganizationInvitationRequest,
3813
+ ): Promise<AcceptOrganizationInvitationResponse> {
3814
+ return await this.requestJson<AcceptOrganizationInvitationResponse>(
3815
+ "POST",
3816
+ `/v1/organization-invitations/${invitationId}/accept`,
3817
+ request,
3818
+ );
3819
+ }
3820
+
3821
+ async revokeOrganizationInvitation(
3822
+ organizationId: string,
3823
+ invitationId: string,
3824
+ request: RevokeOrganizationInvitationRequest,
3825
+ ): Promise<OrganizationInvitation> {
3826
+ return await this.requestJson<OrganizationInvitation>(
3827
+ "POST",
3828
+ `/v1/organizations/${organizationId}/invitations/${invitationId}/revoke`,
3829
+ request,
3830
+ );
3831
+ }
3832
+
3833
+ async listOrganizationMembers(organizationId: string): Promise<ListOrganizationMembersResponse> {
3834
+ return await this.requestJson<ListOrganizationMembersResponse>(
3835
+ "GET",
3836
+ `/v1/organizations/${organizationId}/members`,
3837
+ );
3838
+ }
3839
+
3840
+ /** Canonical organization identity and every non-personal workspace access roster. */
3841
+ async getOrganizationAdministrationOverview(
3842
+ organizationId: string,
3843
+ ): Promise<OrganizationAdministrationOverview> {
3844
+ return await this.requestJson<OrganizationAdministrationOverview>(
3845
+ "GET",
3846
+ `/v1/organizations/${organizationId}/overview`,
3847
+ );
3848
+ }
3849
+
3850
+ /** Rename the organization under an exact optimistic-concurrency fence. */
3851
+ async updateOrganizationName(
3852
+ organizationId: string,
3853
+ request: UpdateOrganizationNameRequest,
3854
+ ): Promise<OrganizationSummary> {
3855
+ return await this.requestJson<OrganizationSummary>(
3856
+ "PATCH",
3857
+ `/v1/organizations/${organizationId}`,
3858
+ request,
3859
+ );
3860
+ }
3861
+
3862
+ /**
3863
+ * Organization control-plane update for a shared workspace. This does not
3864
+ * require or create operational workspace access for the organization admin.
3865
+ */
3866
+ async updateOrganizationWorkspace(
3867
+ organizationId: string,
3868
+ workspaceId: string,
3869
+ request: UpdateWorkspaceRequest,
3870
+ ): Promise<Workspace> {
3871
+ return await this.requestJson<Workspace>(
3872
+ "PATCH",
3873
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}`,
3874
+ request,
3875
+ );
3876
+ }
3877
+
3878
+ /** Create a shared workspace without implicitly granting the actor access. */
3879
+ async createOrganizationWorkspace(
3880
+ organizationId: string,
3881
+ request: CreateOrganizationWorkspaceRequest,
3882
+ ): Promise<Workspace> {
3883
+ return await this.requestJson<Workspace>(
3884
+ "POST",
3885
+ `/v1/organizations/${organizationId}/workspaces`,
3886
+ request,
3887
+ );
3888
+ }
3889
+
3890
+ async updateOrganizationWorkspaceSettings(
3891
+ organizationId: string,
3892
+ workspaceId: string,
3893
+ request: UpdateWorkspaceSettingsRequest,
3894
+ ): Promise<Workspace> {
3895
+ return await this.requestJson<Workspace>(
3896
+ "PATCH",
3897
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}/settings`,
3898
+ request,
3899
+ );
3900
+ }
3901
+
3902
+ async addOrganizationWorkspaceMember(
3903
+ organizationId: string,
3904
+ workspaceId: string,
3905
+ request: AddOrganizationWorkspaceMemberRequest,
3906
+ ): Promise<WorkspaceMember> {
3907
+ return await this.requestJson<WorkspaceMember>(
3908
+ "POST",
3909
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}/members`,
3910
+ request,
3911
+ );
3912
+ }
3913
+
3914
+ async updateOrganizationWorkspaceMember(
3915
+ organizationId: string,
3916
+ workspaceId: string,
3917
+ subjectId: string,
3918
+ request: UpdateWorkspaceMemberRequest,
3919
+ ): Promise<WorkspaceMember> {
3920
+ return await this.requestJson<WorkspaceMember>(
3921
+ "PATCH",
3922
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}/members/${encodeURIComponent(
3923
+ subjectId,
3924
+ )}`,
3925
+ request,
3926
+ );
3927
+ }
3928
+
3929
+ async removeOrganizationWorkspaceMember(
3930
+ organizationId: string,
3931
+ workspaceId: string,
3932
+ subjectId: string,
3933
+ ): Promise<void> {
3934
+ await this.requestVoid(
3935
+ "DELETE",
3936
+ `/v1/organizations/${organizationId}/workspaces/${workspaceId}/members/${encodeURIComponent(
3937
+ subjectId,
3938
+ )}`,
3939
+ );
3940
+ }
3941
+
3942
+ async updateOrganizationMember(
3943
+ organizationId: string,
3944
+ membershipId: string,
3945
+ request: UpdateOrganizationMemberRequest,
3946
+ ): Promise<OrganizationMember> {
3947
+ return await this.requestJson<OrganizationMember>(
3948
+ "PATCH",
3949
+ `/v1/organizations/${organizationId}/members/${membershipId}`,
3950
+ request,
3951
+ );
3952
+ }
3953
+
3954
+ async getOrganizationRetentionPolicy(
3955
+ organizationId: string,
3956
+ ): Promise<OrganizationRetentionPolicy> {
3957
+ return await this.requestJson<OrganizationRetentionPolicy>(
3958
+ "GET",
3959
+ `/v1/organizations/${organizationId}/retention-policy`,
3960
+ );
3961
+ }
3962
+
3963
+ async updateOrganizationRetentionPolicy(
3964
+ organizationId: string,
3965
+ request: UpdateOrganizationRetentionPolicyRequest,
3966
+ ): Promise<OrganizationRetentionPolicy> {
3967
+ return await this.requestJson<OrganizationRetentionPolicy>(
3968
+ "PATCH",
3969
+ `/v1/organizations/${organizationId}/retention-policy`,
3970
+ request,
3971
+ );
3972
+ }
3973
+
3410
3974
  async listWorkspaces(): Promise<Workspace[]> {
3411
3975
  return await this.requestJson<Workspace[]>("GET", "/v1/workspaces");
3412
3976
  }
@@ -3447,6 +4011,28 @@ export class OpenGeniClient {
3447
4011
  );
3448
4012
  }
3449
4013
 
4014
+ /** Permission-filtered Company Brain package with authorized guidance bodies. */
4015
+ getCompanyBrain(workspaceId: string): Promise<CompanyBrainOkfPackage> {
4016
+ return this.requestJson<CompanyBrainOkfPackage>(
4017
+ "GET",
4018
+ `/v1/workspaces/${workspaceId}/company-brain`,
4019
+ );
4020
+ }
4021
+
4022
+ /** Download the deterministic Markdown/YAML Company Brain package. */
4023
+ async exportCompanyBrainOkf(workspaceId: string): Promise<CompanyBrainOkfDownload> {
4024
+ const response = await this.requestResponse(
4025
+ "GET",
4026
+ `/v1/workspaces/${workspaceId}/company-brain/export`,
4027
+ );
4028
+ const headers = response.headers;
4029
+ return {
4030
+ content: await response.text(),
4031
+ contentType: headers.get("content-type") ?? "text/markdown",
4032
+ filename: headers.get("content-disposition")?.split('"')[1] ?? "company-brain.okf.md",
4033
+ };
4034
+ }
4035
+
3450
4036
  async updateWorkspace(workspaceId: string, request: UpdateWorkspaceRequest): Promise<Workspace> {
3451
4037
  return await this.requestJson<Workspace>("PATCH", `/v1/workspaces/${workspaceId}`, request);
3452
4038
  }
@@ -3471,6 +4057,66 @@ export class OpenGeniClient {
3471
4057
  );
3472
4058
  }
3473
4059
 
4060
+ /** Inspect the bounded, permission-filtered governed-learning timeline. */
4061
+ async getWorkspaceLearningHistory(
4062
+ workspaceId: string,
4063
+ options: WorkspaceLearningHistoryOptions = {},
4064
+ ): Promise<WorkspaceLearningHistoryResponse> {
4065
+ const params = new URLSearchParams();
4066
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
4067
+ const query = params.toString();
4068
+ return await this.requestJson<WorkspaceLearningHistoryResponse>(
4069
+ "GET",
4070
+ `/v1/workspaces/${workspaceId}/learning${query ? `?${query}` : ""}`,
4071
+ );
4072
+ }
4073
+
4074
+ async createWorkspaceLearningPolicyRevision(
4075
+ workspaceId: string,
4076
+ request: CreateWorkspaceLearningPolicyRevisionRequest,
4077
+ ): Promise<WorkspaceLearningPolicyRevision> {
4078
+ return await this.requestJson<WorkspaceLearningPolicyRevision>(
4079
+ "POST",
4080
+ `/v1/workspaces/${workspaceId}/learning/revisions`,
4081
+ request,
4082
+ );
4083
+ }
4084
+
4085
+ async activateWorkspaceLearningPolicyRevision(
4086
+ workspaceId: string,
4087
+ revisionId: string,
4088
+ request: ActivateWorkspaceLearningPolicyRevisionRequest,
4089
+ ): Promise<WorkspaceLearningPolicyMutationResponse> {
4090
+ return await this.requestJson<WorkspaceLearningPolicyMutationResponse>(
4091
+ "POST",
4092
+ `/v1/workspaces/${workspaceId}/learning/revisions/${encodeURIComponent(revisionId)}/activate`,
4093
+ request,
4094
+ );
4095
+ }
4096
+
4097
+ async rollbackWorkspaceLearningPolicyRevision(
4098
+ workspaceId: string,
4099
+ request: RollbackWorkspaceLearningPolicyRevisionRequest,
4100
+ ): Promise<WorkspaceLearningPolicyMutationResponse> {
4101
+ return await this.requestJson<WorkspaceLearningPolicyMutationResponse>(
4102
+ "POST",
4103
+ `/v1/workspaces/${workspaceId}/learning/rollback`,
4104
+ request,
4105
+ );
4106
+ }
4107
+
4108
+ async undoGovernedLearningActivation(
4109
+ workspaceId: string,
4110
+ activationReceiptId: string,
4111
+ request: { operationId?: string } = {},
4112
+ ): Promise<GovernedLearningActivationUndoReceipt> {
4113
+ return await this.requestJson<GovernedLearningActivationUndoReceipt>(
4114
+ "POST",
4115
+ `/v1/workspaces/${workspaceId}/learning/activations/${encodeURIComponent(activationReceiptId)}/undo`,
4116
+ request,
4117
+ );
4118
+ }
4119
+
3474
4120
  async getWorkspaceInstructionPolicyRevision(
3475
4121
  workspaceId: string,
3476
4122
  revisionId: string,
@@ -4092,6 +4738,14 @@ export class OpenGeniClient {
4092
4738
  );
4093
4739
  }
4094
4740
 
4741
+ async reorderChannels(workspaceId: string, request: ReorderChannelsRequest): Promise<Channel[]> {
4742
+ return await this.requestJson<Channel[]>(
4743
+ "PUT",
4744
+ `/v1/workspaces/${workspaceId}/channels/order`,
4745
+ request,
4746
+ );
4747
+ }
4748
+
4095
4749
  async deleteChannel(workspaceId: string, channelId: string): Promise<void> {
4096
4750
  await this.requestJson<unknown>(
4097
4751
  "DELETE",
@@ -4460,24 +5114,24 @@ export class OpenGeniClient {
4460
5114
  );
4461
5115
  }
4462
5116
 
4463
- /** Assemble one permanent generated-image receipt from bounded authenticated ranges. */
5117
+ /** Assemble one permanent image or file artifact from bounded authenticated ranges. */
4464
5118
  async downloadRetainedArtifact(
4465
5119
  workspaceId: string,
4466
5120
  artifact: RetainedArtifactReference,
4467
5121
  options: RetainedArtifactDownloadOptions = {},
4468
5122
  ): Promise<RetainedArtifactDownload> {
4469
- assertRetainedGeneratedImageReceipt(workspaceId, artifact);
5123
+ assertRetainedWorkspaceArtifactReceipt(workspaceId, artifact);
4470
5124
  const bytes = await this.downloadRetainedArtifactBytes(artifact, options);
4471
5125
  return { artifact, bytes };
4472
5126
  }
4473
5127
 
4474
- /** Mint a short-lived, zero-copy browser source for a validated generated image. */
5128
+ /** Mint a short-lived, zero-copy browser source for a validated workspace artifact. */
4475
5129
  async createRetainedArtifactDownloadUrl(
4476
5130
  workspaceId: string,
4477
5131
  artifact: RetainedArtifactReference,
4478
5132
  options: OpenGeniRequestOptions = {},
4479
5133
  ): Promise<FileDownloadUrlResponse> {
4480
- assertRetainedGeneratedImageReceipt(workspaceId, artifact);
5134
+ assertRetainedWorkspaceArtifactReceipt(workspaceId, artifact);
4481
5135
  const download = await this.createFileDownloadUrl(workspaceId, artifact.artifactId, options);
4482
5136
  assertSafeArtifactDownloadUrl(download);
4483
5137
  return download;
@@ -4741,6 +5395,34 @@ export class OpenGeniClient {
4741
5395
  );
4742
5396
  }
4743
5397
 
5398
+ /**
5399
+ * List every Document the current human can manage from this workspace,
5400
+ * including portable personal and organization-scoped Documents whose
5401
+ * immutable ingestion workspace is different.
5402
+ */
5403
+ async listAccessibleDocuments(workspaceId: string): Promise<Document[]> {
5404
+ return await this.requestJson<Document[]>("GET", `/v1/workspaces/${workspaceId}/documents`);
5405
+ }
5406
+
5407
+ /** Read the immutable source file through the Document's effective authority. */
5408
+ async getDocumentOriginalFile(workspaceId: string, documentId: string): Promise<FileAsset> {
5409
+ return await this.requestJson<FileAsset>(
5410
+ "GET",
5411
+ `/v1/workspaces/${workspaceId}/documents/${documentId}/original-file`,
5412
+ );
5413
+ }
5414
+
5415
+ /** Mint a source-file URL through the Document's effective authority. */
5416
+ async createDocumentOriginalFileDownloadUrl(
5417
+ workspaceId: string,
5418
+ documentId: string,
5419
+ ): Promise<FileDownloadUrlResponse> {
5420
+ return await this.requestJson<FileDownloadUrlResponse>(
5421
+ "POST",
5422
+ `/v1/workspaces/${workspaceId}/documents/${documentId}/original-file/download-url`,
5423
+ );
5424
+ }
5425
+
4744
5426
  /**
4745
5427
  * Drop raw text or an already-uploaded file into the workspace's Default
4746
5428
  * base. When curation is enabled, it may name, summarize, categorize, and
@@ -4774,6 +5456,100 @@ export class OpenGeniClient {
4774
5456
  );
4775
5457
  }
4776
5458
 
5459
+ /**
5460
+ * Atomically reclassify a Document's authority and every indexed chunk.
5461
+ * The operation is replay-safe and rejects a stale expected authority tuple.
5462
+ */
5463
+ async reclassifyDocumentAuthority(
5464
+ workspaceId: string,
5465
+ documentId: string,
5466
+ request: ReclassifyDocumentAuthorityRequest,
5467
+ ): Promise<DocumentAuthorityReclassification> {
5468
+ return await this.requestJson<DocumentAuthorityReclassification>(
5469
+ "POST",
5470
+ `/v1/workspaces/${workspaceId}/documents/${documentId}/authority-reclassifications`,
5471
+ request,
5472
+ );
5473
+ }
5474
+
5475
+ /** List the current actor's durable authority-reclassification receipts. */
5476
+ async listDocumentAuthorityReclassifications(
5477
+ workspaceId: string,
5478
+ documentId: string,
5479
+ options: ListDocumentAuthorityReclassificationsOptions = {},
5480
+ ): Promise<ListDocumentAuthorityReclassificationsResponse> {
5481
+ const params = new URLSearchParams();
5482
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
5483
+ if (options.cursor) params.set("cursor", options.cursor);
5484
+ const query = params.size > 0 ? `?${params.toString()}` : "";
5485
+ return await this.requestJson<ListDocumentAuthorityReclassificationsResponse>(
5486
+ "GET",
5487
+ `/v1/workspaces/${workspaceId}/documents/${documentId}/authority-reclassifications${query}`,
5488
+ );
5489
+ }
5490
+
5491
+ /**
5492
+ * Advance one resumable, organization-scoped Default collection backfill.
5493
+ * Reusing an operation ID is idempotent; keep the run ID across batches.
5494
+ */
5495
+ async runDocumentDefaultCollectionBackfill(
5496
+ workspaceId: string,
5497
+ request: RunDocumentDefaultCollectionBackfillRequest,
5498
+ ): Promise<DocumentDefaultCollectionBackfill> {
5499
+ return await this.requestJson<DocumentDefaultCollectionBackfill>(
5500
+ "POST",
5501
+ `/v1/workspaces/${workspaceId}/document-default-collection-backfills`,
5502
+ request,
5503
+ );
5504
+ }
5505
+
5506
+ /** List organization-scoped Default collection backfill runs (organization admin only). */
5507
+ async listDocumentDefaultCollectionBackfillRuns(
5508
+ workspaceId: string,
5509
+ options: ListDocumentAuthorityReclassificationsOptions = {},
5510
+ ): Promise<ListDocumentDefaultCollectionBackfillRunsResponse> {
5511
+ const params = new URLSearchParams();
5512
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
5513
+ if (options.cursor) params.set("cursor", options.cursor);
5514
+ const query = params.size > 0 ? `?${params.toString()}` : "";
5515
+ return await this.requestJson<ListDocumentDefaultCollectionBackfillRunsResponse>(
5516
+ "GET",
5517
+ `/v1/workspaces/${workspaceId}/document-default-collection-backfills${query}`,
5518
+ );
5519
+ }
5520
+
5521
+ /** Read bounded operation and workspace receipts for one Default-collection backfill run. */
5522
+ async getDocumentDefaultCollectionBackfillAudit(
5523
+ workspaceId: string,
5524
+ runId: string,
5525
+ options: GetDocumentDefaultCollectionBackfillAuditOptions = {},
5526
+ ): Promise<DocumentDefaultCollectionBackfillAudit> {
5527
+ const params = new URLSearchParams();
5528
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
5529
+ if (options.operationCursor) params.set("operationCursor", options.operationCursor);
5530
+ if (options.receiptCursor) params.set("receiptCursor", options.receiptCursor);
5531
+ const query = params.size > 0 ? `?${params.toString()}` : "";
5532
+ return await this.requestJson<DocumentDefaultCollectionBackfillAudit>(
5533
+ "GET",
5534
+ `/v1/workspaces/${workspaceId}/document-default-collection-backfills/${runId}${query}`,
5535
+ );
5536
+ }
5537
+
5538
+ /** List organization-wide Document authority changes (organization admin only). */
5539
+ async listOrganizationDocumentAuthorityReclassifications(
5540
+ workspaceId: string,
5541
+ options: ListDocumentAuthorityReclassificationsOptions = {},
5542
+ ): Promise<ListOrganizationDocumentAuthorityReclassificationsResponse> {
5543
+ const params = new URLSearchParams();
5544
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
5545
+ if (options.cursor) params.set("cursor", options.cursor);
5546
+ const query = params.size > 0 ? `?${params.toString()}` : "";
5547
+ return await this.requestJson<ListOrganizationDocumentAuthorityReclassificationsResponse>(
5548
+ "GET",
5549
+ `/v1/workspaces/${workspaceId}/document-authority-reclassifications${query}`,
5550
+ );
5551
+ }
5552
+
4777
5553
  /** Retry indexing for a failed document. */
4778
5554
  async reindexDocument(
4779
5555
  workspaceId: string,
@@ -5389,6 +6165,96 @@ export class OpenGeniClient {
5389
6165
  return response.connections;
5390
6166
  }
5391
6167
 
6168
+ /** Secret-free status for the caller's exact personal GitHub connection. */
6169
+ async personalGitHubStatus(workspaceId: string): Promise<PersonalGitHubConnectionStatusResponse> {
6170
+ return await this.requestJson<PersonalGitHubConnectionStatusResponse>(
6171
+ "GET",
6172
+ `/v1/workspaces/${workspaceId}/connections/github`,
6173
+ );
6174
+ }
6175
+
6176
+ /** Start the dedicated personal GitHub authorization-code + PKCE flow. */
6177
+ async startPersonalGitHubOAuth(
6178
+ workspaceId: string,
6179
+ request: Omit<PersonalGitHubOAuthStartRequest, "connectionId"> = {},
6180
+ ): Promise<PersonalGitHubOAuthStartResponse> {
6181
+ return await this.requestJson<PersonalGitHubOAuthStartResponse>(
6182
+ "POST",
6183
+ `/v1/workspaces/${workspaceId}/connections/github/oauth/start`,
6184
+ request,
6185
+ );
6186
+ }
6187
+
6188
+ /** Re-authorize one exact personal GitHub Connection generation in place. */
6189
+ async reconnectPersonalGitHub(
6190
+ workspaceId: string,
6191
+ connectionId: string,
6192
+ request: Omit<PersonalGitHubOAuthStartRequest, "connectionId"> = {},
6193
+ ): Promise<PersonalGitHubOAuthStartResponse> {
6194
+ return await this.requestJson<PersonalGitHubOAuthStartResponse>(
6195
+ "POST",
6196
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/reconnect`,
6197
+ request,
6198
+ );
6199
+ }
6200
+
6201
+ /** Revoke one exact generation through an idempotent owner-only disconnect. */
6202
+ async disconnectPersonalGitHub(
6203
+ workspaceId: string,
6204
+ connectionId: string,
6205
+ request: PersonalGitHubDisconnectRequest,
6206
+ ): Promise<ConnectionMetadata> {
6207
+ const response = await this.requestJson<ConnectionResponse>(
6208
+ "DELETE",
6209
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}`,
6210
+ request,
6211
+ );
6212
+ return response.connection;
6213
+ }
6214
+
6215
+ /** Browse one bounded page of repositories visible to one exact owner connection. */
6216
+ async listPersonalGitHubRepositories(
6217
+ workspaceId: string,
6218
+ connectionId: string,
6219
+ options: ListPersonalGitHubRepositoriesOptions = {},
6220
+ ): Promise<ListPersonalGitHubRepositoriesResponse> {
6221
+ return await this.requestJson<ListPersonalGitHubRepositoriesResponse>(
6222
+ "GET",
6223
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/repositories`,
6224
+ undefined,
6225
+ {
6226
+ ...(options.cursor !== undefined ? { cursor: String(options.cursor) } : {}),
6227
+ ...(options.limit !== undefined ? { limit: String(options.limit) } : {}),
6228
+ },
6229
+ );
6230
+ }
6231
+
6232
+ /** Atomically replace the exact owner connection's selected repository set. */
6233
+ async replacePersonalGitHubRepositorySelections(
6234
+ workspaceId: string,
6235
+ connectionId: string,
6236
+ request: ReplacePersonalGitHubRepositorySelectionsRequest,
6237
+ ): Promise<PersonalGitHubRepositorySelectionState> {
6238
+ return await this.requestJson<PersonalGitHubRepositorySelectionState>(
6239
+ "PUT",
6240
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/repositories`,
6241
+ request,
6242
+ );
6243
+ }
6244
+
6245
+ /** Revalidate every selected repository without accepting provider URLs from the caller. */
6246
+ async verifyPersonalGitHubRepositorySelections(
6247
+ workspaceId: string,
6248
+ connectionId: string,
6249
+ request: VerifyPersonalGitHubRepositorySelectionsRequest,
6250
+ ): Promise<PersonalGitHubRepositorySelectionState> {
6251
+ return await this.requestJson<PersonalGitHubRepositorySelectionState>(
6252
+ "POST",
6253
+ `/v1/workspaces/${workspaceId}/connections/${connectionId}/github/repositories/verify`,
6254
+ request,
6255
+ );
6256
+ }
6257
+
5392
6258
  /** List the secret-free Slack team -> OpenGeni tenant routing authority. */
5393
6259
  async listSlackInstallationBindings(workspaceId: string): Promise<SlackInstallationBinding[]> {
5394
6260
  const response = await this.requestJson<ListSlackInstallationBindingsResponse>(
@@ -5463,6 +6329,28 @@ export class OpenGeniClient {
5463
6329
  );
5464
6330
  }
5465
6331
 
6332
+ async listOpenGeniSlackChannelRoutes(
6333
+ workspaceId: string,
6334
+ connectionId: string,
6335
+ ): Promise<SlackChannelRouteListResponse> {
6336
+ const query = new URLSearchParams({ connectionId });
6337
+ return await this.requestJson<SlackChannelRouteListResponse>(
6338
+ "GET",
6339
+ `/v1/workspaces/${workspaceId}/integrations/slack/channel-routes?${query}`,
6340
+ );
6341
+ }
6342
+
6343
+ async updateOpenGeniSlackChannelRoutes(
6344
+ workspaceId: string,
6345
+ request: UpdateSlackChannelRoutesRequest,
6346
+ ): Promise<void> {
6347
+ await this.requestJson<{ ok: boolean }>(
6348
+ "PUT",
6349
+ `/v1/workspaces/${workspaceId}/integrations/slack/channel-routes`,
6350
+ request,
6351
+ );
6352
+ }
6353
+
5466
6354
  async updateConnection(
5467
6355
  workspaceId: string,
5468
6356
  connectionId: string,
@@ -5705,6 +6593,17 @@ export class OpenGeniClient {
5705
6593
  return await this.requestJson<CreateCheckoutResponse>("POST", "/v1/billing/checkout", request);
5706
6594
  }
5707
6595
 
6596
+ /** Open Stripe's hosted portal for invoices and payment information. */
6597
+ async createBillingPortalSession(
6598
+ request: CreateBillingPortalRequest = {},
6599
+ ): Promise<CreateBillingPortalResponse> {
6600
+ return await this.requestJson<CreateBillingPortalResponse>(
6601
+ "POST",
6602
+ "/v1/billing/portal",
6603
+ request,
6604
+ );
6605
+ }
6606
+
5708
6607
  // --- Internals -------------------------------------------------------------
5709
6608
 
5710
6609
  private headers(correlationId?: string): Record<string, string> {
@@ -5988,6 +6887,19 @@ export class OpenGeniClient {
5988
6887
  }>("DELETE", `/v1/workspaces/${workspaceId}/supergrok/accounts/${accountId}`, {});
5989
6888
  }
5990
6889
 
6890
+ /** Contract-checked JSON transport shared by opt-in typed SDK clients. */
6891
+ private async requestSessionCommand<T>(method: string, path: string, body?: unknown): Promise<T> {
6892
+ return await this.requestJson<T>(
6893
+ method,
6894
+ path,
6895
+ body,
6896
+ {},
6897
+ {
6898
+ timeoutMs: this.sessionCommandTimeoutMs,
6899
+ },
6900
+ );
6901
+ }
6902
+
5991
6903
  /** Contract-checked JSON transport shared by opt-in typed SDK clients. */
5992
6904
  async requestJson<T>(
5993
6905
  method: string,
@@ -5997,36 +6909,46 @@ export class OpenGeniClient {
5997
6909
  options: OpenGeniRequestOptions = {},
5998
6910
  ): Promise<T> {
5999
6911
  const correlationId = crypto.randomUUID();
6000
- let response: Response;
6912
+ const abort = requestAbortSignal(options);
6001
6913
  try {
6002
- response = await this.fetchImpl(this.url(path, query), {
6003
- method,
6004
- headers: {
6005
- ...this.headers(correlationId),
6006
- Accept: "application/json",
6007
- ...(body !== undefined ? { "Content-Type": "application/json" } : {}),
6008
- },
6009
- ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
6010
- ...(options.signal ? { signal: options.signal } : {}),
6011
- });
6012
- } catch (error) {
6013
- if (isMutationMethod(method)) {
6014
- throw mutationTransportError(correlationId);
6914
+ let response: Response;
6915
+ try {
6916
+ response = await awaitWithAbort(
6917
+ this.fetchImpl(this.url(path, query), {
6918
+ method,
6919
+ headers: {
6920
+ ...this.headers(correlationId),
6921
+ Accept: "application/json",
6922
+ ...(body !== undefined ? { "Content-Type": "application/json" } : {}),
6923
+ },
6924
+ ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
6925
+ ...(abort.signal ? { signal: abort.signal } : {}),
6926
+ }),
6927
+ abort.signal,
6928
+ );
6929
+ } catch (error) {
6930
+ if (options.signal?.aborted) throw error;
6931
+ if (isMutationMethod(method)) {
6932
+ throw mutationTransportError(correlationId);
6933
+ }
6934
+ throw error;
6015
6935
  }
6016
- throw error;
6017
- }
6018
- assertApiContractResponse(response);
6019
- if (!response.ok) {
6020
- throw await apiErrorFromResponse(response, { method, correlationId });
6021
- }
6022
- await assertJsonResponse(response, { method, correlationId });
6023
- try {
6024
- return (await response.json()) as T;
6025
- } catch (error) {
6026
- if (isMutationMethod(method)) {
6027
- throw mutationTransportError(correlationId);
6936
+ assertApiContractResponse(response);
6937
+ if (!response.ok) {
6938
+ throw await apiErrorFromResponse(response, { method, correlationId });
6028
6939
  }
6029
- throw error;
6940
+ await assertJsonResponse(response, { method, correlationId });
6941
+ try {
6942
+ return (await response.json()) as T;
6943
+ } catch (error) {
6944
+ if (options.signal?.aborted) throw error;
6945
+ if (isMutationMethod(method)) {
6946
+ throw mutationTransportError(correlationId);
6947
+ }
6948
+ throw error;
6949
+ }
6950
+ } finally {
6951
+ abort.dispose();
6030
6952
  }
6031
6953
  }
6032
6954
 
@@ -6059,8 +6981,8 @@ export class OpenGeniClient {
6059
6981
  return response;
6060
6982
  }
6061
6983
 
6062
- /** Like `requestJson` for endpoints that respond with no body (204). */
6063
- private async requestVoid(method: string, path: string, body?: unknown): Promise<void> {
6984
+ /** Contract-checked transport shared by opt-in typed SDK clients for 204 responses. */
6985
+ async requestVoid(method: string, path: string, body?: unknown): Promise<void> {
6064
6986
  const correlationId = crypto.randomUUID();
6065
6987
  let response: Response;
6066
6988
  try {
@@ -6210,6 +7132,59 @@ function filenameForAudioMimeType(mimeType: string): string {
6210
7132
 
6211
7133
  const API_ERROR_MAX_BYTES = 16 * 1024;
6212
7134
 
7135
+ function requestAbortSignal(options: OpenGeniRequestOptions): {
7136
+ signal: AbortSignal | undefined;
7137
+ dispose: () => void;
7138
+ } {
7139
+ const timeoutMs = options.timeoutMs ?? 0;
7140
+ if (timeoutMs <= 0) {
7141
+ return { signal: options.signal, dispose: () => undefined };
7142
+ }
7143
+ const controller = new AbortController();
7144
+ const onCallerAbort = () => controller.abort(options.signal?.reason);
7145
+ if (options.signal?.aborted) {
7146
+ onCallerAbort();
7147
+ } else {
7148
+ options.signal?.addEventListener("abort", onCallerAbort, { once: true });
7149
+ }
7150
+ const timer = setTimeout(
7151
+ () => controller.abort(new DOMException("Request timed out", "TimeoutError")),
7152
+ timeoutMs,
7153
+ );
7154
+ return {
7155
+ signal: controller.signal,
7156
+ dispose: () => {
7157
+ clearTimeout(timer);
7158
+ options.signal?.removeEventListener("abort", onCallerAbort);
7159
+ },
7160
+ };
7161
+ }
7162
+
7163
+ async function awaitWithAbort<T>(promise: Promise<T>, signal: AbortSignal | undefined): Promise<T> {
7164
+ if (!signal) return await promise;
7165
+ if (signal.aborted) {
7166
+ throw signal.reason ?? new DOMException("Request aborted", "AbortError");
7167
+ }
7168
+ return await new Promise<T>((resolve, reject) => {
7169
+ const onAbort = () => {
7170
+ cleanup();
7171
+ reject(signal.reason ?? new DOMException("Request aborted", "AbortError"));
7172
+ };
7173
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
7174
+ signal.addEventListener("abort", onAbort, { once: true });
7175
+ promise.then(
7176
+ (value) => {
7177
+ cleanup();
7178
+ resolve(value);
7179
+ },
7180
+ (cause) => {
7181
+ cleanup();
7182
+ reject(cause);
7183
+ },
7184
+ );
7185
+ });
7186
+ }
7187
+
6213
7188
  type ApiErrorRequestContext = {
6214
7189
  method: string;
6215
7190
  correlationId?: string | undefined;
@@ -6298,12 +7273,15 @@ async function cancelResponseBody(response: Response, reason: string): Promise<v
6298
7273
  await response.body?.cancel(reason).catch(() => undefined);
6299
7274
  }
6300
7275
 
6301
- function assertRetainedGeneratedImageReceipt(
7276
+ function assertRetainedWorkspaceArtifactReceipt(
6302
7277
  workspaceId: string,
6303
7278
  artifact: RetainedArtifactReference,
6304
7279
  ): void {
6305
- if (!parseRetainedGeneratedImageReference(artifact, workspaceId)) {
6306
- throw new OpenGeniApiError(502, "retained generated image receipt is invalid");
7280
+ if (
7281
+ !parseRetainedGeneratedImageReference(artifact, workspaceId) &&
7282
+ !parseRetainedWorkspaceFileReference(artifact, workspaceId)
7283
+ ) {
7284
+ throw new OpenGeniApiError(502, "retained workspace artifact receipt is invalid");
6307
7285
  }
6308
7286
  }
6309
7287