@opengeni/contracts 0.22.0 → 0.26.1

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
@@ -6,6 +6,8 @@ import {
6
6
  type SessionEventBoundarySurface,
7
7
  } from "./event-preview";
8
8
 
9
+ export * from "./slack-bot-scopes";
10
+
9
11
  export {
10
12
  SESSION_EVENT_PAYLOAD_MAX_BYTES,
11
13
  approximateSessionEventTokens,
@@ -46,6 +48,25 @@ export {
46
48
  type RetainedOutputResolvedRange,
47
49
  } from "./retained-output";
48
50
 
51
+ export {
52
+ NATIVE_SNAPSHOT_PREFIXES,
53
+ WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION,
54
+ backendForNativeSnapshotProvider,
55
+ decodeNativeSnapshotRef,
56
+ parseWorkspaceArchiveDescriptor,
57
+ type NativeSnapshotDescriptor,
58
+ type NativeSnapshotProvider,
59
+ type NativeSnapshotRef,
60
+ type TarWorkspaceArchiveDescriptor,
61
+ type WorkspaceArchiveDescriptor,
62
+ type WorkspaceTreeFingerprint,
63
+ } from "./sandbox-snapshots";
64
+
65
+ export {
66
+ canonicalModalCheckpointProviderBinding,
67
+ type ModalCheckpointProviderBinding,
68
+ } from "./checkpoint-provider-bindings";
69
+
49
70
  export const SessionStatus = z.enum([
50
71
  "queued",
51
72
  "running",
@@ -458,6 +479,10 @@ export const CAPABILITY_DESCRIPTORS: Record<SandboxBackend, CapabilityDescriptor
458
479
  };
459
480
 
460
481
  export const ReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh"]);
482
+
483
+ /** Provider service-tier / latency mode selected for a turn or session default. */
484
+ export const LatencyMode = z.enum(["standard", "priority", "fast"]);
485
+ export type LatencyMode = z.infer<typeof LatencyMode>;
461
486
  export type ReasoningEffort = z.infer<typeof ReasoningEffort>;
462
487
 
463
488
  export const ErrorCode = z.enum([
@@ -467,9 +492,11 @@ export const ErrorCode = z.enum([
467
492
  "validation_failed",
468
493
  "conflict",
469
494
  "idempotency_conflict",
495
+ "payment_required",
470
496
  "limit_exceeded",
471
497
  "nested_agent_depth_exceeded",
472
498
  "nested_agent_depth_override_forbidden",
499
+ "codex_compaction_v2_provider_locked",
473
500
  "provider_verification_failed",
474
501
  "upstream_unavailable",
475
502
  "internal_error",
@@ -643,6 +670,8 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
643
670
  "memory_search",
644
671
  "memory_save",
645
672
  "memory_correct",
673
+ "preference_registry_summary",
674
+ "preference_registry_get",
646
675
  "sandboxes_list",
647
676
  "sandbox_attach",
648
677
  "sandbox_swap",
@@ -683,23 +712,24 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
683
712
  "scheduled_task_runs_list",
684
713
  "slack_bot_list_channels",
685
714
  "slack_bot_channel_history",
715
+ "slack_bot_thread_replies",
686
716
  "slack_bot_list_users",
717
+ "slack_bot_list_files",
718
+ "slack_bot_file_info",
719
+ "slack_bot_file_content",
687
720
  "slack_bot_post_message",
721
+ "slack_bot_delete_message",
688
722
  ] as const;
689
723
  export const FirstPartyMcpToolName = z.enum(FIRST_PARTY_MCP_TOOL_NAMES);
690
724
  export type FirstPartyMcpToolName = z.infer<typeof FirstPartyMcpToolName>;
691
725
 
692
726
  /**
693
- * Ordinary sessions get only the small self-management surface. Authorization
694
- * permissions remain an independent, additional boundary.
727
+ * Every catalogued OpenGeni tool is selected by default. Registration-time
728
+ * authorization remains the independent access boundary; an explicit session
729
+ * policy may narrow this model-visible set.
695
730
  */
696
- export const DEFAULT_FIRST_PARTY_MCP_TOOLS = [
697
- "set_session_title",
698
- "goal_set",
699
- "goal_update",
700
- "goal_complete",
701
- "goal_pause",
702
- ] as const satisfies readonly FirstPartyMcpToolName[];
731
+ export const DEFAULT_FIRST_PARTY_MCP_TOOLS =
732
+ FIRST_PARTY_MCP_TOOL_NAMES satisfies readonly FirstPartyMcpToolName[];
703
733
 
704
734
  export function prefixedMcpToolName(registryId: string, toolName: string): string {
705
735
  return `${registryId}__${toolName}`;
@@ -804,10 +834,17 @@ export const TranscriptionErrorCode = z.enum([
804
834
  "policy_blocked",
805
835
  "timeout",
806
836
  "cancelled",
837
+ "unavailable",
838
+ "too_large",
839
+ "invalid_audio",
807
840
  "unknown",
808
841
  ]);
809
842
  export type TranscriptionErrorCode = z.infer<typeof TranscriptionErrorCode>;
810
843
 
844
+ /** Stable user-safe error codes for the native voice-input transcription path. */
845
+ export const VoiceInputErrorCode = TranscriptionErrorCode;
846
+ export type VoiceInputErrorCode = TranscriptionErrorCode;
847
+
811
848
  export const TranscriptionTimeSpan = z
812
849
  .object({
813
850
  startMilliseconds: z.number().finite().nonnegative(),
@@ -929,6 +966,9 @@ export const TranscriptionEvent = z.discriminatedUnion("type", [
929
966
  export type TranscriptionEvent = z.infer<typeof TranscriptionEvent>;
930
967
 
931
968
  /**
969
+ * @deprecated Host-adapter transcription policy. Kept for one release so existing
970
+ * workspace settings remain readable. New writes use `WorkspaceVoiceInputSettings`.
971
+ *
932
972
  * Workspace-only policy for the distinct speech-to-text capability. It never
933
973
  * authorizes a turn model/provider and contains connection references rather
934
974
  * than secrets. `acceptanceId` changes whenever an admin accepts a new target
@@ -1045,16 +1085,77 @@ export const WorkspaceTranscriptionPolicy = z
1045
1085
  });
1046
1086
  export type WorkspaceTranscriptionPolicy = z.infer<typeof WorkspaceTranscriptionPolicy>;
1047
1087
 
1088
+ /**
1089
+ * Workspace toggle for native browser voice input. Provider/model/credentials
1090
+ * stay server-private; this only records whether the workspace allows the
1091
+ * deployment-configured transcription path.
1092
+ */
1093
+ export const WorkspaceVoiceInputSettings = z
1094
+ .object({
1095
+ enabled: z.boolean(),
1096
+ })
1097
+ .strict();
1098
+ export type WorkspaceVoiceInputSettings = z.infer<typeof WorkspaceVoiceInputSettings>;
1099
+
1100
+ /** Client-safe voice-input capability projection. Never includes provider secrets. */
1101
+ export const ClientVoiceInputConfig = z
1102
+ .object({
1103
+ available: z.boolean(),
1104
+ maxDurationSeconds: z.number().int().positive().max(600),
1105
+ maxSizeBytes: z.number().int().positive(),
1106
+ acceptedMimeTypes: z.array(z.string().trim().min(1).max(128)).min(1).max(32),
1107
+ })
1108
+ .strict();
1109
+ export type ClientVoiceInputConfig = z.infer<typeof ClientVoiceInputConfig>;
1110
+
1111
+ /** Response from POST /v1/workspaces/:workspaceId/transcriptions. */
1112
+ export const TranscribeAudioResponse = z
1113
+ .object({
1114
+ text: z.string().max(1_000_000),
1115
+ languages: z.array(z.string().trim().min(1).max(64)).max(16).default([]),
1116
+ })
1117
+ .strict();
1118
+ export type TranscribeAudioResponse = z.infer<typeof TranscribeAudioResponse>;
1119
+
1120
+ /** Default ceilings for native voice input (hard-stop recording + upload). */
1121
+ export const VOICE_INPUT_MAX_DURATION_SECONDS = 60 as const;
1122
+ export const VOICE_INPUT_MAX_SIZE_BYTES = 25 * 1024 * 1024;
1123
+ export const VOICE_INPUT_ACCEPTED_MIME_TYPES = [
1124
+ "audio/webm",
1125
+ "audio/webm;codecs=opus",
1126
+ "audio/mp4",
1127
+ "audio/ogg",
1128
+ "audio/ogg;codecs=opus",
1129
+ "audio/mpeg",
1130
+ "audio/wav",
1131
+ "audio/x-wav",
1132
+ "audio/mp3",
1133
+ "audio/m4a",
1134
+ ] as const;
1135
+
1136
+ /** Per-session / workspace Codex compaction strategy. */
1137
+ export const CodexCompactionMode = z.enum(["remote_v2", "portable"]);
1138
+ export type CodexCompactionMode = z.infer<typeof CodexCompactionMode>;
1139
+
1048
1140
  // Validates the KNOWN keys of workspaces.settings; passthrough keeps unknown
1049
- // (future) keys rather than stripping them. memoryEnabled and transcription are
1050
- // both default-off capabilities.
1141
+ // (future) keys rather than stripping them. memoryEnabled defaults off;
1142
+ // voiceInput defaults to enabled when the deployment has a provider.
1051
1143
  export const WorkspaceSettingsSchema = z
1052
1144
  .object({
1053
1145
  memoryEnabled: z.boolean().optional(),
1146
+ /** Preferred workspace voice-input toggle. */
1147
+ voiceInput: WorkspaceVoiceInputSettings.optional(),
1148
+ /**
1149
+ * @deprecated Legacy host-adapter policy. Read for compatibility; new writes
1150
+ * should use `voiceInput`.
1151
+ */
1054
1152
  transcription: WorkspaceTranscriptionPolicy.optional(),
1055
1153
  // null clears the workspace override and falls back to the persisted
1056
1154
  // deployment policy. The database boundary validates the same range.
1057
1155
  maxNestedAgentDepth: NestedAgentDepthValue.nullable().optional(),
1156
+ // Default compaction strategy for NEW Codex sessions created in this
1157
+ // workspace. Absent ⇒ remote_v2. Non-Codex sessions always freeze portable.
1158
+ codexCompactionDefault: CodexCompactionMode.optional(),
1058
1159
  })
1059
1160
  .passthrough();
1060
1161
  export type WorkspaceSettings = z.infer<typeof WorkspaceSettingsSchema>;
@@ -1065,14 +1166,40 @@ export function resolveWorkspaceMemoryEnabled(settings: unknown): boolean {
1065
1166
  return parsed.success ? parsed.data.memoryEnabled === true : false;
1066
1167
  }
1067
1168
 
1169
+ /** Default Codex compaction mode for new Codex sessions (remote_v2 when unset). */
1170
+ export function resolveWorkspaceCodexCompactionDefault(settings: unknown): CodexCompactionMode {
1171
+ const parsed = WorkspaceSettingsSchema.safeParse(settings ?? {});
1172
+ if (!parsed.success) return "remote_v2";
1173
+ return parsed.data.codexCompactionDefault ?? "remote_v2";
1174
+ }
1175
+
1176
+ /**
1177
+ * Resolve whether voice input is enabled for a workspace.
1178
+ *
1179
+ * - Prefer `settings.voiceInput.enabled` when present.
1180
+ * - Map legacy `settings.transcription.enabled` when voiceInput is absent.
1181
+ * - Return `null` when neither is set so callers can default to deployment
1182
+ * availability (enabled when a provider is configured).
1183
+ */
1184
+ export function resolveWorkspaceVoiceInputEnabled(settings: unknown): boolean | null {
1185
+ const parsed = WorkspaceSettingsSchema.safeParse(settings ?? {});
1186
+ if (!parsed.success) return null;
1187
+ if (parsed.data.voiceInput) return parsed.data.voiceInput.enabled;
1188
+ if (parsed.data.transcription) return parsed.data.transcription.enabled;
1189
+ return null;
1190
+ }
1191
+
1068
1192
  // PATCH body for workspace settings: a partial top-level patch that merges into
1069
- // the stored bag. Nested transcription policy updates are therefore full
1070
- // replacements; passthrough carries forward-compatible unknown keys.
1193
+ // the stored bag. Nested voiceInput/transcription updates are full replacements;
1194
+ // passthrough carries forward-compatible unknown keys.
1071
1195
  export const UpdateWorkspaceSettingsRequest = z
1072
1196
  .object({
1073
1197
  memoryEnabled: z.boolean().optional(),
1198
+ voiceInput: WorkspaceVoiceInputSettings.optional(),
1199
+ /** @deprecated Prefer `voiceInput`. Kept for one compatibility release. */
1074
1200
  transcription: WorkspaceTranscriptionPolicy.optional(),
1075
1201
  maxNestedAgentDepth: NestedAgentDepthValue.nullable().optional(),
1202
+ codexCompactionDefault: CodexCompactionMode.optional(),
1076
1203
  })
1077
1204
  .passthrough();
1078
1205
  export type UpdateWorkspaceSettingsRequest = z.infer<typeof UpdateWorkspaceSettingsRequest>;
@@ -1164,6 +1291,16 @@ export const ServiceTurnInitiatorContext = TurnInitiatorContext.superRefine((val
1164
1291
  });
1165
1292
  export type ServiceTurnInitiatorContext = z.infer<typeof ServiceTurnInitiatorContext>;
1166
1293
 
1294
+ export const DelegatedAccessPrincipalKind = z.enum(["human_session", "agent_attempt", "service"]);
1295
+ export type DelegatedAccessPrincipalKind = z.infer<typeof DelegatedAccessPrincipalKind>;
1296
+
1297
+ export const AccessPrincipalKind = z.enum([
1298
+ ...DelegatedAccessPrincipalKind.options,
1299
+ "api_key",
1300
+ "configured_key",
1301
+ ]);
1302
+ export type AccessPrincipalKind = z.infer<typeof AccessPrincipalKind>;
1303
+
1167
1304
  export const AccountGrant = z.object({
1168
1305
  accountId: z.string().uuid(),
1169
1306
  subjectId: z.string().min(1),
@@ -1180,6 +1317,9 @@ export const AccessGrant = z.object({
1180
1317
  subjectId: z.string().min(1),
1181
1318
  subjectLabel: z.string().optional(),
1182
1319
  permissions: z.array(Permission),
1320
+ // Trusted principal provenance. Delegated grants copy this from the signed
1321
+ // token claim; managed/local grants derive it from their authenticated path.
1322
+ principalKind: AccessPrincipalKind.optional(),
1183
1323
  metadata: z.record(z.string(), z.unknown()).optional(),
1184
1324
  // Optional trusted causal principal for a command submitted by an embedding
1185
1325
  // host. Authorization still uses subjectId + permissions above.
@@ -1206,6 +1346,10 @@ export const DelegatedAccessTokenPayload = z
1206
1346
  subjectId: z.string().min(1),
1207
1347
  subjectLabel: z.string().optional(),
1208
1348
  permissions: z.array(Permission).min(1),
1349
+ // Required and covered by the token HMAC. Authorization must positively
1350
+ // select a principal kind instead of inferring "human" from absent machine
1351
+ // markers.
1352
+ principalKind: DelegatedAccessPrincipalKind,
1209
1353
  // Trusted embedding hosts can sign a causal service principal separately
1210
1354
  // from the grant subject that authorizes the request. The claim is consumed
1211
1355
  // only when a command creates a new session/turn.
@@ -1230,6 +1374,53 @@ export const DelegatedAccessTokenPayload = z
1230
1374
  exp: z.number().int().positive(),
1231
1375
  })
1232
1376
  .superRefine((payload, ctx) => {
1377
+ const exactAttemptClaims = [
1378
+ payload.sessionId,
1379
+ payload.turnId,
1380
+ payload.attemptId,
1381
+ payload.executionGeneration,
1382
+ ];
1383
+ const exactAttemptClaimCount = exactAttemptClaims.filter((value) => value !== undefined).length;
1384
+ if (
1385
+ payload.principalKind === "human_session" &&
1386
+ (exactAttemptClaimCount !== 0 || payload.serviceInitiator !== undefined)
1387
+ ) {
1388
+ ctx.addIssue({
1389
+ code: z.ZodIssueCode.custom,
1390
+ path: ["principalKind"],
1391
+ message: "human_session principal cannot carry machine authority claims",
1392
+ });
1393
+ }
1394
+ if (
1395
+ payload.principalKind === "agent_attempt" &&
1396
+ (exactAttemptClaimCount !== exactAttemptClaims.length ||
1397
+ payload.serviceInitiator !== undefined)
1398
+ ) {
1399
+ ctx.addIssue({
1400
+ code: z.ZodIssueCode.custom,
1401
+ path: ["principalKind"],
1402
+ message: "agent_attempt principal requires one exact signed attempt authority",
1403
+ });
1404
+ }
1405
+ if (
1406
+ payload.principalKind === "service" &&
1407
+ (payload.turnId !== undefined ||
1408
+ payload.attemptId !== undefined ||
1409
+ payload.executionGeneration !== undefined)
1410
+ ) {
1411
+ ctx.addIssue({
1412
+ code: z.ZodIssueCode.custom,
1413
+ path: ["principalKind"],
1414
+ message: "service principal cannot carry exact agent-attempt authority",
1415
+ });
1416
+ }
1417
+ if (payload.serviceInitiator && payload.principalKind !== "service") {
1418
+ ctx.addIssue({
1419
+ code: z.ZodIssueCode.custom,
1420
+ path: ["principalKind"],
1421
+ message: "serviceInitiator requires a service principal",
1422
+ });
1423
+ }
1233
1424
  if (payload.serviceInitiatorContext && !payload.serviceInitiator) {
1234
1425
  ctx.addIssue({
1235
1426
  code: z.ZodIssueCode.custom,
@@ -1741,6 +1932,169 @@ export const UsageEvent = z.object({
1741
1932
  });
1742
1933
  export type UsageEvent = z.infer<typeof UsageEvent>;
1743
1934
 
1935
+ /** UTC Insights windows. "this month" aligns with billing's UTC month. */
1936
+ export const InsightsRange = z.enum(["today", "week", "month", "ytd"]);
1937
+ export type InsightsRange = z.infer<typeof InsightsRange>;
1938
+
1939
+ export const InsightsBillingPath = z.enum(["opengeni_credits", "external"]);
1940
+ export type InsightsBillingPath = z.infer<typeof InsightsBillingPath>;
1941
+
1942
+ export const InsightsModelUsageRow = z.object({
1943
+ id: z.string().min(1),
1944
+ model: z.string().min(1),
1945
+ provider: z.string().min(1),
1946
+ billing: InsightsBillingPath,
1947
+ calls: z.number().int().nonnegative(),
1948
+ inputTokens: z.number().nonnegative(),
1949
+ outputTokens: z.number().nonnegative(),
1950
+ cachedTokens: z.number().nonnegative(),
1951
+ cacheWriteTokens: z.number().nonnegative(),
1952
+ reasoningTokens: z.number().nonnegative(),
1953
+ /** Priced OpenGeni credit $ for this model×provider (from model_call_facts). */
1954
+ creditUsd: z.number().nonnegative(),
1955
+ });
1956
+ export type InsightsModelUsageRow = z.infer<typeof InsightsModelUsageRow>;
1957
+
1958
+ export const InsightsSeriesPoint = z.object({
1959
+ label: z.string().min(1),
1960
+ /** Day-bucketed sum of usage_events.model.cost (workspace-wide) or filtered facts when provider/model set. */
1961
+ modelCostUsd: z.number().nonnegative(),
1962
+ warmSeconds: z.number().nonnegative(),
1963
+ inputTokens: z.number().nonnegative(),
1964
+ cachedTokens: z.number().nonnegative(),
1965
+ cacheHitPct: z.number().int().min(0).max(100),
1966
+ calls: z.number().int().nonnegative(),
1967
+ });
1968
+ export type InsightsSeriesPoint = z.infer<typeof InsightsSeriesPoint>;
1969
+
1970
+ export const InsightsDepthBucket = z.object({
1971
+ depth: z.number().int().nonnegative(),
1972
+ sessions: z.number().int().nonnegative(),
1973
+ });
1974
+ export type InsightsDepthBucket = z.infer<typeof InsightsDepthBucket>;
1975
+
1976
+ export const InsightsModelFacet = z.object({
1977
+ provider: z.string().min(1),
1978
+ model: z.string().min(1),
1979
+ });
1980
+ export type InsightsModelFacet = z.infer<typeof InsightsModelFacet>;
1981
+
1982
+ export const InsightsSpendDriver = z.object({
1983
+ id: z.string().min(1),
1984
+ groupBy: z.enum(["root_session", "schedule"]),
1985
+ label: z.string().min(1),
1986
+ creditUsd: z.number().nonnegative(),
1987
+ tokens: z.number().nonnegative(),
1988
+ cacheHitPct: z.number().int().min(0).max(100),
1989
+ pctOfCreditUsd: z.number().int().min(0).max(100),
1990
+ deltaUsdVsPrior: z.number(),
1991
+ });
1992
+ export type InsightsSpendDriver = z.infer<typeof InsightsSpendDriver>;
1993
+
1994
+ export const InsightsWarmGroupRow = z.object({
1995
+ id: z.string().min(1),
1996
+ groupId: z.string().uuid(),
1997
+ label: z.string().min(1),
1998
+ /** Live lease backend when known; null when only historical warm ticks exist. */
1999
+ backend: z.string().nullable(),
2000
+ warmSeconds: z.number().nonnegative(),
2001
+ /** Currently attached sessions — not cost share. */
2002
+ sessionsAttached: z.number().int().nonnegative(),
2003
+ });
2004
+ export type InsightsWarmGroupRow = z.infer<typeof InsightsWarmGroupRow>;
2005
+
2006
+ export const InsightsLiveWarmLease = z.object({
2007
+ id: z.string().uuid(),
2008
+ groupId: z.string().uuid(),
2009
+ backend: z.string().min(1),
2010
+ turnHolders: z.number().int().nonnegative(),
2011
+ viewerHolders: z.number().int().nonnegative(),
2012
+ warmForLabel: z.string().min(1),
2013
+ warmSeconds: z.number().nonnegative(),
2014
+ });
2015
+ export type InsightsLiveWarmLease = z.infer<typeof InsightsLiveWarmLease>;
2016
+
2017
+ export const InsightsFloorSession = z.object({
2018
+ id: z.string().uuid(),
2019
+ title: z.string(),
2020
+ state: z.enum(["running", "paused", "failed", "idle", "compacting", "waiting"]),
2021
+ depth: z.number().int().nonnegative(),
2022
+ model: z.string().nullable(),
2023
+ provider: z.string().nullable(),
2024
+ ageLabel: z.string(),
2025
+ cacheHitPct: z.number().int().min(0).max(100).nullable(),
2026
+ route: z.string().nullable(),
2027
+ });
2028
+ export type InsightsFloorSession = z.infer<typeof InsightsFloorSession>;
2029
+
2030
+ export const InsightsScheduleRow = z.object({
2031
+ id: z.string().uuid(),
2032
+ name: z.string(),
2033
+ fires: z.number().int().nonnegative(),
2034
+ /** Null when no facts carry scheduled_task_id for this window. */
2035
+ creditUsd: z.number().nonnegative().nullable(),
2036
+ tokens: z.number().nonnegative().nullable(),
2037
+ cacheHitPct: z.number().int().min(0).max(100).nullable(),
2038
+ billing: InsightsBillingPath.nullable(),
2039
+ });
2040
+ export type InsightsScheduleRow = z.infer<typeof InsightsScheduleRow>;
2041
+
2042
+ export const WorkspaceInsightsSnapshot = z.object({
2043
+ range: InsightsRange,
2044
+ rangeLabel: z.string().min(1),
2045
+ priorLabel: z.string().min(1),
2046
+ seriesLabel: z.string().min(1),
2047
+ cacheSeriesLabel: z.string().min(1),
2048
+ /** All ranges/series are UTC. */
2049
+ timezone: z.literal("UTC"),
2050
+ models: z.array(InsightsModelUsageRow),
2051
+ /** Unfiltered provider×model pairs in the window — drives filter dropdowns. */
2052
+ facets: z.array(InsightsModelFacet),
2053
+ series: z.array(InsightsSeriesPoint),
2054
+ depth: z.array(InsightsDepthBucket),
2055
+ drivers: z.array(InsightsSpendDriver),
2056
+ schedules: z.array(InsightsScheduleRow),
2057
+ warmSeconds: z.number().nonnegative(),
2058
+ priorWarmSeconds: z.number().nonnegative(),
2059
+ warmGroups: z.array(InsightsWarmGroupRow),
2060
+ liveWarm: z.array(InsightsLiveWarmLease),
2061
+ floor: z.array(InsightsFloorSession),
2062
+ selfhostedEnabled: z.boolean(),
2063
+ machinesOnline: z.number().int().nonnegative(),
2064
+ /** Workspace-wide OpenGeni credit $ from usage_events.model.cost (unfiltered). */
2065
+ workspaceCreditUsd: z.number().nonnegative(),
2066
+ priorWorkspaceCreditUsd: z.number().nonnegative(),
2067
+ /** Model-filterable credit $ from facts (equals workspace when unfiltered, ignoring late-reject drift). */
2068
+ creditUsd: z.number().nonnegative(),
2069
+ priorCreditUsd: z.number().nonnegative(),
2070
+ priorInputTokens: z.number().nonnegative(),
2071
+ priorCacheHitPct: z.number().int().min(0).max(100),
2072
+ priorCalls: z.number().int().nonnegative(),
2073
+ /** Lifetime workspace topology (not scoped to the selected Insights range). */
2074
+ goalsActive: z.number().int().nonnegative(),
2075
+ goalsCompleted: z.number().int().nonnegative(),
2076
+ sessionsTouched: z.number().int().nonnegative(),
2077
+ rootSessions: z.number().int().nonnegative(),
2078
+ deepestDepth: z.number().int().nonnegative(),
2079
+ deepestSessionTitle: z.string(),
2080
+ avgDepth: z.number().nonnegative(),
2081
+ warmIdleNow: z.number().int().nonnegative(),
2082
+ /** Billable credits-path tokens this UTC month (usage_events.model.tokens). */
2083
+ billableTokensUsed: z.number().nonnegative(),
2084
+ billableTokenCap: z.number().int().positive().nullable(),
2085
+ /** Agent runs this UTC month (usage_events.agent_run.created). */
2086
+ agentRunsUsed: z.number().nonnegative(),
2087
+ agentRunCap: z.number().int().positive().nullable(),
2088
+ /** True when provider/model filters exclude workspace-wide warm/caps meaning. */
2089
+ modelFilterActive: z.boolean(),
2090
+ });
2091
+ export type WorkspaceInsightsSnapshot = z.infer<typeof WorkspaceInsightsSnapshot>;
2092
+
2093
+ export const WorkspaceInsightsResponse = z.object({
2094
+ snapshot: WorkspaceInsightsSnapshot,
2095
+ });
2096
+ export type WorkspaceInsightsResponse = z.infer<typeof WorkspaceInsightsResponse>;
2097
+
1744
2098
  export const LimitAction = z.enum([
1745
2099
  "agent_run:create",
1746
2100
  "tokens:consume",
@@ -2264,6 +2618,11 @@ export type GitHubInstallationSummary = {
2264
2618
 
2265
2619
  export type GitHubInstallationAuthorityKind = "personal_owner" | "organization_owner";
2266
2620
 
2621
+ export interface GitHubInstallationBindingCandidate {
2622
+ installation: GitHubInstallationSummary;
2623
+ authorityKind: GitHubInstallationAuthorityKind;
2624
+ }
2625
+
2267
2626
  export interface GitHubInstallationBindingProof {
2268
2627
  actorId: number;
2269
2628
  actorLogin: string;
@@ -2301,6 +2660,15 @@ export type GitHubAppApiPort = {
2301
2660
  code: string;
2302
2661
  installationId: number;
2303
2662
  }) => Promise<GitHubInstallationBindingProof>;
2663
+ /**
2664
+ * Exchange one fresh GitHub user-authorization code and return only existing
2665
+ * App installations for which that exact human is the personal owner or an
2666
+ * active organization owner. Visibility and repository permissions alone
2667
+ * must never produce a candidate.
2668
+ */
2669
+ discoverInstallationBindingCandidates?: (input: {
2670
+ code: string;
2671
+ }) => Promise<GitHubInstallationBindingCandidate[]>;
2304
2672
  authorizeUser?: (input: { code: string }) => Promise<GitHubUserInstallationAccess[]>;
2305
2673
  verifyInstallationAccessForUser?: (input: {
2306
2674
  code: string;
@@ -2886,11 +3254,14 @@ export const ToolRef = z.object({
2886
3254
  kind: z.literal("mcp"),
2887
3255
  id: z.string().min(1),
2888
3256
  // Non-fatal-on-connect marker for MCP server refs that can degrade
2889
- // gracefully. Absent/false is STRICT: the id must be configured and an
2890
- // unavailable server fails the turn. `optional:true` is preserved for known
2891
- // servers and makes runtime connect/list failures skip that server; if the
2892
- // deployment does not configure the id, validation drops the ref. The server
2893
- // also sets this for auto-attached workspace-default capability MCPs.
3257
+ // gracefully. On new input, absent/false is STRICT: the id must be configured
3258
+ // and an unavailable registered server fails the turn. Persisted refs are
3259
+ // intersected with the current registry at each turn boundary, so a server
3260
+ // disconnected after admission is retained in policy/audit truth but skipped
3261
+ // until it is registered again. `optional:true` additionally makes runtime
3262
+ // connect/list failures skip a known server; if the deployment does not
3263
+ // configure the id, validation drops the ref. Auto-attached workspace-default
3264
+ // capability MCPs also use this marker.
2894
3265
  optional: z.boolean().optional(),
2895
3266
  });
2896
3267
  export type ToolRef = z.infer<typeof ToolRef>;
@@ -2899,12 +3270,9 @@ const registryId = /^[A-Za-z0-9_-]+$/;
2899
3270
  export const SessionMcpServerId = z.string().min(1).regex(registryId);
2900
3271
  export type SessionMcpServerId = z.infer<typeof SessionMcpServerId>;
2901
3272
 
2902
- // How a session's persisted `tools` snapshot was selected. `legacy` is
2903
- // reserved for rows written before this descriptor existed; those rows must
2904
- // keep their materialized historical allow-list rather than being guessed to
2905
- // mean either omitted or explicitly empty.
3273
+ // How a session's persisted tool selection was chosen.
2906
3274
  export const SessionToolPolicy = z.object({
2907
- mode: z.enum(["workspace_default", "explicit", "inherited", "legacy"]),
3275
+ mode: z.enum(["workspace_default", "explicit", "inherited"]),
2908
3276
  inheritedFromSessionId: z.string().uuid().nullable(),
2909
3277
  });
2910
3278
  export type SessionToolPolicy = z.infer<typeof SessionToolPolicy>;
@@ -2926,7 +3294,7 @@ const SessionEffectiveToolPolicyIds = z
2926
3294
  // counts remain exact and idsTruncated makes that explicit to clients.
2927
3295
  export const SessionEffectiveToolPolicy = z
2928
3296
  .object({
2929
- mode: z.enum(["workspace_default", "explicit", "inherited", "legacy"]),
3297
+ mode: z.enum(["workspace_default", "explicit", "inherited"]),
2930
3298
  inheritedFromSessionId: z.string().uuid().nullable(),
2931
3299
  selectedIds: SessionEffectiveToolPolicyIds,
2932
3300
  effectiveIds: SessionEffectiveToolPolicyIds,
@@ -3154,6 +3522,14 @@ export function reasoningEffortForMetadata(
3154
3522
  : fallback;
3155
3523
  }
3156
3524
 
3525
+ export function latencyModeForMetadata(
3526
+ metadata: Record<string, unknown>,
3527
+ fallback: LatencyMode = "standard",
3528
+ ): LatencyMode {
3529
+ const value = metadata.latencyMode;
3530
+ return value === "standard" || value === "priority" || value === "fast" ? value : fallback;
3531
+ }
3532
+
3157
3533
  export function stableJson(value: unknown): string {
3158
3534
  return JSON.stringify(sortJson(value));
3159
3535
  }
@@ -3304,10 +3680,9 @@ export const UpdateSessionRequest = z.object({
3304
3680
  export type UpdateSessionRequest = z.infer<typeof UpdateSessionRequest>;
3305
3681
 
3306
3682
  /**
3307
- * Replace an existing session's durable tool policy, or explicitly opt back in
3308
- * to the current workspace defaults. The mode-less explicit shape is retained
3309
- * for compatibility with clients released before workspace-default adoption
3310
- * was supported.
3683
+ * Replace the complete durable session tool policy, or explicitly opt back in
3684
+ * to current workspace defaults. MCP servers and individual OpenGeni tools
3685
+ * advance atomically under one policy version.
3311
3686
  */
3312
3687
  export const UpdateSessionToolPolicyRequest = z.union([
3313
3688
  z
@@ -3318,8 +3693,9 @@ export const UpdateSessionToolPolicyRequest = z.union([
3318
3693
  .strict(),
3319
3694
  z
3320
3695
  .object({
3321
- mode: z.literal("explicit").optional(),
3696
+ mode: z.literal("explicit"),
3322
3697
  tools: z.array(ToolRef).max(64),
3698
+ firstPartyMcpTools: z.array(FirstPartyMcpToolName),
3323
3699
  expectedVersion: z.number().int().positive(),
3324
3700
  })
3325
3701
  .strict(),
@@ -3588,6 +3964,7 @@ export const SessionTurn = z.object({
3588
3964
  toolsProvided: z.boolean().optional(),
3589
3965
  model: z.string().min(1),
3590
3966
  reasoningEffort: ReasoningEffort,
3967
+ latencyMode: LatencyMode.default("standard"),
3591
3968
  sandboxBackend: SandboxBackend,
3592
3969
  // Per-turn OS override. NULL = inherit the session's sandboxOs.
3593
3970
  sandboxOs: SandboxOs.nullable(),
@@ -3674,12 +4051,9 @@ export const ComposerDraft = z.object({
3674
4051
  revision: z.number().int().nonnegative(),
3675
4052
  text: z.string(),
3676
4053
  resources: z.array(ResourceRef),
3677
- tools: z.array(ToolRef),
3678
- // False means the draft inherits the session policy. True preserves an
3679
- // explicit array, including [], across autosave/reload and queue checkout.
3680
- toolsProvided: z.boolean().default(false),
3681
4054
  model: z.string().min(1),
3682
4055
  reasoningEffort: ReasoningEffort,
4056
+ latencyMode: LatencyMode.default("standard"),
3683
4057
  sourceTurnId: z.string().uuid().nullable(),
3684
4058
  sourceTurnVersion: z.number().int().positive().nullable(),
3685
4059
  updatedAt: z.string().nullable(),
@@ -3718,10 +4092,9 @@ export type DeleteSessionQueueItemRequest = z.infer<typeof DeleteSessionQueueIte
3718
4092
  export const SaveComposerDraftRequest = ComposerDraft.pick({
3719
4093
  text: true,
3720
4094
  resources: true,
3721
- tools: true,
3722
- toolsProvided: true,
3723
4095
  model: true,
3724
4096
  reasoningEffort: true,
4097
+ latencyMode: true,
3725
4098
  }).extend({ expectedRevision: z.number().int().nonnegative() });
3726
4099
  export type SaveComposerDraftRequest = z.infer<typeof SaveComposerDraftRequest>;
3727
4100
 
@@ -3738,6 +4111,7 @@ export const NewSessionDraftOptions = z.object({
3738
4111
  rigId: z.string().uuid().optional(),
3739
4112
  goal: GoalSpec.optional(),
3740
4113
  firstPartyMcpPermissions: z.array(Permission).optional(),
4114
+ firstPartyMcpTools: z.array(FirstPartyMcpToolName).optional(),
3741
4115
  });
3742
4116
  export type NewSessionDraftOptions = z.infer<typeof NewSessionDraftOptions>;
3743
4117
 
@@ -3751,6 +4125,7 @@ export const NewSessionDraft = z.object({
3751
4125
  toolsProvided: z.boolean().default(false),
3752
4126
  model: z.string().min(1),
3753
4127
  reasoningEffort: ReasoningEffort,
4128
+ latencyMode: LatencyMode.default("standard"),
3754
4129
  options: NewSessionDraftOptions,
3755
4130
  updatedAt: z.string().nullable(),
3756
4131
  });
@@ -3763,6 +4138,7 @@ export const SaveNewSessionDraftRequest = NewSessionDraft.pick({
3763
4138
  toolsProvided: true,
3764
4139
  model: true,
3765
4140
  reasoningEffort: true,
4141
+ latencyMode: true,
3766
4142
  options: true,
3767
4143
  }).extend({ expectedRevision: z.number().int().nonnegative() });
3768
4144
  export type SaveNewSessionDraftRequest = z.infer<typeof SaveNewSessionDraftRequest>;
@@ -4851,20 +5227,11 @@ export type ConnectionKind = z.infer<typeof ConnectionKind>;
4851
5227
  export const ConnectionStatus = z.enum(["active", "needs_reauth", "revoked", "error"]);
4852
5228
  export type ConnectionStatus = z.infer<typeof ConnectionStatus>;
4853
5229
 
5230
+ export const OPENGENI_PERSONAL_SLACK_MCP_URL = "https://mcp.slack.com/mcp" as const;
5231
+
4854
5232
  export const OPENGENI_SLACK_BOT_CREDENTIAL_ROLE = "opengeni_slack_bot" as const;
4855
5233
  export const OPENGENI_SLACK_BOT_CREDENTIAL_LABEL = "OpenGeni Slack bot" as const;
4856
5234
  export const OPENGENI_SLACK_BOT_SESSION_METADATA_KEY = "opengeniSlackBotConnectionId" as const;
4857
- export const OPENGENI_SLACK_BOT_REQUIRED_SCOPES = [
4858
- "chat:write",
4859
- "im:write",
4860
- "channels:read",
4861
- "channels:history",
4862
- "groups:read",
4863
- "groups:history",
4864
- "users:read",
4865
- ] as const;
4866
- export const OPENGENI_SLACK_BOT_FORBIDDEN_SCOPES = ["channels:join", "chat:write.public"] as const;
4867
-
4868
5235
  export const OpenGeniSlackBotConnectionMetadata = z
4869
5236
  .object({
4870
5237
  credentialRole: z.literal(OPENGENI_SLACK_BOT_CREDENTIAL_ROLE),
@@ -5204,13 +5571,9 @@ export const Session = z.object({
5204
5571
  resources: z.array(ResourceRef),
5205
5572
  skills: SessionSkills.default([]),
5206
5573
  tools: z.array(ToolRef),
5207
- // Origin of the persisted tool allow-list. Optional for rolling client
5208
- // compatibility; current servers emit it and legacy rows map to `legacy`.
5209
- toolPolicy: SessionToolPolicy.optional(),
5210
- // Optimistic-concurrency fence for durable policy mutations. Optional for
5211
- // older clients/fixtures; current servers always emit the authoritative
5212
- // value.
5213
- toolPolicyVersion: z.number().int().positive().optional(),
5574
+ // Origin and optimistic-concurrency fence for the durable session policy.
5575
+ toolPolicy: SessionToolPolicy,
5576
+ toolPolicyVersion: z.number().int().positive(),
5214
5577
  // Secret-safe current resolution, computed at an API/read or execution
5215
5578
  // boundary from IDs only. Optional because internal DB readers need not load
5216
5579
  // the workspace runtime registry.
@@ -5247,9 +5610,9 @@ export const Session = z.object({
5247
5610
  // Non-default first-party MCP token permissions (manager-style sessions);
5248
5611
  // null means the fixed worker default set.
5249
5612
  firstPartyMcpPermissions: z.array(Permission).nullable(),
5250
- // null means the fixed minimal worker-visible default. An explicit array,
5251
- // including [], is the exact model-visible first-party selection.
5252
- firstPartyMcpTools: z.array(FirstPartyMcpToolName).nullable().default(null),
5613
+ // Exact model-visible OpenGeni selection. All catalogued tools are selected
5614
+ // by default; [] intentionally selects none.
5615
+ firstPartyMcpTools: z.array(FirstPartyMcpToolName),
5253
5616
  // Per-session third-party MCP servers, metadata only. Credential values are
5254
5617
  // write-only and never appear here.
5255
5618
  mcpServers: z.array(SessionMcpServerMetadata).default([]),
@@ -5287,6 +5650,10 @@ export const Session = z.object({
5287
5650
  // "Running on:" indicator's source). Both are credential-row ids, null until set.
5288
5651
  codexPinnedCredentialId: z.string().uuid().nullable(),
5289
5652
  codexLastCredentialId: z.string().uuid().nullable(),
5653
+ // Frozen at session create. remote_v2 ⇒ Codex remote compaction + Codex-only
5654
+ // model admission for the life of the session; portable ⇒ plaintext compaction
5655
+ // and free mid-session provider switching (today's behavior).
5656
+ codexCompactionMode: CodexCompactionMode,
5290
5657
  /** Personal (authenticated subject) workspace pin state, never workspace-global. */
5291
5658
  pinned: z.boolean().default(false),
5292
5659
  /** Stable pin ordering key; null when this subject has not pinned the session. */
@@ -5377,6 +5744,7 @@ export const SessionEventType = z.enum([
5377
5744
  "session.requiresAction",
5378
5745
  "session.humanInput.requested",
5379
5746
  "session.context.compaction.requested",
5747
+ "session.context.compaction.started",
5380
5748
  "session.context.compacted",
5381
5749
  "session.context.compaction.skipped",
5382
5750
  "session.context.cleared",
@@ -5670,6 +6038,7 @@ export const SESSION_EVENT_SEMANTIC_CLASS_TYPES = {
5670
6038
  ],
5671
6039
  checkpoint: [
5672
6040
  "session.context.compaction.requested",
6041
+ "session.context.compaction.started",
5673
6042
  "session.context.compacted",
5674
6043
  "session.context.compaction.skipped",
5675
6044
  "session.context.cleared",
@@ -7496,6 +7865,7 @@ export const CreateSessionRequest = withVariableSetIdAlias({
7496
7865
  metadata: z.record(z.string(), z.unknown()).default({}),
7497
7866
  model: z.string().min(1).optional(),
7498
7867
  reasoningEffort: ReasoningEffort.optional(),
7868
+ latencyMode: LatencyMode.optional(),
7499
7869
  sandboxBackend: SandboxBackend.optional(),
7500
7870
  // The enrolled machine (a sandbox id) to run this session on; seeds the
7501
7871
  // active-sandbox pointer at creation so the FIRST turn routes to the chosen
@@ -7542,7 +7912,7 @@ export const CreateSessionRequest = withVariableSetIdAlias({
7542
7912
  // rejected; creation never silently expands a child beyond that set.
7543
7913
  firstPartyMcpPermissions: z.array(Permission).optional(),
7544
7914
  // Exact model-visible selection from the broad first-party OpenGeni MCP
7545
- // catalog. Omit for the minimal default; [] intentionally exposes none.
7915
+ // catalog. Omission selects the full catalog; [] intentionally exposes none.
7546
7916
  // This does not grant authority: every registered tool is permission-gated.
7547
7917
  firstPartyMcpTools: z.array(FirstPartyMcpToolName).optional(),
7548
7918
  // Third-party MCP servers attached only to this session. For an agent-created
@@ -7756,21 +8126,23 @@ export const ClientSessionEvent = z.discriminatedUnion("type", [
7756
8126
  z.object({
7757
8127
  type: z.literal("user.message"),
7758
8128
  clientEventId: SessionOperationKey.optional(),
7759
- payload: z.object({
7760
- text: z.string().min(1),
7761
- // System-level host context for this exact turn only. Persisted on the
7762
- // turn for retry/recovery, never copied into the visible user message.
7763
- turnInstructions: z.string().trim().min(1).max(32768).optional(),
7764
- resources: z.array(ResourceRef).default([]),
7765
- tools: z.array(ToolRef).default([]),
7766
- model: z.string().min(1).optional(),
7767
- reasoningEffort: ReasoningEffort.optional(),
7768
- controlEtag: z.string().min(1).optional(),
7769
- expectedDraftRevision: z.number().int().nonnegative().optional(),
7770
- // Header-value rotation only. URL/name/tool settings are immutable after
7771
- // session create; persisted events expose metadata, never header values.
7772
- mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
7773
- }),
8129
+ payload: z
8130
+ .object({
8131
+ text: z.string().min(1),
8132
+ // System-level host context for this exact turn only. Persisted on the
8133
+ // turn for retry/recovery, never copied into the visible user message.
8134
+ turnInstructions: z.string().trim().min(1).max(32768).optional(),
8135
+ resources: z.array(ResourceRef).default([]),
8136
+ model: z.string().min(1).optional(),
8137
+ reasoningEffort: ReasoningEffort.optional(),
8138
+ latencyMode: LatencyMode.optional(),
8139
+ controlEtag: z.string().min(1).optional(),
8140
+ expectedDraftRevision: z.number().int().nonnegative().optional(),
8141
+ // Header-value rotation only. URL/name/tool settings are immutable after
8142
+ // session create; persisted events expose metadata, never header values.
8143
+ mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
8144
+ })
8145
+ .strict(),
7774
8146
  }),
7775
8147
  z.object({
7776
8148
  type: z.literal("user.approvalDecision"),
@@ -7792,19 +8164,21 @@ export const ClientSessionEvent = z.discriminatedUnion("type", [
7792
8164
  ]);
7793
8165
  export type ClientSessionEvent = z.infer<typeof ClientSessionEvent>;
7794
8166
 
7795
- export const SteerSessionMessageRequest = z.object({
7796
- text: z.string().min(1),
7797
- // Same per-turn system-level context as a queued user.message.
7798
- turnInstructions: z.string().trim().min(1).max(32768).optional(),
7799
- resources: z.array(ResourceRef).default([]),
7800
- tools: z.array(ToolRef).default([]),
7801
- model: z.string().min(1).optional(),
7802
- reasoningEffort: ReasoningEffort.optional(),
7803
- clientEventId: SessionOperationKey.optional(),
7804
- controlEtag: z.string().min(1).optional(),
7805
- expectedDraftRevision: z.number().int().nonnegative().optional(),
7806
- mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
7807
- });
8167
+ export const SteerSessionMessageRequest = z
8168
+ .object({
8169
+ text: z.string().min(1),
8170
+ // Same per-turn system-level context as a queued user.message.
8171
+ turnInstructions: z.string().trim().min(1).max(32768).optional(),
8172
+ resources: z.array(ResourceRef).default([]),
8173
+ model: z.string().min(1).optional(),
8174
+ reasoningEffort: ReasoningEffort.optional(),
8175
+ latencyMode: LatencyMode.optional(),
8176
+ clientEventId: SessionOperationKey.optional(),
8177
+ controlEtag: z.string().min(1).optional(),
8178
+ expectedDraftRevision: z.number().int().nonnegative().optional(),
8179
+ mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
8180
+ })
8181
+ .strict();
7808
8182
  export type SteerSessionMessageRequest = z.infer<typeof SteerSessionMessageRequest>;
7809
8183
 
7810
8184
  export const SteerSessionMessageResponse = z.object({
@@ -7848,6 +8222,9 @@ export type GitHubRepositoryScope = z.infer<typeof GitHubRepositoryScope>;
7848
8222
  export const GitHubBindingStatus = z.enum(["disabled", "unbound", "bound"]);
7849
8223
  export type GitHubBindingStatus = z.infer<typeof GitHubBindingStatus>;
7850
8224
 
8225
+ export const GitHubAppSetupMode = z.enum(["platform", "operator"]);
8226
+ export type GitHubAppSetupMode = z.infer<typeof GitHubAppSetupMode>;
8227
+
7851
8228
  export const GitHubInstallationLifecycle = z.enum(["active", "suspended", "deleted", "unverified"]);
7852
8229
  export type GitHubInstallationLifecycle = z.infer<typeof GitHubInstallationLifecycle>;
7853
8230
 
@@ -7859,6 +8236,7 @@ export const GitHubInstallationBinding = z.object({
7859
8236
  lifecycle: GitHubInstallationLifecycle,
7860
8237
  repositoryScope: GitHubRepositoryScope,
7861
8238
  repositoryCount: z.number().int().nonnegative(),
8239
+ configureUrl: z.string().url().nullable(),
7862
8240
  createdAt: z.string(),
7863
8241
  updatedAt: z.string(),
7864
8242
  });
@@ -7867,6 +8245,7 @@ export type GitHubInstallationBinding = z.infer<typeof GitHubInstallationBinding
7867
8245
  export const GitHubAppInfo = z.object({
7868
8246
  configured: z.boolean(),
7869
8247
  status: GitHubBindingStatus,
8248
+ setupMode: GitHubAppSetupMode,
7870
8249
  appId: z.string().nullable(),
7871
8250
  clientId: z.string().nullable(),
7872
8251
  appSlug: z.string().nullable(),
@@ -8570,6 +8949,11 @@ export const TurnExecutionReasoningSourceV1 = /* @__PURE__ */ defineModelContrac
8570
8949
  );
8571
8950
  export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoningSourceV1>;
8572
8951
 
8952
+ export const TurnExecutionLatencyModeSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
8953
+ z.enum(["explicit", "session", "deployment", "continuation"]),
8954
+ );
8955
+ export type TurnExecutionLatencyModeSourceV1 = z.infer<typeof TurnExecutionLatencyModeSourceV1>;
8956
+
8573
8957
  /**
8574
8958
  * Secret-safe execution identity frozen onto one accepted logical turn.
8575
8959
  *
@@ -8577,6 +8961,9 @@ export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoni
8577
8961
  * definition rather than a serialized provider client. It must never contain
8578
8962
  * a key/token, concrete connected credential id, account label, authorization
8579
8963
  * header, or credential-bearing URL/query value.
8964
+ *
8965
+ * `latencyMode` / `latencyModeSource` default to standard/deployment so legacy
8966
+ * snapshots without those keys remain readable as Standard.
8580
8967
  */
8581
8968
  export const TurnExecutionPolicyV1 = /* @__PURE__ */ defineModelContractSchema(() =>
8582
8969
  z
@@ -8587,6 +8974,8 @@ export const TurnExecutionPolicyV1 = /* @__PURE__ */ defineModelContractSchema((
8587
8974
  modelSource: TurnExecutionModelSourceV1,
8588
8975
  reasoningEffort: ReasoningEffort,
8589
8976
  reasoningSource: TurnExecutionReasoningSourceV1,
8977
+ latencyMode: LatencyMode.default("standard"),
8978
+ latencyModeSource: TurnExecutionLatencyModeSourceV1.default("deployment"),
8590
8979
  providerId: z.string().min(1),
8591
8980
  upstreamModelId: z.string().min(1),
8592
8981
  wireApi: z.enum(["responses", "chat"]),
@@ -8677,6 +9066,8 @@ export function turnExecutionPolicyAuditMetadata(
8677
9066
  modelSource: parsed.modelSource,
8678
9067
  effectiveReasoningEffort: parsed.reasoningEffort,
8679
9068
  reasoningSource: parsed.reasoningSource,
9069
+ effectiveLatencyMode: parsed.latencyMode,
9070
+ latencyModeSource: parsed.latencyModeSource,
8680
9071
  providerId: parsed.providerId,
8681
9072
  credentialSourceKind: parsed.credentialSource.kind,
8682
9073
  credentialSourceMechanism:
@@ -8889,6 +9280,14 @@ export const ClientConfig = /* @__PURE__ */ defineModelContractSchema(() =>
8889
9280
  enabled: z.boolean(),
8890
9281
  maxSizeBytes: z.number().int().positive(),
8891
9282
  }),
9283
+ // Native voice-input capability. Provider/model/credentials stay server-private;
9284
+ // clients only learn whether a deployment can transcribe and the hard ceilings.
9285
+ voiceInput: ClientVoiceInputConfig.default({
9286
+ available: false,
9287
+ maxDurationSeconds: VOICE_INPUT_MAX_DURATION_SECONDS,
9288
+ maxSizeBytes: VOICE_INPUT_MAX_SIZE_BYTES,
9289
+ acceptedMimeTypes: [...VOICE_INPUT_ACCEPTED_MIME_TYPES],
9290
+ }),
8892
9291
  productAccessMode: ProductAccessMode,
8893
9292
  auth: ClientAuthConfig.default({ mode: "none" }),
8894
9293
  // Server-wide hint: does this deployment support Channel-A structured services
@@ -8984,3 +9383,5 @@ export function evaluateWorkspaceModelPolicy(
8984
9383
  export * from "./codex-fleet-policy";
8985
9384
  export * from "./secret-redaction";
8986
9385
  export * from "./workspace-instruction-policies";
9386
+ export * from "./workspace-state";
9387
+ export * from "./preference-registry";