@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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
2
- import { AgentApi, AgentPermissions, ClientInfo, ConfigEdit, ConnectMessagePayload, GenerateInput, GenerateResult, GenerationEvent, GenerationEventPayloads, GenerationEventType, GenerationRun, PublishSnapshotInput, PublishSnapshotResult, RpcConnection, RpcConnector, StudioApi, generationEventTypes } from "./protocol.js";
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
- * Number of pool sessions this agent serves. Read by `createClient`, which opens one
189
- * session per slot, and reported to Studio at registration.
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
- poolSize?: number;
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 a live pool's token is rejected during background reconnect (401: revoked, or
228
- * the agent was deleted). The whole pool is already stopped by the time this fires, so a host
229
- * only needs to get a replacement token and start a new client.
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 the session pool. Resolves once the pool is starting: the
239
- * sessions keep running, and reconnect on their own, until `disconnect` is called.
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 every session and stops reconnecting.
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({ storage, onAuthRequired, ...options }: ClientOptions): Client;
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, and what would change it.
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, clientId, agentKind, signal }: StartPairingOptions): Promise<PairingSession>;
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. A poll that
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, the user denies it, or Studio returns an unexpected error.
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 pollForPairingToken({ studioUrl, session, signal }: PollOptions): Promise<PairingResult>;
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