@opengeni/contracts 0.2.0 → 0.4.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/index.d.ts +1962 -1
- package/dist/index.js +1560 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2028 -7
package/dist/index.js
CHANGED
|
@@ -8,7 +8,348 @@ var SessionStatus = z.enum([
|
|
|
8
8
|
"failed",
|
|
9
9
|
"cancelled"
|
|
10
10
|
]);
|
|
11
|
-
var SandboxBackend = z.enum([
|
|
11
|
+
var SandboxBackend = z.enum([
|
|
12
|
+
"docker",
|
|
13
|
+
"modal",
|
|
14
|
+
"local",
|
|
15
|
+
"none",
|
|
16
|
+
"daytona",
|
|
17
|
+
"runloop",
|
|
18
|
+
"e2b",
|
|
19
|
+
"blaxel",
|
|
20
|
+
"cloudflare",
|
|
21
|
+
"vercel",
|
|
22
|
+
"selfhosted"
|
|
23
|
+
]);
|
|
24
|
+
var SandboxOs = z.enum(["linux", "macos", "windows"]);
|
|
25
|
+
var SandboxCapabilityName = z.enum([
|
|
26
|
+
"FileSystem",
|
|
27
|
+
// Channel A: list/read/write/search (Pierre tree)
|
|
28
|
+
"Terminal",
|
|
29
|
+
// Channel A: command-output firehose (+ future pty-ws)
|
|
30
|
+
"Git",
|
|
31
|
+
// Channel A: status/diff/log/show (Pierre diff)
|
|
32
|
+
"DesktopStream",
|
|
33
|
+
// Channel B: noVNC pixels over a scoped tunnel URL
|
|
34
|
+
"Recording"
|
|
35
|
+
// ffmpeg x11grab -> object storage
|
|
36
|
+
]);
|
|
37
|
+
var DESKTOP_STREAM_PORT = 6080;
|
|
38
|
+
var TERMINAL_STREAM_PORT = 7681;
|
|
39
|
+
var CAPABILITY_DESCRIPTORS = {
|
|
40
|
+
modal: {
|
|
41
|
+
backend: "modal",
|
|
42
|
+
backendId: "modal",
|
|
43
|
+
tier: "desktop",
|
|
44
|
+
os: { supported: ["linux"], default: "linux" },
|
|
45
|
+
capabilities: {
|
|
46
|
+
FileSystem: { available: true, readOnly: false },
|
|
47
|
+
Terminal: { available: true, transport: "sse-events", pty: true },
|
|
48
|
+
Git: { available: true },
|
|
49
|
+
DesktopStream: { available: true, transport: "vnc-ws" },
|
|
50
|
+
Recording: { available: true }
|
|
51
|
+
},
|
|
52
|
+
lifetime: {
|
|
53
|
+
hardLifetimeMs: 24 * 60 * 60 * 1e3,
|
|
54
|
+
requiresSnapshotRollover: true,
|
|
55
|
+
hasIdleKiller: true,
|
|
56
|
+
supportsSuspendResume: true,
|
|
57
|
+
resumeIsLockFree: true
|
|
58
|
+
},
|
|
59
|
+
snapshot: { kind: "native-fs", hasTarFallback: true },
|
|
60
|
+
portExposure: { kind: "provider-tunnel", supportsOnDemandPorts: false },
|
|
61
|
+
// pre-declare 6080
|
|
62
|
+
workspaceRoot: "/workspace",
|
|
63
|
+
nativeBucketMount: true,
|
|
64
|
+
persistable: true,
|
|
65
|
+
supportsRunAs: true
|
|
66
|
+
},
|
|
67
|
+
daytona: {
|
|
68
|
+
backend: "daytona",
|
|
69
|
+
backendId: "daytona",
|
|
70
|
+
tier: "desktop",
|
|
71
|
+
os: { supported: ["linux"], default: "linux" },
|
|
72
|
+
capabilities: {
|
|
73
|
+
FileSystem: { available: true, readOnly: false },
|
|
74
|
+
Terminal: { available: true, transport: "sse-events", pty: true },
|
|
75
|
+
Git: { available: true },
|
|
76
|
+
DesktopStream: { available: true, transport: "vnc-ws" },
|
|
77
|
+
Recording: { available: true }
|
|
78
|
+
},
|
|
79
|
+
lifetime: {
|
|
80
|
+
requiresSnapshotRollover: false,
|
|
81
|
+
hasIdleKiller: true,
|
|
82
|
+
supportsSuspendResume: true,
|
|
83
|
+
resumeIsLockFree: false
|
|
84
|
+
},
|
|
85
|
+
snapshot: { kind: "native-snapshot-id", hasTarFallback: true },
|
|
86
|
+
portExposure: { kind: "preview-url", supportsOnDemandPorts: false },
|
|
87
|
+
workspaceRoot: "/workspace",
|
|
88
|
+
nativeBucketMount: false,
|
|
89
|
+
persistable: true,
|
|
90
|
+
supportsRunAs: true
|
|
91
|
+
},
|
|
92
|
+
runloop: {
|
|
93
|
+
backend: "runloop",
|
|
94
|
+
backendId: "runloop",
|
|
95
|
+
tier: "desktop",
|
|
96
|
+
os: { supported: ["linux"], default: "linux" },
|
|
97
|
+
capabilities: {
|
|
98
|
+
FileSystem: { available: true, readOnly: false },
|
|
99
|
+
Terminal: { available: true, transport: "sse-events", pty: false },
|
|
100
|
+
Git: { available: true },
|
|
101
|
+
DesktopStream: { available: true, transport: "vnc-ws" },
|
|
102
|
+
Recording: { available: true }
|
|
103
|
+
},
|
|
104
|
+
lifetime: {
|
|
105
|
+
requiresSnapshotRollover: false,
|
|
106
|
+
hasIdleKiller: true,
|
|
107
|
+
supportsSuspendResume: true,
|
|
108
|
+
resumeIsLockFree: false
|
|
109
|
+
},
|
|
110
|
+
snapshot: { kind: "native-snapshot-id", hasTarFallback: true },
|
|
111
|
+
portExposure: { kind: "provider-tunnel", supportsOnDemandPorts: false },
|
|
112
|
+
// CR9: pre-declare 6080
|
|
113
|
+
workspaceRoot: "/workspace",
|
|
114
|
+
nativeBucketMount: false,
|
|
115
|
+
persistable: true,
|
|
116
|
+
supportsRunAs: false
|
|
117
|
+
},
|
|
118
|
+
e2b: {
|
|
119
|
+
backend: "e2b",
|
|
120
|
+
backendId: "e2b",
|
|
121
|
+
tier: "desktop",
|
|
122
|
+
os: { supported: ["linux"], default: "linux" },
|
|
123
|
+
capabilities: {
|
|
124
|
+
FileSystem: { available: true, readOnly: false },
|
|
125
|
+
Terminal: { available: true, transport: "sse-events", pty: false },
|
|
126
|
+
// pty-until-proven=no
|
|
127
|
+
Git: { available: true },
|
|
128
|
+
DesktopStream: { available: true, transport: "vnc-ws" },
|
|
129
|
+
Recording: { available: true }
|
|
130
|
+
},
|
|
131
|
+
lifetime: {
|
|
132
|
+
requiresSnapshotRollover: false,
|
|
133
|
+
hasIdleKiller: true,
|
|
134
|
+
supportsSuspendResume: true,
|
|
135
|
+
resumeIsLockFree: false
|
|
136
|
+
},
|
|
137
|
+
snapshot: { kind: "native-snapshot-id", hasTarFallback: true },
|
|
138
|
+
portExposure: { kind: "preview-url", supportsOnDemandPorts: false },
|
|
139
|
+
workspaceRoot: "/home/user",
|
|
140
|
+
nativeBucketMount: false,
|
|
141
|
+
persistable: true,
|
|
142
|
+
supportsRunAs: false
|
|
143
|
+
},
|
|
144
|
+
blaxel: {
|
|
145
|
+
backend: "blaxel",
|
|
146
|
+
backendId: "blaxel",
|
|
147
|
+
tier: "desktop",
|
|
148
|
+
os: { supported: ["linux"], default: "linux" },
|
|
149
|
+
capabilities: {
|
|
150
|
+
FileSystem: { available: true, readOnly: false },
|
|
151
|
+
Terminal: { available: true, transport: "sse-events", pty: false },
|
|
152
|
+
// pty-until-proven=no
|
|
153
|
+
Git: { available: true },
|
|
154
|
+
DesktopStream: { available: true, transport: "vnc-ws" },
|
|
155
|
+
Recording: { available: true }
|
|
156
|
+
},
|
|
157
|
+
lifetime: {
|
|
158
|
+
requiresSnapshotRollover: false,
|
|
159
|
+
hasIdleKiller: true,
|
|
160
|
+
supportsSuspendResume: false,
|
|
161
|
+
resumeIsLockFree: false
|
|
162
|
+
},
|
|
163
|
+
snapshot: { kind: "tar-only", hasTarFallback: true },
|
|
164
|
+
portExposure: { kind: "provider-tunnel", supportsOnDemandPorts: true },
|
|
165
|
+
// only on-demand backend
|
|
166
|
+
workspaceRoot: "/workspace",
|
|
167
|
+
nativeBucketMount: false,
|
|
168
|
+
persistable: true,
|
|
169
|
+
supportsRunAs: false
|
|
170
|
+
},
|
|
171
|
+
cloudflare: {
|
|
172
|
+
backend: "cloudflare",
|
|
173
|
+
backendId: "cloudflare",
|
|
174
|
+
tier: "headless",
|
|
175
|
+
os: { supported: ["linux"], default: "linux" },
|
|
176
|
+
capabilities: {
|
|
177
|
+
FileSystem: { available: true, readOnly: false },
|
|
178
|
+
Terminal: { available: true, transport: "sse-events", pty: true },
|
|
179
|
+
Git: { available: true },
|
|
180
|
+
DesktopStream: { available: false, transport: null },
|
|
181
|
+
Recording: { available: false }
|
|
182
|
+
},
|
|
183
|
+
lifetime: {
|
|
184
|
+
requiresSnapshotRollover: false,
|
|
185
|
+
hasIdleKiller: true,
|
|
186
|
+
supportsSuspendResume: false,
|
|
187
|
+
resumeIsLockFree: false
|
|
188
|
+
},
|
|
189
|
+
snapshot: { kind: "tar-only", hasTarFallback: true },
|
|
190
|
+
portExposure: { kind: "provider-tunnel", supportsOnDemandPorts: false },
|
|
191
|
+
workspaceRoot: "/workspace",
|
|
192
|
+
nativeBucketMount: false,
|
|
193
|
+
persistable: true,
|
|
194
|
+
supportsRunAs: true
|
|
195
|
+
},
|
|
196
|
+
vercel: {
|
|
197
|
+
backend: "vercel",
|
|
198
|
+
backendId: "vercel",
|
|
199
|
+
tier: "headless",
|
|
200
|
+
os: { supported: ["linux"], default: "linux" },
|
|
201
|
+
capabilities: {
|
|
202
|
+
FileSystem: { available: true, readOnly: false },
|
|
203
|
+
Terminal: { available: true, transport: "sse-events", pty: false },
|
|
204
|
+
Git: { available: true },
|
|
205
|
+
DesktopStream: { available: false, transport: null },
|
|
206
|
+
Recording: { available: false }
|
|
207
|
+
},
|
|
208
|
+
lifetime: {
|
|
209
|
+
hardLifetimeMs: 5 * 60 * 60 * 1e3,
|
|
210
|
+
requiresSnapshotRollover: true,
|
|
211
|
+
hasIdleKiller: true,
|
|
212
|
+
supportsSuspendResume: true,
|
|
213
|
+
resumeIsLockFree: false
|
|
214
|
+
},
|
|
215
|
+
snapshot: { kind: "tar-only", hasTarFallback: true },
|
|
216
|
+
portExposure: { kind: "preview-url", supportsOnDemandPorts: false },
|
|
217
|
+
workspaceRoot: "/vercel/sandbox",
|
|
218
|
+
nativeBucketMount: false,
|
|
219
|
+
persistable: true,
|
|
220
|
+
supportsRunAs: false
|
|
221
|
+
},
|
|
222
|
+
docker: {
|
|
223
|
+
backend: "docker",
|
|
224
|
+
backendId: "docker",
|
|
225
|
+
tier: "dev",
|
|
226
|
+
os: { supported: ["linux"], default: "linux" },
|
|
227
|
+
capabilities: {
|
|
228
|
+
FileSystem: { available: true, readOnly: false },
|
|
229
|
+
Terminal: { available: true, transport: "sse-events", pty: true },
|
|
230
|
+
Git: { available: true },
|
|
231
|
+
DesktopStream: { available: false, transport: null },
|
|
232
|
+
// local
|
|
233
|
+
Recording: { available: false }
|
|
234
|
+
},
|
|
235
|
+
lifetime: {
|
|
236
|
+
requiresSnapshotRollover: false,
|
|
237
|
+
hasIdleKiller: false,
|
|
238
|
+
supportsSuspendResume: false,
|
|
239
|
+
resumeIsLockFree: true
|
|
240
|
+
},
|
|
241
|
+
snapshot: { kind: "native-dir", hasTarFallback: true },
|
|
242
|
+
portExposure: { kind: "local-port", supportsOnDemandPorts: false },
|
|
243
|
+
workspaceRoot: "/workspace",
|
|
244
|
+
nativeBucketMount: false,
|
|
245
|
+
persistable: true,
|
|
246
|
+
supportsRunAs: true
|
|
247
|
+
},
|
|
248
|
+
local: {
|
|
249
|
+
backend: "local",
|
|
250
|
+
// The SDK's UnixLocalSandboxClient reports backendId "unix_local" — this MUST
|
|
251
|
+
// match it (it is the resume-fence field compared against client.backendId).
|
|
252
|
+
backendId: "unix_local",
|
|
253
|
+
tier: "dev",
|
|
254
|
+
os: { supported: ["linux"], default: "linux" },
|
|
255
|
+
capabilities: {
|
|
256
|
+
FileSystem: { available: true, readOnly: false },
|
|
257
|
+
Terminal: { available: true, transport: "sse-events", pty: true },
|
|
258
|
+
Git: { available: true },
|
|
259
|
+
DesktopStream: { available: false, transport: null },
|
|
260
|
+
Recording: { available: false }
|
|
261
|
+
},
|
|
262
|
+
lifetime: {
|
|
263
|
+
requiresSnapshotRollover: false,
|
|
264
|
+
hasIdleKiller: false,
|
|
265
|
+
supportsSuspendResume: false,
|
|
266
|
+
resumeIsLockFree: true
|
|
267
|
+
},
|
|
268
|
+
snapshot: { kind: "native-dir", hasTarFallback: true },
|
|
269
|
+
portExposure: { kind: "local-port", supportsOnDemandPorts: false },
|
|
270
|
+
workspaceRoot: "/workspace",
|
|
271
|
+
nativeBucketMount: false,
|
|
272
|
+
persistable: false,
|
|
273
|
+
supportsRunAs: false
|
|
274
|
+
},
|
|
275
|
+
none: {
|
|
276
|
+
backend: "none",
|
|
277
|
+
backendId: "none",
|
|
278
|
+
tier: "none",
|
|
279
|
+
os: { supported: ["linux"], default: "linux" },
|
|
280
|
+
capabilities: {
|
|
281
|
+
FileSystem: { available: false, readOnly: true },
|
|
282
|
+
Terminal: { available: false, transport: null, pty: false },
|
|
283
|
+
Git: { available: false },
|
|
284
|
+
DesktopStream: { available: false, transport: null },
|
|
285
|
+
Recording: { available: false }
|
|
286
|
+
},
|
|
287
|
+
lifetime: {
|
|
288
|
+
requiresSnapshotRollover: false,
|
|
289
|
+
hasIdleKiller: false,
|
|
290
|
+
supportsSuspendResume: false,
|
|
291
|
+
resumeIsLockFree: true
|
|
292
|
+
},
|
|
293
|
+
snapshot: { kind: "none", hasTarFallback: false },
|
|
294
|
+
portExposure: { kind: "none", supportsOnDemandPorts: false },
|
|
295
|
+
workspaceRoot: "/workspace",
|
|
296
|
+
nativeBucketMount: false,
|
|
297
|
+
persistable: false,
|
|
298
|
+
supportsRunAs: false
|
|
299
|
+
},
|
|
300
|
+
// Bring-your-own-compute: the user's OWN machine, enrolled via a Rust agent,
|
|
301
|
+
// becomes ONE shared whole-machine sandbox (the agent IS the box). It is the
|
|
302
|
+
// first backend to make macOS/Windows reachable (default linux). Desktop is
|
|
303
|
+
// capability-PROCLAIMED ("vnc-ws") — the agent serves a native display stack
|
|
304
|
+
// (Linux X11/Xvfb, macOS CGEvent/ScreenCaptureKit) consent-gated at enroll;
|
|
305
|
+
// the online/offline/consent/display negotiation lives in select.ts (M3), this
|
|
306
|
+
// row is the static feasibility ceiling. Always-on (process-lifetime, never
|
|
307
|
+
// idle-reaped) and NOT persistable — OpenGeni cannot snapshot the user's disk,
|
|
308
|
+
// so resume = "is the agent's subject live?", never a cold re-create. Ports
|
|
309
|
+
// surface on-demand through the stateless relay edge, which lands behind the
|
|
310
|
+
// `resolveExposedPort` swap-seam later; until then it reuses the existing
|
|
311
|
+
// `provider-tunnel` exposure kind (the relay IS the provider tunnel for the
|
|
312
|
+
// agent) so no new PortExposureKind literal — and no new switch arms — are
|
|
313
|
+
// introduced. supportsOnDemandPorts:true: the agent opens a stream channel for
|
|
314
|
+
// a port on request rather than pre-declaring 6080/7681 at construction.
|
|
315
|
+
selfhosted: {
|
|
316
|
+
backend: "selfhosted",
|
|
317
|
+
backendId: "selfhosted",
|
|
318
|
+
tier: "desktop",
|
|
319
|
+
os: { supported: ["linux", "macos", "windows"], default: "linux" },
|
|
320
|
+
capabilities: {
|
|
321
|
+
FileSystem: { available: true, readOnly: false },
|
|
322
|
+
Terminal: { available: true, transport: "pty-ws", pty: true },
|
|
323
|
+
// real PTY over the relay
|
|
324
|
+
Git: { available: true },
|
|
325
|
+
DesktopStream: { available: true, transport: "vnc-ws" },
|
|
326
|
+
// proclaimed; consent-gated at enroll
|
|
327
|
+
Recording: { available: true }
|
|
328
|
+
// boot invariant: == DesktopStream.available
|
|
329
|
+
},
|
|
330
|
+
lifetime: {
|
|
331
|
+
// Whole-machine, always-there: online while the agent process runs, offline
|
|
332
|
+
// when it stops. The lease is NEVER idle-killed (it's the user's machine,
|
|
333
|
+
// not a reapable cloud box) and there is nothing to suspend/resume — the
|
|
334
|
+
// machine simply is or isn't reachable.
|
|
335
|
+
requiresSnapshotRollover: false,
|
|
336
|
+
hasIdleKiller: false,
|
|
337
|
+
supportsSuspendResume: false,
|
|
338
|
+
resumeIsLockFree: true
|
|
339
|
+
// resume = address the live NATS subject; no provider lock
|
|
340
|
+
},
|
|
341
|
+
// persistable:false forces snapshot.kind:"none" (the descriptor invariant
|
|
342
|
+
// `persistable ⇒ snapshot.kind!=="none"`): OpenGeni cannot snapshot the
|
|
343
|
+
// user's disk — the machine itself is the persistence.
|
|
344
|
+
snapshot: { kind: "none", hasTarFallback: false },
|
|
345
|
+
portExposure: { kind: "provider-tunnel", supportsOnDemandPorts: true },
|
|
346
|
+
workspaceRoot: "/",
|
|
347
|
+
// agent-reported machine root (the whole machine is the sandbox)
|
|
348
|
+
nativeBucketMount: false,
|
|
349
|
+
persistable: false,
|
|
350
|
+
supportsRunAs: false
|
|
351
|
+
}
|
|
352
|
+
};
|
|
12
353
|
var ReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh"]);
|
|
13
354
|
var ErrorCode = z.enum([
|
|
14
355
|
"unauthenticated",
|
|
@@ -53,8 +394,28 @@ var Permission = z.enum([
|
|
|
53
394
|
"sessions:create",
|
|
54
395
|
"sessions:read",
|
|
55
396
|
"sessions:control",
|
|
397
|
+
// Sandbox-surfacing (master-spine §C.3 / crosscut PART 1.2). stream:view is a
|
|
398
|
+
// REAL, distinct permission — strictly BROADER than sessions:read — because the
|
|
399
|
+
// pixel plane (Channel B) is UN-REDACTED: a viewer of raw pixels can see cloud
|
|
400
|
+
// creds the agent cat's into a terminal, which the redacted Channel-A event log
|
|
401
|
+
// never exposes. sessions:read is NOT permission to watch raw pixels.
|
|
402
|
+
"stream:view",
|
|
403
|
+
// SEPARATE from stream:view: raw input to the desktop (bypasses approvalQueue /
|
|
404
|
+
// interrupt). NEVER granted by default in v1 (the input plane is OFF —
|
|
405
|
+
// streamControlEnabled=false); the permission exists so later hardening is a
|
|
406
|
+
// flag flip, not a redesign.
|
|
407
|
+
"stream:control",
|
|
408
|
+
// Accept the pixel-plane secret-leak acknowledgment (consent gate before the
|
|
409
|
+
// un-redacted desktop URL is handed out).
|
|
410
|
+
"stream:acknowledge",
|
|
56
411
|
"files:upload",
|
|
57
412
|
"files:read",
|
|
413
|
+
// Channel-A structured write surface (FS writes / apply-patch); distinct from
|
|
414
|
+
// files:read so a read-only viewer can't mutate the box filesystem.
|
|
415
|
+
"files:write",
|
|
416
|
+
// Attach to an interactive PTY (terminal-as-pty, Channel A); distinct from
|
|
417
|
+
// sessions:read which only reads the command-output firehose.
|
|
418
|
+
"terminal:attach",
|
|
58
419
|
"documents:manage",
|
|
59
420
|
"documents:search",
|
|
60
421
|
"scheduled_tasks:manage",
|
|
@@ -64,7 +425,14 @@ var Permission = z.enum([
|
|
|
64
425
|
"api_keys:manage",
|
|
65
426
|
"environments:manage",
|
|
66
427
|
"environments:use",
|
|
67
|
-
"goals:manage"
|
|
428
|
+
"goals:manage",
|
|
429
|
+
// Bring-your-own-compute (M5). enrollments:read lists a workspace's machines;
|
|
430
|
+
// enrollments:manage approves a device-flow enrollment (the LOUD whole-machine
|
|
431
|
+
// consent) + revokes a machine. Distinct from sessions/stream perms because an
|
|
432
|
+
// enrollment grants WHOLE-MACHINE access to a user's own hardware — a high-trust,
|
|
433
|
+
// admin-shaped action. workspace:admin is the super-wildcard over both.
|
|
434
|
+
"enrollments:read",
|
|
435
|
+
"enrollments:manage"
|
|
68
436
|
]);
|
|
69
437
|
var ProductAccessMode = z.enum(["local", "configured", "managed"]);
|
|
70
438
|
var BillingMode = z.enum(["disabled", "stripe"]);
|
|
@@ -157,6 +525,172 @@ async function verifyDelegatedAccessToken(secret, token, nowSeconds = Math.floor
|
|
|
157
525
|
}
|
|
158
526
|
return payload.data;
|
|
159
527
|
}
|
|
528
|
+
var EnrollmentBearerPayload = z.object({
|
|
529
|
+
workspaceId: z.string().uuid(),
|
|
530
|
+
agentId: z.string().uuid(),
|
|
531
|
+
enrollmentId: z.string().uuid(),
|
|
532
|
+
// The Account-scoped control-plane subject prefix the agent subscribes to.
|
|
533
|
+
subjectPrefix: z.string().min(1),
|
|
534
|
+
exp: z.number().int().positive()
|
|
535
|
+
});
|
|
536
|
+
async function signEnrollmentBearer(secret, payload) {
|
|
537
|
+
const encodedPayload = base64UrlEncode(JSON.stringify(EnrollmentBearerPayload.parse(payload)));
|
|
538
|
+
const signature = await hmacSha256Base64Url(secret, encodedPayload);
|
|
539
|
+
return `oge_${encodedPayload}.${signature}`;
|
|
540
|
+
}
|
|
541
|
+
async function verifyEnrollmentBearer(secret, token, nowSeconds = Math.floor(Date.now() / 1e3)) {
|
|
542
|
+
if (!token.startsWith("oge_")) {
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
const withoutPrefix = token.slice("oge_".length);
|
|
546
|
+
const dot = withoutPrefix.lastIndexOf(".");
|
|
547
|
+
if (dot <= 0) {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
const encodedPayload = withoutPrefix.slice(0, dot);
|
|
551
|
+
const signature = withoutPrefix.slice(dot + 1);
|
|
552
|
+
const expected = await hmacSha256Base64Url(secret, encodedPayload);
|
|
553
|
+
if (!constantTimeEqual(signature, expected)) {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
const payload = EnrollmentBearerPayload.safeParse(JSON.parse(base64UrlDecode(encodedPayload)));
|
|
557
|
+
if (!payload.success || payload.data.exp < nowSeconds) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
return payload.data;
|
|
561
|
+
}
|
|
562
|
+
var EnrollTokenPayload = z.object({
|
|
563
|
+
// Domain-separation claim — fixed "enroll" so an `oge_`/`ogd_`/`ogs_` payload (no
|
|
564
|
+
// typ, or a different typ) can never satisfy verifyEnrollToken even past the prefix.
|
|
565
|
+
typ: z.literal("enroll"),
|
|
566
|
+
workspaceId: z.string().uuid(),
|
|
567
|
+
accountId: z.string().uuid(),
|
|
568
|
+
// The screen-control consent baked into the token at mint (the minting user's
|
|
569
|
+
// decision); the exchange records it as consentedScreenControl on the enrollment.
|
|
570
|
+
allowScreenControl: z.boolean(),
|
|
571
|
+
iat: z.number().int().nonnegative(),
|
|
572
|
+
exp: z.number().int().positive()
|
|
573
|
+
});
|
|
574
|
+
async function signEnrollToken(secret, payload) {
|
|
575
|
+
const encodedPayload = base64UrlEncode(JSON.stringify(EnrollTokenPayload.parse(payload)));
|
|
576
|
+
const signature = await hmacSha256Base64Url(secret, encodedPayload);
|
|
577
|
+
return `oget_${encodedPayload}.${signature}`;
|
|
578
|
+
}
|
|
579
|
+
async function verifyEnrollToken(secret, token, nowSeconds = Math.floor(Date.now() / 1e3)) {
|
|
580
|
+
if (!token.startsWith("oget_")) {
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
const withoutPrefix = token.slice("oget_".length);
|
|
584
|
+
const dot = withoutPrefix.lastIndexOf(".");
|
|
585
|
+
if (dot <= 0) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
const encodedPayload = withoutPrefix.slice(0, dot);
|
|
589
|
+
const signature = withoutPrefix.slice(dot + 1);
|
|
590
|
+
const expected = await hmacSha256Base64Url(secret, encodedPayload);
|
|
591
|
+
if (!constantTimeEqual(signature, expected)) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
let decoded;
|
|
595
|
+
try {
|
|
596
|
+
decoded = JSON.parse(base64UrlDecode(encodedPayload));
|
|
597
|
+
} catch {
|
|
598
|
+
return null;
|
|
599
|
+
}
|
|
600
|
+
const payload = EnrollTokenPayload.safeParse(decoded);
|
|
601
|
+
if (!payload.success || payload.data.exp < nowSeconds) {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
return payload.data;
|
|
605
|
+
}
|
|
606
|
+
var StreamTokenPayload = z.object({
|
|
607
|
+
workspaceId: z.string().uuid(),
|
|
608
|
+
sessionId: z.string().uuid(),
|
|
609
|
+
// Identifies the sandbox_lease_holders row (the viewer holder).
|
|
610
|
+
viewerId: z.string().uuid(),
|
|
611
|
+
// Fence: the token logically dies when the box is re-elected (epoch++).
|
|
612
|
+
leaseEpoch: z.number().int().nonnegative(),
|
|
613
|
+
// v1 is always "view"; "control" is the never-granted raw-input plane.
|
|
614
|
+
mode: z.enum(["view", "control"]),
|
|
615
|
+
// 6080 (noVNC); pins the token to ONE exposed port.
|
|
616
|
+
port: z.number().int().positive(),
|
|
617
|
+
// Short TTL (120s default); rotation is event-driven under the epoch fence,
|
|
618
|
+
// not on a keepalive clock.
|
|
619
|
+
exp: z.number().int().positive()
|
|
620
|
+
});
|
|
621
|
+
async function signStreamToken(secret, payload) {
|
|
622
|
+
const encodedPayload = base64UrlEncode(JSON.stringify(StreamTokenPayload.parse(payload)));
|
|
623
|
+
const signature = await hmacSha256Base64Url(secret, encodedPayload);
|
|
624
|
+
return `ogs_${encodedPayload}.${signature}`;
|
|
625
|
+
}
|
|
626
|
+
async function verifyStreamToken(secret, token, nowSeconds = Math.floor(Date.now() / 1e3)) {
|
|
627
|
+
if (!token.startsWith("ogs_")) {
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
const withoutPrefix = token.slice("ogs_".length);
|
|
631
|
+
const dot = withoutPrefix.lastIndexOf(".");
|
|
632
|
+
if (dot <= 0) {
|
|
633
|
+
return null;
|
|
634
|
+
}
|
|
635
|
+
const encodedPayload = withoutPrefix.slice(0, dot);
|
|
636
|
+
const signature = withoutPrefix.slice(dot + 1);
|
|
637
|
+
const expected = await hmacSha256Base64Url(secret, encodedPayload);
|
|
638
|
+
if (!constantTimeEqual(signature, expected)) {
|
|
639
|
+
return null;
|
|
640
|
+
}
|
|
641
|
+
let decoded;
|
|
642
|
+
try {
|
|
643
|
+
decoded = JSON.parse(base64UrlDecode(encodedPayload));
|
|
644
|
+
} catch {
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
const payload = StreamTokenPayload.safeParse(decoded);
|
|
648
|
+
if (!payload.success || payload.data.exp < nowSeconds) {
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
return payload.data;
|
|
652
|
+
}
|
|
653
|
+
var RelayTokenPayload = z.object({
|
|
654
|
+
// The workspace the agent (and its channels) belong to — the relay asserts this
|
|
655
|
+
// equals the channel-key's ws so a producer can only register its own channels.
|
|
656
|
+
workspaceId: z.string().uuid(),
|
|
657
|
+
// The agent (machine) id — the relay asserts this equals the channel-key's agent.
|
|
658
|
+
agentId: z.string().uuid(),
|
|
659
|
+
// Expiry (unix seconds). Enrollment-scoped horizon (re-minted on re-enroll).
|
|
660
|
+
exp: z.number().int().positive()
|
|
661
|
+
});
|
|
662
|
+
async function signRelayToken(secret, payload) {
|
|
663
|
+
const encodedPayload = base64UrlEncode(JSON.stringify(RelayTokenPayload.parse(payload)));
|
|
664
|
+
const signature = await hmacSha256Base64Url(secret, encodedPayload);
|
|
665
|
+
return `ogr_${encodedPayload}.${signature}`;
|
|
666
|
+
}
|
|
667
|
+
async function verifyRelayToken(secret, token, nowSeconds = Math.floor(Date.now() / 1e3)) {
|
|
668
|
+
if (!token.startsWith("ogr_")) {
|
|
669
|
+
return null;
|
|
670
|
+
}
|
|
671
|
+
const withoutPrefix = token.slice("ogr_".length);
|
|
672
|
+
const dot = withoutPrefix.lastIndexOf(".");
|
|
673
|
+
if (dot <= 0) {
|
|
674
|
+
return null;
|
|
675
|
+
}
|
|
676
|
+
const encodedPayload = withoutPrefix.slice(0, dot);
|
|
677
|
+
const signature = withoutPrefix.slice(dot + 1);
|
|
678
|
+
const expected = await hmacSha256Base64Url(secret, encodedPayload);
|
|
679
|
+
if (!constantTimeEqual(signature, expected)) {
|
|
680
|
+
return null;
|
|
681
|
+
}
|
|
682
|
+
let decoded;
|
|
683
|
+
try {
|
|
684
|
+
decoded = JSON.parse(base64UrlDecode(encodedPayload));
|
|
685
|
+
} catch {
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
const payload = RelayTokenPayload.safeParse(decoded);
|
|
689
|
+
if (!payload.success || payload.data.exp < nowSeconds) {
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
return payload.data;
|
|
693
|
+
}
|
|
160
694
|
var CreateWorkspaceRequest = z.object({
|
|
161
695
|
accountId: z.string().uuid().optional(),
|
|
162
696
|
name: z.string().min(1),
|
|
@@ -197,6 +731,27 @@ var CreateApiKeyResponse = z.object({
|
|
|
197
731
|
apiKey: ApiKey,
|
|
198
732
|
token: z.string().min(1)
|
|
199
733
|
});
|
|
734
|
+
var WorkspaceMember = z.object({
|
|
735
|
+
subjectId: z.string().min(1),
|
|
736
|
+
subjectLabel: z.string().nullable(),
|
|
737
|
+
role: z.string(),
|
|
738
|
+
permissions: z.array(Permission),
|
|
739
|
+
createdAt: z.string()
|
|
740
|
+
});
|
|
741
|
+
var ListWorkspaceMembersResponse = z.object({
|
|
742
|
+
members: z.array(WorkspaceMember)
|
|
743
|
+
});
|
|
744
|
+
var AddWorkspaceMemberRequest = z.object({
|
|
745
|
+
// Resolved against the managed (Better Auth) users; email invites for
|
|
746
|
+
// not-yet-registered users are deferred, so an unknown email returns 404.
|
|
747
|
+
email: z.string().email(),
|
|
748
|
+
role: z.string().min(1).optional(),
|
|
749
|
+
permissions: z.array(Permission)
|
|
750
|
+
});
|
|
751
|
+
var UpdateWorkspaceMemberRequest = z.object({
|
|
752
|
+
role: z.string().min(1).optional(),
|
|
753
|
+
permissions: z.array(Permission)
|
|
754
|
+
});
|
|
200
755
|
var UsageEventType = z.enum([
|
|
201
756
|
"agent_run.created",
|
|
202
757
|
"agent_run.completed",
|
|
@@ -206,7 +761,16 @@ var UsageEventType = z.enum([
|
|
|
206
761
|
"file.deleted",
|
|
207
762
|
"document.indexed",
|
|
208
763
|
"scheduled_task.fired",
|
|
209
|
-
"api_key.request"
|
|
764
|
+
"api_key.request",
|
|
765
|
+
// --- sandbox warm-time metering (P2.1) ---
|
|
766
|
+
// Wall-clock seconds a box was warm — the billable warm-time meter. Accrued on
|
|
767
|
+
// the two stateless ticks (turn heartbeat + reaper sweep), idempotent on
|
|
768
|
+
// (sandbox_group_id, lease_epoch, tick) so a shared box (N sessions) is metered
|
|
769
|
+
// EXACTLY ONCE per tick (N sessions != N x bill). Orthogonal to model.tokens /
|
|
770
|
+
// model.cost (model API cost vs provider compute cost — both real, no overlap).
|
|
771
|
+
"sandbox.warm_seconds",
|
|
772
|
+
// usd_micros: warm-seconds x the per-provider per-second warm rate.
|
|
773
|
+
"sandbox.warm_cost"
|
|
210
774
|
]);
|
|
211
775
|
var UsageEvent = z.object({
|
|
212
776
|
id: z.string().uuid(),
|
|
@@ -249,6 +813,10 @@ var LimitDecision = z.discriminatedUnion("allowed", [
|
|
|
249
813
|
z.object({ allowed: z.literal(true) }),
|
|
250
814
|
z.object({ allowed: z.literal(false), code: z.string(), message: z.string() })
|
|
251
815
|
]);
|
|
816
|
+
var EntitlementDecision = z.discriminatedUnion("allowed", [
|
|
817
|
+
z.object({ allowed: z.literal(true), quantity: z.number().optional() }),
|
|
818
|
+
z.object({ allowed: z.literal(false), reason: z.string(), code: z.string().optional(), quantity: z.number().optional() })
|
|
819
|
+
]);
|
|
252
820
|
var BillingBalance = z.object({
|
|
253
821
|
accountId: z.string().uuid(),
|
|
254
822
|
balanceMicros: z.number().int(),
|
|
@@ -367,7 +935,17 @@ var DocumentSearchRequest = z.object({
|
|
|
367
935
|
});
|
|
368
936
|
var ToolRef = z.object({
|
|
369
937
|
kind: z.literal("mcp"),
|
|
370
|
-
id: z.string().min(1)
|
|
938
|
+
id: z.string().min(1),
|
|
939
|
+
// Non-fatal-on-connect marker for an AUTO-ATTACHED (workspace-default)
|
|
940
|
+
// capability MCP server: when true, a connect / tools-list failure (e.g. an
|
|
941
|
+
// expired capability credential returning 401) must SKIP that server with a
|
|
942
|
+
// logged warning and let the turn proceed, rather than failing the whole
|
|
943
|
+
// turn before the model runs. Absent/false ⇒ STRICT: an unavailable server
|
|
944
|
+
// fails the turn (the contract for EXPLICITLY-requested tools). This flag is
|
|
945
|
+
// set server-side only, at the default-capability auto-attach seam; it is
|
|
946
|
+
// stripped from client-supplied tool refs so an explicit request always
|
|
947
|
+
// stays strict.
|
|
948
|
+
optional: z.boolean().optional()
|
|
371
949
|
});
|
|
372
950
|
var ResourceRefConflictError = class extends Error {
|
|
373
951
|
constructor(message) {
|
|
@@ -376,17 +954,22 @@ var ResourceRefConflictError = class extends Error {
|
|
|
376
954
|
}
|
|
377
955
|
};
|
|
378
956
|
function mergeToolRefs(existing, additions) {
|
|
379
|
-
const
|
|
380
|
-
const
|
|
957
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
958
|
+
const order = [];
|
|
381
959
|
for (const tool of [...existing, ...additions]) {
|
|
382
960
|
const key = `${tool.kind}:${tool.id}`;
|
|
383
|
-
|
|
961
|
+
const prior = byKey.get(key);
|
|
962
|
+
if (!prior) {
|
|
963
|
+
byKey.set(key, tool);
|
|
964
|
+
order.push(key);
|
|
384
965
|
continue;
|
|
385
966
|
}
|
|
386
|
-
|
|
387
|
-
|
|
967
|
+
if (prior.optional === true && tool.optional !== true) {
|
|
968
|
+
const { optional: _dropped, ...strict } = prior;
|
|
969
|
+
byKey.set(key, strict);
|
|
970
|
+
}
|
|
388
971
|
}
|
|
389
|
-
return
|
|
972
|
+
return order.map((key) => byKey.get(key));
|
|
390
973
|
}
|
|
391
974
|
function mergeResourceRefs(existing, additions, options = {}) {
|
|
392
975
|
const out = [...existing];
|
|
@@ -481,6 +1064,9 @@ var UpdateSessionGoalRequest = z.object({
|
|
|
481
1064
|
status: z.enum(["paused", "active"]),
|
|
482
1065
|
rationale: z.string().min(1).optional()
|
|
483
1066
|
});
|
|
1067
|
+
var UpdateSessionRequest = z.object({
|
|
1068
|
+
title: z.string().min(1).max(200)
|
|
1069
|
+
});
|
|
484
1070
|
var ClearSessionContextRequest = z.object({
|
|
485
1071
|
confirm: z.literal(true)
|
|
486
1072
|
});
|
|
@@ -519,6 +1105,8 @@ var SessionTurn = z.object({
|
|
|
519
1105
|
model: z.string().min(1),
|
|
520
1106
|
reasoningEffort: ReasoningEffort,
|
|
521
1107
|
sandboxBackend: SandboxBackend,
|
|
1108
|
+
// Per-turn OS override. NULL = inherit the session's sandboxOs.
|
|
1109
|
+
sandboxOs: SandboxOs.nullable(),
|
|
522
1110
|
metadata: z.record(z.string(), z.unknown()),
|
|
523
1111
|
startedAt: z.string().nullable(),
|
|
524
1112
|
finishedAt: z.string().nullable(),
|
|
@@ -943,11 +1531,26 @@ var Session = z.object({
|
|
|
943
1531
|
accountId: z.string().uuid(),
|
|
944
1532
|
status: SessionStatus,
|
|
945
1533
|
initialMessage: z.string(),
|
|
1534
|
+
title: z.string().nullable(),
|
|
1535
|
+
titleSource: z.enum(["user", "agent"]).nullable(),
|
|
946
1536
|
resources: z.array(ResourceRef),
|
|
947
1537
|
tools: z.array(ToolRef),
|
|
948
1538
|
metadata: z.record(z.string(), z.unknown()),
|
|
949
1539
|
model: z.string(),
|
|
950
1540
|
sandboxBackend: SandboxBackend,
|
|
1541
|
+
// The OS the session's box runs. Defaults to 'linux' (today's only OS).
|
|
1542
|
+
sandboxOs: SandboxOs,
|
|
1543
|
+
// The shared-sandbox group the session's box belongs to. Equals the session's
|
|
1544
|
+
// own id for a singleton group (today's 1:1 default); equals the parent's
|
|
1545
|
+
// group when spawned shared (both sessions run in ONE box).
|
|
1546
|
+
sandboxGroupId: z.string().uuid(),
|
|
1547
|
+
// The first-class swappable-sandbox POINTER (bring-your-own-compute M2). NULL
|
|
1548
|
+
// resolves to the session's own group sandbox (the backward-compat default);
|
|
1549
|
+
// a swap sets it to the target sandbox row. active_epoch is the second epoch
|
|
1550
|
+
// ABOVE the lease epoch, bumped on every swap so the routing proxy can fence a
|
|
1551
|
+
// stale in-flight op and retry against the new active sandbox.
|
|
1552
|
+
activeSandboxId: z.string().uuid().nullable(),
|
|
1553
|
+
activeEpoch: z.number().int().nonnegative(),
|
|
951
1554
|
environmentId: z.string().uuid().nullable(),
|
|
952
1555
|
// Non-default first-party MCP token permissions (manager-style sessions);
|
|
953
1556
|
// null means the fixed worker default set.
|
|
@@ -968,6 +1571,12 @@ var Session = z.object({
|
|
|
968
1571
|
// signal. Null until a turn with usage has completed.
|
|
969
1572
|
lastInputTokens: z.number().int().nonnegative().nullable(),
|
|
970
1573
|
lastSequence: z.number().int().nonnegative(),
|
|
1574
|
+
// Multi-account Codex (P1). codexPinnedCredentialId: the account this session is
|
|
1575
|
+
// manually PINNED to (null ⇒ follow the workspace active pointer).
|
|
1576
|
+
// codexLastCredentialId: the account the most recent turn actually ran on (the
|
|
1577
|
+
// "Running on:" indicator's source). Both are credential-row ids, null until set.
|
|
1578
|
+
codexPinnedCredentialId: z.string().uuid().nullable(),
|
|
1579
|
+
codexLastCredentialId: z.string().uuid().nullable(),
|
|
971
1580
|
createdAt: z.string(),
|
|
972
1581
|
updatedAt: z.string()
|
|
973
1582
|
});
|
|
@@ -1003,8 +1612,437 @@ var SessionEventType = z.enum([
|
|
|
1003
1612
|
"goal.completed",
|
|
1004
1613
|
"goal.paused",
|
|
1005
1614
|
"goal.resumed",
|
|
1006
|
-
"goal.continuation"
|
|
1615
|
+
"goal.continuation",
|
|
1616
|
+
// Channel-B desktop pixel-plane signals (07-channel-b §1.2). The pixel socket
|
|
1617
|
+
// carries opaque RFB and cannot carry a control message the client can act on,
|
|
1618
|
+
// so these ride the durable, sequenced, gap-filled Channel-A SSE spine.
|
|
1619
|
+
"stream.url.rotated",
|
|
1620
|
+
// re-minted {url,token,expiresAt} on box rollover (event-driven)
|
|
1621
|
+
"stream.opened",
|
|
1622
|
+
// a viewer attached (audit + refcount visibility)
|
|
1623
|
+
"stream.closed",
|
|
1624
|
+
// a viewer detached / was reaped
|
|
1625
|
+
"stream.revoked",
|
|
1626
|
+
// a grant was revoked → connected clients MUST disconnect now
|
|
1627
|
+
// Channel-B recording signals (P4.3 / module 05 §3.4). The "agent films itself
|
|
1628
|
+
// proving the fix" loop: ffmpeg x11grab of the SAME :0 humans watch → artifact
|
|
1629
|
+
// → storage. The artifact ref rides the AVAILABLE event (storageKey, NOT a
|
|
1630
|
+
// long-lived URL — clients mint a short-TTL signed GET via the route).
|
|
1631
|
+
"recording.started",
|
|
1632
|
+
// ffmpeg launched on :0 (mode/codec/dimensions)
|
|
1633
|
+
"recording.available",
|
|
1634
|
+
// finalized: bytes PUT to storage, replayable
|
|
1635
|
+
"recording.failed",
|
|
1636
|
+
// ffmpeg/box-death/rollover/upload error — no artifact
|
|
1637
|
+
// Channel-A structured-service notifications (P4.4 / modules/08-channel-a.md
|
|
1638
|
+
// §2.2). The A2 reads (fs/git/terminal exec) are SYNCHRONOUS API-direct point
|
|
1639
|
+
// queries (their result is the HTTP response, NEVER an event). What rides A1
|
|
1640
|
+
// here are the side-effect NOTIFICATIONS — a path changed, git state changed,
|
|
1641
|
+
// a pty opened/printed/exited — durable, sequenced, gap-filled like every
|
|
1642
|
+
// other session event, so any viewer's Pierre tree / diff / terminal stays
|
|
1643
|
+
// live. fs.changed/git.changed are cache-invalidation signals; the pty.*
|
|
1644
|
+
// events carry the interactive terminal byte stream.
|
|
1645
|
+
"fs.changed",
|
|
1646
|
+
// a path was created/modified/deleted (write or agent mutation)
|
|
1647
|
+
"git.changed",
|
|
1648
|
+
// working-tree/index/HEAD changed (debounced re-probe)
|
|
1649
|
+
"terminal.pty.started",
|
|
1650
|
+
// an interactive PTY session opened (carries ptyId)
|
|
1651
|
+
"terminal.pty.output.delta",
|
|
1652
|
+
// PTY stdout/stderr bytes (separate from command.output)
|
|
1653
|
+
"terminal.pty.exited",
|
|
1654
|
+
// PTY session ended (exitCode/reason)
|
|
1655
|
+
"session.title_set",
|
|
1656
|
+
// Multi-account Codex (P1): the account a session's turn runs on changed
|
|
1657
|
+
// (manual switch in P1; failover/rotation in P3 reuse the same event). Drives
|
|
1658
|
+
// the in-session "Running on:" indicator's live flip.
|
|
1659
|
+
"codex.account.switched"
|
|
1660
|
+
]);
|
|
1661
|
+
var StreamUrlRotatedPayload = z.object({
|
|
1662
|
+
url: z.string().url(),
|
|
1663
|
+
token: z.string().nullable(),
|
|
1664
|
+
expiresAt: z.string().datetime().nullable(),
|
|
1665
|
+
// The epoch the new URL was minted under (the box-rollover fence the client
|
|
1666
|
+
// reconciles against). A client must drop a rotation event whose epoch it has
|
|
1667
|
+
// already advanced past.
|
|
1668
|
+
leaseEpoch: z.number().int().nonnegative(),
|
|
1669
|
+
transport: z.literal("vnc-ws"),
|
|
1670
|
+
// The viewer holder this URL is for (so a client filters out other viewers').
|
|
1671
|
+
viewerId: z.string().uuid().nullable().default(null)
|
|
1672
|
+
});
|
|
1673
|
+
var StreamOpenedPayload = z.object({
|
|
1674
|
+
viewerId: z.string().uuid(),
|
|
1675
|
+
shared: z.boolean().default(false),
|
|
1676
|
+
viewerCount: z.number().int().nonnegative()
|
|
1677
|
+
});
|
|
1678
|
+
var StreamClosedPayload = z.object({
|
|
1679
|
+
viewerId: z.string().uuid(),
|
|
1680
|
+
reason: z.enum(["client-disconnect", "reaped", "revoked", "box-rollover"]),
|
|
1681
|
+
viewerCount: z.number().int().nonnegative()
|
|
1682
|
+
});
|
|
1683
|
+
var StreamRevokedPayload = z.object({
|
|
1684
|
+
viewerId: z.string().uuid().nullable().default(null),
|
|
1685
|
+
reason: z.enum(["grant-revoked", "session-failed", "admin"])
|
|
1686
|
+
});
|
|
1687
|
+
var RecordingMode = z.enum(["manual", "on-turn", "on-verify"]);
|
|
1688
|
+
var RecordingCodec = z.enum(["h264-mp4", "vp9-webm"]);
|
|
1689
|
+
var RecordingContentType = z.enum(["video/mp4", "video/webm"]);
|
|
1690
|
+
var RecordingStartedPayload = z.object({
|
|
1691
|
+
recordingId: z.string().uuid(),
|
|
1692
|
+
turnId: z.string().uuid().nullable(),
|
|
1693
|
+
mode: RecordingMode,
|
|
1694
|
+
codec: RecordingCodec,
|
|
1695
|
+
dimensions: z.tuple([z.number().int().positive(), z.number().int().positive()]),
|
|
1696
|
+
framerate: z.number().int().positive(),
|
|
1697
|
+
startedAt: z.string(),
|
|
1698
|
+
// ISO
|
|
1699
|
+
// The verification rationale ("agent-verification: tf apply succeeded"). Agent-
|
|
1700
|
+
// authored free text — the producer caps + scrubs it before emit.
|
|
1701
|
+
reason: z.string().nullable().optional()
|
|
1702
|
+
});
|
|
1703
|
+
var RecordingAvailablePayload = z.object({
|
|
1704
|
+
recordingId: z.string().uuid(),
|
|
1705
|
+
turnId: z.string().uuid().nullable(),
|
|
1706
|
+
codec: RecordingCodec,
|
|
1707
|
+
contentType: RecordingContentType,
|
|
1708
|
+
// The @opengeni/storage object key. NO long-lived URL in the event — clients
|
|
1709
|
+
// mint a short-TTL signed GET via GET …/recordings/:id/url.
|
|
1710
|
+
storageKey: z.string(),
|
|
1711
|
+
durationSeconds: z.number().nonnegative().nullable(),
|
|
1712
|
+
sizeBytes: z.number().int().nonnegative(),
|
|
1713
|
+
dimensions: z.tuple([z.number().int().positive(), z.number().int().positive()])
|
|
1714
|
+
});
|
|
1715
|
+
var RecordingFailedReason = z.enum([
|
|
1716
|
+
"ffmpeg-error",
|
|
1717
|
+
"box-death",
|
|
1718
|
+
"box-rollover",
|
|
1719
|
+
"upload-failed",
|
|
1720
|
+
"max-bytes-exceeded",
|
|
1721
|
+
"display-unavailable"
|
|
1722
|
+
]);
|
|
1723
|
+
var RecordingFailedPayload = z.object({
|
|
1724
|
+
recordingId: z.string().uuid(),
|
|
1725
|
+
turnId: z.string().uuid().nullable(),
|
|
1726
|
+
reason: RecordingFailedReason,
|
|
1727
|
+
// ffmpeg-stderr tail / error detail — agent/ffmpeg-controlled, so the producer
|
|
1728
|
+
// caps + scrubs it before emit (it rides redact() like every payload).
|
|
1729
|
+
detail: z.string().nullable().optional()
|
|
1730
|
+
});
|
|
1731
|
+
var SandboxCommandOutputDeltaPayload = z.object({
|
|
1732
|
+
stream: z.enum(["stdout", "stderr"]).default("stdout"),
|
|
1733
|
+
chunk: z.string(),
|
|
1734
|
+
// raw bytes, utf-8 (lossy) — terminal is opaque-ish
|
|
1735
|
+
commandId: z.string().optional(),
|
|
1736
|
+
// groups deltas to one agent command
|
|
1737
|
+
seq: z.number().int().nonnegative().optional()
|
|
1738
|
+
// intra-command ordering hint
|
|
1739
|
+
});
|
|
1740
|
+
var FsChangeKind = z.enum(["created", "modified", "deleted", "renamed"]);
|
|
1741
|
+
var FsChangedPayload = z.object({
|
|
1742
|
+
changes: z.array(z.object({
|
|
1743
|
+
path: z.string(),
|
|
1744
|
+
// workspace-relative POSIX path
|
|
1745
|
+
kind: FsChangeKind,
|
|
1746
|
+
isDir: z.boolean().default(false),
|
|
1747
|
+
sizeBytes: z.number().int().nonnegative().nullable().default(null),
|
|
1748
|
+
oldPath: z.string().optional()
|
|
1749
|
+
// for "renamed"
|
|
1750
|
+
})).min(1),
|
|
1751
|
+
source: z.enum(["write", "watch", "agent"]).default("write"),
|
|
1752
|
+
// Monotonic FS revision (per-lease, paired with leaseEpoch for staleness).
|
|
1753
|
+
revision: z.number().int().nonnegative(),
|
|
1754
|
+
// The lease epoch the revision was minted under: a client invalidates on a
|
|
1755
|
+
// (leaseEpoch, revision) tuple change, never a bare revision compare (H3 —
|
|
1756
|
+
// revision resets to 0 on box re-key, so a bare monotonic compare goes stale).
|
|
1757
|
+
leaseEpoch: z.number().int().nonnegative().default(0)
|
|
1758
|
+
});
|
|
1759
|
+
var GitChangedPayload = z.object({
|
|
1760
|
+
head: z.string().nullable(),
|
|
1761
|
+
// current branch or detached SHA
|
|
1762
|
+
dirty: z.boolean(),
|
|
1763
|
+
// working tree has uncommitted changes
|
|
1764
|
+
ahead: z.number().int().nonnegative().default(0),
|
|
1765
|
+
behind: z.number().int().nonnegative().default(0),
|
|
1766
|
+
changedFileCount: z.number().int().nonnegative(),
|
|
1767
|
+
reason: z.enum(["commit", "checkout", "stage", "worktree", "fetch", "unknown"]).default("unknown"),
|
|
1768
|
+
revision: z.number().int().nonnegative().default(0),
|
|
1769
|
+
leaseEpoch: z.number().int().nonnegative().default(0)
|
|
1770
|
+
});
|
|
1771
|
+
var TerminalPtyStartedPayload = z.object({
|
|
1772
|
+
ptyId: z.string().uuid(),
|
|
1773
|
+
cols: z.number().int().positive(),
|
|
1774
|
+
rows: z.number().int().positive(),
|
|
1775
|
+
shell: z.string(),
|
|
1776
|
+
// resolved shell, e.g. "/bin/bash"
|
|
1777
|
+
cwd: z.string()
|
|
1778
|
+
});
|
|
1779
|
+
var TerminalPtyOutputDeltaPayload = z.object({
|
|
1780
|
+
ptyId: z.string().uuid(),
|
|
1781
|
+
stream: z.enum(["stdout", "stderr"]).default("stdout"),
|
|
1782
|
+
chunk: z.string(),
|
|
1783
|
+
// raw terminal bytes (incl. ANSI), utf-8 lossy
|
|
1784
|
+
seq: z.number().int().nonnegative()
|
|
1785
|
+
// strict per-pty ordering (owner-assigned)
|
|
1786
|
+
});
|
|
1787
|
+
var TerminalPtyExitedPayload = z.object({
|
|
1788
|
+
ptyId: z.string().uuid(),
|
|
1789
|
+
exitCode: z.number().int().nullable(),
|
|
1790
|
+
reason: z.enum(["exit", "killed", "owner_gone", "timeout"])
|
|
1791
|
+
});
|
|
1792
|
+
var FsNodeType = z.enum(["file", "dir", "symlink", "other"]);
|
|
1793
|
+
var FsTreeNode = z.lazy(() => z.object({
|
|
1794
|
+
name: z.string(),
|
|
1795
|
+
path: z.string(),
|
|
1796
|
+
type: FsNodeType,
|
|
1797
|
+
sizeBytes: z.number().int().nonnegative().nullable(),
|
|
1798
|
+
mtimeMs: z.number().int().nonnegative().nullable(),
|
|
1799
|
+
mode: z.number().int().nullable(),
|
|
1800
|
+
children: z.array(FsTreeNode).optional(),
|
|
1801
|
+
truncated: z.boolean().default(false)
|
|
1802
|
+
}));
|
|
1803
|
+
var FsListRequest = z.object({
|
|
1804
|
+
path: z.string().default(""),
|
|
1805
|
+
// "" = workspace root
|
|
1806
|
+
depth: z.number().int().min(0).max(8).default(1),
|
|
1807
|
+
maxEntries: z.number().int().positive().max(2e4).default(2e3),
|
|
1808
|
+
includeHidden: z.boolean().default(true)
|
|
1809
|
+
});
|
|
1810
|
+
var FsListResponse = z.object({
|
|
1811
|
+
root: FsTreeNode,
|
|
1812
|
+
revision: z.number().int().nonnegative(),
|
|
1813
|
+
truncated: z.boolean()
|
|
1814
|
+
// global cap hit
|
|
1815
|
+
});
|
|
1816
|
+
var FsEncoding = z.enum(["utf8", "base64"]);
|
|
1817
|
+
var FsReadRequest = z.object({
|
|
1818
|
+
path: z.string(),
|
|
1819
|
+
encoding: FsEncoding.default("utf8"),
|
|
1820
|
+
maxBytes: z.number().int().positive().max(25 * 1024 * 1024).default(5 * 1024 * 1024)
|
|
1821
|
+
});
|
|
1822
|
+
var FsReadResponse = z.object({
|
|
1823
|
+
path: z.string(),
|
|
1824
|
+
encoding: FsEncoding,
|
|
1825
|
+
content: z.string(),
|
|
1826
|
+
// text or base64 per encoding
|
|
1827
|
+
sizeBytes: z.number().int().nonnegative(),
|
|
1828
|
+
// bytes returned (== content size)
|
|
1829
|
+
truncated: z.boolean(),
|
|
1830
|
+
// sizeBytes hit maxBytes; content is the prefix
|
|
1831
|
+
isBinary: z.boolean(),
|
|
1832
|
+
// sniffed NUL byte in first 8KB
|
|
1833
|
+
revision: z.number().int().nonnegative()
|
|
1834
|
+
});
|
|
1835
|
+
var FsWriteRequest = z.object({
|
|
1836
|
+
path: z.string(),
|
|
1837
|
+
encoding: FsEncoding.default("utf8"),
|
|
1838
|
+
content: z.string(),
|
|
1839
|
+
overwrite: z.boolean().default(true),
|
|
1840
|
+
// false + existing path => 409
|
|
1841
|
+
createParents: z.boolean().default(true)
|
|
1842
|
+
});
|
|
1843
|
+
var FsWriteResponse = z.object({
|
|
1844
|
+
path: z.string(),
|
|
1845
|
+
sizeBytes: z.number().int().nonnegative(),
|
|
1846
|
+
revision: z.number().int().nonnegative()
|
|
1847
|
+
// == the fs.changed revision
|
|
1848
|
+
});
|
|
1849
|
+
var FsDeleteRequest = z.object({
|
|
1850
|
+
path: z.string(),
|
|
1851
|
+
recursive: z.boolean().default(false)
|
|
1852
|
+
// required true to delete a non-empty dir
|
|
1853
|
+
});
|
|
1854
|
+
var FsDeleteResponse = z.object({ revision: z.number().int().nonnegative() });
|
|
1855
|
+
var FsMoveRequest = z.object({
|
|
1856
|
+
path: z.string(),
|
|
1857
|
+
newPath: z.string(),
|
|
1858
|
+
overwrite: z.boolean().default(false),
|
|
1859
|
+
// false + existing destination => 409
|
|
1860
|
+
createParents: z.boolean().default(true)
|
|
1861
|
+
});
|
|
1862
|
+
var FsMoveResponse = z.object({
|
|
1863
|
+
path: z.string(),
|
|
1864
|
+
newPath: z.string(),
|
|
1865
|
+
revision: z.number().int().nonnegative()
|
|
1866
|
+
// == the fs.changed revision
|
|
1867
|
+
});
|
|
1868
|
+
var FsMkdirRequest = z.object({
|
|
1869
|
+
path: z.string(),
|
|
1870
|
+
recursive: z.boolean().default(true)
|
|
1871
|
+
// false + existing path => 400
|
|
1872
|
+
});
|
|
1873
|
+
var FsMkdirResponse = z.object({
|
|
1874
|
+
path: z.string(),
|
|
1875
|
+
revision: z.number().int().nonnegative()
|
|
1876
|
+
// == the fs.changed revision
|
|
1877
|
+
});
|
|
1878
|
+
var GitFileStatusCode = z.enum([
|
|
1879
|
+
"added",
|
|
1880
|
+
"modified",
|
|
1881
|
+
"deleted",
|
|
1882
|
+
"renamed",
|
|
1883
|
+
"copied",
|
|
1884
|
+
"untracked",
|
|
1885
|
+
"ignored",
|
|
1886
|
+
"conflicted",
|
|
1887
|
+
"typechange"
|
|
1007
1888
|
]);
|
|
1889
|
+
var GitFileStatus = z.object({
|
|
1890
|
+
path: z.string(),
|
|
1891
|
+
oldPath: z.string().nullable(),
|
|
1892
|
+
// for renamed/copied
|
|
1893
|
+
index: GitFileStatusCode.nullable(),
|
|
1894
|
+
// staged change (X in porcelain XY)
|
|
1895
|
+
worktree: GitFileStatusCode.nullable(),
|
|
1896
|
+
// unstaged change (Y in porcelain XY)
|
|
1897
|
+
isConflicted: z.boolean().default(false)
|
|
1898
|
+
});
|
|
1899
|
+
var GitStatusRequest = z.object({
|
|
1900
|
+
path: z.string().default("")
|
|
1901
|
+
// repo root within workspace (multi-repo support)
|
|
1902
|
+
});
|
|
1903
|
+
var GitStatusResponse = z.object({
|
|
1904
|
+
isRepo: z.boolean(),
|
|
1905
|
+
head: z.string().nullable(),
|
|
1906
|
+
// branch name
|
|
1907
|
+
detached: z.boolean().default(false),
|
|
1908
|
+
upstream: z.string().nullable(),
|
|
1909
|
+
ahead: z.number().int().nonnegative().default(0),
|
|
1910
|
+
behind: z.number().int().nonnegative().default(0),
|
|
1911
|
+
files: z.array(GitFileStatus),
|
|
1912
|
+
revision: z.number().int().nonnegative()
|
|
1913
|
+
});
|
|
1914
|
+
var GitDiffLineType = z.enum(["context", "add", "del", "meta"]);
|
|
1915
|
+
var GitDiffLine = z.object({
|
|
1916
|
+
type: GitDiffLineType,
|
|
1917
|
+
// null on the side that doesn't have the line (add => oldNo null; del => newNo null)
|
|
1918
|
+
oldNo: z.number().int().positive().nullable(),
|
|
1919
|
+
newNo: z.number().int().positive().nullable(),
|
|
1920
|
+
text: z.string()
|
|
1921
|
+
// line WITHOUT leading +/-/space marker
|
|
1922
|
+
});
|
|
1923
|
+
var GitDiffHunk = z.object({
|
|
1924
|
+
oldStart: z.number().int().nonnegative(),
|
|
1925
|
+
oldLines: z.number().int().nonnegative(),
|
|
1926
|
+
newStart: z.number().int().nonnegative(),
|
|
1927
|
+
newLines: z.number().int().nonnegative(),
|
|
1928
|
+
header: z.string(),
|
|
1929
|
+
// the @@ ... @@ section heading
|
|
1930
|
+
lines: z.array(GitDiffLine)
|
|
1931
|
+
});
|
|
1932
|
+
var GitFileDiff = z.object({
|
|
1933
|
+
path: z.string(),
|
|
1934
|
+
oldPath: z.string().nullable(),
|
|
1935
|
+
status: GitFileStatusCode,
|
|
1936
|
+
isBinary: z.boolean().default(false),
|
|
1937
|
+
isImage: z.boolean().default(false),
|
|
1938
|
+
additions: z.number().int().nonnegative(),
|
|
1939
|
+
deletions: z.number().int().nonnegative(),
|
|
1940
|
+
hunks: z.array(GitDiffHunk),
|
|
1941
|
+
// empty if binary or truncated
|
|
1942
|
+
truncated: z.boolean().default(false)
|
|
1943
|
+
// diff exceeded maxBytes; hunks omitted
|
|
1944
|
+
});
|
|
1945
|
+
var GitDiffRequest = z.object({
|
|
1946
|
+
path: z.string().default(""),
|
|
1947
|
+
// repo root
|
|
1948
|
+
// diff selectors, mutually exclusive precedence: refs > staged > worktree
|
|
1949
|
+
staged: z.boolean().default(false),
|
|
1950
|
+
// --cached (index vs HEAD)
|
|
1951
|
+
fromRef: z.string().optional(),
|
|
1952
|
+
toRef: z.string().optional(),
|
|
1953
|
+
pathspec: z.array(z.string()).default([]),
|
|
1954
|
+
contextLines: z.number().int().min(0).max(10).default(3),
|
|
1955
|
+
maxBytesPerFile: z.number().int().positive().max(2 * 1024 * 1024).default(512 * 1024)
|
|
1956
|
+
});
|
|
1957
|
+
var GitDiffResponse = z.object({
|
|
1958
|
+
files: z.array(GitFileDiff),
|
|
1959
|
+
revision: z.number().int().nonnegative()
|
|
1960
|
+
});
|
|
1961
|
+
var GitLogRequest = z.object({
|
|
1962
|
+
path: z.string().default(""),
|
|
1963
|
+
ref: z.string().default("HEAD"),
|
|
1964
|
+
maxCount: z.number().int().positive().max(1e3).default(100),
|
|
1965
|
+
skip: z.number().int().nonnegative().default(0),
|
|
1966
|
+
pathspec: z.array(z.string()).default([])
|
|
1967
|
+
});
|
|
1968
|
+
var GitCommit = z.object({
|
|
1969
|
+
sha: z.string(),
|
|
1970
|
+
shortSha: z.string(),
|
|
1971
|
+
parents: z.array(z.string()),
|
|
1972
|
+
author: z.object({ name: z.string(), email: z.string(), timestamp: z.number().int() }),
|
|
1973
|
+
committer: z.object({ name: z.string(), email: z.string(), timestamp: z.number().int() }),
|
|
1974
|
+
subject: z.string(),
|
|
1975
|
+
body: z.string(),
|
|
1976
|
+
refs: z.array(z.string()).default([])
|
|
1977
|
+
// decorations: branch/tag pointers
|
|
1978
|
+
});
|
|
1979
|
+
var GitLogResponse = z.object({ commits: z.array(GitCommit), hasMore: z.boolean() });
|
|
1980
|
+
var GitShowRequest = z.object({
|
|
1981
|
+
path: z.string().default(""),
|
|
1982
|
+
ref: z.string(),
|
|
1983
|
+
// a commit/tag/tree-ish
|
|
1984
|
+
filePath: z.string().optional(),
|
|
1985
|
+
// ref + filePath => raw blob ("open file at commit")
|
|
1986
|
+
encoding: FsEncoding.default("utf8"),
|
|
1987
|
+
maxBytesPerFile: z.number().int().positive().max(2 * 1024 * 1024).default(512 * 1024)
|
|
1988
|
+
});
|
|
1989
|
+
var GitShowResponse = z.object({
|
|
1990
|
+
commit: GitCommit.nullable(),
|
|
1991
|
+
// null when fetching a raw blob
|
|
1992
|
+
files: z.array(GitFileDiff),
|
|
1993
|
+
// commit diff vs first parent
|
|
1994
|
+
blob: z.object({ content: z.string(), encoding: FsEncoding, sizeBytes: z.number().int(), truncated: z.boolean() }).nullable(),
|
|
1995
|
+
revision: z.number().int().nonnegative()
|
|
1996
|
+
});
|
|
1997
|
+
var TerminalExecRequest = z.object({
|
|
1998
|
+
command: z.string().min(1),
|
|
1999
|
+
cwd: z.string().default(""),
|
|
2000
|
+
// workspace-relative
|
|
2001
|
+
// Soft per-call wall-clock bound (the box yields output back when reached).
|
|
2002
|
+
timeoutMs: z.number().int().positive().max(12e4).default(3e4),
|
|
2003
|
+
// Stream the deltas onto A1 as the agent firehose (so other viewers see it),
|
|
2004
|
+
// in addition to returning the buffered result inline.
|
|
2005
|
+
emitStream: z.boolean().default(true)
|
|
2006
|
+
});
|
|
2007
|
+
var TerminalExecResponse = z.object({
|
|
2008
|
+
stdout: z.string(),
|
|
2009
|
+
stderr: z.string(),
|
|
2010
|
+
exitCode: z.number().int().nullable(),
|
|
2011
|
+
// True when the process was still running when the call yielded (a long
|
|
2012
|
+
// command); the remaining output drains onto A1 if emitStream was set.
|
|
2013
|
+
running: z.boolean(),
|
|
2014
|
+
wallTimeSeconds: z.number().nonnegative()
|
|
2015
|
+
});
|
|
2016
|
+
var PtyOpenRequest = z.object({
|
|
2017
|
+
cols: z.number().int().positive().max(500).default(80),
|
|
2018
|
+
rows: z.number().int().positive().max(300).default(24),
|
|
2019
|
+
cwd: z.string().default(""),
|
|
2020
|
+
// workspace-relative
|
|
2021
|
+
shell: z.string().optional()
|
|
2022
|
+
// default: resolved login shell
|
|
2023
|
+
});
|
|
2024
|
+
var PtyOpenResponse = z.object({
|
|
2025
|
+
ptyId: z.string().uuid(),
|
|
2026
|
+
// output streams as terminal.pty.output.delta on the SSE channel the client holds
|
|
2027
|
+
streamVia: z.literal("sse-events"),
|
|
2028
|
+
supportsInput: z.boolean()
|
|
2029
|
+
// false on backends without writeStdin
|
|
2030
|
+
});
|
|
2031
|
+
var PtyWriteRequest = z.object({ ptyId: z.string().uuid(), data: z.string() });
|
|
2032
|
+
var PtyResizeRequest = z.object({ ptyId: z.string().uuid(), cols: z.number().int().positive(), rows: z.number().int().positive() });
|
|
2033
|
+
var PtyCloseRequest = z.object({ ptyId: z.string().uuid() });
|
|
2034
|
+
var SessionStructuredCapabilities = z.object({
|
|
2035
|
+
FileSystem: z.object({ available: z.boolean(), readOnly: z.boolean(), root: z.string() }),
|
|
2036
|
+
Terminal: z.object({
|
|
2037
|
+
events: z.boolean(),
|
|
2038
|
+
// command.output firehose (always on if a box exists)
|
|
2039
|
+
exec: z.boolean(),
|
|
2040
|
+
// synchronous terminal exec
|
|
2041
|
+
pty: z.object({ available: z.boolean() })
|
|
2042
|
+
// interactive stdin (writeStdin)
|
|
2043
|
+
}),
|
|
2044
|
+
Git: z.object({ available: z.boolean(), repos: z.array(z.string()) })
|
|
2045
|
+
});
|
|
1008
2046
|
var SessionEvent = z.object({
|
|
1009
2047
|
id: z.string().uuid(),
|
|
1010
2048
|
workspaceId: z.string().uuid(),
|
|
@@ -1024,6 +2062,17 @@ var CreateSessionRequest = z.object({
|
|
|
1024
2062
|
model: z.string().min(1).optional(),
|
|
1025
2063
|
reasoningEffort: ReasoningEffort.optional(),
|
|
1026
2064
|
sandboxBackend: SandboxBackend.optional(),
|
|
2065
|
+
// The enrolled machine (a sandbox id) to run this session on; seeds the
|
|
2066
|
+
// active-sandbox pointer at creation so the FIRST turn routes to the chosen
|
|
2067
|
+
// machine (race-free: the pointer is committed before the worker turn
|
|
2068
|
+
// workflow can read it). An invalid/unowned/offline target fails the create.
|
|
2069
|
+
targetSandboxId: z.string().uuid().optional(),
|
|
2070
|
+
// The working directory the targeted machine runs the session under — the
|
|
2071
|
+
// path/cwd base for its agent exec, terminal, and file dock. Free-form pass-
|
|
2072
|
+
// through: a launch-workspace_root-relative subdir or an absolute machine path
|
|
2073
|
+
// (the agent's resolve_cwd handles both). Only valid WITH targetSandboxId
|
|
2074
|
+
// (workingDir alone is a 422); omitted ⇒ the machine's default workspace_root.
|
|
2075
|
+
workingDir: z.string().min(1).optional(),
|
|
1027
2076
|
// Workspace environment attachment is fixed at session creation; follow-up
|
|
1028
2077
|
// user.message events cannot switch or add one.
|
|
1029
2078
|
environmentId: z.string().uuid().optional(),
|
|
@@ -1040,7 +2089,29 @@ var CreateSessionRequest = z.object({
|
|
|
1040
2089
|
// the fixed worker default — how an operator hands a manager-style session
|
|
1041
2090
|
// the orchestration/environment/github tools. Capped at creation: every
|
|
1042
2091
|
// requested permission must be held by the creating grant (no escalation).
|
|
1043
|
-
firstPartyMcpPermissions: z.array(Permission).optional()
|
|
2092
|
+
firstPartyMcpPermissions: z.array(Permission).optional(),
|
|
2093
|
+
// Shared-sandbox placement (addendum 05 §D.1). Three-way union; OMITTED ⇒
|
|
2094
|
+
// today's behavior (a context-dependent default resolved server-side: from
|
|
2095
|
+
// inside a session → "shared" with the creator's box, top-level → "new").
|
|
2096
|
+
// - "shared": join the CREATOR's box. Requires a parent session (inferred
|
|
2097
|
+
// from the worker-signed sessionId claim, never caller-supplied);
|
|
2098
|
+
// top-level "shared" is a 422.
|
|
2099
|
+
// - "new": mint a fresh singleton box (group ≡ the new session's id).
|
|
2100
|
+
// - {groupId}: join a SPECIFIC sibling group in THIS workspace (manager
|
|
2101
|
+
// fan-out). Validated workspace-scoped (cross-workspace → 404).
|
|
2102
|
+
// A shared spawn inherits the box's (backend, os) — it is literally the same
|
|
2103
|
+
// box; the child cannot pick its own backend. Cross-workspace sharing is
|
|
2104
|
+
// forbidden by construction (the parent/group reads are RLS-workspace-scoped).
|
|
2105
|
+
// ENV-AWARE: the box's environment is fixed at creation, so a share requires
|
|
2106
|
+
// the SAME environmentId as the creator's box. On a mismatch the inherited
|
|
2107
|
+
// default silently falls back to an own box; an explicit "shared"/{groupId}
|
|
2108
|
+
// request 422s at create (instead of the first turn dying on the SDK's
|
|
2109
|
+
// manifest-env guard).
|
|
2110
|
+
sandbox: z.union([
|
|
2111
|
+
z.literal("shared"),
|
|
2112
|
+
z.literal("new"),
|
|
2113
|
+
z.object({ groupId: z.string().uuid() })
|
|
2114
|
+
]).optional()
|
|
1044
2115
|
});
|
|
1045
2116
|
var ClientSessionEvent = z.discriminatedUnion("type", [
|
|
1046
2117
|
z.object({
|
|
@@ -1110,10 +2181,358 @@ var ClientAuthConfig = z.discriminatedUnion("mode", [
|
|
|
1110
2181
|
session: z.literal("cookie")
|
|
1111
2182
|
})
|
|
1112
2183
|
]);
|
|
2184
|
+
var CapabilityUnavailableReason = z.enum([
|
|
2185
|
+
"backend_unsupported",
|
|
2186
|
+
"os_unsupported",
|
|
2187
|
+
"not_provisioned",
|
|
2188
|
+
"disabled_by_policy",
|
|
2189
|
+
"lease_cold",
|
|
2190
|
+
"tier_headless",
|
|
2191
|
+
// Selfhosted (bring-your-own-compute) negotiation states (M1 additive; the
|
|
2192
|
+
// selfhosted negotiation in select.ts wires them in M3):
|
|
2193
|
+
"agent_offline",
|
|
2194
|
+
// the enrolled agent process is not running / unreachable
|
|
2195
|
+
"agent_reconnecting",
|
|
2196
|
+
// a transient blip — the agent is reconnecting (warmable)
|
|
2197
|
+
"consent_required",
|
|
2198
|
+
// whole-machine / screen-control consent not yet acknowledged
|
|
2199
|
+
"display_unavailable"
|
|
2200
|
+
// headless machine with no display stack (no DesktopStream)
|
|
2201
|
+
]);
|
|
2202
|
+
var SessionCapabilities = z.object({
|
|
2203
|
+
sessionId: z.string().uuid(),
|
|
2204
|
+
backend: SandboxBackend,
|
|
2205
|
+
os: SandboxOs,
|
|
2206
|
+
liveness: z.enum(["cold", "warming", "warm", "draining"]),
|
|
2207
|
+
// Echoed on viewer heartbeats (the split-brain fence).
|
|
2208
|
+
leaseEpoch: z.number().int().nonnegative(),
|
|
2209
|
+
viewerHeartbeatIntervalMs: z.number().int().positive().default(3e4),
|
|
2210
|
+
FileSystem: z.object({
|
|
2211
|
+
available: z.boolean(),
|
|
2212
|
+
readOnly: z.boolean(),
|
|
2213
|
+
root: z.string(),
|
|
2214
|
+
pathSep: z.enum(["/", "\\"]),
|
|
2215
|
+
treeMode: z.enum(["lazy", "snapshot"]),
|
|
2216
|
+
reason: CapabilityUnavailableReason.nullable()
|
|
2217
|
+
}),
|
|
2218
|
+
Terminal: z.object({
|
|
2219
|
+
transport: z.enum(["sse-events", "pty-ws"]).nullable(),
|
|
2220
|
+
ptyCapable: z.boolean(),
|
|
2221
|
+
shell: z.string(),
|
|
2222
|
+
// The direct-to-provider ttyd PTY-over-websocket URL (pty-ws) resolved on the
|
|
2223
|
+
// SAME tunnel as the desktop; null on a cold lease / read-only sse-events
|
|
2224
|
+
// firehose / degraded terminal. The scoped stream token is recorded against
|
|
2225
|
+
// the holder (NEVER a URL query param), symmetric with DesktopStream.
|
|
2226
|
+
url: z.string().url().nullable(),
|
|
2227
|
+
token: z.string().nullable(),
|
|
2228
|
+
// ISO absolute expiry of the minted stream token (symmetric with
|
|
2229
|
+
// DesktopStream.expiresAt). Null when no live URL/token is minted.
|
|
2230
|
+
expiresAt: z.string().nullable(),
|
|
2231
|
+
reason: CapabilityUnavailableReason.nullable()
|
|
2232
|
+
}),
|
|
2233
|
+
Git: z.object({
|
|
2234
|
+
available: z.boolean(),
|
|
2235
|
+
repos: z.array(z.string()),
|
|
2236
|
+
reason: CapabilityUnavailableReason.nullable()
|
|
2237
|
+
}),
|
|
2238
|
+
DesktopStream: z.object({
|
|
2239
|
+
// "relay-frames" is the selfhosted framebuffer stream: PNG-per-frame protobuf
|
|
2240
|
+
// datagrams spliced over the relay (NOT RFB). The viewer renders it with the
|
|
2241
|
+
// "frames" client (a canvas painter), distinct from Modal's "vnc-ws"/"novnc".
|
|
2242
|
+
transport: z.enum(["vnc-ws", "rdp-ws", "webrtc", "relay-frames"]).nullable(),
|
|
2243
|
+
client: z.enum(["novnc", "web-rdp", "frames"]).nullable(),
|
|
2244
|
+
mode: z.enum(["read-only", "interactive"]).default("read-only"),
|
|
2245
|
+
url: z.string().url().nullable(),
|
|
2246
|
+
token: z.string().nullable(),
|
|
2247
|
+
expiresAt: z.string().nullable(),
|
|
2248
|
+
resolution: z.tuple([z.number().int().positive(), z.number().int().positive()]).default([1024, 768]),
|
|
2249
|
+
// REQUIRED, no default (the server must assert un-redacted pixels).
|
|
2250
|
+
unredacted: z.boolean(),
|
|
2251
|
+
requiresAcknowledgment: z.boolean(),
|
|
2252
|
+
acknowledged: z.boolean(),
|
|
2253
|
+
// SHARED-EXPOSURE disclosure (addendum E.1). `shared` is true when the box's
|
|
2254
|
+
// group has >1 session: watching this desktop ALSO shows the sibling
|
|
2255
|
+
// sessions' agents on the one :0 framebuffer (the pixels cannot be redacted).
|
|
2256
|
+
// `sharedSessionIds` lists the OTHER sessions whose agents may appear — IDS
|
|
2257
|
+
// ONLY, never their goal/metadata/conversation (a viewer of A must not be
|
|
2258
|
+
// able to use "I can see B's id" to subscribe to B's events; stress g). When
|
|
2259
|
+
// shared, the consent gate requires the shared-exposure acknowledgment (409
|
|
2260
|
+
// shared_acknowledgment_required) before the desktop path is handed out.
|
|
2261
|
+
shared: z.boolean().default(false),
|
|
2262
|
+
sharedSessionIds: z.array(z.string().uuid()).default([]),
|
|
2263
|
+
reason: CapabilityUnavailableReason.nullable()
|
|
2264
|
+
}),
|
|
2265
|
+
Recording: z.object({
|
|
2266
|
+
available: z.boolean(),
|
|
2267
|
+
modes: z.array(z.enum(["manual", "on-turn", "on-verify"])),
|
|
2268
|
+
codecs: z.array(z.enum(["h264-mp4", "vp9-webm"])),
|
|
2269
|
+
reason: CapabilityUnavailableReason.nullable()
|
|
2270
|
+
}),
|
|
2271
|
+
// The AGENT drives the SAME :0 (xdotool/XTEST + scrot) the human watches; the
|
|
2272
|
+
// human viewer plane is read-only by default (§6). `available` == desktop-
|
|
2273
|
+
// capable backend && computerUseEnabled; `readOnly` reports whether the agent
|
|
2274
|
+
// driver itself is gated to no-op input (v1 default false — the agent clicks).
|
|
2275
|
+
ComputerUse: z.object({
|
|
2276
|
+
available: z.boolean(),
|
|
2277
|
+
readOnly: z.boolean(),
|
|
2278
|
+
reason: CapabilityUnavailableReason.nullable()
|
|
2279
|
+
}),
|
|
2280
|
+
negotiatedAt: z.string()
|
|
2281
|
+
});
|
|
2282
|
+
var AttachViewerRequest = z.object({
|
|
2283
|
+
viewerId: z.string().uuid().optional(),
|
|
2284
|
+
desktop: z.boolean().optional()
|
|
2285
|
+
});
|
|
2286
|
+
var ViewerHolder = z.object({
|
|
2287
|
+
viewerId: z.string().uuid(),
|
|
2288
|
+
sandboxGroupId: z.string().uuid(),
|
|
2289
|
+
liveness: z.enum(["cold", "warming", "warm", "draining"]),
|
|
2290
|
+
// The epoch the viewer is fenced on; echoed back on heartbeats.
|
|
2291
|
+
leaseEpoch: z.number().int().nonnegative(),
|
|
2292
|
+
viewerHeartbeatIntervalMs: z.number().int().positive(),
|
|
2293
|
+
// The desktop pixel tunnel URL the viewer connects to directly; null until
|
|
2294
|
+
// P4 mints it (gated until then).
|
|
2295
|
+
dataPlaneUrl: z.string().nullable()
|
|
2296
|
+
});
|
|
2297
|
+
var AcknowledgeStreamRequest = z.object({
|
|
2298
|
+
// The principal accepts that the desktop pixel plane is un-redacted (can show
|
|
2299
|
+
// cloud creds the agent cat's into a terminal). Always true to record consent;
|
|
2300
|
+
// present for self-documentation + a future explicit withdraw.
|
|
2301
|
+
acknowledgeUnredacted: z.boolean().default(true),
|
|
2302
|
+
// The principal accepts the shared-exposure disclosure: watching this desktop
|
|
2303
|
+
// also shows sibling sessions' agents on the one framebuffer.
|
|
2304
|
+
acknowledgeShared: z.boolean().default(false)
|
|
2305
|
+
});
|
|
2306
|
+
var AcknowledgeStreamResponse = z.object({
|
|
2307
|
+
acknowledged: z.boolean(),
|
|
2308
|
+
acknowledgedShared: z.boolean()
|
|
2309
|
+
});
|
|
2310
|
+
var ViewerHeartbeatRequest = z.object({
|
|
2311
|
+
leaseEpoch: z.number().int().nonnegative()
|
|
2312
|
+
});
|
|
2313
|
+
var ViewerHeartbeatResponse = z.object({
|
|
2314
|
+
// false ⇒ the holder was reaped or the epoch is stale; the client re-attaches.
|
|
2315
|
+
alive: z.boolean()
|
|
2316
|
+
});
|
|
2317
|
+
var EnrollmentOs = z.enum(["linux", "macos", "windows"]);
|
|
2318
|
+
var EnrollmentArch = z.enum(["x86_64", "aarch64"]);
|
|
2319
|
+
var DeviceEnrollmentStartRequest = z.object({
|
|
2320
|
+
// The agent's ed25519 public key (the machine identity the enrollment binds to).
|
|
2321
|
+
publicKey: z.string().min(1).max(1024),
|
|
2322
|
+
os: EnrollmentOs.default("linux"),
|
|
2323
|
+
arch: EnrollmentArch.default("x86_64"),
|
|
2324
|
+
// Human-friendly machine name (hostname by default).
|
|
2325
|
+
machineName: z.string().min(1).max(256).optional(),
|
|
2326
|
+
// v1 only supports whole-machine; kept explicit so the consent is recorded.
|
|
2327
|
+
exposure: z.literal("whole-machine").default("whole-machine"),
|
|
2328
|
+
// The agent can offer a display (a real screen / Xvfb is available).
|
|
2329
|
+
canOfferDisplay: z.boolean().default(false),
|
|
2330
|
+
// The agent requests screen control (computer-use); the user's allow_screen_control
|
|
2331
|
+
// at approve is the AUTHORITATIVE consent.
|
|
2332
|
+
requestsScreenControl: z.boolean().default(false),
|
|
2333
|
+
// The workspace this machine is enrolling into. The agent is told this at install
|
|
2334
|
+
// (the user picks the workspace, or the install/enroll token carries it). The user
|
|
2335
|
+
// who approves must hold a grant in THIS workspace — that binding is what makes
|
|
2336
|
+
// the (user-unauthenticated) start safe: it cannot grant access to a workspace no
|
|
2337
|
+
// authorized user later approves in.
|
|
2338
|
+
workspaceId: z.string().uuid()
|
|
2339
|
+
});
|
|
2340
|
+
var DeviceEnrollmentStartResponse = z.object({
|
|
2341
|
+
deviceCode: z.string(),
|
|
2342
|
+
userCode: z.string(),
|
|
2343
|
+
verificationUri: z.string(),
|
|
2344
|
+
verificationUriComplete: z.string(),
|
|
2345
|
+
intervalSeconds: z.number().int().positive(),
|
|
2346
|
+
expiresInSeconds: z.number().int().positive()
|
|
2347
|
+
});
|
|
2348
|
+
var DeviceEnrollmentApproveRequest = z.object({
|
|
2349
|
+
userCode: z.string().min(1).max(64),
|
|
2350
|
+
allowScreenControl: z.boolean().default(false)
|
|
2351
|
+
});
|
|
2352
|
+
var DeviceEnrollmentApproveResponse = z.object({
|
|
2353
|
+
approved: z.boolean(),
|
|
2354
|
+
enrollmentId: z.string().uuid(),
|
|
2355
|
+
sandboxId: z.string().uuid(),
|
|
2356
|
+
allowScreenControl: z.boolean()
|
|
2357
|
+
});
|
|
2358
|
+
var DeviceEnrollmentPollRequest = z.object({
|
|
2359
|
+
deviceCode: z.string().min(1).max(256)
|
|
2360
|
+
});
|
|
2361
|
+
var DeviceEnrollmentState = z.enum(["pending", "authorized", "denied", "expired", "disabled"]);
|
|
2362
|
+
var EnrollmentCredentialsResponse = z.object({
|
|
2363
|
+
agentId: z.string().uuid(),
|
|
2364
|
+
workspaceId: z.string().uuid(),
|
|
2365
|
+
// The signed bearer the agent presents to the control plane (the `oge_` token).
|
|
2366
|
+
bearer: z.string(),
|
|
2367
|
+
// The Account-scoped control-plane subject prefix the agent subscribes to:
|
|
2368
|
+
// agent.<workspaceId>.<agentId>.
|
|
2369
|
+
subjectPrefix: z.string(),
|
|
2370
|
+
// Connect info for the control plane + stream relay (may be empty when not yet
|
|
2371
|
+
// configured for this deployment — the agent surfaces "control plane unconfigured").
|
|
2372
|
+
natsUrls: z.array(z.string()),
|
|
2373
|
+
relayUrl: z.string(),
|
|
2374
|
+
// The agent's PRODUCER token for the relay edge (the `ogr_` token; M8b). Presented
|
|
2375
|
+
// as StreamOpen.token when the agent registers a pty/desktop channel; the relay
|
|
2376
|
+
// verifies it then pairs the producer with the viewer (whose `ogs_` token the
|
|
2377
|
+
// relay also verifies). Empty when the relay-token plane is unconfigured for this
|
|
2378
|
+
// deployment (graceful degrade — the agent then presents an empty token the relay
|
|
2379
|
+
// rejects, surfacing the gap loudly rather than silently producing a dead stream).
|
|
2380
|
+
relayToken: z.string(),
|
|
2381
|
+
// VESTIGIAL (M-AUTH): there is no per-machine NATS Account creds file. The agent
|
|
2382
|
+
// presents the `bearer` above as the NATS connect AUTH-TOKEN; the server's
|
|
2383
|
+
// auth-callout responder validates it and mints a workspace-scoped user JWT. This
|
|
2384
|
+
// field echoes the bearer so a consumer reading it as the connect credential still
|
|
2385
|
+
// works; new consumers should read `bearer` directly.
|
|
2386
|
+
natsAccountCreds: z.string(),
|
|
2387
|
+
// The minisign public key the agent pins for self-update verification.
|
|
2388
|
+
updatePublicKey: z.string(),
|
|
2389
|
+
consentedWholeMachine: z.boolean(),
|
|
2390
|
+
consentedScreenControl: z.boolean()
|
|
2391
|
+
});
|
|
2392
|
+
var DeviceEnrollmentPollResponse = z.object({
|
|
2393
|
+
state: DeviceEnrollmentState,
|
|
2394
|
+
// Present only when state === "authorized".
|
|
2395
|
+
credentials: EnrollmentCredentialsResponse.optional()
|
|
2396
|
+
});
|
|
2397
|
+
var EnrollmentSummary = z.object({
|
|
2398
|
+
id: z.string().uuid(),
|
|
2399
|
+
pubkey: z.string(),
|
|
2400
|
+
exposure: z.literal("whole-machine"),
|
|
2401
|
+
hasDisplay: z.boolean(),
|
|
2402
|
+
allowScreenControl: z.boolean(),
|
|
2403
|
+
status: z.enum(["active", "revoked"]),
|
|
2404
|
+
os: EnrollmentOs,
|
|
2405
|
+
arch: z.string(),
|
|
2406
|
+
lastSeenAt: z.string().nullable(),
|
|
2407
|
+
createdAt: z.string(),
|
|
2408
|
+
revokedAt: z.string().nullable()
|
|
2409
|
+
});
|
|
2410
|
+
var ListEnrollmentsResponse = z.object({
|
|
2411
|
+
enrollments: z.array(EnrollmentSummary)
|
|
2412
|
+
});
|
|
2413
|
+
var RevokeEnrollmentResponse = z.object({
|
|
2414
|
+
revoked: z.boolean()
|
|
2415
|
+
});
|
|
2416
|
+
var DeviceEnrollmentLookupRequest = z.object({
|
|
2417
|
+
userCode: z.string().min(1).max(64)
|
|
2418
|
+
});
|
|
2419
|
+
var DeviceEnrollmentLookupMachine = z.object({
|
|
2420
|
+
machineName: z.string().nullable(),
|
|
2421
|
+
os: EnrollmentOs,
|
|
2422
|
+
arch: z.string(),
|
|
2423
|
+
canOfferDisplay: z.boolean(),
|
|
2424
|
+
requestsScreenControl: z.boolean()
|
|
2425
|
+
});
|
|
2426
|
+
var DeviceEnrollmentLookupResponse = z.object({
|
|
2427
|
+
workspaceId: z.string().uuid(),
|
|
2428
|
+
userCode: z.string(),
|
|
2429
|
+
machine: DeviceEnrollmentLookupMachine,
|
|
2430
|
+
expiresAt: z.string()
|
|
2431
|
+
});
|
|
2432
|
+
var DeviceEnrollmentDenyRequest = z.object({
|
|
2433
|
+
userCode: z.string().min(1).max(64)
|
|
2434
|
+
});
|
|
2435
|
+
var DeviceEnrollmentDenyResponse = z.object({
|
|
2436
|
+
denied: z.boolean()
|
|
2437
|
+
});
|
|
2438
|
+
var MintEnrollTokenRequest = z.object({
|
|
2439
|
+
allowScreenControl: z.boolean().default(false)
|
|
2440
|
+
});
|
|
2441
|
+
var MintEnrollTokenResponse = z.object({
|
|
2442
|
+
// The `oget_` token. SECRET — the UI shows it once with a copy-now warning.
|
|
2443
|
+
token: z.string(),
|
|
2444
|
+
expiresAt: z.string(),
|
|
2445
|
+
expiresInSeconds: z.number().int().positive()
|
|
2446
|
+
});
|
|
2447
|
+
var EnrollTokenExchangeRequest = z.object({
|
|
2448
|
+
// The `oget_` enroll token (the auth + the workspace/account/consent grant).
|
|
2449
|
+
token: z.string().min(1),
|
|
2450
|
+
// The agent's ed25519 public key (the machine identity the enrollment binds to).
|
|
2451
|
+
publicKey: z.string().min(1).max(1024),
|
|
2452
|
+
os: EnrollmentOs.default("linux"),
|
|
2453
|
+
arch: EnrollmentArch.default("x86_64"),
|
|
2454
|
+
machineName: z.string().min(1).max(256).optional(),
|
|
2455
|
+
// v1 only supports whole-machine; kept explicit so the consent is recorded.
|
|
2456
|
+
exposure: z.literal("whole-machine").default("whole-machine"),
|
|
2457
|
+
canOfferDisplay: z.boolean().default(false),
|
|
2458
|
+
// The agent's REQUEST; the token's allowScreenControl is the AUTHORITATIVE consent.
|
|
2459
|
+
requestsScreenControl: z.boolean().default(false)
|
|
2460
|
+
});
|
|
2461
|
+
var EnrollTokenExchangeResponse = z.object({
|
|
2462
|
+
credentials: EnrollmentCredentialsResponse
|
|
2463
|
+
});
|
|
2464
|
+
var MetricSample = z.object({
|
|
2465
|
+
cpuPct: z.number(),
|
|
2466
|
+
load1: z.number(),
|
|
2467
|
+
load5: z.number(),
|
|
2468
|
+
load15: z.number(),
|
|
2469
|
+
memUsedBytes: z.number().int(),
|
|
2470
|
+
memTotalBytes: z.number().int(),
|
|
2471
|
+
diskUsedBytes: z.number().int(),
|
|
2472
|
+
diskTotalBytes: z.number().int(),
|
|
2473
|
+
gpuUtilPct: z.number().nullable(),
|
|
2474
|
+
gpuMemBytes: z.number().int().nullable(),
|
|
2475
|
+
runQueue: z.number(),
|
|
2476
|
+
sampledAt: z.string()
|
|
2477
|
+
});
|
|
2478
|
+
var MachineState = z.enum([
|
|
2479
|
+
"online",
|
|
2480
|
+
"reconnecting",
|
|
2481
|
+
"offline",
|
|
2482
|
+
"consent_required",
|
|
2483
|
+
"display_unavailable",
|
|
2484
|
+
"enrolling"
|
|
2485
|
+
]);
|
|
2486
|
+
var MachineKind = z.enum(["modal", "selfhosted"]);
|
|
2487
|
+
var MachineView = z.object({
|
|
2488
|
+
sandboxId: z.string(),
|
|
2489
|
+
enrollmentId: z.string().nullable(),
|
|
2490
|
+
name: z.string(),
|
|
2491
|
+
kind: MachineKind,
|
|
2492
|
+
state: MachineState,
|
|
2493
|
+
active: z.boolean(),
|
|
2494
|
+
isSessionGroup: z.boolean(),
|
|
2495
|
+
os: z.string(),
|
|
2496
|
+
arch: z.string(),
|
|
2497
|
+
hasDisplay: z.boolean(),
|
|
2498
|
+
allowScreenControl: z.boolean(),
|
|
2499
|
+
sharedSessionCount: z.number().int(),
|
|
2500
|
+
lastSeenAt: z.string().nullable(),
|
|
2501
|
+
metrics: MetricSample.nullable()
|
|
2502
|
+
});
|
|
2503
|
+
var MachinesResponse = z.object({
|
|
2504
|
+
activeSandboxId: z.string().nullable(),
|
|
2505
|
+
activeEpoch: z.number().int(),
|
|
2506
|
+
machines: z.array(MachineView)
|
|
2507
|
+
});
|
|
2508
|
+
var SwapActiveSandboxRequest = z.object({
|
|
2509
|
+
target: z.string().min(1)
|
|
2510
|
+
});
|
|
2511
|
+
var SwapActiveSandboxResponse = z.object({
|
|
2512
|
+
swapped: z.boolean(),
|
|
2513
|
+
activeSandboxId: z.string().nullable(),
|
|
2514
|
+
activeEpoch: z.number().int(),
|
|
2515
|
+
reason: z.string().optional()
|
|
2516
|
+
});
|
|
2517
|
+
var MachineMetricsSeriesResponse = z.object({
|
|
2518
|
+
samples: z.array(MetricSample)
|
|
2519
|
+
});
|
|
2520
|
+
var ClientModel = z.object({
|
|
2521
|
+
id: z.string(),
|
|
2522
|
+
label: z.string(),
|
|
2523
|
+
provider: z.string(),
|
|
2524
|
+
// provider id
|
|
2525
|
+
providerLabel: z.string(),
|
|
2526
|
+
api: z.enum(["responses", "chat"]),
|
|
2527
|
+
contextWindowTokens: z.number().int().positive().optional()
|
|
2528
|
+
});
|
|
1113
2529
|
var ClientConfig = z.object({
|
|
1114
2530
|
deploymentRevision: z.string(),
|
|
1115
2531
|
defaultModel: z.string(),
|
|
1116
2532
|
allowedModels: z.array(z.string()).min(1),
|
|
2533
|
+
// Richer model list (provider-grouped) for the picker. Defaults to [] for
|
|
2534
|
+
// back-compat: callers that only read allowedModels are unaffected.
|
|
2535
|
+
models: z.array(ClientModel).default([]),
|
|
1117
2536
|
defaultReasoningEffort: ReasoningEffort,
|
|
1118
2537
|
allowedReasoningEfforts: z.array(ReasoningEffort).min(1),
|
|
1119
2538
|
mcpServers: z.array(z.object({
|
|
@@ -1125,7 +2544,16 @@ var ClientConfig = z.object({
|
|
|
1125
2544
|
maxSizeBytes: z.number().int().positive()
|
|
1126
2545
|
}),
|
|
1127
2546
|
productAccessMode: ProductAccessMode,
|
|
1128
|
-
auth: ClientAuthConfig.default({ mode: "none" })
|
|
2547
|
+
auth: ClientAuthConfig.default({ mode: "none" }),
|
|
2548
|
+
// Server-wide hint: does this deployment support Channel-A structured services
|
|
2549
|
+
// at all (P4.4). Per-session availability is negotiated on /stream-capabilities
|
|
2550
|
+
// (it depends on the session's pinned backend); this is the coarse on/off the
|
|
2551
|
+
// client uses to decide whether to even attempt the fs/git/terminal panels.
|
|
2552
|
+
structuredServices: z.object({
|
|
2553
|
+
fileSystem: z.boolean(),
|
|
2554
|
+
git: z.boolean(),
|
|
2555
|
+
terminalEvents: z.boolean()
|
|
2556
|
+
}).default({ fileSystem: false, git: false, terminalEvents: false })
|
|
1129
2557
|
});
|
|
1130
2558
|
function base64UrlEncode(value) {
|
|
1131
2559
|
return Buffer.from(value, "utf8").toString("base64url");
|
|
@@ -1161,10 +2589,15 @@ export {
|
|
|
1161
2589
|
AccessGrant,
|
|
1162
2590
|
AccountGrant,
|
|
1163
2591
|
AccountRole,
|
|
2592
|
+
AcknowledgeStreamRequest,
|
|
2593
|
+
AcknowledgeStreamResponse,
|
|
1164
2594
|
AddDocumentRequest,
|
|
2595
|
+
AddWorkspaceMemberRequest,
|
|
1165
2596
|
ApiKey,
|
|
2597
|
+
AttachViewerRequest,
|
|
1166
2598
|
BillingBalance,
|
|
1167
2599
|
BillingMode,
|
|
2600
|
+
CAPABILITY_DESCRIPTORS,
|
|
1168
2601
|
CLEARED_RUN_STATE_BLOB,
|
|
1169
2602
|
CLEARED_RUN_STATE_MARKER,
|
|
1170
2603
|
CapabilityCatalogItem,
|
|
@@ -1181,9 +2614,11 @@ export {
|
|
|
1181
2614
|
CapabilityPackSkillFile,
|
|
1182
2615
|
CapabilityRuntime,
|
|
1183
2616
|
CapabilitySource,
|
|
2617
|
+
CapabilityUnavailableReason,
|
|
1184
2618
|
ClearSessionContextRequest,
|
|
1185
2619
|
ClientAuthConfig,
|
|
1186
2620
|
ClientConfig,
|
|
2621
|
+
ClientModel,
|
|
1187
2622
|
ClientSessionEvent,
|
|
1188
2623
|
CompactSessionContextRequest,
|
|
1189
2624
|
CompactSessionContextResult,
|
|
@@ -1202,7 +2637,20 @@ export {
|
|
|
1202
2637
|
CreateSocialPostRequest,
|
|
1203
2638
|
CreateWorkspaceEnvironmentRequest,
|
|
1204
2639
|
CreateWorkspaceRequest,
|
|
2640
|
+
DESKTOP_STREAM_PORT,
|
|
1205
2641
|
DelegatedAccessTokenPayload,
|
|
2642
|
+
DeviceEnrollmentApproveRequest,
|
|
2643
|
+
DeviceEnrollmentApproveResponse,
|
|
2644
|
+
DeviceEnrollmentDenyRequest,
|
|
2645
|
+
DeviceEnrollmentDenyResponse,
|
|
2646
|
+
DeviceEnrollmentLookupMachine,
|
|
2647
|
+
DeviceEnrollmentLookupRequest,
|
|
2648
|
+
DeviceEnrollmentLookupResponse,
|
|
2649
|
+
DeviceEnrollmentPollRequest,
|
|
2650
|
+
DeviceEnrollmentPollResponse,
|
|
2651
|
+
DeviceEnrollmentStartRequest,
|
|
2652
|
+
DeviceEnrollmentStartResponse,
|
|
2653
|
+
DeviceEnrollmentState,
|
|
1206
2654
|
DiscoverMcpCapabilitiesResponse,
|
|
1207
2655
|
Document,
|
|
1208
2656
|
DocumentBase,
|
|
@@ -1211,6 +2659,15 @@ export {
|
|
|
1211
2659
|
DocumentStatus,
|
|
1212
2660
|
EnableCapabilityRequest,
|
|
1213
2661
|
EnablePackRequest,
|
|
2662
|
+
EnrollTokenExchangeRequest,
|
|
2663
|
+
EnrollTokenExchangeResponse,
|
|
2664
|
+
EnrollTokenPayload,
|
|
2665
|
+
EnrollmentArch,
|
|
2666
|
+
EnrollmentBearerPayload,
|
|
2667
|
+
EnrollmentCredentialsResponse,
|
|
2668
|
+
EnrollmentOs,
|
|
2669
|
+
EnrollmentSummary,
|
|
2670
|
+
EntitlementDecision,
|
|
1214
2671
|
EntitlementValue,
|
|
1215
2672
|
Entitlements,
|
|
1216
2673
|
EntitlementsMode,
|
|
@@ -1221,25 +2678,85 @@ export {
|
|
|
1221
2678
|
FileResourceRef,
|
|
1222
2679
|
FileStatus,
|
|
1223
2680
|
FileUploadStatus,
|
|
2681
|
+
FsChangeKind,
|
|
2682
|
+
FsChangedPayload,
|
|
2683
|
+
FsDeleteRequest,
|
|
2684
|
+
FsDeleteResponse,
|
|
2685
|
+
FsEncoding,
|
|
2686
|
+
FsListRequest,
|
|
2687
|
+
FsListResponse,
|
|
2688
|
+
FsMkdirRequest,
|
|
2689
|
+
FsMkdirResponse,
|
|
2690
|
+
FsMoveRequest,
|
|
2691
|
+
FsMoveResponse,
|
|
2692
|
+
FsNodeType,
|
|
2693
|
+
FsReadRequest,
|
|
2694
|
+
FsReadResponse,
|
|
2695
|
+
FsTreeNode,
|
|
2696
|
+
FsWriteRequest,
|
|
2697
|
+
FsWriteResponse,
|
|
2698
|
+
GitChangedPayload,
|
|
2699
|
+
GitCommit,
|
|
2700
|
+
GitDiffHunk,
|
|
2701
|
+
GitDiffLine,
|
|
2702
|
+
GitDiffLineType,
|
|
2703
|
+
GitDiffRequest,
|
|
2704
|
+
GitDiffResponse,
|
|
2705
|
+
GitFileDiff,
|
|
2706
|
+
GitFileStatus,
|
|
2707
|
+
GitFileStatusCode,
|
|
1224
2708
|
GitHubAppManifestCreate,
|
|
1225
2709
|
GitHubRepository,
|
|
2710
|
+
GitLogRequest,
|
|
2711
|
+
GitLogResponse,
|
|
2712
|
+
GitShowRequest,
|
|
2713
|
+
GitShowResponse,
|
|
2714
|
+
GitStatusRequest,
|
|
2715
|
+
GitStatusResponse,
|
|
1226
2716
|
GoalSpec,
|
|
1227
2717
|
LimitAction,
|
|
1228
2718
|
LimitDecision,
|
|
2719
|
+
ListEnrollmentsResponse,
|
|
2720
|
+
ListWorkspaceMembersResponse,
|
|
2721
|
+
MachineKind,
|
|
2722
|
+
MachineMetricsSeriesResponse,
|
|
2723
|
+
MachineState,
|
|
2724
|
+
MachineView,
|
|
2725
|
+
MachinesResponse,
|
|
1229
2726
|
ManagedAccount,
|
|
1230
2727
|
MarketingDailyAnalysisTaskRequest,
|
|
2728
|
+
MetricSample,
|
|
2729
|
+
MintEnrollTokenRequest,
|
|
2730
|
+
MintEnrollTokenResponse,
|
|
1231
2731
|
PackInstallation,
|
|
1232
2732
|
PackInstallationStatus,
|
|
1233
2733
|
PageInfo,
|
|
1234
2734
|
Permission,
|
|
1235
2735
|
ProductAccessMode,
|
|
2736
|
+
PtyCloseRequest,
|
|
2737
|
+
PtyOpenRequest,
|
|
2738
|
+
PtyOpenResponse,
|
|
2739
|
+
PtyResizeRequest,
|
|
2740
|
+
PtyWriteRequest,
|
|
1236
2741
|
ReasoningEffort,
|
|
2742
|
+
RecordingAvailablePayload,
|
|
2743
|
+
RecordingCodec,
|
|
2744
|
+
RecordingContentType,
|
|
2745
|
+
RecordingFailedPayload,
|
|
2746
|
+
RecordingFailedReason,
|
|
2747
|
+
RecordingMode,
|
|
2748
|
+
RecordingStartedPayload,
|
|
1237
2749
|
RegisterCapabilityPackRequest,
|
|
2750
|
+
RelayTokenPayload,
|
|
1238
2751
|
ReorderSessionTurnsRequest,
|
|
1239
2752
|
RepositoryResourceRef,
|
|
1240
2753
|
ResourceRef,
|
|
1241
2754
|
ResourceRefConflictError,
|
|
2755
|
+
RevokeEnrollmentResponse,
|
|
1242
2756
|
SandboxBackend,
|
|
2757
|
+
SandboxCapabilityName,
|
|
2758
|
+
SandboxCommandOutputDeltaPayload,
|
|
2759
|
+
SandboxOs,
|
|
1243
2760
|
ScheduledTask,
|
|
1244
2761
|
ScheduledTaskAgentConfig,
|
|
1245
2762
|
ScheduledTaskOverlapPolicy,
|
|
@@ -1251,6 +2768,7 @@ export {
|
|
|
1251
2768
|
ScheduledTaskTriggerType,
|
|
1252
2769
|
Session,
|
|
1253
2770
|
SessionBusMessage,
|
|
2771
|
+
SessionCapabilities,
|
|
1254
2772
|
SessionEvent,
|
|
1255
2773
|
SessionEventType,
|
|
1256
2774
|
SessionGoal,
|
|
@@ -1258,6 +2776,7 @@ export {
|
|
|
1258
2776
|
SessionGoalPausedReason,
|
|
1259
2777
|
SessionGoalStatus,
|
|
1260
2778
|
SessionStatus,
|
|
2779
|
+
SessionStructuredCapabilities,
|
|
1261
2780
|
SessionTurn,
|
|
1262
2781
|
SessionTurnSource,
|
|
1263
2782
|
SessionTurnStatus,
|
|
@@ -1267,20 +2786,39 @@ export {
|
|
|
1267
2786
|
SocialPost,
|
|
1268
2787
|
SocialProvider,
|
|
1269
2788
|
StaticUsageLimits,
|
|
2789
|
+
StreamClosedPayload,
|
|
2790
|
+
StreamOpenedPayload,
|
|
2791
|
+
StreamRevokedPayload,
|
|
2792
|
+
StreamTokenPayload,
|
|
2793
|
+
StreamUrlRotatedPayload,
|
|
2794
|
+
SwapActiveSandboxRequest,
|
|
2795
|
+
SwapActiveSandboxResponse,
|
|
2796
|
+
TERMINAL_STREAM_PORT,
|
|
2797
|
+
TerminalExecRequest,
|
|
2798
|
+
TerminalExecResponse,
|
|
2799
|
+
TerminalPtyExitedPayload,
|
|
2800
|
+
TerminalPtyOutputDeltaPayload,
|
|
2801
|
+
TerminalPtyStartedPayload,
|
|
1270
2802
|
ToolRef,
|
|
1271
2803
|
TriggerScheduledTaskRequest,
|
|
1272
2804
|
UpdateScheduledTaskRequest,
|
|
1273
2805
|
UpdateSessionGoalRequest,
|
|
2806
|
+
UpdateSessionRequest,
|
|
1274
2807
|
UpdateSessionTurnRequest,
|
|
1275
2808
|
UpdateWorkspaceEnvironmentRequest,
|
|
2809
|
+
UpdateWorkspaceMemberRequest,
|
|
1276
2810
|
UpdateWorkspaceRequest,
|
|
1277
2811
|
UsageEvent,
|
|
1278
2812
|
UsageEventType,
|
|
1279
2813
|
UsageLimitsMode,
|
|
2814
|
+
ViewerHeartbeatRequest,
|
|
2815
|
+
ViewerHeartbeatResponse,
|
|
2816
|
+
ViewerHolder,
|
|
1280
2817
|
Workspace,
|
|
1281
2818
|
WorkspaceEnvironment,
|
|
1282
2819
|
WorkspaceEnvironmentVariableMetadata,
|
|
1283
2820
|
WorkspaceEnvironmentVariableName,
|
|
2821
|
+
WorkspaceMember,
|
|
1284
2822
|
WorkspaceRegisteredPack,
|
|
1285
2823
|
isClearedRunStateBlob,
|
|
1286
2824
|
mergeResourceRefs,
|
|
@@ -1289,7 +2827,15 @@ export {
|
|
|
1289
2827
|
reasoningEffortForMetadata,
|
|
1290
2828
|
resourceIdentityKey,
|
|
1291
2829
|
signDelegatedAccessToken,
|
|
2830
|
+
signEnrollToken,
|
|
2831
|
+
signEnrollmentBearer,
|
|
2832
|
+
signRelayToken,
|
|
2833
|
+
signStreamToken,
|
|
1292
2834
|
stableJson,
|
|
1293
|
-
verifyDelegatedAccessToken
|
|
2835
|
+
verifyDelegatedAccessToken,
|
|
2836
|
+
verifyEnrollToken,
|
|
2837
|
+
verifyEnrollmentBearer,
|
|
2838
|
+
verifyRelayToken,
|
|
2839
|
+
verifyStreamToken
|
|
1294
2840
|
};
|
|
1295
2841
|
//# sourceMappingURL=index.js.map
|