@cofy-x/axern-sdk 0.6.2 → 0.8.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.
Files changed (68) hide show
  1. package/README.md +28 -76
  2. package/dist/client/index.d.ts +49 -11
  3. package/dist/client/index.js +207 -58
  4. package/dist/config/index.d.ts +0 -1
  5. package/dist/config/index.js +2 -4
  6. package/dist/generated/proto.js +0 -1
  7. package/dist/index.d.ts +4 -5
  8. package/dist/index.js +1 -2
  9. package/dist/node/archive.js +1 -1
  10. package/dist/node/attached_process.d.ts +1 -2
  11. package/dist/node/attached_process.js +14 -28
  12. package/dist/node/capabilities.js +1 -1
  13. package/dist/node/client.d.ts +4 -6
  14. package/dist/node/client.js +2 -9
  15. package/dist/node/computer_use.js +1 -1
  16. package/dist/node/context.d.ts +1 -1
  17. package/dist/node/context.js +1 -1
  18. package/dist/node/exec.d.ts +1 -3
  19. package/dist/node/exec.js +1 -44
  20. package/dist/node/files.js +1 -1
  21. package/dist/node/process.d.ts +11 -6
  22. package/dist/node/process.js +45 -6
  23. package/dist/proto/axern/control/admin/v1/access.proto +12 -5
  24. package/dist/proto/axern/control/admin/v1/audit.proto +14 -16
  25. package/dist/proto/axern/control/admin/v1/node.proto +23 -67
  26. package/dist/proto/axern/control/admin/v1/reliability.proto +11 -78
  27. package/dist/proto/axern/control/capability/v1/capability.proto +34 -94
  28. package/dist/proto/axern/control/common/v1/common.proto +41 -98
  29. package/dist/proto/axern/control/environment/v1/environment.proto +42 -26
  30. package/dist/proto/axern/control/identity/v1/identity.proto +1 -1
  31. package/dist/proto/axern/control/namespace/v1/namespace.proto +2 -3
  32. package/dist/proto/axern/control/quota/v1/quota.proto +22 -32
  33. package/dist/proto/axern/control/run/v1/run.proto +25 -22
  34. package/dist/proto/axern/control/secret/v1/secret.proto +1 -3
  35. package/dist/proto/axern/control/tunnel/v1/tunnel.proto +20 -29
  36. package/dist/proto/axern/node/sandbox/v1/node.proto +106 -375
  37. package/dist/sandbox/index.d.ts +5 -11
  38. package/dist/sandbox/index.js +24 -25
  39. package/dist/sandbox/lifecycle.d.ts +1 -1
  40. package/dist/sandbox/lifecycle.js +55 -17
  41. package/dist/tunnel/connector.js +1 -1
  42. package/dist/tunnel/control.d.ts +0 -1
  43. package/dist/tunnel/control.js +0 -1
  44. package/dist/tunnel/runtime.d.ts +0 -1
  45. package/dist/tunnel/runtime.js +0 -1
  46. package/dist/tunnel/types.d.ts +0 -1
  47. package/dist/types.d.ts +4 -24
  48. package/dist/types.js +1 -3
  49. package/dist/version.d.ts +1 -1
  50. package/dist/version.js +1 -1
  51. package/package.json +1 -1
  52. package/dist/proto/axern/control/admin/v1/allocation_lifecycle.proto +0 -91
  53. package/dist/proto/axern/control/admin/v1/service.proto +0 -18
  54. package/dist/proto/axern/control/admin/v1/storage.proto +0 -81
  55. package/dist/proto/axern/control/agentprofile/v1/agent_profile.proto +0 -169
  56. package/dist/proto/axern/control/catalog/v1/catalog.proto +0 -127
  57. package/dist/proto/axern/control/function/v1/function.proto +0 -130
  58. package/dist/proto/axern/control/function/v1/function_types.proto +0 -233
  59. package/dist/proto/axern/control/gateway/v1/gateway.proto +0 -92
  60. package/dist/proto/axern/control/node/v1/node_control.proto +0 -443
  61. package/dist/proto/axern/control/rollout/v1/rollout.proto +0 -344
  62. package/dist/proto/axern/control/service/v1/service.proto +0 -96
  63. package/dist/proto/axern/control/service/v1/service_event.proto +0 -47
  64. package/dist/proto/axern/control/service/v1/service_replica.proto +0 -78
  65. package/dist/proto/axern/control/service/v1/service_types.proto +0 -155
  66. package/dist/proto/axern/control/storage/v1/storage.proto +0 -107
  67. package/dist/proto/axern/control/storage/v1/storage_types.proto +0 -125
  68. package/dist/proto/axern/data/artifact/v1/artifact.proto +0 -19
@@ -3,7 +3,6 @@ import { readFileSync } from "node:fs";
3
3
  export function loadAxernEnv(overrides = {}) {
4
4
  return {
5
5
  endpoint: overrides.endpoint ?? process.env.AXERN_ENDPOINT ?? "127.0.0.1:25000",
6
- serviceUrl: overrides.serviceUrl ?? process.env.AXERN_SERVICE_URL,
7
6
  sshEndpoint: overrides.sshEndpoint ?? process.env.AXERN_SSH_ENDPOINT,
8
7
  sshIdentityFile: overrides.sshIdentityFile ?? process.env.AXERN_SSH_IDENTITY_FILE,
9
8
  tlsCaCert: overrides.tlsCaCert ?? process.env.AXERN_TLS_CA_CERT,
@@ -15,18 +14,17 @@ export function loadAxernEnv(overrides = {}) {
15
14
  }
16
15
  export function loadAxernContext(path, name = "") {
17
16
  const file = JSON.parse(readFileSync(path, "utf8"));
18
- rejectUnknown(file, ["current_context", "contexts", "agent_profiles"], "config");
17
+ rejectUnknown(file, ["current_context", "contexts"], "config");
19
18
  const contextName = name || stringValue(file.current_context);
20
19
  if (!contextName)
21
20
  throw new Error("Axern context name is required");
22
21
  const contexts = objectValue(file.contexts, "contexts");
23
22
  const context = objectValue(contexts[contextName], `context ${JSON.stringify(contextName)}`);
24
- rejectUnknown(context, ["endpoint", "service_url", "ssh_endpoint", "ssh_identity_file", "tls", "proxy_mode"], "context");
23
+ rejectUnknown(context, ["endpoint", "ssh_endpoint", "ssh_identity_file", "tls", "proxy_mode"], "context");
25
24
  const tls = objectValue(context.tls, "context.tls");
26
25
  rejectUnknown(tls, ["ca_cert", "cert", "key", "server_name"], "context.tls");
27
26
  const config = {
28
27
  endpoint: stringValue(context.endpoint),
29
- serviceUrl: stringValue(context.service_url) || undefined,
30
28
  sshEndpoint: stringValue(context.ssh_endpoint) || undefined,
31
29
  sshIdentityFile: stringValue(context.ssh_identity_file) || undefined,
32
30
  tlsCaCert: stringValue(tls.ca_cert),
@@ -16,7 +16,6 @@ const defaultProtoRootCandidates = [
16
16
  const protoFiles = [
17
17
  "axern/control/environment/v1/environment.proto",
18
18
  "axern/control/run/v1/run.proto",
19
- "axern/control/service/v1/service.proto",
20
19
  "axern/control/tunnel/v1/tunnel.proto",
21
20
  "axern/node/sandbox/v1/node.proto",
22
21
  "axern/tunnel/v1/tunnel.proto",
package/dist/index.d.ts CHANGED
@@ -4,18 +4,17 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  export { AxernClient } from "./client/index.js";
7
- export type { AxernClientOptions, CreateEnvironmentOptions, CreateServiceOptions, } from "./client/index.js";
7
+ export type { AxernClientOptions, CreateEnvironmentOptions, CreateRunOptions, DeclaredOutput, DeclaredOutputFormat, ListOptions, ListResult, SealedOutput, } from "./client/index.js";
8
8
  export { loadAxernContext, loadAxernEnv } from "./config/index.js";
9
9
  export type { AxernConfig } from "./config/index.js";
10
10
  export { AxernError, AxernRpcError, isNotFound, isCancelled, isUnavailable, errorRetryable, isPermissionDenied, isTimeout, rpcCode, SandboxExecError, SandboxStateError, SandboxTimeoutError, SandboxValidationError, } from "./errors/index.js";
11
- export { NodeSandboxClient } from "./node/client.js";
12
- export type { NodeSandboxClientOptions } from "./node/client.js";
11
+ export { AllocationClient } from "./node/client.js";
12
+ export type { AllocationClientOptions } from "./node/client.js";
13
13
  export { SandboxProcess } from "./node/process.js";
14
14
  export type { ResourceQuantity } from "./resources.js";
15
15
  export { Sandbox } from "./sandbox/index.js";
16
16
  export type { SandboxMetadata, SandboxOptions, SandboxState } from "./sandbox/index.js";
17
17
  export { NetworkPolicy, cidrRule, portRange } from "./network-policy.js";
18
18
  export type { CIDRRule, PortRange, StrictNetworkPolicyOptions } from "./network-policy.js";
19
- export type { ChmodOptions, CapabilityDependencyStatus, CapabilityProviderStatus, CapabilityProviderSummary, CapabilityStatus, Command, ComputerUseDependencyStatus, ComputerUseDisplay, ComputerUseKeyboardOptions, ComputerUseMouseOptions, ComputerUseRegion, ComputerUseScreenshot, ComputerUseScreenshotOptions, ComputerUseStatus, CopyOptions, DownloadArchiveOptions, DownloadDirOptions, ExecOptions, ExecResult, ImageExecOptions, ImageProcessMount, ImageProcessOptions, MkdirOptions, MoveOptions, NodeCallOptions, ProcessEvent, ProcessOptions, ProcessResult, RemoveOptions, SandboxFileInfo, SandboxFileKind, TouchOptions, TunnelConnectorOptions, TunnelMetadata, TunnelOptions, UploadArchiveOptions, UploadDirOptions, VolumeMount, WriteFileOptions, } from "./types.js";
20
- export { workspaceMount } from "./types.js";
19
+ export type { ChmodOptions, CapabilityProviderDependencyStatus, CapabilityProviderStatus, CapabilityProviderSummary, CapabilityStatus, Command, ComputerUseDependencyStatus, ComputerUseDisplay, ComputerUseKeyboardOptions, ComputerUseMouseOptions, ComputerUseRegion, ComputerUseScreenshot, ComputerUseScreenshotOptions, ComputerUseStatus, CopyOptions, DownloadArchiveOptions, DownloadDirOptions, ExecOptions, ExecResult, MkdirOptions, MoveOptions, NodeCallOptions, ProcessEvent, ProcessOptions, ProcessResult, RemoveOptions, SandboxFileInfo, SandboxFileKind, TouchOptions, TunnelConnectorOptions, TunnelMetadata, TunnelOptions, UploadArchiveOptions, UploadDirOptions, WriteFileOptions, } from "./types.js";
21
20
  export { AXERN_VERSION, platformName } from "./version.js";
package/dist/index.js CHANGED
@@ -6,9 +6,8 @@
6
6
  export { AxernClient } from "./client/index.js";
7
7
  export { loadAxernContext, loadAxernEnv } from "./config/index.js";
8
8
  export { AxernError, AxernRpcError, isNotFound, isCancelled, isUnavailable, errorRetryable, isPermissionDenied, isTimeout, rpcCode, SandboxExecError, SandboxStateError, SandboxTimeoutError, SandboxValidationError, } from "./errors/index.js";
9
- export { NodeSandboxClient } from "./node/client.js";
9
+ export { AllocationClient } from "./node/client.js";
10
10
  export { SandboxProcess } from "./node/process.js";
11
11
  export { Sandbox } from "./sandbox/index.js";
12
12
  export { NetworkPolicy, cidrRule, portRange } from "./network-policy.js";
13
- export { workspaceMount } from "./types.js";
14
13
  export { AXERN_VERSION, platformName } from "./version.js";
@@ -8,7 +8,7 @@ import { nonEmptyPath } from "../validation.js";
8
8
  import { downloadArchiveStream, uploadArchiveStream } from "./streams.js";
9
9
  export async function uploadArchive(ctx, path, chunks, options = {}) {
10
10
  try {
11
- await ctx.withAuthRetry(options.leaseTtlSeconds ?? 300, (client) => uploadArchiveStream(client, ctx.authRequest({
11
+ await ctx.withAuthRetry((client) => uploadArchiveStream(client, ctx.authRequest({
12
12
  path: nonEmptyPath(path),
13
13
  format: 1,
14
14
  create_parents: options.createParents ?? true,
@@ -3,8 +3,7 @@
3
3
  * Copyright 2026 cofy-x
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import type { Command, ImageProcessOptions, ProcessOptions } from "../types.js";
6
+ import type { Command, ProcessOptions } from "../types.js";
7
7
  import { NodeClientContext } from "./context.js";
8
8
  import { SandboxProcess } from "./process.js";
9
9
  export declare function process(ctx: NodeClientContext, command: Command, options?: ProcessOptions): Promise<SandboxProcess>;
10
- export declare function processImage(ctx: NodeClientContext, image: string, command: Command, options?: ImageProcessOptions): Promise<SandboxProcess>;
@@ -3,12 +3,13 @@
3
3
  * Copyright 2026 cofy-x
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { mapRpcError } from "../errors/index.js";
6
+ import { mapRpcError, SandboxValidationError } from "../errors/index.js";
7
7
  import { normalizeCommand } from "../validation.js";
8
- import { execSpec, imageProcessSpec } from "./exec.js";
8
+ import { execSpec } from "./exec.js";
9
9
  import { SandboxProcess } from "./process.js";
10
10
  export async function process(ctx, command, options = {}) {
11
11
  const argv = normalizeCommand(command);
12
+ const initialSize = processInitialSize(options);
12
13
  const client = ctx.rpcClient();
13
14
  const call = client
14
15
  .Process();
@@ -17,11 +18,12 @@ export async function process(ctx, command, options = {}) {
17
18
  call,
18
19
  closeClient: () => client.close(),
19
20
  });
20
- call.write({
21
+ await new Promise((resolve, reject) => call.write({
21
22
  open: ctx.authRequest({
22
23
  spec: execSpec(argv, options),
24
+ ...(initialSize === undefined ? {} : { initial_size: initialSize }),
23
25
  }),
24
- });
26
+ }, (error) => error == null ? resolve() : reject(error)));
25
27
  try {
26
28
  await sandboxProcess.waitReady();
27
29
  return sandboxProcess;
@@ -31,30 +33,14 @@ export async function process(ctx, command, options = {}) {
31
33
  throw mapRpcError(error, "sandbox process", ctx.allocationId);
32
34
  }
33
35
  }
34
- export async function processImage(ctx, image, command, options = {}) {
35
- if (image.trim() === "") {
36
- throw new Error("image is required");
37
- }
38
- const argv = normalizeCommand(command);
39
- const client = ctx.rpcClient();
40
- const call = client
41
- .ProcessImage();
42
- const sandboxProcess = new SandboxProcess({
43
- allocationId: ctx.allocationId,
44
- call,
45
- closeClient: () => client.close(),
46
- });
47
- call.write({
48
- open: ctx.authRequest({
49
- spec: imageProcessSpec(image, argv, options),
50
- }),
51
- });
52
- try {
53
- await sandboxProcess.waitReady();
54
- return sandboxProcess;
36
+ function processInitialSize(options) {
37
+ const cols = options.initialCols ?? 0;
38
+ const rows = options.initialRows ?? 0;
39
+ if ((cols === 0) !== (rows === 0)) {
40
+ throw new SandboxValidationError("initialCols and initialRows must both be zero or both be positive");
55
41
  }
56
- catch (error) {
57
- await sandboxProcess.close();
58
- throw mapRpcError(error, "sandbox image process", ctx.allocationId);
42
+ if (cols < 0 || rows < 0 || !Number.isInteger(cols) || !Number.isInteger(rows)) {
43
+ throw new SandboxValidationError("initialCols and initialRows must be non-negative integers");
59
44
  }
45
+ return cols === 0 ? undefined : { cols, rows };
60
46
  }
@@ -7,7 +7,7 @@ import { mapRpcError } from "../errors/index.js";
7
7
  import { unary } from "../generated/proto.js";
8
8
  export async function capabilityStatus(ctx, options = {}) {
9
9
  try {
10
- const response = await ctx.withAuthRetry(60, (client) => unary(client, "CapabilityStatus", ctx.authRequest({}), options.rpcTimeoutMs));
10
+ const response = await ctx.withAuthRetry((client) => unary(client, "CapabilityStatus", ctx.authRequest({}), options.rpcTimeoutMs));
11
11
  return {
12
12
  ready: response.ready === true,
13
13
  capabilities: strings(response.capabilities),
@@ -4,22 +4,20 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import type * as grpc from "@grpc/grpc-js";
7
- import type { ChmodOptions, CapabilityStatus, Command, ComputerUseDisplay, ComputerUseKeyboardOptions, ComputerUseMouseOptions, ComputerUseScreenshot, ComputerUseScreenshotOptions, ComputerUseStatus, CopyOptions, DownloadArchiveOptions, ExecOptions, ExecResult, ImageExecOptions, ImageProcessOptions, MkdirOptions, MoveOptions, NodeCallOptions, ProcessOptions, RemoveOptions, SandboxFileInfo, TouchOptions, UploadArchiveOptions, WriteFileOptions } from "../types.js";
7
+ import type { ChmodOptions, CapabilityStatus, Command, ComputerUseDisplay, ComputerUseKeyboardOptions, ComputerUseMouseOptions, ComputerUseScreenshot, ComputerUseScreenshotOptions, ComputerUseStatus, CopyOptions, DownloadArchiveOptions, ExecOptions, ExecResult, MkdirOptions, MoveOptions, NodeCallOptions, ProcessOptions, RemoveOptions, SandboxFileInfo, TouchOptions, UploadArchiveOptions, WriteFileOptions } from "../types.js";
8
8
  import type { SandboxProcess } from "./process.js";
9
- export interface NodeSandboxClientOptions {
9
+ export interface AllocationClientOptions {
10
10
  allocationId: string;
11
11
  target: string;
12
12
  credentials: grpc.ChannelCredentials;
13
13
  channelOptions?: grpc.ChannelOptions;
14
14
  }
15
- export declare class NodeSandboxClient {
15
+ export declare class AllocationClient {
16
16
  readonly allocationId: string;
17
17
  private readonly ctx;
18
- constructor(options: NodeSandboxClientOptions);
18
+ constructor(options: AllocationClientOptions);
19
19
  exec(command: Command, options?: ExecOptions): Promise<ExecResult>;
20
20
  process(command: Command, options?: ProcessOptions): Promise<SandboxProcess>;
21
- execImage(image: string, command: Command, options?: ImageExecOptions): Promise<ExecResult>;
22
- processImage(image: string, command: Command, options?: ImageProcessOptions): Promise<SandboxProcess>;
23
21
  capabilityStatus(options?: NodeCallOptions): Promise<CapabilityStatus>;
24
22
  computerUseStatus(options?: NodeCallOptions): Promise<ComputerUseStatus>;
25
23
  computerUseScreenshot(options?: ComputerUseScreenshotOptions): Promise<ComputerUseScreenshot>;
@@ -7,11 +7,10 @@ import { uploadArchive, downloadArchive } from "./archive.js";
7
7
  import { capabilityStatus } from "./capabilities.js";
8
8
  import * as computerUse from "./computer_use.js";
9
9
  import { process as startProcess } from "./attached_process.js";
10
- import { processImage as startImageProcess } from "./attached_process.js";
11
10
  import { NodeClientContext } from "./context.js";
12
- import { exec, execImage } from "./exec.js";
11
+ import { exec } from "./exec.js";
13
12
  import * as files from "./files.js";
14
- export class NodeSandboxClient {
13
+ export class AllocationClient {
15
14
  allocationId;
16
15
  ctx;
17
16
  constructor(options) {
@@ -24,12 +23,6 @@ export class NodeSandboxClient {
24
23
  async process(command, options = {}) {
25
24
  return startProcess(this.ctx, command, options);
26
25
  }
27
- async execImage(image, command, options = {}) {
28
- return execImage(this.ctx, image, command, options);
29
- }
30
- async processImage(image, command, options = {}) {
31
- return startImageProcess(this.ctx, image, command, options);
32
- }
33
26
  async capabilityStatus(options = {}) {
34
27
  return capabilityStatus(this.ctx, options);
35
28
  }
@@ -68,7 +68,7 @@ export async function computerUseKeyboard(ctx, options = {}) {
68
68
  }
69
69
  async function computerUseUnary(ctx, method, payload, rpcTimeoutMs) {
70
70
  try {
71
- return await ctx.withAuthRetry(60, (client) => unary(client, method, ctx.authRequest(payload), rpcTimeoutMs));
71
+ return await ctx.withAuthRetry((client) => unary(client, method, ctx.authRequest(payload), rpcTimeoutMs));
72
72
  }
73
73
  catch (error) {
74
74
  throw mapRpcError(error, `sandbox ${method}`, ctx.allocationId);
@@ -16,7 +16,7 @@ export declare class NodeClientContext {
16
16
  private readonly credentials;
17
17
  private readonly channelOptions;
18
18
  constructor(options: NodeClientContextOptions);
19
- withAuthRetry<T>(_leaseTtlSeconds: number, operation: (client: grpc.Client) => Promise<T>): Promise<T>;
19
+ withAuthRetry<T>(operation: (client: grpc.Client) => Promise<T>): Promise<T>;
20
20
  rpcClient(): grpc.Client;
21
21
  authRequest(payload: Record<string, unknown>): Record<string, unknown>;
22
22
  }
@@ -15,7 +15,7 @@ export class NodeClientContext {
15
15
  this.credentials = options.credentials;
16
16
  this.channelOptions = options.channelOptions ?? {};
17
17
  }
18
- async withAuthRetry(_leaseTtlSeconds, operation) {
18
+ async withAuthRetry(operation) {
19
19
  const client = this.rpcClient();
20
20
  try {
21
21
  return await operation(client);
@@ -3,10 +3,8 @@
3
3
  * Copyright 2026 cofy-x
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import type { Command, ExecOptions, ExecResult, ImageExecOptions, ImageProcessOptions, ProcessOptions } from "../types.js";
6
+ import type { Command, ExecOptions, ExecResult, ProcessOptions } from "../types.js";
7
7
  import type { NodeClientContext } from "./context.js";
8
8
  export declare function exec(ctx: NodeClientContext, command: Command, options?: ExecOptions): Promise<ExecResult>;
9
- export declare function execImage(ctx: NodeClientContext, image: string, command: Command, options?: ImageExecOptions): Promise<ExecResult>;
10
9
  export declare function execSpec(argv: string[], options: ExecOptions | ProcessOptions): Record<string, unknown>;
11
- export declare function imageProcessSpec(image: string, argv: string[], options: ImageExecOptions | ImageProcessOptions): Record<string, unknown>;
12
10
  export declare function execResult(response: Record<string, unknown>): ExecResult;
package/dist/node/exec.js CHANGED
@@ -9,7 +9,7 @@ import { normalizeCommand } from "../validation.js";
9
9
  export async function exec(ctx, command, options = {}) {
10
10
  const argv = normalizeCommand(command);
11
11
  try {
12
- const response = await ctx.withAuthRetry(options.leaseTtlSeconds ?? 300, async (client) => unary(client, "Exec", ctx.authRequest({
12
+ const response = await ctx.withAuthRetry(async (client) => unary(client, "Exec", ctx.authRequest({
13
13
  spec: execSpec(argv, options),
14
14
  }), options.rpcTimeoutMs));
15
15
  const result = execResult(response);
@@ -25,28 +25,6 @@ export async function exec(ctx, command, options = {}) {
25
25
  throw mapRpcError(error, "sandbox exec", ctx.allocationId);
26
26
  }
27
27
  }
28
- export async function execImage(ctx, image, command, options = {}) {
29
- if (image.trim() === "") {
30
- throw new Error("image is required");
31
- }
32
- const argv = normalizeCommand(command);
33
- try {
34
- const response = await ctx.withAuthRetry(options.leaseTtlSeconds ?? 300, async (client) => unary(client, "ExecImage", ctx.authRequest({
35
- spec: imageProcessSpec(image, argv, options),
36
- }), options.rpcTimeoutMs));
37
- const result = execResult(response);
38
- if (options.check === true && result.exitCode !== 0) {
39
- throw new SandboxExecError(argv, result);
40
- }
41
- return result;
42
- }
43
- catch (error) {
44
- if (error instanceof SandboxExecError) {
45
- throw error;
46
- }
47
- throw mapRpcError(error, "sandbox exec image", ctx.allocationId);
48
- }
49
- }
50
28
  export function execSpec(argv, options) {
51
29
  return {
52
30
  argv,
@@ -57,27 +35,6 @@ export function execSpec(argv, options) {
57
35
  user: options.user ?? "",
58
36
  };
59
37
  }
60
- export function imageProcessSpec(image, argv, options) {
61
- return {
62
- image,
63
- argv,
64
- env: options.env ?? {},
65
- cwd: options.cwd ?? "",
66
- timeout_seconds: options.timeoutSeconds ?? 0,
67
- tty: options.tty ?? false,
68
- user: options.user ?? "",
69
- mounts: imageProcessMounts(options.mounts),
70
- };
71
- }
72
- function imageProcessMounts(mounts) {
73
- const effective = mounts ?? [{ sandboxPath: "/workspace", targetPath: "/workspace" }];
74
- return effective.map((mount) => ({
75
- sandbox_path: mount.sandboxPath,
76
- target_path: mount.targetPath,
77
- readonly: mount.readonly ?? false,
78
- options: [...(mount.options ?? [])],
79
- }));
80
- }
81
38
  export function execResult(response) {
82
39
  const stdout = Buffer.from(response.stdout ?? []);
83
40
  const stderr = Buffer.from(response.stderr ?? []);
@@ -70,7 +70,7 @@ export async function touch(ctx, path, options = {}) {
70
70
  }
71
71
  async function fileUnary(ctx, method, payload) {
72
72
  try {
73
- return await ctx.withAuthRetry(300, (client) => unary(client, method, ctx.authRequest(payload)));
73
+ return await ctx.withAuthRetry((client) => unary(client, method, ctx.authRequest(payload)));
74
74
  }
75
75
  catch (error) {
76
76
  throw mapRpcError(error, `sandbox ${method}`, ctx.allocationId);
@@ -19,18 +19,23 @@ export declare class SandboxProcess {
19
19
  private error;
20
20
  private ended;
21
21
  private exit?;
22
+ private paused;
23
+ private closed;
24
+ private static readonly maxQueuedEvents;
25
+ private static readonly resumeQueuedEvents;
22
26
  constructor(options: SandboxProcessOptions);
23
- write(data: Buffer | Uint8Array | string): void;
24
- closeStdin(): void;
25
- resize(cols: number, rows: number): void;
26
- signal(signal: string): void;
27
- terminate(): void;
28
- kill(): void;
27
+ write(data: Buffer | Uint8Array | string): Promise<void>;
28
+ closeStdin(): Promise<void>;
29
+ resize(cols: number, rows: number): Promise<void>;
30
+ signal(signal: string): Promise<void>;
31
+ terminate(): Promise<void>;
32
+ kill(): Promise<void>;
29
33
  waitReady(): Promise<void>;
30
34
  wait(): Promise<ProcessResult>;
31
35
  close(): Promise<void>;
32
36
  events(): AsyncIterable<ProcessEvent>;
33
37
  private nextEvent;
34
38
  private enqueue;
39
+ private writeRequest;
35
40
  private finish;
36
41
  }
@@ -13,6 +13,10 @@ export class SandboxProcess {
13
13
  error;
14
14
  ended = false;
15
15
  exit;
16
+ paused = false;
17
+ closed = false;
18
+ static maxQueuedEvents = 64;
19
+ static resumeQueuedEvents = 32;
16
20
  constructor(options) {
17
21
  this.allocationId = options.allocationId;
18
22
  this.call = options.call;
@@ -25,22 +29,22 @@ export class SandboxProcess {
25
29
  this.call.on("end", () => this.finish());
26
30
  }
27
31
  write(data) {
28
- this.call.write({ stdin: Buffer.isBuffer(data) ? data : Buffer.from(data) });
32
+ return this.writeRequest({ stdin: Buffer.isBuffer(data) ? data : Buffer.from(data) });
29
33
  }
30
34
  closeStdin() {
31
- this.call.write({ close_stdin: true });
35
+ return this.writeRequest({ close_stdin: true });
32
36
  }
33
37
  resize(cols, rows) {
34
- this.call.write({ resize: { cols, rows } });
38
+ return this.writeRequest({ resize: { cols, rows } });
35
39
  }
36
40
  signal(signal) {
37
- this.call.write({ signal: { signal } });
41
+ return this.writeRequest({ signal: { signal } });
38
42
  }
39
43
  terminate() {
40
- this.signal("TERM");
44
+ return this.signal("TERM");
41
45
  }
42
46
  kill() {
43
- this.signal("KILL");
47
+ return this.signal("KILL");
44
48
  }
45
49
  async waitReady() {
46
50
  const next = await this.nextEvent();
@@ -69,7 +73,14 @@ export class SandboxProcess {
69
73
  throw new Error("sandbox process stream ended before exit");
70
74
  }
71
75
  async close() {
76
+ if (this.closed)
77
+ return;
78
+ if (!this.ended && this.exit === undefined) {
79
+ await this.terminate().catch(() => undefined);
80
+ }
81
+ this.closed = true;
72
82
  this.call.end();
83
+ this.call.cancel();
73
84
  this.closeClient();
74
85
  }
75
86
  async *events() {
@@ -90,6 +101,10 @@ export class SandboxProcess {
90
101
  nextEvent() {
91
102
  const event = this.queue.shift();
92
103
  if (event !== undefined) {
104
+ if (this.paused && this.queue.length <= SandboxProcess.resumeQueuedEvents) {
105
+ this.paused = false;
106
+ this.call.resume();
107
+ }
93
108
  return Promise.resolve({ done: false, value: event });
94
109
  }
95
110
  if (this.ended) {
@@ -108,8 +123,32 @@ export class SandboxProcess {
108
123
  waiter({ done: false, value: event });
109
124
  }
110
125
  else {
126
+ if (this.queue.length >= SandboxProcess.maxQueuedEvents) {
127
+ this.error = new Error("sandbox process consumer is too slow; event queue limit exceeded");
128
+ this.call.cancel();
129
+ this.finish();
130
+ return;
131
+ }
111
132
  this.queue.push(event);
133
+ if (!this.paused && this.queue.length >= SandboxProcess.maxQueuedEvents) {
134
+ this.paused = true;
135
+ this.call.pause();
136
+ }
137
+ }
138
+ }
139
+ writeRequest(request) {
140
+ if (this.closed || this.ended) {
141
+ return Promise.reject(new Error("sandbox process stream is closed"));
112
142
  }
143
+ return new Promise((resolve, reject) => {
144
+ this.call.write(request, (error) => {
145
+ if (error !== undefined && error !== null) {
146
+ reject(mapRpcError(error, "sandbox process write", this.allocationId));
147
+ return;
148
+ }
149
+ resolve();
150
+ });
151
+ });
113
152
  }
114
153
  finish() {
115
154
  if (this.ended) {
@@ -30,7 +30,12 @@ enum AccessRole {
30
30
  ACCESS_ROLE_NAMESPACE_ADMIN = 2;
31
31
  ACCESS_ROLE_NAMESPACE_EDITOR = 3;
32
32
  ACCESS_ROLE_NAMESPACE_VIEWER = 4;
33
- ACCESS_ROLE_ROLLOUT_EXECUTOR = 5;
33
+ }
34
+
35
+ enum CredentialKind {
36
+ CREDENTIAL_KIND_UNSPECIFIED = 0;
37
+ CREDENTIAL_KIND_X509 = 1;
38
+ CREDENTIAL_KIND_SSH = 2;
34
39
  }
35
40
 
36
41
  message Principal {
@@ -39,19 +44,19 @@ message Principal {
39
44
  string display_name = 3;
40
45
  PrincipalKind kind = 4;
41
46
  PrincipalStatus status = 5;
42
- int64 version = 6;
43
- google.protobuf.Timestamp created_at = 7;
44
- google.protobuf.Timestamp updated_at = 8;
47
+ google.protobuf.Timestamp created_at = 6;
48
+ google.protobuf.Timestamp updated_at = 7;
45
49
  }
46
50
 
47
51
  message PrincipalCredential {
48
52
  string credential_id = 1;
49
53
  string principal_id = 2;
50
54
  string fingerprint = 3;
51
- google.protobuf.Timestamp certificate_not_after = 4;
55
+ google.protobuf.Timestamp expires_at = 4;
52
56
  string label = 5;
53
57
  google.protobuf.Timestamp created_at = 6;
54
58
  google.protobuf.Timestamp revoked_at = 7;
59
+ CredentialKind kind = 8;
55
60
  }
56
61
 
57
62
  message RoleBinding {
@@ -83,6 +88,8 @@ message AddPrincipalCredentialRequest {
83
88
  string principal_id = 1;
84
89
  bytes certificate_der = 2;
85
90
  string label = 3;
91
+ string ssh_public_key = 4;
92
+ google.protobuf.Timestamp expires_at = 5;
86
93
  }
87
94
  message AddPrincipalCredentialResponse { PrincipalCredential credential = 1; }
88
95
 
@@ -11,27 +11,25 @@ enum AdminAuditOperation {
11
11
  ADMIN_AUDIT_OPERATION_FORCE_ALLOCATION_LIFECYCLE_RETRY = 1;
12
12
  ADMIN_AUDIT_OPERATION_FAIL_ALLOCATION_LIFECYCLE_RETRY = 2;
13
13
  ADMIN_AUDIT_OPERATION_CLEAR_ALLOCATION_LIFECYCLE_RETRY = 3;
14
- ADMIN_AUDIT_OPERATION_RETRY_STORAGE_BINDING = 4;
15
- ADMIN_AUDIT_OPERATION_PURGE_SERVICE = 5;
16
- ADMIN_AUDIT_OPERATION_RETIRE_NODE = 6;
17
- ADMIN_AUDIT_OPERATION_CREATE_PRINCIPAL = 7;
18
- ADMIN_AUDIT_OPERATION_DISABLE_PRINCIPAL = 8;
19
- ADMIN_AUDIT_OPERATION_ADD_CREDENTIAL = 9;
20
- ADMIN_AUDIT_OPERATION_REVOKE_CREDENTIAL = 10;
21
- ADMIN_AUDIT_OPERATION_GRANT_ROLE_BINDING = 11;
22
- ADMIN_AUDIT_OPERATION_REVOKE_ROLE_BINDING = 12;
23
- ADMIN_AUDIT_OPERATION_BOOTSTRAP_ACCESS = 13;
14
+ ADMIN_AUDIT_OPERATION_RETIRE_NODE = 4;
15
+ ADMIN_AUDIT_OPERATION_CREATE_PRINCIPAL = 5;
16
+ ADMIN_AUDIT_OPERATION_DISABLE_PRINCIPAL = 6;
17
+ ADMIN_AUDIT_OPERATION_ADD_CREDENTIAL = 7;
18
+ ADMIN_AUDIT_OPERATION_REVOKE_CREDENTIAL = 8;
19
+ ADMIN_AUDIT_OPERATION_GRANT_ROLE_BINDING = 9;
20
+ ADMIN_AUDIT_OPERATION_REVOKE_ROLE_BINDING = 10;
21
+ ADMIN_AUDIT_OPERATION_BOOTSTRAP_ACCESS = 11;
22
+ ADMIN_AUDIT_OPERATION_ADMIT_NODE = 12;
23
+ ADMIN_AUDIT_OPERATION_REVOKE_NODE = 13;
24
24
  }
25
25
 
26
26
  enum AdminAuditTargetType {
27
27
  ADMIN_AUDIT_TARGET_TYPE_UNSPECIFIED = 0;
28
28
  ADMIN_AUDIT_TARGET_TYPE_ALLOCATION = 1;
29
- ADMIN_AUDIT_TARGET_TYPE_STORAGE_BINDING = 2;
30
- ADMIN_AUDIT_TARGET_TYPE_SERVICE = 3;
31
- ADMIN_AUDIT_TARGET_TYPE_NODE = 4;
32
- ADMIN_AUDIT_TARGET_TYPE_PRINCIPAL = 5;
33
- ADMIN_AUDIT_TARGET_TYPE_CREDENTIAL = 6;
34
- ADMIN_AUDIT_TARGET_TYPE_ROLE_BINDING = 7;
29
+ ADMIN_AUDIT_TARGET_TYPE_NODE = 2;
30
+ ADMIN_AUDIT_TARGET_TYPE_PRINCIPAL = 3;
31
+ ADMIN_AUDIT_TARGET_TYPE_CREDENTIAL = 4;
32
+ ADMIN_AUDIT_TARGET_TYPE_ROLE_BINDING = 5;
35
33
  }
36
34
 
37
35
  message AdminAuditEvent {