@cofy-x/axern-sdk 0.3.1 → 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/client/index.d.ts +7 -0
- package/dist/client/index.js +92 -0
- package/dist/generated/proto.js +1 -0
- package/dist/proto/axern/control/gateway/v1/gateway.proto +7 -0
- package/dist/proto/axern/control/run/v1/run.proto +13 -0
- package/dist/proto/axern/control/secret/v1/secret.proto +1 -0
- package/dist/proto/axern/node/sandbox/v1/node.proto +24 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/client/index.d.ts
CHANGED
|
@@ -40,11 +40,16 @@ export interface CreateServiceOptions {
|
|
|
40
40
|
limitMemory?: ResourceQuantity;
|
|
41
41
|
labels?: Record<string, string>;
|
|
42
42
|
}
|
|
43
|
+
export interface ReadRunOutputOptions {
|
|
44
|
+
cursor?: string;
|
|
45
|
+
follow?: boolean;
|
|
46
|
+
}
|
|
43
47
|
export declare class AxernClient {
|
|
44
48
|
readonly endpoint: string;
|
|
45
49
|
private readonly credentials;
|
|
46
50
|
private readonly controlOptions;
|
|
47
51
|
private readonly environmentControl;
|
|
52
|
+
private readonly runControl;
|
|
48
53
|
private readonly serviceControl;
|
|
49
54
|
private readonly tunnelControl;
|
|
50
55
|
private readonly gatewayTransport;
|
|
@@ -54,6 +59,8 @@ export declare class AxernClient {
|
|
|
54
59
|
close(): void;
|
|
55
60
|
createEnvironment(options: CreateEnvironmentOptions): Promise<Record<string, unknown>>;
|
|
56
61
|
deleteEnvironment(environmentId: string): Promise<void>;
|
|
62
|
+
watchRun(runId: string, afterVersion?: number): AsyncGenerator<Record<string, unknown>>;
|
|
63
|
+
readRunOutput(runId: string, options?: ReadRunOutputOptions): AsyncGenerator<Record<string, unknown>>;
|
|
57
64
|
createService(options: CreateServiceOptions): Promise<Record<string, unknown>>;
|
|
58
65
|
deleteService(serviceId: string): Promise<void>;
|
|
59
66
|
listServiceReplicas(serviceId: string): Promise<Record<string, unknown>[]>;
|
package/dist/client/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export class AxernClient {
|
|
|
17
17
|
credentials;
|
|
18
18
|
controlOptions;
|
|
19
19
|
environmentControl;
|
|
20
|
+
runControl;
|
|
20
21
|
serviceControl;
|
|
21
22
|
tunnelControl;
|
|
22
23
|
gatewayTransport;
|
|
@@ -55,9 +56,11 @@ export class AxernClient {
|
|
|
55
56
|
"v1",
|
|
56
57
|
"EnvironmentControl",
|
|
57
58
|
]);
|
|
59
|
+
const RunControl = serviceConstructor(["axern", "control", "run", "v1", "RunControl"]);
|
|
58
60
|
const ServiceControl = serviceConstructor(["axern", "control", "service", "v1", "ServiceControl"]);
|
|
59
61
|
const TunnelControl = serviceConstructor(["axern", "control", "tunnel", "v1", "TunnelControl"]);
|
|
60
62
|
this.environmentControl = new EnvironmentControl(this.endpoint, this.credentials, this.controlOptions);
|
|
63
|
+
this.runControl = new RunControl(this.endpoint, this.credentials, this.controlOptions);
|
|
61
64
|
this.serviceControl = new ServiceControl(this.endpoint, this.credentials, this.controlOptions);
|
|
62
65
|
this.tunnelControl = new TunnelControl(this.endpoint, this.credentials, this.controlOptions);
|
|
63
66
|
}
|
|
@@ -78,6 +81,7 @@ export class AxernClient {
|
|
|
78
81
|
}
|
|
79
82
|
close() {
|
|
80
83
|
this.environmentControl.close();
|
|
84
|
+
this.runControl.close();
|
|
81
85
|
this.serviceControl.close();
|
|
82
86
|
this.tunnelControl.close();
|
|
83
87
|
}
|
|
@@ -114,6 +118,83 @@ export class AxernClient {
|
|
|
114
118
|
throw mapRpcError(error, "delete environment");
|
|
115
119
|
}
|
|
116
120
|
}
|
|
121
|
+
async *watchRun(runId, afterVersion = 0) {
|
|
122
|
+
if (afterVersion < 0) {
|
|
123
|
+
throw new Error("afterVersion must be non-negative");
|
|
124
|
+
}
|
|
125
|
+
let version = afterVersion;
|
|
126
|
+
let retryDelayMs = 100;
|
|
127
|
+
for (;;) {
|
|
128
|
+
const stream = serverStream(this.runControl, "WatchRun", {
|
|
129
|
+
run_id: required("runId", runId),
|
|
130
|
+
after_version: version,
|
|
131
|
+
});
|
|
132
|
+
try {
|
|
133
|
+
for await (const response of stream) {
|
|
134
|
+
const run = response.run;
|
|
135
|
+
if (run === undefined)
|
|
136
|
+
continue;
|
|
137
|
+
const nextVersion = Number(run.version ?? 0);
|
|
138
|
+
if (nextVersion <= version)
|
|
139
|
+
continue;
|
|
140
|
+
version = nextVersion;
|
|
141
|
+
retryDelayMs = 100;
|
|
142
|
+
yield run;
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (!transientReadError(error))
|
|
148
|
+
throw mapRpcError(error, "watch run");
|
|
149
|
+
}
|
|
150
|
+
await sleep(retryDelayMs);
|
|
151
|
+
retryDelayMs = Math.min(retryDelayMs * 2, 2_000);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async *readRunOutput(runId, options = {}) {
|
|
155
|
+
const response = await unary(this.runControl, "GetRun", { run_id: required("runId", runId) });
|
|
156
|
+
const allocationId = String(response.run?.allocation_id ?? "");
|
|
157
|
+
if (allocationId === "")
|
|
158
|
+
throw new Error(`run ${runId} output is not available yet`);
|
|
159
|
+
let cursor = options.cursor ?? "";
|
|
160
|
+
let retryDelayMs = 100;
|
|
161
|
+
let notFoundSince = 0;
|
|
162
|
+
for (;;) {
|
|
163
|
+
const NodeSandbox = serviceConstructor(["axern", "node", "sandbox", "v1", "NodeSandbox"]);
|
|
164
|
+
const node = new NodeSandbox(this.endpoint, this.credentials, this.controlOptions);
|
|
165
|
+
const stream = serverStream(node, "ReadOutput", {
|
|
166
|
+
allocation_id: allocationId,
|
|
167
|
+
cursor,
|
|
168
|
+
follow: options.follow ?? false,
|
|
169
|
+
});
|
|
170
|
+
try {
|
|
171
|
+
for await (const event of stream) {
|
|
172
|
+
cursor = String(event.next_cursor ?? cursor);
|
|
173
|
+
retryDelayMs = 100;
|
|
174
|
+
notFoundSince = 0;
|
|
175
|
+
yield event;
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
const code = error.code;
|
|
181
|
+
const startupNotFound = code === grpc.status.NOT_FOUND;
|
|
182
|
+
if (!(options.follow ?? false) || (!transientReadError(error) && !startupNotFound)) {
|
|
183
|
+
throw mapRpcError(error, "read run output");
|
|
184
|
+
}
|
|
185
|
+
if (startupNotFound) {
|
|
186
|
+
notFoundSince ||= Date.now();
|
|
187
|
+
if (Date.now() - notFoundSince >= 30_000)
|
|
188
|
+
throw mapRpcError(error, "read run output");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
node.close();
|
|
193
|
+
}
|
|
194
|
+
await sleep(retryDelayMs);
|
|
195
|
+
retryDelayMs = Math.min(retryDelayMs * 2, 2_000);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
117
198
|
async createService(options) {
|
|
118
199
|
const resources = buildResourceSpec(options);
|
|
119
200
|
try {
|
|
@@ -180,6 +261,17 @@ function serviceVolumeMounts(mounts) {
|
|
|
180
261
|
options: [...(mount.options ?? [])],
|
|
181
262
|
}));
|
|
182
263
|
}
|
|
264
|
+
function serverStream(client, method, request) {
|
|
265
|
+
const fn = client[method];
|
|
266
|
+
return fn.call(client, request);
|
|
267
|
+
}
|
|
268
|
+
function transientReadError(error) {
|
|
269
|
+
const code = error.code;
|
|
270
|
+
return code === grpc.status.UNAVAILABLE || code === grpc.status.DEADLINE_EXCEEDED;
|
|
271
|
+
}
|
|
272
|
+
function sleep(milliseconds) {
|
|
273
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
274
|
+
}
|
|
183
275
|
function controlCredentials(options) {
|
|
184
276
|
const configured = [options.tlsCaCert, options.tlsCert, options.tlsKey].filter((value) => value !== undefined && value !== "");
|
|
185
277
|
if (configured.length === 0) {
|
package/dist/generated/proto.js
CHANGED
|
@@ -15,6 +15,7 @@ const defaultProtoRootCandidates = [
|
|
|
15
15
|
];
|
|
16
16
|
const protoFiles = [
|
|
17
17
|
"axern/control/environment/v1/environment.proto",
|
|
18
|
+
"axern/control/run/v1/run.proto",
|
|
18
19
|
"axern/control/service/v1/service.proto",
|
|
19
20
|
"axern/control/tunnel/v1/tunnel.proto",
|
|
20
21
|
"axern/node/sandbox/v1/node.proto",
|
|
@@ -44,6 +44,13 @@ message ResolveAllocationTerminalRequest {
|
|
|
44
44
|
int64 ttl_seconds = 2;
|
|
45
45
|
string client_certificate_fingerprint = 3;
|
|
46
46
|
string rollout_execution_lease = 4;
|
|
47
|
+
AllocationAccessPurpose purpose = 5;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
enum AllocationAccessPurpose {
|
|
51
|
+
ALLOCATION_ACCESS_PURPOSE_UNSPECIFIED = 0;
|
|
52
|
+
ALLOCATION_ACCESS_PURPOSE_INTERACTIVE = 1;
|
|
53
|
+
ALLOCATION_ACCESS_PURPOSE_RUN_OUTPUT = 2;
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
message ResolveAllocationTerminalResponse {
|
|
@@ -34,6 +34,9 @@ message Run {
|
|
|
34
34
|
bool exit_code_known = 13;
|
|
35
35
|
string message = 14;
|
|
36
36
|
axern.control.common.v1.WorkloadDiagnosticCode diagnostic_code = 15;
|
|
37
|
+
// Reserved for durable output metadata once output retention is owned by
|
|
38
|
+
// the control plane rather than inferred from a node-local allocation.
|
|
39
|
+
reserved 16 to 18;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
message RunListFilter {
|
|
@@ -63,6 +66,15 @@ message GetRunResponse {
|
|
|
63
66
|
Run run = 1;
|
|
64
67
|
}
|
|
65
68
|
|
|
69
|
+
message WatchRunRequest {
|
|
70
|
+
string run_id = 1;
|
|
71
|
+
int64 after_version = 2;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
message WatchRunResponse {
|
|
75
|
+
Run run = 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
66
78
|
message ListRunsRequest {
|
|
67
79
|
RunListFilter filter = 1;
|
|
68
80
|
}
|
|
@@ -83,6 +95,7 @@ message CancelRunResponse {
|
|
|
83
95
|
service RunControl {
|
|
84
96
|
rpc CreateRun(CreateRunRequest) returns (CreateRunResponse) {}
|
|
85
97
|
rpc GetRun(GetRunRequest) returns (GetRunResponse) {}
|
|
98
|
+
rpc WatchRun(WatchRunRequest) returns (stream WatchRunResponse) {}
|
|
86
99
|
rpc ListRuns(ListRunsRequest) returns (ListRunsResponse) {}
|
|
87
100
|
rpc CancelRun(CancelRunRequest) returns (CancelRunResponse) {}
|
|
88
101
|
}
|
|
@@ -34,6 +34,7 @@ message SecretListFilter {
|
|
|
34
34
|
message CreateSecretRequest {
|
|
35
35
|
string namespace = 1;
|
|
36
36
|
SecretType type = 2;
|
|
37
|
+
// The JSON-encoded map must not exceed 64 KiB. Values are preserved verbatim.
|
|
37
38
|
map<string, string> string_data = 3;
|
|
38
39
|
map<string, string> labels = 4;
|
|
39
40
|
}
|
|
@@ -199,6 +199,29 @@ message WaitSandboxResponse {
|
|
|
199
199
|
string message = 4;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
enum OutputStream {
|
|
203
|
+
OUTPUT_STREAM_UNSPECIFIED = 0;
|
|
204
|
+
OUTPUT_STREAM_STDOUT = 1;
|
|
205
|
+
OUTPUT_STREAM_STDERR = 2;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
message ReadOutputRequest {
|
|
209
|
+
string allocation_id = 1;
|
|
210
|
+
int64 attempt = 2;
|
|
211
|
+
string execution_lease_token = 3;
|
|
212
|
+
string cursor = 4;
|
|
213
|
+
bool follow = 5;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
message ReadOutputResponse {
|
|
217
|
+
OutputStream stream = 1;
|
|
218
|
+
bytes data = 2;
|
|
219
|
+
string next_cursor = 3;
|
|
220
|
+
bool terminal = 4;
|
|
221
|
+
bool truncated = 5;
|
|
222
|
+
int64 observed_at_unix_milli = 6;
|
|
223
|
+
}
|
|
224
|
+
|
|
202
225
|
// Capabilities
|
|
203
226
|
|
|
204
227
|
message CapabilityStatusRequest {
|
|
@@ -620,6 +643,7 @@ service NodeSandbox {
|
|
|
620
643
|
rpc ExecImage(ExecImageRequest) returns (ExecImageResponse) {}
|
|
621
644
|
rpc ProcessImage(stream ProcessImageRequest) returns (stream ProcessImageResponse) {}
|
|
622
645
|
rpc WaitSandbox(WaitSandboxRequest) returns (WaitSandboxResponse) {}
|
|
646
|
+
rpc ReadOutput(ReadOutputRequest) returns (stream ReadOutputResponse) {}
|
|
623
647
|
rpc CapabilityStatus(CapabilityStatusRequest) returns (CapabilityStatusResponse) {}
|
|
624
648
|
rpc ProxyHTTP(stream ProxyHTTPRequest) returns (stream ProxyHTTPResponse) {}
|
|
625
649
|
rpc StatFile(StatFileRequest) returns (StatFileResponse) {}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED