@helmr/sdk 0.1.0-preview.g52eb0eef.b35190749915
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/LICENSE +190 -0
- package/README.md +65 -0
- package/dist/actor.d.ts +3 -0
- package/dist/client-actor.d.ts +32 -0
- package/dist/client-deployment.d.ts +30 -0
- package/dist/client-sandbox.d.ts +26 -0
- package/dist/client-schedule.d.ts +44 -0
- package/dist/client-secret.d.ts +51 -0
- package/dist/client-session.d.ts +38 -0
- package/dist/client-workspace.d.ts +36 -0
- package/dist/client.d.ts +153 -0
- package/dist/config.d.ts +11 -0
- package/dist/contract.d.ts +341 -0
- package/dist/definitions.d.ts +42 -0
- package/dist/fuzzy.d.ts +1 -0
- package/dist/fuzzy.js +29 -0
- package/dist/image.d.ts +63 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +3029 -0
- package/dist/internal/abort.d.ts +1 -0
- package/dist/internal/definition-query.d.ts +10 -0
- package/dist/internal/id.d.ts +1 -0
- package/dist/internal/jsoncanon.d.ts +5 -0
- package/dist/internal/origin.d.ts +1 -0
- package/dist/internal/program.d.ts +10 -0
- package/dist/internal/run-failure.d.ts +2 -0
- package/dist/internal/run-handle.d.ts +3 -0
- package/dist/internal/runtime.d.ts +43 -0
- package/dist/internal/session.d.ts +5 -0
- package/dist/internal/strings.d.ts +1 -0
- package/dist/internal/timestamp.d.ts +1 -0
- package/dist/internal/utf8.d.ts +3 -0
- package/dist/internal.d.ts +13 -0
- package/dist/internal.js +994 -0
- package/dist/logger.d.ts +9 -0
- package/dist/metadata.d.ts +6 -0
- package/dist/request.d.ts +3 -0
- package/dist/schedules.d.ts +33 -0
- package/dist/schema/payload.d.ts +39 -0
- package/dist/schema/task.d.ts +3 -0
- package/dist/secret.d.ts +1 -0
- package/dist/session.d.ts +5 -0
- package/dist/task.d.ts +2 -0
- package/dist/timers.d.ts +6 -0
- package/dist/tokens.d.ts +77 -0
- package/dist/workspace.d.ts +142 -0
- package/package.json +49 -0
package/dist/internal.js
ADDED
|
@@ -0,0 +1,994 @@
|
|
|
1
|
+
// sdk/typescript/src/internal/utf8.ts
|
|
2
|
+
var encoder = new TextEncoder;
|
|
3
|
+
var encode = TextEncoder.prototype.encode.call.bind(TextEncoder.prototype.encode);
|
|
4
|
+
var charCodeAt = String.prototype.charCodeAt.call.bind(String.prototype.charCodeAt);
|
|
5
|
+
function compareUTF8(left, right) {
|
|
6
|
+
const leftBytes = encode(encoder, left);
|
|
7
|
+
const rightBytes = encode(encoder, right);
|
|
8
|
+
const length = leftBytes.length < rightBytes.length ? leftBytes.length : rightBytes.length;
|
|
9
|
+
for (let index = 0;index < length; index++) {
|
|
10
|
+
const difference = leftBytes[index] - rightBytes[index];
|
|
11
|
+
if (difference !== 0)
|
|
12
|
+
return difference;
|
|
13
|
+
}
|
|
14
|
+
return leftBytes.length - rightBytes.length;
|
|
15
|
+
}
|
|
16
|
+
function hasOnlyUnicodeScalarValues(value) {
|
|
17
|
+
for (let index = 0;index < value.length; index++) {
|
|
18
|
+
const unit = charCodeAt(value, index);
|
|
19
|
+
if (unit >= 55296 && unit <= 56319) {
|
|
20
|
+
if (index + 1 === value.length)
|
|
21
|
+
return false;
|
|
22
|
+
const next = charCodeAt(value, index + 1);
|
|
23
|
+
if (next < 56320 || next > 57343)
|
|
24
|
+
return false;
|
|
25
|
+
index++;
|
|
26
|
+
} else if (unit >= 56320 && unit <= 57343) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
function assertUnicodeString(value) {
|
|
33
|
+
if (!hasOnlyUnicodeScalarValues(value)) {
|
|
34
|
+
throw new Error("canonical JSON contains an unpaired surrogate");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// sdk/typescript/src/config.ts
|
|
39
|
+
var arrayIsArray = Array.isArray;
|
|
40
|
+
var arrayPrototype = Array.prototype;
|
|
41
|
+
var defineProperty = Object.defineProperty;
|
|
42
|
+
var objectPrototype = Object.prototype;
|
|
43
|
+
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
44
|
+
var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors;
|
|
45
|
+
var getPrototypeOf = Object.getPrototypeOf;
|
|
46
|
+
var hasOwn = Object.hasOwn;
|
|
47
|
+
var freeze = Object.freeze;
|
|
48
|
+
var ownKeys = Reflect.ownKeys;
|
|
49
|
+
var startsWith = String.prototype.startsWith.call.bind(String.prototype.startsWith);
|
|
50
|
+
var endsWith = String.prototype.endsWith.call.bind(String.prototype.endsWith);
|
|
51
|
+
var includes = String.prototype.includes.call.bind(String.prototype.includes);
|
|
52
|
+
var split = String.prototype.split.call.bind(String.prototype.split);
|
|
53
|
+
var slice = String.prototype.slice.call.bind(String.prototype.slice);
|
|
54
|
+
var charCodeAt2 = String.prototype.charCodeAt.call.bind(String.prototype.charCodeAt);
|
|
55
|
+
var regexpTest = RegExp.prototype.test.call.bind(RegExp.prototype.test);
|
|
56
|
+
function inspectConfig(value) {
|
|
57
|
+
if (typeof value !== "object" || value === null) {
|
|
58
|
+
throw new Error("config must be an ordinary object");
|
|
59
|
+
}
|
|
60
|
+
return normalizeConfig(value);
|
|
61
|
+
}
|
|
62
|
+
function matchesIgnorePattern(pattern, path) {
|
|
63
|
+
const patternSegments = split(pattern, "/");
|
|
64
|
+
const pathSegments = split(path, "/");
|
|
65
|
+
const matches = (patternIndex, pathIndex) => {
|
|
66
|
+
if (patternIndex === patternSegments.length) {
|
|
67
|
+
return pathIndex === pathSegments.length;
|
|
68
|
+
}
|
|
69
|
+
const segment = patternSegments[patternIndex];
|
|
70
|
+
if (segment === "**") {
|
|
71
|
+
if (patternIndex === patternSegments.length - 1) {
|
|
72
|
+
return pathIndex < pathSegments.length;
|
|
73
|
+
}
|
|
74
|
+
for (let candidate = pathIndex;candidate <= pathSegments.length; candidate++) {
|
|
75
|
+
if (matches(patternIndex + 1, candidate))
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return pathIndex < pathSegments.length && matchesSegment(segment, pathSegments[pathIndex]) && matches(patternIndex + 1, pathIndex + 1);
|
|
81
|
+
};
|
|
82
|
+
return matches(0, 0);
|
|
83
|
+
}
|
|
84
|
+
function validateDirectory(value) {
|
|
85
|
+
if (typeof value !== "string" || value === "" || !hasOnlyUnicodeScalarValues(value) || startsWith(value, "/") || includes(value, "\\") || hasControl(value)) {
|
|
86
|
+
throw new Error("config dirs entries must be non-empty root-relative POSIX paths");
|
|
87
|
+
}
|
|
88
|
+
const normalized = startsWith(value, "./") ? slice(value, 2) : value;
|
|
89
|
+
const segments = split(normalized, "/");
|
|
90
|
+
let invalidSegment = normalized === "";
|
|
91
|
+
for (let index = 0;index < segments.length; index++) {
|
|
92
|
+
const segment = segments[index];
|
|
93
|
+
if (segment === "" || segment === "." || segment === "..") {
|
|
94
|
+
invalidSegment = true;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (invalidSegment) {
|
|
99
|
+
throw new Error("config dirs entries must be normalized root-relative paths");
|
|
100
|
+
}
|
|
101
|
+
return normalized;
|
|
102
|
+
}
|
|
103
|
+
function validateIgnorePattern(value) {
|
|
104
|
+
if (typeof value !== "string" || value === "" || !hasOnlyUnicodeScalarValues(value) || startsWith(value, "./") || startsWith(value, "/") || endsWith(value, "/") || includes(value, "//") || includes(value, "\\") || hasControl(value) || startsWith(value, "!") || regexpTest(/[[\]{}]/, value) || regexpTest(/[?*+@!]\(/, value)) {
|
|
105
|
+
throw new Error(`unsupported ignorePattern ${JSON.stringify(value)}`);
|
|
106
|
+
}
|
|
107
|
+
const segments = split(value, "/");
|
|
108
|
+
for (let index = 0;index < segments.length; index++) {
|
|
109
|
+
const segment = segments[index];
|
|
110
|
+
if (segment === ".." || includes(segment, "**") && segment !== "**") {
|
|
111
|
+
throw new Error(`unsupported ignorePattern ${JSON.stringify(value)}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
function matchesSegment(pattern, value) {
|
|
117
|
+
const patternCharacters = codePoints(pattern);
|
|
118
|
+
const valueCharacters = codePoints(value);
|
|
119
|
+
let patternIndex = 0;
|
|
120
|
+
let valueIndex = 0;
|
|
121
|
+
let star = -1;
|
|
122
|
+
let starValue = -1;
|
|
123
|
+
while (valueIndex < valueCharacters.length) {
|
|
124
|
+
const token = patternCharacters[patternIndex];
|
|
125
|
+
if (token === "?" || token === valueCharacters[valueIndex]) {
|
|
126
|
+
patternIndex++;
|
|
127
|
+
valueIndex++;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (token === "*") {
|
|
131
|
+
star = patternIndex++;
|
|
132
|
+
starValue = valueIndex;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (star !== -1) {
|
|
136
|
+
patternIndex = star + 1;
|
|
137
|
+
valueIndex = ++starValue;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
while (patternCharacters[patternIndex] === "*")
|
|
143
|
+
patternIndex++;
|
|
144
|
+
return patternIndex === patternCharacters.length;
|
|
145
|
+
}
|
|
146
|
+
function hasControl(value) {
|
|
147
|
+
for (let index = 0;index < value.length; index++) {
|
|
148
|
+
const code = charCodeAt2(value, index);
|
|
149
|
+
if (code <= 31 || code >= 127 && code <= 159)
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
function codePoints(value) {
|
|
155
|
+
const result = [];
|
|
156
|
+
for (let index = 0;index < value.length; ) {
|
|
157
|
+
const first = charCodeAt2(value, index);
|
|
158
|
+
const width = first >= 55296 && first <= 56319 ? 2 : 1;
|
|
159
|
+
setArrayIndex(result, result.length, slice(value, index, index + width));
|
|
160
|
+
index += width;
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
function normalizeConfig(value) {
|
|
165
|
+
if (arrayIsArray(value) || getPrototypeOf(value) !== objectPrototype) {
|
|
166
|
+
throw new Error("config must be an ordinary object");
|
|
167
|
+
}
|
|
168
|
+
const descriptors = getOwnPropertyDescriptors(value);
|
|
169
|
+
const keys = ownKeys(value);
|
|
170
|
+
let invalidKey = false;
|
|
171
|
+
for (let index = 0;index < keys.length; index++) {
|
|
172
|
+
const key = keys[index];
|
|
173
|
+
if (typeof key !== "string" || key !== "dirs" && key !== "ignorePatterns") {
|
|
174
|
+
invalidKey = true;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (invalidKey) {
|
|
179
|
+
throw new Error("config accepts only dirs and ignorePatterns");
|
|
180
|
+
}
|
|
181
|
+
for (let index = 0;index < keys.length; index++) {
|
|
182
|
+
const key = keys[index];
|
|
183
|
+
if (typeof key !== "string") {
|
|
184
|
+
throw new Error("config accepts only dirs and ignorePatterns");
|
|
185
|
+
}
|
|
186
|
+
const descriptor = descriptors[key];
|
|
187
|
+
if (descriptor === undefined || !descriptor.enumerable || !hasOwn(descriptor, "value")) {
|
|
188
|
+
throw new Error("config properties must be enumerable data properties");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const dirs = normalizeStringSet(hasOwn(descriptors, "dirs") ? descriptors["dirs"]?.value : ["tasks"], "config dirs", validateDirectory, true);
|
|
192
|
+
const ignorePatterns = normalizeStringSet(hasOwn(descriptors, "ignorePatterns") ? descriptors["ignorePatterns"]?.value : [], "config ignorePatterns", validateIgnorePattern, false);
|
|
193
|
+
return freeze({
|
|
194
|
+
dirs: freeze(dirs),
|
|
195
|
+
ignorePatterns: freeze(ignorePatterns)
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
function normalizeStringSet(value, name, normalize, nonempty) {
|
|
199
|
+
if (!arrayIsArray(value) || getPrototypeOf(value) !== arrayPrototype) {
|
|
200
|
+
throw new Error(`${name} must be an array`);
|
|
201
|
+
}
|
|
202
|
+
const keys = ownKeys(value);
|
|
203
|
+
const lengthDescriptor = getOwnPropertyDescriptor(value, "length");
|
|
204
|
+
const length = lengthDescriptor?.value;
|
|
205
|
+
if (typeof length !== "number" || keys.length !== length + 1 || keys[length] !== "length") {
|
|
206
|
+
throw new Error(`${name} must be a dense ordinary array`);
|
|
207
|
+
}
|
|
208
|
+
const normalized = [];
|
|
209
|
+
for (let index = 0;index < length; index++) {
|
|
210
|
+
const key = `${index}`;
|
|
211
|
+
if (keys[index] !== key) {
|
|
212
|
+
throw new Error(`${name} must be a dense ordinary array`);
|
|
213
|
+
}
|
|
214
|
+
const descriptor = getOwnPropertyDescriptor(value, key);
|
|
215
|
+
if (descriptor === undefined || !descriptor.enumerable || !hasOwn(descriptor, "value")) {
|
|
216
|
+
throw new Error(`${name} entries must be enumerable data properties`);
|
|
217
|
+
}
|
|
218
|
+
const current = normalize(descriptor.value);
|
|
219
|
+
let insertion = normalized.length;
|
|
220
|
+
while (insertion > 0 && compareUTF8(current, normalized[insertion - 1]) < 0) {
|
|
221
|
+
setArrayIndex(normalized, insertion, normalized[insertion - 1]);
|
|
222
|
+
insertion--;
|
|
223
|
+
}
|
|
224
|
+
setArrayIndex(normalized, insertion, current);
|
|
225
|
+
}
|
|
226
|
+
if (nonempty && length === 0) {
|
|
227
|
+
throw new Error(`${name} must be non-empty`);
|
|
228
|
+
}
|
|
229
|
+
for (let index = 1;index < normalized.length; index++) {
|
|
230
|
+
if (normalized[index] === normalized[index - 1]) {
|
|
231
|
+
throw new Error(`${name} contains a duplicate entry`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return normalized;
|
|
235
|
+
}
|
|
236
|
+
function setArrayIndex(array, index, value) {
|
|
237
|
+
defineProperty(array, `${index}`, {
|
|
238
|
+
configurable: true,
|
|
239
|
+
enumerable: true,
|
|
240
|
+
value,
|
|
241
|
+
writable: true
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
// sdk/typescript/src/schema/payload.ts
|
|
245
|
+
var payloadSchemaValidationErrorBrand = Symbol.for("helmr.sdk.PayloadSchemaValidationError");
|
|
246
|
+
function assertPayloadSchema(value, label = "payload") {
|
|
247
|
+
if (value === undefined) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
assertStandardSchema(value, label);
|
|
251
|
+
}
|
|
252
|
+
function assertStandardSchema(value, label = "schema") {
|
|
253
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
254
|
+
throw new Error(`${label} must implement the Standard Schema v1 interface`);
|
|
255
|
+
}
|
|
256
|
+
const standard = value["~standard"];
|
|
257
|
+
if (standard === null || typeof standard !== "object") {
|
|
258
|
+
throw new Error(`${label} must implement the Standard Schema v1 interface`);
|
|
259
|
+
}
|
|
260
|
+
const record = standard;
|
|
261
|
+
if (record["version"] !== 1 || typeof record["validate"] !== "function") {
|
|
262
|
+
throw new Error(`${label} must implement the Standard Schema v1 interface`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// sdk/typescript/src/schema/task.ts
|
|
267
|
+
var TASK_ID_PATTERN = "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$";
|
|
268
|
+
var TASK_ID_MAX_LENGTH = 128;
|
|
269
|
+
var QUEUE_NAME_PATTERN = "^[A-Za-z0-9][A-Za-z0-9._/-]{0,255}$";
|
|
270
|
+
var QUEUE_NAME_MAX_LENGTH = 256;
|
|
271
|
+
|
|
272
|
+
class TaskIdError extends Error {
|
|
273
|
+
name = "TaskIdError";
|
|
274
|
+
value;
|
|
275
|
+
constructor(value) {
|
|
276
|
+
super(`task id must match ${TASK_ID_PATTERN}: ${JSON.stringify(value)}`);
|
|
277
|
+
this.value = value;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function validateTaskId(value) {
|
|
281
|
+
if (!isValidTaskId(value)) {
|
|
282
|
+
throw new TaskIdError(value);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function isValidTaskId(value) {
|
|
286
|
+
if (value.length === 0 || value.length > TASK_ID_MAX_LENGTH) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
const first = value.charCodeAt(0);
|
|
290
|
+
if (!isAsciiAlnum(first)) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
for (let index = 1;index < value.length; index += 1) {
|
|
294
|
+
const code = value.charCodeAt(index);
|
|
295
|
+
if (!(isAsciiAlnum(code) || code === 46 || code === 95 || code === 45)) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
class TaskQueueNameError extends Error {
|
|
303
|
+
name = "TaskQueueNameError";
|
|
304
|
+
value;
|
|
305
|
+
constructor(value) {
|
|
306
|
+
super(`queue name must match ${QUEUE_NAME_PATTERN}: ${JSON.stringify(value)}`);
|
|
307
|
+
this.value = value;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
class TaskQueueConcurrencyLimitError extends Error {
|
|
312
|
+
name = "TaskQueueConcurrencyLimitError";
|
|
313
|
+
value;
|
|
314
|
+
constructor(value) {
|
|
315
|
+
super("queue concurrencyLimit must be a positive integer");
|
|
316
|
+
this.value = value;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function validateQueueName(value) {
|
|
320
|
+
if (!isValidQueueName(value)) {
|
|
321
|
+
throw new TaskQueueNameError(value);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function isValidQueueName(value) {
|
|
325
|
+
if (value.length === 0 || value.length > QUEUE_NAME_MAX_LENGTH) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
const first = value.charCodeAt(0);
|
|
329
|
+
if (!isAsciiAlnum(first)) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
for (let index = 1;index < value.length; index += 1) {
|
|
333
|
+
const code = value.charCodeAt(index);
|
|
334
|
+
if (!(isAsciiAlnum(code) || code === 46 || code === 95 || code === 45 || code === 47)) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
function validateOptionalQueueConcurrencyLimit(value) {
|
|
341
|
+
if (value === undefined || value === null) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value > 0) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
throw new TaskQueueConcurrencyLimitError(value);
|
|
348
|
+
}
|
|
349
|
+
function isAsciiAlnum(code) {
|
|
350
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// sdk/typescript/src/internal/runtime.ts
|
|
354
|
+
var runtimeOperationsSymbol = Symbol.for("helmr.sdk.v0.runtime_operations");
|
|
355
|
+
function installRuntimeOperations(operations) {
|
|
356
|
+
const target = globalThis;
|
|
357
|
+
if (target[runtimeOperationsSymbol] !== undefined) {
|
|
358
|
+
throw new Error("Helmr runtime operations are already installed");
|
|
359
|
+
}
|
|
360
|
+
const installed = Object.freeze(operations);
|
|
361
|
+
target[runtimeOperationsSymbol] = installed;
|
|
362
|
+
return () => {
|
|
363
|
+
if (target[runtimeOperationsSymbol] === installed) {
|
|
364
|
+
delete target[runtimeOperationsSymbol];
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function currentRuntimeOperations() {
|
|
369
|
+
const operations = globalThis[runtimeOperationsSymbol];
|
|
370
|
+
if (operations === undefined) {
|
|
371
|
+
throw new Error("runtime operation is unavailable without the Helmr managed runtime");
|
|
372
|
+
}
|
|
373
|
+
return operations;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// sdk/typescript/src/internal/id.ts
|
|
377
|
+
var uuidV7Pattern = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
378
|
+
function resourceID(value, label) {
|
|
379
|
+
if (typeof value !== "string" || !uuidV7Pattern.test(value)) {
|
|
380
|
+
throw new Error(`${label} must be a canonical UUIDv7`);
|
|
381
|
+
}
|
|
382
|
+
return value;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// sdk/typescript/src/session.ts
|
|
386
|
+
function createRuntimeSessionRef(id) {
|
|
387
|
+
const sessionID = resourceID(id, "Session ID");
|
|
388
|
+
return Object.freeze({
|
|
389
|
+
id: sessionID,
|
|
390
|
+
input: Object.freeze({
|
|
391
|
+
send(input, request, options) {
|
|
392
|
+
return currentRuntimeOperations().actorInputSend(sessionID, input, request, options?.signal);
|
|
393
|
+
}
|
|
394
|
+
}),
|
|
395
|
+
output: Object.freeze({
|
|
396
|
+
list(query, options) {
|
|
397
|
+
return currentRuntimeOperations().sessionOutputPage(sessionID, query, options?.signal);
|
|
398
|
+
}
|
|
399
|
+
}),
|
|
400
|
+
retrieve(options = {}) {
|
|
401
|
+
return currentRuntimeOperations().sessionRetrieve(sessionID, options.signal);
|
|
402
|
+
},
|
|
403
|
+
close(request, options) {
|
|
404
|
+
return currentRuntimeOperations().sessionClose(sessionID, request, options?.signal);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
var sessions = Object.freeze({
|
|
409
|
+
ref(id) {
|
|
410
|
+
return createRuntimeSessionRef(id);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// sdk/typescript/src/internal/run-handle.ts
|
|
415
|
+
function createRunHandle(id) {
|
|
416
|
+
return Object.freeze({
|
|
417
|
+
id: resourceID(id, "Run ID")
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
function runHandleID(value) {
|
|
421
|
+
return resourceID(typeof value === "string" ? value : value.id, "Run ID");
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// sdk/typescript/src/definitions.ts
|
|
425
|
+
var privateDefinitionBrand = Symbol.for("helmr.sdk.v0.definition");
|
|
426
|
+
var privateQueueBrand = Symbol.for("helmr.sdk.v0.queue");
|
|
427
|
+
function inspectDefinition(value) {
|
|
428
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
if (!Object.hasOwn(value, privateDefinitionBrand))
|
|
432
|
+
return;
|
|
433
|
+
const definition = value[privateDefinitionBrand];
|
|
434
|
+
if (!isInternalDefinition(definition)) {
|
|
435
|
+
throw new Error("invalid private definition record");
|
|
436
|
+
}
|
|
437
|
+
return definition;
|
|
438
|
+
}
|
|
439
|
+
function isQueue(value) {
|
|
440
|
+
if (typeof value !== "object" || value === null)
|
|
441
|
+
return false;
|
|
442
|
+
if (!Object.hasOwn(value, privateQueueBrand))
|
|
443
|
+
return false;
|
|
444
|
+
if (value[privateQueueBrand] !== true) {
|
|
445
|
+
throw new Error("invalid private queue record");
|
|
446
|
+
}
|
|
447
|
+
const queue = value;
|
|
448
|
+
if (typeof queue.name !== "string") {
|
|
449
|
+
throw new Error("invalid private queue record");
|
|
450
|
+
}
|
|
451
|
+
validateQueueName(queue.name);
|
|
452
|
+
validateOptionalQueueConcurrencyLimit(queue.concurrencyLimit);
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
455
|
+
function isInternalDefinition(value) {
|
|
456
|
+
if (typeof value !== "object" || value === null)
|
|
457
|
+
return false;
|
|
458
|
+
const definition = value;
|
|
459
|
+
if (typeof definition.id !== "string")
|
|
460
|
+
return false;
|
|
461
|
+
validateTaskId(definition.id);
|
|
462
|
+
switch (definition.kind) {
|
|
463
|
+
case "task":
|
|
464
|
+
if (typeof definition.handler !== "function" || typeof definition.hasPayload !== "boolean") {
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
if (definition.hasPayload) {
|
|
468
|
+
assertPayloadSchema(definition.payloadSchema, `task ${JSON.stringify(definition.id)} payload`);
|
|
469
|
+
} else if (Object.hasOwn(definition, "payloadSchema")) {
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
return true;
|
|
473
|
+
case "actor":
|
|
474
|
+
return typeof definition.handler === "function";
|
|
475
|
+
default:
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// sdk/typescript/src/image.ts
|
|
480
|
+
var imageBrand = Symbol.for("helmr.sdk.v0.image");
|
|
481
|
+
var sourceFileBrand = Symbol.for("helmr.sdk.v0.source-file");
|
|
482
|
+
var sourceDirectoryBrand = Symbol.for("helmr.sdk.v0.source-directory");
|
|
483
|
+
class SourceFileValue {
|
|
484
|
+
path;
|
|
485
|
+
constructor(path) {
|
|
486
|
+
this.path = path;
|
|
487
|
+
Object.defineProperty(this, sourceFileBrand, { value: true });
|
|
488
|
+
Object.freeze(this);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
class SourceDirectoryValue {
|
|
493
|
+
path;
|
|
494
|
+
constructor(path) {
|
|
495
|
+
this.path = path;
|
|
496
|
+
Object.defineProperty(this, sourceDirectoryBrand, { value: true });
|
|
497
|
+
Object.freeze(this);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
var source = Object.freeze({
|
|
501
|
+
file(path) {
|
|
502
|
+
return new SourceFileValue(path);
|
|
503
|
+
},
|
|
504
|
+
directory(path) {
|
|
505
|
+
return new SourceDirectoryValue(path);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
function inspectImage(value) {
|
|
509
|
+
if (typeof value !== "object" || value === null || value[imageBrand] !== true) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const imageValue = value;
|
|
513
|
+
return { key: imageValue.key, steps: imageValue.steps };
|
|
514
|
+
}
|
|
515
|
+
// sdk/typescript/src/secret.ts
|
|
516
|
+
var secretNamePattern = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/;
|
|
517
|
+
function validateSecretName(value) {
|
|
518
|
+
if (typeof value !== "string" || !secretNamePattern.test(value)) {
|
|
519
|
+
throw new Error("Secret name is invalid");
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// sdk/typescript/src/internal/origin.ts
|
|
524
|
+
function canonicalSecretOrigin(value) {
|
|
525
|
+
if (typeof value !== "string" || value.trim() !== value || !/^https:\/\//i.test(value)) {
|
|
526
|
+
throw new Error("Secret origin must be an exact HTTPS origin");
|
|
527
|
+
}
|
|
528
|
+
const authority = value.replace(/^https:\/\//i, "").replace(/\/$/, "");
|
|
529
|
+
if (!/^[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(authority))
|
|
530
|
+
throw new Error("Secret origin must contain only a DNS hostname and optional port");
|
|
531
|
+
const [rawHost, port] = authority.split(":");
|
|
532
|
+
const host = rawHost.toLowerCase();
|
|
533
|
+
if (host.length > 253 || host === "localhost" || host.endsWith(".localhost") || /^[0-9.]+$/.test(host) || host.split(".").some((label) => !/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label))) {
|
|
534
|
+
throw new Error("Secret origin must use a DNS hostname without wildcards or IP addresses");
|
|
535
|
+
}
|
|
536
|
+
if (port !== undefined && (!/^[1-9][0-9]*$/.test(port) || Number(port) > 65535))
|
|
537
|
+
throw new Error("Secret origin port is invalid");
|
|
538
|
+
return `https://${host}${port === undefined || port === "443" ? "" : `:${port}`}`;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// sdk/typescript/src/internal/timestamp.ts
|
|
542
|
+
var utcRFC3339 = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,9})?Z$/;
|
|
543
|
+
function timestampString(value, label) {
|
|
544
|
+
const match = typeof value === "string" ? utcRFC3339.exec(value) : null;
|
|
545
|
+
if (match === null || !validDateTime(match)) {
|
|
546
|
+
throw new Error(`${label} must be a UTC RFC 3339 timestamp`);
|
|
547
|
+
}
|
|
548
|
+
return value;
|
|
549
|
+
}
|
|
550
|
+
function validDateTime(match) {
|
|
551
|
+
const year = Number(match[1]);
|
|
552
|
+
const month = Number(match[2]);
|
|
553
|
+
const day = Number(match[3]);
|
|
554
|
+
const hour = Number(match[4]);
|
|
555
|
+
const minute = Number(match[5]);
|
|
556
|
+
const second = Number(match[6]);
|
|
557
|
+
if (month < 1 || month > 12 || hour > 23 || minute > 59 || second > 59) {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
561
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
562
|
+
return day >= 1 && day <= days[month - 1];
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// sdk/typescript/src/workspace.ts
|
|
566
|
+
var sandboxDefinitionBrand = Symbol.for("helmr.sdk.v0.sandbox");
|
|
567
|
+
var workspaceAddressBrand = Symbol.for("helmr.sdk.v0.workspace-address");
|
|
568
|
+
var workspaces = Object.freeze({
|
|
569
|
+
ref: createWorkspaceRef
|
|
570
|
+
});
|
|
571
|
+
function inspectWorkspaceAddress(value) {
|
|
572
|
+
if (typeof value !== "object" || value === null || value[workspaceAddressBrand] !== true) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const address = value;
|
|
576
|
+
if (address.id === undefined) {
|
|
577
|
+
throw new Error("private Workspace address is invalid");
|
|
578
|
+
}
|
|
579
|
+
return createWorkspaceAddress(address.id);
|
|
580
|
+
}
|
|
581
|
+
function workspaceRefID(value) {
|
|
582
|
+
const address = inspectWorkspaceAddress(value);
|
|
583
|
+
if (address === undefined || typeof address.id !== "string") {
|
|
584
|
+
throw new Error("Workspace requires a Workspace ref");
|
|
585
|
+
}
|
|
586
|
+
return address.id;
|
|
587
|
+
}
|
|
588
|
+
function encodeWorkspaceSecrets(inputs) {
|
|
589
|
+
if (inputs === undefined)
|
|
590
|
+
return Object.freeze([]);
|
|
591
|
+
if (!Array.isArray(inputs) || inputs.length > 64)
|
|
592
|
+
throw new Error("Workspace secrets must be an array of at most 64 bindings");
|
|
593
|
+
const envNames = new Set;
|
|
594
|
+
const files = [];
|
|
595
|
+
let originCount = 0;
|
|
596
|
+
const result = inputs.map((input) => {
|
|
597
|
+
const value = workspaceObject(input, "Workspace Secret");
|
|
598
|
+
validateSecretName(value["secret"]);
|
|
599
|
+
const hasEnv = value["env"] !== undefined;
|
|
600
|
+
const hasFile = value["file"] !== undefined;
|
|
601
|
+
if (hasEnv === hasFile)
|
|
602
|
+
throw new Error("Workspace Secret requires exactly one of env or file");
|
|
603
|
+
exactBindingKeys(value, ["secret", "env", "file"]);
|
|
604
|
+
if (hasEnv) {
|
|
605
|
+
const env = workspaceObject(value["env"], "Workspace Secret env");
|
|
606
|
+
const mode = env["mode"];
|
|
607
|
+
if (mode !== "raw" && mode !== "protected")
|
|
608
|
+
throw new Error("Workspace Secret env requires explicit raw or protected mode");
|
|
609
|
+
exactBindingKeys(env, ["name", "mode", "allowedOrigins"]);
|
|
610
|
+
if (mode === "raw" && env["allowedOrigins"] !== undefined)
|
|
611
|
+
throw new Error("Raw env cannot specify allowedOrigins");
|
|
612
|
+
const name = env["name"];
|
|
613
|
+
if (typeof name !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) || name.startsWith("HELMR_") || name.startsWith("LD_") || ["NODE_OPTIONS", "NODE_PATH", "NODE_ICU_DATA", "OPENSSL_CONF", "OPENSSL_MODULES", "OPENSSL_ENGINES", "GCONV_PATH", "LOCPATH"].includes(name) || ["SSL_CERT_FILE", "SSL_CERT_DIR", "NODE_EXTRA_CA_CERTS", "NODE_USE_SYSTEM_CA"].includes(name.toUpperCase()))
|
|
614
|
+
throw new Error("Invalid or reserved Secret env name");
|
|
615
|
+
if (envNames.has(name))
|
|
616
|
+
throw new Error(`Duplicate Secret env target ${name}`);
|
|
617
|
+
envNames.add(name);
|
|
618
|
+
if (mode === "raw")
|
|
619
|
+
return Object.freeze({ secret: input.secret, env: Object.freeze({ name, mode }) });
|
|
620
|
+
const origins = env["allowedOrigins"];
|
|
621
|
+
if (!Array.isArray(origins) || origins.length === 0 || origins.length > 16)
|
|
622
|
+
throw new Error("Protected env requires 1 to 16 exact HTTPS origins");
|
|
623
|
+
const allowed_origins = Object.freeze([...new Set(origins.map(canonicalSecretOrigin))].sort());
|
|
624
|
+
originCount += allowed_origins.length;
|
|
625
|
+
return Object.freeze({ secret: input.secret, env: Object.freeze({ name, mode, allowed_origins }) });
|
|
626
|
+
}
|
|
627
|
+
const file = workspaceObject(value["file"], "Workspace Secret file");
|
|
628
|
+
exactBindingKeys(file, ["path"]);
|
|
629
|
+
const path = file["path"];
|
|
630
|
+
if (typeof path !== "string" || path.length > 4096 || !path.startsWith("/") || path === "/" || path.includes("\x00") || path.split("/").slice(1).some((part) => part === "" || part === "." || part === "..") || ["/workspace", "/var/lib/helmr", "/dev", "/opt/helmr", "/proc", "/sys", "/.helmr-old-root", "/run/helmr"].some((root) => path === root || path.startsWith(root + "/")))
|
|
631
|
+
throw new Error("Invalid or reserved Secret file path");
|
|
632
|
+
files.push(path);
|
|
633
|
+
return Object.freeze({ secret: input.secret, file: Object.freeze({ path }) });
|
|
634
|
+
});
|
|
635
|
+
files.sort();
|
|
636
|
+
if (files.some((path, index) => index > 0 && (path === files[index - 1] || path.startsWith(files[index - 1] + "/"))))
|
|
637
|
+
throw new Error("Conflicting Secret file paths");
|
|
638
|
+
if (originCount > 256)
|
|
639
|
+
throw new Error("Workspace Secret origins exceed 256");
|
|
640
|
+
return Object.freeze(result);
|
|
641
|
+
}
|
|
642
|
+
function exactBindingKeys(value, allowed) {
|
|
643
|
+
const unknown = Object.keys(value).find((key) => !allowed.includes(key));
|
|
644
|
+
if (unknown !== undefined)
|
|
645
|
+
throw new Error(`Workspace Secret has unknown member ${JSON.stringify(unknown)}`);
|
|
646
|
+
}
|
|
647
|
+
function inspectSandboxDefinition(value) {
|
|
648
|
+
if (typeof value !== "object" || value === null)
|
|
649
|
+
return;
|
|
650
|
+
if (!Object.hasOwn(value, sandboxDefinitionBrand))
|
|
651
|
+
return;
|
|
652
|
+
if (value[sandboxDefinitionBrand] !== true) {
|
|
653
|
+
throw new Error("invalid private Sandbox record");
|
|
654
|
+
}
|
|
655
|
+
const internal = value.internal;
|
|
656
|
+
if (typeof internal !== "object" || internal === null || internal.kind !== "sandbox" || typeof internal.id !== "string" || typeof internal.image !== "object" || internal.image === null || typeof internal.resources !== "object" || internal.resources === null) {
|
|
657
|
+
throw new Error("invalid private Sandbox record");
|
|
658
|
+
}
|
|
659
|
+
validateTaskId(internal.id);
|
|
660
|
+
return internal;
|
|
661
|
+
}
|
|
662
|
+
function createWorkspaceRef(id) {
|
|
663
|
+
const workspaceID = resourceID(id, "Workspace ID");
|
|
664
|
+
const operations = {
|
|
665
|
+
retrieve(options) {
|
|
666
|
+
return currentRuntimeOperations().workspaceRetrieve(workspaceID, options?.signal);
|
|
667
|
+
},
|
|
668
|
+
exec(request, options) {
|
|
669
|
+
return currentRuntimeOperations().workspaceExec(workspaceID, request, options?.signal);
|
|
670
|
+
},
|
|
671
|
+
delete(request, options) {
|
|
672
|
+
return currentRuntimeOperations().workspaceDelete(workspaceID, request, options?.signal);
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
return brandWorkspaceAddress({ id: workspaceID, ...operations });
|
|
676
|
+
}
|
|
677
|
+
function createWorkspaceAddress(id) {
|
|
678
|
+
return brandWorkspaceAddress({ id: resourceID(id, "Workspace ID") });
|
|
679
|
+
}
|
|
680
|
+
function brandWorkspaceAddress(value) {
|
|
681
|
+
resourceID(value.id, "Workspace ID");
|
|
682
|
+
return freezeWorkspaceAddress(value);
|
|
683
|
+
}
|
|
684
|
+
function freezeWorkspaceAddress(value) {
|
|
685
|
+
Object.defineProperty(value, workspaceAddressBrand, { value: true });
|
|
686
|
+
return Object.freeze(value);
|
|
687
|
+
}
|
|
688
|
+
function parseWorkspace(value) {
|
|
689
|
+
const input = workspaceObject(value, "Workspace response");
|
|
690
|
+
const key = input["key"];
|
|
691
|
+
if (key !== undefined && typeof key !== "string") {
|
|
692
|
+
throw new Error("Workspace response.key must be a string");
|
|
693
|
+
}
|
|
694
|
+
const sandboxId = input["sandbox_id"];
|
|
695
|
+
if (typeof sandboxId !== "string") {
|
|
696
|
+
throw new Error("Workspace response.sandbox_id must be a string");
|
|
697
|
+
}
|
|
698
|
+
validateTaskId(sandboxId);
|
|
699
|
+
const status = input["status"];
|
|
700
|
+
if (status !== "available" && status !== "recovery_required" && status !== "deleting") {
|
|
701
|
+
throw new Error("Workspace response.status is invalid");
|
|
702
|
+
}
|
|
703
|
+
if (!Array.isArray(input["secrets"])) {
|
|
704
|
+
throw new Error("Workspace response.secrets must be an array");
|
|
705
|
+
}
|
|
706
|
+
const owner = parseWorkspaceOwner(input["owner"], "Workspace response.owner");
|
|
707
|
+
return Object.freeze({
|
|
708
|
+
id: resourceID(input["id"], "Workspace response.id"),
|
|
709
|
+
...key === undefined ? {} : { key },
|
|
710
|
+
sandboxId,
|
|
711
|
+
deploymentId: resourceID(input["deployment_id"], "Workspace response.deployment_id"),
|
|
712
|
+
status,
|
|
713
|
+
...owner === undefined ? {} : { owner },
|
|
714
|
+
secrets: Object.freeze(input["secrets"].map(parseWorkspaceSecret)),
|
|
715
|
+
lastActivityAt: workspaceTimestamp(input["last_activity_at"], "last_activity_at"),
|
|
716
|
+
createdAt: workspaceTimestamp(input["created_at"], "created_at"),
|
|
717
|
+
updatedAt: workspaceTimestamp(input["updated_at"], "updated_at")
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
function parseWorkspaceOwner(value, label) {
|
|
721
|
+
if (value === undefined)
|
|
722
|
+
return;
|
|
723
|
+
const input = workspaceObject(value, label);
|
|
724
|
+
const hasSession = input["session_id"] !== undefined;
|
|
725
|
+
const hasRun = input["run_id"] !== undefined;
|
|
726
|
+
if (hasSession === hasRun) {
|
|
727
|
+
throw new Error(`${label} must name exactly one of session_id or run_id`);
|
|
728
|
+
}
|
|
729
|
+
return Object.freeze(hasSession ? { sessionId: resourceID(input["session_id"], `${label}.session_id`) } : { runId: resourceID(input["run_id"], `${label}.run_id`) });
|
|
730
|
+
}
|
|
731
|
+
function parseWorkspaceSecret(value) {
|
|
732
|
+
const wire = workspaceObject(value, "Workspace Secret");
|
|
733
|
+
exactBindingKeys(wire, wire["env"] !== undefined ? ["secret", "env"] : ["secret", "file"]);
|
|
734
|
+
let binding;
|
|
735
|
+
if (wire["env"] !== undefined) {
|
|
736
|
+
const env = workspaceObject(wire["env"], "Workspace Secret env");
|
|
737
|
+
exactBindingKeys(env, ["name", "mode", "allowed_origins"]);
|
|
738
|
+
binding = { secret: wire["secret"], env: { name: env["name"], mode: env["mode"], ...env["allowed_origins"] === undefined ? {} : { allowedOrigins: env["allowed_origins"] } } };
|
|
739
|
+
} else {
|
|
740
|
+
binding = { secret: wire["secret"], file: wire["file"] };
|
|
741
|
+
}
|
|
742
|
+
const normalized = encodeWorkspaceSecrets([binding])[0];
|
|
743
|
+
return normalized.env !== undefined ? Object.freeze({ secret: normalized.secret, env: Object.freeze({ name: normalized.env.name, mode: normalized.env.mode, ...normalized.env.allowed_origins === undefined ? {} : { allowedOrigins: normalized.env.allowed_origins } }) }) : Object.freeze({ secret: normalized.secret, file: normalized.file });
|
|
744
|
+
}
|
|
745
|
+
function parseWorkspaceExecResult(value) {
|
|
746
|
+
const response = workspaceObject(value, "Workspace exec response");
|
|
747
|
+
const exitCode = response["exit_code"];
|
|
748
|
+
if (!Number.isSafeInteger(exitCode)) {
|
|
749
|
+
throw new Error("Workspace exec response.exit_code must be an integer");
|
|
750
|
+
}
|
|
751
|
+
return Object.freeze({
|
|
752
|
+
exitCode,
|
|
753
|
+
stdout: decodeWorkspaceBase64(response["stdout_base64"], "Workspace exec response.stdout_base64"),
|
|
754
|
+
stderr: decodeWorkspaceBase64(response["stderr_base64"], "Workspace exec response.stderr_base64")
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
function parseWorkspaceDeleteReceipt(value) {
|
|
758
|
+
const response = workspaceObject(value, "Workspace delete response");
|
|
759
|
+
return Object.freeze({
|
|
760
|
+
workspaceId: resourceID(response["workspace_id"], "Workspace delete response.workspace_id")
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
function workspaceObject(value, label) {
|
|
764
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
765
|
+
throw new Error(`${label} must be an object`);
|
|
766
|
+
}
|
|
767
|
+
return value;
|
|
768
|
+
}
|
|
769
|
+
function workspaceTimestamp(value, field) {
|
|
770
|
+
return timestampString(value, `Workspace response.${field}`);
|
|
771
|
+
}
|
|
772
|
+
function decodeWorkspaceBase64(value, label) {
|
|
773
|
+
if (typeof value !== "string") {
|
|
774
|
+
throw new Error(`${label} must be canonical padded base64`);
|
|
775
|
+
}
|
|
776
|
+
let binary;
|
|
777
|
+
try {
|
|
778
|
+
binary = atob(value);
|
|
779
|
+
} catch {
|
|
780
|
+
throw new Error(`${label} must be canonical padded base64`);
|
|
781
|
+
}
|
|
782
|
+
if (btoa(binary) !== value) {
|
|
783
|
+
throw new Error(`${label} must be canonical padded base64`);
|
|
784
|
+
}
|
|
785
|
+
const output = new Uint8Array(binary.length);
|
|
786
|
+
for (let index = 0;index < binary.length; index++) {
|
|
787
|
+
output[index] = binary.charCodeAt(index);
|
|
788
|
+
}
|
|
789
|
+
return output;
|
|
790
|
+
}
|
|
791
|
+
// sdk/typescript/src/internal/jsoncanon.ts
|
|
792
|
+
var textEncoder = new TextEncoder;
|
|
793
|
+
function canonicalizeJsonValue(value) {
|
|
794
|
+
return textEncoder.encode(serialize(value, new Set));
|
|
795
|
+
}
|
|
796
|
+
function serialize(value, ancestors) {
|
|
797
|
+
if (value === null || typeof value === "boolean") {
|
|
798
|
+
return String(value);
|
|
799
|
+
}
|
|
800
|
+
if (typeof value === "number") {
|
|
801
|
+
if (!Number.isFinite(value)) {
|
|
802
|
+
throw new Error("canonical JSON numbers must be finite IEEE 754 doubles");
|
|
803
|
+
}
|
|
804
|
+
return JSON.stringify(value);
|
|
805
|
+
}
|
|
806
|
+
if (typeof value === "string") {
|
|
807
|
+
assertUnicodeString(value);
|
|
808
|
+
return JSON.stringify(value);
|
|
809
|
+
}
|
|
810
|
+
if (typeof value !== "object") {
|
|
811
|
+
throw new Error(`canonical JSON does not support ${typeof value}`);
|
|
812
|
+
}
|
|
813
|
+
if (ancestors.has(value)) {
|
|
814
|
+
throw new Error("canonical JSON does not support cyclic values");
|
|
815
|
+
}
|
|
816
|
+
ancestors.add(value);
|
|
817
|
+
try {
|
|
818
|
+
if (Array.isArray(value)) {
|
|
819
|
+
assertPlainArray(value);
|
|
820
|
+
const items = value.map((item) => serialize(item, ancestors));
|
|
821
|
+
return `[${items.join(",")}]`;
|
|
822
|
+
}
|
|
823
|
+
const objectValue = value;
|
|
824
|
+
assertPlainObject(objectValue);
|
|
825
|
+
const entries = Object.keys(objectValue).sort().map((key) => {
|
|
826
|
+
assertUnicodeString(key);
|
|
827
|
+
return `${JSON.stringify(key)}:${serialize(objectValue[key], ancestors)}`;
|
|
828
|
+
});
|
|
829
|
+
return `{${entries.join(",")}}`;
|
|
830
|
+
} finally {
|
|
831
|
+
ancestors.delete(value);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
function assertPlainArray(value) {
|
|
835
|
+
const keys = Reflect.ownKeys(value);
|
|
836
|
+
const expected = Array.from({ length: value.length }, (_, index) => String(index));
|
|
837
|
+
expected.push("length");
|
|
838
|
+
if (keys.length !== expected.length || keys.some((key, index) => key !== expected[index])) {
|
|
839
|
+
throw new Error("canonical JSON arrays must be dense and have no extra properties");
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
function assertPlainObject(value) {
|
|
843
|
+
const prototype = Object.getPrototypeOf(value);
|
|
844
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
845
|
+
throw new Error("canonical JSON objects must have a plain or null prototype");
|
|
846
|
+
}
|
|
847
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
848
|
+
if (typeof key !== "string") {
|
|
849
|
+
throw new Error("canonical JSON objects cannot have symbol properties");
|
|
850
|
+
}
|
|
851
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
852
|
+
if (!descriptor?.enumerable || !("value" in descriptor)) {
|
|
853
|
+
throw new Error("canonical JSON object properties must be enumerable data properties");
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
// sdk/typescript/src/internal/session.ts
|
|
858
|
+
function parseSession(value) {
|
|
859
|
+
const input = objectValue(value, "Session response");
|
|
860
|
+
const status = sessionStatus(input["status"]);
|
|
861
|
+
const failure = input["failure"] === undefined ? undefined : parseSessionFailure(input["failure"]);
|
|
862
|
+
const terminalFailure = status === "cancelled" || status === "failed";
|
|
863
|
+
if (terminalFailure !== (failure !== undefined)) {
|
|
864
|
+
throw new Error("Session response has an inconsistent failure projection");
|
|
865
|
+
}
|
|
866
|
+
if (failure !== undefined && status === "cancelled" !== (failure.code === "cancelled")) {
|
|
867
|
+
throw new Error("Session response failure code is inconsistent with status");
|
|
868
|
+
}
|
|
869
|
+
const actorId = requiredString(input, "actor_id", "Session response");
|
|
870
|
+
validateTaskId(actorId);
|
|
871
|
+
return Object.freeze({
|
|
872
|
+
id: resourceID(input["id"], "Session response.id"),
|
|
873
|
+
actorId,
|
|
874
|
+
deploymentId: resourceID(input["deployment_id"], "Session response.deployment_id"),
|
|
875
|
+
workspaceId: resourceID(input["workspace_id"], "Session response.workspace_id"),
|
|
876
|
+
...input["key"] === undefined ? {} : { key: requiredString(input, "key", "Session response") },
|
|
877
|
+
status,
|
|
878
|
+
createdAt: timestampString(input["created_at"], "Session response.created_at"),
|
|
879
|
+
updatedAt: timestampString(input["updated_at"], "Session response.updated_at"),
|
|
880
|
+
...input["current_run_id"] === undefined ? {} : { currentRunId: resourceID(input["current_run_id"], "Session response.current_run_id") },
|
|
881
|
+
...failure === undefined ? {} : { failure }
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
function parseSessionInputRecord(value) {
|
|
885
|
+
const input = objectValue(value, "Session input response");
|
|
886
|
+
if (!Object.hasOwn(input, "data")) {
|
|
887
|
+
throw new Error("Session input response.data is required");
|
|
888
|
+
}
|
|
889
|
+
const data = input["data"];
|
|
890
|
+
canonicalizeJsonValue(data);
|
|
891
|
+
const source2 = objectValue(input["source"], "Session input response.source");
|
|
892
|
+
const type = source2["type"];
|
|
893
|
+
if (type !== "external" && type !== "run") {
|
|
894
|
+
throw new Error("Session input response.source.type is invalid");
|
|
895
|
+
}
|
|
896
|
+
const parsedSource = type === "external" ? Object.freeze({ type }) : Object.freeze({
|
|
897
|
+
type,
|
|
898
|
+
runId: resourceID(source2["run_id"], "Session input response.source.run_id")
|
|
899
|
+
});
|
|
900
|
+
return Object.freeze({
|
|
901
|
+
id: resourceID(input["id"], "Session input response.id"),
|
|
902
|
+
sequence: safeSequence(input["sequence"], "Session input response.sequence"),
|
|
903
|
+
data,
|
|
904
|
+
source: parsedSource,
|
|
905
|
+
createdAt: timestampString(input["created_at"], "Session input response.created_at")
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
function parseSessionOutputRecord(value) {
|
|
909
|
+
const input = objectValue(value, "Session output record");
|
|
910
|
+
if (!Object.hasOwn(input, "data")) {
|
|
911
|
+
throw new Error("Session output record.data is required");
|
|
912
|
+
}
|
|
913
|
+
const provenance = objectValue(input["provenance"], "Session output provenance");
|
|
914
|
+
return Object.freeze({
|
|
915
|
+
id: resourceID(input["id"], "Session output record.id"),
|
|
916
|
+
sequence: safeSequence(input["sequence"], "Session output record.sequence"),
|
|
917
|
+
data: input["data"],
|
|
918
|
+
contentType: requiredString(input, "content_type", "Session output record"),
|
|
919
|
+
createdAt: timestampString(input["created_at"], "Session output record.created_at"),
|
|
920
|
+
provenance: Object.freeze({
|
|
921
|
+
runId: resourceID(provenance["run_id"], "Session output provenance.run_id"),
|
|
922
|
+
attemptNumber: safeSequence(provenance["attempt_number"], "Session output provenance.attempt_number"),
|
|
923
|
+
deploymentId: resourceID(provenance["deployment_id"], "Session output provenance.deployment_id")
|
|
924
|
+
})
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
function parseSessionFailure(value) {
|
|
928
|
+
const input = objectValue(value, "Session failure");
|
|
929
|
+
const code = requiredString(input, "code", "Session failure");
|
|
930
|
+
const details = objectValue(input["details"], "Session failure.details");
|
|
931
|
+
const runId = details["run_id"] === undefined ? undefined : resourceID(details["run_id"], "Session failure.details.run_id");
|
|
932
|
+
return Object.freeze({
|
|
933
|
+
code,
|
|
934
|
+
message: requiredString(input, "message", "Session failure"),
|
|
935
|
+
details: Object.freeze(runId === undefined ? {} : { runId })
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
function sessionStatus(value, label = "Session response.status") {
|
|
939
|
+
if (value !== "open" && value !== "closed" && value !== "cancelled" && value !== "failed") {
|
|
940
|
+
throw new Error(`${label} is invalid`);
|
|
941
|
+
}
|
|
942
|
+
return value;
|
|
943
|
+
}
|
|
944
|
+
function requiredString(value, field, label) {
|
|
945
|
+
const result = value[field];
|
|
946
|
+
if (typeof result !== "string" || result.length === 0) {
|
|
947
|
+
throw new Error(`${label}.${field} must be a non-empty string`);
|
|
948
|
+
}
|
|
949
|
+
return result;
|
|
950
|
+
}
|
|
951
|
+
function objectValue(value, label) {
|
|
952
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
953
|
+
throw new Error(`${label} must be an object`);
|
|
954
|
+
}
|
|
955
|
+
return value;
|
|
956
|
+
}
|
|
957
|
+
function safeSequence(value, label) {
|
|
958
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
959
|
+
throw new Error(`${label} must be a non-negative safe integer`);
|
|
960
|
+
}
|
|
961
|
+
return value;
|
|
962
|
+
}
|
|
963
|
+
// sdk/typescript/src/internal/strings.ts
|
|
964
|
+
var goSpaceEdges = /^[\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+|[\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+$/gu;
|
|
965
|
+
function trimGoSpace(value) {
|
|
966
|
+
return value.replace(goSpaceEdges, "");
|
|
967
|
+
}
|
|
968
|
+
export {
|
|
969
|
+
workspaceRefID,
|
|
970
|
+
validateQueueName,
|
|
971
|
+
trimGoSpace,
|
|
972
|
+
timestampString,
|
|
973
|
+
runHandleID,
|
|
974
|
+
resourceID,
|
|
975
|
+
parseWorkspaceExecResult,
|
|
976
|
+
parseWorkspaceDeleteReceipt,
|
|
977
|
+
parseWorkspace,
|
|
978
|
+
parseSessionOutputRecord,
|
|
979
|
+
parseSessionInputRecord,
|
|
980
|
+
parseSession,
|
|
981
|
+
matchesIgnorePattern,
|
|
982
|
+
isQueue,
|
|
983
|
+
installRuntimeOperations,
|
|
984
|
+
inspectWorkspaceAddress,
|
|
985
|
+
inspectSandboxDefinition,
|
|
986
|
+
inspectImage,
|
|
987
|
+
inspectDefinition,
|
|
988
|
+
inspectConfig,
|
|
989
|
+
encodeWorkspaceSecrets,
|
|
990
|
+
createWorkspaceRef,
|
|
991
|
+
createRunHandle,
|
|
992
|
+
canonicalizeJsonValue,
|
|
993
|
+
brandWorkspaceAddress
|
|
994
|
+
};
|