@opengeni/contracts 0.38.3 → 0.40.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/dist/{chunk-ZNH72ZGW.js → chunk-5HR2GPSC.js} +3553 -3200
- package/dist/chunk-5HR2GPSC.js.map +1 -0
- package/dist/event-preview.d.ts +6 -6
- package/dist/google-drive.js +1 -1
- package/dist/index.d.ts +576 -17
- package/dist/index.js +89 -17
- package/dist/mcp-receipts.d.ts +96 -0
- package/dist/retained-output.d.ts +59 -6
- package/dist/transcription-recordings.d.ts +300 -0
- package/package.json +1 -1
- package/src/event-preview.ts +6 -6
- package/src/index.ts +296 -40
- package/src/mcp-receipts.ts +281 -0
- package/src/retained-output.ts +101 -8
- package/src/transcription-recordings.ts +169 -0
- package/dist/chunk-ZNH72ZGW.js.map +0 -1
- package/dist/secret-redaction.d.ts +0 -40
- package/src/secret-redaction.ts +0 -364
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type SessionEventBoundarySurface,
|
|
7
7
|
} from "./event-preview";
|
|
8
8
|
import { WorkspaceInstructionPolicyRoleKeyInput } from "./workspace-instruction-policies";
|
|
9
|
+
import { ClientResumableVoiceInputConfig } from "./transcription-recordings";
|
|
9
10
|
|
|
10
11
|
export * from "./slack-bot-scopes";
|
|
11
12
|
export * from "./connector-destinations";
|
|
@@ -35,6 +36,19 @@ export {
|
|
|
35
36
|
normalizeWorkspaceArtifactSlug,
|
|
36
37
|
} from "./artifacts";
|
|
37
38
|
|
|
39
|
+
export {
|
|
40
|
+
MCP_MUTATION_RECEIPT_MAX_BYTES,
|
|
41
|
+
MCP_MUTATION_RECEIPT_VERSION,
|
|
42
|
+
McpMutationReceipt,
|
|
43
|
+
McpMutationReceiptIdempotencyStatus,
|
|
44
|
+
McpMutationReceiptOutcome,
|
|
45
|
+
McpMutationResource,
|
|
46
|
+
type McpMutationReceipt as McpMutationReceiptType,
|
|
47
|
+
type McpMutationReceiptIdempotencyStatus as McpMutationReceiptIdempotencyStatusType,
|
|
48
|
+
type McpMutationReceiptOutcome as McpMutationReceiptOutcomeType,
|
|
49
|
+
type McpMutationResource as McpMutationResourceType,
|
|
50
|
+
} from "./mcp-receipts";
|
|
51
|
+
|
|
38
52
|
export {
|
|
39
53
|
SESSION_EVENT_PAYLOAD_MAX_BYTES,
|
|
40
54
|
approximateSessionEventTokens,
|
|
@@ -52,6 +66,11 @@ export {
|
|
|
52
66
|
} from "./event-preview";
|
|
53
67
|
|
|
54
68
|
export {
|
|
69
|
+
COMPUTER_SCREENSHOT_MAX_BYTES,
|
|
70
|
+
COMPUTER_SCREENSHOT_MAX_DIMENSION,
|
|
71
|
+
COMPUTER_SCREENSHOT_MAX_PIXELS,
|
|
72
|
+
COMPUTER_SCREENSHOT_RETENTION_MS,
|
|
73
|
+
COMPUTER_SCREENSHOT_WORKSPACE_QUOTA_BYTES,
|
|
55
74
|
RETAINED_OUTPUT_DEFAULT_PAGE_BYTES,
|
|
56
75
|
RETAINED_OUTPUT_MAX_PAGE_BYTES,
|
|
57
76
|
RETAINED_OUTPUT_RECEIPT_MAX_BYTES,
|
|
@@ -62,12 +81,14 @@ export {
|
|
|
62
81
|
RetainedOutputKind,
|
|
63
82
|
RetainedOutputUnavailableReason,
|
|
64
83
|
retainedArtifactReferenceFromFile,
|
|
84
|
+
retainedScreenshotReferenceFromFile,
|
|
65
85
|
retainedOutputUnavailable,
|
|
66
86
|
resolveRetainedOutputRange,
|
|
67
87
|
validateRetainedOutputEvidence,
|
|
68
88
|
type RetainedArtifactFileInput,
|
|
69
89
|
type RetainedArtifactMetadata,
|
|
70
90
|
type RetainedArtifactReference,
|
|
91
|
+
type RetainedScreenshotArtifactInput,
|
|
71
92
|
type RetainedArtifactUnavailable,
|
|
72
93
|
type RetainedOutputAvailableEvidence,
|
|
73
94
|
type RetainedOutputEvidence,
|
|
@@ -595,9 +616,9 @@ export const Permission = z.enum([
|
|
|
595
616
|
"sessions:control",
|
|
596
617
|
// sandbox workspace (sandbox contract §C.3 / crosscut PART 1.2). stream:view is a
|
|
597
618
|
// REAL, distinct permission — strictly BROADER than sessions:read — because the
|
|
598
|
-
// pixel plane (Channel B)
|
|
599
|
-
//
|
|
600
|
-
//
|
|
619
|
+
// pixel plane (Channel B) exposes raw pixels: a viewer can see content the
|
|
620
|
+
// structured Channel-A event log never captured. sessions:read is NOT
|
|
621
|
+
// permission to watch raw pixels.
|
|
601
622
|
"stream:view",
|
|
602
623
|
// SEPARATE from stream:view: raw input to the desktop (bypasses approvalQueue /
|
|
603
624
|
// interrupt). NEVER granted by default in v1 (the input plane is OFF —
|
|
@@ -628,8 +649,14 @@ export const Permission = z.enum([
|
|
|
628
649
|
"environments:manage",
|
|
629
650
|
/** @deprecated alias of variable-sets:use */
|
|
630
651
|
"environments:use",
|
|
652
|
+
"variable-sets:list",
|
|
653
|
+
"variable-sets:read",
|
|
654
|
+
"variable-sets:write",
|
|
631
655
|
"variable-sets:manage",
|
|
632
656
|
"variable-sets:use",
|
|
657
|
+
"secrets:list",
|
|
658
|
+
"secrets:read",
|
|
659
|
+
"secrets:write",
|
|
633
660
|
// Attach or rotate per-session third-party MCP server credentials. Deliberately
|
|
634
661
|
// not part of the worker's default first-party MCP permission set: a sandboxed
|
|
635
662
|
// agent must not be able to hand itself new bearer credentials.
|
|
@@ -714,6 +741,7 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
|
|
|
714
741
|
"sandbox_swap",
|
|
715
742
|
"run_on",
|
|
716
743
|
"sandbox_provision",
|
|
744
|
+
"connected_machine_remove",
|
|
717
745
|
"rig_list",
|
|
718
746
|
"rig_get",
|
|
719
747
|
"rig_propose_change",
|
|
@@ -730,6 +758,7 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
|
|
|
730
758
|
"set_other_session_title",
|
|
731
759
|
"variable_set_list",
|
|
732
760
|
"environment_list",
|
|
761
|
+
"variable_set_get_variable",
|
|
733
762
|
"variable_set_set_variable",
|
|
734
763
|
"environment_set_variable",
|
|
735
764
|
"github_connect_link",
|
|
@@ -1155,6 +1184,7 @@ export const ClientVoiceInputConfig = z
|
|
|
1155
1184
|
.positive()
|
|
1156
1185
|
.max(25 * 1024 * 1024),
|
|
1157
1186
|
acceptedMimeTypes: z.array(z.string().trim().min(1).max(128)).min(1).max(32),
|
|
1187
|
+
resumable: ClientResumableVoiceInputConfig.optional(),
|
|
1158
1188
|
})
|
|
1159
1189
|
.strict();
|
|
1160
1190
|
export type ClientVoiceInputConfig = z.infer<typeof ClientVoiceInputConfig>;
|
|
@@ -1184,6 +1214,8 @@ export const VOICE_INPUT_ACCEPTED_MIME_TYPES = [
|
|
|
1184
1214
|
"audio/m4a",
|
|
1185
1215
|
] as const;
|
|
1186
1216
|
|
|
1217
|
+
export * from "./transcription-recordings";
|
|
1218
|
+
|
|
1187
1219
|
/** Per-session / workspace Codex compaction strategy. */
|
|
1188
1220
|
export const CodexCompactionMode = z.enum(["remote_v2", "portable"]);
|
|
1189
1221
|
export type CodexCompactionMode = z.infer<typeof CodexCompactionMode>;
|
|
@@ -1258,6 +1290,9 @@ export const WorkspaceSettingsSchema = z
|
|
|
1258
1290
|
// Default compaction strategy for NEW Codex sessions created in this
|
|
1259
1291
|
// workspace. Absent ⇒ remote_v2. Non-Codex sessions always freeze portable.
|
|
1260
1292
|
codexCompactionDefault: CodexCompactionMode.optional(),
|
|
1293
|
+
// Whether agents may expose and invoke the built-in structured human-input
|
|
1294
|
+
// tool. Absent preserves the historical enabled behavior.
|
|
1295
|
+
agentHumanInputEnabled: z.boolean().optional(),
|
|
1261
1296
|
// Optional Slack reaction invocation. Absent/invalid fails closed to the
|
|
1262
1297
|
// disabled default via resolveWorkspaceSlackReactionSummonSettings.
|
|
1263
1298
|
slackReactionSummon: WorkspaceSlackReactionSummonSettings.optional(),
|
|
@@ -1278,6 +1313,12 @@ export function resolveWorkspaceCodexCompactionDefault(settings: unknown): Codex
|
|
|
1278
1313
|
return parsed.data.codexCompactionDefault ?? "remote_v2";
|
|
1279
1314
|
}
|
|
1280
1315
|
|
|
1316
|
+
/** Whether agents may request structured human input (enabled when unset). */
|
|
1317
|
+
export function resolveWorkspaceAgentHumanInputEnabled(settings: unknown): boolean {
|
|
1318
|
+
const parsed = WorkspaceSettingsSchema.safeParse(settings ?? {});
|
|
1319
|
+
return parsed.success ? parsed.data.agentHumanInputEnabled !== false : true;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1281
1322
|
/**
|
|
1282
1323
|
* Resolve whether voice input is enabled for a workspace.
|
|
1283
1324
|
*
|
|
@@ -1303,7 +1344,9 @@ export function resolveWorkspaceSlackReactionSummonSettings(
|
|
|
1303
1344
|
return {
|
|
1304
1345
|
enabled: DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS.enabled,
|
|
1305
1346
|
emoji: DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS.emoji,
|
|
1306
|
-
channelPolicy: {
|
|
1347
|
+
channelPolicy: {
|
|
1348
|
+
...DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS.channelPolicy,
|
|
1349
|
+
},
|
|
1307
1350
|
};
|
|
1308
1351
|
}
|
|
1309
1352
|
return configured.channelPolicy.mode === "allowlist"
|
|
@@ -1338,6 +1381,7 @@ export const UpdateWorkspaceSettingsRequest = z
|
|
|
1338
1381
|
transcription: WorkspaceTranscriptionPolicy.optional(),
|
|
1339
1382
|
maxNestedAgentDepth: NestedAgentDepthValue.nullable().optional(),
|
|
1340
1383
|
codexCompactionDefault: CodexCompactionMode.optional(),
|
|
1384
|
+
agentHumanInputEnabled: z.boolean().optional(),
|
|
1341
1385
|
slackReactionSummon: WorkspaceSlackReactionSummonSettings.optional(),
|
|
1342
1386
|
})
|
|
1343
1387
|
.passthrough();
|
|
@@ -1665,6 +1709,11 @@ export const EnrollmentBearerPayload = z.object({
|
|
|
1665
1709
|
workspaceId: z.string().uuid(),
|
|
1666
1710
|
agentId: z.string().uuid(),
|
|
1667
1711
|
enrollmentId: z.string().uuid(),
|
|
1712
|
+
// Backward-compatible credential-family fence. Generationless bearers minted
|
|
1713
|
+
// before migration 0061 parse ONLY as generation 1, matching the migration's
|
|
1714
|
+
// default for existing rows. signEnrollmentBearer serializes the parsed output,
|
|
1715
|
+
// so every newly signed bearer carries this claim explicitly.
|
|
1716
|
+
credentialGeneration: z.number().int().positive().default(1),
|
|
1668
1717
|
// The Account-scoped control-plane subject prefix the agent subscribes to.
|
|
1669
1718
|
subjectPrefix: z.string().min(1),
|
|
1670
1719
|
exp: z.number().int().positive(),
|
|
@@ -1699,7 +1748,13 @@ export async function verifyEnrollmentBearer(
|
|
|
1699
1748
|
if (!constantTimeEqual(signature, expected)) {
|
|
1700
1749
|
return null;
|
|
1701
1750
|
}
|
|
1702
|
-
|
|
1751
|
+
let decoded: unknown;
|
|
1752
|
+
try {
|
|
1753
|
+
decoded = JSON.parse(base64UrlDecode(encodedPayload));
|
|
1754
|
+
} catch {
|
|
1755
|
+
return null;
|
|
1756
|
+
}
|
|
1757
|
+
const payload = EnrollmentBearerPayload.safeParse(decoded);
|
|
1703
1758
|
if (!payload.success || payload.data.exp < nowSeconds) {
|
|
1704
1759
|
return null;
|
|
1705
1760
|
}
|
|
@@ -2506,13 +2561,6 @@ export type RunCredentialAuthNeeded = {
|
|
|
2506
2561
|
message?: string;
|
|
2507
2562
|
};
|
|
2508
2563
|
|
|
2509
|
-
export type RunCredentialRedaction = {
|
|
2510
|
-
/** Bounded diagnostic label used only in the replacement marker. */
|
|
2511
|
-
name: string;
|
|
2512
|
-
/** One atomic secret value that must be removed from streamed/audit output. */
|
|
2513
|
-
value: string;
|
|
2514
|
-
};
|
|
2515
|
-
|
|
2516
2564
|
export type RunCredentialsRequest = {
|
|
2517
2565
|
accountId: string;
|
|
2518
2566
|
workspaceId: string;
|
|
@@ -2558,12 +2606,6 @@ export type RunCredentialsResolution =
|
|
|
2558
2606
|
files?: RunCredentialFile[];
|
|
2559
2607
|
/** Environment name to one returned relative file path. */
|
|
2560
2608
|
fileEnvironment?: Record<string, string>;
|
|
2561
|
-
/**
|
|
2562
|
-
* Atomic sensitive values embedded inside credential files or derived
|
|
2563
|
-
* material. Environment values are registered automatically; hosts list
|
|
2564
|
-
* additional file-contained values here so chunked output is redacted.
|
|
2565
|
-
*/
|
|
2566
|
-
redactions?: RunCredentialRedaction[];
|
|
2567
2609
|
/** Earliest material expiry. Null/omitted uses a bounded refresh cadence. */
|
|
2568
2610
|
expiresAt?: string | null;
|
|
2569
2611
|
/** Partial degradation: usable material may coexist with reconnect notices. */
|
|
@@ -2955,6 +2997,93 @@ export function gitCredentialBindingIdForRepository(
|
|
|
2955
2997
|
);
|
|
2956
2998
|
}
|
|
2957
2999
|
|
|
3000
|
+
type GitRemotePathSemantics = "dot_git_alias" | "exact";
|
|
3001
|
+
|
|
3002
|
+
/**
|
|
3003
|
+
* Provider-declared remote-path behavior. Keeping this exhaustive makes a new
|
|
3004
|
+
* provider choose its semantics instead of inheriting GitHub conventions.
|
|
3005
|
+
*/
|
|
3006
|
+
const GIT_REMOTE_PATH_SEMANTICS = {
|
|
3007
|
+
github: "dot_git_alias",
|
|
3008
|
+
gitlab: "dot_git_alias",
|
|
3009
|
+
azure_devops: "exact",
|
|
3010
|
+
} as const satisfies Record<GitCredentialProvider, GitRemotePathSemantics>;
|
|
3011
|
+
|
|
3012
|
+
function gitRemotePathSemantics(
|
|
3013
|
+
provider: GitCredentialProvider | null | undefined,
|
|
3014
|
+
): GitRemotePathSemantics {
|
|
3015
|
+
return provider ? GIT_REMOTE_PATH_SEMANTICS[provider] : "exact";
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
export class RepositoryUriError extends Error {
|
|
3019
|
+
constructor(message: string) {
|
|
3020
|
+
super(message);
|
|
3021
|
+
this.name = "RepositoryUriError";
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
/**
|
|
3026
|
+
* Normalize only the safe, provider-neutral parts of an HTTPS clone URI.
|
|
3027
|
+
*
|
|
3028
|
+
* The provider-defined path is opaque: this helper never adds or removes a
|
|
3029
|
+
* `.git` suffix. Embedded user info, query parameters, and fragments are not
|
|
3030
|
+
* durable resource identity and are omitted, matching the existing secret-free
|
|
3031
|
+
* resource contract.
|
|
3032
|
+
*/
|
|
3033
|
+
export function normalizeRepositoryTransportUri(uri: string): string {
|
|
3034
|
+
let url: URL;
|
|
3035
|
+
try {
|
|
3036
|
+
url = new URL(uri.trim());
|
|
3037
|
+
} catch {
|
|
3038
|
+
throw new RepositoryUriError(`invalid repository URI: ${uri}`);
|
|
3039
|
+
}
|
|
3040
|
+
if (url.protocol !== "https:" || !url.hostname) {
|
|
3041
|
+
throw new RepositoryUriError("repository resources must use HTTPS Git URLs");
|
|
3042
|
+
}
|
|
3043
|
+
const path = url.pathname.replace(/^\/+|\/+$/g, "");
|
|
3044
|
+
if (path.split("/").filter(Boolean).length < 2) {
|
|
3045
|
+
throw new RepositoryUriError("repository URL must include owner and repo");
|
|
3046
|
+
}
|
|
3047
|
+
return `https://${url.host.toLowerCase()}/${path}`;
|
|
3048
|
+
}
|
|
3049
|
+
|
|
3050
|
+
/**
|
|
3051
|
+
* Return every URI spelling that a provider explicitly declares equivalent.
|
|
3052
|
+
* Exact-path and unqualified providers return only the normalized input URI.
|
|
3053
|
+
*/
|
|
3054
|
+
export function gitRemoteUriAliases(
|
|
3055
|
+
uri: string,
|
|
3056
|
+
provider: GitCredentialProvider | null | undefined,
|
|
3057
|
+
): string[] {
|
|
3058
|
+
const normalizedUri = normalizeRepositoryTransportUri(uri);
|
|
3059
|
+
if (gitRemotePathSemantics(provider) === "exact") {
|
|
3060
|
+
return [normalizedUri];
|
|
3061
|
+
}
|
|
3062
|
+
const base = normalizedUri.replace(/\.git$/, "");
|
|
3063
|
+
return [...new Set([normalizedUri, base, `${base}.git`])];
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
/** Stable remote identity for deduplication and credential-binding ownership. */
|
|
3067
|
+
export function gitRemoteIdentity(
|
|
3068
|
+
uri: string,
|
|
3069
|
+
provider: GitCredentialProvider | null | undefined,
|
|
3070
|
+
): string {
|
|
3071
|
+
const normalizedUri = normalizeRepositoryTransportUri(uri);
|
|
3072
|
+
return gitRemotePathSemantics(provider) === "dot_git_alias"
|
|
3073
|
+
? normalizedUri.replace(/\.git$/, "")
|
|
3074
|
+
: normalizedUri;
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
/** Provider-aware Git credential-helper path aliases, without a leading slash. */
|
|
3078
|
+
export function gitRemotePathAliases(
|
|
3079
|
+
uri: string,
|
|
3080
|
+
provider: GitCredentialProvider | null | undefined,
|
|
3081
|
+
): string[] {
|
|
3082
|
+
return gitRemoteUriAliases(uri, provider).map((alias) =>
|
|
3083
|
+
new URL(alias).pathname.replace(/^\/+|\/+$/g, ""),
|
|
3084
|
+
);
|
|
3085
|
+
}
|
|
3086
|
+
|
|
2958
3087
|
export const FileResourceRef = z.object({
|
|
2959
3088
|
kind: z.literal("file"),
|
|
2960
3089
|
fileId: z.string().uuid(),
|
|
@@ -3035,7 +3164,10 @@ export function resourceMountPathCollisionKey(path: string): string {
|
|
|
3035
3164
|
* GitLab, Azure DevOps, or a custom host do not collide. Encoding the host keeps
|
|
3036
3165
|
* IPv6/custom-port identities inside one portable path segment.
|
|
3037
3166
|
*/
|
|
3038
|
-
export function defaultRepositoryMountPath(
|
|
3167
|
+
export function defaultRepositoryMountPath(
|
|
3168
|
+
uri: string,
|
|
3169
|
+
provider?: GitCredentialProvider | null,
|
|
3170
|
+
): string {
|
|
3039
3171
|
let url: URL;
|
|
3040
3172
|
try {
|
|
3041
3173
|
url = new URL(uri);
|
|
@@ -3045,7 +3177,11 @@ export function defaultRepositoryMountPath(uri: string): string {
|
|
|
3045
3177
|
if (url.protocol !== "https:" || !url.host) {
|
|
3046
3178
|
throw new ResourceMountPathError(`invalid repository URI for mount path: ${uri}`);
|
|
3047
3179
|
}
|
|
3048
|
-
const
|
|
3180
|
+
const remotePath = url.pathname.replace(/^\/+|\/+$/g, "");
|
|
3181
|
+
const repositoryPath =
|
|
3182
|
+
gitRemotePathSemantics(provider) === "dot_git_alias"
|
|
3183
|
+
? remotePath.replace(/\.git$/, "")
|
|
3184
|
+
: remotePath;
|
|
3049
3185
|
const segments = repositoryPath.split("/").filter(Boolean);
|
|
3050
3186
|
if (segments.length < 2) {
|
|
3051
3187
|
throw new ResourceMountPathError(`repository URI must include owner and repo: ${uri}`);
|
|
@@ -3062,7 +3198,7 @@ export function resourceMountPath(resource: ResourceRef): string {
|
|
|
3062
3198
|
if (resource.mountPath) return normalizeResourceMountPath(resource.mountPath);
|
|
3063
3199
|
return resource.kind === "file"
|
|
3064
3200
|
? normalizeResourceMountPath(`${DEFAULT_FILE_RESOURCE_MOUNT_ROOT}/${resource.fileId}`)
|
|
3065
|
-
: defaultRepositoryMountPath(resource.uri);
|
|
3201
|
+
: defaultRepositoryMountPath(resource.uri, gitCredentialProviderForRepository(resource));
|
|
3066
3202
|
}
|
|
3067
3203
|
|
|
3068
3204
|
/** Fail before sandbox execution when two resources share a portable path. */
|
|
@@ -3753,7 +3889,10 @@ export function resourceIdentityKey(resource: ResourceRef): string {
|
|
|
3753
3889
|
if (resource.kind === "file") {
|
|
3754
3890
|
return `file:${resource.fileId}`;
|
|
3755
3891
|
}
|
|
3756
|
-
return `repository:${
|
|
3892
|
+
return `repository:${gitRemoteIdentity(
|
|
3893
|
+
resource.uri,
|
|
3894
|
+
gitCredentialProviderForRepository(resource),
|
|
3895
|
+
)}`;
|
|
3757
3896
|
}
|
|
3758
3897
|
|
|
3759
3898
|
function sortJson(value: unknown): unknown {
|
|
@@ -4310,6 +4449,7 @@ export const SessionAuthorizationOperation = z.enum([
|
|
|
4310
4449
|
"session.viewer.read",
|
|
4311
4450
|
"session.viewer.control",
|
|
4312
4451
|
"session.first_party_mcp.call",
|
|
4452
|
+
"session.secret.read",
|
|
4313
4453
|
"session.toolspace.call",
|
|
4314
4454
|
"session.pin.write",
|
|
4315
4455
|
"session.codex_account.write",
|
|
@@ -5031,9 +5171,9 @@ function withVariableSetIdAlias<T extends z.ZodRawShape>(shape: T) {
|
|
|
5031
5171
|
}, z.object(shape));
|
|
5032
5172
|
}
|
|
5033
5173
|
|
|
5034
|
-
//
|
|
5035
|
-
//
|
|
5036
|
-
//
|
|
5174
|
+
// Generic variable-set reads remain metadata-only. Exact plaintext has one
|
|
5175
|
+
// dedicated response schema so callers cannot accidentally widen another
|
|
5176
|
+
// workspace/session response with secret material.
|
|
5037
5177
|
export const VariableSetVariableMetadata = z.object({
|
|
5038
5178
|
name: VariableSetVariableName,
|
|
5039
5179
|
version: z.number().int().positive(),
|
|
@@ -5046,6 +5186,14 @@ export const WorkspaceEnvironmentVariableMetadata = VariableSetVariableMetadata;
|
|
|
5046
5186
|
/** @deprecated use VariableSetVariableMetadata */
|
|
5047
5187
|
export type WorkspaceEnvironmentVariableMetadata = VariableSetVariableMetadata;
|
|
5048
5188
|
|
|
5189
|
+
export const VariableSetSecret = z.object({
|
|
5190
|
+
variableSetId: z.string().uuid(),
|
|
5191
|
+
name: VariableSetVariableName,
|
|
5192
|
+
version: z.number().int().positive(),
|
|
5193
|
+
value: z.string(),
|
|
5194
|
+
});
|
|
5195
|
+
export type VariableSetSecret = z.infer<typeof VariableSetSecret>;
|
|
5196
|
+
|
|
5049
5197
|
export const VariableSet = z.object({
|
|
5050
5198
|
id: z.string().uuid(),
|
|
5051
5199
|
accountId: z.string().uuid(),
|
|
@@ -5247,7 +5395,11 @@ export type ScheduledTaskStatus = z.infer<typeof ScheduledTaskStatus>;
|
|
|
5247
5395
|
export const ScheduledTaskRunStatus = z.enum(["queued", "dispatched", "failed"]);
|
|
5248
5396
|
export type ScheduledTaskRunStatus = z.infer<typeof ScheduledTaskRunStatus>;
|
|
5249
5397
|
|
|
5250
|
-
export const ScheduledTaskRunMode = z.enum([
|
|
5398
|
+
export const ScheduledTaskRunMode = z.enum([
|
|
5399
|
+
"new_session_per_run",
|
|
5400
|
+
"reusable_session",
|
|
5401
|
+
"existing_session",
|
|
5402
|
+
]);
|
|
5251
5403
|
export type ScheduledTaskRunMode = z.infer<typeof ScheduledTaskRunMode>;
|
|
5252
5404
|
|
|
5253
5405
|
export const ScheduledTaskOverlapPolicy = z.enum(["allow_concurrent", "skip", "buffer_one"]);
|
|
@@ -5311,10 +5463,14 @@ export const ScheduledTask = z.object({
|
|
|
5311
5463
|
runMode: ScheduledTaskRunMode,
|
|
5312
5464
|
overlapPolicy: ScheduledTaskOverlapPolicy,
|
|
5313
5465
|
agentConfig: ScheduledTaskAgentConfig,
|
|
5314
|
-
createdBy: TurnInitiator.default({
|
|
5466
|
+
createdBy: TurnInitiator.default({
|
|
5467
|
+
kind: "service",
|
|
5468
|
+
subjectId: "unattributed-legacy",
|
|
5469
|
+
}),
|
|
5315
5470
|
createdByContext: TurnInitiatorContext.default({}),
|
|
5316
5471
|
personalConnections: z.array(McpPersonalConnectionSummary).default([]),
|
|
5317
5472
|
reusableSessionId: z.string().uuid().nullable(),
|
|
5473
|
+
targetSessionId: z.string().uuid().nullable().default(null),
|
|
5318
5474
|
variableSetId: z.string().uuid().nullable().default(null),
|
|
5319
5475
|
/** @deprecated use variableSetId */
|
|
5320
5476
|
environmentId: z.string().uuid().nullable().default(null),
|
|
@@ -5350,6 +5506,7 @@ export const CreateScheduledTaskRequest = withVariableSetIdAlias({
|
|
|
5350
5506
|
schedule: ScheduledTaskScheduleSpec,
|
|
5351
5507
|
runMode: ScheduledTaskRunMode.default("new_session_per_run"),
|
|
5352
5508
|
overlapPolicy: ScheduledTaskOverlapPolicy.default("allow_concurrent"),
|
|
5509
|
+
targetSessionId: z.string().uuid().nullable().optional(),
|
|
5353
5510
|
agentConfig: ScheduledTaskAgentConfig,
|
|
5354
5511
|
status: ScheduledTaskStatus.default("active"),
|
|
5355
5512
|
variableSetId: z.string().uuid().nullable().optional(),
|
|
@@ -5357,6 +5514,28 @@ export const CreateScheduledTaskRequest = withVariableSetIdAlias({
|
|
|
5357
5514
|
// The rig each run binds to (M3); its active version is resolved per fire.
|
|
5358
5515
|
rigId: z.string().uuid().nullable().optional(),
|
|
5359
5516
|
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
5517
|
+
}).superRefine((value, context) => {
|
|
5518
|
+
if (value.runMode === "existing_session" && !value.targetSessionId) {
|
|
5519
|
+
context.addIssue({
|
|
5520
|
+
code: "custom",
|
|
5521
|
+
path: ["targetSessionId"],
|
|
5522
|
+
message: "targetSessionId is required when runMode=existing_session",
|
|
5523
|
+
});
|
|
5524
|
+
}
|
|
5525
|
+
if (value.runMode !== "existing_session" && value.targetSessionId) {
|
|
5526
|
+
context.addIssue({
|
|
5527
|
+
code: "custom",
|
|
5528
|
+
path: ["targetSessionId"],
|
|
5529
|
+
message: "targetSessionId requires runMode=existing_session",
|
|
5530
|
+
});
|
|
5531
|
+
}
|
|
5532
|
+
if (value.runMode === "existing_session" && value.agentConfig.goal) {
|
|
5533
|
+
context.addIssue({
|
|
5534
|
+
code: "custom",
|
|
5535
|
+
path: ["agentConfig", "goal"],
|
|
5536
|
+
message: "agentConfig.goal cannot be used with an existing-session target",
|
|
5537
|
+
});
|
|
5538
|
+
}
|
|
5360
5539
|
});
|
|
5361
5540
|
export type CreateScheduledTaskRequest = z.infer<typeof CreateScheduledTaskRequest>;
|
|
5362
5541
|
|
|
@@ -5365,6 +5544,7 @@ export const UpdateScheduledTaskRequest = withVariableSetIdAlias({
|
|
|
5365
5544
|
schedule: ScheduledTaskScheduleSpec.optional(),
|
|
5366
5545
|
runMode: ScheduledTaskRunMode.optional(),
|
|
5367
5546
|
overlapPolicy: ScheduledTaskOverlapPolicy.optional(),
|
|
5547
|
+
targetSessionId: z.string().uuid().nullable().optional(),
|
|
5368
5548
|
agentConfig: ScheduledTaskAgentConfig.optional(),
|
|
5369
5549
|
status: ScheduledTaskStatus.optional(),
|
|
5370
5550
|
variableSetId: z.string().uuid().nullable().optional(),
|
|
@@ -5373,6 +5553,31 @@ export const UpdateScheduledTaskRequest = withVariableSetIdAlias({
|
|
|
5373
5553
|
// resolved per fire, so an update takes effect on the next dispatch.
|
|
5374
5554
|
rigId: z.string().uuid().nullable().optional(),
|
|
5375
5555
|
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
5556
|
+
}).superRefine((value, context) => {
|
|
5557
|
+
if (value.targetSessionId && value.runMode && value.runMode !== "existing_session") {
|
|
5558
|
+
context.addIssue({
|
|
5559
|
+
code: "custom",
|
|
5560
|
+
path: ["targetSessionId"],
|
|
5561
|
+
message: "targetSessionId requires runMode=existing_session",
|
|
5562
|
+
});
|
|
5563
|
+
}
|
|
5564
|
+
if (value.runMode === "existing_session" && value.targetSessionId === null) {
|
|
5565
|
+
context.addIssue({
|
|
5566
|
+
code: "custom",
|
|
5567
|
+
path: ["targetSessionId"],
|
|
5568
|
+
message: "targetSessionId cannot be null when runMode=existing_session",
|
|
5569
|
+
});
|
|
5570
|
+
}
|
|
5571
|
+
if (
|
|
5572
|
+
value.agentConfig?.goal &&
|
|
5573
|
+
(value.runMode === "existing_session" || Boolean(value.targetSessionId))
|
|
5574
|
+
) {
|
|
5575
|
+
context.addIssue({
|
|
5576
|
+
code: "custom",
|
|
5577
|
+
path: ["agentConfig", "goal"],
|
|
5578
|
+
message: "agentConfig.goal cannot be used with an existing-session target",
|
|
5579
|
+
});
|
|
5580
|
+
}
|
|
5376
5581
|
});
|
|
5377
5582
|
export type UpdateScheduledTaskRequest = z.infer<typeof UpdateScheduledTaskRequest>;
|
|
5378
5583
|
|
|
@@ -6253,9 +6458,9 @@ export const Session = z.object({
|
|
|
6253
6458
|
createIdempotencyKey: z.string().nullable(),
|
|
6254
6459
|
temporalWorkflowId: z.string().nullable(),
|
|
6255
6460
|
activeTurnId: z.string().uuid().nullable(),
|
|
6256
|
-
//
|
|
6257
|
-
//
|
|
6258
|
-
//
|
|
6461
|
+
// Provider-reported input tokens of the latest authoritative terminal
|
|
6462
|
+
// response. Null after a context transition or whenever that latest response
|
|
6463
|
+
// supplied no usable count, so an older response can never drive compaction.
|
|
6259
6464
|
lastInputTokens: z.number().int().nonnegative().nullable(),
|
|
6260
6465
|
queueVersion: z.number().int().nonnegative(),
|
|
6261
6466
|
queueHeadPosition: z.number().int(),
|
|
@@ -6859,8 +7064,8 @@ export const RecordingFailedPayload = z.object({
|
|
|
6859
7064
|
recordingId: z.string().uuid(),
|
|
6860
7065
|
turnId: z.string().uuid().nullable(),
|
|
6861
7066
|
reason: RecordingFailedReason,
|
|
6862
|
-
// ffmpeg
|
|
6863
|
-
//
|
|
7067
|
+
// Exact ffmpeg stderr/error detail. Event transport limits must reject or
|
|
7068
|
+
// paginate rather than rewriting this canonical diagnostic.
|
|
6864
7069
|
detail: z.string().nullable().optional(),
|
|
6865
7070
|
});
|
|
6866
7071
|
export type RecordingFailedPayload = z.infer<typeof RecordingFailedPayload>;
|
|
@@ -6988,6 +7193,18 @@ export const FsListResponse = z.object({
|
|
|
6988
7193
|
});
|
|
6989
7194
|
export type FsListResponse = z.infer<typeof FsListResponse>;
|
|
6990
7195
|
|
|
7196
|
+
/** Several independent directory listings served behind one Channel-A lease.
|
|
7197
|
+
* The response order exactly matches `requests`; callers can paint a root and
|
|
7198
|
+
* hydrate a bounded lazy-tree frontier without repeating provider attach work. */
|
|
7199
|
+
export const FsListBatchRequest = z.object({
|
|
7200
|
+
requests: z.array(FsListRequest).min(1).max(16),
|
|
7201
|
+
});
|
|
7202
|
+
export type FsListBatchRequest = z.infer<typeof FsListBatchRequest>;
|
|
7203
|
+
export const FsListBatchResponse = z.object({
|
|
7204
|
+
results: z.array(FsListResponse),
|
|
7205
|
+
});
|
|
7206
|
+
export type FsListBatchResponse = z.infer<typeof FsListBatchResponse>;
|
|
7207
|
+
|
|
6991
7208
|
export const FsEncoding = z.enum(["utf8", "base64"]);
|
|
6992
7209
|
export type FsEncoding = z.infer<typeof FsEncoding>;
|
|
6993
7210
|
export const FsReadRequest = z.object({
|
|
@@ -7156,6 +7373,27 @@ export const GitDiffResponse = z.object({
|
|
|
7156
7373
|
});
|
|
7157
7374
|
export type GitDiffResponse = z.infer<typeof GitDiffResponse>;
|
|
7158
7375
|
|
|
7376
|
+
/** One repository read unit: status metadata plus an optional comparison.
|
|
7377
|
+
* Multiple units execute behind one Channel-A lease and preserve input order. */
|
|
7378
|
+
export const GitReadBatchItemRequest = z.object({
|
|
7379
|
+
status: GitStatusRequest,
|
|
7380
|
+
diff: GitDiffRequest.optional(),
|
|
7381
|
+
});
|
|
7382
|
+
export type GitReadBatchItemRequest = z.infer<typeof GitReadBatchItemRequest>;
|
|
7383
|
+
export const GitReadBatchRequest = z.object({
|
|
7384
|
+
requests: z.array(GitReadBatchItemRequest).min(1).max(32),
|
|
7385
|
+
});
|
|
7386
|
+
export type GitReadBatchRequest = z.infer<typeof GitReadBatchRequest>;
|
|
7387
|
+
export const GitReadBatchItemResponse = z.object({
|
|
7388
|
+
status: GitStatusResponse,
|
|
7389
|
+
diff: GitDiffResponse.optional(),
|
|
7390
|
+
});
|
|
7391
|
+
export type GitReadBatchItemResponse = z.infer<typeof GitReadBatchItemResponse>;
|
|
7392
|
+
export const GitReadBatchResponse = z.object({
|
|
7393
|
+
results: z.array(GitReadBatchItemResponse),
|
|
7394
|
+
});
|
|
7395
|
+
export type GitReadBatchResponse = z.infer<typeof GitReadBatchResponse>;
|
|
7396
|
+
|
|
7159
7397
|
// ─── Workbench v2 turn-end workspace capture ────────────
|
|
7160
7398
|
// A capture is a point-in-time snapshot of the session workspace's CHANGES,
|
|
7161
7399
|
// probed live off the box at turn end (detectRepos → gitStatus/gitDiff → fsRead
|
|
@@ -7187,10 +7425,10 @@ export const WorkspaceCaptureFile = z.object({
|
|
|
7187
7425
|
});
|
|
7188
7426
|
export type WorkspaceCaptureFile = z.infer<typeof WorkspaceCaptureFile>;
|
|
7189
7427
|
|
|
7190
|
-
// One repo discovered in the workspace. `diff` is
|
|
7191
|
-
//
|
|
7192
|
-
//
|
|
7193
|
-
//
|
|
7428
|
+
// One repo discovered in the workspace. `diff` is the working/index surface vs
|
|
7429
|
+
// HEAD; `branchDiff`, when available, is the complete current branch vs the
|
|
7430
|
+
// remote default branch and therefore retains committed agent work. `status`
|
|
7431
|
+
// is the full porcelain file list. root "" = the workspace root repo.
|
|
7194
7432
|
export const WorkspaceCaptureRepo = z.object({
|
|
7195
7433
|
root: z.string(),
|
|
7196
7434
|
head: z.string().nullable(),
|
|
@@ -7200,6 +7438,7 @@ export const WorkspaceCaptureRepo = z.object({
|
|
|
7200
7438
|
behind: z.number().int().nonnegative().default(0),
|
|
7201
7439
|
status: z.array(GitFileStatus),
|
|
7202
7440
|
diff: z.array(GitFileDiff),
|
|
7441
|
+
branchDiff: z.array(GitFileDiff).optional(),
|
|
7203
7442
|
});
|
|
7204
7443
|
export type WorkspaceCaptureRepo = z.infer<typeof WorkspaceCaptureRepo>;
|
|
7205
7444
|
|
|
@@ -9263,9 +9502,26 @@ export type ListEnrollmentsResponse = z.infer<typeof ListEnrollmentsResponse>;
|
|
|
9263
9502
|
|
|
9264
9503
|
export const RevokeEnrollmentResponse = z.object({
|
|
9265
9504
|
revoked: z.boolean(),
|
|
9505
|
+
outcome: z.enum(["removed", "already_removed", "blocked"]),
|
|
9506
|
+
enrollmentId: z.string().uuid(),
|
|
9507
|
+
machineName: z.string().nullable(),
|
|
9508
|
+
lastSeenAt: z.string().datetime({ offset: true }).nullable(),
|
|
9509
|
+
revokedAt: z.string().datetime({ offset: true }).nullable(),
|
|
9510
|
+
code: z
|
|
9511
|
+
.enum(["active_route", "active_commands", "active_lease", "recovery_pending", "not_selfhosted"])
|
|
9512
|
+
.nullable(),
|
|
9513
|
+
message: z.string(),
|
|
9514
|
+
action: z.string(),
|
|
9266
9515
|
});
|
|
9267
9516
|
export type RevokeEnrollmentResponse = z.infer<typeof RevokeEnrollmentResponse>;
|
|
9268
9517
|
|
|
9518
|
+
/** POST /v1/workspaces/:workspaceId/enrollments/:id/revoke body. */
|
|
9519
|
+
export const RemoveEnrollmentRequest = z.object({
|
|
9520
|
+
expectedUpdatedAt: z.string().datetime({ offset: true }).optional(),
|
|
9521
|
+
idempotencyKey: z.string().trim().min(1).max(200).optional(),
|
|
9522
|
+
});
|
|
9523
|
+
export type RemoveEnrollmentRequest = z.infer<typeof RemoveEnrollmentRequest>;
|
|
9524
|
+
|
|
9269
9525
|
// =============================================================================
|
|
9270
9526
|
// Enrollment UX (self-hosted enrollment UX, design 11): the click-Grant approve
|
|
9271
9527
|
// page lookup/deny + the headless enroll-token mint/exchange. These sit beside the
|
|
@@ -9611,9 +9867,10 @@ export const TurnExecutionReasoningSourceV1 =
|
|
|
9611
9867
|
);
|
|
9612
9868
|
export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoningSourceV1>;
|
|
9613
9869
|
|
|
9614
|
-
export const TurnExecutionLatencyModeSourceV1 =
|
|
9615
|
-
|
|
9616
|
-
)
|
|
9870
|
+
export const TurnExecutionLatencyModeSourceV1 =
|
|
9871
|
+
/* @__PURE__ */ defineModelContractSchema(() =>
|
|
9872
|
+
z.enum(["explicit", "session", "deployment", "continuation"]),
|
|
9873
|
+
);
|
|
9617
9874
|
export type TurnExecutionLatencyModeSourceV1 = z.infer<typeof TurnExecutionLatencyModeSourceV1>;
|
|
9618
9875
|
|
|
9619
9876
|
/**
|
|
@@ -10078,7 +10335,6 @@ export function evaluateWorkspaceModelPolicy(
|
|
|
10078
10335
|
}
|
|
10079
10336
|
|
|
10080
10337
|
export * from "./codex-fleet-policy";
|
|
10081
|
-
export * from "./secret-redaction";
|
|
10082
10338
|
export * from "./workspace-instruction-policies";
|
|
10083
10339
|
export * from "./workspace-state";
|
|
10084
10340
|
export * from "./preference-registry";
|