@kici-dev/agent 0.1.15 → 0.1.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/diagnostics/mini-bundle.d.ts +9 -0
- package/dist/execution/dep-installer.d.ts +7 -3
- package/dist/execution/dep-packer.d.ts +6 -1
- package/dist/execution/env-init/presets/directives.d.ts +20 -0
- package/dist/execution/env-init/presets/expand.d.ts +16 -0
- package/dist/execution/env-init/presets/mise/cache-key.d.ts +7 -0
- package/dist/execution/env-init/presets/mise/expander.d.ts +16 -0
- package/dist/execution/env-init/presets/mise/templates.d.ts +16 -0
- package/dist/execution/env-init/presets/mise/windows-install.d.ts +18 -0
- package/dist/execution/env-init/presets/registry.d.ts +31 -0
- package/dist/execution/init-runner.d.ts +7 -0
- package/dist/execution/job-runner.d.ts +18 -1
- package/dist/execution/sandbox/env-delta.d.ts +2 -0
- package/dist/execution/sandbox/index.d.ts +1 -1
- package/dist/execution/sandbox/ipc-protocol.d.ts +101 -3
- package/dist/execution/sandbox/step-loop.d.ts +24 -1
- package/dist/execution/sandbox/types.d.ts +18 -1
- package/dist/execution/sandbox/workflow-runner.d.ts +12 -7
- package/dist/execution/validate-kici-deps.d.ts +5 -0
- package/dist/execution/workspace-siblings.d.ts +33 -0
- package/dist/index.js +223 -6
- package/dist/provenance/attest.d.ts +30 -0
- package/dist/provenance/sign.d.ts +21 -0
- package/dist/provenance/statement-builder.d.ts +38 -0
- package/dist/server.js +698 -146
- package/dist/version.d.ts +2 -0
- package/dist/workflow-runner.js +877 -45
- package/dist/ws/orchestrator-client.d.ts +53 -4
- package/package.json +8 -5
- package/sbom.spdx.json +1957 -152
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface AgentMiniBundleOptions {
|
|
2
|
+
agentId: string;
|
|
3
|
+
logDir?: string;
|
|
4
|
+
logWindowHours: number;
|
|
5
|
+
config: Record<string, unknown>;
|
|
6
|
+
metricsText?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function buildAgentMiniBundle(opts: AgentMiniBundleOptions): Promise<Buffer>;
|
|
9
|
+
//# sourceMappingURL=mini-bundle.d.ts.map
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* When the dep cache is unavailable or a download fails, the agent installs
|
|
5
5
|
* `.kici/` dependencies directly with the repository's package manager.
|
|
6
6
|
*
|
|
7
|
-
* The package manager is detected from the cloned repo (npm / pnpm); the
|
|
7
|
+
* The package manager is detected from the cloned repo (npm / pnpm / yarn); the
|
|
8
8
|
* presence of `.kici/package.json` signals that deps should be installed. npm
|
|
9
9
|
* is the default and ships with every Node.js install; pnpm is used when the
|
|
10
10
|
* repo is a pnpm workspace so a `.kici/` member can resolve in-repo
|
|
11
|
-
* `workspace:` siblings. yarn
|
|
12
|
-
*
|
|
11
|
+
* `workspace:` siblings. yarn classic (v1) is supported for registry
|
|
12
|
+
* dependencies and version-range workspace siblings (which it links but does
|
|
13
|
+
* not build, so the agent builds the in-repo closure after install). yarn
|
|
14
|
+
* berry (v2+) is not yet supported.
|
|
13
15
|
*
|
|
14
16
|
* Security: the install runs with an isolated per-invocation cache/store
|
|
15
17
|
* directory to prevent cache poisoning across build jobs — a malicious
|
|
@@ -49,4 +51,6 @@ export interface InstallDepsOptions {
|
|
|
49
51
|
* @param opts - Optional registry / installEnv / repoRoot configuration.
|
|
50
52
|
*/
|
|
51
53
|
export declare function installDeps(kiciDir: string, opts?: InstallDepsOptions): Promise<void>;
|
|
54
|
+
/** Pure: argv for `yarn install` with an isolated cache folder. */
|
|
55
|
+
export declare function buildYarnInstallArgs(cacheDir: string, hasPrivateRegistry: boolean): string[];
|
|
52
56
|
//# sourceMappingURL=dep-installer.d.ts.map
|
|
@@ -6,13 +6,18 @@
|
|
|
6
6
|
* **repo-root-relative** (cwd = the clone root) so restore is a single layout
|
|
7
7
|
* regardless of package manager:
|
|
8
8
|
*
|
|
9
|
-
* - npm
|
|
9
|
+
* - npm: just `.kici/node_modules`.
|
|
10
10
|
* - pnpm: `.kici/node_modules` plus the repo-root `node_modules/.pnpm` virtual
|
|
11
11
|
* store and the in-repo `workspace:` sibling package directories `.kici`
|
|
12
12
|
* depends on (with their built output). pnpm lays `.kici/node_modules` out as
|
|
13
13
|
* symlinks into the root store and into sibling dirs that live outside
|
|
14
14
|
* `.kici/`, so packing `.kici/node_modules` alone would capture dangling
|
|
15
15
|
* links — the store and siblings must travel together.
|
|
16
|
+
* - yarn classic: the resolved node_modules root (standalone `.kici` →
|
|
17
|
+
* `.kici/node_modules`; hoisted workspace member → the repo-root
|
|
18
|
+
* `node_modules`) plus the in-repo version-range sibling package directories
|
|
19
|
+
* `.kici` depends on (with their built output), whose symlinks would dangle
|
|
20
|
+
* otherwise.
|
|
16
21
|
*
|
|
17
22
|
* Uses tar.gz (Node.js built-in zlib, no external binary) in portable mode to
|
|
18
23
|
* strip user/group info for cross-machine consistency; symlinks are preserved
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { GenericInitConfig, Job, MiseInitConfig } from '@kici-dev/sdk';
|
|
2
|
+
/** A normalized init step, ready for agent-side expansion. */
|
|
3
|
+
export type InitDirective = {
|
|
4
|
+
kind: 'generic';
|
|
5
|
+
config: GenericInitConfig;
|
|
6
|
+
} | {
|
|
7
|
+
kind: 'preset';
|
|
8
|
+
name: 'mise';
|
|
9
|
+
config: MiseInitConfig;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'auto';
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Normalize `Job.init` to an ordered list of directives, without touching the
|
|
15
|
+
* filesystem. `false`/`undefined` -> []; `'auto'` -> one auto directive;
|
|
16
|
+
* presets/generic configs -> their directive; arrays map element-wise.
|
|
17
|
+
* `'auto'` is a scalar only — finding it inside an array throws.
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeInitItems(job: Job | undefined): InitDirective[];
|
|
20
|
+
//# sourceMappingURL=directives.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GenericInitConfig } from '@kici-dev/sdk';
|
|
2
|
+
import type { InitDirective } from './directives.js';
|
|
3
|
+
/** Options for agent-side directive expansion. */
|
|
4
|
+
export interface ExpandOptions {
|
|
5
|
+
cloneRoot: string;
|
|
6
|
+
/** Host platform; defaults to process.platform. */
|
|
7
|
+
platform?: NodeJS.Platform;
|
|
8
|
+
/** Optional info logger (e.g. to emit a pseudo-step line). */
|
|
9
|
+
log?: (message: string) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Expand normalized directives into concrete generic init configs, reading the
|
|
13
|
+
* clone root for preset cache keys and `'auto'` marker detection.
|
|
14
|
+
*/
|
|
15
|
+
export declare function expandInitDirectives(directives: InitDirective[], opts: ExpandOptions): Promise<GenericInitConfig[]>;
|
|
16
|
+
//# sourceMappingURL=expand.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive the default mise cache key from the committed mise config under
|
|
3
|
+
* `cloneRoot`. Concatenates whichever of {@link MISE_CONFIG_FILES} exist (in
|
|
4
|
+
* fixed order) and hashes them. Returns `mise-noconfig` when none exist.
|
|
5
|
+
*/
|
|
6
|
+
export declare function miseCacheKey(cloneRoot: string): Promise<string>;
|
|
7
|
+
//# sourceMappingURL=cache-key.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GenericInitConfig, MiseInitConfig } from '@kici-dev/sdk';
|
|
2
|
+
import { type MiseWindowsArch } from './windows-install.js';
|
|
3
|
+
/** Arguments to expand the mise preset into a concrete generic init config. */
|
|
4
|
+
export interface MiseExpandArgs {
|
|
5
|
+
cloneRoot: string;
|
|
6
|
+
config: MiseInitConfig;
|
|
7
|
+
/** Host platform (defaults to process.platform). Injected for tests. */
|
|
8
|
+
platform?: NodeJS.Platform;
|
|
9
|
+
/** Windows asset resolver (defaults to the real GitHub lookup). Injected for tests. */
|
|
10
|
+
resolveWindowsAsset?: (arch: MiseWindowsArch) => Promise<string>;
|
|
11
|
+
}
|
|
12
|
+
/** The mise preset expander: turns MiseInitConfig into an OS-correct GenericInitConfig. */
|
|
13
|
+
export declare const miseExpander: {
|
|
14
|
+
expand(args: MiseExpandArgs): Promise<GenericInitConfig>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=expander.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** OS-specific pieces of a mise init expansion. */
|
|
2
|
+
export interface MiseTemplate {
|
|
3
|
+
/** The `run` command. */
|
|
4
|
+
run: string;
|
|
5
|
+
/** Shell to run it with. */
|
|
6
|
+
shell: string;
|
|
7
|
+
/** Cache `paths` for mise's data dir on this OS. */
|
|
8
|
+
cachePaths: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Pick the mise template for a host platform (Node `process.platform` value).
|
|
12
|
+
* The Windows `run` carries an `<ASSET_URL>` placeholder the expander replaces
|
|
13
|
+
* with the resolved GitHub-release zip URL.
|
|
14
|
+
*/
|
|
15
|
+
export declare function selectMiseTemplate(platform: NodeJS.Platform): MiseTemplate;
|
|
16
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** mise Windows architecture slug used in release asset names. */
|
|
2
|
+
export type MiseWindowsArch = 'x64' | 'arm64';
|
|
3
|
+
interface GithubRelease {
|
|
4
|
+
assets: {
|
|
5
|
+
name: string;
|
|
6
|
+
browser_download_url: string;
|
|
7
|
+
}[];
|
|
8
|
+
}
|
|
9
|
+
/** Map a Windows `PROCESSOR_ARCHITECTURE` value to mise's asset arch slug. */
|
|
10
|
+
export declare function miseWindowsArch(processorArch: string | undefined): MiseWindowsArch;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the download URL of the latest mise standalone Windows zip for `arch`.
|
|
13
|
+
* `fetchJson` is injected (defaults to a real fetch) so the resolution is
|
|
14
|
+
* unit-testable without network.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveLatestMiseWindowsAsset(arch: MiseWindowsArch, fetchJson?: (url: string) => Promise<GithubRelease>): Promise<string>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=windows-install.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { GenericInitConfig } from '@kici-dev/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* A preset expander: clone root + typed config -> a concrete generic init config.
|
|
4
|
+
* Expanders may accept additional optional fields (e.g. an injected `platform`
|
|
5
|
+
* for tests); the agent path passes only `cloneRoot` + `config`.
|
|
6
|
+
*/
|
|
7
|
+
export interface PresetExpander<C> {
|
|
8
|
+
expand(args: {
|
|
9
|
+
cloneRoot: string;
|
|
10
|
+
config: C;
|
|
11
|
+
platform?: NodeJS.Platform;
|
|
12
|
+
}): Promise<GenericInitConfig>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The set of typed presets. Nix is added here (one row) once its provider lands.
|
|
16
|
+
*/
|
|
17
|
+
export declare const PRESET_REGISTRY: {
|
|
18
|
+
mise: {
|
|
19
|
+
expand(args: import("./mise/expander.js").MiseExpandArgs): Promise<GenericInitConfig>;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export type PresetName = keyof typeof PRESET_REGISTRY;
|
|
23
|
+
/**
|
|
24
|
+
* Ordered auto-detect table: `init: 'auto'` tries each row against the clone
|
|
25
|
+
* root and accumulates matches in this order. (nix row added with its provider.)
|
|
26
|
+
*/
|
|
27
|
+
export declare const AUTO_DETECT_TABLE: {
|
|
28
|
+
markers: string[];
|
|
29
|
+
preset: PresetName;
|
|
30
|
+
}[];
|
|
31
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Workflow } from '@kici-dev/sdk';
|
|
2
|
+
import { type MatrixValues } from '@kici-dev/engine';
|
|
2
3
|
/**
|
|
3
4
|
* Result of evaluating dynamic fields on a job.
|
|
4
5
|
* Only fields that were flagged as dynamic and successfully resolved are set.
|
|
@@ -7,6 +8,11 @@ export interface InitResult {
|
|
|
7
8
|
environmentName?: string;
|
|
8
9
|
env?: Record<string, string>;
|
|
9
10
|
concurrencyGroup?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Resolved matrix combinations when the job's matrix is a dynamic function.
|
|
13
|
+
* The orchestrator re-materializes these into N execution jobs at dispatch.
|
|
14
|
+
*/
|
|
15
|
+
matrixValues?: MatrixValues[];
|
|
10
16
|
}
|
|
11
17
|
/**
|
|
12
18
|
* Evaluate dynamic fields (environment, env, concurrencyGroup) on a job.
|
|
@@ -29,5 +35,6 @@ export declare function evaluateDynamicFields(workflow: Workflow, jobName: strin
|
|
|
29
35
|
dynamicEnvironment: boolean;
|
|
30
36
|
dynamicEnv: boolean;
|
|
31
37
|
dynamicConcurrencyGroup: boolean;
|
|
38
|
+
dynamicMatrix?: boolean;
|
|
32
39
|
}, timeoutMs?: number): Promise<InitResult>;
|
|
33
40
|
//# sourceMappingURL=init-runner.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentToOrchestratorMessage, JobDispatch } from '@kici-dev/engine';
|
|
2
2
|
import type { AppConfig } from '../config.js';
|
|
3
|
-
import type { CacheRequestIpc, CacheResponseIpc } from './sandbox/index.js';
|
|
3
|
+
import type { CacheRequestIpc, CacheResponseIpc, ProvenanceRequestIpc, ProvenanceResponseIpc, StepApprovalRequestIpc, StepApprovalResolvedIpc } from './sandbox/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Dependencies injected into JobRunner.
|
|
6
6
|
*/
|
|
@@ -91,6 +91,21 @@ export interface JobRunnerDeps {
|
|
|
91
91
|
* Optional for backward compatibility (callers that don't support the cache).
|
|
92
92
|
*/
|
|
93
93
|
requestUserCache?: (jobId: string, request: CacheRequestIpc) => Promise<CacheResponseIpc>;
|
|
94
|
+
/**
|
|
95
|
+
* Relay a provenance bundle upload operation to the orchestrator and await the
|
|
96
|
+
* response. Translates the sandbox `provenance.request` IPC into the matching
|
|
97
|
+
* `provenance.upload.request` / `.complete` WS message. Optional for backward
|
|
98
|
+
* compatibility (callers that don't support provenance).
|
|
99
|
+
*/
|
|
100
|
+
relayProvenance?: (jobId: string, request: ProvenanceRequestIpc) => Promise<ProvenanceResponseIpc>;
|
|
101
|
+
/**
|
|
102
|
+
* Relay a step-level approval request to the orchestrator and await the
|
|
103
|
+
* resolution. Translates the sandbox `approval.request` IPC into a
|
|
104
|
+
* `step.approval-request` WS message and returns the orchestrator's
|
|
105
|
+
* `step.approval-resolved` mapped onto the IPC response shape. Optional for
|
|
106
|
+
* backward compatibility (callers that don't support approvals).
|
|
107
|
+
*/
|
|
108
|
+
sendStepApproval?: (runId: string, jobId: string, request: StepApprovalRequestIpc) => Promise<StepApprovalResolvedIpc>;
|
|
94
109
|
}
|
|
95
110
|
interface ActiveJob {
|
|
96
111
|
abortController: AbortController;
|
|
@@ -125,6 +140,8 @@ export declare class JobRunner {
|
|
|
125
140
|
private readonly _sendConcurrencyReport;
|
|
126
141
|
private readonly _sendApiRequest?;
|
|
127
142
|
private readonly _requestUserCache?;
|
|
143
|
+
private readonly _relayProvenance?;
|
|
144
|
+
private readonly _sendStepApproval?;
|
|
128
145
|
/** Tracks running jobs for concurrency and cancellation */
|
|
129
146
|
readonly activeJobs: Map<string, ActiveJob>;
|
|
130
147
|
/** Active sandbox for the current job (used for abort). */
|
|
@@ -31,6 +31,8 @@ export interface ApplyEnvDeltaOptions {
|
|
|
31
31
|
target?: NodeJS.ProcessEnv;
|
|
32
32
|
/** Invoked once per rejected key (e.g. to emit a masked log warning). */
|
|
33
33
|
onReject?: (key: string) => void;
|
|
34
|
+
/** PATH list separator. Defaults to the platform separator (';' on Windows, ':' elsewhere). */
|
|
35
|
+
pathSeparator?: string;
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* Apply an environment delta to `target` (defaults to process.env), honoring the
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* import { BareMetalSandbox, ContainerSandbox, buildSanitizedEnv } from './sandbox/index.js';
|
|
6
6
|
*/
|
|
7
7
|
export type { ExecutionSandbox, SandboxSetupOptions, JobExecutionOptions, JobExecutionResult, SandboxStepResult, } from './types.js';
|
|
8
|
-
export type { RunnerToAgentMessage, AgentToRunnerMessage, EventEmitRequest, EventEmitResponse, CacheRequestIpc, CacheResponseIpc, JobExecutionRequest, } from './ipc-protocol.js';
|
|
8
|
+
export type { RunnerToAgentMessage, AgentToRunnerMessage, EventEmitRequest, EventEmitResponse, CacheRequestIpc, CacheResponseIpc, ProvenanceRequestIpc, ProvenanceResponseIpc, StepApprovalRequestIpc, StepApprovalResolvedIpc, JobExecutionRequest, } from './ipc-protocol.js';
|
|
9
9
|
export { buildSanitizedEnv } from './env-sanitizer.js';
|
|
10
10
|
export { ALLOWED_SYSTEM_VARS, KICI_AGENT_ENV_PREFIX, AGENT_REQUIRED_KICI_VARS, } from '@kici-dev/engine';
|
|
11
11
|
export { BareMetalSandbox } from './bare-metal-sandbox.js';
|
|
@@ -159,7 +159,54 @@ export interface CacheRequestIpc {
|
|
|
159
159
|
/** Tarball size in bytes (drives quota accounting). `completeSave` only. */
|
|
160
160
|
sizeBytes?: number;
|
|
161
161
|
}
|
|
162
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Request a step-level approval hold (runner -> agent). The sandbox runner
|
|
164
|
+
* blocks the step loop before a `requireApproval` step; the agent relays this
|
|
165
|
+
* as a `step.approval-request` WS message and pipes the orchestrator's
|
|
166
|
+
* resolution back as a {@link StepApprovalResolvedIpc}. Mirrors the
|
|
167
|
+
* {@link CacheRequestIpc} relay pattern.
|
|
168
|
+
*/
|
|
169
|
+
export interface StepApprovalRequestIpc {
|
|
170
|
+
type: 'approval.request';
|
|
171
|
+
/** UUID for correlating the response. */
|
|
172
|
+
requestId: string;
|
|
173
|
+
/** Step index within the job. */
|
|
174
|
+
stepIndex: number;
|
|
175
|
+
/** Step name (for the hold reason / logs). */
|
|
176
|
+
stepName: string;
|
|
177
|
+
/** AND-list of approver clauses (empty = any approval-capable member). */
|
|
178
|
+
clauses: Array<{
|
|
179
|
+
team: string;
|
|
180
|
+
} | {
|
|
181
|
+
user: string;
|
|
182
|
+
}>;
|
|
183
|
+
/** Human label for the gate. */
|
|
184
|
+
reason: string;
|
|
185
|
+
/** Per-gate timeout override (seconds) from the SDK `requireApproval.timeout`. */
|
|
186
|
+
timeoutSeconds?: number;
|
|
187
|
+
}
|
|
188
|
+
/** Which provenance upload operation to relay. */
|
|
189
|
+
export type ProvenanceRequestOp = 'requestUploadUrl' | 'complete';
|
|
190
|
+
/**
|
|
191
|
+
* Request a provenance bundle upload operation (runner -> agent). The agent
|
|
192
|
+
* relays it over the WS as a `provenance.upload.request` / `.complete` and pipes
|
|
193
|
+
* the response back as a {@link ProvenanceResponseIpc}. Mirrors the
|
|
194
|
+
* {@link CacheRequestIpc} relay pattern.
|
|
195
|
+
*/
|
|
196
|
+
export interface ProvenanceRequestIpc {
|
|
197
|
+
type: 'provenance.request';
|
|
198
|
+
/** UUID for correlating the response. */
|
|
199
|
+
requestId: string;
|
|
200
|
+
/** Which provenance operation to perform. */
|
|
201
|
+
op: ProvenanceRequestOp;
|
|
202
|
+
/** Primary subject digest (lowercase hex) — the storage-key discriminator. */
|
|
203
|
+
subjectDigest: string;
|
|
204
|
+
/** Caller-supplied artifact name. `complete` only. */
|
|
205
|
+
subjectName?: string;
|
|
206
|
+
/** Bundle media type. `complete` only. */
|
|
207
|
+
mediaType?: string;
|
|
208
|
+
}
|
|
209
|
+
export type RunnerToAgentMessage = ReadyMessage | StepStartMessage | StepCompleteMessage | LogLineMessage | StepSecretMountMessage | JobCompleteMessage | EventEmitRequest | ConcurrencyReportMessage | AgentApiRequestIpc | CacheRequestIpc | ProvenanceRequestIpc | StepApprovalRequestIpc;
|
|
163
210
|
/** Instruct the workflow runner to execute a job. */
|
|
164
211
|
interface ExecuteMessage {
|
|
165
212
|
type: 'execute';
|
|
@@ -233,7 +280,38 @@ export interface CacheResponseIpc {
|
|
|
233
280
|
/** Error description (present when the relay or orchestrator failed). */
|
|
234
281
|
error?: string;
|
|
235
282
|
}
|
|
236
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Resolution of a step-level approval hold (agent -> runner). Relayed from the
|
|
285
|
+
* orchestrator's `step.approval-resolved` WS message. On `approved` the runner
|
|
286
|
+
* runs the step; on `rejected`/`expired` it fails the job. `error` is set when
|
|
287
|
+
* the relay itself failed (treated as a fail-closed reject by the runner).
|
|
288
|
+
*/
|
|
289
|
+
export interface StepApprovalResolvedIpc {
|
|
290
|
+
type: 'approval.resolved';
|
|
291
|
+
/** Matches the original request's requestId. */
|
|
292
|
+
requestId: string;
|
|
293
|
+
/** Outcome of the hold. */
|
|
294
|
+
outcome?: 'approved' | 'rejected' | 'expired';
|
|
295
|
+
/** Optional human reason (e.g. the reject reason). */
|
|
296
|
+
reason?: string;
|
|
297
|
+
/** Error description (present when the relay or orchestrator failed). */
|
|
298
|
+
error?: string;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Response to a {@link ProvenanceRequestIpc} (agent -> runner). `requestUploadUrl`
|
|
302
|
+
* resolves with `uploadUrl`; `complete` resolves with an empty (no-field)
|
|
303
|
+
* response. `error` is set when the relay or orchestrator failed.
|
|
304
|
+
*/
|
|
305
|
+
export interface ProvenanceResponseIpc {
|
|
306
|
+
type: 'provenance.response';
|
|
307
|
+
/** Matches the original request's requestId. */
|
|
308
|
+
requestId: string;
|
|
309
|
+
/** Presigned PUT URL for the bundle. `requestUploadUrl` only. */
|
|
310
|
+
uploadUrl?: string;
|
|
311
|
+
/** Error description (present when the relay or orchestrator failed). */
|
|
312
|
+
error?: string;
|
|
313
|
+
}
|
|
314
|
+
export type AgentToRunnerMessage = ExecuteMessage | AbortMessage | EventEmitResponse | ConcurrencyAckMessage | AgentApiResponseIpc | CacheResponseIpc | ProvenanceResponseIpc | StepApprovalResolvedIpc;
|
|
237
315
|
/**
|
|
238
316
|
* All data the workflow runner needs to execute a job inside the sandbox.
|
|
239
317
|
*
|
|
@@ -241,6 +319,17 @@ export type AgentToRunnerMessage = ExecuteMessage | AbortMessage | EventEmitResp
|
|
|
241
319
|
* The runner uses this to clone, install deps, compile, and execute steps.
|
|
242
320
|
*/
|
|
243
321
|
export interface JobExecutionRequest {
|
|
322
|
+
/**
|
|
323
|
+
* Run UUID. Threaded into the step context so the OIDC token relay can name
|
|
324
|
+
* the job/run a request is bound to. Correlation only — the orchestrator
|
|
325
|
+
* re-derives ownership and the runId from its own dispatch state.
|
|
326
|
+
*/
|
|
327
|
+
runId: string;
|
|
328
|
+
/**
|
|
329
|
+
* Job UUID. Sent with `ctx.kici.oidc.token()` requests so the orchestrator
|
|
330
|
+
* can verify the agent owns this job before relaying a mint request.
|
|
331
|
+
*/
|
|
332
|
+
jobId: string;
|
|
244
333
|
/** Working directory inside the sandbox (e.g. /workspace). */
|
|
245
334
|
workDir: string;
|
|
246
335
|
/** Repository URL for git clone. */
|
|
@@ -277,10 +366,19 @@ export interface JobExecutionRequest {
|
|
|
277
366
|
depsHash?: string;
|
|
278
367
|
/** Workflow name to execute. */
|
|
279
368
|
workflowName: string;
|
|
280
|
-
/**
|
|
369
|
+
/**
|
|
370
|
+
* Job name used to locate the job in the compiled workflow and to populate
|
|
371
|
+
* `ctx.job.name`. For a matrix child this is the BASE job name (the job is
|
|
372
|
+
* defined once in source); the combination is exposed only via `ctx.matrix`.
|
|
373
|
+
*/
|
|
281
374
|
jobName: string;
|
|
282
375
|
/** Runs-on label for the job. */
|
|
283
376
|
runsOn: string;
|
|
377
|
+
/**
|
|
378
|
+
* Matrix combination values for this child (e.g. `{ variant: 'a' }`), exposed
|
|
379
|
+
* to steps as `ctx.matrix`. Absent for non-matrix jobs.
|
|
380
|
+
*/
|
|
381
|
+
matrixValues?: Record<string, unknown>;
|
|
284
382
|
/** Secrets to merge into step environment (highest precedence). */
|
|
285
383
|
secrets?: Record<string, string>;
|
|
286
384
|
/** Namespaced secrets by context name for ctx.secrets['context-name'].KEY access. */
|
|
@@ -19,7 +19,7 @@ export interface JobHooks {
|
|
|
19
19
|
cleanup?: HookInput;
|
|
20
20
|
}
|
|
21
21
|
/** Options for the step execution loop. */
|
|
22
|
-
interface StepLoopOptions {
|
|
22
|
+
export interface StepLoopOptions {
|
|
23
23
|
steps: Step[];
|
|
24
24
|
/** Factory that creates a StepContext for a given step index and name. */
|
|
25
25
|
createStepContext: (stepIndex: number, stepName: string) => StepContext;
|
|
@@ -83,6 +83,29 @@ interface StepLoopOptions {
|
|
|
83
83
|
* them for the next step. Never throws -- errors are logged by the wired impl.
|
|
84
84
|
*/
|
|
85
85
|
afterStepApplyEnvFiles?: () => Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Block a `requireApproval` step pending an orchestrator-side approval hold.
|
|
88
|
+
* The runner sends the normalized requirement and awaits the resolution; the
|
|
89
|
+
* agent keeps job heartbeats flowing during the wait so the agent isn't
|
|
90
|
+
* reaped. Absent ⇒ approvals are not gated (CT / unit harnesses) and steps
|
|
91
|
+
* run unconditionally.
|
|
92
|
+
*/
|
|
93
|
+
awaitStepApproval?: (req: {
|
|
94
|
+
stepIndex: number;
|
|
95
|
+
stepName: string;
|
|
96
|
+
clauses: Array<{
|
|
97
|
+
team: string;
|
|
98
|
+
} | {
|
|
99
|
+
user: string;
|
|
100
|
+
}>;
|
|
101
|
+
reason: string;
|
|
102
|
+
timeoutSeconds?: number;
|
|
103
|
+
}) => Promise<StepApprovalResolution>;
|
|
104
|
+
}
|
|
105
|
+
/** Outcome of an awaited step-level approval hold. */
|
|
106
|
+
export interface StepApprovalResolution {
|
|
107
|
+
outcome: 'approved' | 'rejected' | 'expired';
|
|
108
|
+
reason?: string;
|
|
86
109
|
}
|
|
87
110
|
/** Result of the step execution loop. */
|
|
88
111
|
interface StepLoopResult {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JobDispatch } from '@kici-dev/engine';
|
|
2
|
-
import type { EventEmitRequest, EventEmitResponse, ConcurrencyReportMessage, ConcurrencyAckMessage, CacheRequestIpc, CacheResponseIpc } from './ipc-protocol.js';
|
|
2
|
+
import type { EventEmitRequest, EventEmitResponse, ConcurrencyReportMessage, ConcurrencyAckMessage, CacheRequestIpc, CacheResponseIpc, ProvenanceRequestIpc, ProvenanceResponseIpc, StepApprovalRequestIpc, StepApprovalResolvedIpc } from './ipc-protocol.js';
|
|
3
3
|
/**
|
|
4
4
|
* Common interface for all execution sandbox backends.
|
|
5
5
|
*
|
|
@@ -89,6 +89,23 @@ export interface JobExecutionOptions {
|
|
|
89
89
|
* working — the runner falls back to a "not configured" cache response.
|
|
90
90
|
*/
|
|
91
91
|
onCacheRequest?: (request: CacheRequestIpc) => Promise<CacheResponseIpc>;
|
|
92
|
+
/**
|
|
93
|
+
* Callback for relaying a provenance bundle upload request from the sandbox to
|
|
94
|
+
* the orchestrator. The sandbox runner sends `provenance.request` IPC; the
|
|
95
|
+
* agent wraps it in the matching `provenance.upload.*` WS message and forwards
|
|
96
|
+
* to the orchestrator. Optional so harnesses that don't thread provenance keep
|
|
97
|
+
* working — the runner falls back to a "not configured" error response.
|
|
98
|
+
*/
|
|
99
|
+
onProvenanceRequest?: (request: ProvenanceRequestIpc) => Promise<ProvenanceResponseIpc>;
|
|
100
|
+
/**
|
|
101
|
+
* Callback for relaying a step-level approval request from the sandbox to the
|
|
102
|
+
* orchestrator. The sandbox runner sends `approval.request` IPC; the agent
|
|
103
|
+
* wraps it in a `step.approval-request` WS message and forwards to the
|
|
104
|
+
* orchestrator, awaiting the `step.approval-resolved` response which it pipes
|
|
105
|
+
* back as `approval.resolved`. Optional so harnesses that don't thread
|
|
106
|
+
* approvals keep working — the runner falls back to a fail-closed reject.
|
|
107
|
+
*/
|
|
108
|
+
onApprovalRequest?: (request: StepApprovalRequestIpc) => Promise<StepApprovalResolvedIpc>;
|
|
92
109
|
/**
|
|
93
110
|
* Callback fired once per `ctx.secrets.mountFile` / `exposeFile` call the
|
|
94
111
|
* workflow runner performs. Carries only key names + the resulting path /
|
|
@@ -13,13 +13,18 @@
|
|
|
13
13
|
* This file is compiled alongside the agent by rolldown (existing build), but
|
|
14
14
|
* runs as a SEPARATE process spawned by the sandbox backend.
|
|
15
15
|
*/
|
|
16
|
-
import type {
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
import type { StepContext } from '@kici-dev/sdk';
|
|
17
|
+
import type { OutputsMap, StepRefMap, TrackedStepSecrets } from '@kici-dev/sdk';
|
|
18
|
+
import type { RunnerToAgentMessage, JobExecutionRequest } from './ipc-protocol.js';
|
|
19
|
+
import { LogMasker } from './log-masker.js';
|
|
19
20
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Create a StepContext natively inside the workflow runner.
|
|
22
|
+
*
|
|
23
|
+
* The context is reconstructed from the environment and IPC request fields --
|
|
24
|
+
* NOT serialized across the process boundary. This means zx $ runs natively
|
|
25
|
+
* inside this process with full shell access.
|
|
23
26
|
*/
|
|
24
|
-
export declare function
|
|
27
|
+
export declare function createSandboxStepContext(workDir: string, stepIndex: number, stepName: string, request: JobExecutionRequest, maskedSendFn: (msg: RunnerToAgentMessage) => void, outputsMap: OutputsMap, refMap: StepRefMap, operatorSecretKeys: Set<string>, secretOutputs: Map<string, string>, jobOutputsMap: OutputsMap, secrets: TrackedStepSecrets, masker: LogMasker): StepContext;
|
|
28
|
+
/** Raw provider webhook body for ctx.rawPayload — nested in the envelope. */
|
|
29
|
+
export declare function rawPayloadFromEvent(event: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
|
|
25
30
|
//# sourceMappingURL=workflow-runner.d.ts.map
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
* clones the whole repo, so an in-repo sibling is present), and resolves
|
|
15
15
|
* `file:`/`link:`/`portal:` against a path — allowed when that path stays
|
|
16
16
|
* inside the cloned repo, rejected when it escapes the clone.
|
|
17
|
+
* - yarn classic (v1) has no `workspace:` protocol and no `portal:` — it links
|
|
18
|
+
* in-repo siblings by version range, not by a local specifier — so both are
|
|
19
|
+
* rejected with guidance; `file:`/`link:` are allowed when the path stays
|
|
20
|
+
* inside the clone, rejected when it escapes. (yarn berry is not yet
|
|
21
|
+
* supported.)
|
|
17
22
|
*
|
|
18
23
|
* This module performs that classification so unresolvable specifiers fail
|
|
19
24
|
* fast with guidance rather than a cryptic install error.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-repo workspace-sibling discovery for the agent's dependency handling.
|
|
3
|
+
*
|
|
4
|
+
* A pnpm or yarn-classic workspace lays out a `.kici/` member's `workspace:`
|
|
5
|
+
* (pnpm) or version-range (yarn) siblings as symlinks pointing at package
|
|
6
|
+
* directories that live inside the clone but outside `.kici/` and outside the
|
|
7
|
+
* `node_modules` store. The dep-cache packer must travel those sibling dirs with
|
|
8
|
+
* the closure (their symlinks would dangle otherwise), and the yarn install path
|
|
9
|
+
* must build them (the install links a sibling but does not build it).
|
|
10
|
+
*
|
|
11
|
+
* `collectInRepoSiblings` walks a starting `node_modules` (and transitively each
|
|
12
|
+
* discovered sibling's `node_modules`), returning each in-repo sibling directory
|
|
13
|
+
* once, repo-root-relative, in breadth-first discovery order. The starting
|
|
14
|
+
* `node_modules` is a parameter so it serves pnpm + yarn-standalone (seeded at
|
|
15
|
+
* `.kici/node_modules`) and yarn-workspace-member (seeded at the hoisted root
|
|
16
|
+
* `node_modules`).
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The directory yarn lays `.kici`'s dependencies into. A standalone `.kici`
|
|
20
|
+
* (own lockfile, no parent workspace) gets `.kici/node_modules`; a workspace
|
|
21
|
+
* member hoists everything to the repo-root `node_modules`, leaving no
|
|
22
|
+
* `.kici/node_modules`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveYarnNodeModulesRoot(repoRoot: string, kiciDir: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Walk `seedNodeModules` (and transitively each in-repo sibling's
|
|
27
|
+
* `node_modules`) collecting the repo-root-relative directories of workspace
|
|
28
|
+
* siblings — package dirs that live inside the clone but outside `.kici/` and
|
|
29
|
+
* outside the repo-root `node_modules/` store. Returns each dir once, in
|
|
30
|
+
* discovery (BFS) order.
|
|
31
|
+
*/
|
|
32
|
+
export declare function collectInRepoSiblings(workDir: string, kiciDir: string, seedNodeModules?: string): Promise<string[]>;
|
|
33
|
+
//# sourceMappingURL=workspace-siblings.d.ts.map
|