@opengeni/contracts 0.31.1 → 0.35.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>;
@@ -2868,6 +2957,14 @@ export const FileResourceRef = z.object({
2868
2957
  });
2869
2958
  export type FileResourceRef = z.infer<typeof FileResourceRef>;
2870
2959
 
2960
+ /**
2961
+ * Private durable metadata carried on user history items. It contains only
2962
+ * stable file references, never file bytes, and is removed before model wire
2963
+ * serialization. Keeping the references beside the message lets a later turn
2964
+ * reconstruct the same typed attachment input after a model switch or retry.
2965
+ */
2966
+ export const MODEL_ATTACHMENT_REFS_FIELD = "opengeni_attachment_refs" as const;
2967
+
2871
2968
  export const ResourceRef = z.discriminatedUnion("kind", [RepositoryResourceRef, FileResourceRef]);
2872
2969
  export type ResourceRef = z.infer<typeof ResourceRef>;
2873
2970
 
@@ -2954,10 +3051,12 @@ export function defaultRepositoryMountPath(uri: string): string {
2954
3051
  }
2955
3052
 
2956
3053
  /** Resolve the exact mount used by API normalization, manifests, and clone hooks. */
3054
+ export const DEFAULT_FILE_RESOURCE_MOUNT_ROOT = ".opengeni/files" as const;
3055
+
2957
3056
  export function resourceMountPath(resource: ResourceRef): string {
2958
3057
  if (resource.mountPath) return normalizeResourceMountPath(resource.mountPath);
2959
3058
  return resource.kind === "file"
2960
- ? normalizeResourceMountPath(`files/${resource.fileId}`)
3059
+ ? normalizeResourceMountPath(`${DEFAULT_FILE_RESOURCE_MOUNT_ROOT}/${resource.fileId}`)
2961
3060
  : defaultRepositoryMountPath(resource.uri);
2962
3061
  }
2963
3062
 
@@ -3049,8 +3148,15 @@ export type KnowledgeSourceKind = z.infer<typeof KnowledgeSourceKind>;
3049
3148
  export const DocumentSearchMode = z.enum(["hybrid", "vector", "keyword"]);
3050
3149
  export type DocumentSearchMode = z.infer<typeof DocumentSearchMode>;
3051
3150
 
3151
+ // Durable document authority. Collections/bases are organizational metadata,
3152
+ // never an authorization boundary.
3153
+ export const DocumentAuthorityKind = z.enum(["organization", "workspace", "personal"]);
3154
+ export type DocumentAuthorityKind = z.infer<typeof DocumentAuthorityKind>;
3155
+
3052
3156
  // 'workspace' documents are readable by anyone with workspace access;
3053
3157
  // 'private' documents are readable only by the grant subject that created them.
3158
+ // Retained as a compatibility projection over authorityKind:
3159
+ // personal -> private; organization/workspace -> workspace.
3054
3160
  export const DocumentVisibility = z.enum(["workspace", "private"]);
3055
3161
  export type DocumentVisibility = z.infer<typeof DocumentVisibility>;
3056
3162
 
@@ -3109,6 +3215,9 @@ export const Document = z.object({
3109
3215
  sourceUpdatedAt: z.string().nullable(),
3110
3216
  sourceVersion: z.string().nullable(),
3111
3217
  aclTags: z.array(z.string()),
3218
+ authorityKind: DocumentAuthorityKind,
3219
+ authorityWorkspaceId: z.string().uuid().nullable(),
3220
+ authoritySubjectId: z.string().nullable(),
3112
3221
  visibility: DocumentVisibility,
3113
3222
  createdBy: z.string().nullable(),
3114
3223
  agentAccess: z.boolean(),
@@ -3123,6 +3232,9 @@ export type Document = z.infer<typeof Document>;
3123
3232
 
3124
3233
  export const DocumentSearchResult = z.object({
3125
3234
  chunkId: z.string().uuid(),
3235
+ // The workspace that ingested the document. Organization-authority results
3236
+ // may originate in another workspace in the same account; this identifier
3237
+ // is provenance and does not grant access to that workspace or its resources.
3126
3238
  workspaceId: z.string().uuid(),
3127
3239
  documentId: z.string().uuid(),
3128
3240
  baseId: z.string().uuid(),
@@ -3144,9 +3256,17 @@ export const DocumentSearchResult = z.object({
3144
3256
  sourceUpdatedAt: z.string().nullable(),
3145
3257
  sourceVersion: z.string().nullable(),
3146
3258
  aclTags: z.array(z.string()),
3259
+ authorityKind: DocumentAuthorityKind,
3260
+ authorityWorkspaceId: z.string().uuid().nullable(),
3261
+ authoritySubjectId: z.string().nullable(),
3147
3262
  });
3148
3263
  export type DocumentSearchResult = z.infer<typeof DocumentSearchResult>;
3149
3264
 
3265
+ export const DocumentSearchResponse = z.object({
3266
+ results: z.array(DocumentSearchResult),
3267
+ });
3268
+ export type DocumentSearchResponse = z.infer<typeof DocumentSearchResponse>;
3269
+
3150
3270
  export const CreateDocumentBaseRequest = z.object({
3151
3271
  name: z.string().min(1),
3152
3272
  description: z.string().optional(),
@@ -3165,6 +3285,7 @@ export const AddDocumentRequest = z.object({
3165
3285
  sourceUpdatedAt: z.string().datetime({ offset: true }).optional(),
3166
3286
  sourceVersion: z.string().min(1).optional(),
3167
3287
  aclTags: z.array(z.string().min(1)).optional(),
3288
+ authorityKind: DocumentAuthorityKind.optional(),
3168
3289
  visibility: DocumentVisibility.optional(),
3169
3290
  agentAccess: z.boolean().optional(),
3170
3291
  });
@@ -3181,6 +3302,7 @@ export const CreateKnowledgeDropRequest = z
3181
3302
  fileId: z.string().uuid().optional(),
3182
3303
  filename: z.string().min(1).optional(),
3183
3304
  title: z.string().min(1).optional(),
3305
+ authorityKind: DocumentAuthorityKind.optional(),
3184
3306
  visibility: DocumentVisibility.optional(),
3185
3307
  agentAccess: z.boolean().optional(),
3186
3308
  })
@@ -3604,7 +3726,8 @@ export function reasoningEffortForMetadata(
3604
3726
  value === "low" ||
3605
3727
  value === "medium" ||
3606
3728
  value === "high" ||
3607
- value === "xhigh"
3729
+ value === "xhigh" ||
3730
+ value === "max"
3608
3731
  ? value
3609
3732
  : fallback;
3610
3733
  }
@@ -3898,6 +4021,267 @@ export const SessionAuthorizationSurface = z.enum([
3898
4021
  ]);
3899
4022
  export type SessionAuthorizationSurface = z.infer<typeof SessionAuthorizationSurface>;
3900
4023
 
4024
+ // Native connected-Codex GPT-Live WebRTC negotiation. The browser sends its
4025
+ // SDP offer, non-provider session configuration, and proof of the exact active
4026
+ // ordinary-session realtime owner. The API consumes that proof before resolving
4027
+ // the subscription credential and returns only the provider's SDP answer.
4028
+ export const CodexRealtimeWebrtcVersion = z.literal("v3");
4029
+ export type CodexRealtimeWebrtcVersion = z.infer<typeof CodexRealtimeWebrtcVersion>;
4030
+
4031
+ export const CodexRealtimeVoice = z.enum([
4032
+ "juniper",
4033
+ "maple",
4034
+ "spruce",
4035
+ "ember",
4036
+ "vale",
4037
+ "breeze",
4038
+ "arbor",
4039
+ "sol",
4040
+ "cove",
4041
+ ]);
4042
+ export type CodexRealtimeVoice = z.infer<typeof CodexRealtimeVoice>;
4043
+
4044
+ const SessionRealtimeOwnerProof = z.object({
4045
+ browserInstanceId: z.string().min(1).max(256),
4046
+ ownerKey: z.string().min(32).max(1024),
4047
+ });
4048
+
4049
+ export const CodexRealtimeWebrtcRequest = SessionRealtimeOwnerProof.extend({
4050
+ realtimeId: z.string().uuid(),
4051
+ operationId: z.string().uuid(),
4052
+ expectedVersion: z.number().int().positive(),
4053
+ expectedConnectionEpoch: z.number().int().positive(),
4054
+ rotate: z.boolean(),
4055
+ browserActivation: z.literal("required").optional(),
4056
+ sdp: z
4057
+ .string()
4058
+ .min(1)
4059
+ .max(1024 * 1024),
4060
+ version: CodexRealtimeWebrtcVersion,
4061
+ instructions: z.string().max(32_768).optional(),
4062
+ voice: CodexRealtimeVoice.optional(),
4063
+ }).strict();
4064
+ export type CodexRealtimeWebrtcRequest = z.infer<typeof CodexRealtimeWebrtcRequest>;
4065
+
4066
+ export const CodexRealtimeWebrtcResponse = z
4067
+ .object({
4068
+ sdp: z
4069
+ .string()
4070
+ .min(1)
4071
+ .max(1024 * 1024),
4072
+ version: CodexRealtimeWebrtcVersion,
4073
+ model: z.literal("gpt-live-1-boulder-alpha"),
4074
+ connectionId: z.string().uuid(),
4075
+ connectionEpoch: z.number().int().positive(),
4076
+ startupFenceSequence: z.number().int().nonnegative(),
4077
+ modeVersion: z.number().int().positive(),
4078
+ replay: z.boolean(),
4079
+ })
4080
+ .strict();
4081
+ export type CodexRealtimeWebrtcResponse = z.infer<typeof CodexRealtimeWebrtcResponse>;
4082
+
4083
+ export const GatewayRealtimeConnectRequest = SessionRealtimeOwnerProof.extend({
4084
+ realtimeId: z.string().uuid(),
4085
+ operationId: z.string().uuid(),
4086
+ expectedVersion: z.number().int().positive(),
4087
+ expectedConnectionEpoch: z.number().int().positive(),
4088
+ rotate: z.boolean(),
4089
+ }).strict();
4090
+ export type GatewayRealtimeConnectRequest = z.infer<typeof GatewayRealtimeConnectRequest>;
4091
+
4092
+ export const GatewayRealtimeInitialItem = z.object({
4093
+ role: z.enum(["user", "developer", "assistant"]),
4094
+ text: z.string().min(1).max(131_072),
4095
+ });
4096
+ export type GatewayRealtimeInitialItem = z.infer<typeof GatewayRealtimeInitialItem>;
4097
+
4098
+ export const GatewayRealtimeConnectResponse = z
4099
+ .object({
4100
+ token: z.string().min(1).max(16_384),
4101
+ url: z.string().url(),
4102
+ upstreamModelId: z.string().min(1).max(256),
4103
+ expiresAt: z.number().int().positive().nullable(),
4104
+ connectionId: z.string().uuid(),
4105
+ connectionEpoch: z.number().int().positive(),
4106
+ startupFenceSequence: z.number().int().nonnegative(),
4107
+ modeVersion: z.number().int().positive(),
4108
+ initialItems: z.array(GatewayRealtimeInitialItem).max(128),
4109
+ instructions: z.string().min(1).max(32_768),
4110
+ replay: z.literal(false),
4111
+ })
4112
+ .strict();
4113
+ export type GatewayRealtimeConnectResponse = z.infer<typeof GatewayRealtimeConnectResponse>;
4114
+
4115
+ export const ActivateCodexRealtimeConnectionRequest = SessionRealtimeOwnerProof.extend({
4116
+ operationId: z.string().uuid(),
4117
+ connectionEpoch: z.number().int().positive(),
4118
+ expectedVersion: z.number().int().positive(),
4119
+ expectedConnectionEpoch: z.number().int().positive(),
4120
+ }).strict();
4121
+ export type ActivateCodexRealtimeConnectionRequest = z.infer<
4122
+ typeof ActivateCodexRealtimeConnectionRequest
4123
+ >;
4124
+
4125
+ export const SessionRealtimeLedgerDirection = z.enum(["provider_in", "provider_out"]);
4126
+ export type SessionRealtimeLedgerDirection = z.infer<typeof SessionRealtimeLedgerDirection>;
4127
+
4128
+ export const SessionRealtimeLedgerKind = z.enum([
4129
+ "user_transcript",
4130
+ "assistant_transcript",
4131
+ "delegation_call",
4132
+ "delegation_progress",
4133
+ "delegation_result",
4134
+ "interruption",
4135
+ "session_update",
4136
+ "error",
4137
+ ]);
4138
+ export type SessionRealtimeLedgerKind = z.infer<typeof SessionRealtimeLedgerKind>;
4139
+
4140
+ export const SessionRealtimeLedgerEntry = z
4141
+ .object({
4142
+ id: z.string().uuid(),
4143
+ realtimeId: z.string().uuid(),
4144
+ operationId: z.string().uuid(),
4145
+ connectionEpoch: z.number().int().positive(),
4146
+ sequence: z.number().int().positive(),
4147
+ direction: SessionRealtimeLedgerDirection,
4148
+ kind: SessionRealtimeLedgerKind,
4149
+ role: z.enum(["user", "assistant"]).nullable(),
4150
+ providerEventId: z.string().nullable(),
4151
+ delegationItemId: z.string().nullable(),
4152
+ sourceUpdateId: z.string().uuid().nullable(),
4153
+ historyItemId: z.string().uuid().nullable(),
4154
+ turnId: z.string().uuid().nullable(),
4155
+ text: z.string().nullable(),
4156
+ payload: z.record(z.string(), z.unknown()),
4157
+ clientAckedAt: z.string().datetime().nullable(),
4158
+ providerAckedAt: z.string().datetime().nullable(),
4159
+ createdAt: z.string().datetime(),
4160
+ updatedAt: z.string().datetime(),
4161
+ })
4162
+ .strict();
4163
+ export type SessionRealtimeLedgerEntry = z.infer<typeof SessionRealtimeLedgerEntry>;
4164
+
4165
+ export const SessionRealtimeInboundEntry = z
4166
+ .object({
4167
+ operationId: z.string().uuid(),
4168
+ kind: z.enum([
4169
+ "user_transcript",
4170
+ "assistant_transcript",
4171
+ "delegation_call",
4172
+ "interruption",
4173
+ "error",
4174
+ ]),
4175
+ role: z.enum(["user", "assistant"]).nullable().optional(),
4176
+ providerEventId: z.string().max(1024).nullable().optional(),
4177
+ delegationItemId: z.string().max(1024).nullable().optional(),
4178
+ text: z.string().max(131_072).nullable().optional(),
4179
+ payload: z.record(z.string(), z.unknown()).optional(),
4180
+ })
4181
+ .strict();
4182
+ export type SessionRealtimeInboundEntry = z.infer<typeof SessionRealtimeInboundEntry>;
4183
+
4184
+ export const SyncSessionRealtimeLedgerRequest = SessionRealtimeOwnerProof.extend({
4185
+ expectedVersion: z.number().int().positive(),
4186
+ connectionId: z.string().uuid(),
4187
+ connectionEpoch: z.number().int().positive(),
4188
+ entries: z.array(SessionRealtimeInboundEntry).max(64).optional(),
4189
+ clientAckThroughSequence: z.number().int().nonnegative().nullable().optional(),
4190
+ providerAckSequences: z.array(z.number().int().positive()).max(100).optional(),
4191
+ providerStarted: z
4192
+ .object({
4193
+ providerSessionId: z.string().min(1).max(1024),
4194
+ providerEventId: z.string().min(1).max(1024).nullable().optional(),
4195
+ })
4196
+ .strict()
4197
+ .optional(),
4198
+ }).strict();
4199
+ export type SyncSessionRealtimeLedgerRequest = z.infer<typeof SyncSessionRealtimeLedgerRequest>;
4200
+
4201
+ export const SyncSessionRealtimeLedgerResponse = z
4202
+ .object({
4203
+ accepted: z.array(
4204
+ z.object({ entry: SessionRealtimeLedgerEntry, replay: z.boolean() }).strict(),
4205
+ ),
4206
+ outbound: z.array(SessionRealtimeLedgerEntry),
4207
+ })
4208
+ .strict();
4209
+ export type SyncSessionRealtimeLedgerResponse = z.infer<typeof SyncSessionRealtimeLedgerResponse>;
4210
+
4211
+ export const SessionRealtimeModel = z.enum([
4212
+ "gpt-live-1-boulder-alpha",
4213
+ "opengeni-gateway/openai/gpt-realtime-2.1",
4214
+ "opengeni-gateway/openai/gpt-realtime-mini",
4215
+ "opengeni-gateway/xai/grok-voice-think-fast-2.0",
4216
+ "workspace-gateway/openai/gpt-realtime-2.1",
4217
+ "workspace-gateway/openai/gpt-realtime-mini",
4218
+ "workspace-gateway/xai/grok-voice-think-fast-2.0",
4219
+ ]);
4220
+ export type SessionRealtimeModel = z.infer<typeof SessionRealtimeModel>;
4221
+
4222
+ export const WorkspaceRealtimeModelCatalogItem = z.object({
4223
+ id: SessionRealtimeModel,
4224
+ label: z.string().min(1),
4225
+ provider: z.enum(["OpenGeni", "Connected Codex", "Your Gateway"]),
4226
+ description: z.string().min(1),
4227
+ available: z.boolean(),
4228
+ unavailableReason: z.string().nullable(),
4229
+ recommended: z.boolean(),
4230
+ });
4231
+ export type WorkspaceRealtimeModelCatalogItem = z.infer<typeof WorkspaceRealtimeModelCatalogItem>;
4232
+
4233
+ export const WorkspaceRealtimeModelCatalogResponse = z.object({
4234
+ models: z.array(WorkspaceRealtimeModelCatalogItem),
4235
+ });
4236
+ export type WorkspaceRealtimeModelCatalogResponse = z.infer<
4237
+ typeof WorkspaceRealtimeModelCatalogResponse
4238
+ >;
4239
+
4240
+ export const SessionRealtimeState = z.enum(["active", "ended"]);
4241
+ export type SessionRealtimeState = z.infer<typeof SessionRealtimeState>;
4242
+
4243
+ export const SessionRealtimeEndReason = z.enum(["user_stop", "browser_unload", "lease_expired"]);
4244
+ export type SessionRealtimeEndReason = z.infer<typeof SessionRealtimeEndReason>;
4245
+
4246
+ export const SessionRealtimeMode = z.object({
4247
+ id: z.string().uuid(),
4248
+ sessionId: z.string().uuid(),
4249
+ operationId: z.string().uuid(),
4250
+ browserInstanceId: z.string().min(1).max(256),
4251
+ model: SessionRealtimeModel,
4252
+ state: SessionRealtimeState,
4253
+ version: z.number().int().positive(),
4254
+ connectionEpoch: z.number().int().positive(),
4255
+ leaseExpiresAt: z.string().datetime(),
4256
+ lastHeartbeatAt: z.string().datetime(),
4257
+ startedAt: z.string().datetime(),
4258
+ endedAt: z.string().datetime().nullable(),
4259
+ endReason: SessionRealtimeEndReason.nullable(),
4260
+ });
4261
+ export type SessionRealtimeMode = z.infer<typeof SessionRealtimeMode>;
4262
+
4263
+ export const BeginSessionRealtimeRequest = SessionRealtimeOwnerProof.extend({
4264
+ operationId: z.string().uuid(),
4265
+ model: SessionRealtimeModel,
4266
+ });
4267
+ export type BeginSessionRealtimeRequest = z.infer<typeof BeginSessionRealtimeRequest>;
4268
+
4269
+ export const RenewSessionRealtimeRequest = SessionRealtimeOwnerProof.extend({
4270
+ expectedVersion: z.number().int().positive(),
4271
+ });
4272
+ export type RenewSessionRealtimeRequest = z.infer<typeof RenewSessionRealtimeRequest>;
4273
+
4274
+ export const EndSessionRealtimeRequest = RenewSessionRealtimeRequest.extend({
4275
+ reason: z.enum(["user_stop", "browser_unload"]),
4276
+ });
4277
+ export type EndSessionRealtimeRequest = z.infer<typeof EndSessionRealtimeRequest>;
4278
+
4279
+ export const SessionRealtimeMutationResponse = z.object({
4280
+ mode: SessionRealtimeMode,
4281
+ replay: z.boolean(),
4282
+ });
4283
+ export type SessionRealtimeMutationResponse = z.infer<typeof SessionRealtimeMutationResponse>;
4284
+
3901
4285
  export const SessionAuthorizationOperation = z.enum([
3902
4286
  "session.read",
3903
4287
  "session.events.read",
@@ -3924,6 +4308,8 @@ export const SessionAuthorizationOperation = z.enum([
3924
4308
  "session.toolspace.call",
3925
4309
  "session.pin.write",
3926
4310
  "session.codex_account.write",
4311
+ "session.realtime.start",
4312
+ "session.realtime.control",
3927
4313
  "session.context.write",
3928
4314
  "session.approval.write",
3929
4315
  "session.human_input.read",
@@ -4246,7 +4632,7 @@ const WorkspaceControlReason = z
4246
4632
  );
4247
4633
 
4248
4634
  export const SessionControlRequest = z.object({
4249
- action: z.enum(["pause", "resume"]),
4635
+ action: z.enum(["pause", "resume", "cancel"]),
4250
4636
  reason: WorkspaceControlReason.optional(),
4251
4637
  clientEventId: SessionOperationKey,
4252
4638
  expectedControlEtag: z.string().min(1).optional(),
@@ -4494,7 +4880,7 @@ export const SessionSystemUpdatePayload = z.discriminatedUnion("type", [
4494
4880
  .object({
4495
4881
  type: z.literal("child_terminal_result"),
4496
4882
  childSessionId: z.string().uuid(),
4497
- status: z.enum(["idle", "failed"]),
4883
+ status: z.enum(["idle", "failed", "cancelled"]),
4498
4884
  })
4499
4885
  .passthrough(),
4500
4886
  ]);
@@ -5786,6 +6172,10 @@ export const Session = z.object({
5786
6172
  // metadata (exposed like title/goal), never a secret and never a timeline event.
5787
6173
  // null when the session carried none.
5788
6174
  instructions: z.string().nullable(),
6175
+ // Immutable prompt-policy role binding. This is separate from human
6176
+ // workspace membership roles and from memory selectors. Null keeps the
6177
+ // compatibility fallback to a normalized metadata.role value.
6178
+ policyRole: WorkspaceInstructionPolicyRoleKeyInput.nullable().default(null),
5789
6179
  resources: z.array(ResourceRef),
5790
6180
  skills: SessionSkills.default([]),
5791
6181
  tools: z.array(ToolRef),
@@ -5959,6 +6349,8 @@ export const SessionEventType = z.enum([
5959
6349
  // crossing NATS, SSE, REST, or browser boundaries.
5960
6350
  "session.event.envelope_omitted",
5961
6351
  "session.status.changed",
6352
+ "session.realtime.started",
6353
+ "session.realtime.ended",
5962
6354
  "session.requiresAction",
5963
6355
  "session.humanInput.requested",
5964
6356
  "session.context.compaction.requested",
@@ -7354,7 +7746,12 @@ function compactFailure(
7354
7746
  const code = compactResultStringField(payload.code);
7355
7747
  const recovery = compactResultStringField(payload.recovery);
7356
7748
  const retryable = typeof payload.retryable === "boolean" ? payload.retryable : null;
7357
- const value = { error: error.value, code: code.value, retryable, recovery: recovery.value };
7749
+ const value = {
7750
+ error: error.value,
7751
+ code: code.value,
7752
+ retryable,
7753
+ recovery: recovery.value,
7754
+ };
7358
7755
  const originalBytes = [error, code, recovery]
7359
7756
  .map((field) => field.originalBytes ?? 0)
7360
7757
  .reduce((sum, bytes) => sum + bytes, 0);
@@ -8045,6 +8442,8 @@ export const SessionControlResponse = z.object({
8045
8442
  effectiveControl: EffectiveSessionControl,
8046
8443
  interruptionCount: z.number().int().nonnegative(),
8047
8444
  wakeCount: z.number().int().nonnegative(),
8445
+ cancelledSessionCount: z.number().int().nonnegative(),
8446
+ cancelledTurnCount: z.number().int().nonnegative(),
8048
8447
  });
8049
8448
  export type SessionControlResponse = z.infer<typeof SessionControlResponse>;
8050
8449
 
@@ -8056,7 +8455,11 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8056
8455
  * identity or authorization from the UUID.
8057
8456
  */
8058
8457
  requestedSessionId: z.string().uuid().optional(),
8059
- initialMessage: z.string().min(1),
8458
+ initialMessage: z.string().min(1).optional(),
8459
+ // Creates the durable session shell without fabricating a user message or
8460
+ // starting an underlying agent turn. Realtime can then become the first
8461
+ // interaction and use the ordinary Send/Steer path when it delegates.
8462
+ startMode: z.literal("realtime").optional(),
8060
8463
  // System-level host context for the initial turn only. Unlike `instructions`,
8061
8464
  // this does not persist into later turns and is never emitted as a user event.
8062
8465
  turnInstructions: z.string().trim().min(1).max(32768).optional(),
@@ -8069,6 +8472,11 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8069
8472
  // matches the codebase's largest free-form string convention (workspace
8070
8473
  // variable set variable values). Absent ⇒ byte-identical to today.
8071
8474
  instructions: z.string().trim().min(1).max(32768).optional(),
8475
+ // Immutable prompt-policy role binding for matching one activated role
8476
+ // policy. This never derives from or grants a human workspace membership
8477
+ // role. Existing callers may continue to use normalized metadata.role as a
8478
+ // compatibility fallback by omitting this field.
8479
+ policyRole: WorkspaceInstructionPolicyRoleKeyInput.optional(),
8072
8480
  // For an agent-created child, omission inherits the trusted immediate
8073
8481
  // parent's repository/file context. An explicit array, including [], is
8074
8482
  // authoritative. Top-level omission remains []. Presence is resolved from
@@ -8102,10 +8510,10 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8102
8510
  variableSetId: z.string().uuid().optional(),
8103
8511
  environmentId: z.string().uuid().optional(),
8104
8512
  // 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(),
8513
+ // FROZEN onto the session at create. Omitted ⇒ inherit the workspace default;
8514
+ // null explicitly create a rig-less session; UUID ⇒ bind that exact rig.
8515
+ // An id that does not name a rig in the workspace is a 422.
8516
+ rigId: z.string().uuid().nullable().optional(),
8109
8517
  goal: GoalSpec.optional(),
8110
8518
  clientEventId: SessionOperationKey.optional(),
8111
8519
  // Workspace-scoped CREATE idempotency key: collapses concurrent/retried
@@ -8162,6 +8570,21 @@ export const CreateSessionRequest = withVariableSetIdAlias({
8162
8570
  sandbox: z
8163
8571
  .union([z.literal("shared"), z.literal("new"), z.object({ groupId: z.string().uuid() })])
8164
8572
  .optional(),
8573
+ }).superRefine((value, context) => {
8574
+ if (value.startMode !== "realtime" && value.initialMessage === undefined) {
8575
+ context.addIssue({
8576
+ code: z.ZodIssueCode.custom,
8577
+ path: ["initialMessage"],
8578
+ message: "initialMessage is required unless startMode is realtime",
8579
+ });
8580
+ }
8581
+ if (value.startMode === "realtime" && value.initialMessage !== undefined) {
8582
+ context.addIssue({
8583
+ code: z.ZodIssueCode.custom,
8584
+ path: ["initialMessage"],
8585
+ message: "initialMessage must be omitted when startMode is realtime",
8586
+ });
8587
+ }
8165
8588
  });
8166
8589
  export type CreateSessionRequest = z.infer<typeof CreateSessionRequest>;
8167
8590
 
@@ -8189,10 +8612,10 @@ export const HumanInputQuestion = z
8189
8612
  options: z.array(HumanInputOption).max(20).default([]),
8190
8613
  required: z.boolean().default(true),
8191
8614
  allowOther: z.boolean().default(false),
8615
+ // Selection bounds only — agents invent useless text char mins/maxes.
8616
+ // Answer strings stay platform-capped on HumanInputAnswer (~8192).
8192
8617
  validation: z
8193
8618
  .object({
8194
- minLength: z.number().int().nonnegative().max(8192).nullable().optional(),
8195
- maxLength: z.number().int().positive().max(8192).nullable().optional(),
8196
8619
  minSelections: z.number().int().nonnegative().max(20).nullable().optional(),
8197
8620
  maxSelections: z.number().int().positive().max(20).nullable().optional(),
8198
8621
  })
@@ -8231,17 +8654,6 @@ export const HumanInputQuestion = z
8231
8654
  });
8232
8655
  }
8233
8656
  const validation = question.validation;
8234
- if (
8235
- validation?.minLength != null &&
8236
- validation?.maxLength != null &&
8237
- validation.minLength > validation.maxLength
8238
- ) {
8239
- ctx.addIssue({
8240
- code: "custom",
8241
- path: ["validation"],
8242
- message: "minLength exceeds maxLength",
8243
- });
8244
- }
8245
8657
  if (
8246
8658
  validation?.minSelections != null &&
8247
8659
  validation?.maxSelections != null &&
@@ -9090,9 +9502,8 @@ function defineModelContractSchema<Schema>(factory: () => Schema): Schema {
9090
9502
  return factory();
9091
9503
  }
9092
9504
 
9093
- export const ModelCapabilitySupportV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9094
- z.enum(["supported", "unsupported", "unknown"]),
9095
- );
9505
+ export const ModelCapabilitySupportV1 =
9506
+ /* @__PURE__ */ defineModelContractSchema(() => z.enum(["supported", "unsupported", "unknown"]));
9096
9507
  export type ModelCapabilitySupportV1 = z.infer<typeof ModelCapabilitySupportV1>;
9097
9508
 
9098
9509
  export const ModelCapabilityStateV1 = /* @__PURE__ */ defineModelContractSchema(() =>
@@ -9118,6 +9529,7 @@ export const ModelCapabilitiesV1 = /* @__PURE__ */ defineModelContractSchema(()
9118
9529
  codeExecution: ModelCapabilityStateV1,
9119
9530
  }),
9120
9531
  inputModalities: z.array(z.enum(["text", "image", "audio"])),
9532
+ inputFileMediaTypes: z.array(z.string()).optional(),
9121
9533
  outputModalities: z.array(z.enum(["text", "image", "audio"])),
9122
9534
  transports: z.object({
9123
9535
  sse: ModelCapabilityStateV1,
@@ -9139,37 +9551,54 @@ export const ModelCapabilitiesV1 = /* @__PURE__ */ defineModelContractSchema(()
9139
9551
  );
9140
9552
  export type ModelCapabilitiesV1 = z.infer<typeof ModelCapabilitiesV1>;
9141
9553
 
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
- );
9554
+ export const ModelCredentialSourceV1 =
9555
+ /* @__PURE__ */ defineModelContractSchema(() =>
9556
+ z.union([
9557
+ z
9558
+ .object({
9559
+ kind: z.literal("deployment"),
9560
+ mechanism: z.enum(["api_key", "azure_ad_bearer"]),
9561
+ })
9562
+ .strict(),
9563
+ z
9564
+ .object({
9565
+ kind: z.literal("connected_subscription"),
9566
+ provider: z.literal("codex"),
9567
+ })
9568
+ .strict(),
9569
+ z
9570
+ .object({
9571
+ kind: z.literal("workspace_connection"),
9572
+ mechanism: z.literal("api_key"),
9573
+ })
9574
+ .strict(),
9575
+ ]),
9576
+ );
9151
9577
  export type ModelCredentialSourceV1 = z.infer<typeof ModelCredentialSourceV1>;
9152
9578
 
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
- );
9579
+ export const ModelBillingAttributionV1 =
9580
+ /* @__PURE__ */ defineModelContractSchema(() =>
9581
+ z
9582
+ .object({
9583
+ upstreamPayer: z.enum(["deployment", "workspace", "connected_subscription"]),
9584
+ metering: z.enum(["opengeni_credits", "external"]),
9585
+ })
9586
+ .strict(),
9587
+ );
9161
9588
  export type ModelBillingAttributionV1 = z.infer<typeof ModelBillingAttributionV1>;
9162
9589
 
9163
9590
  export const TURN_EXECUTION_POLICY_METADATA_KEY = "turnExecutionPolicyV1" as const;
9164
9591
 
9165
- export const TurnExecutionModelSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9166
- z.enum(["explicit", "session", "deployment", "continuation"]),
9167
- );
9592
+ export const TurnExecutionModelSourceV1 =
9593
+ /* @__PURE__ */ defineModelContractSchema(() =>
9594
+ z.enum(["explicit", "session", "deployment", "continuation"]),
9595
+ );
9168
9596
  export type TurnExecutionModelSourceV1 = z.infer<typeof TurnExecutionModelSourceV1>;
9169
9597
 
9170
- export const TurnExecutionReasoningSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
9171
- z.enum(["explicit", "session", "deployment", "continuation"]),
9172
- );
9598
+ export const TurnExecutionReasoningSourceV1 =
9599
+ /* @__PURE__ */ defineModelContractSchema(() =>
9600
+ z.enum(["explicit", "session", "deployment", "continuation"]),
9601
+ );
9173
9602
  export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoningSourceV1>;
9174
9603
 
9175
9604
  export const TurnExecutionLatencyModeSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
@@ -9374,59 +9803,60 @@ export const ClientModel = /* @__PURE__ */ defineModelContractSchema(() =>
9374
9803
  );
9375
9804
  export type ClientModel = z.infer<typeof ClientModel>;
9376
9805
 
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
- );
9806
+ export const ModelCredentialReadinessV1 =
9807
+ /* @__PURE__ */ defineModelContractSchema(() =>
9808
+ z
9809
+ .object({
9810
+ status: z.enum(["ready", "not_ready", "error"]),
9811
+ reason: z
9812
+ .enum([
9813
+ "missing_credential",
9814
+ "needs_reauth",
9815
+ "prerequisites_missing",
9816
+ "resolver_error",
9817
+ "observation_stale",
9818
+ ])
9819
+ .nullable(),
9820
+ basis: z.enum(["configuration", "connection", "resolver"]),
9821
+ checkedAt: z.string().datetime().nullable(),
9822
+ })
9823
+ .strict()
9824
+ .superRefine((readiness, context) => {
9825
+ if ((readiness.status === "ready") !== (readiness.reason === null)) {
9826
+ context.addIssue({
9827
+ code: "custom",
9828
+ path: ["reason"],
9829
+ message: "ready credential state requires no reason; non-ready state requires a reason",
9830
+ });
9831
+ }
9832
+ if ((readiness.status === "error") !== (readiness.reason === "resolver_error")) {
9833
+ context.addIssue({
9834
+ code: "custom",
9835
+ path: ["reason"],
9836
+ message:
9837
+ "credential errors require resolver_error and resolver_error requires error status",
9838
+ });
9839
+ }
9840
+ if (
9841
+ readiness.basis === "resolver" &&
9842
+ readiness.status === "ready" &&
9843
+ readiness.checkedAt === null
9844
+ ) {
9845
+ context.addIssue({
9846
+ code: "custom",
9847
+ path: ["checkedAt"],
9848
+ message: "resolver readiness requires an observation timestamp",
9849
+ });
9850
+ }
9851
+ if (readiness.reason === "observation_stale" && readiness.checkedAt === null) {
9852
+ context.addIssue({
9853
+ code: "custom",
9854
+ path: ["checkedAt"],
9855
+ message: "a stale observation requires its observation timestamp",
9856
+ });
9857
+ }
9858
+ }),
9859
+ );
9430
9860
  export type ModelCredentialReadinessV1 = z.infer<typeof ModelCredentialReadinessV1>;
9431
9861
 
9432
9862
  export const ModelAvailabilityV1 = /* @__PURE__ */ defineModelContractSchema(() =>
@@ -9449,19 +9879,21 @@ export const ModelAvailabilityV1 = /* @__PURE__ */ defineModelContractSchema(()
9449
9879
  );
9450
9880
  export type ModelAvailabilityV1 = z.infer<typeof ModelAvailabilityV1>;
9451
9881
 
9452
- export const WorkspaceModelCatalogModel = /* @__PURE__ */ defineModelContractSchema(() =>
9453
- ClientModel.extend({
9454
- credentialReadiness: ModelCredentialReadinessV1,
9455
- availability: ModelAvailabilityV1,
9456
- }),
9457
- );
9882
+ export const WorkspaceModelCatalogModel =
9883
+ /* @__PURE__ */ defineModelContractSchema(() =>
9884
+ ClientModel.extend({
9885
+ credentialReadiness: ModelCredentialReadinessV1,
9886
+ availability: ModelAvailabilityV1,
9887
+ }),
9888
+ );
9458
9889
  export type WorkspaceModelCatalogModel = z.infer<typeof WorkspaceModelCatalogModel>;
9459
9890
 
9460
- export const WorkspaceModelCatalogResponse = /* @__PURE__ */ defineModelContractSchema(() =>
9461
- z.object({
9462
- models: z.array(WorkspaceModelCatalogModel),
9463
- }),
9464
- );
9891
+ export const WorkspaceModelCatalogResponse =
9892
+ /* @__PURE__ */ defineModelContractSchema(() =>
9893
+ z.object({
9894
+ models: z.array(WorkspaceModelCatalogModel),
9895
+ }),
9896
+ );
9465
9897
  export type WorkspaceModelCatalogResponse = z.infer<typeof WorkspaceModelCatalogResponse>;
9466
9898
 
9467
9899
  /**