@hlix/sdk 0.2.0 → 0.3.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/api-client/src/client.d.ts +43 -0
- package/dist/api-client/src/generated/schema.d.ts +26163 -0
- package/dist/api-client/src/index.d.ts +13 -0
- package/dist/auth.d.ts +41 -0
- package/dist/errors.d.ts +78 -0
- package/dist/http.d.ts +45 -0
- package/dist/index.d.ts +268 -9395
- package/dist/index.js +449 -277
- package/dist/observe.d.ts +58 -0
- package/dist/retry.d.ts +47 -0
- package/dist/revision-watch.d.ts +29 -0
- package/dist/streaming.d.ts +33 -0
- package/dist/test-schema-guard.d.ts +27 -0
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -7,7 +7,6 @@ function createHlixClient(options) {
|
|
|
7
7
|
fetch: options.fetch
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
|
-
|
|
11
10
|
// src/auth.ts
|
|
12
11
|
var apiKeyCredential = (apiKey) => ({
|
|
13
12
|
kind: "apiKey",
|
|
@@ -17,8 +16,19 @@ var sessionCredential = (cookie) => ({
|
|
|
17
16
|
kind: "session",
|
|
18
17
|
cookie
|
|
19
18
|
});
|
|
19
|
+
var bearerCredential = (token) => ({
|
|
20
|
+
kind: "bearer",
|
|
21
|
+
token
|
|
22
|
+
});
|
|
20
23
|
function credentialHeaders(credential) {
|
|
21
|
-
|
|
24
|
+
switch (credential.kind) {
|
|
25
|
+
case "apiKey":
|
|
26
|
+
return { "x-api-key": credential.apiKey };
|
|
27
|
+
case "session":
|
|
28
|
+
return { cookie: credential.cookie };
|
|
29
|
+
case "bearer":
|
|
30
|
+
return { authorization: `Bearer ${credential.token}` };
|
|
31
|
+
}
|
|
22
32
|
}
|
|
23
33
|
function organizationHeaders(organizationId) {
|
|
24
34
|
return organizationId ? { "X-Organization-Id": organizationId } : {};
|
|
@@ -32,11 +42,13 @@ function authHeaders(credential, organizationId) {
|
|
|
32
42
|
|
|
33
43
|
// src/errors.ts
|
|
34
44
|
function errorMessageOf(body) {
|
|
35
|
-
if (typeof body !== "object" || body === null)
|
|
45
|
+
if (typeof body !== "object" || body === null)
|
|
46
|
+
return null;
|
|
36
47
|
const { error } = body;
|
|
37
48
|
return typeof error === "string" ? error : null;
|
|
38
49
|
}
|
|
39
|
-
|
|
50
|
+
|
|
51
|
+
class HlixError extends Error {
|
|
40
52
|
status;
|
|
41
53
|
body;
|
|
42
54
|
requestId;
|
|
@@ -51,37 +63,46 @@ var HlixError = class extends Error {
|
|
|
51
63
|
this.method = init.method;
|
|
52
64
|
this.url = init.url;
|
|
53
65
|
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
class HlixValidationError extends HlixError {
|
|
57
69
|
issues;
|
|
58
70
|
constructor(message, init, issues) {
|
|
59
71
|
super(message, init);
|
|
60
72
|
this.issues = issues;
|
|
61
73
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
class HlixBadRequestError extends HlixError {
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
class HlixAuthenticationError extends HlixError {
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
class HlixPermissionError extends HlixError {
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
class HlixNotFoundError extends HlixError {
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
class HlixConflictError extends HlixError {
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
class HlixRateLimitError extends HlixError {
|
|
74
92
|
retryAfter;
|
|
75
93
|
constructor(message, init, retryAfter) {
|
|
76
94
|
super(message, init);
|
|
77
95
|
this.retryAfter = retryAfter;
|
|
78
96
|
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
class HlixNotImplementedError extends HlixError {
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
class HlixServerError extends HlixError {
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
class HlixTransportError extends Error {
|
|
85
106
|
method;
|
|
86
107
|
url;
|
|
87
108
|
constructor(message, init) {
|
|
@@ -90,13 +111,16 @@ var HlixTransportError = class extends Error {
|
|
|
90
111
|
this.method = init.method;
|
|
91
112
|
this.url = init.url;
|
|
92
113
|
}
|
|
93
|
-
}
|
|
114
|
+
}
|
|
94
115
|
function validationIssues(body) {
|
|
95
|
-
if (typeof body !== "object" || body === null)
|
|
116
|
+
if (typeof body !== "object" || body === null)
|
|
117
|
+
return null;
|
|
96
118
|
const candidate = body;
|
|
97
|
-
if (candidate.success !== false)
|
|
119
|
+
if (candidate.success !== false)
|
|
120
|
+
return null;
|
|
98
121
|
const raw = candidate.error?.message;
|
|
99
|
-
if (typeof raw !== "string")
|
|
122
|
+
if (typeof raw !== "string")
|
|
123
|
+
return null;
|
|
100
124
|
try {
|
|
101
125
|
const parsed = JSON.parse(raw);
|
|
102
126
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -106,7 +130,8 @@ function validationIssues(body) {
|
|
|
106
130
|
}
|
|
107
131
|
function retryAfterSeconds(headers) {
|
|
108
132
|
const raw = headers.get("retry-after");
|
|
109
|
-
if (!raw)
|
|
133
|
+
if (!raw)
|
|
134
|
+
return null;
|
|
110
135
|
const seconds = Number(raw);
|
|
111
136
|
return Number.isFinite(seconds) && seconds >= 0 ? seconds : null;
|
|
112
137
|
}
|
|
@@ -122,11 +147,7 @@ function errorForResponse(response, body, request) {
|
|
|
122
147
|
const fallback = `${request.method} ${request.url} failed with ${response.status}`;
|
|
123
148
|
const issues = validationIssues(body);
|
|
124
149
|
if (issues) {
|
|
125
|
-
return new HlixValidationError(
|
|
126
|
-
`${request.method} ${request.url}: request body failed validation`,
|
|
127
|
-
init,
|
|
128
|
-
issues
|
|
129
|
-
);
|
|
150
|
+
return new HlixValidationError(`${request.method} ${request.url}: request body failed validation`, init, issues);
|
|
130
151
|
}
|
|
131
152
|
const message = stated ?? fallback;
|
|
132
153
|
switch (response.status) {
|
|
@@ -150,7 +171,7 @@ function errorForResponse(response, body, request) {
|
|
|
150
171
|
}
|
|
151
172
|
|
|
152
173
|
// src/retry.ts
|
|
153
|
-
var IDEMPOTENT_METHODS =
|
|
174
|
+
var IDEMPOTENT_METHODS = new Set([
|
|
154
175
|
"GET",
|
|
155
176
|
"HEAD",
|
|
156
177
|
"PUT",
|
|
@@ -161,7 +182,7 @@ var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
|
|
|
161
182
|
function isIdempotent(method) {
|
|
162
183
|
return IDEMPOTENT_METHODS.has(method.toUpperCase());
|
|
163
184
|
}
|
|
164
|
-
var RETRYABLE_STATUSES =
|
|
185
|
+
var RETRYABLE_STATUSES = new Set([
|
|
165
186
|
429,
|
|
166
187
|
500,
|
|
167
188
|
502,
|
|
@@ -174,18 +195,20 @@ function isRetryableStatus(status) {
|
|
|
174
195
|
var DEFAULT_RETRY = {
|
|
175
196
|
attempts: 3,
|
|
176
197
|
baseDelayMs: 200,
|
|
177
|
-
maxDelayMs:
|
|
198
|
+
maxDelayMs: 5000
|
|
178
199
|
};
|
|
179
|
-
function backoffDelayMs(attempt, policy,
|
|
180
|
-
if (
|
|
181
|
-
return Math.min(
|
|
200
|
+
function backoffDelayMs(attempt, policy, retryAfterSeconds, random = Math.random) {
|
|
201
|
+
if (retryAfterSeconds !== null) {
|
|
202
|
+
return Math.min(retryAfterSeconds * 1000, policy.maxDelayMs);
|
|
182
203
|
}
|
|
183
204
|
const ceiling = Math.min(policy.baseDelayMs * 2 ** attempt, policy.maxDelayMs);
|
|
184
205
|
return Math.round(random() * ceiling);
|
|
185
206
|
}
|
|
186
207
|
function shouldRetry(input) {
|
|
187
|
-
if (!isIdempotent(input.method))
|
|
188
|
-
|
|
208
|
+
if (!isIdempotent(input.method))
|
|
209
|
+
return false;
|
|
210
|
+
if (input.attempt + 1 >= input.policy.attempts)
|
|
211
|
+
return false;
|
|
189
212
|
return input.status === null || isRetryableStatus(input.status);
|
|
190
213
|
}
|
|
191
214
|
|
|
@@ -193,7 +216,8 @@ function shouldRetry(input) {
|
|
|
193
216
|
var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
194
217
|
function retryAfterSeconds2(response) {
|
|
195
218
|
const raw = response.headers.get("retry-after");
|
|
196
|
-
if (!raw)
|
|
219
|
+
if (!raw)
|
|
220
|
+
return null;
|
|
197
221
|
const seconds = Number(raw);
|
|
198
222
|
return Number.isFinite(seconds) && seconds >= 0 ? seconds : null;
|
|
199
223
|
}
|
|
@@ -204,17 +228,14 @@ function retryingFetch(options) {
|
|
|
204
228
|
return async (input) => {
|
|
205
229
|
const method = input.method.toUpperCase();
|
|
206
230
|
const replayable = isIdempotent(method) ? input.clone() : null;
|
|
207
|
-
for (let attempt = 0
|
|
231
|
+
for (let attempt = 0;; attempt += 1) {
|
|
208
232
|
const request = attempt === 0 ? input : replayable.clone();
|
|
209
233
|
let response;
|
|
210
234
|
try {
|
|
211
235
|
response = await base(request);
|
|
212
236
|
} catch (cause) {
|
|
213
237
|
if (!replayable || !shouldRetry({ method, attempt, policy, status: null })) {
|
|
214
|
-
throw new HlixTransportError(
|
|
215
|
-
`${method} ${input.url}: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
216
|
-
{ method, url: input.url, cause }
|
|
217
|
-
);
|
|
238
|
+
throw new HlixTransportError(`${method} ${input.url}: ${cause instanceof Error ? cause.message : String(cause)}`, { method, url: input.url, cause });
|
|
218
239
|
}
|
|
219
240
|
await sleep(backoffDelayMs(attempt, policy, null, random));
|
|
220
241
|
continue;
|
|
@@ -222,16 +243,53 @@ function retryingFetch(options) {
|
|
|
222
243
|
if (!shouldRetry({ method, attempt, policy, status: response.status })) {
|
|
223
244
|
return response;
|
|
224
245
|
}
|
|
225
|
-
if (!replayable)
|
|
246
|
+
if (!replayable)
|
|
247
|
+
return response;
|
|
226
248
|
await sleep(backoffDelayMs(attempt, policy, retryAfterSeconds2(response), random));
|
|
227
249
|
}
|
|
228
250
|
};
|
|
229
251
|
}
|
|
230
252
|
function unwrap(result, request) {
|
|
231
|
-
if (result.response.ok)
|
|
253
|
+
if (result.response.ok)
|
|
254
|
+
return result.data;
|
|
232
255
|
throw errorForResponse(result.response, result.error ?? result.data, request);
|
|
233
256
|
}
|
|
234
257
|
|
|
258
|
+
// src/observe.ts
|
|
259
|
+
var text = (value) => typeof value === "string" ? value : "";
|
|
260
|
+
function parseObserveFrame(data) {
|
|
261
|
+
let parsed;
|
|
262
|
+
try {
|
|
263
|
+
parsed = JSON.parse(data);
|
|
264
|
+
} catch {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
268
|
+
return null;
|
|
269
|
+
const frame = parsed;
|
|
270
|
+
switch (frame.type) {
|
|
271
|
+
case "idle":
|
|
272
|
+
return { type: "idle" };
|
|
273
|
+
case "done":
|
|
274
|
+
return { type: "done" };
|
|
275
|
+
case "active":
|
|
276
|
+
return typeof frame.runId === "string" ? { type: "active", runId: frame.runId } : { type: "active" };
|
|
277
|
+
case "on_chat_model_stream":
|
|
278
|
+
return { type: "on_chat_model_stream", delta: text(frame.delta) };
|
|
279
|
+
case "reasoning":
|
|
280
|
+
return { type: "reasoning", delta: text(frame.delta) };
|
|
281
|
+
case "on_tool_start":
|
|
282
|
+
return { type: "on_tool_start", name: text(frame.name), input: frame.input };
|
|
283
|
+
case "on_tool_end":
|
|
284
|
+
return { type: "on_tool_end", name: text(frame.name), output: frame.output };
|
|
285
|
+
case "error":
|
|
286
|
+
return { type: "error", message: text(frame.message) };
|
|
287
|
+
default:
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
var isTerminalObserveFrame = (frame) => frame.type === "done" || frame.type === "idle" || frame.type === "error";
|
|
292
|
+
|
|
235
293
|
// src/streaming.ts
|
|
236
294
|
var emptyFrame = () => ({ event: null, data: [], id: null, retry: null });
|
|
237
295
|
function applyField(frame, name, value) {
|
|
@@ -243,10 +301,12 @@ function applyField(frame, name, value) {
|
|
|
243
301
|
frame.data.push(value);
|
|
244
302
|
return;
|
|
245
303
|
case "id":
|
|
246
|
-
if (!value.includes("\
|
|
304
|
+
if (!value.includes("\x00"))
|
|
305
|
+
frame.id = value;
|
|
247
306
|
return;
|
|
248
307
|
case "retry": {
|
|
249
|
-
if (/^\d+$/.test(value))
|
|
308
|
+
if (/^\d+$/.test(value))
|
|
309
|
+
frame.retry = Number(value);
|
|
250
310
|
return;
|
|
251
311
|
}
|
|
252
312
|
default:
|
|
@@ -254,17 +314,21 @@ function applyField(frame, name, value) {
|
|
|
254
314
|
}
|
|
255
315
|
}
|
|
256
316
|
function dispatch(frame) {
|
|
257
|
-
const data = frame.data.join(
|
|
317
|
+
const data = frame.data.join(`
|
|
318
|
+
`);
|
|
258
319
|
const event = frame.event;
|
|
259
320
|
const id = frame.id;
|
|
260
321
|
frame.data = [];
|
|
261
322
|
frame.event = null;
|
|
262
|
-
if (data === "")
|
|
323
|
+
if (data === "")
|
|
324
|
+
return null;
|
|
263
325
|
return { event, data, id, retry: frame.retry };
|
|
264
326
|
}
|
|
265
327
|
function consumeLine(frame, line) {
|
|
266
|
-
if (line === "")
|
|
267
|
-
|
|
328
|
+
if (line === "")
|
|
329
|
+
return dispatch(frame);
|
|
330
|
+
if (line.startsWith(":"))
|
|
331
|
+
return null;
|
|
268
332
|
const colon = line.indexOf(":");
|
|
269
333
|
if (colon === -1) {
|
|
270
334
|
applyField(frame, line, "");
|
|
@@ -272,66 +336,117 @@ function consumeLine(frame, line) {
|
|
|
272
336
|
}
|
|
273
337
|
const name = line.slice(0, colon);
|
|
274
338
|
let value = line.slice(colon + 1);
|
|
275
|
-
if (value.startsWith(" "))
|
|
339
|
+
if (value.startsWith(" "))
|
|
340
|
+
value = value.slice(1);
|
|
276
341
|
applyField(frame, name, value);
|
|
277
342
|
return null;
|
|
278
343
|
}
|
|
279
344
|
function splitLines(buffer) {
|
|
280
345
|
const lines = [];
|
|
281
346
|
let start = 0;
|
|
282
|
-
for (let i = 0;
|
|
347
|
+
for (let i = 0;i < buffer.length; i += 1) {
|
|
283
348
|
const ch = buffer[i];
|
|
284
|
-
if (ch !==
|
|
349
|
+
if (ch !== `
|
|
350
|
+
` && ch !== "\r")
|
|
351
|
+
continue;
|
|
285
352
|
lines.push(buffer.slice(start, i));
|
|
286
|
-
if (ch === "\r" && buffer[i + 1] ===
|
|
353
|
+
if (ch === "\r" && buffer[i + 1] === `
|
|
354
|
+
`)
|
|
355
|
+
i += 1;
|
|
287
356
|
start = i + 1;
|
|
288
357
|
}
|
|
289
358
|
return { lines, rest: buffer.slice(start) };
|
|
290
359
|
}
|
|
291
360
|
async function* parseSseStream(body, signal) {
|
|
292
361
|
const reader = body.getReader();
|
|
293
|
-
const decoder = new TextDecoder
|
|
362
|
+
const decoder = new TextDecoder;
|
|
294
363
|
const frame = emptyFrame();
|
|
295
364
|
let buffer = "";
|
|
296
|
-
const abort = () => void reader.cancel().catch(() => {
|
|
297
|
-
});
|
|
365
|
+
const abort = () => void reader.cancel().catch(() => {});
|
|
298
366
|
signal?.addEventListener("abort", abort, { once: true });
|
|
299
367
|
try {
|
|
300
|
-
for (
|
|
368
|
+
for (;; ) {
|
|
301
369
|
const { done, value } = await reader.read();
|
|
302
|
-
if (done)
|
|
370
|
+
if (done)
|
|
371
|
+
break;
|
|
303
372
|
buffer += decoder.decode(value, { stream: true });
|
|
304
373
|
const { lines, rest } = splitLines(buffer);
|
|
305
374
|
buffer = rest;
|
|
306
375
|
for (const line of lines) {
|
|
307
376
|
const event = consumeLine(frame, line);
|
|
308
|
-
if (event)
|
|
377
|
+
if (event)
|
|
378
|
+
yield event;
|
|
309
379
|
}
|
|
310
|
-
if (signal?.aborted)
|
|
380
|
+
if (signal?.aborted)
|
|
381
|
+
return;
|
|
311
382
|
}
|
|
312
383
|
buffer += decoder.decode();
|
|
313
384
|
if (buffer !== "") {
|
|
314
385
|
const event = consumeLine(frame, buffer);
|
|
315
|
-
if (event)
|
|
386
|
+
if (event)
|
|
387
|
+
yield event;
|
|
316
388
|
}
|
|
317
389
|
const trailing = dispatch(frame);
|
|
318
|
-
if (trailing)
|
|
390
|
+
if (trailing)
|
|
391
|
+
yield trailing;
|
|
319
392
|
} finally {
|
|
320
393
|
signal?.removeEventListener("abort", abort);
|
|
321
394
|
reader.releaseLock();
|
|
322
395
|
}
|
|
323
396
|
}
|
|
324
397
|
|
|
398
|
+
// src/revision-watch.ts
|
|
399
|
+
function parseRevisionWatchFrame(data) {
|
|
400
|
+
let parsed;
|
|
401
|
+
try {
|
|
402
|
+
parsed = JSON.parse(data);
|
|
403
|
+
} catch {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
407
|
+
return null;
|
|
408
|
+
const frame = parsed;
|
|
409
|
+
if (frame.kind === "ready")
|
|
410
|
+
return { kind: "ready" };
|
|
411
|
+
if (frame.kind === "workspace")
|
|
412
|
+
return { kind: "workspace" };
|
|
413
|
+
if (frame.kind === "head" && typeof frame.revisionId === "string" && typeof frame.generation === "number") {
|
|
414
|
+
return { kind: "head", revisionId: frame.revisionId, generation: frame.generation };
|
|
415
|
+
}
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
function isPermanentWatchFailure(error) {
|
|
419
|
+
return error instanceof HlixError && error.status >= 400 && error.status < 500 && error.status !== 408 && error.status !== 429;
|
|
420
|
+
}
|
|
421
|
+
var WATCH_RECONNECT = { firstDelayMs: 1000, maxDelayMs: 30000 };
|
|
422
|
+
function pause(ms, signal) {
|
|
423
|
+
return new Promise((resolve) => {
|
|
424
|
+
if (signal?.aborted)
|
|
425
|
+
return resolve();
|
|
426
|
+
const timer = setTimeout(done, ms);
|
|
427
|
+
function done() {
|
|
428
|
+
clearTimeout(timer);
|
|
429
|
+
signal?.removeEventListener("abort", done);
|
|
430
|
+
resolve();
|
|
431
|
+
}
|
|
432
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
325
436
|
// src/index.ts
|
|
326
|
-
|
|
327
|
-
/** The un-opinionated transport, for anything this facade does not wrap. */
|
|
437
|
+
class Hlix {
|
|
328
438
|
raw;
|
|
329
439
|
baseUrl;
|
|
330
440
|
headers;
|
|
331
441
|
fetcher;
|
|
332
442
|
constructor(options) {
|
|
333
443
|
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
334
|
-
|
|
444
|
+
const auth = authHeaders(options.credential, options.organizationId);
|
|
445
|
+
const owned = new Set(Object.keys(auth).map((name) => name.toLowerCase()));
|
|
446
|
+
this.headers = {
|
|
447
|
+
...Object.fromEntries(Object.entries(options.headers ?? {}).filter(([name]) => !owned.has(name.toLowerCase()))),
|
|
448
|
+
...auth
|
|
449
|
+
};
|
|
335
450
|
const policy = { ...DEFAULT_RETRY, ...options.retry };
|
|
336
451
|
const base = options.fetch ?? ((input) => globalThis.fetch(input));
|
|
337
452
|
this.fetcher = retryingFetch({ base, policy });
|
|
@@ -344,53 +459,135 @@ var Hlix = class {
|
|
|
344
459
|
at(method, path) {
|
|
345
460
|
return { method, url: `${this.baseUrl}${path}` };
|
|
346
461
|
}
|
|
462
|
+
workspaces = {
|
|
463
|
+
list: async (options = {}) => unwrap(await this.raw.GET("/v1/api/workspaces", options), this.at("GET", "/v1/api/workspaces"))
|
|
464
|
+
};
|
|
347
465
|
projects = {
|
|
348
|
-
list: async () => unwrap(
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
),
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
466
|
+
list: async () => unwrap(await this.raw.GET("/v1/api/projects"), this.at("GET", "/v1/api/projects")),
|
|
467
|
+
get: async (id, options = {}) => unwrap(await this.raw.GET("/v1/api/projects/{id}", { ...options, params: { path: { id } } }), this.at("GET", `/v1/api/projects/${id}`)),
|
|
468
|
+
create: async (body) => unwrap(await this.raw.POST("/v1/api/projects", { body }), this.at("POST", "/v1/api/projects")),
|
|
469
|
+
delete: async (id) => unwrap(await this.raw.DELETE("/v1/api/projects/{id}", {
|
|
470
|
+
params: { path: { id } }
|
|
471
|
+
}), this.at("DELETE", `/v1/api/projects/${id}`)),
|
|
472
|
+
start: async (id, body) => unwrap(await this.raw.POST("/v1/api/projects/{id}/start", {
|
|
473
|
+
params: { path: { id } },
|
|
474
|
+
body
|
|
475
|
+
}), this.at("POST", `/v1/api/projects/${id}/start`)),
|
|
476
|
+
refreshPreview: async (id) => unwrap(await this.raw.POST("/v1/api/projects/{id}/preview/refresh", {
|
|
477
|
+
params: { path: { id } }
|
|
478
|
+
}), this.at("POST", `/v1/api/projects/${id}/preview/refresh`)),
|
|
479
|
+
stop: async (id) => unwrap(await this.raw.POST("/v1/api/projects/{id}/stop", { params: { path: { id } } }), this.at("POST", `/v1/api/projects/${id}/stop`)),
|
|
480
|
+
status: async (id, options = {}) => unwrap(await this.raw.GET("/v1/api/projects/{id}/status", { ...options, params: { path: { id } } }), this.at("GET", `/v1/api/projects/${id}/status`)),
|
|
481
|
+
preview: async (id) => unwrap(await this.raw.GET("/v1/api/projects/{id}/preview", { params: { path: { id } } }), this.at("GET", `/v1/api/projects/${id}/preview`)),
|
|
482
|
+
deliver: async (id) => unwrap(await this.raw.POST("/v1/api/projects/{id}/delivery", { params: { path: { id } } }), this.at("POST", `/v1/api/projects/${id}/delivery`)),
|
|
483
|
+
connectRepo: async (id, body) => {
|
|
484
|
+
const result = await this.raw.POST("/v1/api/projects/{id}/repos/connect", {
|
|
485
|
+
params: { path: { id } },
|
|
486
|
+
body
|
|
487
|
+
});
|
|
488
|
+
return unwrap(result, this.at("POST", `/v1/api/projects/${id}/repos/connect`));
|
|
489
|
+
},
|
|
490
|
+
terminal: async (id) => unwrap(await this.raw.GET("/v1/api/projects/{id}/terminal", { params: { path: { id } } }), this.at("GET", `/v1/api/projects/${id}/terminal`)),
|
|
491
|
+
observeAgent: (projectId, agentId, init) => this.observeAgent(projectId, agentId, init),
|
|
492
|
+
workspace: (id) => ({
|
|
493
|
+
environment: async () => unwrap(await this.raw.GET("/v1/api/projects/{id}/environment", {
|
|
362
494
|
params: { path: { id } }
|
|
363
|
-
}),
|
|
364
|
-
this.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
495
|
+
}), this.at("GET", `/v1/api/projects/${id}/environment`)),
|
|
496
|
+
fs: async (body) => unwrap(await this.raw.POST("/v1/api/projects/{id}/workspace/fs", {
|
|
497
|
+
params: { path: { id } },
|
|
498
|
+
body
|
|
499
|
+
}), this.at("POST", `/v1/api/projects/${id}/workspace/fs`)),
|
|
500
|
+
exec: async (body) => unwrap(await this.raw.POST("/v1/api/projects/{id}/workspace/exec", {
|
|
368
501
|
params: { path: { id } },
|
|
369
502
|
body
|
|
370
|
-
}),
|
|
371
|
-
|
|
372
|
-
|
|
503
|
+
}), this.at("POST", `/v1/api/projects/${id}/workspace/exec`))
|
|
504
|
+
})
|
|
505
|
+
};
|
|
506
|
+
secrets = {
|
|
507
|
+
listEntries: async (projectId) => unwrap(await this.raw.GET("/v1/api/secrets/project/{projectId}/entries", {
|
|
508
|
+
params: { path: { projectId } }
|
|
509
|
+
}), this.at("GET", `/v1/api/secrets/project/${projectId}/entries`)),
|
|
510
|
+
upsertEntries: async (projectId, body) => unwrap(await this.raw.PUT("/v1/api/secrets/project/{projectId}/entries", {
|
|
511
|
+
params: { path: { projectId } },
|
|
512
|
+
body
|
|
513
|
+
}), this.at("PUT", `/v1/api/secrets/project/${projectId}/entries`)),
|
|
514
|
+
importFiles: async (projectId, files) => unwrap(await this.raw.PUT("/v1/api/secrets/project/{projectId}/files", {
|
|
515
|
+
params: { path: { projectId } },
|
|
516
|
+
body: { files }
|
|
517
|
+
}), this.at("PUT", `/v1/api/secrets/project/${projectId}/files`)),
|
|
518
|
+
deleteEntry: async (projectId, key, source) => unwrap(await this.raw.DELETE("/v1/api/secrets/project/{projectId}/entries/{key}", {
|
|
519
|
+
params: {
|
|
520
|
+
path: { projectId, key },
|
|
521
|
+
...source === undefined ? {} : { query: { source } }
|
|
522
|
+
}
|
|
523
|
+
}), this.at("DELETE", `/v1/api/secrets/project/${projectId}/entries/${encodeURIComponent(key)}`)),
|
|
524
|
+
exportEntries: async (projectId, options = {}) => {
|
|
525
|
+
const path = `/v1/api/secrets/project/${projectId}/export`;
|
|
526
|
+
const url = `${this.baseUrl}${path}`;
|
|
527
|
+
const response = await this.fetcher(new Request(url, {
|
|
528
|
+
method: "POST",
|
|
529
|
+
headers: { ...this.headers, "content-type": "application/json" },
|
|
530
|
+
body: JSON.stringify({
|
|
531
|
+
...options.source === undefined ? {} : { source: options.source },
|
|
532
|
+
...options.format === undefined ? {} : { format: options.format }
|
|
533
|
+
})
|
|
534
|
+
}));
|
|
535
|
+
if (!response.ok) {
|
|
536
|
+
throw errorForResponse(response, await response.json().catch(() => {
|
|
537
|
+
return;
|
|
538
|
+
}), { method: "POST", url });
|
|
539
|
+
}
|
|
540
|
+
return response.text();
|
|
541
|
+
}
|
|
373
542
|
};
|
|
374
543
|
imports = {
|
|
375
544
|
create: async (body) => {
|
|
376
545
|
const result = await this.raw.POST("/v1/api/imports", { body });
|
|
377
546
|
return unwrap(result, this.at("POST", "/v1/api/imports"));
|
|
378
547
|
},
|
|
379
|
-
get: async (id) => unwrap(
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
),
|
|
385
|
-
finalize: async (id, body) => {
|
|
548
|
+
get: async (id, options = {}) => unwrap(await this.raw.GET("/v1/api/imports/{id}", {
|
|
549
|
+
signal: options.signal,
|
|
550
|
+
params: { path: { id } }
|
|
551
|
+
}), this.at("GET", `/v1/api/imports/${id}`)),
|
|
552
|
+
finalize: async (id, body, options = {}) => {
|
|
386
553
|
const result = await this.raw.POST("/v1/api/imports/{id}/finalize", {
|
|
554
|
+
signal: options.signal,
|
|
387
555
|
params: { path: { id } },
|
|
388
556
|
body
|
|
389
557
|
});
|
|
390
|
-
return unwrap(
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
);
|
|
558
|
+
return unwrap(result, this.at("POST", `/v1/api/imports/${id}/finalize`));
|
|
559
|
+
},
|
|
560
|
+
finalizeAndWait: async (id, body, options = {}) => {
|
|
561
|
+
const deadline = AbortSignal.timeout(options.timeoutMs ?? 600000);
|
|
562
|
+
const signal = options.signal ? AbortSignal.any([options.signal, deadline]) : deadline;
|
|
563
|
+
try {
|
|
564
|
+
return await this.imports.finalize(id, body, { signal });
|
|
565
|
+
} catch (error) {
|
|
566
|
+
signal.throwIfAborted();
|
|
567
|
+
if (!(error instanceof HlixServerError || error instanceof HlixTransportError || error instanceof HlixConflictError))
|
|
568
|
+
throw error;
|
|
569
|
+
}
|
|
570
|
+
return this.imports.waitUntilReady(id, { ...options, signal });
|
|
571
|
+
},
|
|
572
|
+
waitUntilReady: async (id, options = {}) => {
|
|
573
|
+
const deadline = AbortSignal.timeout(options.timeoutMs ?? 600000);
|
|
574
|
+
const signal = options.signal ? AbortSignal.any([options.signal, deadline]) : deadline;
|
|
575
|
+
while (true) {
|
|
576
|
+
signal.throwIfAborted();
|
|
577
|
+
try {
|
|
578
|
+
const result = await this.imports.get(id, { signal });
|
|
579
|
+
if (result.import.status === "ready")
|
|
580
|
+
return result;
|
|
581
|
+
if (result.import.status !== "finalizing") {
|
|
582
|
+
throw new Error(`Import ${id} is ${result.import.status}: ${result.import.error ?? "rerun hlix import to resume this session"}`);
|
|
583
|
+
}
|
|
584
|
+
} catch (error) {
|
|
585
|
+
signal.throwIfAborted();
|
|
586
|
+
if (!(error instanceof HlixServerError || error instanceof HlixTransportError))
|
|
587
|
+
throw error;
|
|
588
|
+
}
|
|
589
|
+
await pause(options.pollIntervalMs ?? 2000, signal);
|
|
590
|
+
}
|
|
394
591
|
},
|
|
395
592
|
uploadBundle: async (upload, bundle, options = {}) => {
|
|
396
593
|
const chunkSize = options.chunkSize ?? 8 * 1024 * 1024;
|
|
@@ -410,7 +607,8 @@ var Hlix = class {
|
|
|
410
607
|
signal: options.signal
|
|
411
608
|
});
|
|
412
609
|
const response = await this.fetcher(request);
|
|
413
|
-
if (!response.ok)
|
|
610
|
+
if (!response.ok)
|
|
611
|
+
await this.throwUploadError(response, url);
|
|
414
612
|
options.onProgress?.(bundle.size, bundle.size);
|
|
415
613
|
return;
|
|
416
614
|
}
|
|
@@ -441,18 +639,13 @@ var Hlix = class {
|
|
|
441
639
|
}
|
|
442
640
|
};
|
|
443
641
|
revisions = {
|
|
444
|
-
head: async (projectId) => unwrap(
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
await this.raw.GET("/v1/api/projects/{id}/protected-files", {
|
|
452
|
-
params: { path: { id: projectId } }
|
|
453
|
-
}),
|
|
454
|
-
this.at("GET", `/v1/api/projects/${projectId}/protected-files`)
|
|
455
|
-
),
|
|
642
|
+
head: async (projectId, options = {}) => unwrap(await this.raw.GET("/v1/api/projects/{id}/revisions/head", {
|
|
643
|
+
...options,
|
|
644
|
+
params: { path: { id: projectId } }
|
|
645
|
+
}), this.at("GET", `/v1/api/projects/${projectId}/revisions/head`)),
|
|
646
|
+
protectedFiles: async (projectId) => unwrap(await this.raw.GET("/v1/api/projects/{id}/protected-files", {
|
|
647
|
+
params: { path: { id: projectId } }
|
|
648
|
+
}), this.at("GET", `/v1/api/projects/${projectId}/protected-files`)),
|
|
456
649
|
createUpload: async (projectId, body) => {
|
|
457
650
|
const result = await this.raw.POST("/v1/api/projects/{id}/revisions/uploads", {
|
|
458
651
|
params: { path: { id: projectId } },
|
|
@@ -461,16 +654,11 @@ var Hlix = class {
|
|
|
461
654
|
return unwrap(result, this.at("POST", `/v1/api/projects/${projectId}/revisions/uploads`));
|
|
462
655
|
},
|
|
463
656
|
finalize: async (projectId, uploadId, body) => {
|
|
464
|
-
const result = await this.raw.POST(
|
|
465
|
-
|
|
466
|
-
{ params: { path: { id: projectId, uploadId } }, body }
|
|
467
|
-
);
|
|
468
|
-
return unwrap(
|
|
469
|
-
result,
|
|
470
|
-
this.at("POST", `/v1/api/projects/${projectId}/revisions/uploads/${uploadId}/finalize`)
|
|
471
|
-
);
|
|
657
|
+
const result = await this.raw.POST("/v1/api/projects/{id}/revisions/uploads/{uploadId}/finalize", { params: { path: { id: projectId, uploadId } }, body });
|
|
658
|
+
return unwrap(result, this.at("POST", `/v1/api/projects/${projectId}/revisions/uploads/${uploadId}/finalize`));
|
|
472
659
|
},
|
|
473
660
|
uploadBundle: async (upload, bundle, options = {}) => this.imports.uploadBundle(upload, bundle, options),
|
|
661
|
+
watch: (projectId, init) => this.watchRevisions(projectId, init),
|
|
474
662
|
downloadBundle: async (projectId, revisionId) => {
|
|
475
663
|
const path = `/v1/api/projects/${projectId}/revisions/${revisionId}/bundle`;
|
|
476
664
|
const request = new Request(`${this.baseUrl}${path}`, {
|
|
@@ -478,32 +666,24 @@ var Hlix = class {
|
|
|
478
666
|
headers: this.headers
|
|
479
667
|
});
|
|
480
668
|
const response = await this.fetcher(request);
|
|
481
|
-
if (!response.ok)
|
|
669
|
+
if (!response.ok)
|
|
670
|
+
await this.throwUploadError(response, `${this.baseUrl}${path}`);
|
|
482
671
|
return response.blob();
|
|
483
672
|
}
|
|
484
673
|
};
|
|
485
674
|
resources = {
|
|
486
|
-
importSkill: async (projectId, body) => unwrap(
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
this.at("POST", `/v1/api/projects/${projectId}/resources/agent`)
|
|
499
|
-
),
|
|
500
|
-
importMcp: async (projectId, body) => unwrap(
|
|
501
|
-
await this.raw.POST("/v1/api/projects/{id}/resources/mcp", {
|
|
502
|
-
params: { path: { id: projectId } },
|
|
503
|
-
body
|
|
504
|
-
}),
|
|
505
|
-
this.at("POST", `/v1/api/projects/${projectId}/resources/mcp`)
|
|
506
|
-
)
|
|
675
|
+
importSkill: async (projectId, body) => unwrap(await this.raw.POST("/v1/api/projects/{id}/resources/skill", {
|
|
676
|
+
params: { path: { id: projectId } },
|
|
677
|
+
body
|
|
678
|
+
}), this.at("POST", `/v1/api/projects/${projectId}/resources/skill`)),
|
|
679
|
+
importAgent: async (projectId, body) => unwrap(await this.raw.POST("/v1/api/projects/{id}/resources/agent", {
|
|
680
|
+
params: { path: { id: projectId } },
|
|
681
|
+
body
|
|
682
|
+
}), this.at("POST", `/v1/api/projects/${projectId}/resources/agent`)),
|
|
683
|
+
importMcp: async (projectId, body) => unwrap(await this.raw.POST("/v1/api/projects/{id}/resources/mcp", {
|
|
684
|
+
params: { path: { id: projectId } },
|
|
685
|
+
body
|
|
686
|
+
}), this.at("POST", `/v1/api/projects/${projectId}/resources/mcp`))
|
|
507
687
|
};
|
|
508
688
|
async throwUploadError(response, url) {
|
|
509
689
|
let body = null;
|
|
@@ -515,140 +695,127 @@ var Hlix = class {
|
|
|
515
695
|
throw errorForResponse(response, body, { method: "PUT", url });
|
|
516
696
|
}
|
|
517
697
|
tasks = {
|
|
518
|
-
list: async (query) => unwrap(
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
),
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
),
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
this.at("PATCH", `/v1/api/tasks/${id}`)
|
|
536
|
-
),
|
|
537
|
-
listComments: async (id) => unwrap(
|
|
538
|
-
await this.raw.GET("/v1/api/tasks/{id}/comments", {
|
|
539
|
-
params: { path: { id } }
|
|
540
|
-
}),
|
|
541
|
-
this.at("GET", `/v1/api/tasks/${id}/comments`)
|
|
542
|
-
),
|
|
543
|
-
addComment: async (id, body) => unwrap(
|
|
544
|
-
await this.raw.POST("/v1/api/tasks/{id}/comments", {
|
|
545
|
-
params: { path: { id } },
|
|
546
|
-
body
|
|
547
|
-
}),
|
|
548
|
-
this.at("POST", `/v1/api/tasks/${id}/comments`)
|
|
549
|
-
),
|
|
550
|
-
/** The verified review evidence — the same observation QA reviews. */
|
|
551
|
-
review: async (id) => unwrap(
|
|
552
|
-
await this.raw.GET("/v1/api/tasks/{id}/review", {
|
|
553
|
-
params: { path: { id } }
|
|
554
|
-
}),
|
|
555
|
-
this.at("GET", `/v1/api/tasks/${id}/review`)
|
|
556
|
-
),
|
|
557
|
-
/** Live status frames. A terminal status closes the stream server-side. */
|
|
698
|
+
list: async (query) => unwrap(await this.raw.GET("/v1/api/tasks", { params: { query: query ?? {} } }), this.at("GET", "/v1/api/tasks")),
|
|
699
|
+
get: async (id) => unwrap(await this.raw.GET("/v1/api/tasks/{id}", { params: { path: { id } } }), this.at("GET", `/v1/api/tasks/${id}`)),
|
|
700
|
+
create: async (body) => unwrap(await this.raw.POST("/v1/api/tasks", { body }), this.at("POST", "/v1/api/tasks")),
|
|
701
|
+
update: async (id, body) => unwrap(await this.raw.PATCH("/v1/api/tasks/{id}", {
|
|
702
|
+
params: { path: { id } },
|
|
703
|
+
body
|
|
704
|
+
}), this.at("PATCH", `/v1/api/tasks/${id}`)),
|
|
705
|
+
listComments: async (id) => unwrap(await this.raw.GET("/v1/api/tasks/{id}/comments", {
|
|
706
|
+
params: { path: { id } }
|
|
707
|
+
}), this.at("GET", `/v1/api/tasks/${id}/comments`)),
|
|
708
|
+
addComment: async (id, body) => unwrap(await this.raw.POST("/v1/api/tasks/{id}/comments", {
|
|
709
|
+
params: { path: { id } },
|
|
710
|
+
body
|
|
711
|
+
}), this.at("POST", `/v1/api/tasks/${id}/comments`)),
|
|
712
|
+
review: async (id) => unwrap(await this.raw.GET("/v1/api/tasks/{id}/review", {
|
|
713
|
+
params: { path: { id } }
|
|
714
|
+
}), this.at("GET", `/v1/api/tasks/${id}/review`)),
|
|
558
715
|
stream: (id, init) => this.stream(`/v1/api/tasks/${id}/stream`, init)
|
|
559
716
|
};
|
|
717
|
+
modelConfig = {
|
|
718
|
+
setProjectHarness: async (projectId, harness) => unwrap(await this.raw.PUT("/v1/api/model-config/harness/{projectId}", {
|
|
719
|
+
params: { path: { projectId } },
|
|
720
|
+
body: { harness }
|
|
721
|
+
}), this.at("PUT", `/v1/api/model-config/harness/${projectId}`)),
|
|
722
|
+
clearProjectHarness: async (projectId) => unwrap(await this.raw.DELETE("/v1/api/model-config/harness/{projectId}", {
|
|
723
|
+
params: { path: { projectId } }
|
|
724
|
+
}), this.at("DELETE", `/v1/api/model-config/harness/${projectId}`)),
|
|
725
|
+
setHarness: async (harness) => unwrap(await this.raw.PUT("/v1/api/model-config/harness", { body: { harness } }), this.at("PUT", "/v1/api/model-config/harness")),
|
|
726
|
+
clearHarness: async () => unwrap(await this.raw.DELETE("/v1/api/model-config/harness"), this.at("DELETE", "/v1/api/model-config/harness")),
|
|
727
|
+
resolvedHarness: async () => unwrap(await this.raw.GET("/v1/api/model-config/harness/resolved"), this.at("GET", "/v1/api/model-config/harness/resolved")),
|
|
728
|
+
resolvedProjectHarness: async (projectId) => unwrap(await this.raw.GET("/v1/api/model-config/harness/{projectId}/resolved", {
|
|
729
|
+
params: { path: { projectId } }
|
|
730
|
+
}), this.at("GET", `/v1/api/model-config/harness/${projectId}/resolved`))
|
|
731
|
+
};
|
|
732
|
+
ai = {
|
|
733
|
+
models: async (workspaceId, init) => unwrap(await this.raw.GET("/v1/api/ai/w/{workspaceId}/models", {
|
|
734
|
+
params: { path: { workspaceId } },
|
|
735
|
+
...init?.signal ? { signal: init.signal } : {}
|
|
736
|
+
}), this.at("GET", `/v1/api/ai/w/${workspaceId}/models`))
|
|
737
|
+
};
|
|
560
738
|
cycles = {
|
|
561
|
-
list: async (query) => unwrap(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
),
|
|
567
|
-
|
|
568
|
-
await this.raw.GET("/v1/api/cycles/{id}", {
|
|
569
|
-
params: { path: { id } }
|
|
570
|
-
}),
|
|
571
|
-
this.at("GET", `/v1/api/cycles/${id}`)
|
|
572
|
-
),
|
|
573
|
-
/** Creation is a PROPOSAL — the orchestrator owns the roadmap. */
|
|
574
|
-
propose: async (body) => unwrap(
|
|
575
|
-
await this.raw.POST("/v1/api/cycles", { body }),
|
|
576
|
-
this.at("POST", "/v1/api/cycles")
|
|
577
|
-
),
|
|
739
|
+
list: async (query) => unwrap(await this.raw.GET("/v1/api/cycles", {
|
|
740
|
+
params: { query: query ?? {} }
|
|
741
|
+
}), this.at("GET", "/v1/api/cycles")),
|
|
742
|
+
get: async (id) => unwrap(await this.raw.GET("/v1/api/cycles/{id}", {
|
|
743
|
+
params: { path: { id } }
|
|
744
|
+
}), this.at("GET", `/v1/api/cycles/${id}`)),
|
|
745
|
+
propose: async (body) => unwrap(await this.raw.POST("/v1/api/cycles", { body }), this.at("POST", "/v1/api/cycles")),
|
|
578
746
|
stream: (id, init) => this.stream(`/v1/api/cycles/${id}/stream`, init)
|
|
579
747
|
};
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
748
|
+
chat = {
|
|
749
|
+
send: async (body) => unwrap(await this.raw.POST("/v1/api/chat/turns", { body }), this.at("POST", "/v1/api/chat/turns")),
|
|
750
|
+
turn: async (turnId, scope) => unwrap(await this.raw.GET("/v1/api/chat/turns/{turnId}", {
|
|
751
|
+
params: { path: { turnId }, query: scope }
|
|
752
|
+
}), this.at("GET", `/v1/api/chat/turns/${turnId}`))
|
|
753
|
+
};
|
|
754
|
+
pendingRequests = {
|
|
755
|
+
list: async (query) => unwrap(await this.raw.GET("/v1/api/pending-requests", { params: { query: query ?? {} } }), this.at("GET", "/v1/api/pending-requests")),
|
|
756
|
+
resolve: async (id, body) => unwrap(await this.raw.POST("/v1/api/pending-requests/{id}/resolve", {
|
|
757
|
+
params: { path: { id } },
|
|
758
|
+
body
|
|
759
|
+
}), this.at("POST", `/v1/api/pending-requests/${id}/resolve`))
|
|
760
|
+
};
|
|
590
761
|
clientInvoices = {
|
|
591
|
-
list: async (query) => unwrap(
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
),
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
),
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
),
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
body: {}
|
|
612
|
-
}),
|
|
613
|
-
this.at("POST", `/v1/api/client-billing/invoices/${id}/issue`)
|
|
614
|
-
),
|
|
615
|
-
void: async (id, reason) => unwrap(
|
|
616
|
-
await this.raw.POST("/v1/api/client-billing/invoices/{id}/void", {
|
|
617
|
-
params: { path: { id } },
|
|
618
|
-
body: { reason }
|
|
619
|
-
}),
|
|
620
|
-
this.at("POST", `/v1/api/client-billing/invoices/${id}/void`)
|
|
621
|
-
),
|
|
622
|
-
pay: async (id) => unwrap(
|
|
623
|
-
await this.raw.POST("/v1/api/client-billing/invoices/{id}/pay", {
|
|
624
|
-
params: { path: { id } },
|
|
625
|
-
body: {}
|
|
626
|
-
}),
|
|
627
|
-
this.at("POST", `/v1/api/client-billing/invoices/${id}/pay`)
|
|
628
|
-
),
|
|
629
|
-
/**
|
|
630
|
-
* Open a PROVIDER-HOSTED checkout. Returns a URL and nothing else — no card
|
|
631
|
-
* field and no payment credential ever passes through hlix or this client.
|
|
632
|
-
* It does not mark the invoice paid: that happens only when the provider's
|
|
633
|
-
* signed webhook reconciles.
|
|
634
|
-
*/
|
|
635
|
-
paymentLink: async (id, body = {}) => unwrap(
|
|
636
|
-
await this.raw.POST(
|
|
637
|
-
"/v1/api/client-billing/invoices/{id}/payment-link",
|
|
638
|
-
{ params: { path: { id } }, body }
|
|
639
|
-
),
|
|
640
|
-
this.at("POST", `/v1/api/client-billing/invoices/${id}/payment-link`)
|
|
641
|
-
)
|
|
762
|
+
list: async (query) => unwrap(await this.raw.GET("/v1/api/client-billing/invoices", {
|
|
763
|
+
params: { query: query ?? {} }
|
|
764
|
+
}), this.at("GET", "/v1/api/client-billing/invoices")),
|
|
765
|
+
get: async (id) => unwrap(await this.raw.GET("/v1/api/client-billing/invoices/{id}", {
|
|
766
|
+
params: { path: { id } }
|
|
767
|
+
}), this.at("GET", `/v1/api/client-billing/invoices/${id}`)),
|
|
768
|
+
createDraft: async (body) => unwrap(await this.raw.POST("/v1/api/client-billing/invoices", { body }), this.at("POST", "/v1/api/client-billing/invoices")),
|
|
769
|
+
issue: async (id) => unwrap(await this.raw.POST("/v1/api/client-billing/invoices/{id}/issue", {
|
|
770
|
+
params: { path: { id } },
|
|
771
|
+
body: {}
|
|
772
|
+
}), this.at("POST", `/v1/api/client-billing/invoices/${id}/issue`)),
|
|
773
|
+
void: async (id, reason) => unwrap(await this.raw.POST("/v1/api/client-billing/invoices/{id}/void", {
|
|
774
|
+
params: { path: { id } },
|
|
775
|
+
body: { reason }
|
|
776
|
+
}), this.at("POST", `/v1/api/client-billing/invoices/${id}/void`)),
|
|
777
|
+
pay: async (id) => unwrap(await this.raw.POST("/v1/api/client-billing/invoices/{id}/pay", {
|
|
778
|
+
params: { path: { id } },
|
|
779
|
+
body: {}
|
|
780
|
+
}), this.at("POST", `/v1/api/client-billing/invoices/${id}/pay`)),
|
|
781
|
+
paymentLink: async (id, body = {}) => unwrap(await this.raw.POST("/v1/api/client-billing/invoices/{id}/payment-link", { params: { path: { id } }, body }), this.at("POST", `/v1/api/client-billing/invoices/${id}/payment-link`))
|
|
642
782
|
};
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
783
|
+
async* observeAgent(projectId, agentId, init) {
|
|
784
|
+
const path = `/v1/api/projects/${projectId}/agents/${agentId}/observe`;
|
|
785
|
+
for await (const event of this.stream(path, init)) {
|
|
786
|
+
const frame = parseObserveFrame(event.data);
|
|
787
|
+
if (!frame)
|
|
788
|
+
continue;
|
|
789
|
+
yield frame;
|
|
790
|
+
if (isTerminalObserveFrame(frame))
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
async* watchRevisions(projectId, init) {
|
|
795
|
+
const path = `/v1/api/projects/${projectId}/revisions/watch`;
|
|
796
|
+
const signal = init?.signal;
|
|
797
|
+
let delay = WATCH_RECONNECT.firstDelayMs;
|
|
798
|
+
while (!signal?.aborted) {
|
|
799
|
+
try {
|
|
800
|
+
for await (const event of this.stream(path, init)) {
|
|
801
|
+
const frame = parseRevisionWatchFrame(event.data);
|
|
802
|
+
if (!frame)
|
|
803
|
+
continue;
|
|
804
|
+
if (frame.kind === "ready")
|
|
805
|
+
delay = WATCH_RECONNECT.firstDelayMs;
|
|
806
|
+
yield frame;
|
|
807
|
+
}
|
|
808
|
+
} catch (error) {
|
|
809
|
+
if (signal?.aborted)
|
|
810
|
+
return;
|
|
811
|
+
if (isPermanentWatchFailure(error))
|
|
812
|
+
throw error;
|
|
813
|
+
}
|
|
814
|
+
await pause(delay, signal);
|
|
815
|
+
delay = Math.min(delay * 2, WATCH_RECONNECT.maxDelayMs);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
async* stream(path, init) {
|
|
652
819
|
const url = `${this.baseUrl}${path}`;
|
|
653
820
|
const request = new Request(url, {
|
|
654
821
|
headers: { ...this.headers, accept: "text/event-stream" },
|
|
@@ -666,7 +833,7 @@ var Hlix = class {
|
|
|
666
833
|
}
|
|
667
834
|
yield* parseSseStream(response.body, init?.signal);
|
|
668
835
|
}
|
|
669
|
-
}
|
|
836
|
+
}
|
|
670
837
|
function createHlix(options) {
|
|
671
838
|
return new Hlix(options);
|
|
672
839
|
}
|
|
@@ -686,8 +853,13 @@ export {
|
|
|
686
853
|
HlixValidationError,
|
|
687
854
|
IDEMPOTENT_METHODS,
|
|
688
855
|
apiKeyCredential,
|
|
856
|
+
bearerCredential,
|
|
689
857
|
createHlix,
|
|
690
858
|
isIdempotent,
|
|
859
|
+
isTerminalObserveFrame,
|
|
860
|
+
parseObserveFrame,
|
|
861
|
+
parseRevisionWatchFrame,
|
|
691
862
|
parseSseStream,
|
|
863
|
+
pause,
|
|
692
864
|
sessionCredential
|
|
693
865
|
};
|