@opengeni/sdk 0.15.0 → 0.23.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.
package/src/types.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { WorkspaceTranscriptionPolicy } from "./transcription";
2
+
1
3
  // Hand-written mirrors of the public wire shapes in `@opengeni/contracts`.
2
4
  // The SDK keeps zero runtime dependencies so it stays framework-agnostic and
3
5
  // publishable on its own; `test/contract-parity.test.ts` pins these types to
@@ -148,7 +150,11 @@ export type StreamUrlRotatedPayload = {
148
150
  transport: "vnc-ws";
149
151
  viewerId: string | null;
150
152
  };
151
- export type StreamOpenedPayload = { viewerId: string; shared: boolean; viewerCount: number };
153
+ export type StreamOpenedPayload = {
154
+ viewerId: string;
155
+ shared: boolean;
156
+ viewerCount: number;
157
+ };
152
158
  export type StreamClosedPayload = {
153
159
  viewerId: string;
154
160
  reason: "client-disconnect" | "reaped" | "revoked" | "box-rollover";
@@ -164,7 +170,10 @@ export type StreamRevokedPayload = {
164
170
  // `desktop:true` opts into the un-redacted pixel plane (the consent-gated noVNC
165
171
  // stream); a terminal/files-only warm attach omits it (defaults false) so it
166
172
  // warms the box + mints the pty-ws terminal cell WITHOUT tripping the consent 409.
167
- export type AttachViewerRequest = { viewerId?: string | undefined; desktop?: boolean | undefined };
173
+ export type AttachViewerRequest = {
174
+ viewerId?: string | undefined;
175
+ desktop?: boolean | undefined;
176
+ };
168
177
 
169
178
  // Mirror of `@opengeni/contracts` ViewerHolder + the P4.2 desktop-stream fields
170
179
  // the POST /viewers handler folds in when the pixel plane is minted in-process.
@@ -202,7 +211,10 @@ export type AcknowledgeStreamRequest = {
202
211
  acknowledgeUnredacted?: boolean | undefined;
203
212
  acknowledgeShared?: boolean | undefined;
204
213
  };
205
- export type AcknowledgeStreamResponse = { acknowledged: boolean; acknowledgedShared: boolean };
214
+ export type AcknowledgeStreamResponse = {
215
+ acknowledged: boolean;
216
+ acknowledgedShared: boolean;
217
+ };
206
218
 
207
219
  // Mirror of `@opengeni/contracts` ViewerHeartbeatRequest/Response — the
208
220
  // Channel-A viewer-liveness ping, epoch-fenced (a stale-epoch beat → alive:false
@@ -212,14 +224,24 @@ export type ViewerHeartbeatResponse = { alive: boolean };
212
224
 
213
225
  export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
214
226
  export type GitCredentialProvider = "github" | "gitlab" | "azure_devops";
227
+ export type GitCredentialBindingId = string;
228
+ export type GitRepositoryAccess = "read" | "write";
215
229
 
216
230
  export type RepositoryResourceRef = {
217
231
  kind: "repository";
218
232
  uri: string;
219
233
  ref: string;
234
+ /**
235
+ * Optional workspace-relative override. When omitted, OpenGeni persists
236
+ * `repos/<encoded-host>/<owner>/<repo>` so equal names on different Git
237
+ * providers do not collide. Explicit paths are portable, traversal-free, and
238
+ * collision-checked case-insensitively before sandbox execution.
239
+ */
220
240
  mountPath?: string | undefined;
221
241
  subpath?: string | undefined;
222
242
  provider?: GitCredentialProvider | undefined;
243
+ credentialBindingId?: GitCredentialBindingId | undefined;
244
+ access?: GitRepositoryAccess | undefined;
223
245
  repositoryId?: number | string | undefined;
224
246
  installationId?: number | string | undefined;
225
247
  projectId?: number | string | undefined;
@@ -231,6 +253,7 @@ export type RepositoryResourceRef = {
231
253
  export type FileResourceRef = {
232
254
  kind: "file";
233
255
  fileId: string;
256
+ /** Optional workspace-relative override; defaults to `files/<file-id>`. */
234
257
  mountPath?: string | undefined;
235
258
  };
236
259
 
@@ -239,6 +262,35 @@ export type ResourceRef = RepositoryResourceRef | FileResourceRef;
239
262
  export type ToolRef = {
240
263
  kind: "mcp";
241
264
  id: string;
265
+ optional?: boolean | undefined;
266
+ };
267
+
268
+ export type SessionToolPolicy = {
269
+ mode: "workspace_default" | "explicit" | "inherited" | "legacy";
270
+ inheritedFromSessionId: string | null;
271
+ };
272
+
273
+ export type SessionEffectiveToolPolicy = {
274
+ mode: SessionToolPolicy["mode"];
275
+ inheritedFromSessionId: string | null;
276
+ selectedIds: string[];
277
+ effectiveIds: string[];
278
+ mandatoryIds: string[];
279
+ lazyRouter: {
280
+ state: "required" | "disabled";
281
+ deferredIds: string[];
282
+ };
283
+ configuredIds: string[];
284
+ droppedIds: string[];
285
+ counts: {
286
+ selected: number;
287
+ effective: number;
288
+ mandatory: number;
289
+ deferred: number;
290
+ configured: number;
291
+ dropped: number;
292
+ };
293
+ idsTruncated: boolean;
242
294
  };
243
295
 
244
296
  export type GoalSpec = {
@@ -254,7 +306,10 @@ export type SessionMcpServerInput = {
254
306
  allowedTools?: string[] | undefined;
255
307
  timeoutMs?: number | undefined;
256
308
  cacheToolsList?: boolean | undefined;
309
+ /** Require human approval for every tool, or only the listed unprefixed tool names. */
310
+ requireApproval?: boolean | string[] | undefined;
257
311
  headers?: Record<string, string> | undefined;
312
+ connectionRef?: McpServerConnectionRef | undefined;
258
313
  };
259
314
 
260
315
  export type SessionMcpCredentialUpdateInput = {
@@ -262,12 +317,25 @@ export type SessionMcpCredentialUpdateInput = {
262
317
  headers: Record<string, string>;
263
318
  };
264
319
 
320
+ export type SessionMcpApprovalPolicy = boolean | string[];
321
+
265
322
  export type SessionMcpServerMetadata = {
266
323
  id: string;
267
324
  name: string | null;
268
325
  url: string;
269
326
  headerNames: string[];
270
327
  credentialVersion: number;
328
+ requireApproval: SessionMcpApprovalPolicy;
329
+ connectionRef: McpServerConnectionRef | null;
330
+ };
331
+
332
+ export type UpdateSessionMcpApprovalPolicyRequest = {
333
+ requireApproval: SessionMcpApprovalPolicy;
334
+ };
335
+
336
+ export type UpdateSessionMcpApprovalPolicyResponse = {
337
+ server: SessionMcpServerMetadata;
338
+ effectiveFrom: "next_attempt";
271
339
  };
272
340
 
273
341
  export type ConnectionKind = "oauth2" | "api_key" | "app_install" | "delegated";
@@ -275,10 +343,17 @@ export type ConnectionStatus = "active" | "needs_reauth" | "revoked" | "error";
275
343
 
276
344
  export type McpServerConnectionRef = {
277
345
  connectionId?: string | undefined;
346
+ provider?: string | undefined;
278
347
  providerDomain: string;
279
348
  kind?: ConnectionKind | undefined;
280
349
  scopes?: string[] | undefined;
281
350
  resource?: string | undefined;
351
+ selectedResources?:
352
+ | Array<{
353
+ id: string;
354
+ kind: "repository";
355
+ }>
356
+ | undefined;
282
357
  subjectScope?: "workspace" | "subject" | undefined;
283
358
  };
284
359
 
@@ -354,6 +429,20 @@ export type OAuthStartResponse = {
354
429
  expiresAt: string;
355
430
  };
356
431
 
432
+ /** The immutable principal whose authority accepted a session or turn. */
433
+ export type TurnInitiator = {
434
+ kind: "subject" | "service";
435
+ subjectId: string;
436
+ /** Display-only snapshot; never an authorization input. */
437
+ label?: string | undefined;
438
+ };
439
+
440
+ /** A trusted embedding host's causal machine/service principal. */
441
+ export type ServiceTurnInitiator = TurnInitiator & { kind: "service" };
442
+
443
+ /** Bounded host provenance; OpenGeni-owned lineage keys are reserved. */
444
+ export type ServiceTurnInitiatorContext = Record<string, unknown>;
445
+
357
446
  export type IntegrationClientMetadata = {
358
447
  client_id: string;
359
448
  client_name: "OpenGeni";
@@ -376,7 +465,12 @@ export type Session = {
376
465
  instructions: string | null;
377
466
  resources: ResourceRef[];
378
467
  tools: ToolRef[];
468
+ toolPolicy?: SessionToolPolicy | undefined;
469
+ effectiveToolPolicy?: SessionEffectiveToolPolicy | undefined;
379
470
  metadata: Record<string, unknown>;
471
+ /** Frozen creator fact; later turns carry their own independent initiator. */
472
+ createdBy: TurnInitiator;
473
+ createdByContext: Record<string, unknown>;
380
474
  model: string;
381
475
  sandboxBackend: SandboxBackend;
382
476
  sandboxOs: SandboxOs;
@@ -421,17 +515,26 @@ export type Session = {
421
515
  attentionDescendants: number;
422
516
  pausedDescendants: number;
423
517
  failedDescendants: number;
518
+ /** Counts are lower bounds rather than exact totals when true. */
519
+ truncated: boolean;
424
520
  }
425
521
  | undefined;
426
522
  createdAt: string;
427
523
  updatedAt: string;
428
524
  };
429
525
 
526
+ /** Additive receipt returned by POST /sessions. */
527
+ export type CreateSessionResponse = Session & {
528
+ initialTurnId: string | null;
529
+ };
530
+
430
531
  export type SessionSummary = Session;
431
532
 
432
533
  /** Canonical session-list page; pinned rows are excluded from ordinary pages. */
433
534
  export type SessionListResponse = {
434
535
  pinned: Session[];
536
+ /** True when the server omitted older pins from its bounded pinned section. */
537
+ pinnedTruncated?: boolean;
435
538
  sessions: Session[];
436
539
  nextCursor: string | null;
437
540
  };
@@ -484,6 +587,7 @@ export type SessionTurn = {
484
587
  prompt: string;
485
588
  resources: ResourceRef[];
486
589
  tools: ToolRef[];
590
+ toolsProvided?: boolean | undefined;
487
591
  model: string;
488
592
  reasoningEffort: ReasoningEffort;
489
593
  sandboxBackend: SandboxBackend;
@@ -493,6 +597,8 @@ export type SessionTurn = {
493
597
  executionGeneration: number;
494
598
  activeAttemptId: string | null;
495
599
  lineage: Record<string, unknown>;
600
+ initiator: TurnInitiator;
601
+ initiatorContext: Record<string, unknown>;
496
602
  cancelledBy?: string | null;
497
603
  cancelReason?: string | null;
498
604
  startedAt: string | null;
@@ -501,10 +607,74 @@ export type SessionTurn = {
501
607
  updatedAt: string;
502
608
  };
503
609
 
610
+ export type HumanInputQuestionKind = "text" | "single_select" | "multi_select";
611
+
612
+ export type HumanInputOption = {
613
+ id: string;
614
+ label: string;
615
+ description?: string | null | undefined;
616
+ };
617
+
618
+ export type HumanInputQuestion = {
619
+ id: string;
620
+ kind: HumanInputQuestionKind;
621
+ prompt: string;
622
+ label?: string | null | undefined;
623
+ helpText?: string | null | undefined;
624
+ options: HumanInputOption[];
625
+ required: boolean;
626
+ allowOther: boolean;
627
+ validation?:
628
+ | {
629
+ minLength?: number | null | undefined;
630
+ maxLength?: number | null | undefined;
631
+ minSelections?: number | null | undefined;
632
+ maxSelections?: number | null | undefined;
633
+ }
634
+ | null
635
+ | undefined;
636
+ };
637
+
638
+ export type HumanInputAnswer = {
639
+ questionId: string;
640
+ values: string[];
641
+ other?: string | null | undefined;
642
+ };
643
+
644
+ export type HumanInputResponse =
645
+ | { outcome: "answered"; answers: HumanInputAnswer[] }
646
+ | { outcome: "skipped" | "expired" | "cancelled" };
647
+
648
+ export type SubmitHumanInputResponseRequest =
649
+ | { outcome: "answered"; answers: HumanInputAnswer[] }
650
+ | { outcome: "skipped" };
651
+
652
+ export type SessionHumanInputRequest = {
653
+ id: string;
654
+ workspaceId: string;
655
+ sessionId: string;
656
+ turnId: string;
657
+ turnGeneration: number;
658
+ creationAttemptId: string;
659
+ toolCallId: string;
660
+ status: "pending" | "answered" | "skipped" | "expired" | "cancelled";
661
+ questions: HumanInputQuestion[];
662
+ allowSkip: boolean;
663
+ response: HumanInputResponse | null;
664
+ respondedBy: string | null;
665
+ respondedAt: string | null;
666
+ expiresAt: string | null;
667
+ createdAt: string;
668
+ updatedAt: string;
669
+ };
670
+
504
671
  export const SESSION_EVENT_TYPES = [
505
672
  "session.created",
673
+ // Defensive bounded projection for malformed/legacy oversized envelopes.
674
+ "session.event.envelope_omitted",
506
675
  "session.status.changed",
507
676
  "session.requiresAction",
677
+ "session.humanInput.requested",
508
678
  "session.context.compaction.requested",
509
679
  "session.context.compacted",
510
680
  "session.context.compaction.skipped",
@@ -512,6 +682,7 @@ export const SESSION_EVENT_TYPES = [
512
682
  "user.message",
513
683
  "user.pause",
514
684
  "user.approvalDecision",
685
+ "user.humanInputResponse",
515
686
  "turn.queued",
516
687
  "turn.started",
517
688
  "turn.completed",
@@ -525,8 +696,10 @@ export const SESSION_EVENT_TYPES = [
525
696
  "agent.reasoning.delta",
526
697
  "agent.toolCall.created",
527
698
  "agent.toolCall.output",
699
+ "agent.model.request",
528
700
  "agent.model.usage",
529
701
  "tool.auth_needed",
702
+ "credential.auth_needed",
530
703
  "agent.updated",
531
704
  "rig.setup.started",
532
705
  "rig.setup.completed",
@@ -575,11 +748,12 @@ export const SESSION_EVENT_TYPES = [
575
748
  "terminal.pty.output.delta",
576
749
  "terminal.pty.exited",
577
750
  "session.title_set",
751
+ "session.mcp.approval_policy.updated",
578
752
  // Multi-account Codex (P1): the session's inference account changed.
579
753
  "codex.account.switched",
580
- // OPE-21 metadata-only per-turn credential selection audit.
754
+ // credential allocator metadata-only per-turn credential selection audit.
581
755
  "codex.credential.selected",
582
- // OPE-21 durable zero-capacity wait lifecycle. These are system/runtime
756
+ // credential allocator durable zero-capacity wait lifecycle. These are system/runtime
583
757
  // events, never synthetic user messages.
584
758
  "codex.capacity.waiting",
585
759
  "codex.capacity.resumed",
@@ -635,14 +809,137 @@ export type SessionEvent = {
635
809
  duplicateReason?: string | null | undefined;
636
810
  };
637
811
 
812
+ export type SessionEventSemanticClass =
813
+ | "control"
814
+ | "terminal"
815
+ | "failure"
816
+ | "checkpoint"
817
+ | "tool_receipt"
818
+ | "provider_account";
819
+ export type SessionEventLatestClass = SessionEventSemanticClass | "receipt";
820
+ export type SessionEventPayloadMode = "none" | "summary" | "full";
821
+ export type SessionEventReadMode = "monitoring" | "forensic";
822
+ export type SessionEventReadDirection = "after" | "before";
823
+ export type SessionEventResultMode = "events" | "compact";
824
+
825
+ type SessionEventListCommonOptions = {
826
+ after?: number;
827
+ before?: number;
828
+ limit?: number;
829
+ compact?: boolean;
830
+ mode?: SessionEventReadMode;
831
+ direction?: SessionEventReadDirection;
832
+ payloadMode?: SessionEventPayloadMode;
833
+ resultMode?: "events";
834
+ };
835
+
836
+ export type SessionEventListOptions = SessionEventListCommonOptions &
837
+ (
838
+ | {
839
+ latest?: never;
840
+ includeTypes?: SessionEventType[];
841
+ excludeTypes?: SessionEventType[];
842
+ includeClasses?: SessionEventSemanticClass[];
843
+ excludeClasses?: SessionEventSemanticClass[];
844
+ }
845
+ | {
846
+ /** Exclusive lookup for the newest event in exactly this semantic class. */
847
+ latest: SessionEventLatestClass;
848
+ includeTypes?: never;
849
+ excludeTypes?: never;
850
+ includeClasses?: never;
851
+ excludeClasses?: never;
852
+ }
853
+ );
854
+
855
+ export type SessionEventCompactResult = {
856
+ version: 1;
857
+ semanticClass: SessionEventSemanticClass;
858
+ source: {
859
+ id: string;
860
+ type: SessionEventType;
861
+ sequence: number;
862
+ occurredAt: string;
863
+ turnId: string | null;
864
+ turnGeneration: number | null;
865
+ turnAttemptId: string | null;
866
+ turnAssociation: SessionEvent["turnAssociation"];
867
+ };
868
+ id: string;
869
+ type: SessionEventType;
870
+ sequence: number;
871
+ occurredAt: string;
872
+ turnId: string | null;
873
+ turnGeneration: number | null;
874
+ turnAttemptId: string | null;
875
+ turnAssociation: SessionEvent["turnAssociation"];
876
+ coveredSequence: { first: number; last: number };
877
+ status:
878
+ | "completed"
879
+ | "failed"
880
+ | "cancelled"
881
+ | "superseded"
882
+ | "checkpoint"
883
+ | "receipt"
884
+ | "unknown";
885
+ text: string | null;
886
+ output: unknown;
887
+ result: unknown;
888
+ failure: {
889
+ error: string | null;
890
+ code: string | null;
891
+ retryable: boolean | null;
892
+ recovery: string | null;
893
+ } | null;
894
+ checkpoint: unknown;
895
+ receipt: unknown;
896
+ truncation: {
897
+ truncated: boolean;
898
+ fields: string[];
899
+ originalBytes: number | null;
900
+ deliveredBytes: number;
901
+ };
902
+ };
903
+
904
+ export type SessionEventCompactResultOptions = {
905
+ latest: SessionEventLatestClass;
906
+ resultMode: "compact";
907
+ mode?: SessionEventReadMode;
908
+ payloadMode?: SessionEventPayloadMode;
909
+ };
910
+
911
+ export type SessionEventPage = {
912
+ events: SessionEvent[];
913
+ mode: SessionEventReadMode;
914
+ payloadMode: SessionEventPayloadMode;
915
+ direction: SessionEventReadDirection;
916
+ bytes: number;
917
+ maxBytes: number;
918
+ truncated: boolean;
919
+ hasMore: boolean;
920
+ truncatedBy: "count" | "bytes" | "http_bytes" | null;
921
+ coveredSequence: { first: number; last: number } | null;
922
+ nextAfter: number | null;
923
+ nextBefore: number | null;
924
+ forensicExact: boolean;
925
+ };
926
+
638
927
  export type ToolAuthNeededPayload = {
639
928
  serverId: string;
640
929
  toolName?: string | null | undefined;
641
930
  providerDomain: string;
931
+ provider?: string | undefined;
642
932
  connectionId?: string | null | undefined;
643
- reason: "missing_connection" | "expired" | "insufficient_scope" | "refresh_failed";
933
+ reason:
934
+ | "missing_connection"
935
+ | "expired"
936
+ | "insufficient_scope"
937
+ | "refresh_failed"
938
+ | "unsupported_auth"
939
+ | "resource_scope_unavailable";
644
940
  scopes?: string[] | undefined;
645
941
  resource?: string | undefined;
942
+ selectedResources?: Array<{ id: string; kind: "repository" }> | undefined;
646
943
  authorizationUrl?: string | undefined;
647
944
  subjectId?: string | null | undefined;
648
945
  };
@@ -771,8 +1068,16 @@ export type FsListRequest = {
771
1068
  maxEntries?: number;
772
1069
  includeHidden?: boolean;
773
1070
  };
774
- export type FsListResponse = { root: FsTreeNode; revision: number; truncated: boolean };
775
- export type FsReadRequest = { path: string; encoding?: FsEncoding; maxBytes?: number };
1071
+ export type FsListResponse = {
1072
+ root: FsTreeNode;
1073
+ revision: number;
1074
+ truncated: boolean;
1075
+ };
1076
+ export type FsReadRequest = {
1077
+ path: string;
1078
+ encoding?: FsEncoding;
1079
+ maxBytes?: number;
1080
+ };
776
1081
  export type FsReadResponse = {
777
1082
  path: string;
778
1083
  encoding: FsEncoding;
@@ -789,7 +1094,11 @@ export type FsWriteRequest = {
789
1094
  overwrite?: boolean;
790
1095
  createParents?: boolean;
791
1096
  };
792
- export type FsWriteResponse = { path: string; sizeBytes: number; revision: number };
1097
+ export type FsWriteResponse = {
1098
+ path: string;
1099
+ sizeBytes: number;
1100
+ revision: number;
1101
+ };
793
1102
  export type FsDeleteRequest = { path: string; recursive?: boolean };
794
1103
  export type FsDeleteResponse = { revision: number };
795
1104
  export type FsMoveRequest = {
@@ -798,7 +1107,11 @@ export type FsMoveRequest = {
798
1107
  overwrite?: boolean;
799
1108
  createParents?: boolean;
800
1109
  };
801
- export type FsMoveResponse = { path: string; newPath: string; revision: number };
1110
+ export type FsMoveResponse = {
1111
+ path: string;
1112
+ newPath: string;
1113
+ revision: number;
1114
+ };
802
1115
  export type FsMkdirRequest = { path: string; recursive?: boolean };
803
1116
  export type FsMkdirResponse = { path: string; revision: number };
804
1117
 
@@ -860,6 +1173,7 @@ export type GitFileDiff = {
860
1173
  export type GitDiffRequest = {
861
1174
  path?: string;
862
1175
  staged?: boolean;
1176
+ includeUntracked?: boolean;
863
1177
  fromRef?: string;
864
1178
  toRef?: string;
865
1179
  pathspec?: string[];
@@ -895,12 +1209,17 @@ export type GitShowRequest = {
895
1209
  export type GitShowResponse = {
896
1210
  commit: GitCommit | null;
897
1211
  files: GitFileDiff[];
898
- blob: { content: string; encoding: FsEncoding; sizeBytes: number; truncated: boolean } | null;
1212
+ blob: {
1213
+ content: string;
1214
+ encoding: FsEncoding;
1215
+ sizeBytes: number;
1216
+ truncated: boolean;
1217
+ } | null;
899
1218
  revision: number;
900
1219
  };
901
1220
 
902
1221
  // Workbench v2 turn-end capture (mirror of `@opengeni/contracts` WorkspaceCapture*
903
- // + the M2 read-API response shapes, dossier §10.3). Reuses FsTreeNode /
1222
+ // + the M2 read-API response shapes). Reuses FsTreeNode /
904
1223
  // GitFileStatus / GitFileDiff / GitFileStatusCode / FsEncoding above.
905
1224
  export type WorkspaceCaptureFile = {
906
1225
  path: string;
@@ -1018,8 +1337,17 @@ export type TerminalExecResponse = {
1018
1337
  running: boolean;
1019
1338
  wallTimeSeconds: number;
1020
1339
  };
1021
- export type PtyOpenRequest = { cols?: number; rows?: number; cwd?: string; shell?: string };
1022
- export type PtyOpenResponse = { ptyId: string; streamVia: "sse-events"; supportsInput: boolean };
1340
+ export type PtyOpenRequest = {
1341
+ cols?: number;
1342
+ rows?: number;
1343
+ cwd?: string;
1344
+ shell?: string;
1345
+ };
1346
+ export type PtyOpenResponse = {
1347
+ ptyId: string;
1348
+ streamVia: "sse-events";
1349
+ supportsInput: boolean;
1350
+ };
1023
1351
  export type PtyWriteRequest = { ptyId: string; data: string };
1024
1352
  export type PtyResizeRequest = { ptyId: string; cols: number; rows: number };
1025
1353
  export type PtyCloseRequest = { ptyId: string };
@@ -1095,7 +1423,13 @@ export type ScheduledTask = {
1095
1423
  };
1096
1424
 
1097
1425
  export type CreateSessionRequest = {
1426
+ // Optional UUID preallocated by an embedding host so it can durably link its
1427
+ // projection before OpenGeni admits the initial turn. Replays must retain the
1428
+ // same UUID and idempotency key.
1429
+ requestedSessionId?: string | undefined;
1098
1430
  initialMessage: string;
1431
+ /** System instructions scoped to the initial turn; never visible timeline text. */
1432
+ turnInstructions?: string | undefined;
1099
1433
  // Per-session agent persona/system instructions (org-visible metadata, not a
1100
1434
  // secret). Delivered system-level, composed AFTER the per-workspace persona —
1101
1435
  // how a host supplies per-agent-type prompts without leaking them into the
@@ -1150,7 +1484,7 @@ export const KNOWN_PERMISSIONS = [
1150
1484
  "sessions:create",
1151
1485
  "sessions:read",
1152
1486
  "sessions:control",
1153
- // Sandbox-surfacing (mirror of @opengeni/contracts Permission). stream:view is
1487
+ // sandbox workspace (mirror of @opengeni/contracts Permission). stream:view is
1154
1488
  // strictly broader than sessions:read (un-redacted pixels); stream:control is
1155
1489
  // the never-granted-v1 raw-input plane; stream:acknowledge is the secret-leak
1156
1490
  // consent gate.
@@ -1193,6 +1527,68 @@ export type Permission = KnownPermission | (string & {});
1193
1527
 
1194
1528
  export type ProductAccessMode = "local" | "configured" | "managed";
1195
1529
 
1530
+ export type ModelCapabilitySupportV1 = "supported" | "unsupported" | "unknown";
1531
+
1532
+ export type ModelCapabilityStateV1 = {
1533
+ upstream: ModelCapabilitySupportV1;
1534
+ runnable: boolean;
1535
+ };
1536
+
1537
+ export type ModelCapabilitiesV1 = {
1538
+ reasoning: ModelCapabilityStateV1 & {
1539
+ efforts: ReasoningEffort[];
1540
+ defaultEffort: ReasoningEffort | null;
1541
+ required: boolean;
1542
+ };
1543
+ functionCalling: ModelCapabilityStateV1;
1544
+ structuredOutput: ModelCapabilityStateV1;
1545
+ hostedTools: {
1546
+ webSearch: ModelCapabilityStateV1;
1547
+ xSearch: ModelCapabilityStateV1;
1548
+ codeExecution: ModelCapabilityStateV1;
1549
+ };
1550
+ inputModalities: Array<"text" | "image" | "audio">;
1551
+ outputModalities: Array<"text" | "image" | "audio">;
1552
+ transports: {
1553
+ sse: ModelCapabilityStateV1;
1554
+ responsesWebSocket: ModelCapabilityStateV1;
1555
+ realtimeAudio: ModelCapabilityStateV1;
1556
+ };
1557
+ latencyModes: Array<{
1558
+ id: "standard" | "priority" | "fast";
1559
+ upstream: ModelCapabilitySupportV1;
1560
+ runnable: boolean;
1561
+ billingMultiplierBps?: number | undefined;
1562
+ }>;
1563
+ };
1564
+
1565
+ export type ModelCredentialSourceV1 =
1566
+ | { kind: "deployment"; mechanism: "api_key" | "azure_ad_bearer" }
1567
+ | { kind: "connected_subscription"; provider: "codex" }
1568
+ | { kind: "workspace_connection"; mechanism: "api_key" };
1569
+
1570
+ export type ModelBillingAttributionV1 = {
1571
+ upstreamPayer: "deployment" | "workspace" | "connected_subscription";
1572
+ metering: "opengeni_credits" | "external";
1573
+ };
1574
+
1575
+ export type ModelPricingV1 = {
1576
+ inputMicrosPerMillionTokens: number;
1577
+ cachedInputMicrosPerMillionTokens?: number | undefined;
1578
+ outputMicrosPerMillionTokens: number;
1579
+ marginBps?: number | undefined;
1580
+ };
1581
+
1582
+ export type ModelPricingScheduleV1 = {
1583
+ default: ModelPricingV1;
1584
+ inputTokenTiers?:
1585
+ | Array<{
1586
+ minimumInputTokens: number;
1587
+ pricing: ModelPricingV1;
1588
+ }>
1589
+ | undefined;
1590
+ };
1591
+
1196
1592
  /**
1197
1593
  * One model a client may select at send time, plus the provider that serves it.
1198
1594
  * The wire API (`responses` | `chat`) lets a client reason about provider
@@ -1207,6 +1603,64 @@ export type ClientModel = {
1207
1603
  providerLabel: string;
1208
1604
  api: "responses" | "chat";
1209
1605
  contextWindowTokens?: number | undefined;
1606
+ schemaVersion?: 1 | undefined;
1607
+ aliases?: string[] | undefined;
1608
+ deployment?:
1609
+ | {
1610
+ upstreamModelId: string;
1611
+ wireApi: "responses" | "chat";
1612
+ }
1613
+ | undefined;
1614
+ executionLimits?:
1615
+ | {
1616
+ contextWindowTokens: number | null;
1617
+ effectiveContextWindowTokens: number | null;
1618
+ autoCompactTokenLimit: number | null;
1619
+ toolOutputTruncationTokens: number | null;
1620
+ }
1621
+ | undefined;
1622
+ credentialSource?: ModelCredentialSourceV1 | undefined;
1623
+ billing?: ModelBillingAttributionV1 | undefined;
1624
+ capabilities?: ModelCapabilitiesV1 | undefined;
1625
+ pricing?: ModelPricingScheduleV1 | undefined;
1626
+ definitionVersion?: string | undefined;
1627
+ };
1628
+
1629
+ export type ModelAvailabilityV1 = {
1630
+ status: "available" | "unavailable" | "degraded" | "unknown";
1631
+ selectable: boolean;
1632
+ reason:
1633
+ | "missing_credential"
1634
+ | "needs_reauth"
1635
+ | "credential_not_ready"
1636
+ | "not_entitled"
1637
+ | "provider_unhealthy"
1638
+ | "policy_blocked"
1639
+ | "unsupported"
1640
+ | null;
1641
+ checkedAt: string | null;
1642
+ };
1643
+
1644
+ export type ModelCredentialReadinessV1 = {
1645
+ status: "ready" | "not_ready" | "error";
1646
+ reason:
1647
+ | "missing_credential"
1648
+ | "needs_reauth"
1649
+ | "prerequisites_missing"
1650
+ | "resolver_error"
1651
+ | "observation_stale"
1652
+ | null;
1653
+ basis: "configuration" | "connection" | "resolver";
1654
+ checkedAt: string | null;
1655
+ };
1656
+
1657
+ export type WorkspaceModelCatalogModel = ClientModel & {
1658
+ credentialReadiness: ModelCredentialReadinessV1;
1659
+ availability: ModelAvailabilityV1;
1660
+ };
1661
+
1662
+ export type WorkspaceModelCatalogResponse = {
1663
+ models: WorkspaceModelCatalogModel[];
1210
1664
  };
1211
1665
 
1212
1666
  /**
@@ -1223,7 +1677,11 @@ export type CodexConnectionStatus = {
1223
1677
  lastError?: string | null;
1224
1678
  models?: ClientModel[];
1225
1679
  /** The account a session runs on when unpinned (label for the in-session indicator). */
1226
- activeAccount?: { id: string; label?: string | null; chatgptAccountId?: string | null } | null;
1680
+ activeAccount?: {
1681
+ id: string;
1682
+ label?: string | null;
1683
+ chatgptAccountId?: string | null;
1684
+ } | null;
1227
1685
  /** How many Codex accounts the workspace has connected. */
1228
1686
  accountCount?: number;
1229
1687
  };
@@ -1254,6 +1712,8 @@ export type CodexUsagePayload = {
1254
1712
  weekly: CodexUsageWindow | null;
1255
1713
  limitReached: boolean;
1256
1714
  fetchedAt: string;
1715
+ /** Authoritative count-only summary from /wham/usage; never synthesized rows. */
1716
+ rateLimitResetCredits?: { availableCount: number; credits: null } | null;
1257
1717
  /** Present only on an auth/refresh failure path. */
1258
1718
  reason?: "needs_relogin";
1259
1719
  additionalLimits?: Array<{
@@ -1290,6 +1750,76 @@ export type CodexAccount = {
1290
1750
  // P3 rotation cooldown: ISO timestamp until which this account is cooling-down
1291
1751
  // (rotated-off after a usage cap). null/absent ⇒ not cooling.
1292
1752
  exhaustedUntil?: string | null;
1753
+ /** Controls only NEW automatic allocations. */
1754
+ allocatorEnabled: boolean;
1755
+ /** Independent OCC sequence; credential/token `version` is never exposed. */
1756
+ allocatorVersion: number;
1757
+ allocatorUpdatedAt?: string | null;
1758
+ /** Cached authoritative summary count, never detailed redemption authority. */
1759
+ resetCreditAvailableCount?: number | null;
1760
+ resetCreditsCheckedAt?: string | null;
1761
+ };
1762
+
1763
+ export type CodexResetCredit = {
1764
+ id: string;
1765
+ resetType: "codexRateLimits" | "unknown";
1766
+ status: "available" | "redeeming" | "redeemed" | "unknown";
1767
+ /** Unix seconds from the provider contract. */
1768
+ grantedAt: number;
1769
+ /** Unix seconds, or null when the provider reports no expiry. */
1770
+ expiresAt: number | null;
1771
+ title: string | null;
1772
+ description: string | null;
1773
+ /** True only for fresh, complete, owning-human provider detail. */
1774
+ actionable: boolean;
1775
+ };
1776
+
1777
+ /** Owning-human recovery metadata. It contains no token, browser-session hash, or provider key. */
1778
+ export type CodexResetRedemptionRecovery = {
1779
+ attemptId: string;
1780
+ creditId: string;
1781
+ status: "provider_started" | "completed";
1782
+ outcome: "reset" | "nothingToReset" | "noCredit" | "alreadyRedeemed" | null;
1783
+ providerStartedAt: string | null;
1784
+ completedAt: string | null;
1785
+ createdAt: string;
1786
+ updatedAt: string;
1787
+ };
1788
+
1789
+ export type CodexAccountOverview = {
1790
+ accountId: string;
1791
+ usage: {
1792
+ source: "provider" | "cache" | "none";
1793
+ fetchedAt: string | null;
1794
+ stale: boolean;
1795
+ error: string | null;
1796
+ value: CodexUsagePayload | null;
1797
+ };
1798
+ resetCredits: {
1799
+ source: "provider" | "cache" | "none";
1800
+ fetchedAt: string | null;
1801
+ stale: boolean;
1802
+ error: string | null;
1803
+ detailState: "detailed" | "count_only" | "capped" | "unsupported" | "unknown" | "error";
1804
+ detailsComplete: boolean;
1805
+ availableCount: number | null;
1806
+ credits: CodexResetCredit[];
1807
+ };
1808
+ canRedeem: boolean;
1809
+ /** Owning managed-cookie human may replay durable completion without a healthy provider token. */
1810
+ canResumeRedemption: boolean;
1811
+ /** Durable owner-scoped ambiguity/completion discovery; never redemption authority for agents. */
1812
+ redemptions: CodexResetRedemptionRecovery[];
1813
+ };
1814
+
1815
+ /** Independently settled live overview keyed by workspace credential id. */
1816
+ export type CodexOverviewResponse = { accounts: Record<string, CodexAccountOverview> };
1817
+
1818
+ export type CodexAllocatorUpdate = {
1819
+ allocatorEnabled: boolean;
1820
+ allocatorVersion: number;
1821
+ allocatorUpdatedAt: string | null;
1822
+ changed: boolean;
1293
1823
  };
1294
1824
 
1295
1825
  /** Per-workspace Codex rotation/active settings. P1: rotation inert, only activeCredentialId loads. */
@@ -1329,7 +1859,12 @@ export type CodexConnectStart = {
1329
1859
  export type CodexConnectPoll =
1330
1860
  | { status: "pending" }
1331
1861
  | { status: "expired" }
1332
- | { status: "connected"; plan?: string | null; accountId?: string; isActive?: boolean };
1862
+ | {
1863
+ status: "connected";
1864
+ plan?: string | null;
1865
+ accountId?: string;
1866
+ isActive?: boolean;
1867
+ };
1333
1868
 
1334
1869
  /** Remaining usage/limits for one account. `usage` is the normalized P2 payload. */
1335
1870
  export type CodexUsage = {
@@ -1353,7 +1888,7 @@ export type ClientAuthConfig =
1353
1888
 
1354
1889
  // Kept value-identical to @opengeni/contracts and pinned by the SDK contract
1355
1890
  // parity suite. The SDK has no runtime dependency on the Zod contracts package.
1356
- export const OPENGENI_API_CONTRACT_REVISION = "2026-07-session-control-v1" as const;
1891
+ export const OPENGENI_API_CONTRACT_REVISION = "2026-07-turn-instructions-v1" as const;
1357
1892
  export const OPENGENI_API_CONTRACT_HEADER = "x-opengeni-api-contract" as const;
1358
1893
 
1359
1894
  /**
@@ -1380,7 +1915,11 @@ export type ClientConfig = {
1380
1915
  // at all (P4.4). Per-session availability is negotiated on /stream-capabilities;
1381
1916
  // this is the coarse on/off the client uses to decide whether to even attempt
1382
1917
  // the fs/git/terminal panels.
1383
- structuredServices: { fileSystem: boolean; git: boolean; terminalEvents: boolean };
1918
+ structuredServices: {
1919
+ fileSystem: boolean;
1920
+ git: boolean;
1921
+ terminalEvents: boolean;
1922
+ };
1384
1923
  };
1385
1924
 
1386
1925
  export type AccountRole = "owner" | "admin" | "member";
@@ -1401,6 +1940,8 @@ export type AccessGrant = {
1401
1940
  subjectLabel?: string | undefined;
1402
1941
  permissions: Permission[];
1403
1942
  metadata?: Record<string, unknown> | undefined;
1943
+ serviceInitiator?: ServiceTurnInitiator | undefined;
1944
+ serviceInitiatorContext?: ServiceTurnInitiatorContext | undefined;
1404
1945
  };
1405
1946
 
1406
1947
  export type AccessContext = {
@@ -1436,11 +1977,13 @@ export type Workspace = {
1436
1977
 
1437
1978
  export type WorkspaceSettings = {
1438
1979
  memoryEnabled?: boolean | undefined;
1980
+ transcription?: WorkspaceTranscriptionPolicy | undefined;
1439
1981
  [key: string]: unknown;
1440
1982
  };
1441
1983
 
1442
1984
  export type UpdateWorkspaceSettingsRequest = {
1443
1985
  memoryEnabled?: boolean | undefined;
1986
+ transcription?: WorkspaceTranscriptionPolicy | undefined;
1444
1987
  [key: string]: unknown;
1445
1988
  };
1446
1989
 
@@ -1594,7 +2137,12 @@ export type EffectiveSessionControl = {
1594
2137
  blockers: EffectiveControlBlocker[];
1595
2138
  resumeOptions: EffectiveControlResumeOption[];
1596
2139
  override: { rootSessionId: string; revision: number } | null;
1597
- settlement: { state: "stopping"; attemptCount: number } | null;
2140
+ settlement: {
2141
+ state: "stopping";
2142
+ attemptCount: number;
2143
+ interruptionPendingCount: number;
2144
+ quiescencePendingCount: number;
2145
+ } | null;
1598
2146
  };
1599
2147
 
1600
2148
  export type SessionCommandReceipt = {
@@ -1615,6 +2163,8 @@ export type ComposerDraft = {
1615
2163
  text: string;
1616
2164
  resources: ResourceRef[];
1617
2165
  tools: ToolRef[];
2166
+ /** False inherits the session policy; true preserves an explicit array. */
2167
+ toolsProvided: boolean;
1618
2168
  model: string;
1619
2169
  reasoningEffort: ReasoningEffort;
1620
2170
  sourceTurnId: string | null;
@@ -1625,6 +2175,8 @@ export type ComposerDraft = {
1625
2175
  export type SessionQueueSnapshot = {
1626
2176
  version: number;
1627
2177
  effectiveControl: EffectiveSessionControl;
2178
+ /** The latest interrupted attempt has not yet durably proved physical quiescence. */
2179
+ stoppingPreviousAttempt: boolean;
1628
2180
  items: SessionTurn[];
1629
2181
  };
1630
2182
 
@@ -1690,6 +2242,26 @@ export type WorkspaceControlEvent = {
1690
2242
  reason: string | null;
1691
2243
  actor: string;
1692
2244
  occurredAt: string;
2245
+ truncation?: {
2246
+ truncated: true;
2247
+ surface:
2248
+ | "durable_control"
2249
+ | "database_guard"
2250
+ | "http_projection"
2251
+ | "nats_legacy_guard"
2252
+ | "sse_legacy_guard";
2253
+ deliveredBytes: number;
2254
+ fields: Array<{
2255
+ field: "reason" | "actor";
2256
+ originalBytes: number;
2257
+ deliveredBytes: number;
2258
+ omittedBytes: number;
2259
+ }>;
2260
+ fullEvidence: {
2261
+ available: false;
2262
+ reason: "not_retained";
2263
+ };
2264
+ } | null;
1693
2265
  };
1694
2266
 
1695
2267
  export type SessionQueueMutationResponse = {
@@ -1976,6 +2548,67 @@ export type FileAsset = {
1976
2548
  updatedAt: string;
1977
2549
  };
1978
2550
 
2551
+ /** Mirrors the closed, provider-neutral retained-output contract. */
2552
+ export const RETAINED_OUTPUT_DEFAULT_PAGE_BYTES = 256 * 1024;
2553
+ export const RETAINED_OUTPUT_MAX_PAGE_BYTES = 1024 * 1024;
2554
+
2555
+ export type RetainedOutputKind =
2556
+ | "tool_result"
2557
+ | "assistant_completion"
2558
+ | "internal_update"
2559
+ | "event_media"
2560
+ | "file";
2561
+
2562
+ export type RetainedOutputUnavailableReason =
2563
+ | "not_retained"
2564
+ | "pending"
2565
+ | "failed"
2566
+ | "expired"
2567
+ | "deleted"
2568
+ | "missing_storage"
2569
+ | "storage_write_failed"
2570
+ | "unsupported";
2571
+
2572
+ export type RetainedArtifactReference = {
2573
+ available: true;
2574
+ artifactId: string;
2575
+ kind: RetainedOutputKind;
2576
+ contentType: string;
2577
+ originalBytes: number;
2578
+ sha256: string;
2579
+ retainedAt: string;
2580
+ retention: { policy: "workspace_file"; expiresAt: null };
2581
+ retrieval: {
2582
+ method: "GET";
2583
+ path: string;
2584
+ acceptRanges: "bytes";
2585
+ maxRangeBytes: number;
2586
+ };
2587
+ };
2588
+
2589
+ export type RetainedArtifactUnavailable = {
2590
+ available: false;
2591
+ artifactId: string;
2592
+ reason: RetainedOutputUnavailableReason;
2593
+ };
2594
+
2595
+ export type RetainedArtifactMetadata = RetainedArtifactReference | RetainedArtifactUnavailable;
2596
+
2597
+ export type RetainedArtifactContentOptions = {
2598
+ /** One RFC-style bytes range, for example `bytes=1048576-2097151`. */
2599
+ range?: string | undefined;
2600
+ signal?: AbortSignal | undefined;
2601
+ };
2602
+
2603
+ export type RetainedArtifactContent = {
2604
+ bytes: Uint8Array;
2605
+ status: 200 | 206;
2606
+ contentType: string;
2607
+ contentLength: number;
2608
+ contentRange: string | null;
2609
+ acceptRanges: "bytes";
2610
+ };
2611
+
1979
2612
  export type CreateFileUploadRequest = {
1980
2613
  filename: string;
1981
2614
  contentType: string;
@@ -2390,6 +3023,7 @@ export type CapabilityKind = "pack" | "mcp" | "api" | "skill" | "plugin";
2390
3023
 
2391
3024
  export type CapabilitySource =
2392
3025
  | "built_in"
3026
+ | "library"
2393
3027
  | "configured"
2394
3028
  | "public_registry"
2395
3029
  | "registry"
@@ -2406,6 +3040,17 @@ export type CapabilityRuntime = {
2406
3040
  mcpServerId?: string | undefined;
2407
3041
  transport?: string | undefined;
2408
3042
  notes: string | null;
3043
+ /** Secret-safe server-derived registry exposure state. */
3044
+ catalogTrust?:
3045
+ | {
3046
+ state: "trusted" | "legacy_active" | "unverified";
3047
+ reason:
3048
+ | "trusted_source"
3049
+ | "verified_probe"
3050
+ | "active_installation_compatibility"
3051
+ | "missing_verification";
3052
+ }
3053
+ | undefined;
2409
3054
  };
2410
3055
 
2411
3056
  export type CapabilityCatalogItem = {
@@ -2439,7 +3084,11 @@ export type CapabilityCatalogItem = {
2439
3084
  enabled: boolean;
2440
3085
  enabledReason: string | null;
2441
3086
  /** The connection backing this enabled installation, or null when none is involved. */
2442
- connectionRef: { connectionId: string; providerDomain: string; kind: string } | null;
3087
+ connectionRef: {
3088
+ connectionId: string;
3089
+ providerDomain: string;
3090
+ kind: string;
3091
+ } | null;
2443
3092
  metadata: Record<string, unknown>;
2444
3093
  createdAt?: string | undefined;
2445
3094
  updatedAt?: string | undefined;
@@ -2519,13 +3168,29 @@ export type GitHubRepository = {
2519
3168
  accountType: string | null;
2520
3169
  };
2521
3170
 
3171
+ export type GitHubRepositoryScope = "all" | "selected";
3172
+
3173
+ export type GitHubInstallationBinding = {
3174
+ installationId: number;
3175
+ accountLogin: string | null;
3176
+ accountType: string | null;
3177
+ repositoryScope: GitHubRepositoryScope;
3178
+ repositoryCount: number;
3179
+ createdAt: string;
3180
+ updatedAt: string;
3181
+ };
3182
+
2522
3183
  export type GitHubAppInfo = {
2523
3184
  configured: boolean;
2524
3185
  appId: string | null;
2525
3186
  clientId: string | null;
2526
3187
  appSlug: string | null;
2527
- /** Ready-to-open GitHub install URL (carries the signed state), if configured. */
3188
+ /** Reserved compatibility field; null while new installation binding is disabled. */
2528
3189
  installUrl: string | null;
3190
+ /** Reserved compatibility field; null while new installation binding is disabled. */
3191
+ linkUrl: string | null;
3192
+ /** Installation bindings owned independently by this workspace. */
3193
+ installations: GitHubInstallationBinding[];
2529
3194
  /** Setting names still missing when `configured` is false. */
2530
3195
  missing: string[];
2531
3196
  };
@@ -2635,6 +3300,7 @@ export type UserMessageEventInput = {
2635
3300
  clientEventId?: string | undefined;
2636
3301
  payload: {
2637
3302
  text: string;
3303
+ turnInstructions?: string | undefined;
2638
3304
  resources?: ResourceRef[] | undefined;
2639
3305
  tools?: ToolRef[] | undefined;
2640
3306
  model?: string | undefined;
@@ -2653,8 +3319,20 @@ export type UserApprovalDecisionEventInput = {
2653
3319
  };
2654
3320
  };
2655
3321
 
3322
+ export type UserHumanInputResponseEventInput = {
3323
+ type: "user.humanInputResponse";
3324
+ clientEventId?: string | undefined;
3325
+ payload: {
3326
+ requestId: string;
3327
+ response: SubmitHumanInputResponseRequest;
3328
+ };
3329
+ };
3330
+
2656
3331
  /** Control/user events a client may POST to a session's event log. */
2657
- export type ClientSessionEventInput = UserMessageEventInput | UserApprovalDecisionEventInput;
3332
+ export type ClientSessionEventInput =
3333
+ | UserMessageEventInput
3334
+ | UserApprovalDecisionEventInput
3335
+ | UserHumanInputResponseEventInput;
2658
3336
 
2659
3337
  // ── Bring-your-own-compute: Machines dashboard + per-machine metrics (M10) ────
2660
3338
  // Hand-written mirrors of the `@opengeni/contracts` MetricSample / MachineView /