@opengeni/contracts 0.31.1 → 0.32.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/index.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  sessionEventJsonBytes,
6
6
  type SessionEventBoundarySurface,
7
7
  } from "./event-preview";
8
+ import { WorkspaceInstructionPolicyRoleKeyInput } from "./workspace-instruction-policies";
8
9
 
9
10
  export * from "./slack-bot-scopes";
10
11
 
@@ -503,7 +504,7 @@ export const CAPABILITY_DESCRIPTORS: Record<SandboxBackend, CapabilityDescriptor
503
504
  },
504
505
  };
505
506
 
506
- export const ReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh"]);
507
+ export const ReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);
507
508
 
508
509
  /** Provider service-tier / latency mode selected for a turn or session default. */
509
510
  export const LatencyMode = z.enum(["standard", "priority", "fast"]);
@@ -1183,6 +1184,57 @@ export const VOICE_INPUT_ACCEPTED_MIME_TYPES = [
1183
1184
  export const CodexCompactionMode = z.enum(["remote_v2", "portable"]);
1184
1185
  export type CodexCompactionMode = z.infer<typeof CodexCompactionMode>;
1185
1186
 
1187
+ export const SlackReactionEmojiName = z
1188
+ .string()
1189
+ .trim()
1190
+ .min(1)
1191
+ .max(64)
1192
+ .regex(/^[a-z0-9_+-]+$/, "use the exact Slack emoji name without surrounding colons");
1193
+ export type SlackReactionEmojiName = z.infer<typeof SlackReactionEmojiName>;
1194
+
1195
+ export const WorkspaceSlackReactionChannelPolicy = z.discriminatedUnion("mode", [
1196
+ z.object({ mode: z.literal("bot_member") }).strict(),
1197
+ z
1198
+ .object({
1199
+ mode: z.literal("allowlist"),
1200
+ channelIds: z.array(z.string().trim().min(1).max(64)).max(100),
1201
+ })
1202
+ .strict(),
1203
+ ]);
1204
+ export type WorkspaceSlackReactionChannelPolicy = z.infer<
1205
+ typeof WorkspaceSlackReactionChannelPolicy
1206
+ >;
1207
+
1208
+ export const WorkspaceSlackReactionSummonSettings = z
1209
+ .object({
1210
+ enabled: z.boolean(),
1211
+ emoji: SlackReactionEmojiName,
1212
+ channelPolicy: WorkspaceSlackReactionChannelPolicy,
1213
+ })
1214
+ .strict();
1215
+ export type WorkspaceSlackReactionSummonSettings = z.infer<
1216
+ typeof WorkspaceSlackReactionSummonSettings
1217
+ >;
1218
+
1219
+ export const SlackReactionChannel = z.object({
1220
+ id: z.string().min(1).max(64),
1221
+ name: z.string().min(1).max(256).nullable(),
1222
+ isPrivate: z.boolean(),
1223
+ });
1224
+ export type SlackReactionChannel = z.infer<typeof SlackReactionChannel>;
1225
+
1226
+ export const SlackReactionChannelListResponse = z.object({
1227
+ channels: z.array(SlackReactionChannel).max(200),
1228
+ nextCursor: z.string().max(1_024).nullable(),
1229
+ });
1230
+ export type SlackReactionChannelListResponse = z.infer<typeof SlackReactionChannelListResponse>;
1231
+
1232
+ export const DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS = {
1233
+ enabled: false,
1234
+ emoji: "genie",
1235
+ channelPolicy: { mode: "bot_member" },
1236
+ } as const satisfies WorkspaceSlackReactionSummonSettings;
1237
+
1186
1238
  // Validates the KNOWN keys of workspaces.settings; passthrough keeps unknown
1187
1239
  // (future) keys rather than stripping them. memoryEnabled defaults off;
1188
1240
  // voiceInput defaults to enabled when the deployment has a provider.
@@ -1202,6 +1254,9 @@ export const WorkspaceSettingsSchema = z
1202
1254
  // Default compaction strategy for NEW Codex sessions created in this
1203
1255
  // workspace. Absent ⇒ remote_v2. Non-Codex sessions always freeze portable.
1204
1256
  codexCompactionDefault: CodexCompactionMode.optional(),
1257
+ // Optional Slack reaction invocation. Absent/invalid fails closed to the
1258
+ // disabled default via resolveWorkspaceSlackReactionSummonSettings.
1259
+ slackReactionSummon: WorkspaceSlackReactionSummonSettings.optional(),
1205
1260
  })
1206
1261
  .passthrough();
1207
1262
  export type WorkspaceSettings = z.infer<typeof WorkspaceSettingsSchema>;
@@ -1235,6 +1290,39 @@ export function resolveWorkspaceVoiceInputEnabled(settings: unknown): boolean |
1235
1290
  return null;
1236
1291
  }
1237
1292
 
1293
+ export function resolveWorkspaceSlackReactionSummonSettings(
1294
+ settings: unknown,
1295
+ ): WorkspaceSlackReactionSummonSettings {
1296
+ const parsed = WorkspaceSettingsSchema.safeParse(settings ?? {});
1297
+ const configured = parsed.success ? parsed.data.slackReactionSummon : undefined;
1298
+ if (!configured) {
1299
+ return {
1300
+ enabled: DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS.enabled,
1301
+ emoji: DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS.emoji,
1302
+ channelPolicy: { ...DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS.channelPolicy },
1303
+ };
1304
+ }
1305
+ return configured.channelPolicy.mode === "allowlist"
1306
+ ? {
1307
+ ...configured,
1308
+ channelPolicy: {
1309
+ mode: "allowlist",
1310
+ channelIds: [...new Set(configured.channelPolicy.channelIds)],
1311
+ },
1312
+ }
1313
+ : { ...configured, channelPolicy: { mode: "bot_member" } };
1314
+ }
1315
+
1316
+ export function workspaceSlackReactionChannelAllowed(
1317
+ settings: WorkspaceSlackReactionSummonSettings,
1318
+ channelId: string,
1319
+ ): boolean {
1320
+ return (
1321
+ settings.channelPolicy.mode === "bot_member" ||
1322
+ settings.channelPolicy.channelIds.includes(channelId)
1323
+ );
1324
+ }
1325
+
1238
1326
  // PATCH body for workspace settings: a partial top-level patch that merges into
1239
1327
  // the stored bag. Nested voiceInput/transcription updates are full replacements;
1240
1328
  // passthrough carries forward-compatible unknown keys.
@@ -1246,6 +1334,7 @@ export const UpdateWorkspaceSettingsRequest = z
1246
1334
  transcription: WorkspaceTranscriptionPolicy.optional(),
1247
1335
  maxNestedAgentDepth: NestedAgentDepthValue.nullable().optional(),
1248
1336
  codexCompactionDefault: CodexCompactionMode.optional(),
1337
+ slackReactionSummon: WorkspaceSlackReactionSummonSettings.optional(),
1249
1338
  })
1250
1339
  .passthrough();
1251
1340
  export type UpdateWorkspaceSettingsRequest = z.infer<typeof UpdateWorkspaceSettingsRequest>;
@@ -3604,7 +3693,8 @@ export function reasoningEffortForMetadata(
3604
3693
  value === "low" ||
3605
3694
  value === "medium" ||
3606
3695
  value === "high" ||
3607
- value === "xhigh"
3696
+ value === "xhigh" ||
3697
+ value === "max"
3608
3698
  ? value
3609
3699
  : fallback;
3610
3700
  }
@@ -3898,6 +3988,267 @@ export const SessionAuthorizationSurface = z.enum([
3898
3988
  ]);
3899
3989
  export type SessionAuthorizationSurface = z.infer<typeof SessionAuthorizationSurface>;
3900
3990
 
3991
+ // Native connected-Codex GPT-Live WebRTC negotiation. The browser sends its
3992
+ // SDP offer, non-provider session configuration, and proof of the exact active
3993
+ // ordinary-session realtime owner. The API consumes that proof before resolving
3994
+ // the subscription credential and returns only the provider's SDP answer.
3995
+ export const CodexRealtimeWebrtcVersion = z.literal("v3");
3996
+ export type CodexRealtimeWebrtcVersion = z.infer<typeof CodexRealtimeWebrtcVersion>;
3997
+
3998
+ export const CodexRealtimeVoice = z.enum([
3999
+ "juniper",
4000
+ "maple",
4001
+ "spruce",
4002
+ "ember",
4003
+ "vale",
4004
+ "breeze",
4005
+ "arbor",
4006
+ "sol",
4007
+ "cove",
4008
+ ]);
4009
+ export type CodexRealtimeVoice = z.infer<typeof CodexRealtimeVoice>;
4010
+
4011
+ const SessionRealtimeOwnerProof = z.object({
4012
+ browserInstanceId: z.string().min(1).max(256),
4013
+ ownerKey: z.string().min(32).max(1024),
4014
+ });
4015
+
4016
+ export const CodexRealtimeWebrtcRequest = SessionRealtimeOwnerProof.extend({
4017
+ realtimeId: z.string().uuid(),
4018
+ operationId: z.string().uuid(),
4019
+ expectedVersion: z.number().int().positive(),
4020
+ expectedConnectionEpoch: z.number().int().positive(),
4021
+ rotate: z.boolean(),
4022
+ browserActivation: z.literal("required").optional(),
4023
+ sdp: z
4024
+ .string()
4025
+ .min(1)
4026
+ .max(1024 * 1024),
4027
+ version: CodexRealtimeWebrtcVersion,
4028
+ instructions: z.string().max(32_768).optional(),
4029
+ voice: CodexRealtimeVoice.optional(),
4030
+ }).strict();
4031
+ export type CodexRealtimeWebrtcRequest = z.infer<typeof CodexRealtimeWebrtcRequest>;
4032
+
4033
+ export const CodexRealtimeWebrtcResponse = z
4034
+ .object({
4035
+ sdp: z
4036
+ .string()
4037
+ .min(1)
4038
+ .max(1024 * 1024),
4039
+ version: CodexRealtimeWebrtcVersion,
4040
+ model: z.literal("gpt-live-1-boulder-alpha"),
4041
+ connectionId: z.string().uuid(),
4042
+ connectionEpoch: z.number().int().positive(),
4043
+ startupFenceSequence: z.number().int().nonnegative(),
4044
+ modeVersion: z.number().int().positive(),
4045
+ replay: z.boolean(),
4046
+ })
4047
+ .strict();
4048
+ export type CodexRealtimeWebrtcResponse = z.infer<typeof CodexRealtimeWebrtcResponse>;
4049
+
4050
+ export const GatewayRealtimeConnectRequest = SessionRealtimeOwnerProof.extend({
4051
+ realtimeId: z.string().uuid(),
4052
+ operationId: z.string().uuid(),
4053
+ expectedVersion: z.number().int().positive(),
4054
+ expectedConnectionEpoch: z.number().int().positive(),
4055
+ rotate: z.boolean(),
4056
+ }).strict();
4057
+ export type GatewayRealtimeConnectRequest = z.infer<typeof GatewayRealtimeConnectRequest>;
4058
+
4059
+ export const GatewayRealtimeInitialItem = z.object({
4060
+ role: z.enum(["user", "developer", "assistant"]),
4061
+ text: z.string().min(1).max(131_072),
4062
+ });
4063
+ export type GatewayRealtimeInitialItem = z.infer<typeof GatewayRealtimeInitialItem>;
4064
+
4065
+ export const GatewayRealtimeConnectResponse = z
4066
+ .object({
4067
+ token: z.string().min(1).max(16_384),
4068
+ url: z.string().url(),
4069
+ upstreamModelId: z.string().min(1).max(256),
4070
+ expiresAt: z.number().int().positive().nullable(),
4071
+ connectionId: z.string().uuid(),
4072
+ connectionEpoch: z.number().int().positive(),
4073
+ startupFenceSequence: z.number().int().nonnegative(),
4074
+ modeVersion: z.number().int().positive(),
4075
+ initialItems: z.array(GatewayRealtimeInitialItem).max(128),
4076
+ instructions: z.string().min(1).max(32_768),
4077
+ replay: z.literal(false),
4078
+ })
4079
+ .strict();
4080
+ export type GatewayRealtimeConnectResponse = z.infer<typeof GatewayRealtimeConnectResponse>;
4081
+
4082
+ export const ActivateCodexRealtimeConnectionRequest = SessionRealtimeOwnerProof.extend({
4083
+ operationId: z.string().uuid(),
4084
+ connectionEpoch: z.number().int().positive(),
4085
+ expectedVersion: z.number().int().positive(),
4086
+ expectedConnectionEpoch: z.number().int().positive(),
4087
+ }).strict();
4088
+ export type ActivateCodexRealtimeConnectionRequest = z.infer<
4089
+ typeof ActivateCodexRealtimeConnectionRequest
4090
+ >;
4091
+
4092
+ export const SessionRealtimeLedgerDirection = z.enum(["provider_in", "provider_out"]);
4093
+ export type SessionRealtimeLedgerDirection = z.infer<typeof SessionRealtimeLedgerDirection>;
4094
+
4095
+ export const SessionRealtimeLedgerKind = z.enum([
4096
+ "user_transcript",
4097
+ "assistant_transcript",
4098
+ "delegation_call",
4099
+ "delegation_progress",
4100
+ "delegation_result",
4101
+ "interruption",
4102
+ "session_update",
4103
+ "error",
4104
+ ]);
4105
+ export type SessionRealtimeLedgerKind = z.infer<typeof SessionRealtimeLedgerKind>;
4106
+
4107
+ export const SessionRealtimeLedgerEntry = z
4108
+ .object({
4109
+ id: z.string().uuid(),
4110
+ realtimeId: z.string().uuid(),
4111
+ operationId: z.string().uuid(),
4112
+ connectionEpoch: z.number().int().positive(),
4113
+ sequence: z.number().int().positive(),
4114
+ direction: SessionRealtimeLedgerDirection,
4115
+ kind: SessionRealtimeLedgerKind,
4116
+ role: z.enum(["user", "assistant"]).nullable(),
4117
+ providerEventId: z.string().nullable(),
4118
+ delegationItemId: z.string().nullable(),
4119
+ sourceUpdateId: z.string().uuid().nullable(),
4120
+ historyItemId: z.string().uuid().nullable(),
4121
+ turnId: z.string().uuid().nullable(),
4122
+ text: z.string().nullable(),
4123
+ payload: z.record(z.string(), z.unknown()),
4124
+ clientAckedAt: z.string().datetime().nullable(),
4125
+ providerAckedAt: z.string().datetime().nullable(),
4126
+ createdAt: z.string().datetime(),
4127
+ updatedAt: z.string().datetime(),
4128
+ })
4129
+ .strict();
4130
+ export type SessionRealtimeLedgerEntry = z.infer<typeof SessionRealtimeLedgerEntry>;
4131
+
4132
+ export const SessionRealtimeInboundEntry = z
4133
+ .object({
4134
+ operationId: z.string().uuid(),
4135
+ kind: z.enum([
4136
+ "user_transcript",
4137
+ "assistant_transcript",
4138
+ "delegation_call",
4139
+ "interruption",
4140
+ "error",
4141
+ ]),
4142
+ role: z.enum(["user", "assistant"]).nullable().optional(),
4143
+ providerEventId: z.string().max(1024).nullable().optional(),
4144
+ delegationItemId: z.string().max(1024).nullable().optional(),
4145
+ text: z.string().max(131_072).nullable().optional(),
4146
+ payload: z.record(z.string(), z.unknown()).optional(),
4147
+ })
4148
+ .strict();
4149
+ export type SessionRealtimeInboundEntry = z.infer<typeof SessionRealtimeInboundEntry>;
4150
+
4151
+ export const SyncSessionRealtimeLedgerRequest = SessionRealtimeOwnerProof.extend({
4152
+ expectedVersion: z.number().int().positive(),
4153
+ connectionId: z.string().uuid(),
4154
+ connectionEpoch: z.number().int().positive(),
4155
+ entries: z.array(SessionRealtimeInboundEntry).max(64).optional(),
4156
+ clientAckThroughSequence: z.number().int().nonnegative().nullable().optional(),
4157
+ providerAckSequences: z.array(z.number().int().positive()).max(100).optional(),
4158
+ providerStarted: z
4159
+ .object({
4160
+ providerSessionId: z.string().min(1).max(1024),
4161
+ providerEventId: z.string().min(1).max(1024).nullable().optional(),
4162
+ })
4163
+ .strict()
4164
+ .optional(),
4165
+ }).strict();
4166
+ export type SyncSessionRealtimeLedgerRequest = z.infer<typeof SyncSessionRealtimeLedgerRequest>;
4167
+
4168
+ export const SyncSessionRealtimeLedgerResponse = z
4169
+ .object({
4170
+ accepted: z.array(
4171
+ z.object({ entry: SessionRealtimeLedgerEntry, replay: z.boolean() }).strict(),
4172
+ ),
4173
+ outbound: z.array(SessionRealtimeLedgerEntry),
4174
+ })
4175
+ .strict();
4176
+ export type SyncSessionRealtimeLedgerResponse = z.infer<typeof SyncSessionRealtimeLedgerResponse>;
4177
+
4178
+ export const SessionRealtimeModel = z.enum([
4179
+ "gpt-live-1-boulder-alpha",
4180
+ "opengeni-gateway/openai/gpt-realtime-2.1",
4181
+ "opengeni-gateway/openai/gpt-realtime-mini",
4182
+ "opengeni-gateway/xai/grok-voice-think-fast-2.0",
4183
+ "workspace-gateway/openai/gpt-realtime-2.1",
4184
+ "workspace-gateway/openai/gpt-realtime-mini",
4185
+ "workspace-gateway/xai/grok-voice-think-fast-2.0",
4186
+ ]);
4187
+ export type SessionRealtimeModel = z.infer<typeof SessionRealtimeModel>;
4188
+
4189
+ export const WorkspaceRealtimeModelCatalogItem = z.object({
4190
+ id: SessionRealtimeModel,
4191
+ label: z.string().min(1),
4192
+ provider: z.enum(["OpenGeni", "Connected Codex", "Your Gateway"]),
4193
+ description: z.string().min(1),
4194
+ available: z.boolean(),
4195
+ unavailableReason: z.string().nullable(),
4196
+ recommended: z.boolean(),
4197
+ });
4198
+ export type WorkspaceRealtimeModelCatalogItem = z.infer<typeof WorkspaceRealtimeModelCatalogItem>;
4199
+
4200
+ export const WorkspaceRealtimeModelCatalogResponse = z.object({
4201
+ models: z.array(WorkspaceRealtimeModelCatalogItem),
4202
+ });
4203
+ export type WorkspaceRealtimeModelCatalogResponse = z.infer<
4204
+ typeof WorkspaceRealtimeModelCatalogResponse
4205
+ >;
4206
+
4207
+ export const SessionRealtimeState = z.enum(["active", "ended"]);
4208
+ export type SessionRealtimeState = z.infer<typeof SessionRealtimeState>;
4209
+
4210
+ export const SessionRealtimeEndReason = z.enum(["user_stop", "browser_unload", "lease_expired"]);
4211
+ export type SessionRealtimeEndReason = z.infer<typeof SessionRealtimeEndReason>;
4212
+
4213
+ export const SessionRealtimeMode = z.object({
4214
+ id: z.string().uuid(),
4215
+ sessionId: z.string().uuid(),
4216
+ operationId: z.string().uuid(),
4217
+ browserInstanceId: z.string().min(1).max(256),
4218
+ model: SessionRealtimeModel,
4219
+ state: SessionRealtimeState,
4220
+ version: z.number().int().positive(),
4221
+ connectionEpoch: z.number().int().positive(),
4222
+ leaseExpiresAt: z.string().datetime(),
4223
+ lastHeartbeatAt: z.string().datetime(),
4224
+ startedAt: z.string().datetime(),
4225
+ endedAt: z.string().datetime().nullable(),
4226
+ endReason: SessionRealtimeEndReason.nullable(),
4227
+ });
4228
+ export type SessionRealtimeMode = z.infer<typeof SessionRealtimeMode>;
4229
+
4230
+ export const BeginSessionRealtimeRequest = SessionRealtimeOwnerProof.extend({
4231
+ operationId: z.string().uuid(),
4232
+ model: SessionRealtimeModel,
4233
+ });
4234
+ export type BeginSessionRealtimeRequest = z.infer<typeof BeginSessionRealtimeRequest>;
4235
+
4236
+ export const RenewSessionRealtimeRequest = SessionRealtimeOwnerProof.extend({
4237
+ expectedVersion: z.number().int().positive(),
4238
+ });
4239
+ export type RenewSessionRealtimeRequest = z.infer<typeof RenewSessionRealtimeRequest>;
4240
+
4241
+ export const EndSessionRealtimeRequest = RenewSessionRealtimeRequest.extend({
4242
+ reason: z.enum(["user_stop", "browser_unload"]),
4243
+ });
4244
+ export type EndSessionRealtimeRequest = z.infer<typeof EndSessionRealtimeRequest>;
4245
+
4246
+ export const SessionRealtimeMutationResponse = z.object({
4247
+ mode: SessionRealtimeMode,
4248
+ replay: z.boolean(),
4249
+ });
4250
+ export type SessionRealtimeMutationResponse = z.infer<typeof SessionRealtimeMutationResponse>;
4251
+
3901
4252
  export const SessionAuthorizationOperation = z.enum([
3902
4253
  "session.read",
3903
4254
  "session.events.read",
@@ -3924,6 +4275,8 @@ export const SessionAuthorizationOperation = z.enum([
3924
4275
  "session.toolspace.call",
3925
4276
  "session.pin.write",
3926
4277
  "session.codex_account.write",
4278
+ "session.realtime.start",
4279
+ "session.realtime.control",
3927
4280
  "session.context.write",
3928
4281
  "session.approval.write",
3929
4282
  "session.human_input.read",
@@ -4246,7 +4599,7 @@ const WorkspaceControlReason = z
4246
4599
  );
4247
4600
 
4248
4601
  export const SessionControlRequest = z.object({
4249
- action: z.enum(["pause", "resume"]),
4602
+ action: z.enum(["pause", "resume", "cancel"]),
4250
4603
  reason: WorkspaceControlReason.optional(),
4251
4604
  clientEventId: SessionOperationKey,
4252
4605
  expectedControlEtag: z.string().min(1).optional(),
@@ -4494,7 +4847,7 @@ export const SessionSystemUpdatePayload = z.discriminatedUnion("type", [
4494
4847
  .object({
4495
4848
  type: z.literal("child_terminal_result"),
4496
4849
  childSessionId: z.string().uuid(),
4497
- status: z.enum(["idle", "failed"]),
4850
+ status: z.enum(["idle", "failed", "cancelled"]),
4498
4851
  })
4499
4852
  .passthrough(),
4500
4853
  ]);
@@ -5786,6 +6139,10 @@ export const Session = z.object({
5786
6139
  // metadata (exposed like title/goal), never a secret and never a timeline event.
5787
6140
  // null when the session carried none.
5788
6141
  instructions: z.string().nullable(),
6142
+ // Immutable prompt-policy role binding. This is separate from human
6143
+ // workspace membership roles and from memory selectors. Null keeps the
6144
+ // compatibility fallback to a normalized metadata.role value.
6145
+ policyRole: WorkspaceInstructionPolicyRoleKeyInput.nullable().default(null),
5789
6146
  resources: z.array(ResourceRef),
5790
6147
  skills: SessionSkills.default([]),
5791
6148
  tools: z.array(ToolRef),
@@ -5959,6 +6316,8 @@ export const SessionEventType = z.enum([
5959
6316
  // crossing NATS, SSE, REST, or browser boundaries.
5960
6317
  "session.event.envelope_omitted",
5961
6318
  "session.status.changed",
6319
+ "session.realtime.started",
6320
+ "session.realtime.ended",
5962
6321
  "session.requiresAction",
5963
6322
  "session.humanInput.requested",
5964
6323
  "session.context.compaction.requested",
@@ -7354,7 +7713,12 @@ function compactFailure(
7354
7713
  const code = compactResultStringField(payload.code);
7355
7714
  const recovery = compactResultStringField(payload.recovery);
7356
7715
  const retryable = typeof payload.retryable === "boolean" ? payload.retryable : null;
7357
- const value = { error: error.value, code: code.value, retryable, recovery: recovery.value };
7716
+ const value = {
7717
+ error: error.value,
7718
+ code: code.value,
7719
+ retryable,
7720
+ recovery: recovery.value,
7721
+ };
7358
7722
  const originalBytes = [error, code, recovery]
7359
7723
  .map((field) => field.originalBytes ?? 0)
7360
7724
  .reduce((sum, bytes) => sum + bytes, 0);
@@ -8045,6 +8409,8 @@ export const SessionControlResponse = z.object({
8045
8409
  effectiveControl: EffectiveSessionControl,
8046
8410
  interruptionCount: z.number().int().nonnegative(),
8047
8411
  wakeCount: z.number().int().nonnegative(),
8412
+ cancelledSessionCount: z.number().int().nonnegative(),
8413
+ cancelledTurnCount: z.number().int().nonnegative(),
8048
8414
  });
8049
8415
  export type SessionControlResponse = z.infer<typeof SessionControlResponse>;
8050
8416
 
@@ -8056,7 +8422,11 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8056
8422
  * identity or authorization from the UUID.
8057
8423
  */
8058
8424
  requestedSessionId: z.string().uuid().optional(),
8059
- initialMessage: z.string().min(1),
8425
+ initialMessage: z.string().min(1).optional(),
8426
+ // Creates the durable session shell without fabricating a user message or
8427
+ // starting an underlying agent turn. Realtime can then become the first
8428
+ // interaction and use the ordinary Send/Steer path when it delegates.
8429
+ startMode: z.literal("realtime").optional(),
8060
8430
  // System-level host context for the initial turn only. Unlike `instructions`,
8061
8431
  // this does not persist into later turns and is never emitted as a user event.
8062
8432
  turnInstructions: z.string().trim().min(1).max(32768).optional(),
@@ -8069,6 +8439,11 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8069
8439
  // matches the codebase's largest free-form string convention (workspace
8070
8440
  // variable set variable values). Absent ⇒ byte-identical to today.
8071
8441
  instructions: z.string().trim().min(1).max(32768).optional(),
8442
+ // Immutable prompt-policy role binding for matching one activated role
8443
+ // policy. This never derives from or grants a human workspace membership
8444
+ // role. Existing callers may continue to use normalized metadata.role as a
8445
+ // compatibility fallback by omitting this field.
8446
+ policyRole: WorkspaceInstructionPolicyRoleKeyInput.optional(),
8072
8447
  // For an agent-created child, omission inherits the trusted immediate
8073
8448
  // parent's repository/file context. An explicit array, including [], is
8074
8449
  // authoritative. Top-level omission remains []. Presence is resolved from
@@ -8102,10 +8477,10 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8102
8477
  variableSetId: z.string().uuid().optional(),
8103
8478
  environmentId: z.string().uuid().optional(),
8104
8479
  // The rig to bind this session to (M3). Its ACTIVE version is resolved and
8105
- // FROZEN onto the session at create. Omitted ⇒ the workspace's default rig
8106
- // (workspaces.default_rig_id) when set, else a rig-less session (today's
8107
- // behavior). An id that does not name a rig in the workspace is a 422.
8108
- rigId: z.string().uuid().optional(),
8480
+ // FROZEN onto the session at create. Omitted ⇒ inherit the workspace default;
8481
+ // null explicitly create a rig-less session; UUID ⇒ bind that exact rig.
8482
+ // An id that does not name a rig in the workspace is a 422.
8483
+ rigId: z.string().uuid().nullable().optional(),
8109
8484
  goal: GoalSpec.optional(),
8110
8485
  clientEventId: SessionOperationKey.optional(),
8111
8486
  // Workspace-scoped CREATE idempotency key: collapses concurrent/retried
@@ -8162,6 +8537,21 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8162
8537
  sandbox: z
8163
8538
  .union([z.literal("shared"), z.literal("new"), z.object({ groupId: z.string().uuid() })])
8164
8539
  .optional(),
8540
+ }).superRefine((value, context) => {
8541
+ if (value.startMode !== "realtime" && value.initialMessage === undefined) {
8542
+ context.addIssue({
8543
+ code: z.ZodIssueCode.custom,
8544
+ path: ["initialMessage"],
8545
+ message: "initialMessage is required unless startMode is realtime",
8546
+ });
8547
+ }
8548
+ if (value.startMode === "realtime" && value.initialMessage !== undefined) {
8549
+ context.addIssue({
8550
+ code: z.ZodIssueCode.custom,
8551
+ path: ["initialMessage"],
8552
+ message: "initialMessage must be omitted when startMode is realtime",
8553
+ });
8554
+ }
8165
8555
  });
8166
8556
  export type CreateSessionRequest = z.infer<typeof CreateSessionRequest>;
8167
8557
 
@@ -9090,9 +9480,8 @@ function defineModelContractSchema<Schema>(factory: () => Schema): Schema {
9090
9480
  return factory();
9091
9481
  }
9092
9482
 
9093
- export const ModelCapabilitySupportV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9094
- z.enum(["supported", "unsupported", "unknown"]),
9095
- );
9483
+ export const ModelCapabilitySupportV1 =
9484
+ /* @__PURE__ */ defineModelContractSchema(() => z.enum(["supported", "unsupported", "unknown"]));
9096
9485
  export type ModelCapabilitySupportV1 = z.infer<typeof ModelCapabilitySupportV1>;
9097
9486
 
9098
9487
  export const ModelCapabilityStateV1 = /* @__PURE__ */ defineModelContractSchema(() =>
@@ -9139,37 +9528,54 @@ export const ModelCapabilitiesV1 = /* @__PURE__ */ defineModelContractSchema(()
9139
9528
  );
9140
9529
  export type ModelCapabilitiesV1 = z.infer<typeof ModelCapabilitiesV1>;
9141
9530
 
9142
- export const ModelCredentialSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9143
- z.union([
9144
- z
9145
- .object({ kind: z.literal("deployment"), mechanism: z.enum(["api_key", "azure_ad_bearer"]) })
9146
- .strict(),
9147
- z.object({ kind: z.literal("connected_subscription"), provider: z.literal("codex") }).strict(),
9148
- z.object({ kind: z.literal("workspace_connection"), mechanism: z.literal("api_key") }).strict(),
9149
- ]),
9150
- );
9531
+ export const ModelCredentialSourceV1 =
9532
+ /* @__PURE__ */ defineModelContractSchema(() =>
9533
+ z.union([
9534
+ z
9535
+ .object({
9536
+ kind: z.literal("deployment"),
9537
+ mechanism: z.enum(["api_key", "azure_ad_bearer"]),
9538
+ })
9539
+ .strict(),
9540
+ z
9541
+ .object({
9542
+ kind: z.literal("connected_subscription"),
9543
+ provider: z.literal("codex"),
9544
+ })
9545
+ .strict(),
9546
+ z
9547
+ .object({
9548
+ kind: z.literal("workspace_connection"),
9549
+ mechanism: z.literal("api_key"),
9550
+ })
9551
+ .strict(),
9552
+ ]),
9553
+ );
9151
9554
  export type ModelCredentialSourceV1 = z.infer<typeof ModelCredentialSourceV1>;
9152
9555
 
9153
- export const ModelBillingAttributionV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9154
- z
9155
- .object({
9156
- upstreamPayer: z.enum(["deployment", "workspace", "connected_subscription"]),
9157
- metering: z.enum(["opengeni_credits", "external"]),
9158
- })
9159
- .strict(),
9160
- );
9556
+ export const ModelBillingAttributionV1 =
9557
+ /* @__PURE__ */ defineModelContractSchema(() =>
9558
+ z
9559
+ .object({
9560
+ upstreamPayer: z.enum(["deployment", "workspace", "connected_subscription"]),
9561
+ metering: z.enum(["opengeni_credits", "external"]),
9562
+ })
9563
+ .strict(),
9564
+ );
9161
9565
  export type ModelBillingAttributionV1 = z.infer<typeof ModelBillingAttributionV1>;
9162
9566
 
9163
9567
  export const TURN_EXECUTION_POLICY_METADATA_KEY = "turnExecutionPolicyV1" as const;
9164
9568
 
9165
- export const TurnExecutionModelSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9166
- z.enum(["explicit", "session", "deployment", "continuation"]),
9167
- );
9569
+ export const TurnExecutionModelSourceV1 =
9570
+ /* @__PURE__ */ defineModelContractSchema(() =>
9571
+ z.enum(["explicit", "session", "deployment", "continuation"]),
9572
+ );
9168
9573
  export type TurnExecutionModelSourceV1 = z.infer<typeof TurnExecutionModelSourceV1>;
9169
9574
 
9170
- export const TurnExecutionReasoningSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9171
- z.enum(["explicit", "session", "deployment", "continuation"]),
9172
- );
9575
+ export const TurnExecutionReasoningSourceV1 =
9576
+ /* @__PURE__ */ defineModelContractSchema(() =>
9577
+ z.enum(["explicit", "session", "deployment", "continuation"]),
9578
+ );
9173
9579
  export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoningSourceV1>;
9174
9580
 
9175
9581
  export const TurnExecutionLatencyModeSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
@@ -9374,59 +9780,60 @@ export const ClientModel = /* @__PURE__ */ defineModelContractSchema(() =>
9374
9780
  );
9375
9781
  export type ClientModel = z.infer<typeof ClientModel>;
9376
9782
 
9377
- export const ModelCredentialReadinessV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9378
- z
9379
- .object({
9380
- status: z.enum(["ready", "not_ready", "error"]),
9381
- reason: z
9382
- .enum([
9383
- "missing_credential",
9384
- "needs_reauth",
9385
- "prerequisites_missing",
9386
- "resolver_error",
9387
- "observation_stale",
9388
- ])
9389
- .nullable(),
9390
- basis: z.enum(["configuration", "connection", "resolver"]),
9391
- checkedAt: z.string().datetime().nullable(),
9392
- })
9393
- .strict()
9394
- .superRefine((readiness, context) => {
9395
- if ((readiness.status === "ready") !== (readiness.reason === null)) {
9396
- context.addIssue({
9397
- code: "custom",
9398
- path: ["reason"],
9399
- message: "ready credential state requires no reason; non-ready state requires a reason",
9400
- });
9401
- }
9402
- if ((readiness.status === "error") !== (readiness.reason === "resolver_error")) {
9403
- context.addIssue({
9404
- code: "custom",
9405
- path: ["reason"],
9406
- message:
9407
- "credential errors require resolver_error and resolver_error requires error status",
9408
- });
9409
- }
9410
- if (
9411
- readiness.basis === "resolver" &&
9412
- readiness.status === "ready" &&
9413
- readiness.checkedAt === null
9414
- ) {
9415
- context.addIssue({
9416
- code: "custom",
9417
- path: ["checkedAt"],
9418
- message: "resolver readiness requires an observation timestamp",
9419
- });
9420
- }
9421
- if (readiness.reason === "observation_stale" && readiness.checkedAt === null) {
9422
- context.addIssue({
9423
- code: "custom",
9424
- path: ["checkedAt"],
9425
- message: "a stale observation requires its observation timestamp",
9426
- });
9427
- }
9428
- }),
9429
- );
9783
+ export const ModelCredentialReadinessV1 =
9784
+ /* @__PURE__ */ defineModelContractSchema(() =>
9785
+ z
9786
+ .object({
9787
+ status: z.enum(["ready", "not_ready", "error"]),
9788
+ reason: z
9789
+ .enum([
9790
+ "missing_credential",
9791
+ "needs_reauth",
9792
+ "prerequisites_missing",
9793
+ "resolver_error",
9794
+ "observation_stale",
9795
+ ])
9796
+ .nullable(),
9797
+ basis: z.enum(["configuration", "connection", "resolver"]),
9798
+ checkedAt: z.string().datetime().nullable(),
9799
+ })
9800
+ .strict()
9801
+ .superRefine((readiness, context) => {
9802
+ if ((readiness.status === "ready") !== (readiness.reason === null)) {
9803
+ context.addIssue({
9804
+ code: "custom",
9805
+ path: ["reason"],
9806
+ message: "ready credential state requires no reason; non-ready state requires a reason",
9807
+ });
9808
+ }
9809
+ if ((readiness.status === "error") !== (readiness.reason === "resolver_error")) {
9810
+ context.addIssue({
9811
+ code: "custom",
9812
+ path: ["reason"],
9813
+ message:
9814
+ "credential errors require resolver_error and resolver_error requires error status",
9815
+ });
9816
+ }
9817
+ if (
9818
+ readiness.basis === "resolver" &&
9819
+ readiness.status === "ready" &&
9820
+ readiness.checkedAt === null
9821
+ ) {
9822
+ context.addIssue({
9823
+ code: "custom",
9824
+ path: ["checkedAt"],
9825
+ message: "resolver readiness requires an observation timestamp",
9826
+ });
9827
+ }
9828
+ if (readiness.reason === "observation_stale" && readiness.checkedAt === null) {
9829
+ context.addIssue({
9830
+ code: "custom",
9831
+ path: ["checkedAt"],
9832
+ message: "a stale observation requires its observation timestamp",
9833
+ });
9834
+ }
9835
+ }),
9836
+ );
9430
9837
  export type ModelCredentialReadinessV1 = z.infer<typeof ModelCredentialReadinessV1>;
9431
9838
 
9432
9839
  export const ModelAvailabilityV1 = /* @__PURE__ */ defineModelContractSchema(() =>
@@ -9449,19 +9856,21 @@ export const ModelAvailabilityV1 = /* @__PURE__ */ defineModelContractSchema(()
9449
9856
  );
9450
9857
  export type ModelAvailabilityV1 = z.infer<typeof ModelAvailabilityV1>;
9451
9858
 
9452
- export const WorkspaceModelCatalogModel = /* @__PURE__ */ defineModelContractSchema(() =>
9453
- ClientModel.extend({
9454
- credentialReadiness: ModelCredentialReadinessV1,
9455
- availability: ModelAvailabilityV1,
9456
- }),
9457
- );
9859
+ export const WorkspaceModelCatalogModel =
9860
+ /* @__PURE__ */ defineModelContractSchema(() =>
9861
+ ClientModel.extend({
9862
+ credentialReadiness: ModelCredentialReadinessV1,
9863
+ availability: ModelAvailabilityV1,
9864
+ }),
9865
+ );
9458
9866
  export type WorkspaceModelCatalogModel = z.infer<typeof WorkspaceModelCatalogModel>;
9459
9867
 
9460
- export const WorkspaceModelCatalogResponse = /* @__PURE__ */ defineModelContractSchema(() =>
9461
- z.object({
9462
- models: z.array(WorkspaceModelCatalogModel),
9463
- }),
9464
- );
9868
+ export const WorkspaceModelCatalogResponse =
9869
+ /* @__PURE__ */ defineModelContractSchema(() =>
9870
+ z.object({
9871
+ models: z.array(WorkspaceModelCatalogModel),
9872
+ }),
9873
+ );
9465
9874
  export type WorkspaceModelCatalogResponse = z.infer<typeof WorkspaceModelCatalogResponse>;
9466
9875
 
9467
9876
  /**