@kubb/studio 5.3.15 → 5.3.17
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/README.md +92 -25
- package/dist/index.cjs +521 -347
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +116 -48
- package/dist/index.js +517 -349
- package/dist/index.js.map +1 -1
- package/dist/protocol.cjs +20 -0
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.ts +80 -50
- package/dist/protocol.js +19 -1
- package/dist/protocol.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
-
import { AgentApi, AgentPermissions,
|
|
2
|
+
import { AGENT_INSTANCE_HEADER, AgentApi, AgentCapacity, AgentCloseCode, AgentLoad, AgentPermissions, AgentRegisterInput, AgentRegisterResponse, ConfigEdit, ConnectMessagePayload, GenerateInput, GenerateResult, GenerationEvent, GenerationEventPayloads, GenerationEventType, GenerationRun, PublishSnapshotInput, PublishSnapshotResult, RpcClose, RpcConnection, RpcConnector, StudioApi, generationEventTypes } from "./protocol.js";
|
|
3
3
|
import { Config, Hookable, KubbHooks } from "@kubb/core";
|
|
4
4
|
import { Storage } from "unstorage";
|
|
5
5
|
//#region src/api.d.ts
|
|
@@ -11,10 +11,31 @@ import { Storage } from "unstorage";
|
|
|
11
11
|
export declare class InvalidAgentTokenError extends Error {
|
|
12
12
|
constructor(studioUrl: string, options?: ErrorOptions);
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when Studio refuses this agent's protocol version (426). Retrying cannot help until the
|
|
16
|
+
* agent is upgraded, so hosts stop instead of reconnecting.
|
|
17
|
+
*/
|
|
18
|
+
export declare class IncompatibleAgentError extends Error {
|
|
19
|
+
constructor(studioUrl: string, detail?: string, options?: ErrorOptions);
|
|
20
|
+
}
|
|
14
21
|
/**
|
|
15
22
|
* Status values returned by Studio's jobs API.
|
|
16
23
|
*/
|
|
17
24
|
type StudioJobStatus = 'queued' | 'running' | 'success' | 'failed' | 'canceled';
|
|
25
|
+
/** How a snapshot's files differ from an earlier snapshot of the same package, relative to `output.path`. */
|
|
26
|
+
type StudioSnapshotChanges = {
|
|
27
|
+
/** The snapshot these changes are measured against, `null` when there is none to compare with. */
|
|
28
|
+
base: {
|
|
29
|
+
id: string;
|
|
30
|
+
version: string | null;
|
|
31
|
+
/** The commit the base snapshot was built from, when reported. */
|
|
32
|
+
commit?: string;
|
|
33
|
+
createdAt: string;
|
|
34
|
+
} | null;
|
|
35
|
+
added: Array<string>;
|
|
36
|
+
changed: Array<string>;
|
|
37
|
+
removed: Array<string>;
|
|
38
|
+
};
|
|
18
39
|
/**
|
|
19
40
|
* Package view returned on a successful snapshot job from Studio.
|
|
20
41
|
*/
|
|
@@ -47,6 +68,10 @@ type StudioSnapshot = {
|
|
|
47
68
|
* ISO timestamp after which Studio may delete the tarball.
|
|
48
69
|
*/
|
|
49
70
|
expiresAt: string;
|
|
71
|
+
/** What changed since the previous snapshot on the same agent. Absent when Studio or the agent predates it. */
|
|
72
|
+
changes?: StudioSnapshotChanges;
|
|
73
|
+
/** What differs from the latest snapshot of the CI agent `baseId` names. Absent without a base. */
|
|
74
|
+
branchChanges?: StudioSnapshotChanges;
|
|
50
75
|
};
|
|
51
76
|
/**
|
|
52
77
|
* Job record from `POST /api/jobs` and `GET /api/jobs/{id}`.
|
|
@@ -75,6 +100,10 @@ type StudioJob = {
|
|
|
75
100
|
* Returns as soon as Studio accepts the job (`202`). Poll with {@link waitForJob} until it finishes.
|
|
76
101
|
* Authenticates with the organization CI API key via `x-api-key`.
|
|
77
102
|
*
|
|
103
|
+
* A busy agent, a full queue, or a momentary lack of a live connection (409, 429, 503) retries with
|
|
104
|
+
* exponential backoff and jitter, honoring Studio's `Retry-After` header when it sends one, up to
|
|
105
|
+
* `timeoutMs`. Every other failure, including a missing agent (404), throws immediately.
|
|
106
|
+
*
|
|
78
107
|
* @example Snapshot job
|
|
79
108
|
* ```ts
|
|
80
109
|
* const job = await createJob({
|
|
@@ -88,14 +117,25 @@ type StudioJob = {
|
|
|
88
117
|
* const finished = await waitForJob({ studioUrl, token, id: job.id })
|
|
89
118
|
* ```
|
|
90
119
|
*/
|
|
91
|
-
export declare function createJob({ studioUrl, token, type, agentId, name, version, config }: {
|
|
120
|
+
export declare function createJob({ studioUrl, token, type, agentId, name, version, commit, baseId, config, timeoutMs, signal }: {
|
|
92
121
|
studioUrl: string;
|
|
93
122
|
token: string;
|
|
94
123
|
type: 'generation' | 'snapshot';
|
|
95
124
|
agentId: string;
|
|
96
125
|
name?: string;
|
|
97
126
|
version?: string;
|
|
127
|
+
/** The commit this snapshot is built from, so the next one can diff against it. */
|
|
128
|
+
commit?: string;
|
|
129
|
+
/** The `id` another CI agent's runs register under, such as the base branch's; this snapshot is also compared with its latest one. */
|
|
130
|
+
baseId?: string;
|
|
98
131
|
config?: Record<string, unknown>;
|
|
132
|
+
/**
|
|
133
|
+
* How long to keep retrying a busy or queue-full response before giving up, in milliseconds.
|
|
134
|
+
*
|
|
135
|
+
* @default 60000
|
|
136
|
+
*/
|
|
137
|
+
timeoutMs?: number;
|
|
138
|
+
signal?: AbortSignal;
|
|
99
139
|
}): Promise<StudioJob>;
|
|
100
140
|
/**
|
|
101
141
|
* Polls `GET /api/jobs/{id}` until the job reaches a terminal status, waiting
|
|
@@ -105,7 +145,7 @@ export declare function createJob({ studioUrl, token, type, agentId, name, versi
|
|
|
105
145
|
* A `failed` job resolves normally. Check `job.status` and `job.error`. Throws only when the
|
|
106
146
|
* deadline passes before Studio finishes.
|
|
107
147
|
*/
|
|
108
|
-
export declare function waitForJob({ studioUrl, token, id, timeoutMs }: {
|
|
148
|
+
export declare function waitForJob({ studioUrl, token, id, timeoutMs, signal }: {
|
|
109
149
|
studioUrl: string;
|
|
110
150
|
token: string;
|
|
111
151
|
id: string;
|
|
@@ -115,6 +155,7 @@ export declare function waitForJob({ studioUrl, token, id, timeoutMs }: {
|
|
|
115
155
|
* @default 60000
|
|
116
156
|
*/
|
|
117
157
|
timeoutMs?: number;
|
|
158
|
+
signal?: AbortSignal;
|
|
118
159
|
}): Promise<StudioJob>;
|
|
119
160
|
/**
|
|
120
161
|
* CI agent returned by {@link createAgent}. The token is issued only once, at creation or reuse.
|
|
@@ -165,10 +206,6 @@ type StudioSessionOptions = {
|
|
|
165
206
|
* The runtime's own version, reported to Studio next to the `kubb` version.
|
|
166
207
|
*/
|
|
167
208
|
version: string;
|
|
168
|
-
/**
|
|
169
|
-
* Identifies the host to Studio, so the UI can badge a CLI connection and show the real project.
|
|
170
|
-
*/
|
|
171
|
-
client?: ClientInfo;
|
|
172
209
|
/**
|
|
173
210
|
* What Studio may do in this project, off unless the host grants it. A sandbox session narrows
|
|
174
211
|
* them further: it never writes to disk and never edits a config file, and it always generates
|
|
@@ -176,7 +213,14 @@ type StudioSessionOptions = {
|
|
|
176
213
|
*/
|
|
177
214
|
permissions?: Partial<AgentPermissions>;
|
|
178
215
|
root?: string;
|
|
216
|
+
/**
|
|
217
|
+
* Maximum reconnect backoff in milliseconds.
|
|
218
|
+
*/
|
|
179
219
|
retryInterval?: number;
|
|
220
|
+
/**
|
|
221
|
+
* Number of consecutive reconnect attempts that already failed.
|
|
222
|
+
*/
|
|
223
|
+
reconnectAttempt?: number;
|
|
180
224
|
/**
|
|
181
225
|
* Milliseconds between keep-alive pings, clamped to `agentDefaults.maxHeartbeatIntervalMs`.
|
|
182
226
|
* Raise it to halve the traffic and database writes a long-lived agent costs, at the price of
|
|
@@ -185,10 +229,16 @@ type StudioSessionOptions = {
|
|
|
185
229
|
*/
|
|
186
230
|
heartbeatInterval?: number;
|
|
187
231
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
232
|
+
* What this agent process can take on, reported to Studio at registration. Unset fields come from
|
|
233
|
+
* `KUBB_AGENT_MAX_CONCURRENT` and `KUBB_AGENT_MEMORY_BUDGET_MB`.
|
|
190
234
|
*/
|
|
191
|
-
|
|
235
|
+
capacity?: Partial<AgentCapacity>;
|
|
236
|
+
/**
|
|
237
|
+
* Names this agent process to Studio, sent at registration and as {@link AGENT_INSTANCE_HEADER}
|
|
238
|
+
* on the socket. `createClient` sets one per process, so a reconnect is the same instance and a
|
|
239
|
+
* restart is a new one. Not meant to be set directly by a host.
|
|
240
|
+
*/
|
|
241
|
+
instanceId?: string;
|
|
192
242
|
/**
|
|
193
243
|
* Aborting this disconnects the session and stops the reconnect loop. Hosts wire it to their own
|
|
194
244
|
* shutdown: Nitro's `close` hook, or `SIGINT`/`SIGTERM` in the CLI.
|
|
@@ -200,13 +250,6 @@ type StudioSessionOptions = {
|
|
|
200
250
|
* default to.
|
|
201
251
|
*/
|
|
202
252
|
installLogger?: (hooks: Hookable<KubbHooks>) => void | Promise<void>;
|
|
203
|
-
/**
|
|
204
|
-
* Threshold for the reconnect loop's own `console.error` lines, using the numeric constants
|
|
205
|
-
* `@kubb/core` exports as `logLevel`. Left out, those lines never print, the same silent default
|
|
206
|
-
* as an unset `installLogger` — a reconnect happens outside any one session's hooks, so it has no
|
|
207
|
-
* other way to ask a host how loud to be.
|
|
208
|
-
*/
|
|
209
|
-
logLevel?: number;
|
|
210
253
|
/**
|
|
211
254
|
* Called when this session's background reconnect is rejected with an invalid token. Unlike
|
|
212
255
|
* `ClientOptions.onAuthRequired`, this fires once per session rather than once per pool:
|
|
@@ -217,16 +260,11 @@ type StudioSessionOptions = {
|
|
|
217
260
|
};
|
|
218
261
|
//#endregion
|
|
219
262
|
//#region src/client.d.ts
|
|
220
|
-
type ClientOptions = Omit<StudioSessionOptions, 'signal' | 'onTokenRejected'> & {
|
|
221
|
-
/**
|
|
222
|
-
* Where the machine secret and the last Studio config are persisted. Defaults to in-memory,
|
|
223
|
-
* which gives up a stable machine identity across restarts.
|
|
224
|
-
*/
|
|
225
|
-
storage?: Storage;
|
|
263
|
+
type ClientOptions = Omit<StudioSessionOptions, 'signal' | 'onTokenRejected' | 'instanceId' | 'reconnectAttempt'> & {
|
|
226
264
|
/**
|
|
227
|
-
* Called once when
|
|
228
|
-
*
|
|
229
|
-
*
|
|
265
|
+
* Called once when the token is rejected during a background reconnect (401: revoked, or the
|
|
266
|
+
* agent was deleted). The client is already stopped by the time this fires, so a host only needs
|
|
267
|
+
* to get a replacement token and start a new client.
|
|
230
268
|
*
|
|
231
269
|
* Never fires for a startup rejection, which `connect()` reports by throwing, nor for an ordinary
|
|
232
270
|
* session expiry or revocation, both of which reconnect on their own.
|
|
@@ -235,12 +273,12 @@ type ClientOptions = Omit<StudioSessionOptions, 'signal' | 'onTokenRejected'> &
|
|
|
235
273
|
};
|
|
236
274
|
type Client = {
|
|
237
275
|
/**
|
|
238
|
-
* Registers with Studio and opens
|
|
239
|
-
*
|
|
276
|
+
* Registers with Studio and opens this process's one socket. Resolves once it is starting: the
|
|
277
|
+
* connection keeps running, and reconnects on its own, until `disconnect` is called.
|
|
240
278
|
*/
|
|
241
279
|
connect: () => Promise<void>;
|
|
242
280
|
/**
|
|
243
|
-
* Closes
|
|
281
|
+
* Closes the socket and stops reconnecting.
|
|
244
282
|
*/
|
|
245
283
|
disconnect: () => void;
|
|
246
284
|
};
|
|
@@ -248,7 +286,8 @@ type Client = {
|
|
|
248
286
|
* Creates the Kubb Studio client: the connection, the command loop, and the generation event
|
|
249
287
|
* stream shared by the `kubb studio` CLI command and the Docker agent.
|
|
250
288
|
*
|
|
251
|
-
* Every permission is off by default. A host that wants more grants it explicitly.
|
|
289
|
+
* Every permission is off by default. A host that wants more grants it explicitly. The machine
|
|
290
|
+
* identity comes from the storage the host installed with `setStorage`, before connecting.
|
|
252
291
|
*
|
|
253
292
|
* @example
|
|
254
293
|
* ```ts
|
|
@@ -256,7 +295,7 @@ type Client = {
|
|
|
256
295
|
* await studio.connect()
|
|
257
296
|
* ```
|
|
258
297
|
*/
|
|
259
|
-
export declare function createClient({
|
|
298
|
+
export declare function createClient({ onAuthRequired, ...options }: ClientOptions): Client;
|
|
260
299
|
//#endregion
|
|
261
300
|
//#region src/hooks.d.ts
|
|
262
301
|
/**
|
|
@@ -313,6 +352,10 @@ type StudioDisconnectedContext = {
|
|
|
313
352
|
*/
|
|
314
353
|
reason: string;
|
|
315
354
|
};
|
|
355
|
+
type StudioReconnectingContext = {
|
|
356
|
+
/** Milliseconds until the next connection attempt. */
|
|
357
|
+
delayMs: number;
|
|
358
|
+
};
|
|
316
359
|
type StudioCommandStartContext = {
|
|
317
360
|
/**
|
|
318
361
|
* The command Studio sent, without its `studio:` prefix: `generate`, `connect` or `save`.
|
|
@@ -331,9 +374,11 @@ type StudioCommandEndContext = {
|
|
|
331
374
|
};
|
|
332
375
|
type StudioWarnContext = {
|
|
333
376
|
/**
|
|
334
|
-
* What was refused or ignored
|
|
377
|
+
* What was refused or ignored.
|
|
335
378
|
*/
|
|
336
379
|
message: string;
|
|
380
|
+
/** The missing permission, if that is why, so the host can append its own remedy. */
|
|
381
|
+
permission?: keyof AgentPermissions;
|
|
337
382
|
};
|
|
338
383
|
type StudioErrorContext = {
|
|
339
384
|
/**
|
|
@@ -349,6 +394,7 @@ declare global {
|
|
|
349
394
|
'studio:connected': [ctx: StudioConnectedContext];
|
|
350
395
|
'studio:ready': [ctx: StudioReadyContext];
|
|
351
396
|
'studio:disconnected': [ctx: StudioDisconnectedContext];
|
|
397
|
+
'studio:reconnecting': [ctx: StudioReconnectingContext];
|
|
352
398
|
'studio:command:start': [ctx: StudioCommandStartContext];
|
|
353
399
|
'studio:command:end': [ctx: StudioCommandEndContext];
|
|
354
400
|
'studio:warn': [ctx: StudioWarnContext];
|
|
@@ -485,6 +531,11 @@ type PairingResult = {
|
|
|
485
531
|
organizationSlug?: string;
|
|
486
532
|
};
|
|
487
533
|
};
|
|
534
|
+
/**
|
|
535
|
+
* What this machine registers as. Any member may approve `cli` (`kubb studio`); only an admin may
|
|
536
|
+
* approve `user` and `sandbox` (the Docker image). A `ci` agent never pairs.
|
|
537
|
+
*/
|
|
538
|
+
type PairingAgentType = 'cli' | 'user' | 'sandbox';
|
|
488
539
|
/**
|
|
489
540
|
* Thrown when a caller aborts `startPairing` or `pollForPairingToken` through their `signal`, such
|
|
490
541
|
* as a `kubb studio` shutdown mid-pairing. Distinct from a denial or an expired code, so a host can
|
|
@@ -493,23 +544,22 @@ type PairingResult = {
|
|
|
493
544
|
export declare class PairingCanceledError extends Error {
|
|
494
545
|
constructor();
|
|
495
546
|
}
|
|
547
|
+
/** Thrown when the code expired unapproved. A fresh code can still succeed. */
|
|
548
|
+
export declare class PairingExpiredError extends Error {
|
|
549
|
+
constructor(message?: string);
|
|
550
|
+
}
|
|
551
|
+
/** Thrown when the pairing was denied in the browser, including by the organization's agent limit. */
|
|
552
|
+
export declare class PairingDeniedError extends Error {
|
|
553
|
+
constructor(message?: string);
|
|
554
|
+
}
|
|
496
555
|
type StartPairingOptions = {
|
|
497
556
|
studioUrl?: string;
|
|
557
|
+
type: PairingAgentType;
|
|
498
558
|
/**
|
|
499
559
|
* Display name for the agent, usually the project or machine name.
|
|
500
560
|
*/
|
|
501
561
|
name: string;
|
|
502
562
|
hostname: string;
|
|
503
|
-
/**
|
|
504
|
-
* Which client is pairing. Defaults to the CLI, where any signed-in member may approve their own
|
|
505
|
-
* machine. The Docker image passes `kubb-agent`, whose codes only an admin can approve.
|
|
506
|
-
*/
|
|
507
|
-
clientId?: string;
|
|
508
|
-
/**
|
|
509
|
-
* What a `kubb-agent` pairing asks to be registered as. Studio rejects the request without it,
|
|
510
|
-
* and ignores it for the CLI.
|
|
511
|
-
*/
|
|
512
|
-
agentKind?: 'user' | 'sandbox';
|
|
513
563
|
/**
|
|
514
564
|
* Aborting this cancels the request in flight and rejects with {@link PairingCanceledError}.
|
|
515
565
|
*/
|
|
@@ -520,7 +570,7 @@ type StartPairingOptions = {
|
|
|
520
570
|
* the code, so approval knows which machine it is pairing: the same machine pairing twice rotates
|
|
521
571
|
* one agent's token instead of creating a second agent.
|
|
522
572
|
*/
|
|
523
|
-
export declare function startPairing({ studioUrl, name, hostname,
|
|
573
|
+
export declare function startPairing({ studioUrl, type, name, hostname, signal }: StartPairingOptions): Promise<PairingSession>;
|
|
524
574
|
type PollOptions = {
|
|
525
575
|
studioUrl?: string;
|
|
526
576
|
session: PairingSession;
|
|
@@ -529,17 +579,35 @@ type PollOptions = {
|
|
|
529
579
|
* lands between polls or during the wait for the next one.
|
|
530
580
|
*/
|
|
531
581
|
signal?: AbortSignal;
|
|
582
|
+
/** Called when a poll could not reach Studio. Polling carries on. */
|
|
583
|
+
onRetry?: (error: Error) => void;
|
|
532
584
|
};
|
|
533
585
|
/**
|
|
534
|
-
* Polls until the user approves or denies, honoring the server's `slow_down` back-off.
|
|
535
|
-
* cannot reach Studio is warned about and retried, since the code stays valid either way.
|
|
586
|
+
* Polls until the user approves or denies, honoring the server's `slow_down` back-off.
|
|
536
587
|
*
|
|
537
588
|
* Studio's own endpoint is used rather than the auth layer's `/device/token`, because an approved
|
|
538
589
|
* Kubb pairing is worth an agent bearer token, not a user session.
|
|
539
590
|
*
|
|
540
|
-
* @throws when the code expires
|
|
591
|
+
* @throws {PairingExpiredError} when the code expires before anyone approves it.
|
|
592
|
+
* @throws {PairingDeniedError} when the pairing is denied in the browser.
|
|
593
|
+
* @throws {PairingCanceledError} when `signal` aborts.
|
|
594
|
+
*/
|
|
595
|
+
export declare function pollForPairingToken({ studioUrl, session, signal, onRetry }: PollOptions): Promise<PairingResult>;
|
|
596
|
+
type PairAgentOptions = StartPairingOptions & {
|
|
597
|
+
/** Shows the code to whoever approves it. Called again for each fresh code. */
|
|
598
|
+
onCode: (session: PairingSession, attempt: number) => void | Promise<void>;
|
|
599
|
+
/** Called when a poll could not reach Studio. Polling carries on. */
|
|
600
|
+
onRetry?: (error: Error) => void;
|
|
601
|
+
/**
|
|
602
|
+
* Codes to ask for in total when one expires unapproved. A denial or abort ends it at once.
|
|
603
|
+
* @default 1
|
|
604
|
+
*/
|
|
605
|
+
maxAttempts?: number;
|
|
606
|
+
};
|
|
607
|
+
/**
|
|
608
|
+
* Pairs this machine with Studio: asks for a code, hands it to the host to show, and waits for approval.
|
|
541
609
|
*/
|
|
542
|
-
export declare function
|
|
610
|
+
export declare function pairAgent({ onCode, onRetry, maxAttempts, ...options }: PairAgentOptions): Promise<PairingResult>;
|
|
543
611
|
//#endregion
|
|
544
612
|
//#region src/rpc.d.ts
|
|
545
613
|
/**
|
|
@@ -554,5 +622,5 @@ export declare function pollForPairingToken({ studioUrl, session, signal }: Poll
|
|
|
554
622
|
*/
|
|
555
623
|
export declare const connectWebSocketRpc: RpcConnector;
|
|
556
624
|
//#endregion
|
|
557
|
-
export { type AgentApi, type Client, type ClientOptions, type ConfigEdit, type ConnectMessagePayload, type ConnectionOptions, type GenerateInput, type GenerateResult, type GenerationEvent, type GenerationEventPayloads, type GenerationEventType, type GenerationRun, type PublishSnapshotInput, type PublishSnapshotResult, type RpcConnection, type RpcConnector, type StudioAgent, type StudioApi, type StudioConnectedContext, type StudioJob, type StudioJobStatus, type StudioSnapshot, generationEventTypes };
|
|
625
|
+
export { AGENT_INSTANCE_HEADER, type AgentApi, type AgentCapacity, AgentCloseCode, type AgentLoad, type AgentRegisterInput, type AgentRegisterResponse, type Client, type ClientOptions, type ConfigEdit, type ConnectMessagePayload, type ConnectionOptions, type GenerateInput, type GenerateResult, type GenerationEvent, type GenerationEventPayloads, type GenerationEventType, type GenerationRun, type PairingAgentType, type PairingResult, type PairingSession, type PublishSnapshotInput, type PublishSnapshotResult, type RpcClose, type RpcConnection, type RpcConnector, type StudioAgent, type StudioApi, type StudioConnectedContext, type StudioJob, type StudioJobStatus, type StudioSnapshot, type StudioSnapshotChanges, generationEventTypes };
|
|
558
626
|
//# sourceMappingURL=index.d.ts.map
|