@kici-dev/agent 0.5.0 → 0.6.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.
Files changed (37) hide show
  1. package/dist/checkout/clone-job-repos.d.ts +53 -0
  2. package/dist/checkout/credential-helper-bin.d.ts +28 -0
  3. package/dist/checkout/credential-helper-host.d.ts +48 -0
  4. package/dist/checkout/credential-helper.d.ts +44 -0
  5. package/dist/checkout/git-clone.d.ts +26 -0
  6. package/dist/checkout/grant-table.d.ts +30 -0
  7. package/dist/checkout/job-git-credentials.d.ts +49 -0
  8. package/dist/checkout/write-elevation.d.ts +40 -0
  9. package/dist/config.d.ts +38 -0
  10. package/dist/container-ts-loader-hook.js +2047 -1814
  11. package/dist/execution/between-jobs-controller.d.ts +50 -0
  12. package/dist/execution/between-jobs-reset.d.ts +25 -0
  13. package/dist/execution/cleanup-rerun.d.ts +21 -0
  14. package/dist/execution/dynamic-job-serializer.d.ts +6 -2
  15. package/dist/execution/image-build/build-engine.d.ts +75 -0
  16. package/dist/execution/image-build/build-step.d.ts +57 -0
  17. package/dist/execution/image-build/resolve-build-spec.d.ts +41 -0
  18. package/dist/execution/image-build/runtime-facts.d.ts +31 -0
  19. package/dist/execution/job-runner.d.ts +48 -0
  20. package/dist/execution/sandbox/bare-metal-sandbox.d.ts +25 -1
  21. package/dist/execution/sandbox/container-sandbox.d.ts +97 -2
  22. package/dist/execution/sandbox/fork-runner.d.ts +55 -1
  23. package/dist/execution/sandbox/image-preflight.d.ts +38 -0
  24. package/dist/execution/sandbox/ipc-protocol.d.ts +96 -2
  25. package/dist/execution/sandbox/kici-runtime.d.ts +48 -0
  26. package/dist/execution/sandbox/step-loop.d.ts +7 -0
  27. package/dist/execution/sandbox/types.d.ts +55 -1
  28. package/dist/execution/sandbox/workflow-runner.d.ts +23 -3
  29. package/dist/idle-shutdown.d.ts +24 -0
  30. package/dist/index.js +133 -62
  31. package/dist/metrics/prometheus.d.ts +26 -0
  32. package/dist/server.js +2050 -312
  33. package/dist/workflow-runner-bundle.js +41961 -41319
  34. package/dist/workflow-runner.js +332 -136
  35. package/dist/ws/orchestrator-client.d.ts +95 -3
  36. package/package.json +10 -10
  37. package/sbom.spdx.json +460 -455
@@ -29,6 +29,14 @@ export interface OrchestratorClientOptions {
29
29
  onJobCancel: (cancel: JobCancel) => void;
30
30
  /** Agent authentication token (kat_ prefixed). When provided, sends auth.request before agent.register. */
31
31
  token?: string;
32
+ /**
33
+ * Self-bootstrap claim code. When set and no static `token` is present, the
34
+ * client exchanges it for its own ephemeral credentials via
35
+ * `scaler.claim-credentials` on WS open — before any auth / register — then
36
+ * adopts the minted token, agentId, and labels. A rejected or expired code
37
+ * fails permanently (no reconnect). Ignored when a static `token` is present.
38
+ */
39
+ scalerClaimCode?: string;
32
40
  /** Heartbeat interval in ms. Default: 30000 (30s). */
33
41
  heartbeatIntervalMs?: number;
34
42
  /** Maximum reconnect delay in ms. Default: 60000 (60s). */
@@ -102,6 +110,8 @@ export declare class OrchestratorClient {
102
110
  private readonly pendingEventEmitRequests;
103
111
  /** Pending agent.api.request calls awaiting orchestrator response. */
104
112
  private readonly pendingApiRequests;
113
+ /** Pending scaler.claim-credentials requests awaiting orchestrator response. */
114
+ private readonly pendingClaimCredentialsRequests;
105
115
  /** Pending user-cache restore/save requests awaiting orchestrator response. */
106
116
  private readonly pendingUserCacheRequests;
107
117
  /** Pending user-artifact upload/download requests awaiting orchestrator response. */
@@ -134,12 +144,13 @@ export declare class OrchestratorClient {
134
144
  /** Pending concurrency report requests awaiting orchestrator ack. */
135
145
  private readonly pendingConcurrencyRequests;
136
146
  private readonly url;
137
- private readonly agentId;
138
- private readonly labels;
147
+ private agentId;
148
+ private labels;
139
149
  private readonly properties;
140
150
  private readonly onJobDispatch;
141
151
  private readonly onJobCancel;
142
- private readonly token?;
152
+ private token?;
153
+ private readonly scalerClaimCode?;
143
154
  private readonly heartbeatIntervalMs;
144
155
  private readonly maxReconnectDelayMs;
145
156
  private readonly getInFlightJobs?;
@@ -158,10 +169,26 @@ export declare class OrchestratorClient {
158
169
  * `pendingDispatch` is set by the orchestrator when a queued job has been
159
170
  * pre-bound to this agent and the dispatch.job message is in flight. The
160
171
  * agent must defer arming the short scaler-idle timer in this case.
172
+ *
173
+ * `warmPool` is set when this agent was pre-spawned to wait for work rather
174
+ * than for a specific queued job. The agent must arm no idle timer at all:
175
+ * the orchestrator's warm-pool reaper owns its lifetime.
161
176
  */
162
177
  onRegistered: ((info: {
163
178
  pendingDispatch: boolean;
179
+ warmPool: boolean;
164
180
  }) => void) | null;
181
+ /**
182
+ * Callback invoked when a self-bootstrap claim exchange fails permanently
183
+ * (invalid / expired / already-consumed claim code, or the exchange itself
184
+ * errored or timed out). Only ever fires in self-bootstrap mode
185
+ * (`scalerClaimCode` set, no static token) — a statically-tokened agent never
186
+ * runs the claim exchange. A one-shot self-bootstrap agent cannot make any
187
+ * further progress after this, so server.ts wires it to a non-zero graceful
188
+ * shutdown; without it the health HTTP server keeps the process alive and a
189
+ * GitHub Actions run hangs until the job timeout.
190
+ */
191
+ onClaimFailedPermanently: ((reason: string) => void) | null;
165
192
  constructor(options: OrchestratorClientOptions);
166
193
  /** Current connection state. */
167
194
  get state(): ConnectionState;
@@ -214,6 +241,7 @@ export declare class OrchestratorClient {
214
241
  requestUploadUrl(jobId: string, cacheType: 'source' | 'deps', key: {
215
242
  contentHash?: string;
216
243
  lockfileHash?: string;
244
+ depsHash?: string;
217
245
  platform: string;
218
246
  arch: string;
219
247
  }): Promise<string>;
@@ -251,6 +279,24 @@ export declare class OrchestratorClient {
251
279
  deliveryId?: string;
252
280
  error?: string;
253
281
  }>;
282
+ /**
283
+ * Send a scaler.claim-credentials WS message and await the response.
284
+ *
285
+ * Used by a provisioning workflow (via `ctx.kici.scaler.claimAgentCredentials`)
286
+ * to exchange a single-use claim code — delivered on a `kici.scaler.scale-up`
287
+ * event — for freshly minted ephemeral agent credentials. The token rides the
288
+ * response only; it is never logged. Times out after 15 seconds (matching the
289
+ * generic agent-API request timeout).
290
+ */
291
+ sendClaimCredentials(claimCode: string): Promise<{
292
+ credentials?: {
293
+ agentToken: string;
294
+ agentId: string;
295
+ orchestratorUrl: string;
296
+ labels: string[];
297
+ };
298
+ error?: string;
299
+ }>;
254
300
  /**
255
301
  * Build this agent's fleet mini-bundle and stream it back to the orchestrator
256
302
  * as ordered fleet.bundle.chunk frames (the WS frame cap forbids one frame).
@@ -369,6 +415,40 @@ export declare class OrchestratorClient {
369
415
  }>;
370
416
  getReconnectDelay(): number;
371
417
  private doConnect;
418
+ /**
419
+ * WS-open handshake driver.
420
+ *
421
+ * Self-bootstrap runs first: when a `scalerClaimCode` is set and no static
422
+ * token is present, the client exchanges the single-use code for its own
423
+ * ephemeral credentials over `scaler.claim-credentials` — before any auth or
424
+ * register — and adopts the minted token, agentId, and labels. A rejected or
425
+ * expired code fails permanently (no reconnect), so a one-shot provisioning
426
+ * run exits visibly rather than looping.
427
+ *
428
+ * Then the normal handshake: with a token (static or just-minted) send
429
+ * `auth.request` and register after `auth.success`; without one, register
430
+ * directly (unauthenticated mode).
431
+ */
432
+ private onWsOpen;
433
+ /**
434
+ * Exchange the single-use claim code for ephemeral credentials, adopting the
435
+ * minted token / agentId / labels on success. Returns true when credentials
436
+ * were adopted; false when the claim failed permanently (the connection has
437
+ * already been torn down with no reconnect).
438
+ */
439
+ private performClaimExchange;
440
+ /**
441
+ * Merge the claim-minted labels into the agent's own label set, deduped. The
442
+ * self-reported `kici:os:` / `kici:arch:` / `kici:host:` facts are derived at
443
+ * register time (`sendAgentRegister`), so they survive regardless.
444
+ */
445
+ private mergeClaimedLabels;
446
+ /**
447
+ * Fail a self-bootstrap claim permanently, using the same no-reconnect
448
+ * mechanism as `auth.failure`: mark the auth context dead, suppress reconnect,
449
+ * and close the socket. A one-shot provisioning run then exits visibly.
450
+ */
451
+ private failClaimPermanently;
372
452
  /**
373
453
  * Resolve a pending user-artifact request from an `artifacts.upload.response`
374
454
  * / `artifacts.download.response` WS message, mapping the wire fields onto the
@@ -418,6 +498,18 @@ export declare class OrchestratorClient {
418
498
  * Returns true when the message was consumed.
419
499
  */
420
500
  private handleArtifactReply;
501
+ /**
502
+ * Resolve a pending scaler credential-claim request from its response
503
+ * message. Returns true when it handled the message. Extracted from
504
+ * handleMessage so that dispatcher stays under the function-length limit.
505
+ */
506
+ private handleClaimCredentialsResponse;
507
+ /**
508
+ * Complete registration: adopt the orchestrator's negotiated capabilities,
509
+ * enter the `registered` state, flush everything parked while disconnected,
510
+ * and hand the ack's lifetime flags to `onRegistered`.
511
+ */
512
+ private handleRegisterAck;
421
513
  private handleMessage;
422
514
  private flushBuffer;
423
515
  /** Send the current pending log batch as an agent.log message. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kici-dev/agent",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Customer-deployable agent for the KiCI CI/CD stack. Connects to an orchestrator, clones the workflow repo, executes steps, and streams logs back.",
5
5
  "keywords": [
6
6
  "ci",
@@ -55,21 +55,21 @@
55
55
  }
56
56
  },
57
57
  "dependencies": {
58
- "@hono/node-server": "^2.0.10",
58
+ "@hono/node-server": "^2.1.1",
59
59
  "archiver": "^8.0.0",
60
60
  "dockerode": "^5.0.1",
61
- "hono": "^4.12.32",
62
- "jose": "^6.1.0",
63
- "tar": "^7.5.20",
61
+ "hono": "^4.13.2",
62
+ "jose": "^6.2.10",
63
+ "tar": "^7.5.22",
64
64
  "winston": "^3.19.0",
65
- "ws": "^8.21.1",
65
+ "ws": "^8.21.3",
66
66
  "yaml": "^2.9.0",
67
67
  "zod": "^4.4.3",
68
68
  "zx": "^8.8.5",
69
- "@kici-dev/core": "0.5.0",
70
- "@kici-dev/engine": "0.5.0",
71
- "@kici-dev/sdk": "0.5.0",
72
- "@kici-dev/shared": "0.5.0"
69
+ "@kici-dev/engine": "0.6.0",
70
+ "@kici-dev/sdk": "0.6.0",
71
+ "@kici-dev/shared": "0.6.0",
72
+ "@kici-dev/core": "0.6.0"
73
73
  },
74
74
  "kici": {
75
75
  "metrics": {