@kici-dev/orchestrator 0.15.0 → 0.17.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/__test-helpers__/scratch-db.d.ts +16 -0
- package/dist/agent/registry.d.ts +1 -8
- package/dist/app-on-error.d.ts +1 -1
- package/dist/approvals/apply-decision.d.ts +12 -1
- package/dist/artifacts/artifact-store.d.ts +0 -2
- package/dist/audit/access-log.d.ts +1 -1
- package/dist/cache/source-cache.d.ts +1 -1
- package/dist/cache/user-cache.d.ts +0 -28
- package/dist/cli/api-client.d.ts +35 -1
- package/dist/cli/commands/access-log.d.ts +1 -1
- package/dist/cli/commands/api-key.d.ts +11 -4
- package/dist/cli/commands/cold-store-impl.d.ts +7 -84
- package/dist/cli/commands/db.d.ts +1 -0
- package/dist/cli/commands/orchestrator-service/status.d.ts +2 -0
- package/dist/cli/commands/org.d.ts +12 -0
- package/dist/cli/commands/scaler.d.ts +14 -0
- package/dist/cli/commands/secret.d.ts +1 -45
- package/dist/cli/commands/service-health.d.ts +21 -13
- package/dist/cli/commands/shared/cli-action.d.ts +17 -0
- package/dist/cli/commands/shared/db.d.ts +5 -5
- package/dist/cli/commands/shared/org-id.d.ts +5 -0
- package/dist/cli/commands/shared/service-verbs.d.ts +19 -0
- package/dist/cli/commands/shared/table.d.ts +3 -0
- package/dist/cli/commands/shared/unbound-context-warning.d.ts +2 -22
- package/dist/cli/commands/trust-policy.d.ts +7 -31
- package/dist/cli/kici-admin.d.ts +1 -1
- package/dist/cli.js +9865 -8203
- package/dist/cluster/coordinator.d.ts +2 -2
- package/dist/cluster/peer-client.d.ts +27 -1
- package/dist/cluster/peer-forget.d.ts +4 -9
- package/dist/cluster/peer-handler.d.ts +11 -1
- package/dist/cluster/peer-request-waiters.d.ts +26 -0
- package/dist/cluster/scaler-orphans-peer.d.ts +4 -9
- package/dist/cluster/scaler-reload-fanout.d.ts +29 -0
- package/dist/cluster/scaler-reload-peer.d.ts +16 -0
- package/dist/cluster/worker-cluster-settings.d.ts +1 -0
- package/dist/cold-store/load-access-log-range.d.ts +3 -3
- package/dist/cold-store/tables/access-log.d.ts +4 -12
- package/dist/cold-store/tables/event-log.d.ts +8 -19
- package/dist/cold-store/tables/execution-jobs.d.ts +7 -24
- package/dist/cold-store/tables/execution-runs.d.ts +6 -20
- package/dist/cold-store/tables/execution-steps.d.ts +8 -26
- package/dist/cold-store/tables/secret-audit-log.d.ts +4 -11
- package/dist/config/env-overlay.d.ts +3 -8
- package/dist/config/reload.d.ts +9 -2
- package/dist/config/schema.d.ts +2 -2
- package/dist/config/types.d.ts +2 -2
- package/dist/config.d.ts +13 -17
- package/dist/contexts/held-runs.d.ts +3 -6
- package/dist/dashboard/cursor.d.ts +12 -0
- package/dist/dashboard/handler.d.ts +5 -12
- package/dist/db/deferred-index-build.d.ts +42 -0
- package/dist/db/deferred-indexes.d.ts +3 -37
- package/dist/db/migrations/100_held_runs_hold_type_vocabulary.d.ts +3 -5
- package/dist/db/migrations/158_normalize_legacy_values.d.ts +4 -0
- package/dist/db/repos/org-ids-repo.d.ts +87 -0
- package/dist/db/schema-snapshot.generated.d.ts +3 -0
- package/dist/db/types.d.ts +5 -22
- package/dist/fault-injection-types.d.ts +0 -6
- package/dist/git/dispatch-git-auth.d.ts +6 -12
- package/dist/helpers/json.d.ts +3 -0
- package/dist/index.js +144 -140
- package/dist/metrics/prometheus.d.ts +0 -5
- package/dist/oidc/id-token-claims.d.ts +1 -1
- package/dist/oidc/resolve-signer.d.ts +2 -4
- package/dist/orchestrator-core.d.ts +10 -3
- package/dist/pipeline/global-eval-round.d.ts +2 -26
- package/dist/pipeline/install-secrets-resolver.d.ts +0 -3
- package/dist/pipeline/manual-schedule.d.ts +1 -7
- package/dist/pipeline/test-pipeline.d.ts +8 -7
- package/dist/provenance/dispatch-context.d.ts +5 -7
- package/dist/provenance/pending-attestations-repo.d.ts +1 -1
- package/dist/provenance/trust-root.d.ts +4 -5
- package/dist/provenance/verify-deferred-capture.d.ts +3 -3
- package/dist/provider-registry.d.ts +13 -40
- package/dist/providers/universal-git/ssh-auth.d.ts +0 -5
- package/dist/queue/terminalize-unroutable.d.ts +5 -0
- package/dist/reporting/check-run-reporter.d.ts +8 -21
- package/dist/reporting/check-run-summary.d.ts +2 -2
- package/dist/reporting/execution-tracker.d.ts +1 -1
- package/dist/reporting/log-chunk-sink.d.ts +1 -1
- package/dist/reporting/run-summary-fields.d.ts +25 -0
- package/dist/reporting/s3-log-storage.d.ts +2 -2
- package/dist/routes/admin-access-log.d.ts +2 -9
- package/dist/routes/admin-auth.d.ts +2 -0
- package/dist/routes/admin-backends.d.ts +2 -9
- package/dist/routes/admin-cluster-name.d.ts +2 -8
- package/dist/routes/admin-cluster-settings.d.ts +2 -8
- package/dist/routes/admin-config.d.ts +0 -3
- package/dist/routes/admin-contexts.d.ts +3 -11
- package/dist/routes/admin-db.d.ts +2 -9
- package/dist/routes/admin-env.d.ts +33 -0
- package/dist/routes/admin-event-dlq.d.ts +2 -9
- package/dist/routes/admin-event-inspect.d.ts +2 -9
- package/dist/routes/admin-event-log.d.ts +2 -9
- package/dist/routes/admin-events.d.ts +3 -13
- package/dist/routes/admin-held-runs.d.ts +2 -8
- package/dist/routes/admin-list-limit.d.ts +3 -0
- package/dist/routes/admin-maintenance.d.ts +2 -9
- package/dist/routes/admin-orchestrator-drain.d.ts +2 -9
- package/dist/routes/admin-org-settings.d.ts +2 -8
- package/dist/routes/admin-orgs.d.ts +27 -0
- package/dist/routes/admin-peer-forget.d.ts +2 -9
- package/dist/routes/admin-queue-execution.d.ts +3 -10
- package/dist/routes/admin-registrations.d.ts +3 -14
- package/dist/routes/admin-runs.d.ts +3 -14
- package/dist/routes/admin-scaler-orphans.d.ts +2 -9
- package/dist/routes/admin-scaler-reload.d.ts +41 -0
- package/dist/routes/admin-scheduled-jobs.d.ts +2 -9
- package/dist/routes/admin-signing-keys.d.ts +2 -9
- package/dist/routes/admin-sources.d.ts +2 -9
- package/dist/routes/admin-trust-policy.d.ts +2 -8
- package/dist/routes/admin.d.ts +15 -13
- package/dist/routes/caller-identity.d.ts +52 -0
- package/dist/routes/test-direct.d.ts +46 -0
- package/dist/routes/uploads.d.ts +12 -11
- package/dist/scaler/config.d.ts +12 -84
- package/dist/scaler/file-reload.d.ts +48 -0
- package/dist/scaler/manager.d.ts +47 -33
- package/dist/scaler/scaler-state-store.d.ts +5 -0
- package/dist/scaler/types.d.ts +1 -4
- package/dist/secrets/job-secret-gate.d.ts +2 -5
- package/dist/secrets/rbac.d.ts +5 -1
- package/dist/secrets/routing-key-scope.d.ts +1 -0
- package/dist/secrets/secret-resolver.d.ts +2 -4
- package/dist/secrets/token-manager.d.ts +1 -0
- package/dist/security/trust-policy-gate.d.ts +0 -4
- package/dist/server.d.ts +6 -17
- package/dist/server.js +9890 -10851
- package/dist/standalone.js +6928 -6576
- package/dist/storage/s3.d.ts +7 -7
- package/dist/storage/types.d.ts +4 -4
- package/dist/worker/reroute-dispatch.d.ts +1 -0
- package/dist/worker/reroute-spawn-control.d.ts +1 -3
- package/dist/worker-core.d.ts +9 -2
- package/dist/ws/agent-handler.d.ts +3 -3
- package/dist/ws/dashboard-access.d.ts +57 -0
- package/dist/ws/dashboard-backends-handler.d.ts +1 -6
- package/dist/ws/dashboard-context-handler.d.ts +10 -15
- package/dist/ws/dashboard-fleet-write-handler.d.ts +1 -6
- package/dist/ws/dashboard-global-workflows-handler.d.ts +1 -6
- package/dist/ws/dashboard-registrations-handler.d.ts +1 -7
- package/dist/ws/platform-client.d.ts +85 -330
- package/dist/ws/test-relay-handlers.d.ts +16 -9
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +53 -53
- package/dist/cache/legacy-prefixes.d.ts +0 -19
- package/dist/cli/commands/agent-service/logs.d.ts +0 -14
- package/dist/cli/commands/agent-service/restart.d.ts +0 -12
- package/dist/cli/commands/agent-service/start.d.ts +0 -12
- package/dist/cli/commands/agent-service/stop.d.ts +0 -12
- package/dist/cli/commands/agent-service/uninstall.d.ts +0 -13
- package/dist/cli/commands/cache.d.ts +0 -51
- package/dist/cli/commands/orchestrator-service/logs.d.ts +0 -14
- package/dist/cli/commands/orchestrator-service/restart.d.ts +0 -12
- package/dist/cli/commands/orchestrator-service/start.d.ts +0 -12
- package/dist/cli/commands/orchestrator-service/stop.d.ts +0 -12
- package/dist/cli/commands/orchestrator-service/uninstall.d.ts +0 -13
- package/dist/git/inherited-secret.d.ts +0 -29
- package/dist/scaler/container-spawn.d.ts +0 -28
package/dist/index.js
CHANGED
|
@@ -10,8 +10,9 @@ import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
|
|
|
10
10
|
import { chmod, mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
11
11
|
import { Kysely, PostgresDialect, sql } from "kysely";
|
|
12
12
|
import pg from "pg";
|
|
13
|
-
import {
|
|
13
|
+
import { DEFAULT_APPROVAL_EXPIRY_SECONDS, ForkPolicy, HoldScope, HoldType, OrchRole, TriggerSource } from "@kici-dev/engine";
|
|
14
14
|
import { z } from "zod";
|
|
15
|
+
import { ORCHESTRATOR_DEFAULT_PORT } from "@kici-dev/shared/env";
|
|
15
16
|
import { platform, tmpdir } from "node:os";
|
|
16
17
|
import { createInterface } from "node:readline";
|
|
17
18
|
import { Octokit } from "@octokit/rest";
|
|
@@ -42,7 +43,7 @@ var S3CacheStorage = class {
|
|
|
42
43
|
client;
|
|
43
44
|
/** Separate client for pre-signed URL generation (uses externalEndpoint if configured). */
|
|
44
45
|
presignClient;
|
|
45
|
-
/**
|
|
46
|
+
/** Client for the developer upload URL: uploadEndpoint, else the presign client. */
|
|
46
47
|
uploadPresignClient;
|
|
47
48
|
bucket;
|
|
48
49
|
prefix;
|
|
@@ -62,11 +63,10 @@ var S3CacheStorage = class {
|
|
|
62
63
|
endpoint: options.externalEndpoint
|
|
63
64
|
});
|
|
64
65
|
else this.presignClient = this.client;
|
|
65
|
-
|
|
66
|
+
this.uploadPresignClient = options.uploadEndpoint ? createS3Client({
|
|
66
67
|
...options,
|
|
67
68
|
endpoint: options.uploadEndpoint
|
|
68
|
-
});
|
|
69
|
-
else this.uploadPresignClient = this.client;
|
|
69
|
+
}) : this.presignClient;
|
|
70
70
|
}
|
|
71
71
|
/** Build the full S3 object key from a cache key. */
|
|
72
72
|
objectKey(key) {
|
|
@@ -702,7 +702,7 @@ function createCacheStorage(config) {
|
|
|
702
702
|
* defect this layout closes — so serving it would serve the bug. For a v6 lock
|
|
703
703
|
* the fallback is unreachable anyway, since the schema bump moves every hash.
|
|
704
704
|
* Old objects are orphaned. The cache TTL is enforced lazily on access, so
|
|
705
|
-
* nothing here removes them
|
|
705
|
+
* nothing here removes them.
|
|
706
706
|
*/
|
|
707
707
|
const logger$4 = createLogger({ prefix: "source-cache" });
|
|
708
708
|
/**
|
|
@@ -1105,8 +1105,7 @@ const DEFAULT_USER_CACHE_TTL_MS = 6048e5;
|
|
|
1105
1105
|
const TAR_SUFFIX = ".tar.gz";
|
|
1106
1106
|
/**
|
|
1107
1107
|
* Stem prefix of an in-flight upload, `.tmp-<uuid>.tar.gz`: the presigned PUT
|
|
1108
|
-
* target a save lands on before commit copies it to its final key.
|
|
1109
|
-
* the retired-layout classifier so both agree on what an upload looks like.
|
|
1108
|
+
* target a save lands on before commit copies it to its final key.
|
|
1110
1109
|
*/
|
|
1111
1110
|
const TEMP_UPLOAD_STEM = ".tmp-";
|
|
1112
1111
|
/** Whether a listed object is an in-flight upload rather than a cache entry. */
|
|
@@ -1122,7 +1121,7 @@ const KEY_DISCRIMINATOR_TAIL = new RegExp(`^(.*)-([0-9a-f]{32})$`);
|
|
|
1122
1121
|
* is what keeps two other kinds of object out of a restore: an in-flight
|
|
1123
1122
|
* `.tmp-<uuid>.tar.gz` upload, which is a partial tarball until commit copies
|
|
1124
1123
|
* it to its final key, and an object under the retired un-discriminated layout,
|
|
1125
|
-
* which nothing writes
|
|
1124
|
+
* which nothing writes.
|
|
1126
1125
|
*/
|
|
1127
1126
|
function isCommittedEntry(key) {
|
|
1128
1127
|
return key.endsWith(TAR_SUFFIX) && KEY_DISCRIMINATOR_TAIL.test(key.slice(0, -7));
|
|
@@ -1147,9 +1146,6 @@ function stripKeyDiscriminator(stem) {
|
|
|
1147
1146
|
* signature on a pre-signed PUT/GET. Repo identifiers like `.` (the internal
|
|
1148
1147
|
* provider's repo id) hit exactly this case, so the all-dots guard keeps the
|
|
1149
1148
|
* object key canonical and the namespace boundary intact.
|
|
1150
|
-
*
|
|
1151
|
-
* Exported so an operator tool that addresses an org's prefix from a raw org id
|
|
1152
|
-
* (`kici-admin cache purge-legacy --org`) lands on the segment the writer used.
|
|
1153
1149
|
*/
|
|
1154
1150
|
function sanitizeSegment(s) {
|
|
1155
1151
|
const cleaned = s.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -1199,10 +1195,8 @@ function finalKey(prefix, key) {
|
|
|
1199
1195
|
}
|
|
1200
1196
|
/**
|
|
1201
1197
|
* The object key a committed save under `key` lands on for this ref. This is
|
|
1202
|
-
* the writer's own path
|
|
1203
|
-
* through it
|
|
1204
|
-
* legacy-layout classifier tests) takes it from here rather than restating
|
|
1205
|
-
* the format.
|
|
1198
|
+
* the writer's own path: `beginSave` and `commitSave` address the entry
|
|
1199
|
+
* through it.
|
|
1206
1200
|
*/
|
|
1207
1201
|
function userCacheEntryKey(ref, key) {
|
|
1208
1202
|
return finalKey(writePrefix(ref), key);
|
|
@@ -1451,7 +1445,7 @@ var PeerCredentialStore = class {
|
|
|
1451
1445
|
}
|
|
1452
1446
|
/** The most recently revoked credential row for `instanceId`, or null. */
|
|
1453
1447
|
async findLatestRevokedByInstanceId(instanceId) {
|
|
1454
|
-
const row = await this.db.selectFrom("peer_credentials").selectAll().where("instance_id", "=", instanceId).where("revoked_at", "is not", null).orderBy("revoked_at", "desc").executeTakeFirst();
|
|
1448
|
+
const row = await this.db.selectFrom("peer_credentials").selectAll().where("instance_id", "=", instanceId).where("revoked_at", "is not", null).orderBy("revoked_at", "desc").orderBy("created_at", "desc").executeTakeFirst();
|
|
1455
1449
|
return row ? mapRow(row) : null;
|
|
1456
1450
|
}
|
|
1457
1451
|
/**
|
|
@@ -2324,18 +2318,15 @@ var HeldRunStore = class {
|
|
|
2324
2318
|
* incidental: `expireOverdue` is not scope-filtered, so a released-but-not-yet-
|
|
2325
2319
|
* resumed row would otherwise be expired out from under its resume.
|
|
2326
2320
|
*
|
|
2327
|
-
* The filter
|
|
2328
|
-
*
|
|
2329
|
-
*
|
|
2330
|
-
* filter on `hold_scope`: a job-scoped timer hold used to be excluded here,
|
|
2331
|
-
* which left it with no release path at all — created, never released,
|
|
2332
|
-
* eventually expired, its job never dispatched.
|
|
2321
|
+
* The filter deliberately does NOT filter on `hold_scope`: a job-scoped timer
|
|
2322
|
+
* hold used to be excluded here, which left it with no release path at all —
|
|
2323
|
+
* created, never released, eventually expired, its job never dispatched.
|
|
2333
2324
|
*/
|
|
2334
2325
|
async releaseDueWaitHolds() {
|
|
2335
2326
|
return (await this.db.updateTable("held_runs").set({
|
|
2336
2327
|
status: "released",
|
|
2337
2328
|
resolved_at: sql`now()`
|
|
2338
|
-
}).where("status", "=", "pending").where("hold_type", "
|
|
2329
|
+
}).where("status", "=", "pending").where("hold_type", "=", HoldType.enum.timer).where("expires_at", "<", sql`now()`).returningAll().execute()).map((row) => ({
|
|
2339
2330
|
holdId: row.id,
|
|
2340
2331
|
runId: row.run_id,
|
|
2341
2332
|
jobId: row.job_id,
|
|
@@ -2353,7 +2344,7 @@ var HeldRunStore = class {
|
|
|
2353
2344
|
* `listQueuedHoldsForContext` fetches the rows it actually releases.
|
|
2354
2345
|
*/
|
|
2355
2346
|
async listAllQueuedHolds() {
|
|
2356
|
-
return await this.db.selectFrom("held_runs").innerJoin("execution_runs", "execution_runs.run_id", "held_runs.run_id").select(["held_runs.org_id as orgId", "execution_runs.context as concurrencyGroup"]).where("held_runs.status", "=", "pending").where("held_runs.hold_type", "
|
|
2347
|
+
return await this.db.selectFrom("held_runs").innerJoin("execution_runs", "execution_runs.run_id", "held_runs.run_id").select(["held_runs.org_id as orgId", "execution_runs.context as concurrencyGroup"]).where("held_runs.status", "=", "pending").where("held_runs.hold_type", "=", HoldType.enum.concurrency).execute();
|
|
2357
2348
|
}
|
|
2358
2349
|
/**
|
|
2359
2350
|
* List the pending queued (concurrency) holds for one context's concurrency
|
|
@@ -2366,7 +2357,7 @@ var HeldRunStore = class {
|
|
|
2366
2357
|
* starve whoever waited longest.
|
|
2367
2358
|
*/
|
|
2368
2359
|
async listQueuedHoldsForContext(orgId, concurrencyGroup) {
|
|
2369
|
-
return this.db.selectFrom("held_runs").innerJoin("execution_runs", "execution_runs.run_id", "held_runs.run_id").selectAll("held_runs").where("held_runs.org_id", "=", orgId).where("held_runs.status", "=", "pending").where("held_runs.hold_type", "
|
|
2360
|
+
return this.db.selectFrom("held_runs").innerJoin("execution_runs", "execution_runs.run_id", "held_runs.run_id").selectAll("held_runs").where("held_runs.org_id", "=", orgId).where("held_runs.status", "=", "pending").where("held_runs.hold_type", "=", HoldType.enum.concurrency).where("execution_runs.context", "=", concurrencyGroup).where("execution_runs.customer_id", "=", orgId).orderBy("held_runs.created_at", "asc").execute();
|
|
2370
2361
|
}
|
|
2371
2362
|
/**
|
|
2372
2363
|
* Expire overdue pending runs. Called by the stale detector.
|
|
@@ -2406,12 +2397,10 @@ function createHeldRunStoreFromUrl(databaseUrl, opts) {
|
|
|
2406
2397
|
const DEFAULT_FORK_POLICY = ForkPolicy.enum.ignore;
|
|
2407
2398
|
Object.freeze({
|
|
2408
2399
|
forkPolicy: DEFAULT_FORK_POLICY,
|
|
2409
|
-
approvalExpiryHours: DEFAULT_APPROVAL_EXPIRY_HOURS,
|
|
2410
2400
|
approvalExpirySeconds: DEFAULT_APPROVAL_EXPIRY_SECONDS
|
|
2411
2401
|
});
|
|
2412
2402
|
Object.freeze({
|
|
2413
2403
|
forkPolicy: ForkPolicy.enum.hold,
|
|
2414
|
-
approvalExpiryHours: DEFAULT_APPROVAL_EXPIRY_HOURS,
|
|
2415
2404
|
approvalExpirySeconds: DEFAULT_APPROVAL_EXPIRY_SECONDS
|
|
2416
2405
|
});
|
|
2417
2406
|
z.enum([
|
|
@@ -2441,34 +2430,9 @@ const TrustPolicySource = z.enum(["platform", "local"]);
|
|
|
2441
2430
|
*/
|
|
2442
2431
|
const DEFAULT_TRUST_POLICY = {
|
|
2443
2432
|
forkPolicy: DEFAULT_FORK_POLICY,
|
|
2444
|
-
approvalExpiryHours: DEFAULT_APPROVAL_EXPIRY_HOURS,
|
|
2445
2433
|
approvalExpirySeconds: DEFAULT_APPROVAL_EXPIRY_SECONDS
|
|
2446
2434
|
};
|
|
2447
2435
|
/**
|
|
2448
|
-
* Resolve a local patch's approval-expiry window against what is already stored.
|
|
2449
|
-
*
|
|
2450
|
-
* One value is being set, spelled two ways, so the pair is merged as a unit and
|
|
2451
|
-
* always re-derived from the winning seconds value:
|
|
2452
|
-
*
|
|
2453
|
-
* - a patch naming `approvalExpirySeconds` sets the window, and the hours field
|
|
2454
|
-
* is recomputed from it — a stale hours value left behind would be the coarse
|
|
2455
|
-
* view of a window that is no longer stored;
|
|
2456
|
-
* - a patch naming only `approvalExpiryHours` sets the window too, and the
|
|
2457
|
-
* seconds field is recomputed from it — keeping the old seconds value would
|
|
2458
|
-
* let it out-rank the operator's explicit hours and silently discard the
|
|
2459
|
-
* write;
|
|
2460
|
-
* - a patch naming both takes the seconds value, because it is the more
|
|
2461
|
-
* specific of the two (`approvalExpirySecondsOf`);
|
|
2462
|
-
* - a patch naming neither leaves the stored window untouched.
|
|
2463
|
-
*/
|
|
2464
|
-
function mergedExpiry(patch, existing) {
|
|
2465
|
-
const seconds = (patch.approvalExpirySeconds != null || patch.approvalExpiryHours != null ? approvalExpirySecondsOf(patch) : null) ?? existing?.approvalExpirySeconds ?? DEFAULT_TRUST_POLICY.approvalExpirySeconds ?? DEFAULT_APPROVAL_EXPIRY_SECONDS;
|
|
2466
|
-
return {
|
|
2467
|
-
approvalExpiryHours: approvalExpiryHoursOf(seconds),
|
|
2468
|
-
approvalExpirySeconds: seconds
|
|
2469
|
-
};
|
|
2470
|
-
}
|
|
2471
|
-
/**
|
|
2472
2436
|
* Namespace for the per-org advisory lock taken by `upsertLocal`, so the key
|
|
2473
2437
|
* cannot collide with another feature's advisory lock in the same database.
|
|
2474
2438
|
*/
|
|
@@ -2484,11 +2448,7 @@ var TrustPolicyStore = class {
|
|
|
2484
2448
|
if (!row) return null;
|
|
2485
2449
|
return {
|
|
2486
2450
|
forkPolicy: row.fork_policy,
|
|
2487
|
-
|
|
2488
|
-
approvalExpirySeconds: approvalExpirySecondsOf({
|
|
2489
|
-
approvalExpiryHours: Number(row.approval_expiry_hours),
|
|
2490
|
-
approvalExpirySeconds: row.approval_expiry_seconds == null ? null : Number(row.approval_expiry_seconds)
|
|
2491
|
-
}),
|
|
2451
|
+
approvalExpirySeconds: Number(row.approval_expiry_seconds),
|
|
2492
2452
|
source: row.source,
|
|
2493
2453
|
updatedAt: row.updated_at
|
|
2494
2454
|
};
|
|
@@ -2528,7 +2488,7 @@ var TrustPolicyStore = class {
|
|
|
2528
2488
|
const existing = await this.get(orgId, trx);
|
|
2529
2489
|
const merged = {
|
|
2530
2490
|
forkPolicy: patch.forkPolicy ?? existing?.forkPolicy ?? DEFAULT_TRUST_POLICY.forkPolicy,
|
|
2531
|
-
|
|
2491
|
+
approvalExpirySeconds: patch.approvalExpirySeconds ?? existing?.approvalExpirySeconds ?? DEFAULT_TRUST_POLICY.approvalExpirySeconds
|
|
2532
2492
|
};
|
|
2533
2493
|
await this.write(orgId, merged, TrustPolicySource.enum.local, trx);
|
|
2534
2494
|
await onWrite?.(trx, merged);
|
|
@@ -2536,11 +2496,9 @@ var TrustPolicyStore = class {
|
|
|
2536
2496
|
});
|
|
2537
2497
|
}
|
|
2538
2498
|
async write(orgId, policy, source, executor = this.db) {
|
|
2539
|
-
const seconds = approvalExpirySecondsOf(policy);
|
|
2540
2499
|
const columns = {
|
|
2541
2500
|
fork_policy: policy.forkPolicy,
|
|
2542
|
-
|
|
2543
|
-
approval_expiry_seconds: seconds,
|
|
2501
|
+
approval_expiry_seconds: policy.approvalExpirySeconds,
|
|
2544
2502
|
source,
|
|
2545
2503
|
updated_at: sql`now()`
|
|
2546
2504
|
};
|
|
@@ -2629,6 +2587,8 @@ function firstCauseMessage(err) {
|
|
|
2629
2587
|
function isTransportFailure(err) {
|
|
2630
2588
|
return err instanceof TypeError && err.message === "fetch failed";
|
|
2631
2589
|
}
|
|
2590
|
+
/** The admin API address kici-admin dials when neither --url nor KICI_ADMIN_URL is set. */
|
|
2591
|
+
const DEFAULT_ADMIN_URL = `http://localhost:${ORCHESTRATOR_DEFAULT_PORT}`;
|
|
2632
2592
|
async function fetchAdminApi(url, init, baseUrl) {
|
|
2633
2593
|
try {
|
|
2634
2594
|
return await fetch(url, init);
|
|
@@ -2639,9 +2599,20 @@ async function fetchAdminApi(url, init, baseUrl) {
|
|
|
2639
2599
|
}
|
|
2640
2600
|
const detail = firstCauseMessage(err);
|
|
2641
2601
|
const cause = detail ? ` (${detail})` : "";
|
|
2642
|
-
|
|
2602
|
+
const defaultHint = baseUrl === DEFAULT_ADMIN_URL ? ` ${DEFAULT_ADMIN_URL} is kici-admin's built-in default, the orchestrator's default port on this host; an orchestrator on another host, or one whose KICI_PORT sets another port, needs KICI_ADMIN_URL or --url.` : "";
|
|
2603
|
+
throw new Error(`cannot reach the orchestrator admin API at ${baseUrl}${cause}. Set KICI_ADMIN_URL to the orchestrator's HTTP address, or pass --base-url where the subcommand accepts it. Note KICI_ORCHESTRATOR_URL is NOT read by this CLI; if other subcommands appear to work, they are using the --database-url / KICI_DATABASE_URL direct-DB path rather than HTTP.${defaultHint}`, { cause: err });
|
|
2643
2604
|
}
|
|
2644
2605
|
}
|
|
2606
|
+
/** Build a `?a=1&b=2` query string, skipping undefined, null and empty-string values. */
|
|
2607
|
+
function toQuery(params) {
|
|
2608
|
+
const usp = new URLSearchParams();
|
|
2609
|
+
for (const [k, v] of Object.entries(params)) {
|
|
2610
|
+
if (v === void 0 || v === null || v === "") continue;
|
|
2611
|
+
usp.set(k, String(v));
|
|
2612
|
+
}
|
|
2613
|
+
const qs = usp.toString();
|
|
2614
|
+
return qs ? `?${qs}` : "";
|
|
2615
|
+
}
|
|
2645
2616
|
var AdminApiClient = class {
|
|
2646
2617
|
baseUrl;
|
|
2647
2618
|
token;
|
|
@@ -2841,17 +2812,17 @@ var AdminApiClient = class {
|
|
|
2841
2812
|
return this.request("POST", `/api/v1/admin/generic-sources/${encodeURIComponent(id)}/disable`);
|
|
2842
2813
|
}
|
|
2843
2814
|
async queryAudit(opts) {
|
|
2844
|
-
const
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
return (await this.request("GET", `/api/v1/admin/audit${qs
|
|
2815
|
+
const qs = toQuery({
|
|
2816
|
+
contextName: opts?.contextName,
|
|
2817
|
+
routingKey: opts?.routingKey,
|
|
2818
|
+
action: opts?.action,
|
|
2819
|
+
from: opts?.from,
|
|
2820
|
+
to: opts?.to,
|
|
2821
|
+
limit: opts?.limit,
|
|
2822
|
+
offset: opts?.offset,
|
|
2823
|
+
includeArchived: opts?.includeArchived || void 0
|
|
2824
|
+
});
|
|
2825
|
+
return (await this.request("GET", `/api/v1/admin/audit${qs}`)).entries;
|
|
2855
2826
|
}
|
|
2856
2827
|
async createToken(data) {
|
|
2857
2828
|
return this.request("POST", "/api/v1/admin/tokens", data);
|
|
@@ -2942,7 +2913,23 @@ var AdminApiClient = class {
|
|
|
2942
2913
|
* other failure throws.
|
|
2943
2914
|
*/
|
|
2944
2915
|
async forgetPeer(body) {
|
|
2945
|
-
const res = await
|
|
2916
|
+
const { res, json, text } = await this.postForBody("/api/v1/admin/peers/forget", body);
|
|
2917
|
+
if (res.ok) return json;
|
|
2918
|
+
if (res.status === 409 && json.acknowledgementRequired === true) return {
|
|
2919
|
+
instanceId: body.instanceId,
|
|
2920
|
+
results: json.results ?? [],
|
|
2921
|
+
acknowledgementRequired: true,
|
|
2922
|
+
...json.error ? { error: json.error } : {}
|
|
2923
|
+
};
|
|
2924
|
+
throw new Error(`HTTP ${res.status}: ${json.error ?? text}`);
|
|
2925
|
+
}
|
|
2926
|
+
/**
|
|
2927
|
+
* POST `body` and parse the answer whatever its status, for a route that
|
|
2928
|
+
* reports per-instance results on a non-2xx status too. An unparseable body
|
|
2929
|
+
* reads as `{}`.
|
|
2930
|
+
*/
|
|
2931
|
+
async postForBody(path, body) {
|
|
2932
|
+
const res = await fetchAdminApi(`${this.baseUrl}${path}`, {
|
|
2946
2933
|
method: "POST",
|
|
2947
2934
|
headers: {
|
|
2948
2935
|
Authorization: `Bearer ${this.token}`,
|
|
@@ -2957,14 +2944,25 @@ var AdminApiClient = class {
|
|
|
2957
2944
|
} catch {
|
|
2958
2945
|
parsed = void 0;
|
|
2959
2946
|
}
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2947
|
+
return {
|
|
2948
|
+
res,
|
|
2949
|
+
json: parsed ?? {},
|
|
2950
|
+
text
|
|
2951
|
+
};
|
|
2952
|
+
}
|
|
2953
|
+
/**
|
|
2954
|
+
* Reload the scaler config on this orchestrator and, unless `single`, on every
|
|
2955
|
+
* peer it is connected to. A response where an instance refused its file or
|
|
2956
|
+
* was not reached (422) is returned like a success, so the caller can show
|
|
2957
|
+
* every instance; a 404 means the orchestrator predates the route.
|
|
2958
|
+
*/
|
|
2959
|
+
async scalerReload(body) {
|
|
2960
|
+
const { res, json, text } = await this.postForBody("/api/v1/admin/scaler/reload", body);
|
|
2961
|
+
if ((res.ok || res.status === 422) && Array.isArray(json.results)) return {
|
|
2962
|
+
scope: json.scope ?? (body.single ? "single" : "cluster"),
|
|
2963
|
+
results: json.results
|
|
2967
2964
|
};
|
|
2965
|
+
if (res.status === 404) throw new Error("this orchestrator predates kici-admin scaler reload; send SIGHUP to it or upgrade it");
|
|
2968
2966
|
throw new Error(`HTTP ${res.status}: ${json.error ?? text}`);
|
|
2969
2967
|
}
|
|
2970
2968
|
/** List the live Firecracker VMs on this coordinator, or on the `target` peer. */
|
|
@@ -2979,9 +2977,17 @@ var AdminApiClient = class {
|
|
|
2979
2977
|
async stopScalerOrphans(body) {
|
|
2980
2978
|
return this.request("POST", "/api/v1/admin/scaler/orphans/stop", body);
|
|
2981
2979
|
}
|
|
2980
|
+
/**
|
|
2981
|
+
* @deprecated No KiCI server serves `/api/v1/api-keys`; use `createToken`
|
|
2982
|
+
* (`kici-admin token create`). Removed in v1.0.0.
|
|
2983
|
+
*/
|
|
2982
2984
|
async createApiKey(opts) {
|
|
2983
2985
|
return this.request("POST", "/api/v1/api-keys", opts);
|
|
2984
2986
|
}
|
|
2987
|
+
/**
|
|
2988
|
+
* @deprecated No KiCI server serves `/api/v1/api-keys`; use `createToken`
|
|
2989
|
+
* with `routingKey` (`kici-admin token create --routing-key`). Removed in v1.0.0.
|
|
2990
|
+
*/
|
|
2985
2991
|
async addRoutingKeyPermission(keyId, pattern) {
|
|
2986
2992
|
return this.request("POST", `/api/v1/api-keys/${encodeURIComponent(keyId)}/routing-permissions`, { pattern });
|
|
2987
2993
|
}
|
|
@@ -3016,15 +3022,15 @@ var AdminApiClient = class {
|
|
|
3016
3022
|
* are returned.
|
|
3017
3023
|
*/
|
|
3018
3024
|
async listRuns(opts) {
|
|
3019
|
-
const
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
return this.request("GET", `/api/v1/admin/runs${qs
|
|
3025
|
+
const qs = toQuery({
|
|
3026
|
+
status: opts?.status,
|
|
3027
|
+
workflowName: opts?.workflowName,
|
|
3028
|
+
repo: opts?.repo,
|
|
3029
|
+
since: opts?.since,
|
|
3030
|
+
limit: opts?.limit || void 0,
|
|
3031
|
+
offset: opts?.offset || void 0
|
|
3032
|
+
});
|
|
3033
|
+
return this.request("GET", `/api/v1/admin/runs${qs}`);
|
|
3028
3034
|
}
|
|
3029
3035
|
/**
|
|
3030
3036
|
* Count matching runs without returning the row list. Wraps the list
|
|
@@ -3077,27 +3083,27 @@ var AdminApiClient = class {
|
|
|
3077
3083
|
* secret_audit_log table.
|
|
3078
3084
|
*/
|
|
3079
3085
|
async getRunSecretOutputs(runId, opts) {
|
|
3080
|
-
const
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
return this.request("GET", `/api/v1/admin/runs/${encodeURIComponent(runId)}/secret-outputs${qs
|
|
3086
|
+
const qs = toQuery({
|
|
3087
|
+
outputKey: opts?.outputKey,
|
|
3088
|
+
reveal: opts?.reveal || void 0
|
|
3089
|
+
});
|
|
3090
|
+
return this.request("GET", `/api/v1/admin/runs/${encodeURIComponent(runId)}/secret-outputs${qs}`);
|
|
3085
3091
|
}
|
|
3086
3092
|
async listEventLog(opts) {
|
|
3087
|
-
const
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
return this.request("GET", `/api/v1/admin/event-log${qs
|
|
3093
|
+
const qs = toQuery({
|
|
3094
|
+
orgId: opts?.orgId,
|
|
3095
|
+
routingKey: opts?.routingKey,
|
|
3096
|
+
event: opts?.event,
|
|
3097
|
+
action: opts?.action,
|
|
3098
|
+
status: opts?.status,
|
|
3099
|
+
from: opts?.from,
|
|
3100
|
+
to: opts?.to,
|
|
3101
|
+
deliveryId: opts?.deliveryId,
|
|
3102
|
+
limit: opts?.limit,
|
|
3103
|
+
offset: opts?.offset,
|
|
3104
|
+
includeArchived: opts?.includeArchived || void 0
|
|
3105
|
+
});
|
|
3106
|
+
return this.request("GET", `/api/v1/admin/event-log${qs}`);
|
|
3101
3107
|
}
|
|
3102
3108
|
async getEventLog(deliveryId, opts) {
|
|
3103
3109
|
const params = new URLSearchParams({ orgId: opts.orgId });
|
|
@@ -3107,44 +3113,42 @@ var AdminApiClient = class {
|
|
|
3107
3113
|
}
|
|
3108
3114
|
/** List internal events, newest first (`GET /api/v1/admin/events`). */
|
|
3109
3115
|
async listEvents(opts) {
|
|
3110
|
-
const
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
return this.request("GET", `/api/v1/admin/events${qs
|
|
3116
|
+
const qs = toQuery({
|
|
3117
|
+
name: opts?.name,
|
|
3118
|
+
outcome: opts?.outcome,
|
|
3119
|
+
since: opts?.since,
|
|
3120
|
+
before: opts?.before,
|
|
3121
|
+
limit: opts?.limit
|
|
3122
|
+
});
|
|
3123
|
+
return this.request("GET", `/api/v1/admin/events${qs}`);
|
|
3118
3124
|
}
|
|
3119
3125
|
/** One internal event with its redacted payload and dispatched runs. */
|
|
3120
3126
|
async getEvent(id) {
|
|
3121
3127
|
return this.request("GET", `/api/v1/admin/events/${encodeURIComponent(id)}`);
|
|
3122
3128
|
}
|
|
3123
3129
|
async listAccessLog(opts) {
|
|
3124
|
-
const
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
return this.request("GET", `/api/v1/admin/access-log${qs
|
|
3130
|
+
const qs = toQuery({
|
|
3131
|
+
orgId: opts?.orgId,
|
|
3132
|
+
actorType: opts?.actorType,
|
|
3133
|
+
actorId: opts?.actorId,
|
|
3134
|
+
action: opts?.action,
|
|
3135
|
+
source: opts?.source,
|
|
3136
|
+
outcome: opts?.outcome,
|
|
3137
|
+
targetType: opts?.targetType,
|
|
3138
|
+
targetId: opts?.targetId,
|
|
3139
|
+
from: opts?.from,
|
|
3140
|
+
to: opts?.to,
|
|
3141
|
+
q: opts?.q,
|
|
3142
|
+
agentLabel: opts?.agentLabel,
|
|
3143
|
+
agentOnly: opts?.agentOnly || void 0,
|
|
3144
|
+
limit: opts?.limit,
|
|
3145
|
+
cursor: opts?.cursor
|
|
3146
|
+
});
|
|
3147
|
+
return this.request("GET", `/api/v1/admin/access-log${qs}`);
|
|
3142
3148
|
}
|
|
3143
3149
|
async getAccessLogEntry(id, opts) {
|
|
3144
|
-
const
|
|
3145
|
-
|
|
3146
|
-
const qs = params.toString();
|
|
3147
|
-
return this.request("GET", `/api/v1/admin/access-log/${encodeURIComponent(id)}${qs ? `?${qs}` : ""}`);
|
|
3150
|
+
const qs = toQuery({ orgId: opts?.orgId });
|
|
3151
|
+
return this.request("GET", `/api/v1/admin/access-log/${encodeURIComponent(id)}${qs}`);
|
|
3148
3152
|
}
|
|
3149
3153
|
async diagnose() {
|
|
3150
3154
|
return this.request("GET", "/admin/diagnose");
|
|
@@ -703,11 +703,6 @@ export declare const wsUnsupportedMessageSentTotal: import("@opentelemetry/api")
|
|
|
703
703
|
* `received_type`.
|
|
704
704
|
*/
|
|
705
705
|
export declare const wsNackReceivedTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
706
|
-
/**
|
|
707
|
-
* Feature-gated sends the orchestrator SUPPRESSED because the Platform advertised
|
|
708
|
-
* a capability set that lacks the required flag. Labelled by `capability` + `type`.
|
|
709
|
-
*/
|
|
710
|
-
export declare const wsPlatformCapabilityGapTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
711
706
|
/**
|
|
712
707
|
* Register every queued orchestrator observable gauge on the real meter.
|
|
713
708
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OIDC ID-token claims for orchestrator-side minting — shared by the
|
|
3
3
|
* production orchestrator-owned mint (`orchestrator-mint.ts`) and the local
|
|
4
|
-
* dev-signed identity (`local-mint.ts`).
|
|
4
|
+
* dev-signed identity (`local-mint.ts`). One claim shape, so
|
|
5
5
|
* every bundle carries the exact same claims the agent's statement builder +
|
|
6
6
|
* the engine verifier expect — the cross-check between the in-toto statement
|
|
7
7
|
* and the token claims is identical across all minters. The dev-signed path
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bounded wait for the orchestrator's provenance signer.
|
|
3
3
|
*
|
|
4
|
-
* A mint that arrives before any node has generated the key must
|
|
5
|
-
*
|
|
6
|
-
* orchestrator trust root), so the resolver waits for the key instead of
|
|
7
|
-
* deferring on the first miss. But the wait exists for ONE condition — a
|
|
4
|
+
* A mint that arrives before any node has generated the key must not fail,
|
|
5
|
+
* so the resolver waits for the key instead of deferring on the first miss. But the wait exists for ONE condition — a
|
|
8
6
|
* reconcile that returns `null` because a non-leader is still leaving key
|
|
9
7
|
* creation to the leader. A reconcile that THROWS is a different answer:
|
|
10
8
|
* a signing key sealed under a master key this process does not hold, or `db`
|
|
@@ -31,6 +31,7 @@ import { AgentMetricsAggregator } from './metrics/agent-metrics-aggregator.js';
|
|
|
31
31
|
import { SourceLocationStore } from './app.js';
|
|
32
32
|
import { ExecutionJobStatus, type PeerHeartbeat, type PeerLogsCollectRequest, type PeerToPeerMessage, type InvokeResult } from '@kici-dev/engine';
|
|
33
33
|
import { ScalerManager } from './scaler/index.js';
|
|
34
|
+
import { type ScalerFileReload } from './scaler/file-reload.js';
|
|
34
35
|
import type { ScalerConfig } from './scaler/index.js';
|
|
35
36
|
import type { CacheStorage } from './storage/index.js';
|
|
36
37
|
import { type ProvenanceTrustRoot } from './provenance/trust-root.js';
|
|
@@ -90,9 +91,9 @@ export interface OrchestratorSubsystems {
|
|
|
90
91
|
scalerConfig: ScalerConfig | null;
|
|
91
92
|
cacheStorage: CacheStorage | undefined;
|
|
92
93
|
/**
|
|
93
|
-
* Provenance trust root used to verify build-provenance bundles at ingest
|
|
94
|
-
*
|
|
95
|
-
*
|
|
94
|
+
* Provenance trust root used to verify build-provenance bundles at ingest:
|
|
95
|
+
* the orchestrator's own key set, the local dev plane's signer, or the
|
|
96
|
+
* configured `KICI_PROVENANCE_ISSUER`.
|
|
96
97
|
*/
|
|
97
98
|
provenanceTrustRoot: ProvenanceTrustRoot;
|
|
98
99
|
/**
|
|
@@ -174,6 +175,12 @@ export interface OrchestratorSubsystems {
|
|
|
174
175
|
* in setupCluster).
|
|
175
176
|
*/
|
|
176
177
|
answerPeerForgetRequest: PeerForgetRequestHandler;
|
|
178
|
+
/**
|
|
179
|
+
* Reloads this orchestrator's scaler config (`kici-admin scaler reload`,
|
|
180
|
+
* SIGHUP). Wired into every outgoing PeerClient to answer a
|
|
181
|
+
* peer.scaler.reload.request.
|
|
182
|
+
*/
|
|
183
|
+
scalerFileReload: ScalerFileReload;
|
|
177
184
|
getLocalInventory: () => Omit<PeerHeartbeat, 'type'>;
|
|
178
185
|
broadcastHeartbeatToAllPeers: () => void;
|
|
179
186
|
broadcastAgentTokenRevoke: (tokenId: string) => void;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* This module owns the partition, the grouping, and the dispatch-and-await. The
|
|
17
17
|
* caller decides what to do with the verdicts.
|
|
18
18
|
*/
|
|
19
|
-
import type {
|
|
19
|
+
import type { GlobalEvalCandidateResult, LockJobOrFactory, LockWorkflow, SimulatedEvent, WorkflowDecision } from '@kici-dev/engine';
|
|
20
20
|
import { type GlobalEvalRoundCache } from '../cache/global-eval-round-cache.js';
|
|
21
21
|
import type { PendingGlobalEvalTracker } from '../cache/pending-global-evals.js';
|
|
22
22
|
import type { ClusterSettingsReader } from '../cluster/cluster-settings-reader.js';
|
|
@@ -135,17 +135,12 @@ export interface GlobalEvalAgentRegistry {
|
|
|
135
135
|
arch: string;
|
|
136
136
|
version?: string | null;
|
|
137
137
|
}>;
|
|
138
|
-
/**
|
|
139
|
-
* Every registered agent, busy or idle. Optional so a test double can omit
|
|
140
|
-
* it; without it the up-front result-aware refusal never fires.
|
|
141
|
-
*/
|
|
138
|
+
/** Every registered agent, busy or idle. Optional so a test double can omit it. */
|
|
142
139
|
getAllEntries?(): Iterable<{
|
|
143
140
|
labels: ReadonlySet<string>;
|
|
144
141
|
platform: string;
|
|
145
142
|
arch: string;
|
|
146
143
|
version: string | null;
|
|
147
|
-
/** What the agent advertised on `agent.register`; `null` = supports nothing optional. */
|
|
148
|
-
capabilities: AgentCapabilities | null;
|
|
149
144
|
}>;
|
|
150
145
|
}
|
|
151
146
|
/**
|
|
@@ -226,25 +221,6 @@ export interface GlobalEvalRoundArgs {
|
|
|
226
221
|
* timeout message that says nothing about agent versions.
|
|
227
222
|
*/
|
|
228
223
|
export declare function unsupportedFleetReason(agentRegistry?: GlobalEvalAgentRegistry): string | null;
|
|
229
|
-
/**
|
|
230
|
-
* Why a candidate with a result-aware generator is refused before any round.
|
|
231
|
-
*
|
|
232
|
-
* An agent without the capability runs every generator in the round, a
|
|
233
|
-
* result-aware one included; that generator sees no upstream outputs and
|
|
234
|
-
* returns the wrong jobs.
|
|
235
|
-
*/
|
|
236
|
-
export declare const RESULT_AWARE_UNSUPPORTED_REASON: string;
|
|
237
|
-
/**
|
|
238
|
-
* Why no agent can run a round holding a result-aware generator, or `null`
|
|
239
|
-
* when one might.
|
|
240
|
-
*
|
|
241
|
-
* The same bar as {@link unsupportedFleetReason}: refused only on proof. That
|
|
242
|
-
* means init-runners ARE registered, every one reports a readable version, and
|
|
243
|
-
* none advertises the capability. An empty fleet, a busy capable agent, or an
|
|
244
|
-
* agent whose version cannot be read is not refused — the round queues on the
|
|
245
|
-
* agent-feature label, and a scaler or a registering agent can still serve it.
|
|
246
|
-
*/
|
|
247
|
-
export declare function resultAwareUnsupportedReason(agentRegistry?: GlobalEvalAgentRegistry): string | null;
|
|
248
224
|
/**
|
|
249
225
|
* Narrow one wire verdict into a value the dispatch path can trust.
|
|
250
226
|
*
|
|
@@ -116,9 +116,6 @@ export declare function validateRegistryUrlScheme(url: string, allowHttp: boolea
|
|
|
116
116
|
* it set one, otherwise the `HoldType` member its action implies. Column and
|
|
117
117
|
* gate share one vocabulary, so nothing is translated here.
|
|
118
118
|
*
|
|
119
|
-
* Distinct from the engine's `normalizePersistedHoldType`, which maps a value
|
|
120
|
-
* read back OUT of the column onto that same vocabulary.
|
|
121
|
-
*
|
|
122
119
|
* Exported for tests.
|
|
123
120
|
*/
|
|
124
121
|
export declare function resolveHoldType(action: 'hold' | 'wait' | 'queue', raw: string | undefined): string;
|