@opengeni/sdk 0.13.0 → 0.20.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
@@ -10,7 +12,6 @@ export type SessionStatus =
10
12
  | "requires_action"
11
13
  | "recovering"
12
14
  | "waiting_capacity"
13
- | "paused"
14
15
  | "failed"
15
16
  | "cancelled";
16
17
 
@@ -149,7 +150,11 @@ export type StreamUrlRotatedPayload = {
149
150
  transport: "vnc-ws";
150
151
  viewerId: string | null;
151
152
  };
152
- export type StreamOpenedPayload = { viewerId: string; shared: boolean; viewerCount: number };
153
+ export type StreamOpenedPayload = {
154
+ viewerId: string;
155
+ shared: boolean;
156
+ viewerCount: number;
157
+ };
153
158
  export type StreamClosedPayload = {
154
159
  viewerId: string;
155
160
  reason: "client-disconnect" | "reaped" | "revoked" | "box-rollover";
@@ -165,7 +170,10 @@ export type StreamRevokedPayload = {
165
170
  // `desktop:true` opts into the un-redacted pixel plane (the consent-gated noVNC
166
171
  // stream); a terminal/files-only warm attach omits it (defaults false) so it
167
172
  // warms the box + mints the pty-ws terminal cell WITHOUT tripping the consent 409.
168
- export type AttachViewerRequest = { viewerId?: string | undefined; desktop?: boolean | undefined };
173
+ export type AttachViewerRequest = {
174
+ viewerId?: string | undefined;
175
+ desktop?: boolean | undefined;
176
+ };
169
177
 
170
178
  // Mirror of `@opengeni/contracts` ViewerHolder + the P4.2 desktop-stream fields
171
179
  // the POST /viewers handler folds in when the pixel plane is minted in-process.
@@ -203,7 +211,10 @@ export type AcknowledgeStreamRequest = {
203
211
  acknowledgeUnredacted?: boolean | undefined;
204
212
  acknowledgeShared?: boolean | undefined;
205
213
  };
206
- export type AcknowledgeStreamResponse = { acknowledged: boolean; acknowledgedShared: boolean };
214
+ export type AcknowledgeStreamResponse = {
215
+ acknowledged: boolean;
216
+ acknowledgedShared: boolean;
217
+ };
207
218
 
208
219
  // Mirror of `@opengeni/contracts` ViewerHeartbeatRequest/Response — the
209
220
  // Channel-A viewer-liveness ping, epoch-fenced (a stale-epoch beat → alive:false
@@ -213,14 +224,24 @@ export type ViewerHeartbeatResponse = { alive: boolean };
213
224
 
214
225
  export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
215
226
  export type GitCredentialProvider = "github" | "gitlab" | "azure_devops";
227
+ export type GitCredentialBindingId = string;
228
+ export type GitRepositoryAccess = "read" | "write";
216
229
 
217
230
  export type RepositoryResourceRef = {
218
231
  kind: "repository";
219
232
  uri: string;
220
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
+ */
221
240
  mountPath?: string | undefined;
222
241
  subpath?: string | undefined;
223
242
  provider?: GitCredentialProvider | undefined;
243
+ credentialBindingId?: GitCredentialBindingId | undefined;
244
+ access?: GitRepositoryAccess | undefined;
224
245
  repositoryId?: number | string | undefined;
225
246
  installationId?: number | string | undefined;
226
247
  projectId?: number | string | undefined;
@@ -232,6 +253,7 @@ export type RepositoryResourceRef = {
232
253
  export type FileResourceRef = {
233
254
  kind: "file";
234
255
  fileId: string;
256
+ /** Optional workspace-relative override; defaults to `files/<file-id>`. */
235
257
  mountPath?: string | undefined;
236
258
  };
237
259
 
@@ -255,7 +277,10 @@ export type SessionMcpServerInput = {
255
277
  allowedTools?: string[] | undefined;
256
278
  timeoutMs?: number | undefined;
257
279
  cacheToolsList?: boolean | undefined;
280
+ /** Require human approval for every tool, or only the listed unprefixed tool names. */
281
+ requireApproval?: boolean | string[] | undefined;
258
282
  headers?: Record<string, string> | undefined;
283
+ connectionRef?: McpServerConnectionRef | undefined;
259
284
  };
260
285
 
261
286
  export type SessionMcpCredentialUpdateInput = {
@@ -269,6 +294,7 @@ export type SessionMcpServerMetadata = {
269
294
  url: string;
270
295
  headerNames: string[];
271
296
  credentialVersion: number;
297
+ connectionRef: McpServerConnectionRef | null;
272
298
  };
273
299
 
274
300
  export type ConnectionKind = "oauth2" | "api_key" | "app_install" | "delegated";
@@ -276,10 +302,17 @@ export type ConnectionStatus = "active" | "needs_reauth" | "revoked" | "error";
276
302
 
277
303
  export type McpServerConnectionRef = {
278
304
  connectionId?: string | undefined;
305
+ provider?: string | undefined;
279
306
  providerDomain: string;
280
307
  kind?: ConnectionKind | undefined;
281
308
  scopes?: string[] | undefined;
282
309
  resource?: string | undefined;
310
+ selectedResources?:
311
+ | Array<{
312
+ id: string;
313
+ kind: "repository";
314
+ }>
315
+ | undefined;
283
316
  subjectScope?: "workspace" | "subject" | undefined;
284
317
  };
285
318
 
@@ -355,6 +388,20 @@ export type OAuthStartResponse = {
355
388
  expiresAt: string;
356
389
  };
357
390
 
391
+ /** The immutable principal whose authority accepted a session or turn. */
392
+ export type TurnInitiator = {
393
+ kind: "subject" | "service";
394
+ subjectId: string;
395
+ /** Display-only snapshot; never an authorization input. */
396
+ label?: string | undefined;
397
+ };
398
+
399
+ /** A trusted embedding host's causal machine/service principal. */
400
+ export type ServiceTurnInitiator = TurnInitiator & { kind: "service" };
401
+
402
+ /** Bounded host provenance; OpenGeni-owned lineage keys are reserved. */
403
+ export type ServiceTurnInitiatorContext = Record<string, unknown>;
404
+
358
405
  export type IntegrationClientMetadata = {
359
406
  client_id: string;
360
407
  client_name: "OpenGeni";
@@ -378,6 +425,9 @@ export type Session = {
378
425
  resources: ResourceRef[];
379
426
  tools: ToolRef[];
380
427
  metadata: Record<string, unknown>;
428
+ /** Frozen creator fact; later turns carry their own independent initiator. */
429
+ createdBy: TurnInitiator;
430
+ createdByContext: Record<string, unknown>;
381
431
  model: string;
382
432
  sandboxBackend: SandboxBackend;
383
433
  sandboxOs: SandboxOs;
@@ -400,12 +450,7 @@ export type Session = {
400
450
  queueVersion: number;
401
451
  queueHeadPosition: number;
402
452
  queueTailPosition: number;
403
- controlState: "active" | "paused";
404
- controlGeneration: number;
405
- controlReason: string | null;
406
- controlChangedBy: string | null;
407
- controlChangedAt: string | null;
408
- workspaceRunExceptionGeneration: number | null;
453
+ effectiveControl: EffectiveSessionControl;
409
454
  lastSequence: number;
410
455
  /** Multi-account Codex (P1): the account this session is pinned to (null ⇒ follow workspace active). */
411
456
  codexPinnedCredentialId?: string | null;
@@ -427,17 +472,26 @@ export type Session = {
427
472
  attentionDescendants: number;
428
473
  pausedDescendants: number;
429
474
  failedDescendants: number;
475
+ /** Counts are lower bounds rather than exact totals when true. */
476
+ truncated: boolean;
430
477
  }
431
478
  | undefined;
432
479
  createdAt: string;
433
480
  updatedAt: string;
434
481
  };
435
482
 
483
+ /** Additive receipt returned by POST /sessions. */
484
+ export type CreateSessionResponse = Session & {
485
+ initialTurnId: string | null;
486
+ };
487
+
436
488
  export type SessionSummary = Session;
437
489
 
438
490
  /** Canonical session-list page; pinned rows are excluded from ordinary pages. */
439
491
  export type SessionListResponse = {
440
492
  pinned: Session[];
493
+ /** True when the server omitted older pins from its bounded pinned section. */
494
+ pinnedTruncated?: boolean;
441
495
  sessions: Session[];
442
496
  nextCursor: string | null;
443
497
  };
@@ -467,7 +521,8 @@ export type SessionTurnStatus =
467
521
  | "completed"
468
522
  | "failed"
469
523
  | "cancelled"
470
- | "superseded";
524
+ | "superseded"
525
+ | "withdrawn_for_edit";
471
526
 
472
527
  export type SessionTurnSource =
473
528
  | "user"
@@ -498,6 +553,8 @@ export type SessionTurn = {
498
553
  executionGeneration: number;
499
554
  activeAttemptId: string | null;
500
555
  lineage: Record<string, unknown>;
556
+ initiator: TurnInitiator;
557
+ initiatorContext: Record<string, unknown>;
501
558
  cancelledBy?: string | null;
502
559
  cancelReason?: string | null;
503
560
  startedAt: string | null;
@@ -506,10 +563,74 @@ export type SessionTurn = {
506
563
  updatedAt: string;
507
564
  };
508
565
 
566
+ export type HumanInputQuestionKind = "text" | "single_select" | "multi_select";
567
+
568
+ export type HumanInputOption = {
569
+ id: string;
570
+ label: string;
571
+ description?: string | null | undefined;
572
+ };
573
+
574
+ export type HumanInputQuestion = {
575
+ id: string;
576
+ kind: HumanInputQuestionKind;
577
+ prompt: string;
578
+ label?: string | null | undefined;
579
+ helpText?: string | null | undefined;
580
+ options: HumanInputOption[];
581
+ required: boolean;
582
+ allowOther: boolean;
583
+ validation?:
584
+ | {
585
+ minLength?: number | null | undefined;
586
+ maxLength?: number | null | undefined;
587
+ minSelections?: number | null | undefined;
588
+ maxSelections?: number | null | undefined;
589
+ }
590
+ | null
591
+ | undefined;
592
+ };
593
+
594
+ export type HumanInputAnswer = {
595
+ questionId: string;
596
+ values: string[];
597
+ other?: string | null | undefined;
598
+ };
599
+
600
+ export type HumanInputResponse =
601
+ | { outcome: "answered"; answers: HumanInputAnswer[] }
602
+ | { outcome: "skipped" | "expired" | "cancelled" };
603
+
604
+ export type SubmitHumanInputResponseRequest =
605
+ | { outcome: "answered"; answers: HumanInputAnswer[] }
606
+ | { outcome: "skipped" };
607
+
608
+ export type SessionHumanInputRequest = {
609
+ id: string;
610
+ workspaceId: string;
611
+ sessionId: string;
612
+ turnId: string;
613
+ turnGeneration: number;
614
+ creationAttemptId: string;
615
+ toolCallId: string;
616
+ status: "pending" | "answered" | "skipped" | "expired" | "cancelled";
617
+ questions: HumanInputQuestion[];
618
+ allowSkip: boolean;
619
+ response: HumanInputResponse | null;
620
+ respondedBy: string | null;
621
+ respondedAt: string | null;
622
+ expiresAt: string | null;
623
+ createdAt: string;
624
+ updatedAt: string;
625
+ };
626
+
509
627
  export const SESSION_EVENT_TYPES = [
510
628
  "session.created",
629
+ // Defensive bounded projection for malformed/legacy oversized envelopes.
630
+ "session.event.envelope_omitted",
511
631
  "session.status.changed",
512
632
  "session.requiresAction",
633
+ "session.humanInput.requested",
513
634
  "session.context.compaction.requested",
514
635
  "session.context.compacted",
515
636
  "session.context.compaction.skipped",
@@ -517,6 +638,7 @@ export const SESSION_EVENT_TYPES = [
517
638
  "user.message",
518
639
  "user.pause",
519
640
  "user.approvalDecision",
641
+ "user.humanInputResponse",
520
642
  "turn.queued",
521
643
  "turn.started",
522
644
  "turn.completed",
@@ -532,6 +654,7 @@ export const SESSION_EVENT_TYPES = [
532
654
  "agent.toolCall.output",
533
655
  "agent.model.usage",
534
656
  "tool.auth_needed",
657
+ "credential.auth_needed",
535
658
  "agent.updated",
536
659
  "rig.setup.started",
537
660
  "rig.setup.completed",
@@ -556,6 +679,7 @@ export const SESSION_EVENT_TYPES = [
556
679
  "session.control.steer_requested",
557
680
  "workspace.inference.paused",
558
681
  "workspace.inference.resumed",
682
+ "session.queue.changed",
559
683
  "session.queue.prompt.cancelled",
560
684
  "session.queue.history",
561
685
  "turn.event.rejected_late",
@@ -581,9 +705,9 @@ export const SESSION_EVENT_TYPES = [
581
705
  "session.title_set",
582
706
  // Multi-account Codex (P1): the session's inference account changed.
583
707
  "codex.account.switched",
584
- // OPE-21 metadata-only per-turn credential selection audit.
708
+ // credential allocator metadata-only per-turn credential selection audit.
585
709
  "codex.credential.selected",
586
- // OPE-21 durable zero-capacity wait lifecycle. These are system/runtime
710
+ // credential allocator durable zero-capacity wait lifecycle. These are system/runtime
587
711
  // events, never synthetic user messages.
588
712
  "codex.capacity.waiting",
589
713
  "codex.capacity.resumed",
@@ -639,14 +763,78 @@ export type SessionEvent = {
639
763
  duplicateReason?: string | null | undefined;
640
764
  };
641
765
 
766
+ export type SessionEventSemanticClass =
767
+ | "control"
768
+ | "terminal"
769
+ | "failure"
770
+ | "checkpoint"
771
+ | "tool_receipt"
772
+ | "provider_account";
773
+ export type SessionEventPayloadMode = "none" | "summary" | "full";
774
+ export type SessionEventReadMode = "monitoring" | "forensic";
775
+ export type SessionEventReadDirection = "after" | "before";
776
+
777
+ type SessionEventListCommonOptions = {
778
+ after?: number;
779
+ before?: number;
780
+ limit?: number;
781
+ compact?: boolean;
782
+ mode?: SessionEventReadMode;
783
+ direction?: SessionEventReadDirection;
784
+ payloadMode?: SessionEventPayloadMode;
785
+ };
786
+
787
+ export type SessionEventListOptions = SessionEventListCommonOptions &
788
+ (
789
+ | {
790
+ latest?: never;
791
+ includeTypes?: SessionEventType[];
792
+ excludeTypes?: SessionEventType[];
793
+ includeClasses?: SessionEventSemanticClass[];
794
+ excludeClasses?: SessionEventSemanticClass[];
795
+ }
796
+ | {
797
+ /** Exclusive lookup for the newest event in exactly this semantic class. */
798
+ latest: SessionEventSemanticClass;
799
+ includeTypes?: never;
800
+ excludeTypes?: never;
801
+ includeClasses?: never;
802
+ excludeClasses?: never;
803
+ }
804
+ );
805
+
806
+ export type SessionEventPage = {
807
+ events: SessionEvent[];
808
+ mode: SessionEventReadMode;
809
+ payloadMode: SessionEventPayloadMode;
810
+ direction: SessionEventReadDirection;
811
+ bytes: number;
812
+ maxBytes: number;
813
+ truncated: boolean;
814
+ hasMore: boolean;
815
+ truncatedBy: "count" | "bytes" | "http_bytes" | null;
816
+ coveredSequence: { first: number; last: number } | null;
817
+ nextAfter: number | null;
818
+ nextBefore: number | null;
819
+ forensicExact: boolean;
820
+ };
821
+
642
822
  export type ToolAuthNeededPayload = {
643
823
  serverId: string;
644
824
  toolName?: string | null | undefined;
645
825
  providerDomain: string;
826
+ provider?: string | undefined;
646
827
  connectionId?: string | null | undefined;
647
- reason: "missing_connection" | "expired" | "insufficient_scope" | "refresh_failed";
828
+ reason:
829
+ | "missing_connection"
830
+ | "expired"
831
+ | "insufficient_scope"
832
+ | "refresh_failed"
833
+ | "unsupported_auth"
834
+ | "resource_scope_unavailable";
648
835
  scopes?: string[] | undefined;
649
836
  resource?: string | undefined;
837
+ selectedResources?: Array<{ id: string; kind: "repository" }> | undefined;
650
838
  authorizationUrl?: string | undefined;
651
839
  subjectId?: string | null | undefined;
652
840
  };
@@ -775,8 +963,16 @@ export type FsListRequest = {
775
963
  maxEntries?: number;
776
964
  includeHidden?: boolean;
777
965
  };
778
- export type FsListResponse = { root: FsTreeNode; revision: number; truncated: boolean };
779
- export type FsReadRequest = { path: string; encoding?: FsEncoding; maxBytes?: number };
966
+ export type FsListResponse = {
967
+ root: FsTreeNode;
968
+ revision: number;
969
+ truncated: boolean;
970
+ };
971
+ export type FsReadRequest = {
972
+ path: string;
973
+ encoding?: FsEncoding;
974
+ maxBytes?: number;
975
+ };
780
976
  export type FsReadResponse = {
781
977
  path: string;
782
978
  encoding: FsEncoding;
@@ -793,7 +989,11 @@ export type FsWriteRequest = {
793
989
  overwrite?: boolean;
794
990
  createParents?: boolean;
795
991
  };
796
- export type FsWriteResponse = { path: string; sizeBytes: number; revision: number };
992
+ export type FsWriteResponse = {
993
+ path: string;
994
+ sizeBytes: number;
995
+ revision: number;
996
+ };
797
997
  export type FsDeleteRequest = { path: string; recursive?: boolean };
798
998
  export type FsDeleteResponse = { revision: number };
799
999
  export type FsMoveRequest = {
@@ -802,7 +1002,11 @@ export type FsMoveRequest = {
802
1002
  overwrite?: boolean;
803
1003
  createParents?: boolean;
804
1004
  };
805
- export type FsMoveResponse = { path: string; newPath: string; revision: number };
1005
+ export type FsMoveResponse = {
1006
+ path: string;
1007
+ newPath: string;
1008
+ revision: number;
1009
+ };
806
1010
  export type FsMkdirRequest = { path: string; recursive?: boolean };
807
1011
  export type FsMkdirResponse = { path: string; revision: number };
808
1012
 
@@ -864,6 +1068,7 @@ export type GitFileDiff = {
864
1068
  export type GitDiffRequest = {
865
1069
  path?: string;
866
1070
  staged?: boolean;
1071
+ includeUntracked?: boolean;
867
1072
  fromRef?: string;
868
1073
  toRef?: string;
869
1074
  pathspec?: string[];
@@ -899,12 +1104,17 @@ export type GitShowRequest = {
899
1104
  export type GitShowResponse = {
900
1105
  commit: GitCommit | null;
901
1106
  files: GitFileDiff[];
902
- blob: { content: string; encoding: FsEncoding; sizeBytes: number; truncated: boolean } | null;
1107
+ blob: {
1108
+ content: string;
1109
+ encoding: FsEncoding;
1110
+ sizeBytes: number;
1111
+ truncated: boolean;
1112
+ } | null;
903
1113
  revision: number;
904
1114
  };
905
1115
 
906
1116
  // Workbench v2 turn-end capture (mirror of `@opengeni/contracts` WorkspaceCapture*
907
- // + the M2 read-API response shapes, dossier §10.3). Reuses FsTreeNode /
1117
+ // + the M2 read-API response shapes). Reuses FsTreeNode /
908
1118
  // GitFileStatus / GitFileDiff / GitFileStatusCode / FsEncoding above.
909
1119
  export type WorkspaceCaptureFile = {
910
1120
  path: string;
@@ -1022,8 +1232,17 @@ export type TerminalExecResponse = {
1022
1232
  running: boolean;
1023
1233
  wallTimeSeconds: number;
1024
1234
  };
1025
- export type PtyOpenRequest = { cols?: number; rows?: number; cwd?: string; shell?: string };
1026
- export type PtyOpenResponse = { ptyId: string; streamVia: "sse-events"; supportsInput: boolean };
1235
+ export type PtyOpenRequest = {
1236
+ cols?: number;
1237
+ rows?: number;
1238
+ cwd?: string;
1239
+ shell?: string;
1240
+ };
1241
+ export type PtyOpenResponse = {
1242
+ ptyId: string;
1243
+ streamVia: "sse-events";
1244
+ supportsInput: boolean;
1245
+ };
1027
1246
  export type PtyWriteRequest = { ptyId: string; data: string };
1028
1247
  export type PtyResizeRequest = { ptyId: string; cols: number; rows: number };
1029
1248
  export type PtyCloseRequest = { ptyId: string };
@@ -1099,7 +1318,13 @@ export type ScheduledTask = {
1099
1318
  };
1100
1319
 
1101
1320
  export type CreateSessionRequest = {
1321
+ // Optional UUID preallocated by an embedding host so it can durably link its
1322
+ // projection before OpenGeni admits the initial turn. Replays must retain the
1323
+ // same UUID and idempotency key.
1324
+ requestedSessionId?: string | undefined;
1102
1325
  initialMessage: string;
1326
+ /** System instructions scoped to the initial turn; never visible timeline text. */
1327
+ turnInstructions?: string | undefined;
1103
1328
  // Per-session agent persona/system instructions (org-visible metadata, not a
1104
1329
  // secret). Delivered system-level, composed AFTER the per-workspace persona —
1105
1330
  // how a host supplies per-agent-type prompts without leaking them into the
@@ -1154,7 +1379,7 @@ export const KNOWN_PERMISSIONS = [
1154
1379
  "sessions:create",
1155
1380
  "sessions:read",
1156
1381
  "sessions:control",
1157
- // Sandbox-surfacing (mirror of @opengeni/contracts Permission). stream:view is
1382
+ // sandbox workspace (mirror of @opengeni/contracts Permission). stream:view is
1158
1383
  // strictly broader than sessions:read (un-redacted pixels); stream:control is
1159
1384
  // the never-granted-v1 raw-input plane; stream:acknowledge is the secret-leak
1160
1385
  // consent gate.
@@ -1227,7 +1452,11 @@ export type CodexConnectionStatus = {
1227
1452
  lastError?: string | null;
1228
1453
  models?: ClientModel[];
1229
1454
  /** The account a session runs on when unpinned (label for the in-session indicator). */
1230
- activeAccount?: { id: string; label?: string | null; chatgptAccountId?: string | null } | null;
1455
+ activeAccount?: {
1456
+ id: string;
1457
+ label?: string | null;
1458
+ chatgptAccountId?: string | null;
1459
+ } | null;
1231
1460
  /** How many Codex accounts the workspace has connected. */
1232
1461
  accountCount?: number;
1233
1462
  };
@@ -1333,7 +1562,12 @@ export type CodexConnectStart = {
1333
1562
  export type CodexConnectPoll =
1334
1563
  | { status: "pending" }
1335
1564
  | { status: "expired" }
1336
- | { status: "connected"; plan?: string | null; accountId?: string; isActive?: boolean };
1565
+ | {
1566
+ status: "connected";
1567
+ plan?: string | null;
1568
+ accountId?: string;
1569
+ isActive?: boolean;
1570
+ };
1337
1571
 
1338
1572
  /** Remaining usage/limits for one account. `usage` is the normalized P2 payload. */
1339
1573
  export type CodexUsage = {
@@ -1355,6 +1589,11 @@ export type ClientAuthConfig =
1355
1589
  | { mode: "configuredToken"; headerName: "authorization"; scheme: "bearer" }
1356
1590
  | { mode: "managedSession"; session: "cookie" };
1357
1591
 
1592
+ // Kept value-identical to @opengeni/contracts and pinned by the SDK contract
1593
+ // parity suite. The SDK has no runtime dependency on the Zod contracts package.
1594
+ export const OPENGENI_API_CONTRACT_REVISION = "2026-07-turn-instructions-v1" as const;
1595
+ export const OPENGENI_API_CONTRACT_HEADER = "x-opengeni-api-contract" as const;
1596
+
1358
1597
  /**
1359
1598
  * Public, unauthenticated-by-default client bootstrap config returned by
1360
1599
  * `GET /v1/config/client`: which models + reasoning efforts are exposed, the
@@ -1364,6 +1603,8 @@ export type ClientAuthConfig =
1364
1603
  */
1365
1604
  export type ClientConfig = {
1366
1605
  deploymentRevision: string;
1606
+ apiContractRevision: typeof OPENGENI_API_CONTRACT_REVISION;
1607
+ serverVersion?: string | undefined;
1367
1608
  defaultModel: string;
1368
1609
  allowedModels: string[];
1369
1610
  models: ClientModel[];
@@ -1377,7 +1618,11 @@ export type ClientConfig = {
1377
1618
  // at all (P4.4). Per-session availability is negotiated on /stream-capabilities;
1378
1619
  // this is the coarse on/off the client uses to decide whether to even attempt
1379
1620
  // the fs/git/terminal panels.
1380
- structuredServices: { fileSystem: boolean; git: boolean; terminalEvents: boolean };
1621
+ structuredServices: {
1622
+ fileSystem: boolean;
1623
+ git: boolean;
1624
+ terminalEvents: boolean;
1625
+ };
1381
1626
  };
1382
1627
 
1383
1628
  export type AccountRole = "owner" | "admin" | "member";
@@ -1398,6 +1643,8 @@ export type AccessGrant = {
1398
1643
  subjectLabel?: string | undefined;
1399
1644
  permissions: Permission[];
1400
1645
  metadata?: Record<string, unknown> | undefined;
1646
+ serviceInitiator?: ServiceTurnInitiator | undefined;
1647
+ serviceInitiatorContext?: ServiceTurnInitiatorContext | undefined;
1401
1648
  };
1402
1649
 
1403
1650
  export type AccessContext = {
@@ -1419,11 +1666,13 @@ export type Workspace = {
1419
1666
  externalId: string | null;
1420
1667
  agentInstructions: string | null;
1421
1668
  settings: Record<string, unknown>;
1422
- inferenceState?: "active" | "paused";
1423
- inferenceGeneration?: number;
1424
- inferenceReason?: string | null;
1425
- inferenceChangedBy?: string | null;
1426
- inferenceChangedAt?: string | null;
1669
+ inferenceControl: {
1670
+ state: "active" | "paused";
1671
+ revision: number;
1672
+ reason: string | null;
1673
+ changedBy: string | null;
1674
+ changedAt: string | null;
1675
+ };
1427
1676
  defaultRigId?: string | null;
1428
1677
  createdAt: string;
1429
1678
  updatedAt: string;
@@ -1431,11 +1680,13 @@ export type Workspace = {
1431
1680
 
1432
1681
  export type WorkspaceSettings = {
1433
1682
  memoryEnabled?: boolean | undefined;
1683
+ transcription?: WorkspaceTranscriptionPolicy | undefined;
1434
1684
  [key: string]: unknown;
1435
1685
  };
1436
1686
 
1437
1687
  export type UpdateWorkspaceSettingsRequest = {
1438
1688
  memoryEnabled?: boolean | undefined;
1689
+ transcription?: WorkspaceTranscriptionPolicy | undefined;
1439
1690
  [key: string]: unknown;
1440
1691
  };
1441
1692
 
@@ -1561,29 +1812,90 @@ export type CompactSessionContextResult = {
1561
1812
 
1562
1813
  // --- Turn queue --------------------------------------------------------------
1563
1814
 
1815
+ export type EffectiveControlBlocker = {
1816
+ kind: "session" | "workspace";
1817
+ sessionId?: string | undefined;
1818
+ displayName: string;
1819
+ actor: string | null;
1820
+ reason: string | null;
1821
+ changedAt: string | null;
1822
+ revision: number;
1823
+ };
1824
+
1825
+ export type EffectiveControlResumeOption = {
1826
+ scope: "selected" | "session" | "workspace";
1827
+ targetId?: string | undefined;
1828
+ selectedStateAfter: "active" | "paused";
1829
+ remainingPrimaryBlocker?: EffectiveControlBlocker | undefined;
1830
+ impactCopy: string;
1831
+ };
1832
+
1833
+ export type EffectiveSessionControl = {
1834
+ state: "active" | "paused";
1835
+ controlVersion: number;
1836
+ controlEtag: string;
1837
+ directState: "active" | "paused";
1838
+ primaryBlocker: EffectiveControlBlocker | null;
1839
+ additionalBlockerCount: number;
1840
+ blockers: EffectiveControlBlocker[];
1841
+ resumeOptions: EffectiveControlResumeOption[];
1842
+ override: { rootSessionId: string; revision: number } | null;
1843
+ settlement: {
1844
+ state: "stopping";
1845
+ attemptCount: number;
1846
+ interruptionPendingCount: number;
1847
+ quiescencePendingCount: number;
1848
+ } | null;
1849
+ };
1850
+
1851
+ export type SessionCommandReceipt = {
1852
+ id: string;
1853
+ action: string;
1854
+ operationKey: string;
1855
+ targetSessionId: string | null;
1856
+ targetTurnId: string | null;
1857
+ appliedControlRevision: number | null;
1858
+ appliedQueueVersion: number | null;
1859
+ appliedTurnVersion: number | null;
1860
+ appliedDraftRevision: number | null;
1861
+ createdAt: string;
1862
+ };
1863
+
1864
+ export type ComposerDraft = {
1865
+ revision: number;
1866
+ text: string;
1867
+ resources: ResourceRef[];
1868
+ tools: ToolRef[];
1869
+ model: string;
1870
+ reasoningEffort: ReasoningEffort;
1871
+ sourceTurnId: string | null;
1872
+ sourceTurnVersion: number | null;
1873
+ updatedAt: string | null;
1874
+ };
1875
+
1564
1876
  export type SessionQueueSnapshot = {
1565
1877
  version: number;
1566
- controlState: "active" | "paused";
1567
- controlGeneration: number;
1568
- workspaceInferenceState: "active" | "paused";
1569
- workspaceInferenceGeneration: number;
1570
- workspaceRunExceptionGeneration: number | null;
1878
+ effectiveControl: EffectiveSessionControl;
1879
+ /** The latest interrupted attempt has not yet durably proved physical quiescence. */
1880
+ stoppingPreviousAttempt: boolean;
1571
1881
  items: SessionTurn[];
1572
1882
  };
1573
1883
 
1574
1884
  export type SystemUpdateClassification = "success" | "failure" | "action_required" | "info";
1575
1885
 
1576
1886
  export type SessionSystemUpdateKind =
1577
- | "child_session_update"
1578
- | "scheduled_wake"
1579
- | "lifecycle_event"
1580
- | "runtime_notice";
1887
+ | "scheduled_occurrence"
1888
+ | "goal_continuation"
1889
+ | "agent_message"
1890
+ | "agent_steer_instruction"
1891
+ | "child_terminal_result";
1581
1892
 
1582
1893
  export type SessionSystemUpdateState =
1583
1894
  | "pending"
1584
1895
  | "deferred"
1585
1896
  | "delivered"
1586
1897
  | "cancelled"
1898
+ | "superseded"
1587
1899
  | "failed";
1588
1900
 
1589
1901
  export type SessionSystemUpdate = {
@@ -1603,33 +1915,92 @@ export type SessionSystemUpdate = {
1603
1915
  };
1604
1916
 
1605
1917
  export type SessionControlResponse = {
1606
- operationId: string;
1607
- event: SessionEvent;
1608
- controlState: "active" | "paused";
1609
- controlGeneration: number;
1610
- expectedActiveTurnId: string | null;
1611
- expectedExecutionGeneration: number | null;
1612
- expectedAttemptId: string | null;
1613
- deliveryEventId: string | null;
1614
- shouldSignalControl: boolean;
1615
- shouldWake: boolean;
1918
+ receipt: SessionCommandReceipt;
1919
+ effectiveControl: EffectiveSessionControl;
1920
+ interruptionCount: number;
1921
+ wakeCount: number;
1616
1922
  };
1617
1923
 
1618
1924
  export type WorkspaceInferenceControlResponse = {
1619
- operationId: string;
1925
+ receipt: SessionCommandReceipt;
1620
1926
  state: "active" | "paused";
1621
- generation: number;
1622
- affectedSessionIds: string[];
1623
- controlSessionIds: string[];
1624
- exceptionSessionIds: string[];
1927
+ revision: number;
1928
+ interruptionCount: number;
1929
+ wakeCount: number;
1930
+ };
1931
+
1932
+ export type WorkspaceControlEvent = {
1933
+ id: string;
1934
+ workspaceId: string;
1935
+ /** Same monotonic value as revision; named sequence for SSE resume cursors. */
1936
+ sequence: number;
1937
+ revision: number;
1938
+ type: "workspace.control.changed";
1939
+ scope: "workspace" | "session";
1940
+ rootSessionId: string | null;
1941
+ action: "pause" | "resume";
1942
+ automatic: boolean;
1943
+ reason: string | null;
1944
+ actor: string;
1945
+ occurredAt: string;
1946
+ truncation?: {
1947
+ truncated: true;
1948
+ surface:
1949
+ | "durable_control"
1950
+ | "database_guard"
1951
+ | "http_projection"
1952
+ | "nats_legacy_guard"
1953
+ | "sse_legacy_guard";
1954
+ deliveredBytes: number;
1955
+ fields: Array<{
1956
+ field: "reason" | "actor";
1957
+ originalBytes: number;
1958
+ deliveredBytes: number;
1959
+ omittedBytes: number;
1960
+ }>;
1961
+ fullEvidence: {
1962
+ available: false;
1963
+ reason: "not_retained";
1964
+ };
1965
+ } | null;
1625
1966
  };
1626
1967
 
1627
1968
  export type SessionQueueMutationResponse = {
1969
+ receipt: SessionCommandReceipt;
1628
1970
  snapshot: SessionQueueSnapshot;
1629
- events: SessionEvent[];
1630
- shouldWake: boolean;
1971
+ draft?: ComposerDraft;
1972
+ };
1973
+
1974
+ export type MoveSessionQueueItemRequest = {
1975
+ clientEventId: string;
1976
+ expectedQueueVersion: number;
1977
+ beforeTurnId: string | null;
1978
+ };
1979
+
1980
+ export type EditSessionQueueItemRequest = {
1981
+ clientEventId: string;
1982
+ expectedTurnVersion: number;
1983
+ expectedDraftRevision: number;
1984
+ replaceDraft: boolean;
1985
+ };
1986
+
1987
+ export type SteerSessionQueueItemRequest = {
1988
+ clientEventId: string;
1989
+ expectedTurnVersion: number;
1990
+ controlEtag?: string;
1631
1991
  };
1632
1992
 
1993
+ export type DeleteSessionQueueItemRequest = {
1994
+ clientEventId: string;
1995
+ expectedTurnVersion: number;
1996
+ reason?: string;
1997
+ };
1998
+
1999
+ export type SaveComposerDraftRequest = Omit<
2000
+ ComposerDraft,
2001
+ "revision" | "sourceTurnId" | "sourceTurnVersion" | "updatedAt"
2002
+ > & { expectedRevision: number };
2003
+
1633
2004
  // --- Scheduled tasks: requests + runs ----------------------------------------
1634
2005
 
1635
2006
  /** Input shape for agent config on create/update (server applies defaults). */
@@ -2292,6 +2663,7 @@ export type CapabilityKind = "pack" | "mcp" | "api" | "skill" | "plugin";
2292
2663
 
2293
2664
  export type CapabilitySource =
2294
2665
  | "built_in"
2666
+ | "library"
2295
2667
  | "configured"
2296
2668
  | "public_registry"
2297
2669
  | "registry"
@@ -2341,7 +2713,11 @@ export type CapabilityCatalogItem = {
2341
2713
  enabled: boolean;
2342
2714
  enabledReason: string | null;
2343
2715
  /** The connection backing this enabled installation, or null when none is involved. */
2344
- connectionRef: { connectionId: string; providerDomain: string; kind: string } | null;
2716
+ connectionRef: {
2717
+ connectionId: string;
2718
+ providerDomain: string;
2719
+ kind: string;
2720
+ } | null;
2345
2721
  metadata: Record<string, unknown>;
2346
2722
  createdAt?: string | undefined;
2347
2723
  updatedAt?: string | undefined;
@@ -2421,13 +2797,29 @@ export type GitHubRepository = {
2421
2797
  accountType: string | null;
2422
2798
  };
2423
2799
 
2800
+ export type GitHubRepositoryScope = "all" | "selected";
2801
+
2802
+ export type GitHubInstallationBinding = {
2803
+ installationId: number;
2804
+ accountLogin: string | null;
2805
+ accountType: string | null;
2806
+ repositoryScope: GitHubRepositoryScope;
2807
+ repositoryCount: number;
2808
+ createdAt: string;
2809
+ updatedAt: string;
2810
+ };
2811
+
2424
2812
  export type GitHubAppInfo = {
2425
2813
  configured: boolean;
2426
2814
  appId: string | null;
2427
2815
  clientId: string | null;
2428
2816
  appSlug: string | null;
2429
- /** Ready-to-open GitHub install URL (carries the signed state), if configured. */
2817
+ /** Reserved compatibility field; null while new installation binding is disabled. */
2430
2818
  installUrl: string | null;
2819
+ /** Reserved compatibility field; null while new installation binding is disabled. */
2820
+ linkUrl: string | null;
2821
+ /** Installation bindings owned independently by this workspace. */
2822
+ installations: GitHubInstallationBinding[];
2431
2823
  /** Setting names still missing when `configured` is false. */
2432
2824
  missing: string[];
2433
2825
  };
@@ -2537,6 +2929,7 @@ export type UserMessageEventInput = {
2537
2929
  clientEventId?: string | undefined;
2538
2930
  payload: {
2539
2931
  text: string;
2932
+ turnInstructions?: string | undefined;
2540
2933
  resources?: ResourceRef[] | undefined;
2541
2934
  tools?: ToolRef[] | undefined;
2542
2935
  model?: string | undefined;
@@ -2555,8 +2948,20 @@ export type UserApprovalDecisionEventInput = {
2555
2948
  };
2556
2949
  };
2557
2950
 
2951
+ export type UserHumanInputResponseEventInput = {
2952
+ type: "user.humanInputResponse";
2953
+ clientEventId?: string | undefined;
2954
+ payload: {
2955
+ requestId: string;
2956
+ response: SubmitHumanInputResponseRequest;
2957
+ };
2958
+ };
2959
+
2558
2960
  /** Control/user events a client may POST to a session's event log. */
2559
- export type ClientSessionEventInput = UserMessageEventInput | UserApprovalDecisionEventInput;
2961
+ export type ClientSessionEventInput =
2962
+ | UserMessageEventInput
2963
+ | UserApprovalDecisionEventInput
2964
+ | UserHumanInputResponseEventInput;
2560
2965
 
2561
2966
  // ── Bring-your-own-compute: Machines dashboard + per-machine metrics (M10) ────
2562
2967
  // Hand-written mirrors of the `@opengeni/contracts` MetricSample / MachineView /