@opengeni/contracts 0.3.0 → 0.5.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.js CHANGED
@@ -18,7 +18,8 @@ var SandboxBackend = z.enum([
18
18
  "e2b",
19
19
  "blaxel",
20
20
  "cloudflare",
21
- "vercel"
21
+ "vercel",
22
+ "selfhosted"
22
23
  ]);
23
24
  var SandboxOs = z.enum(["linux", "macos", "windows"]);
24
25
  var SandboxCapabilityName = z.enum([
@@ -295,6 +296,58 @@ var CAPABILITY_DESCRIPTORS = {
295
296
  nativeBucketMount: false,
296
297
  persistable: false,
297
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
298
351
  }
299
352
  };
300
353
  var ReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh"]);
@@ -372,7 +425,18 @@ var Permission = z.enum([
372
425
  "api_keys:manage",
373
426
  "environments:manage",
374
427
  "environments:use",
375
- "goals:manage"
428
+ // Attach or rotate per-session third-party MCP server credentials. Deliberately
429
+ // not part of the worker's default first-party MCP permission set: a sandboxed
430
+ // agent must not be able to hand itself new bearer credentials.
431
+ "mcp_servers:attach",
432
+ "goals:manage",
433
+ // Bring-your-own-compute (M5). enrollments:read lists a workspace's machines;
434
+ // enrollments:manage approves a device-flow enrollment (the LOUD whole-machine
435
+ // consent) + revokes a machine. Distinct from sessions/stream perms because an
436
+ // enrollment grants WHOLE-MACHINE access to a user's own hardware — a high-trust,
437
+ // admin-shaped action. workspace:admin is the super-wildcard over both.
438
+ "enrollments:read",
439
+ "enrollments:manage"
376
440
  ]);
377
441
  var ProductAccessMode = z.enum(["local", "configured", "managed"]);
378
442
  var BillingMode = z.enum(["disabled", "stripe"]);
@@ -465,6 +529,84 @@ async function verifyDelegatedAccessToken(secret, token, nowSeconds = Math.floor
465
529
  }
466
530
  return payload.data;
467
531
  }
532
+ var EnrollmentBearerPayload = z.object({
533
+ workspaceId: z.string().uuid(),
534
+ agentId: z.string().uuid(),
535
+ enrollmentId: z.string().uuid(),
536
+ // The Account-scoped control-plane subject prefix the agent subscribes to.
537
+ subjectPrefix: z.string().min(1),
538
+ exp: z.number().int().positive()
539
+ });
540
+ async function signEnrollmentBearer(secret, payload) {
541
+ const encodedPayload = base64UrlEncode(JSON.stringify(EnrollmentBearerPayload.parse(payload)));
542
+ const signature = await hmacSha256Base64Url(secret, encodedPayload);
543
+ return `oge_${encodedPayload}.${signature}`;
544
+ }
545
+ async function verifyEnrollmentBearer(secret, token, nowSeconds = Math.floor(Date.now() / 1e3)) {
546
+ if (!token.startsWith("oge_")) {
547
+ return null;
548
+ }
549
+ const withoutPrefix = token.slice("oge_".length);
550
+ const dot = withoutPrefix.lastIndexOf(".");
551
+ if (dot <= 0) {
552
+ return null;
553
+ }
554
+ const encodedPayload = withoutPrefix.slice(0, dot);
555
+ const signature = withoutPrefix.slice(dot + 1);
556
+ const expected = await hmacSha256Base64Url(secret, encodedPayload);
557
+ if (!constantTimeEqual(signature, expected)) {
558
+ return null;
559
+ }
560
+ const payload = EnrollmentBearerPayload.safeParse(JSON.parse(base64UrlDecode(encodedPayload)));
561
+ if (!payload.success || payload.data.exp < nowSeconds) {
562
+ return null;
563
+ }
564
+ return payload.data;
565
+ }
566
+ var EnrollTokenPayload = z.object({
567
+ // Domain-separation claim — fixed "enroll" so an `oge_`/`ogd_`/`ogs_` payload (no
568
+ // typ, or a different typ) can never satisfy verifyEnrollToken even past the prefix.
569
+ typ: z.literal("enroll"),
570
+ workspaceId: z.string().uuid(),
571
+ accountId: z.string().uuid(),
572
+ // The screen-control consent baked into the token at mint (the minting user's
573
+ // decision); the exchange records it as consentedScreenControl on the enrollment.
574
+ allowScreenControl: z.boolean(),
575
+ iat: z.number().int().nonnegative(),
576
+ exp: z.number().int().positive()
577
+ });
578
+ async function signEnrollToken(secret, payload) {
579
+ const encodedPayload = base64UrlEncode(JSON.stringify(EnrollTokenPayload.parse(payload)));
580
+ const signature = await hmacSha256Base64Url(secret, encodedPayload);
581
+ return `oget_${encodedPayload}.${signature}`;
582
+ }
583
+ async function verifyEnrollToken(secret, token, nowSeconds = Math.floor(Date.now() / 1e3)) {
584
+ if (!token.startsWith("oget_")) {
585
+ return null;
586
+ }
587
+ const withoutPrefix = token.slice("oget_".length);
588
+ const dot = withoutPrefix.lastIndexOf(".");
589
+ if (dot <= 0) {
590
+ return null;
591
+ }
592
+ const encodedPayload = withoutPrefix.slice(0, dot);
593
+ const signature = withoutPrefix.slice(dot + 1);
594
+ const expected = await hmacSha256Base64Url(secret, encodedPayload);
595
+ if (!constantTimeEqual(signature, expected)) {
596
+ return null;
597
+ }
598
+ let decoded;
599
+ try {
600
+ decoded = JSON.parse(base64UrlDecode(encodedPayload));
601
+ } catch {
602
+ return null;
603
+ }
604
+ const payload = EnrollTokenPayload.safeParse(decoded);
605
+ if (!payload.success || payload.data.exp < nowSeconds) {
606
+ return null;
607
+ }
608
+ return payload.data;
609
+ }
468
610
  var StreamTokenPayload = z.object({
469
611
  workspaceId: z.string().uuid(),
470
612
  sessionId: z.string().uuid(),
@@ -512,6 +654,47 @@ async function verifyStreamToken(secret, token, nowSeconds = Math.floor(Date.now
512
654
  }
513
655
  return payload.data;
514
656
  }
657
+ var RelayTokenPayload = z.object({
658
+ // The workspace the agent (and its channels) belong to — the relay asserts this
659
+ // equals the channel-key's ws so a producer can only register its own channels.
660
+ workspaceId: z.string().uuid(),
661
+ // The agent (machine) id — the relay asserts this equals the channel-key's agent.
662
+ agentId: z.string().uuid(),
663
+ // Expiry (unix seconds). Enrollment-scoped horizon (re-minted on re-enroll).
664
+ exp: z.number().int().positive()
665
+ });
666
+ async function signRelayToken(secret, payload) {
667
+ const encodedPayload = base64UrlEncode(JSON.stringify(RelayTokenPayload.parse(payload)));
668
+ const signature = await hmacSha256Base64Url(secret, encodedPayload);
669
+ return `ogr_${encodedPayload}.${signature}`;
670
+ }
671
+ async function verifyRelayToken(secret, token, nowSeconds = Math.floor(Date.now() / 1e3)) {
672
+ if (!token.startsWith("ogr_")) {
673
+ return null;
674
+ }
675
+ const withoutPrefix = token.slice("ogr_".length);
676
+ const dot = withoutPrefix.lastIndexOf(".");
677
+ if (dot <= 0) {
678
+ return null;
679
+ }
680
+ const encodedPayload = withoutPrefix.slice(0, dot);
681
+ const signature = withoutPrefix.slice(dot + 1);
682
+ const expected = await hmacSha256Base64Url(secret, encodedPayload);
683
+ if (!constantTimeEqual(signature, expected)) {
684
+ return null;
685
+ }
686
+ let decoded;
687
+ try {
688
+ decoded = JSON.parse(base64UrlDecode(encodedPayload));
689
+ } catch {
690
+ return null;
691
+ }
692
+ const payload = RelayTokenPayload.safeParse(decoded);
693
+ if (!payload.success || payload.data.exp < nowSeconds) {
694
+ return null;
695
+ }
696
+ return payload.data;
697
+ }
515
698
  var CreateWorkspaceRequest = z.object({
516
699
  accountId: z.string().uuid().optional(),
517
700
  name: z.string().min(1),
@@ -634,6 +817,10 @@ var LimitDecision = z.discriminatedUnion("allowed", [
634
817
  z.object({ allowed: z.literal(true) }),
635
818
  z.object({ allowed: z.literal(false), code: z.string(), message: z.string() })
636
819
  ]);
820
+ var EntitlementDecision = z.discriminatedUnion("allowed", [
821
+ z.object({ allowed: z.literal(true), quantity: z.number().optional() }),
822
+ z.object({ allowed: z.literal(false), reason: z.string(), code: z.string().optional(), quantity: z.number().optional() })
823
+ ]);
637
824
  var BillingBalance = z.object({
638
825
  accountId: z.string().uuid(),
639
826
  balanceMicros: z.number().int(),
@@ -752,8 +939,45 @@ var DocumentSearchRequest = z.object({
752
939
  });
753
940
  var ToolRef = z.object({
754
941
  kind: z.literal("mcp"),
755
- id: z.string().min(1)
756
- });
942
+ id: z.string().min(1),
943
+ // Non-fatal-on-connect marker for MCP server refs that can degrade
944
+ // gracefully. Absent/false is STRICT: the id must be configured and an
945
+ // unavailable server fails the turn. `optional:true` is preserved for known
946
+ // servers and makes runtime connect/list failures skip that server; if the
947
+ // deployment does not configure the id, validation drops the ref. The server
948
+ // also sets this for auto-attached workspace-default capability MCPs.
949
+ optional: z.boolean().optional()
950
+ });
951
+ var registryId = /^[A-Za-z0-9_-]+$/;
952
+ var httpsUrl = z.string().url().refine((value) => {
953
+ try {
954
+ return new URL(value).protocol === "https:";
955
+ } catch {
956
+ return false;
957
+ }
958
+ }, { message: "URL must use https" });
959
+ var SessionMcpServerInput = z.object({
960
+ id: z.string().min(1).regex(registryId),
961
+ name: z.string().min(1).optional(),
962
+ url: httpsUrl,
963
+ allowedTools: z.array(z.string().min(1)).optional(),
964
+ timeoutMs: z.number().int().positive().optional(),
965
+ cacheToolsList: z.boolean().optional(),
966
+ // Write-only credential headers. Values are encrypted at rest and never
967
+ // returned in session responses or events; response metadata exposes names.
968
+ headers: z.record(z.string(), z.string()).optional()
969
+ });
970
+ var SessionMcpCredentialUpdateInput = z.object({
971
+ id: z.string().min(1).regex(registryId),
972
+ headers: z.record(z.string(), z.string())
973
+ });
974
+ var SessionMcpServerMetadata = z.object({
975
+ id: z.string().min(1).regex(registryId),
976
+ name: z.string().min(1).nullable(),
977
+ url: httpsUrl,
978
+ headerNames: z.array(z.string()).default([]),
979
+ credentialVersion: z.number().int().positive()
980
+ }).strict();
757
981
  var ResourceRefConflictError = class extends Error {
758
982
  constructor(message) {
759
983
  super(message);
@@ -761,17 +985,22 @@ var ResourceRefConflictError = class extends Error {
761
985
  }
762
986
  };
763
987
  function mergeToolRefs(existing, additions) {
764
- const seen = /* @__PURE__ */ new Set();
765
- const out = [];
988
+ const byKey = /* @__PURE__ */ new Map();
989
+ const order = [];
766
990
  for (const tool of [...existing, ...additions]) {
767
991
  const key = `${tool.kind}:${tool.id}`;
768
- if (seen.has(key)) {
992
+ const prior = byKey.get(key);
993
+ if (!prior) {
994
+ byKey.set(key, tool);
995
+ order.push(key);
769
996
  continue;
770
997
  }
771
- seen.add(key);
772
- out.push(tool);
998
+ if (prior.optional === true && tool.optional !== true) {
999
+ const { optional: _dropped, ...strict } = prior;
1000
+ byKey.set(key, strict);
1001
+ }
773
1002
  }
774
- return out;
1003
+ return order.map((key) => byKey.get(key));
775
1004
  }
776
1005
  function mergeResourceRefs(existing, additions, options = {}) {
777
1006
  const out = [...existing];
@@ -1346,10 +1575,20 @@ var Session = z.object({
1346
1575
  // own id for a singleton group (today's 1:1 default); equals the parent's
1347
1576
  // group when spawned shared (both sessions run in ONE box).
1348
1577
  sandboxGroupId: z.string().uuid(),
1578
+ // The first-class swappable-sandbox POINTER (bring-your-own-compute M2). NULL
1579
+ // resolves to the session's own group sandbox (the backward-compat default);
1580
+ // a swap sets it to the target sandbox row. active_epoch is the second epoch
1581
+ // ABOVE the lease epoch, bumped on every swap so the routing proxy can fence a
1582
+ // stale in-flight op and retry against the new active sandbox.
1583
+ activeSandboxId: z.string().uuid().nullable(),
1584
+ activeEpoch: z.number().int().nonnegative(),
1349
1585
  environmentId: z.string().uuid().nullable(),
1350
1586
  // Non-default first-party MCP token permissions (manager-style sessions);
1351
1587
  // null means the fixed worker default set.
1352
1588
  firstPartyMcpPermissions: z.array(Permission).nullable(),
1589
+ // Per-session third-party MCP servers, metadata only. Credential values are
1590
+ // write-only and never appear here.
1591
+ mcpServers: z.array(SessionMcpServerMetadata).default([]),
1353
1592
  // The manager session that spawned this one via session_create (set only
1354
1593
  // when the creating grant carried a worker-signed sessionId claim); null for
1355
1594
  // direct API creates and scheduled-task runs. When set, this session's
@@ -1366,6 +1605,12 @@ var Session = z.object({
1366
1605
  // signal. Null until a turn with usage has completed.
1367
1606
  lastInputTokens: z.number().int().nonnegative().nullable(),
1368
1607
  lastSequence: z.number().int().nonnegative(),
1608
+ // Multi-account Codex (P1). codexPinnedCredentialId: the account this session is
1609
+ // manually PINNED to (null ⇒ follow the workspace active pointer).
1610
+ // codexLastCredentialId: the account the most recent turn actually ran on (the
1611
+ // "Running on:" indicator's source). Both are credential-row ids, null until set.
1612
+ codexPinnedCredentialId: z.string().uuid().nullable(),
1613
+ codexLastCredentialId: z.string().uuid().nullable(),
1369
1614
  createdAt: z.string(),
1370
1615
  updatedAt: z.string()
1371
1616
  });
@@ -1441,7 +1686,11 @@ var SessionEventType = z.enum([
1441
1686
  // PTY stdout/stderr bytes (separate from command.output)
1442
1687
  "terminal.pty.exited",
1443
1688
  // PTY session ended (exitCode/reason)
1444
- "session.title_set"
1689
+ "session.title_set",
1690
+ // Multi-account Codex (P1): the account a session's turn runs on changed
1691
+ // (manual switch in P1; failover/rotation in P3 reuse the same event). Drives
1692
+ // the in-session "Running on:" indicator's live flip.
1693
+ "codex.account.switched"
1445
1694
  ]);
1446
1695
  var StreamUrlRotatedPayload = z.object({
1447
1696
  url: z.string().url(),
@@ -1847,6 +2096,17 @@ var CreateSessionRequest = z.object({
1847
2096
  model: z.string().min(1).optional(),
1848
2097
  reasoningEffort: ReasoningEffort.optional(),
1849
2098
  sandboxBackend: SandboxBackend.optional(),
2099
+ // The enrolled machine (a sandbox id) to run this session on; seeds the
2100
+ // active-sandbox pointer at creation so the FIRST turn routes to the chosen
2101
+ // machine (race-free: the pointer is committed before the worker turn
2102
+ // workflow can read it). An invalid/unowned/offline target fails the create.
2103
+ targetSandboxId: z.string().uuid().optional(),
2104
+ // The working directory the targeted machine runs the session under — the
2105
+ // path/cwd base for its agent exec, terminal, and file dock. Free-form pass-
2106
+ // through: a launch-workspace_root-relative subdir or an absolute machine path
2107
+ // (the agent's resolve_cwd handles both). Only valid WITH targetSandboxId
2108
+ // (workingDir alone is a 422); omitted ⇒ the machine's default workspace_root.
2109
+ workingDir: z.string().min(1).optional(),
1850
2110
  // Workspace environment attachment is fixed at session creation; follow-up
1851
2111
  // user.message events cannot switch or add one.
1852
2112
  environmentId: z.string().uuid().optional(),
@@ -1864,6 +2124,9 @@ var CreateSessionRequest = z.object({
1864
2124
  // the orchestration/environment/github tools. Capped at creation: every
1865
2125
  // requested permission must be held by the creating grant (no escalation).
1866
2126
  firstPartyMcpPermissions: z.array(Permission).optional(),
2127
+ // Third-party MCP servers attached only to this session. Credential headers are
2128
+ // write-only: create responses and events expose only SessionMcpServerMetadata.
2129
+ mcpServers: z.array(SessionMcpServerInput).default([]),
1867
2130
  // Shared-sandbox placement (addendum 05 §D.1). Three-way union; OMITTED ⇒
1868
2131
  // today's behavior (a context-dependent default resolved server-side: from
1869
2132
  // inside a session → "shared" with the creator's box, top-level → "new").
@@ -1876,6 +2139,11 @@ var CreateSessionRequest = z.object({
1876
2139
  // A shared spawn inherits the box's (backend, os) — it is literally the same
1877
2140
  // box; the child cannot pick its own backend. Cross-workspace sharing is
1878
2141
  // forbidden by construction (the parent/group reads are RLS-workspace-scoped).
2142
+ // ENV-AWARE: the box's environment is fixed at creation, so a share requires
2143
+ // the SAME environmentId as the creator's box. On a mismatch the inherited
2144
+ // default silently falls back to an own box; an explicit "shared"/{groupId}
2145
+ // request 422s at create (instead of the first turn dying on the SDK's
2146
+ // manifest-env guard).
1879
2147
  sandbox: z.union([
1880
2148
  z.literal("shared"),
1881
2149
  z.literal("new"),
@@ -1891,7 +2159,10 @@ var ClientSessionEvent = z.discriminatedUnion("type", [
1891
2159
  resources: z.array(ResourceRef).default([]),
1892
2160
  tools: z.array(ToolRef).default([]),
1893
2161
  model: z.string().min(1).optional(),
1894
- reasoningEffort: ReasoningEffort.optional()
2162
+ reasoningEffort: ReasoningEffort.optional(),
2163
+ // Header-value rotation only. URL/name/tool settings are immutable after
2164
+ // session create; persisted events expose metadata, never header values.
2165
+ mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional()
1895
2166
  })
1896
2167
  }),
1897
2168
  z.object({
@@ -1956,7 +2227,17 @@ var CapabilityUnavailableReason = z.enum([
1956
2227
  "not_provisioned",
1957
2228
  "disabled_by_policy",
1958
2229
  "lease_cold",
1959
- "tier_headless"
2230
+ "tier_headless",
2231
+ // Selfhosted (bring-your-own-compute) negotiation states (M1 additive; the
2232
+ // selfhosted negotiation in select.ts wires them in M3):
2233
+ "agent_offline",
2234
+ // the enrolled agent process is not running / unreachable
2235
+ "agent_reconnecting",
2236
+ // a transient blip — the agent is reconnecting (warmable)
2237
+ "consent_required",
2238
+ // whole-machine / screen-control consent not yet acknowledged
2239
+ "display_unavailable"
2240
+ // headless machine with no display stack (no DesktopStream)
1960
2241
  ]);
1961
2242
  var SessionCapabilities = z.object({
1962
2243
  sessionId: z.string().uuid(),
@@ -1995,8 +2276,11 @@ var SessionCapabilities = z.object({
1995
2276
  reason: CapabilityUnavailableReason.nullable()
1996
2277
  }),
1997
2278
  DesktopStream: z.object({
1998
- transport: z.enum(["vnc-ws", "rdp-ws", "webrtc"]).nullable(),
1999
- client: z.enum(["novnc", "web-rdp"]).nullable(),
2279
+ // "relay-frames" is the selfhosted framebuffer stream: PNG-per-frame protobuf
2280
+ // datagrams spliced over the relay (NOT RFB). The viewer renders it with the
2281
+ // "frames" client (a canvas painter), distinct from Modal's "vnc-ws"/"novnc".
2282
+ transport: z.enum(["vnc-ws", "rdp-ws", "webrtc", "relay-frames"]).nullable(),
2283
+ client: z.enum(["novnc", "web-rdp", "frames"]).nullable(),
2000
2284
  mode: z.enum(["read-only", "interactive"]).default("read-only"),
2001
2285
  url: z.string().url().nullable(),
2002
2286
  token: z.string().nullable(),
@@ -2070,6 +2354,209 @@ var ViewerHeartbeatResponse = z.object({
2070
2354
  // false ⇒ the holder was reaped or the epoch is stale; the client re-attaches.
2071
2355
  alive: z.boolean()
2072
2356
  });
2357
+ var EnrollmentOs = z.enum(["linux", "macos", "windows"]);
2358
+ var EnrollmentArch = z.enum(["x86_64", "aarch64"]);
2359
+ var DeviceEnrollmentStartRequest = z.object({
2360
+ // The agent's ed25519 public key (the machine identity the enrollment binds to).
2361
+ publicKey: z.string().min(1).max(1024),
2362
+ os: EnrollmentOs.default("linux"),
2363
+ arch: EnrollmentArch.default("x86_64"),
2364
+ // Human-friendly machine name (hostname by default).
2365
+ machineName: z.string().min(1).max(256).optional(),
2366
+ // v1 only supports whole-machine; kept explicit so the consent is recorded.
2367
+ exposure: z.literal("whole-machine").default("whole-machine"),
2368
+ // The agent can offer a display (a real screen / Xvfb is available).
2369
+ canOfferDisplay: z.boolean().default(false),
2370
+ // The agent requests screen control (computer-use); the user's allow_screen_control
2371
+ // at approve is the AUTHORITATIVE consent.
2372
+ requestsScreenControl: z.boolean().default(false),
2373
+ // The workspace this machine is enrolling into. The agent is told this at install
2374
+ // (the user picks the workspace, or the install/enroll token carries it). The user
2375
+ // who approves must hold a grant in THIS workspace — that binding is what makes
2376
+ // the (user-unauthenticated) start safe: it cannot grant access to a workspace no
2377
+ // authorized user later approves in.
2378
+ workspaceId: z.string().uuid()
2379
+ });
2380
+ var DeviceEnrollmentStartResponse = z.object({
2381
+ deviceCode: z.string(),
2382
+ userCode: z.string(),
2383
+ verificationUri: z.string(),
2384
+ verificationUriComplete: z.string(),
2385
+ intervalSeconds: z.number().int().positive(),
2386
+ expiresInSeconds: z.number().int().positive()
2387
+ });
2388
+ var DeviceEnrollmentApproveRequest = z.object({
2389
+ userCode: z.string().min(1).max(64),
2390
+ allowScreenControl: z.boolean().default(false)
2391
+ });
2392
+ var DeviceEnrollmentApproveResponse = z.object({
2393
+ approved: z.boolean(),
2394
+ enrollmentId: z.string().uuid(),
2395
+ sandboxId: z.string().uuid(),
2396
+ allowScreenControl: z.boolean()
2397
+ });
2398
+ var DeviceEnrollmentPollRequest = z.object({
2399
+ deviceCode: z.string().min(1).max(256)
2400
+ });
2401
+ var DeviceEnrollmentState = z.enum(["pending", "authorized", "denied", "expired", "disabled"]);
2402
+ var EnrollmentCredentialsResponse = z.object({
2403
+ agentId: z.string().uuid(),
2404
+ workspaceId: z.string().uuid(),
2405
+ // The signed bearer the agent presents to the control plane (the `oge_` token).
2406
+ bearer: z.string(),
2407
+ // The Account-scoped control-plane subject prefix the agent subscribes to:
2408
+ // agent.<workspaceId>.<agentId>.
2409
+ subjectPrefix: z.string(),
2410
+ // Connect info for the control plane + stream relay (may be empty when not yet
2411
+ // configured for this deployment — the agent surfaces "control plane unconfigured").
2412
+ natsUrls: z.array(z.string()),
2413
+ relayUrl: z.string(),
2414
+ // The agent's PRODUCER token for the relay edge (the `ogr_` token; M8b). Presented
2415
+ // as StreamOpen.token when the agent registers a pty/desktop channel; the relay
2416
+ // verifies it then pairs the producer with the viewer (whose `ogs_` token the
2417
+ // relay also verifies). Empty when the relay-token plane is unconfigured for this
2418
+ // deployment (graceful degrade — the agent then presents an empty token the relay
2419
+ // rejects, surfacing the gap loudly rather than silently producing a dead stream).
2420
+ relayToken: z.string(),
2421
+ // VESTIGIAL (M-AUTH): there is no per-machine NATS Account creds file. The agent
2422
+ // presents the `bearer` above as the NATS connect AUTH-TOKEN; the server's
2423
+ // auth-callout responder validates it and mints a workspace-scoped user JWT. This
2424
+ // field echoes the bearer so a consumer reading it as the connect credential still
2425
+ // works; new consumers should read `bearer` directly.
2426
+ natsAccountCreds: z.string(),
2427
+ // The minisign public key the agent pins for self-update verification.
2428
+ updatePublicKey: z.string(),
2429
+ consentedWholeMachine: z.boolean(),
2430
+ consentedScreenControl: z.boolean()
2431
+ });
2432
+ var DeviceEnrollmentPollResponse = z.object({
2433
+ state: DeviceEnrollmentState,
2434
+ // Present only when state === "authorized".
2435
+ credentials: EnrollmentCredentialsResponse.optional()
2436
+ });
2437
+ var EnrollmentSummary = z.object({
2438
+ id: z.string().uuid(),
2439
+ pubkey: z.string(),
2440
+ exposure: z.literal("whole-machine"),
2441
+ hasDisplay: z.boolean(),
2442
+ allowScreenControl: z.boolean(),
2443
+ status: z.enum(["active", "revoked"]),
2444
+ os: EnrollmentOs,
2445
+ arch: z.string(),
2446
+ lastSeenAt: z.string().nullable(),
2447
+ createdAt: z.string(),
2448
+ revokedAt: z.string().nullable()
2449
+ });
2450
+ var ListEnrollmentsResponse = z.object({
2451
+ enrollments: z.array(EnrollmentSummary)
2452
+ });
2453
+ var RevokeEnrollmentResponse = z.object({
2454
+ revoked: z.boolean()
2455
+ });
2456
+ var DeviceEnrollmentLookupRequest = z.object({
2457
+ userCode: z.string().min(1).max(64)
2458
+ });
2459
+ var DeviceEnrollmentLookupMachine = z.object({
2460
+ machineName: z.string().nullable(),
2461
+ os: EnrollmentOs,
2462
+ arch: z.string(),
2463
+ canOfferDisplay: z.boolean(),
2464
+ requestsScreenControl: z.boolean()
2465
+ });
2466
+ var DeviceEnrollmentLookupResponse = z.object({
2467
+ workspaceId: z.string().uuid(),
2468
+ userCode: z.string(),
2469
+ machine: DeviceEnrollmentLookupMachine,
2470
+ expiresAt: z.string()
2471
+ });
2472
+ var DeviceEnrollmentDenyRequest = z.object({
2473
+ userCode: z.string().min(1).max(64)
2474
+ });
2475
+ var DeviceEnrollmentDenyResponse = z.object({
2476
+ denied: z.boolean()
2477
+ });
2478
+ var MintEnrollTokenRequest = z.object({
2479
+ allowScreenControl: z.boolean().default(false)
2480
+ });
2481
+ var MintEnrollTokenResponse = z.object({
2482
+ // The `oget_` token. SECRET — the UI shows it once with a copy-now warning.
2483
+ token: z.string(),
2484
+ expiresAt: z.string(),
2485
+ expiresInSeconds: z.number().int().positive()
2486
+ });
2487
+ var EnrollTokenExchangeRequest = z.object({
2488
+ // The `oget_` enroll token (the auth + the workspace/account/consent grant).
2489
+ token: z.string().min(1),
2490
+ // The agent's ed25519 public key (the machine identity the enrollment binds to).
2491
+ publicKey: z.string().min(1).max(1024),
2492
+ os: EnrollmentOs.default("linux"),
2493
+ arch: EnrollmentArch.default("x86_64"),
2494
+ machineName: z.string().min(1).max(256).optional(),
2495
+ // v1 only supports whole-machine; kept explicit so the consent is recorded.
2496
+ exposure: z.literal("whole-machine").default("whole-machine"),
2497
+ canOfferDisplay: z.boolean().default(false),
2498
+ // The agent's REQUEST; the token's allowScreenControl is the AUTHORITATIVE consent.
2499
+ requestsScreenControl: z.boolean().default(false)
2500
+ });
2501
+ var EnrollTokenExchangeResponse = z.object({
2502
+ credentials: EnrollmentCredentialsResponse
2503
+ });
2504
+ var MetricSample = z.object({
2505
+ cpuPct: z.number(),
2506
+ load1: z.number(),
2507
+ load5: z.number(),
2508
+ load15: z.number(),
2509
+ memUsedBytes: z.number().int(),
2510
+ memTotalBytes: z.number().int(),
2511
+ diskUsedBytes: z.number().int(),
2512
+ diskTotalBytes: z.number().int(),
2513
+ gpuUtilPct: z.number().nullable(),
2514
+ gpuMemBytes: z.number().int().nullable(),
2515
+ runQueue: z.number(),
2516
+ sampledAt: z.string()
2517
+ });
2518
+ var MachineState = z.enum([
2519
+ "online",
2520
+ "reconnecting",
2521
+ "offline",
2522
+ "consent_required",
2523
+ "display_unavailable",
2524
+ "enrolling"
2525
+ ]);
2526
+ var MachineKind = z.enum(["modal", "selfhosted"]);
2527
+ var MachineView = z.object({
2528
+ sandboxId: z.string(),
2529
+ enrollmentId: z.string().nullable(),
2530
+ name: z.string(),
2531
+ kind: MachineKind,
2532
+ state: MachineState,
2533
+ active: z.boolean(),
2534
+ isSessionGroup: z.boolean(),
2535
+ os: z.string(),
2536
+ arch: z.string(),
2537
+ hasDisplay: z.boolean(),
2538
+ allowScreenControl: z.boolean(),
2539
+ sharedSessionCount: z.number().int(),
2540
+ lastSeenAt: z.string().nullable(),
2541
+ metrics: MetricSample.nullable()
2542
+ });
2543
+ var MachinesResponse = z.object({
2544
+ activeSandboxId: z.string().nullable(),
2545
+ activeEpoch: z.number().int(),
2546
+ machines: z.array(MachineView)
2547
+ });
2548
+ var SwapActiveSandboxRequest = z.object({
2549
+ target: z.string().min(1)
2550
+ });
2551
+ var SwapActiveSandboxResponse = z.object({
2552
+ swapped: z.boolean(),
2553
+ activeSandboxId: z.string().nullable(),
2554
+ activeEpoch: z.number().int(),
2555
+ reason: z.string().optional()
2556
+ });
2557
+ var MachineMetricsSeriesResponse = z.object({
2558
+ samples: z.array(MetricSample)
2559
+ });
2073
2560
  var ClientModel = z.object({
2074
2561
  id: z.string(),
2075
2562
  label: z.string(),
@@ -2192,6 +2679,18 @@ export {
2192
2679
  CreateWorkspaceRequest,
2193
2680
  DESKTOP_STREAM_PORT,
2194
2681
  DelegatedAccessTokenPayload,
2682
+ DeviceEnrollmentApproveRequest,
2683
+ DeviceEnrollmentApproveResponse,
2684
+ DeviceEnrollmentDenyRequest,
2685
+ DeviceEnrollmentDenyResponse,
2686
+ DeviceEnrollmentLookupMachine,
2687
+ DeviceEnrollmentLookupRequest,
2688
+ DeviceEnrollmentLookupResponse,
2689
+ DeviceEnrollmentPollRequest,
2690
+ DeviceEnrollmentPollResponse,
2691
+ DeviceEnrollmentStartRequest,
2692
+ DeviceEnrollmentStartResponse,
2693
+ DeviceEnrollmentState,
2195
2694
  DiscoverMcpCapabilitiesResponse,
2196
2695
  Document,
2197
2696
  DocumentBase,
@@ -2200,6 +2699,15 @@ export {
2200
2699
  DocumentStatus,
2201
2700
  EnableCapabilityRequest,
2202
2701
  EnablePackRequest,
2702
+ EnrollTokenExchangeRequest,
2703
+ EnrollTokenExchangeResponse,
2704
+ EnrollTokenPayload,
2705
+ EnrollmentArch,
2706
+ EnrollmentBearerPayload,
2707
+ EnrollmentCredentialsResponse,
2708
+ EnrollmentOs,
2709
+ EnrollmentSummary,
2710
+ EntitlementDecision,
2203
2711
  EntitlementValue,
2204
2712
  Entitlements,
2205
2713
  EntitlementsMode,
@@ -2248,9 +2756,18 @@ export {
2248
2756
  GoalSpec,
2249
2757
  LimitAction,
2250
2758
  LimitDecision,
2759
+ ListEnrollmentsResponse,
2251
2760
  ListWorkspaceMembersResponse,
2761
+ MachineKind,
2762
+ MachineMetricsSeriesResponse,
2763
+ MachineState,
2764
+ MachineView,
2765
+ MachinesResponse,
2252
2766
  ManagedAccount,
2253
2767
  MarketingDailyAnalysisTaskRequest,
2768
+ MetricSample,
2769
+ MintEnrollTokenRequest,
2770
+ MintEnrollTokenResponse,
2254
2771
  PackInstallation,
2255
2772
  PackInstallationStatus,
2256
2773
  PageInfo,
@@ -2270,10 +2787,12 @@ export {
2270
2787
  RecordingMode,
2271
2788
  RecordingStartedPayload,
2272
2789
  RegisterCapabilityPackRequest,
2790
+ RelayTokenPayload,
2273
2791
  ReorderSessionTurnsRequest,
2274
2792
  RepositoryResourceRef,
2275
2793
  ResourceRef,
2276
2794
  ResourceRefConflictError,
2795
+ RevokeEnrollmentResponse,
2277
2796
  SandboxBackend,
2278
2797
  SandboxCapabilityName,
2279
2798
  SandboxCommandOutputDeltaPayload,
@@ -2296,6 +2815,9 @@ export {
2296
2815
  SessionGoalCreatedBy,
2297
2816
  SessionGoalPausedReason,
2298
2817
  SessionGoalStatus,
2818
+ SessionMcpCredentialUpdateInput,
2819
+ SessionMcpServerInput,
2820
+ SessionMcpServerMetadata,
2299
2821
  SessionStatus,
2300
2822
  SessionStructuredCapabilities,
2301
2823
  SessionTurn,
@@ -2312,6 +2834,8 @@ export {
2312
2834
  StreamRevokedPayload,
2313
2835
  StreamTokenPayload,
2314
2836
  StreamUrlRotatedPayload,
2837
+ SwapActiveSandboxRequest,
2838
+ SwapActiveSandboxResponse,
2315
2839
  TERMINAL_STREAM_PORT,
2316
2840
  TerminalExecRequest,
2317
2841
  TerminalExecResponse,
@@ -2346,9 +2870,15 @@ export {
2346
2870
  reasoningEffortForMetadata,
2347
2871
  resourceIdentityKey,
2348
2872
  signDelegatedAccessToken,
2873
+ signEnrollToken,
2874
+ signEnrollmentBearer,
2875
+ signRelayToken,
2349
2876
  signStreamToken,
2350
2877
  stableJson,
2351
2878
  verifyDelegatedAccessToken,
2879
+ verifyEnrollToken,
2880
+ verifyEnrollmentBearer,
2881
+ verifyRelayToken,
2352
2882
  verifyStreamToken
2353
2883
  };
2354
2884
  //# sourceMappingURL=index.js.map