@kici-dev/agent 0.5.0 → 0.6.1
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/checkout/clone-job-repos.d.ts +53 -0
- package/dist/checkout/credential-helper-bin.d.ts +28 -0
- package/dist/checkout/credential-helper-host.d.ts +48 -0
- package/dist/checkout/credential-helper.d.ts +44 -0
- package/dist/checkout/git-clone.d.ts +26 -0
- package/dist/checkout/grant-table.d.ts +30 -0
- package/dist/checkout/job-git-credentials.d.ts +49 -0
- package/dist/checkout/write-elevation.d.ts +40 -0
- package/dist/config.d.ts +38 -0
- package/dist/container-ts-loader-hook.js +2047 -1814
- package/dist/execution/between-jobs-controller.d.ts +50 -0
- package/dist/execution/between-jobs-reset.d.ts +25 -0
- package/dist/execution/cleanup-rerun.d.ts +21 -0
- package/dist/execution/dynamic-job-serializer.d.ts +6 -2
- package/dist/execution/image-build/build-engine.d.ts +75 -0
- package/dist/execution/image-build/build-step.d.ts +57 -0
- package/dist/execution/image-build/resolve-build-spec.d.ts +41 -0
- package/dist/execution/image-build/runtime-facts.d.ts +31 -0
- package/dist/execution/job-runner.d.ts +48 -0
- package/dist/execution/sandbox/bare-metal-sandbox.d.ts +25 -1
- package/dist/execution/sandbox/container-sandbox.d.ts +97 -2
- package/dist/execution/sandbox/fork-runner.d.ts +55 -1
- package/dist/execution/sandbox/image-preflight.d.ts +38 -0
- package/dist/execution/sandbox/ipc-protocol.d.ts +96 -2
- package/dist/execution/sandbox/kici-runtime.d.ts +48 -0
- package/dist/execution/sandbox/step-loop.d.ts +7 -0
- package/dist/execution/sandbox/types.d.ts +55 -1
- package/dist/execution/sandbox/workflow-runner.d.ts +23 -3
- package/dist/idle-shutdown.d.ts +24 -0
- package/dist/index.js +133 -62
- package/dist/metrics/prometheus.d.ts +26 -0
- package/dist/server.js +2050 -312
- package/dist/workflow-runner-bundle.js +41971 -41318
- package/dist/workflow-runner.js +332 -136
- package/dist/ws/orchestrator-client.d.ts +95 -3
- package/package.json +10 -10
- package/sbom.spdx.json +460 -455
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clone a job's repositories — from the host or from inside the sandbox.
|
|
3
|
+
*
|
|
4
|
+
* This used to live only inside the workflow runner, which meant the clone
|
|
5
|
+
* always happened wherever the runner ran: for a container job, inside the
|
|
6
|
+
* customer's image, which therefore had to ship git. Extracting it lets the
|
|
7
|
+
* AGENT clone on the host and copy the tree in, so the image needs no git —
|
|
8
|
+
* and it puts clone-time credentials on the host, where the credential helper
|
|
9
|
+
* already works, rather than needing a route into a container hardened with
|
|
10
|
+
* `CapDrop: ALL`.
|
|
11
|
+
*
|
|
12
|
+
* Both callers run the SAME code: the runner keeps calling it for bare-metal
|
|
13
|
+
* and for the legacy container path, and the agent calls it for a host-side
|
|
14
|
+
* checkout. A second implementation would be two subtly different clones.
|
|
15
|
+
*/
|
|
16
|
+
import { type GitAuth } from './git-clone.js';
|
|
17
|
+
/** The clone-relevant slice of a job execution request. */
|
|
18
|
+
export interface CloneJobReposRequest {
|
|
19
|
+
repoUrl: string;
|
|
20
|
+
ref: string;
|
|
21
|
+
sha: string;
|
|
22
|
+
token?: string | undefined;
|
|
23
|
+
sourceAuth?: GitAuth | undefined;
|
|
24
|
+
workflowAuth?: GitAuth | undefined;
|
|
25
|
+
workflowRepoUrl?: string | undefined;
|
|
26
|
+
workflowRef?: string | undefined;
|
|
27
|
+
workflowSha?: string | undefined;
|
|
28
|
+
checkout?: boolean | undefined;
|
|
29
|
+
fullRepo?: boolean | undefined;
|
|
30
|
+
credentialHelperPath?: string | undefined;
|
|
31
|
+
}
|
|
32
|
+
export interface CloneJobReposDirs {
|
|
33
|
+
workDir: string;
|
|
34
|
+
workflowDir: string;
|
|
35
|
+
sourceDir: string;
|
|
36
|
+
}
|
|
37
|
+
export interface CloneJobReposDeps {
|
|
38
|
+
/** Whether this job runs a global workflow (workflow repo + source repo). */
|
|
39
|
+
isGlobal: boolean;
|
|
40
|
+
/** Progress sink. The runner routes this to IPC; the agent to its logger. */
|
|
41
|
+
log: (line: string) => void;
|
|
42
|
+
/** Hide dep-restore scratch dirs from `git status` in a cloned tree. */
|
|
43
|
+
excludeScratchFromGit: (dir: string) => Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Clone whatever this job needs, or nothing.
|
|
47
|
+
*
|
|
48
|
+
* Three modes, unchanged from where this logic used to live: full-repo overlay
|
|
49
|
+
* (no clone), global dual-clone (workflow repo + source repo), and the ordinary
|
|
50
|
+
* single-repo clone.
|
|
51
|
+
*/
|
|
52
|
+
export declare function cloneJobRepos(request: CloneJobReposRequest, dirs: CloneJobReposDirs, deps: CloneJobReposDeps): Promise<void>;
|
|
53
|
+
//# sourceMappingURL=clone-job-repos.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The executable git spawns as `credential.helper`.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately minimal: read stdin, forward to the agent over its local socket,
|
|
5
|
+
* write stdout. No state, no decisions, no logging — anything it printed would
|
|
6
|
+
* risk putting a token in a log, and git treats unexpected stdout as part of
|
|
7
|
+
* the credential reply.
|
|
8
|
+
*
|
|
9
|
+
* Every failure mode answers with an EMPTY reply rather than a non-zero exit:
|
|
10
|
+
* git then falls through to its own mechanisms and reports a normal
|
|
11
|
+
* authentication failure, instead of the helper turning a recoverable miss into
|
|
12
|
+
* a crash mid-push.
|
|
13
|
+
*/
|
|
14
|
+
export interface HelperDeps {
|
|
15
|
+
/** Round-trip to the agent over its local socket. */
|
|
16
|
+
send: (query: {
|
|
17
|
+
protocol?: string;
|
|
18
|
+
host?: string;
|
|
19
|
+
path?: string;
|
|
20
|
+
}) => Promise<{
|
|
21
|
+
kind: string;
|
|
22
|
+
user?: string;
|
|
23
|
+
secret: string;
|
|
24
|
+
} | null>;
|
|
25
|
+
}
|
|
26
|
+
/** Testable core. `argv` is git's operation word: `get`, `store`, or `erase`. */
|
|
27
|
+
export declare function runHelperMain(argv: readonly string[], stdin: string, deps: HelperDeps): Promise<string>;
|
|
28
|
+
//# sourceMappingURL=credential-helper-bin.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host side of the git credential helper.
|
|
3
|
+
*
|
|
4
|
+
* Git spawns the helper as its own process, so it cannot call into the agent
|
|
5
|
+
* directly. This module gives it a route: a per-job unix socket the agent
|
|
6
|
+
* listens on, plus a tiny executable shim that connects to it and speaks git's
|
|
7
|
+
* credential protocol on stdin/stdout.
|
|
8
|
+
*
|
|
9
|
+
* The shim is deliberately self-contained — no imports beyond `node:net` — so it
|
|
10
|
+
* needs no module resolution, no bundle, and no dependency on where the agent
|
|
11
|
+
* was installed. Its only job is to move bytes.
|
|
12
|
+
*
|
|
13
|
+
* Scope: this is the HOST path, which covers bare-metal jobs. A container job
|
|
14
|
+
* clones and executes inside the container today and has no route to this
|
|
15
|
+
* socket; that is fixed by the dual-mode container work, which moves the clone
|
|
16
|
+
* to the host and injects `/opt/kici` read-only.
|
|
17
|
+
*/
|
|
18
|
+
/** What the shim asks for, and what it gets back. */
|
|
19
|
+
export interface HelperQuery {
|
|
20
|
+
protocol?: string;
|
|
21
|
+
host?: string;
|
|
22
|
+
path?: string;
|
|
23
|
+
}
|
|
24
|
+
export type HelperAnswer = {
|
|
25
|
+
username: string;
|
|
26
|
+
password: string;
|
|
27
|
+
} | null;
|
|
28
|
+
/** The shim source. Kept inline so the helper has no build step of its own. */
|
|
29
|
+
export declare function shimSource(socketPath: string): string;
|
|
30
|
+
export interface CredentialHelperHost {
|
|
31
|
+
/** Absolute path to pass as `credential.helper`. */
|
|
32
|
+
helperPath: string;
|
|
33
|
+
/** Stop listening and release the socket. */
|
|
34
|
+
close(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Start the per-job helper socket and materialize the shim.
|
|
38
|
+
*
|
|
39
|
+
* `answer` is the agent's resolver: it consults the grant table and asks the
|
|
40
|
+
* orchestrator broker. Returning null means "no credential", which the shim
|
|
41
|
+
* turns into an empty reply so git falls through to its own mechanisms.
|
|
42
|
+
*/
|
|
43
|
+
export declare function startCredentialHelperHost(args: {
|
|
44
|
+
/** Job-scoped directory to hold the socket and the shim. */
|
|
45
|
+
dir: string;
|
|
46
|
+
answer: (query: HelperQuery) => Promise<HelperAnswer>;
|
|
47
|
+
}): Promise<CredentialHelperHost>;
|
|
48
|
+
//# sourceMappingURL=credential-helper-host.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git credential-helper protocol, agent side.
|
|
3
|
+
*
|
|
4
|
+
* Git invokes the helper on EVERY network operation, which is the mechanism
|
|
5
|
+
* that defeats the one-hour GitHub App token expiry: a token is always minted
|
|
6
|
+
* seconds before it is used, and nothing is ever persisted to `.git/config`,
|
|
7
|
+
* the step environment, or a log.
|
|
8
|
+
*
|
|
9
|
+
* The default is read-only. An elevated credential is served only while a write
|
|
10
|
+
* grant covers the repository git is contacting.
|
|
11
|
+
*/
|
|
12
|
+
import type { GrantTable } from './grant-table.js';
|
|
13
|
+
export interface CredentialQuery {
|
|
14
|
+
protocol?: string;
|
|
15
|
+
host?: string;
|
|
16
|
+
path?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface CredentialReply {
|
|
19
|
+
username: string;
|
|
20
|
+
password: string;
|
|
21
|
+
}
|
|
22
|
+
/** Parse git's `key=value\n…\n\n` block. Unknown or malformed lines are skipped. */
|
|
23
|
+
export declare function parseCredentialInput(stdin: string): CredentialQuery;
|
|
24
|
+
/** Render a reply in the same `key=value` form. */
|
|
25
|
+
export declare function formatCredentialOutput(reply: CredentialReply): string;
|
|
26
|
+
export interface ServeCredentialDeps {
|
|
27
|
+
grants: GrantTable;
|
|
28
|
+
/** Round-trip to the orchestrator broker. Returns null when there is no credential. */
|
|
29
|
+
request: (args: {
|
|
30
|
+
repository: string;
|
|
31
|
+
permissions: Readonly<Record<string, string>>;
|
|
32
|
+
}) => Promise<{
|
|
33
|
+
kind: string;
|
|
34
|
+
user?: string;
|
|
35
|
+
secret: string;
|
|
36
|
+
} | null>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Answer one `get`. Returns the reply block, or an empty string when we have no
|
|
40
|
+
* credential — an empty reply lets git fall through to its own mechanisms
|
|
41
|
+
* rather than failing outright.
|
|
42
|
+
*/
|
|
43
|
+
export declare function serveCredential(query: CredentialQuery, deps: ServeCredentialDeps): Promise<string>;
|
|
44
|
+
//# sourceMappingURL=credential-helper.d.ts.map
|
|
@@ -42,7 +42,33 @@ interface CloneOptions {
|
|
|
42
42
|
gitAuth?: GitAuth;
|
|
43
43
|
/** Clone depth (default: 1 for shallow clone) */
|
|
44
44
|
depth?: number;
|
|
45
|
+
/**
|
|
46
|
+
* When set, the clone is configured to use this credential helper, so every
|
|
47
|
+
* later git network operation asks the agent for a freshly minted credential
|
|
48
|
+
* instead of relying on one captured at clone time.
|
|
49
|
+
*/
|
|
50
|
+
credentialHelperPath?: string;
|
|
51
|
+
/**
|
|
52
|
+
* When set, the temp SSH key is handed to the job rather than deleted when
|
|
53
|
+
* the clone returns — which is what lets a later step push. Omit and the
|
|
54
|
+
* existing cleanup applies unchanged.
|
|
55
|
+
*/
|
|
56
|
+
sshCleanupRegistry?: SshCleanupRegistry;
|
|
45
57
|
}
|
|
58
|
+
/** Hands SSH key cleanup to the job, so the key outlives the clone. */
|
|
59
|
+
export interface SshCleanupRegistry {
|
|
60
|
+
defer(cleanup: () => Promise<void>): void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Point a clone at the agent's credential helper.
|
|
64
|
+
*
|
|
65
|
+
* Only the helper PATH is written — never a secret — which is what makes it
|
|
66
|
+
* safe to persist in `.git/config`. `useHttpPath` makes git include
|
|
67
|
+
* `path=owner/repo.git` in every credential query, without which the helper
|
|
68
|
+
* could not tell one repository from another and a write grant could not be
|
|
69
|
+
* confined to its own repo.
|
|
70
|
+
*/
|
|
71
|
+
export declare function configureCredentialHelper(workDir: string, helperPath: string): void;
|
|
46
72
|
/**
|
|
47
73
|
* Shallow-clone a git repository at a specific ref with optional token auth.
|
|
48
74
|
*
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live write grants for this job.
|
|
3
|
+
*
|
|
4
|
+
* `withWrite` adds a grant before running its callback and revokes it in a
|
|
5
|
+
* `finally`; the TTL is a backstop so a step that crashes cannot leave one
|
|
6
|
+
* standing. The credential helper consults this table to decide whether to ask
|
|
7
|
+
* the broker for a read-only or an elevated credential.
|
|
8
|
+
*
|
|
9
|
+
* Scope note, stated because the name could mislead: a grant is scoped to a
|
|
10
|
+
* REPOSITORY and a TIME WINDOW — not to a step. The agent forks one process per
|
|
11
|
+
* job and `parallel()` runs its children inside that process, so a concurrent
|
|
12
|
+
* sibling step can push to the same repository while a grant is live. It cannot
|
|
13
|
+
* reach a different repository.
|
|
14
|
+
*/
|
|
15
|
+
export interface WriteGrant {
|
|
16
|
+
/** `owner/repo`, however git spelled it. */
|
|
17
|
+
repoPath: string;
|
|
18
|
+
permissions: Readonly<Record<string, string>>;
|
|
19
|
+
/** Epoch millis after which the grant is dead regardless of revocation. */
|
|
20
|
+
expiresAt: number;
|
|
21
|
+
}
|
|
22
|
+
export declare class GrantTable {
|
|
23
|
+
private readonly grants;
|
|
24
|
+
add(grant: WriteGrant): string;
|
|
25
|
+
revoke(grantId: string): void;
|
|
26
|
+
lookup(repoPath: string, now?: number): WriteGrant | null;
|
|
27
|
+
/** Live grant count, after reaping expired entries. Test and diagnostics use. */
|
|
28
|
+
size(now?: number): number;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=grant-table.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-job git credential plumbing.
|
|
3
|
+
*
|
|
4
|
+
* Owns the three things a job needs to authenticate git: the grant table, the
|
|
5
|
+
* helper socket git talks to, and the relay to the orchestrator broker. Kept in
|
|
6
|
+
* its own module so the job runner wires one object rather than three, and so
|
|
7
|
+
* this logic is testable without standing up a job.
|
|
8
|
+
*
|
|
9
|
+
* Scope: this is the HOST path, which covers bare-metal jobs. A container job
|
|
10
|
+
* clones and executes inside the container today and has no route to the
|
|
11
|
+
* socket; that is fixed by the dual-mode container work, which moves the clone
|
|
12
|
+
* to the host and injects `/opt/kici` read-only.
|
|
13
|
+
*/
|
|
14
|
+
import type { GitGrantRequestIpc, GitGrantResponseIpc } from '../execution/sandbox/ipc-protocol.js';
|
|
15
|
+
export interface JobGitCredentials {
|
|
16
|
+
/** Path to pass as `credential.helper` on every clone this job makes. */
|
|
17
|
+
helperPath: string;
|
|
18
|
+
/** Handler for `git.grant.request` IPC from the sandbox runner. */
|
|
19
|
+
onGitGrantRequest: (request: GitGrantRequestIpc) => Promise<GitGrantResponseIpc>;
|
|
20
|
+
/**
|
|
21
|
+
* Attach the job's declared credential to an outgoing broker request.
|
|
22
|
+
*
|
|
23
|
+
* `ctx.kici.git.github.getToken()` reaches the orchestrator directly rather
|
|
24
|
+
* than through the credential helper, so without this it would carry no ref
|
|
25
|
+
* and fall back to the source credential.
|
|
26
|
+
*/
|
|
27
|
+
withRef(params: Record<string, unknown>): Record<string, unknown>;
|
|
28
|
+
/** Release the socket. Safe to call more than once. */
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Stand up git credentials for one job.
|
|
33
|
+
*
|
|
34
|
+
* `sendApiRequest` is the agent's existing orchestrator relay — the same one
|
|
35
|
+
* `ctx.kici` uses — so this adds no new transport.
|
|
36
|
+
*/
|
|
37
|
+
export declare function startJobGitCredentials(args: {
|
|
38
|
+
jobId: string;
|
|
39
|
+
/**
|
|
40
|
+
* Named credentials declared on the job (`gitCredentials`), carried through
|
|
41
|
+
* the lock file in `jobConfig`. Values are SECRET NAMES; the orchestrator
|
|
42
|
+
* resolves them. `default` applies when a call names none.
|
|
43
|
+
*/
|
|
44
|
+
credentials?: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
45
|
+
/** Job-scoped directory for the socket and shim. */
|
|
46
|
+
dir: string;
|
|
47
|
+
sendApiRequest: (method: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
48
|
+
}): Promise<JobGitCredentials>;
|
|
49
|
+
//# sourceMappingURL=job-git-credentials.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open a write window for one repository, pre-flighting the grant.
|
|
3
|
+
*
|
|
4
|
+
* The mint happens HERE — at elevation entry, before any git runs — and the
|
|
5
|
+
* forge returns the permissions it actually granted. Comparing the two turns
|
|
6
|
+
* "wrong permission requested" from a cryptic push-time git failure at the end
|
|
7
|
+
* of a long build into a legible failure at the call site.
|
|
8
|
+
*
|
|
9
|
+
* What pre-flight proves: the TOKEN holds the permission. What it cannot prove:
|
|
10
|
+
* that the push will succeed. A branch protection rule or repository ruleset
|
|
11
|
+
* can still reject, and no token inspection predicts that.
|
|
12
|
+
*/
|
|
13
|
+
import type { GrantTable } from './grant-table.js';
|
|
14
|
+
type Permissions = Readonly<Record<string, string>>;
|
|
15
|
+
type Grant = {
|
|
16
|
+
scoped: false;
|
|
17
|
+
} | {
|
|
18
|
+
scoped: true;
|
|
19
|
+
permissions: Record<string, string>;
|
|
20
|
+
};
|
|
21
|
+
/** Requested entries the grant does not satisfy, as `key=value` strings. */
|
|
22
|
+
export declare function missingPermissions(requested: Permissions, granted: Permissions): string[];
|
|
23
|
+
export interface ElevateArgs {
|
|
24
|
+
repository: string;
|
|
25
|
+
permissions: Permissions;
|
|
26
|
+
grants: GrantTable;
|
|
27
|
+
request: (args: {
|
|
28
|
+
repository: string;
|
|
29
|
+
permissions: Permissions;
|
|
30
|
+
}) => Promise<{
|
|
31
|
+
grant: Grant;
|
|
32
|
+
expiresAt: string | null;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
export declare function elevateForWrite(args: ElevateArgs): Promise<{
|
|
36
|
+
grantId: string;
|
|
37
|
+
granted: Grant;
|
|
38
|
+
}>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=write-elevation.d.ts.map
|
package/dist/config.d.ts
CHANGED
|
@@ -6,6 +6,12 @@ export declare const ExecutionMode: z.ZodEnum<{
|
|
|
6
6
|
firecracker: "firecracker";
|
|
7
7
|
}>;
|
|
8
8
|
export type ExecutionMode = z.infer<typeof ExecutionMode>;
|
|
9
|
+
/** When the operator between-jobs reset command runs. */
|
|
10
|
+
export declare const BetweenJobsRunOn: z.ZodEnum<{
|
|
11
|
+
always: "always";
|
|
12
|
+
"on-failure": "on-failure";
|
|
13
|
+
}>;
|
|
14
|
+
export type BetweenJobsRunOn = z.infer<typeof BetweenJobsRunOn>;
|
|
9
15
|
declare const configSchema: z.ZodObject<{
|
|
10
16
|
orchestratorUrl: z.ZodString;
|
|
11
17
|
agentId: z.ZodOptional<z.ZodString>;
|
|
@@ -45,6 +51,14 @@ declare const configSchema: z.ZodObject<{
|
|
|
45
51
|
sandboxMemoryBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
46
52
|
sandboxNanoCpus: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
47
53
|
scalerManaged: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<boolean, string | undefined>>;
|
|
54
|
+
jobImageAgent: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<boolean, string | undefined>>;
|
|
55
|
+
runtimeImage: z.ZodOptional<z.ZodString>;
|
|
56
|
+
runtimeNodeSource: z.ZodOptional<z.ZodString>;
|
|
57
|
+
containerBuildCli: z.ZodOptional<z.ZodEnum<{
|
|
58
|
+
docker: "docker";
|
|
59
|
+
podman: "podman";
|
|
60
|
+
}>>;
|
|
61
|
+
scalerClaimCode: z.ZodOptional<z.ZodString>;
|
|
48
62
|
scalerIdleTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
49
63
|
scalerPendingDispatchTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
50
64
|
executionMode: z.ZodOptional<z.ZodEnum<{
|
|
@@ -55,6 +69,14 @@ declare const configSchema: z.ZodObject<{
|
|
|
55
69
|
otelExporterOtlpEndpoint: z.ZodOptional<z.ZodString>;
|
|
56
70
|
concurrencyWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
57
71
|
isOrchestratorHost: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<boolean, string | undefined>>;
|
|
72
|
+
betweenJobsResetCommand: z.ZodOptional<z.ZodString>;
|
|
73
|
+
betweenJobsResetTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
74
|
+
betweenJobsResetRunOn: z.ZodDefault<z.ZodEnum<{
|
|
75
|
+
always: "always";
|
|
76
|
+
"on-failure": "on-failure";
|
|
77
|
+
}>>;
|
|
78
|
+
orphanCleanup: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
79
|
+
drainOnResetFailure: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
58
80
|
}, z.core.$strip>;
|
|
59
81
|
/**
|
|
60
82
|
* App configuration type. Includes computed agentId when not provided.
|
|
@@ -96,12 +118,22 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
96
118
|
sandboxMemoryBytes: number;
|
|
97
119
|
sandboxNanoCpus: number;
|
|
98
120
|
scalerManaged: boolean;
|
|
121
|
+
jobImageAgent: boolean;
|
|
122
|
+
runtimeImage?: string | undefined;
|
|
123
|
+
runtimeNodeSource?: string | undefined;
|
|
124
|
+
containerBuildCli?: "docker" | "podman" | undefined;
|
|
125
|
+
scalerClaimCode?: string | undefined;
|
|
99
126
|
scalerIdleTimeoutMs: number;
|
|
100
127
|
scalerPendingDispatchTimeoutMs: number;
|
|
101
128
|
executionMode?: "bare-metal" | "container" | "firecracker" | undefined;
|
|
102
129
|
otelExporterOtlpEndpoint?: string | undefined;
|
|
103
130
|
concurrencyWaitTimeoutMs: number;
|
|
104
131
|
isOrchestratorHost: boolean;
|
|
132
|
+
betweenJobsResetCommand?: string | undefined;
|
|
133
|
+
betweenJobsResetTimeoutMs: number;
|
|
134
|
+
betweenJobsResetRunOn: "always" | "on-failure";
|
|
135
|
+
orphanCleanup: boolean;
|
|
136
|
+
drainOnResetFailure: boolean;
|
|
105
137
|
}>;
|
|
106
138
|
/**
|
|
107
139
|
* Load and validate agent configuration from environment variables.
|
|
@@ -132,10 +164,16 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
132
164
|
* - KICI_SANDBOX_MEMORY_BYTES (default: 2 GiB) — memory cap in bytes for the job container cgroup
|
|
133
165
|
* - KICI_SANDBOX_NANO_CPUS (default: 2 CPUs) — CPU cap in nano-CPUs for the job container cgroup
|
|
134
166
|
* - KICI_SCALER_MANAGED (set to "1" by the orchestrator's auto-scaler — agent self-shuts down on idle)
|
|
167
|
+
* - KICI_SCALER_CLAIM_CODE (optional single-use claim code the agent exchanges for its own ephemeral credentials before registering; ignored when KICI_AGENT_TOKEN is set)
|
|
135
168
|
* - KICI_SCALER_IDLE_TIMEOUT (ms, default 5000) — how long a scaler-managed agent waits before shutdown after going idle
|
|
136
169
|
* - KICI_SCALER_PENDING_DISPATCH_TIMEOUT (ms, default 60000) — extended idle window when register.ack signals a queued bound job
|
|
137
170
|
* - KICI_EXECUTION_MODE (optional, options: container | bare-metal | firecracker) — override the runner's mode-pick logic
|
|
138
171
|
* - KICI_CONCURRENCY_WAIT_TIMEOUT_MS (default: 3_600_000) — workflow-runner timeout when long-polling for a slot-release follow-up `concurrency.ack`
|
|
172
|
+
* - KICI_AGENT_BETWEEN_JOBS_RESET_COMMAND (optional) — host-reset command run between jobs on a reused agent (fail-open)
|
|
173
|
+
* - KICI_AGENT_BETWEEN_JOBS_RESET_TIMEOUT_MS (default: 60000) — reset command timeout
|
|
174
|
+
* - KICI_AGENT_BETWEEN_JOBS_RESET_RUN_ON (default: always, options: always | on-failure) — when the reset command runs
|
|
175
|
+
* - KICI_AGENT_ORPHAN_CLEANUP (default: true) — reap a finished job's leaked process tree (bare-metal); false = only signal the runner child
|
|
176
|
+
* - KICI_AGENT_DRAIN_ON_RESET_FAILURE (default: false) — drain the agent after repeated consecutive reset failures
|
|
139
177
|
*/
|
|
140
178
|
export declare function loadConfig(): AppConfig;
|
|
141
179
|
/**
|