@opengeni/contracts 0.23.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,8 +712,13 @@ 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>;
@@ -800,10 +834,17 @@ export const TranscriptionErrorCode = z.enum([
800
834
  "policy_blocked",
801
835
  "timeout",
802
836
  "cancelled",
837
+ "unavailable",
838
+ "too_large",
839
+ "invalid_audio",
803
840
  "unknown",
804
841
  ]);
805
842
  export type TranscriptionErrorCode = z.infer<typeof TranscriptionErrorCode>;
806
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
+
807
848
  export const TranscriptionTimeSpan = z
808
849
  .object({
809
850
  startMilliseconds: z.number().finite().nonnegative(),
@@ -925,6 +966,9 @@ export const TranscriptionEvent = z.discriminatedUnion("type", [
925
966
  export type TranscriptionEvent = z.infer<typeof TranscriptionEvent>;
926
967
 
927
968
  /**
969
+ * @deprecated Host-adapter transcription policy. Kept for one release so existing
970
+ * workspace settings remain readable. New writes use `WorkspaceVoiceInputSettings`.
971
+ *
928
972
  * Workspace-only policy for the distinct speech-to-text capability. It never
929
973
  * authorizes a turn model/provider and contains connection references rather
930
974
  * than secrets. `acceptanceId` changes whenever an admin accepts a new target
@@ -1041,16 +1085,77 @@ export const WorkspaceTranscriptionPolicy = z
1041
1085
  });
1042
1086
  export type WorkspaceTranscriptionPolicy = z.infer<typeof WorkspaceTranscriptionPolicy>;
1043
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
+
1044
1140
  // Validates the KNOWN keys of workspaces.settings; passthrough keeps unknown
1045
- // (future) keys rather than stripping them. memoryEnabled and transcription are
1046
- // 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.
1047
1143
  export const WorkspaceSettingsSchema = z
1048
1144
  .object({
1049
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
+ */
1050
1152
  transcription: WorkspaceTranscriptionPolicy.optional(),
1051
1153
  // null clears the workspace override and falls back to the persisted
1052
1154
  // deployment policy. The database boundary validates the same range.
1053
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(),
1054
1159
  })
1055
1160
  .passthrough();
1056
1161
  export type WorkspaceSettings = z.infer<typeof WorkspaceSettingsSchema>;
@@ -1061,14 +1166,40 @@ export function resolveWorkspaceMemoryEnabled(settings: unknown): boolean {
1061
1166
  return parsed.success ? parsed.data.memoryEnabled === true : false;
1062
1167
  }
1063
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
+
1064
1192
  // PATCH body for workspace settings: a partial top-level patch that merges into
1065
- // the stored bag. Nested transcription policy updates are therefore full
1066
- // 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.
1067
1195
  export const UpdateWorkspaceSettingsRequest = z
1068
1196
  .object({
1069
1197
  memoryEnabled: z.boolean().optional(),
1198
+ voiceInput: WorkspaceVoiceInputSettings.optional(),
1199
+ /** @deprecated Prefer `voiceInput`. Kept for one compatibility release. */
1070
1200
  transcription: WorkspaceTranscriptionPolicy.optional(),
1071
1201
  maxNestedAgentDepth: NestedAgentDepthValue.nullable().optional(),
1202
+ codexCompactionDefault: CodexCompactionMode.optional(),
1072
1203
  })
1073
1204
  .passthrough();
1074
1205
  export type UpdateWorkspaceSettingsRequest = z.infer<typeof UpdateWorkspaceSettingsRequest>;
@@ -1160,6 +1291,16 @@ export const ServiceTurnInitiatorContext = TurnInitiatorContext.superRefine((val
1160
1291
  });
1161
1292
  export type ServiceTurnInitiatorContext = z.infer<typeof ServiceTurnInitiatorContext>;
1162
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
+
1163
1304
  export const AccountGrant = z.object({
1164
1305
  accountId: z.string().uuid(),
1165
1306
  subjectId: z.string().min(1),
@@ -1176,6 +1317,9 @@ export const AccessGrant = z.object({
1176
1317
  subjectId: z.string().min(1),
1177
1318
  subjectLabel: z.string().optional(),
1178
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(),
1179
1323
  metadata: z.record(z.string(), z.unknown()).optional(),
1180
1324
  // Optional trusted causal principal for a command submitted by an embedding
1181
1325
  // host. Authorization still uses subjectId + permissions above.
@@ -1202,6 +1346,10 @@ export const DelegatedAccessTokenPayload = z
1202
1346
  subjectId: z.string().min(1),
1203
1347
  subjectLabel: z.string().optional(),
1204
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,
1205
1353
  // Trusted embedding hosts can sign a causal service principal separately
1206
1354
  // from the grant subject that authorizes the request. The claim is consumed
1207
1355
  // only when a command creates a new session/turn.
@@ -1226,6 +1374,53 @@ export const DelegatedAccessTokenPayload = z
1226
1374
  exp: z.number().int().positive(),
1227
1375
  })
1228
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
+ }
1229
1424
  if (payload.serviceInitiatorContext && !payload.serviceInitiator) {
1230
1425
  ctx.addIssue({
1231
1426
  code: z.ZodIssueCode.custom,
@@ -1737,6 +1932,169 @@ export const UsageEvent = z.object({
1737
1932
  });
1738
1933
  export type UsageEvent = z.infer<typeof UsageEvent>;
1739
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
+
1740
2098
  export const LimitAction = z.enum([
1741
2099
  "agent_run:create",
1742
2100
  "tokens:consume",
@@ -2896,11 +3254,14 @@ export const ToolRef = z.object({
2896
3254
  kind: z.literal("mcp"),
2897
3255
  id: z.string().min(1),
2898
3256
  // Non-fatal-on-connect marker for MCP server refs that can degrade
2899
- // gracefully. Absent/false is STRICT: the id must be configured and an
2900
- // unavailable server fails the turn. `optional:true` is preserved for known
2901
- // servers and makes runtime connect/list failures skip that server; if the
2902
- // deployment does not configure the id, validation drops the ref. The server
2903
- // 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.
2904
3265
  optional: z.boolean().optional(),
2905
3266
  });
2906
3267
  export type ToolRef = z.infer<typeof ToolRef>;
@@ -3161,6 +3522,14 @@ export function reasoningEffortForMetadata(
3161
3522
  : fallback;
3162
3523
  }
3163
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
+
3164
3533
  export function stableJson(value: unknown): string {
3165
3534
  return JSON.stringify(sortJson(value));
3166
3535
  }
@@ -3595,6 +3964,7 @@ export const SessionTurn = z.object({
3595
3964
  toolsProvided: z.boolean().optional(),
3596
3965
  model: z.string().min(1),
3597
3966
  reasoningEffort: ReasoningEffort,
3967
+ latencyMode: LatencyMode.default("standard"),
3598
3968
  sandboxBackend: SandboxBackend,
3599
3969
  // Per-turn OS override. NULL = inherit the session's sandboxOs.
3600
3970
  sandboxOs: SandboxOs.nullable(),
@@ -3683,6 +4053,7 @@ export const ComposerDraft = z.object({
3683
4053
  resources: z.array(ResourceRef),
3684
4054
  model: z.string().min(1),
3685
4055
  reasoningEffort: ReasoningEffort,
4056
+ latencyMode: LatencyMode.default("standard"),
3686
4057
  sourceTurnId: z.string().uuid().nullable(),
3687
4058
  sourceTurnVersion: z.number().int().positive().nullable(),
3688
4059
  updatedAt: z.string().nullable(),
@@ -3723,6 +4094,7 @@ export const SaveComposerDraftRequest = ComposerDraft.pick({
3723
4094
  resources: true,
3724
4095
  model: true,
3725
4096
  reasoningEffort: true,
4097
+ latencyMode: true,
3726
4098
  }).extend({ expectedRevision: z.number().int().nonnegative() });
3727
4099
  export type SaveComposerDraftRequest = z.infer<typeof SaveComposerDraftRequest>;
3728
4100
 
@@ -3753,6 +4125,7 @@ export const NewSessionDraft = z.object({
3753
4125
  toolsProvided: z.boolean().default(false),
3754
4126
  model: z.string().min(1),
3755
4127
  reasoningEffort: ReasoningEffort,
4128
+ latencyMode: LatencyMode.default("standard"),
3756
4129
  options: NewSessionDraftOptions,
3757
4130
  updatedAt: z.string().nullable(),
3758
4131
  });
@@ -3765,6 +4138,7 @@ export const SaveNewSessionDraftRequest = NewSessionDraft.pick({
3765
4138
  toolsProvided: true,
3766
4139
  model: true,
3767
4140
  reasoningEffort: true,
4141
+ latencyMode: true,
3768
4142
  options: true,
3769
4143
  }).extend({ expectedRevision: z.number().int().nonnegative() });
3770
4144
  export type SaveNewSessionDraftRequest = z.infer<typeof SaveNewSessionDraftRequest>;
@@ -4853,20 +5227,11 @@ export type ConnectionKind = z.infer<typeof ConnectionKind>;
4853
5227
  export const ConnectionStatus = z.enum(["active", "needs_reauth", "revoked", "error"]);
4854
5228
  export type ConnectionStatus = z.infer<typeof ConnectionStatus>;
4855
5229
 
5230
+ export const OPENGENI_PERSONAL_SLACK_MCP_URL = "https://mcp.slack.com/mcp" as const;
5231
+
4856
5232
  export const OPENGENI_SLACK_BOT_CREDENTIAL_ROLE = "opengeni_slack_bot" as const;
4857
5233
  export const OPENGENI_SLACK_BOT_CREDENTIAL_LABEL = "OpenGeni Slack bot" as const;
4858
5234
  export const OPENGENI_SLACK_BOT_SESSION_METADATA_KEY = "opengeniSlackBotConnectionId" as const;
4859
- export const OPENGENI_SLACK_BOT_REQUIRED_SCOPES = [
4860
- "chat:write",
4861
- "im:write",
4862
- "channels:read",
4863
- "channels:history",
4864
- "groups:read",
4865
- "groups:history",
4866
- "users:read",
4867
- ] as const;
4868
- export const OPENGENI_SLACK_BOT_FORBIDDEN_SCOPES = ["channels:join", "chat:write.public"] as const;
4869
-
4870
5235
  export const OpenGeniSlackBotConnectionMetadata = z
4871
5236
  .object({
4872
5237
  credentialRole: z.literal(OPENGENI_SLACK_BOT_CREDENTIAL_ROLE),
@@ -5285,6 +5650,10 @@ export const Session = z.object({
5285
5650
  // "Running on:" indicator's source). Both are credential-row ids, null until set.
5286
5651
  codexPinnedCredentialId: z.string().uuid().nullable(),
5287
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,
5288
5657
  /** Personal (authenticated subject) workspace pin state, never workspace-global. */
5289
5658
  pinned: z.boolean().default(false),
5290
5659
  /** Stable pin ordering key; null when this subject has not pinned the session. */
@@ -5375,6 +5744,7 @@ export const SessionEventType = z.enum([
5375
5744
  "session.requiresAction",
5376
5745
  "session.humanInput.requested",
5377
5746
  "session.context.compaction.requested",
5747
+ "session.context.compaction.started",
5378
5748
  "session.context.compacted",
5379
5749
  "session.context.compaction.skipped",
5380
5750
  "session.context.cleared",
@@ -5668,6 +6038,7 @@ export const SESSION_EVENT_SEMANTIC_CLASS_TYPES = {
5668
6038
  ],
5669
6039
  checkpoint: [
5670
6040
  "session.context.compaction.requested",
6041
+ "session.context.compaction.started",
5671
6042
  "session.context.compacted",
5672
6043
  "session.context.compaction.skipped",
5673
6044
  "session.context.cleared",
@@ -7494,6 +7865,7 @@ export const CreateSessionRequest = withVariableSetIdAlias({
7494
7865
  metadata: z.record(z.string(), z.unknown()).default({}),
7495
7866
  model: z.string().min(1).optional(),
7496
7867
  reasoningEffort: ReasoningEffort.optional(),
7868
+ latencyMode: LatencyMode.optional(),
7497
7869
  sandboxBackend: SandboxBackend.optional(),
7498
7870
  // The enrolled machine (a sandbox id) to run this session on; seeds the
7499
7871
  // active-sandbox pointer at creation so the FIRST turn routes to the chosen
@@ -7763,6 +8135,7 @@ export const ClientSessionEvent = z.discriminatedUnion("type", [
7763
8135
  resources: z.array(ResourceRef).default([]),
7764
8136
  model: z.string().min(1).optional(),
7765
8137
  reasoningEffort: ReasoningEffort.optional(),
8138
+ latencyMode: LatencyMode.optional(),
7766
8139
  controlEtag: z.string().min(1).optional(),
7767
8140
  expectedDraftRevision: z.number().int().nonnegative().optional(),
7768
8141
  // Header-value rotation only. URL/name/tool settings are immutable after
@@ -7799,6 +8172,7 @@ export const SteerSessionMessageRequest = z
7799
8172
  resources: z.array(ResourceRef).default([]),
7800
8173
  model: z.string().min(1).optional(),
7801
8174
  reasoningEffort: ReasoningEffort.optional(),
8175
+ latencyMode: LatencyMode.optional(),
7802
8176
  clientEventId: SessionOperationKey.optional(),
7803
8177
  controlEtag: z.string().min(1).optional(),
7804
8178
  expectedDraftRevision: z.number().int().nonnegative().optional(),
@@ -8575,6 +8949,11 @@ export const TurnExecutionReasoningSourceV1 = /* @__PURE__ */ defineModelContrac
8575
8949
  );
8576
8950
  export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoningSourceV1>;
8577
8951
 
8952
+ export const TurnExecutionLatencyModeSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
8953
+ z.enum(["explicit", "session", "deployment", "continuation"]),
8954
+ );
8955
+ export type TurnExecutionLatencyModeSourceV1 = z.infer<typeof TurnExecutionLatencyModeSourceV1>;
8956
+
8578
8957
  /**
8579
8958
  * Secret-safe execution identity frozen onto one accepted logical turn.
8580
8959
  *
@@ -8582,6 +8961,9 @@ export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoni
8582
8961
  * definition rather than a serialized provider client. It must never contain
8583
8962
  * a key/token, concrete connected credential id, account label, authorization
8584
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.
8585
8967
  */
8586
8968
  export const TurnExecutionPolicyV1 = /* @__PURE__ */ defineModelContractSchema(() =>
8587
8969
  z
@@ -8592,6 +8974,8 @@ export const TurnExecutionPolicyV1 = /* @__PURE__ */ defineModelContractSchema((
8592
8974
  modelSource: TurnExecutionModelSourceV1,
8593
8975
  reasoningEffort: ReasoningEffort,
8594
8976
  reasoningSource: TurnExecutionReasoningSourceV1,
8977
+ latencyMode: LatencyMode.default("standard"),
8978
+ latencyModeSource: TurnExecutionLatencyModeSourceV1.default("deployment"),
8595
8979
  providerId: z.string().min(1),
8596
8980
  upstreamModelId: z.string().min(1),
8597
8981
  wireApi: z.enum(["responses", "chat"]),
@@ -8682,6 +9066,8 @@ export function turnExecutionPolicyAuditMetadata(
8682
9066
  modelSource: parsed.modelSource,
8683
9067
  effectiveReasoningEffort: parsed.reasoningEffort,
8684
9068
  reasoningSource: parsed.reasoningSource,
9069
+ effectiveLatencyMode: parsed.latencyMode,
9070
+ latencyModeSource: parsed.latencyModeSource,
8685
9071
  providerId: parsed.providerId,
8686
9072
  credentialSourceKind: parsed.credentialSource.kind,
8687
9073
  credentialSourceMechanism:
@@ -8894,6 +9280,14 @@ export const ClientConfig = /* @__PURE__ */ defineModelContractSchema(() =>
8894
9280
  enabled: z.boolean(),
8895
9281
  maxSizeBytes: z.number().int().positive(),
8896
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
+ }),
8897
9291
  productAccessMode: ProductAccessMode,
8898
9292
  auth: ClientAuthConfig.default({ mode: "none" }),
8899
9293
  // Server-wide hint: does this deployment support Channel-A structured services
@@ -8989,3 +9383,5 @@ export function evaluateWorkspaceModelPolicy(
8989
9383
  export * from "./codex-fleet-policy";
8990
9384
  export * from "./secret-redaction";
8991
9385
  export * from "./workspace-instruction-policies";
9386
+ export * from "./workspace-state";
9387
+ export * from "./preference-registry";