@kici-dev/agent 0.1.17 → 0.1.19
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/execution/dep-installer.d.ts +9 -4
- package/dist/execution/dep-packer.d.ts +8 -5
- package/dist/execution/sandbox/ipc-protocol.d.ts +23 -0
- package/dist/execution/validate-kici-deps.d.ts +7 -4
- package/dist/execution/workflow-loader.d.ts +5 -1
- package/dist/execution/yarnrc-berry-config.d.ts +23 -0
- package/dist/index.js +217 -28
- package/dist/provenance/attest.d.ts +9 -1
- package/dist/server.js +277 -80
- package/dist/workflow-runner.js +238 -37
- package/package.json +13 -12
- package/sbom.spdx.json +2551 -6049
package/dist/server.js
CHANGED
|
@@ -15,8 +15,9 @@ import { LOGGER_ENV_VARS, defineEnv, validateUnknownKiciVars } from "@kici-dev/s
|
|
|
15
15
|
import { ALLOWED_SYSTEM_VARS, CacheRunEventType, CacheStepType, ExecutionJobStatus, ExecutionStepStatus, InitFailureCategory, KNOWN_ROLES, PROTOCOL_VERSION, SANDBOX_DEFAULT_VARS, WS_CLOSE_AGENT_AUTH_FAILED, WS_MAX_PAYLOAD_BYTES, applyIncludeExclude, deriveOsArchLabels, expandMatrix, heartbeatSchema, hostLabel, mergeAutoLabels, orchestratorToAgentMessageSchema, resolveRoleLabels, validateNoReservedLabels } from "@kici-dev/engine";
|
|
16
16
|
import { execFile, execFileSync, execSync, fork, spawn } from "node:child_process";
|
|
17
17
|
import WebSocket from "ws";
|
|
18
|
-
import
|
|
18
|
+
import * as fs$2 from "node:fs";
|
|
19
19
|
import fs, { existsSync } from "node:fs";
|
|
20
|
+
import { ZipArchive } from "archiver";
|
|
20
21
|
import path, { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
21
22
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
22
23
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -24,13 +25,15 @@ import { format, promisify } from "node:util";
|
|
|
24
25
|
import { gcStaleTmpDirs } from "@kici-dev/core/tmp-gc";
|
|
25
26
|
import fs$1, { access, lstat, mkdir, mkdtemp, readFile, readdir, realpath, rm, unlink, writeFile } from "node:fs/promises";
|
|
26
27
|
import Docker from "dockerode";
|
|
27
|
-
import { buildKiciApi, isDynamicGroupRef, isDynamicJobFn, isStaticArray, isStaticObject } from "@kici-dev/sdk";
|
|
28
|
+
import { buildKiciApi, buildNeedsContext, isDynamicGroupRef, isDynamicJobFn, isStaticArray, isStaticObject } from "@kici-dev/sdk";
|
|
28
29
|
import { c, x } from "tar";
|
|
29
30
|
import https from "node:https";
|
|
30
31
|
import http from "node:http";
|
|
31
32
|
import { pipeline } from "node:stream/promises";
|
|
32
33
|
import { createGunzip } from "node:zlib";
|
|
33
|
-
import {
|
|
34
|
+
import { normalizeRunsOnToMatchers } from "@kici-dev/engine/labels/compile";
|
|
35
|
+
import { PNPM_IGNORE_BUILD_GATE_ARG, PackageManager, YarnFlavor, detectPackageManagerFromManifests, detectYarnFlavor } from "@kici-dev/shared/package-manager";
|
|
36
|
+
import { parse, stringify } from "yaml";
|
|
34
37
|
import { createInterface } from "node:readline";
|
|
35
38
|
var __defProp = Object.defineProperty;
|
|
36
39
|
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -189,7 +192,7 @@ function agentClientConnectionOptions(config) {
|
|
|
189
192
|
* lean subset of the orchestrator's createDebugBundle.
|
|
190
193
|
*/
|
|
191
194
|
async function buildAgentMiniBundle(opts) {
|
|
192
|
-
const archive =
|
|
195
|
+
const archive = new ZipArchive({ zlib: { level: 6 } });
|
|
193
196
|
const chunks = [];
|
|
194
197
|
archive.on("data", (d) => chunks.push(d));
|
|
195
198
|
const done = new Promise((resolve, reject) => {
|
|
@@ -213,7 +216,7 @@ async function buildAgentMiniBundle(opts) {
|
|
|
213
216
|
uptime: os$1.uptime()
|
|
214
217
|
}, null, 2), { name: "system/info.json" });
|
|
215
218
|
if (opts.metricsText) archive.append(opts.metricsText, { name: "system/metrics.txt" });
|
|
216
|
-
if (opts.logDir) await addLogsToArchive(archive, opts.logDir, opts.logWindowHours);
|
|
219
|
+
if (opts.logDir && fs$2.existsSync(opts.logDir)) await addLogsToArchive(archive, opts.logDir, opts.logWindowHours);
|
|
217
220
|
await archive.finalize();
|
|
218
221
|
await done;
|
|
219
222
|
return Buffer.concat(chunks);
|
|
@@ -1297,14 +1300,14 @@ var init_console_capture = __esmMin((() => {
|
|
|
1297
1300
|
init_console_capture();
|
|
1298
1301
|
function safe(name, fallback = "unknown") {
|
|
1299
1302
|
switch (name) {
|
|
1300
|
-
case "version": return "0.1.
|
|
1301
|
-
case "buildCommit": return "
|
|
1302
|
-
case "sdkVersion": return "0.1.
|
|
1303
|
-
case "sdkBundleHash": return "
|
|
1304
|
-
case "sharedVersion": return "0.1.
|
|
1305
|
-
case "sharedBundleHash": return "
|
|
1306
|
-
case "engineVersion": return "0.1.
|
|
1307
|
-
case "engineBundleHash": return "
|
|
1303
|
+
case "version": return "0.1.19";
|
|
1304
|
+
case "buildCommit": return "1590f5e99";
|
|
1305
|
+
case "sdkVersion": return "0.1.19";
|
|
1306
|
+
case "sdkBundleHash": return "8308089347c304e41b457d3867b17bbff11d6b5cd9706b6823e7abdbd849f33f";
|
|
1307
|
+
case "sharedVersion": return "0.1.19";
|
|
1308
|
+
case "sharedBundleHash": return "5f2c220f24d166b0f13d0620a2e80d19689ac8b683a12154daef44e938fd46a7";
|
|
1309
|
+
case "engineVersion": return "0.1.19";
|
|
1310
|
+
case "engineBundleHash": return "79ce14640d1798eaaa7cb3aa6c4bc325da3bff1e9f4716936e19614eabb1d858";
|
|
1308
1311
|
default: return fallback;
|
|
1309
1312
|
}
|
|
1310
1313
|
}
|
|
@@ -1949,18 +1952,20 @@ function extractSteps(workflow, jobName) {
|
|
|
1949
1952
|
* A sibling mismatch logs a warning; a missing target job throws a clear
|
|
1950
1953
|
* determinism error.
|
|
1951
1954
|
*/
|
|
1952
|
-
async function extractStepsFromDynamicJob(workflow, dynamicIndex, jobName, event, env, apiTransport, expectedJobNames) {
|
|
1955
|
+
async function extractStepsFromDynamicJob(workflow, dynamicIndex, jobName, event, env, apiTransport, expectedJobNames, upstreamSnapshot, declaredNeeds) {
|
|
1953
1956
|
const dynamicFn = extractDynamicJobFn(workflow, dynamicIndex);
|
|
1954
1957
|
const { $ } = await import("zx");
|
|
1955
1958
|
const { createLogger } = await import("@kici-dev/shared");
|
|
1956
|
-
const { buildKiciApi } = await import("@kici-dev/sdk");
|
|
1959
|
+
const { buildKiciApi, buildNeedsContext } = await import("@kici-dev/sdk");
|
|
1957
1960
|
const log = createLogger({ prefix: `dynamic-job-fn:${workflow.name}` });
|
|
1958
1961
|
const kici = buildKiciApi(apiTransport ?? (() => Promise.reject(/* @__PURE__ */ new Error("Agent API not available during re-evaluation"))));
|
|
1962
|
+
const needs = upstreamSnapshot ? buildNeedsContext(upstreamSnapshot, declaredNeeds ?? []) : void 0;
|
|
1959
1963
|
const generatedJobs = await dynamicFn({
|
|
1960
1964
|
$,
|
|
1961
1965
|
ctx: {
|
|
1962
1966
|
workflow: { name: workflow.name },
|
|
1963
|
-
event
|
|
1967
|
+
event,
|
|
1968
|
+
...needs && { needs }
|
|
1964
1969
|
},
|
|
1965
1970
|
log,
|
|
1966
1971
|
env,
|
|
@@ -1988,8 +1993,8 @@ async function extractStepsFromDynamicJob(workflow, dynamicIndex, jobName, event
|
|
|
1988
1993
|
}
|
|
1989
1994
|
var AGENT_SDK_VERSION, AGENT_SDK_BUNDLE_HASH, hookRegistered;
|
|
1990
1995
|
var init_workflow_loader = __esmMin((() => {
|
|
1991
|
-
AGENT_SDK_VERSION = "0.1.
|
|
1992
|
-
AGENT_SDK_BUNDLE_HASH = "
|
|
1996
|
+
AGENT_SDK_VERSION = "0.1.19";
|
|
1997
|
+
AGENT_SDK_BUNDLE_HASH = "8308089347c304e41b457d3867b17bbff11d6b5cd9706b6823e7abdbd849f33f";
|
|
1993
1998
|
hookRegistered = false;
|
|
1994
1999
|
}));
|
|
1995
2000
|
//#endregion
|
|
@@ -2496,7 +2501,7 @@ async function serializeJobsToLock(jobs, ctx, staticNames, allowedGroups) {
|
|
|
2496
2501
|
return result;
|
|
2497
2502
|
}
|
|
2498
2503
|
async function serializeJob(job, generatedNames, ctx, staticNames, allowedGroups) {
|
|
2499
|
-
const { runsOn, excludeLabels } =
|
|
2504
|
+
const { include: runsOn, exclude: excludeLabels } = normalizeRunsOnToMatchers(job.runsOn, `generated job '${job.name}' runsOn`);
|
|
2500
2505
|
let resolvedEnvironment;
|
|
2501
2506
|
if (typeof job.environment === "function") {
|
|
2502
2507
|
const value = await withTimeout(() => job.environment(ctx.event), DYNAMIC_FIELD_TIMEOUT_MS, `dynamic environment for generated job '${job.name}'`);
|
|
@@ -2519,7 +2524,7 @@ async function serializeJob(job, generatedNames, ctx, staticNames, allowedGroups
|
|
|
2519
2524
|
_type: "static",
|
|
2520
2525
|
name: job.name,
|
|
2521
2526
|
runsOn,
|
|
2522
|
-
...excludeLabels ? { excludeLabels } : {},
|
|
2527
|
+
...excludeLabels.length > 0 ? { excludeLabels } : {},
|
|
2523
2528
|
needs: resolvedNeeds,
|
|
2524
2529
|
...dependsOnGroups.length > 0 ? { dependsOnGroups } : {},
|
|
2525
2530
|
steps: serializeSteps(job.steps),
|
|
@@ -2533,20 +2538,6 @@ async function serializeJob(job, generatedNames, ctx, staticNames, allowedGroups
|
|
|
2533
2538
|
};
|
|
2534
2539
|
}
|
|
2535
2540
|
/**
|
|
2536
|
-
* Normalize the polymorphic RunsOn type into the lock file format.
|
|
2537
|
-
*/
|
|
2538
|
-
function normalizeRunsOn(runsOn) {
|
|
2539
|
-
if (typeof runsOn === "string") return { runsOn };
|
|
2540
|
-
if (Array.isArray(runsOn)) return { runsOn };
|
|
2541
|
-
const selector = runsOn;
|
|
2542
|
-
const labels = typeof selector.labels === "string" ? [selector.labels] : selector.labels;
|
|
2543
|
-
const exclude = selector.exclude ? typeof selector.exclude === "string" ? [selector.exclude] : selector.exclude : void 0;
|
|
2544
|
-
return {
|
|
2545
|
-
runsOn: labels,
|
|
2546
|
-
...exclude ? { excludeLabels: exclude } : {}
|
|
2547
|
-
};
|
|
2548
|
-
}
|
|
2549
|
-
/**
|
|
2550
2541
|
* Resolve needs references. Jobs can reference other jobs by name (string),
|
|
2551
2542
|
* Job object reference, DynamicGroupRef, or NeedsEntry/NeedsGroupEntry objects.
|
|
2552
2543
|
* Validates against generatedNames union staticNames union allowedGroups.
|
|
@@ -2632,7 +2623,7 @@ async function serializeMatrix(matrix, jobName, runsOn, ctx) {
|
|
|
2632
2623
|
workflow: { name: ctx.workflowName },
|
|
2633
2624
|
job: {
|
|
2634
2625
|
name: jobName,
|
|
2635
|
-
runsOn:
|
|
2626
|
+
runsOn: runsOn.map((m) => m.kind === "exact" ? m.value : `/${m.source}/${m.flags}`)
|
|
2636
2627
|
}
|
|
2637
2628
|
},
|
|
2638
2629
|
log: ctx.log,
|
|
@@ -3059,7 +3050,7 @@ function noopResult() {
|
|
|
3059
3050
|
};
|
|
3060
3051
|
}
|
|
3061
3052
|
/** Build the synthesized env-var name for registry index `i`. */
|
|
3062
|
-
function tokenEnvName(jobIdShort, index) {
|
|
3053
|
+
function tokenEnvName$1(jobIdShort, index) {
|
|
3063
3054
|
return `KICI_NPM_TOKEN_${jobIdShort}_${index}`;
|
|
3064
3055
|
}
|
|
3065
3056
|
/** Render the agent-managed block of `.npmrc` lines. */
|
|
@@ -3068,7 +3059,7 @@ function renderAgentLines(registries, jobIdShort) {
|
|
|
3068
3059
|
const lines = [];
|
|
3069
3060
|
for (let i = 0; i < registries.length; i++) {
|
|
3070
3061
|
const reg = registries[i];
|
|
3071
|
-
const envVar = tokenEnvName(jobIdShort, i);
|
|
3062
|
+
const envVar = tokenEnvName$1(jobIdShort, i);
|
|
3072
3063
|
const authKey = reg.url.replace(/^https?:/, "");
|
|
3073
3064
|
if (reg.scope) lines.push(`${reg.scope}:registry=${reg.url}`);
|
|
3074
3065
|
else lines.push(`registry=${reg.url}`);
|
|
@@ -3100,7 +3091,7 @@ async function applyNpmRegistryConfig(args) {
|
|
|
3100
3091
|
const tokenEnv = {};
|
|
3101
3092
|
const tokensForRedaction = [];
|
|
3102
3093
|
for (let i = 0; i < registries.length; i++) {
|
|
3103
|
-
tokenEnv[tokenEnvName(args.jobIdShort, i)] = registries[i].token;
|
|
3094
|
+
tokenEnv[tokenEnvName$1(args.jobIdShort, i)] = registries[i].token;
|
|
3104
3095
|
tokensForRedaction.push(registries[i].token);
|
|
3105
3096
|
}
|
|
3106
3097
|
for (const value of Object.values(installEnvSecrets)) if (value) tokensForRedaction.push(value);
|
|
@@ -3138,6 +3129,113 @@ function redactNpmOutput(input, tokens) {
|
|
|
3138
3129
|
}
|
|
3139
3130
|
var init_npm_registry_config = __esmMin((() => {}));
|
|
3140
3131
|
//#endregion
|
|
3132
|
+
//#region src/execution/yarnrc-berry-config.ts
|
|
3133
|
+
/**
|
|
3134
|
+
* Apply yarn-berry registry auth + a forced `nodeLinker: node-modules` to a
|
|
3135
|
+
* workflow's `.kici/.yarnrc.yml` for the lifetime of one `yarn install`, then
|
|
3136
|
+
* restore the file on cleanup. The berry analog of `npm-registry-config.ts`:
|
|
3137
|
+
* berry reads `.yarnrc.yml` (not `.npmrc`), so the auth block uses berry's
|
|
3138
|
+
* `npmRegistryServer` / `npmScopes` / `npmAuthToken` keys with `${VAR}`
|
|
3139
|
+
* env-var interpolation. Token bytes never reach disk — each registry token is
|
|
3140
|
+
* exposed as a job-scoped env var and the on-disk value is the `${VAR}`
|
|
3141
|
+
* reference.
|
|
3142
|
+
*
|
|
3143
|
+
* `nodeLinker: node-modules` makes berry lay down a real `node_modules` tree
|
|
3144
|
+
* (no PnP `.pnp.cjs`), so the agent's packer / restore / sibling-walk /
|
|
3145
|
+
* workflow-loader work unchanged. `enableScripts: false` (when a private
|
|
3146
|
+
* registry is configured) keeps dependency lifecycle scripts from seeing the
|
|
3147
|
+
* synthesized token env vars — the same security model as npm/pnpm/classic
|
|
3148
|
+
* `--ignore-scripts`.
|
|
3149
|
+
*
|
|
3150
|
+
* Reuses the same `ApplyNpmRegistryConfigArgs` / `ApplyNpmRegistryConfigResult`
|
|
3151
|
+
* shapes as the npm overlay so `dep-installer` can pick either by flavor.
|
|
3152
|
+
*/
|
|
3153
|
+
/** Build the synthesized env-var name for registry index `i`. */
|
|
3154
|
+
function tokenEnvName(jobIdShort, index) {
|
|
3155
|
+
return `KICI_NPM_TOKEN_${jobIdShort}_${index}`;
|
|
3156
|
+
}
|
|
3157
|
+
/** Read + parse an existing `.yarnrc.yml`, or `{}` when absent/empty. */
|
|
3158
|
+
async function readOriginalYarnrc(path) {
|
|
3159
|
+
try {
|
|
3160
|
+
const raw = await readFile(path, "utf8");
|
|
3161
|
+
return {
|
|
3162
|
+
raw,
|
|
3163
|
+
doc: parse(raw) ?? {}
|
|
3164
|
+
};
|
|
3165
|
+
} catch (err) {
|
|
3166
|
+
if (err.code === "ENOENT") return {
|
|
3167
|
+
raw: null,
|
|
3168
|
+
doc: {}
|
|
3169
|
+
};
|
|
3170
|
+
throw err;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
function buildRegistryBlock(envVar, url, alwaysAuth) {
|
|
3174
|
+
return {
|
|
3175
|
+
npmRegistryServer: url,
|
|
3176
|
+
npmAuthToken: `\${${envVar}}`,
|
|
3177
|
+
...alwaysAuth ? { npmAlwaysAuth: true } : {}
|
|
3178
|
+
};
|
|
3179
|
+
}
|
|
3180
|
+
async function applyYarnrcBerryConfig(args) {
|
|
3181
|
+
const registries = args.npmRegistries ?? [];
|
|
3182
|
+
const installEnvSecrets = args.installEnvSecrets ?? {};
|
|
3183
|
+
const hasPrivateRegistry = registries.length > 0 || Object.keys(installEnvSecrets).length > 0;
|
|
3184
|
+
const yarnrcPath = join(args.kiciDir, ".yarnrc.yml");
|
|
3185
|
+
const { raw: original, doc } = await readOriginalYarnrc(yarnrcPath);
|
|
3186
|
+
const cacheFolder = await mkdtemp(join(tmpdir(), "kici-yarn-berry-cache-"));
|
|
3187
|
+
const merged = {
|
|
3188
|
+
...doc,
|
|
3189
|
+
nodeLinker: "node-modules",
|
|
3190
|
+
enableGlobalCache: false,
|
|
3191
|
+
cacheFolder
|
|
3192
|
+
};
|
|
3193
|
+
const tokenEnv = {};
|
|
3194
|
+
const tokensForRedaction = [];
|
|
3195
|
+
if (hasPrivateRegistry) {
|
|
3196
|
+
merged.enableScripts = false;
|
|
3197
|
+
const npmScopes = { ...doc.npmScopes ?? {} };
|
|
3198
|
+
for (let i = 0; i < registries.length; i++) {
|
|
3199
|
+
const reg = registries[i];
|
|
3200
|
+
const envVar = tokenEnvName(args.jobIdShort, i);
|
|
3201
|
+
tokenEnv[envVar] = reg.token;
|
|
3202
|
+
tokensForRedaction.push(reg.token);
|
|
3203
|
+
const block = buildRegistryBlock(envVar, reg.url, reg.alwaysAuth);
|
|
3204
|
+
if (reg.scope) npmScopes[reg.scope] = block;
|
|
3205
|
+
else {
|
|
3206
|
+
merged.npmRegistryServer = reg.url;
|
|
3207
|
+
merged.npmAuthToken = block.npmAuthToken;
|
|
3208
|
+
if (reg.alwaysAuth) merged.npmAlwaysAuth = true;
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
if (Object.keys(npmScopes).length > 0) merged.npmScopes = npmScopes;
|
|
3212
|
+
for (const value of Object.values(installEnvSecrets)) if (value) tokensForRedaction.push(value);
|
|
3213
|
+
}
|
|
3214
|
+
await writeFile(yarnrcPath, stringify(merged), {
|
|
3215
|
+
encoding: "utf8",
|
|
3216
|
+
mode: 384
|
|
3217
|
+
});
|
|
3218
|
+
const cleanup = async () => {
|
|
3219
|
+
try {
|
|
3220
|
+
if (original === null) await unlink(yarnrcPath).catch(() => {});
|
|
3221
|
+
else await writeFile(yarnrcPath, original, { encoding: "utf8" });
|
|
3222
|
+
} catch {}
|
|
3223
|
+
await rm(cacheFolder, {
|
|
3224
|
+
recursive: true,
|
|
3225
|
+
force: true
|
|
3226
|
+
}).catch(() => {});
|
|
3227
|
+
};
|
|
3228
|
+
return {
|
|
3229
|
+
extraEnv: {
|
|
3230
|
+
...installEnvSecrets,
|
|
3231
|
+
...tokenEnv
|
|
3232
|
+
},
|
|
3233
|
+
tokensForRedaction,
|
|
3234
|
+
cleanup
|
|
3235
|
+
};
|
|
3236
|
+
}
|
|
3237
|
+
var init_yarnrc_berry_config = __esmMin((() => {}));
|
|
3238
|
+
//#endregion
|
|
3141
3239
|
//#region src/execution/validate-kici-deps.ts
|
|
3142
3240
|
/**
|
|
3143
3241
|
* Pre-install validation for `.kici/` dependency specifiers.
|
|
@@ -3158,8 +3256,10 @@ var init_npm_registry_config = __esmMin((() => {}));
|
|
|
3158
3256
|
* - yarn classic (v1) has no `workspace:` protocol and no `portal:` — it links
|
|
3159
3257
|
* in-repo siblings by version range, not by a local specifier — so both are
|
|
3160
3258
|
* rejected with guidance; `file:`/`link:` are allowed when the path stays
|
|
3161
|
-
* inside the clone, rejected when it escapes.
|
|
3162
|
-
*
|
|
3259
|
+
* inside the clone, rejected when it escapes.
|
|
3260
|
+
* - yarn berry (v2+) resolves `workspace:` against the repo-root package.json
|
|
3261
|
+
* `workspaces` field and `portal:`/`file:`/`link:` against inside-repo paths,
|
|
3262
|
+
* so those are allowed when present/inside the clone and rejected otherwise.
|
|
3163
3263
|
*
|
|
3164
3264
|
* This module performs that classification so unresolvable specifiers fail
|
|
3165
3265
|
* fast with guidance rather than a cryptic install error.
|
|
@@ -3219,6 +3319,17 @@ async function fileExists$1(target) {
|
|
|
3219
3319
|
return false;
|
|
3220
3320
|
}
|
|
3221
3321
|
}
|
|
3322
|
+
/** Whether the repo-root package.json declares a non-empty `workspaces` array. */
|
|
3323
|
+
async function rootHasWorkspaces(repoRoot) {
|
|
3324
|
+
try {
|
|
3325
|
+
const ws = JSON.parse(await readFile(join(repoRoot, "package.json"), "utf-8")).workspaces;
|
|
3326
|
+
if (Array.isArray(ws)) return ws.length > 0;
|
|
3327
|
+
if (ws && typeof ws === "object" && Array.isArray(ws.packages)) return ws.packages.length > 0;
|
|
3328
|
+
return false;
|
|
3329
|
+
} catch {
|
|
3330
|
+
return false;
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
3222
3333
|
/** Resolve a `file:`/`link:`/`portal:` spec to an absolute path under kiciDir. */
|
|
3223
3334
|
function resolveLocalPath(kiciDir, dep) {
|
|
3224
3335
|
const rawPath = dep.spec.slice(dep.protocol.length);
|
|
@@ -3233,8 +3344,20 @@ function isInsideRepo(repoRoot, target) {
|
|
|
3233
3344
|
* Classify each local-protocol dependency for the detected package manager and
|
|
3234
3345
|
* return the ones that are unresolvable in the agent's single-clone model.
|
|
3235
3346
|
*/
|
|
3236
|
-
async function findUnresolvableDeps(deps, packageManager, kiciDir, repoRoot) {
|
|
3347
|
+
async function findUnresolvableDeps(deps, packageManager, kiciDir, repoRoot, yarnFlavor) {
|
|
3237
3348
|
if (packageManager === PackageManager.Npm) return [...deps];
|
|
3349
|
+
if (packageManager === PackageManager.Yarn && yarnFlavor === YarnFlavor.Berry) {
|
|
3350
|
+
const hasWorkspaces = await rootHasWorkspaces(repoRoot);
|
|
3351
|
+
const unresolvable = [];
|
|
3352
|
+
for (const dep of deps) {
|
|
3353
|
+
if (dep.protocol === "workspace:") {
|
|
3354
|
+
if (!hasWorkspaces) unresolvable.push(dep);
|
|
3355
|
+
continue;
|
|
3356
|
+
}
|
|
3357
|
+
if (!isInsideRepo(repoRoot, resolveLocalPath(kiciDir, dep))) unresolvable.push(dep);
|
|
3358
|
+
}
|
|
3359
|
+
return unresolvable;
|
|
3360
|
+
}
|
|
3238
3361
|
if (packageManager === PackageManager.Yarn) {
|
|
3239
3362
|
const unresolvable = [];
|
|
3240
3363
|
for (const dep of deps) {
|
|
@@ -3258,10 +3381,11 @@ async function findUnresolvableDeps(deps, packageManager, kiciDir, repoRoot) {
|
|
|
3258
3381
|
return unresolvable;
|
|
3259
3382
|
}
|
|
3260
3383
|
/** Build the actionable error for unresolvable local-protocol dependencies. */
|
|
3261
|
-
function formatUnresolvableDepError(offenders, packageManager) {
|
|
3384
|
+
function formatUnresolvableDepError(offenders, packageManager, yarnFlavor) {
|
|
3262
3385
|
const list = offenders.map((o) => `${o.name}: ${o.spec}`).join(", ");
|
|
3263
3386
|
if (packageManager === PackageManager.Npm) return `These .kici/ dependencies use local-protocol specifiers npm cannot resolve from a registry: ${list}. npm has no workspace protocol — pin a published version, publish the package to your registry, or use pnpm so an in-repo workspace sibling can be resolved.`;
|
|
3264
|
-
if (packageManager === PackageManager.Yarn) return `These .kici/ dependencies
|
|
3387
|
+
if (packageManager === PackageManager.Yarn && yarnFlavor === YarnFlavor.Berry) return `These .kici/ dependencies cannot be resolved by yarn berry from the cloned repository: ${list}. A workspace: dependency requires a "workspaces" array in the repo-root package.json, and file:/link:/portal: paths must stay inside this repository.`;
|
|
3388
|
+
if (packageManager === PackageManager.Yarn) return `These .kici/ dependencies use specifiers yarn classic cannot resolve: ${list}. yarn classic has no workspace: or portal: protocol — reference an in-repo sibling by a version range (yarn links matching workspace members), use pnpm, or keep file:/link: paths inside this repository. (yarn berry support requires a yarn@2+ packageManager field or a .yarnrc.yml.)`;
|
|
3265
3389
|
return `These .kici/ dependencies point outside the cloned repository, which the agent never has: ${list}. A workspace: dependency requires a pnpm-workspace.yaml at the repo root, and file:/link:/portal: paths must stay inside this repository.`;
|
|
3266
3390
|
}
|
|
3267
3391
|
/**
|
|
@@ -3275,9 +3399,10 @@ async function assertResolvableDeps(args) {
|
|
|
3275
3399
|
if (!pkg) return;
|
|
3276
3400
|
const localDeps = findLocalProtocolDeps(pkg);
|
|
3277
3401
|
if (localDeps.length === 0) return;
|
|
3278
|
-
const
|
|
3402
|
+
const flavor = args.yarnFlavor ?? YarnFlavor.Classic;
|
|
3403
|
+
const offenders = await findUnresolvableDeps(localDeps, args.packageManager, args.kiciDir, args.repoRoot, flavor);
|
|
3279
3404
|
if (offenders.length === 0) return;
|
|
3280
|
-
throw new Error(formatUnresolvableDepError(offenders, args.packageManager));
|
|
3405
|
+
throw new Error(formatUnresolvableDepError(offenders, args.packageManager, flavor));
|
|
3281
3406
|
}
|
|
3282
3407
|
var LOCAL_PROTOCOLS, DEP_FIELDS;
|
|
3283
3408
|
var init_validate_kici_deps = __esmMin((() => {
|
|
@@ -3402,10 +3527,13 @@ var init_workspace_siblings = __esmMin((() => {}));
|
|
|
3402
3527
|
* presence of `.kici/package.json` signals that deps should be installed. npm
|
|
3403
3528
|
* is the default and ships with every Node.js install; pnpm is used when the
|
|
3404
3529
|
* repo is a pnpm workspace so a `.kici/` member can resolve in-repo
|
|
3405
|
-
* `workspace:` siblings. yarn classic (v1)
|
|
3406
|
-
*
|
|
3407
|
-
*
|
|
3408
|
-
*
|
|
3530
|
+
* `workspace:` siblings. yarn is supported in both flavors: classic (v1) reads
|
|
3531
|
+
* `.kici/.npmrc` for registry auth and links version-range workspace siblings;
|
|
3532
|
+
* berry (v2+) reads a synthesized `.kici/.yarnrc.yml` for auth, runs with a
|
|
3533
|
+
* forced `nodeLinker: node-modules` (so the resulting tree matches classic/npm
|
|
3534
|
+
* and the runner's plain node resolution holds), and resolves
|
|
3535
|
+
* `workspace:`/`portal:` siblings. Either flavor links the sibling but does not
|
|
3536
|
+
* build it, so the agent builds the in-repo closure after install.
|
|
3409
3537
|
*
|
|
3410
3538
|
* Security: the install runs with an isolated per-invocation cache/store
|
|
3411
3539
|
* directory to prevent cache poisoning across build jobs — a malicious
|
|
@@ -3426,6 +3554,15 @@ async function detectKiciPackageManager(repoRoot, kiciDir) {
|
|
|
3426
3554
|
return await detectPackageManagerFromManifests(repoRoot) ?? await detectPackageManagerFromManifests(kiciDir) ?? PackageManager.Npm;
|
|
3427
3555
|
}
|
|
3428
3556
|
/**
|
|
3557
|
+
* Detect the yarn flavor (classic vs berry) for the cloned repo. Mirrors
|
|
3558
|
+
* `detectKiciPackageManager`: probe the repo root first, then `.kici/` for a
|
|
3559
|
+
* standalone project. Only called when the detected manager is `Yarn`.
|
|
3560
|
+
*/
|
|
3561
|
+
async function detectKiciYarnFlavor(repoRoot, kiciDir) {
|
|
3562
|
+
if (await detectYarnFlavor(repoRoot) === YarnFlavor.Berry) return YarnFlavor.Berry;
|
|
3563
|
+
return detectYarnFlavor(kiciDir);
|
|
3564
|
+
}
|
|
3565
|
+
/**
|
|
3429
3566
|
* Install `.kici/` dependencies inline with the repo's package manager.
|
|
3430
3567
|
*
|
|
3431
3568
|
* Falls back to this when the dep cache is unavailable or a download fails.
|
|
@@ -3444,19 +3581,28 @@ async function detectKiciPackageManager(repoRoot, kiciDir) {
|
|
|
3444
3581
|
async function installDeps(kiciDir, opts = {}) {
|
|
3445
3582
|
const repoRoot = opts.repoRoot ?? dirname(kiciDir);
|
|
3446
3583
|
const packageManager = await detectKiciPackageManager(repoRoot, kiciDir);
|
|
3584
|
+
const yarnFlavor = packageManager === PackageManager.Yarn ? await detectKiciYarnFlavor(repoRoot, kiciDir) : YarnFlavor.Classic;
|
|
3447
3585
|
logger$6.info("Installing deps inline", {
|
|
3448
3586
|
packageManager,
|
|
3587
|
+
yarnFlavor,
|
|
3449
3588
|
dir: kiciDir
|
|
3450
3589
|
});
|
|
3451
|
-
process.stderr.write(`[dep-installer:trace] starting install: pm=${packageManager}, cwd=${kiciDir}\n`);
|
|
3590
|
+
process.stderr.write(`[dep-installer:trace] starting install: pm=${packageManager}, flavor=${yarnFlavor}, cwd=${kiciDir}\n`);
|
|
3452
3591
|
await assertResolvableDeps({
|
|
3453
3592
|
kiciDir,
|
|
3454
3593
|
repoRoot,
|
|
3455
|
-
packageManager
|
|
3594
|
+
packageManager,
|
|
3595
|
+
yarnFlavor
|
|
3456
3596
|
});
|
|
3457
3597
|
const startTime = Date.now();
|
|
3458
3598
|
const hasPrivateRegistry = (opts.npmRegistries?.length ?? 0) > 0 || (opts.installEnvSecrets ? Object.keys(opts.installEnvSecrets).length > 0 : false);
|
|
3459
|
-
const
|
|
3599
|
+
const isBerry = packageManager === PackageManager.Yarn && yarnFlavor === YarnFlavor.Berry;
|
|
3600
|
+
const registryConfig = isBerry ? await applyYarnrcBerryConfig({
|
|
3601
|
+
kiciDir,
|
|
3602
|
+
npmRegistries: opts.npmRegistries,
|
|
3603
|
+
installEnvSecrets: opts.installEnvSecrets,
|
|
3604
|
+
jobIdShort: opts.jobIdShort ?? "00000000"
|
|
3605
|
+
}) : await applyNpmRegistryConfig({
|
|
3460
3606
|
kiciDir,
|
|
3461
3607
|
npmRegistries: opts.npmRegistries,
|
|
3462
3608
|
installEnvSecrets: opts.installEnvSecrets,
|
|
@@ -3468,6 +3614,10 @@ async function installDeps(kiciDir, opts = {}) {
|
|
|
3468
3614
|
hasPrivateRegistry,
|
|
3469
3615
|
registryConfig
|
|
3470
3616
|
});
|
|
3617
|
+
else if (isBerry) await runYarnBerryInstall({
|
|
3618
|
+
kiciDir,
|
|
3619
|
+
registryConfig
|
|
3620
|
+
});
|
|
3471
3621
|
else if (packageManager === PackageManager.Yarn) await runYarnInstall({
|
|
3472
3622
|
kiciDir,
|
|
3473
3623
|
hasPrivateRegistry,
|
|
@@ -3487,7 +3637,7 @@ async function installDeps(kiciDir, opts = {}) {
|
|
|
3487
3637
|
await registryConfig.cleanup();
|
|
3488
3638
|
}
|
|
3489
3639
|
if (packageManager === PackageManager.Pnpm && await kiciHasLocalProtocolDeps(kiciDir)) await buildWorkspaceClosure(repoRoot);
|
|
3490
|
-
if (packageManager === PackageManager.Yarn) await buildYarnWorkspaceClosure(repoRoot, kiciDir);
|
|
3640
|
+
if (packageManager === PackageManager.Yarn) await buildYarnWorkspaceClosure(repoRoot, kiciDir, yarnFlavor);
|
|
3491
3641
|
const durationMs = Date.now() - startTime;
|
|
3492
3642
|
process.stderr.write(`[dep-installer:trace] install complete: ${durationMs}ms\n`);
|
|
3493
3643
|
logger$6.info("Deps installed inline", {
|
|
@@ -3616,6 +3766,35 @@ async function runYarnInstall(args) {
|
|
|
3616
3766
|
}).catch(() => {});
|
|
3617
3767
|
}
|
|
3618
3768
|
}
|
|
3769
|
+
/** Pure: argv for a berry `yarn install`. Cache + linker live in .yarnrc.yml. */
|
|
3770
|
+
function buildYarnBerryInstallArgs() {
|
|
3771
|
+
return ["install"];
|
|
3772
|
+
}
|
|
3773
|
+
/**
|
|
3774
|
+
* Run a berry `yarn install` from `.kici/`. The synthesized `.kici/.yarnrc.yml`
|
|
3775
|
+
* (applied by `applyYarnrcBerryConfig`) forces `nodeLinker: node-modules`, an
|
|
3776
|
+
* isolated `cacheFolder`, and — when a private registry is configured —
|
|
3777
|
+
* `enableScripts: false` + `npmScopes`/`npmRegistryServer` auth. corepack
|
|
3778
|
+
* provisions the repo-pinned berry version; `COREPACK_ENABLE_DOWNLOAD_PROMPT=0`
|
|
3779
|
+
* makes that non-interactive. Not `--immutable` (resolved URLs in the lockfile
|
|
3780
|
+
* may point at a different registry than the synthesized config).
|
|
3781
|
+
*/
|
|
3782
|
+
async function runYarnBerryInstall(args) {
|
|
3783
|
+
await assertYarnAvailable();
|
|
3784
|
+
const { nodeDir } = resolveNpm();
|
|
3785
|
+
const env = {
|
|
3786
|
+
...envWithNodeOnPath(args.registryConfig.extraEnv, nodeDir),
|
|
3787
|
+
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
|
|
3788
|
+
};
|
|
3789
|
+
const argv = buildYarnBerryInstallArgs();
|
|
3790
|
+
process.stderr.write(`[dep-installer:trace] running: yarn ${argv.join(" ")} (berry)\n`);
|
|
3791
|
+
await execFileAsync("yarn", argv, {
|
|
3792
|
+
cwd: args.kiciDir,
|
|
3793
|
+
env,
|
|
3794
|
+
timeout: INSTALL_TIMEOUT_MS,
|
|
3795
|
+
maxBuffer: INSTALL_MAX_BUFFER
|
|
3796
|
+
});
|
|
3797
|
+
}
|
|
3619
3798
|
/** Throw an actionable error when the repo needs yarn but it is not installed. */
|
|
3620
3799
|
async function assertYarnAvailable() {
|
|
3621
3800
|
try {
|
|
@@ -3635,7 +3814,7 @@ async function assertYarnAvailable() {
|
|
|
3635
3814
|
* Deep cross-sibling build chains may build out of strict topological order —
|
|
3636
3815
|
* real `.kici` closures are shallow.
|
|
3637
3816
|
*/
|
|
3638
|
-
async function buildYarnWorkspaceClosure(repoRoot, kiciDir) {
|
|
3817
|
+
async function buildYarnWorkspaceClosure(repoRoot, kiciDir, yarnFlavor) {
|
|
3639
3818
|
const siblings = await collectInRepoSiblings(repoRoot, kiciDir, resolveYarnNodeModulesRoot(repoRoot, kiciDir));
|
|
3640
3819
|
if (siblings.length === 0) return;
|
|
3641
3820
|
const { nodeDir } = resolveNpm();
|
|
@@ -3643,15 +3822,16 @@ async function buildYarnWorkspaceClosure(repoRoot, kiciDir) {
|
|
|
3643
3822
|
for (const rel of [...siblings].reverse()) {
|
|
3644
3823
|
const sibDir = join(repoRoot, rel);
|
|
3645
3824
|
if (!await siblingHasBuildScript(sibDir)) continue;
|
|
3646
|
-
|
|
3825
|
+
const [argv, cwd] = yarnFlavor === YarnFlavor.Berry ? [["run", "build"], sibDir] : [[
|
|
3826
|
+
"--cwd",
|
|
3827
|
+
sibDir,
|
|
3828
|
+
"run",
|
|
3829
|
+
"build"
|
|
3830
|
+
], repoRoot];
|
|
3831
|
+
process.stderr.write(`[dep-installer:trace] building yarn sibling (${yarnFlavor}): yarn ${argv.join(" ")} @ ${cwd}\n`);
|
|
3647
3832
|
try {
|
|
3648
|
-
await execFileAsync("yarn",
|
|
3649
|
-
|
|
3650
|
-
sibDir,
|
|
3651
|
-
"run",
|
|
3652
|
-
"build"
|
|
3653
|
-
], {
|
|
3654
|
-
cwd: repoRoot,
|
|
3833
|
+
await execFileAsync("yarn", argv, {
|
|
3834
|
+
cwd,
|
|
3655
3835
|
env,
|
|
3656
3836
|
timeout: INSTALL_TIMEOUT_MS,
|
|
3657
3837
|
maxBuffer: INSTALL_MAX_BUFFER
|
|
@@ -3729,6 +3909,7 @@ function logSubprocessStreams(e, tokens) {
|
|
|
3729
3909
|
var logger$6, execFileAsync, INSTALL_TIMEOUT_MS, INSTALL_MAX_BUFFER;
|
|
3730
3910
|
var init_dep_installer = __esmMin((() => {
|
|
3731
3911
|
init_npm_registry_config();
|
|
3912
|
+
init_yarnrc_berry_config();
|
|
3732
3913
|
init_validate_kici_deps();
|
|
3733
3914
|
init_workspace_siblings();
|
|
3734
3915
|
logger$6 = createLogger({ prefix: "dep-installer" });
|
|
@@ -3753,11 +3934,14 @@ var init_dep_installer = __esmMin((() => {
|
|
|
3753
3934
|
* symlinks into the root store and into sibling dirs that live outside
|
|
3754
3935
|
* `.kici/`, so packing `.kici/node_modules` alone would capture dangling
|
|
3755
3936
|
* links — the store and siblings must travel together.
|
|
3756
|
-
* - yarn classic: the resolved node_modules root (standalone `.kici`
|
|
3757
|
-
* `.kici/node_modules`; hoisted workspace member → the repo-root
|
|
3758
|
-
* `node_modules`) plus the in-repo
|
|
3759
|
-
*
|
|
3760
|
-
*
|
|
3937
|
+
* - yarn (classic + berry): the resolved node_modules root (standalone `.kici`
|
|
3938
|
+
* → `.kici/node_modules`; hoisted workspace member → the repo-root
|
|
3939
|
+
* `node_modules`) plus the in-repo sibling package directories `.kici` depends
|
|
3940
|
+
* on (with their built output), whose symlinks would dangle otherwise. Berry
|
|
3941
|
+
* runs with a forced `nodeLinker: node-modules`, so its tree has the same
|
|
3942
|
+
* node_modules shape as classic and is packed identically (the flavor only
|
|
3943
|
+
* changes how siblings are referenced — version range vs `workspace:`/`portal:`
|
|
3944
|
+
* — not the packed layout).
|
|
3761
3945
|
*
|
|
3762
3946
|
* Uses tar.gz (Node.js built-in zlib, no external binary) in portable mode to
|
|
3763
3947
|
* strip user/group info for cross-machine consistency; symlinks are preserved
|
|
@@ -3805,10 +3989,11 @@ async function packNodeModules(kiciDir) {
|
|
|
3805
3989
|
/**
|
|
3806
3990
|
* Compute the repo-root-relative tar entries for the dependency closure. npm
|
|
3807
3991
|
* needs only `.kici/node_modules`. pnpm additionally needs the root store and
|
|
3808
|
-
* the in-repo workspace siblings `.kici` resolves. yarn classic packs
|
|
3809
|
-
* resolved node_modules root (standalone → `.kici/node_modules`; hoisted
|
|
3810
|
-
* workspace member → root `node_modules`) plus the in-repo
|
|
3811
|
-
*
|
|
3992
|
+
* the in-repo workspace siblings `.kici` resolves. yarn (classic + berry) packs
|
|
3993
|
+
* the resolved node_modules root (standalone → `.kici/node_modules`; hoisted
|
|
3994
|
+
* workspace member → root `node_modules`) plus the in-repo siblings, which it
|
|
3995
|
+
* links but does not place in the store. Berry's forced node-modules linker
|
|
3996
|
+
* gives it the same packed shape as classic.
|
|
3812
3997
|
*/
|
|
3813
3998
|
async function closureEntries(workDir, kiciDir, packageManager) {
|
|
3814
3999
|
if (packageManager === PackageManager.Pnpm) {
|
|
@@ -3988,6 +4173,8 @@ function buildRequest(dispatch, workDir) {
|
|
|
3988
4173
|
jobName: jobConfig.baseJobName ?? jobConfig.name ?? "",
|
|
3989
4174
|
runsOn: jobConfig.runsOn ?? "",
|
|
3990
4175
|
matrixValues: jobConfig.matrixValues,
|
|
4176
|
+
host: jobConfig.host,
|
|
4177
|
+
agent: jobConfig.agent,
|
|
3991
4178
|
secrets: dispatch.secrets,
|
|
3992
4179
|
namespacedSecrets: dispatch.namespacedSecrets,
|
|
3993
4180
|
sourceFile: jobConfig.source?.file,
|
|
@@ -5241,6 +5428,14 @@ function determineExecutionMode(jobConfig, agentConfig) {
|
|
|
5241
5428
|
if (agentConfig.scalerManaged) return "firecracker";
|
|
5242
5429
|
return "bare-metal";
|
|
5243
5430
|
}
|
|
5431
|
+
/**
|
|
5432
|
+
* Build the result-aware `ctx.needs` for a dynamic eval from its frozen upstream
|
|
5433
|
+
* snapshot. Returns undefined for an event-only generator (no snapshot).
|
|
5434
|
+
*/
|
|
5435
|
+
function buildEvalNeedsContext(config) {
|
|
5436
|
+
if (!config.resultAware || !config.upstreamSnapshot) return void 0;
|
|
5437
|
+
return buildNeedsContext(config.upstreamSnapshot, config.declaredNeeds ?? []);
|
|
5438
|
+
}
|
|
5244
5439
|
var logger$2, JobRunner$1;
|
|
5245
5440
|
var init_job_runner = __esmMin((() => {
|
|
5246
5441
|
init_git_clone();
|
|
@@ -5988,11 +6183,13 @@ var init_job_runner = __esmMin((() => {
|
|
|
5988
6183
|
const { extractDynamicJobFn } = await Promise.resolve().then(() => (init_workflow_loader(), workflow_loader_exports));
|
|
5989
6184
|
const dynamicFn = extractDynamicJobFn(extractWorkflow(module, config.workflowName), config.source.index);
|
|
5990
6185
|
evalLog(`Evaluating DynamicJobFn (index ${config.source.index}, timeout ${timeoutMs}ms)`);
|
|
6186
|
+
const needs = buildEvalNeedsContext(config);
|
|
5991
6187
|
const context = {
|
|
5992
6188
|
$: scopedDollar,
|
|
5993
6189
|
ctx: {
|
|
5994
6190
|
workflow: { name: config.workflowName },
|
|
5995
|
-
event: config.event
|
|
6191
|
+
event: config.event,
|
|
6192
|
+
...needs && { needs }
|
|
5996
6193
|
},
|
|
5997
6194
|
log: dynamicJobLogger,
|
|
5998
6195
|
env: process.env,
|
|
@@ -6209,14 +6406,14 @@ var init_job_runner = __esmMin((() => {
|
|
|
6209
6406
|
*/
|
|
6210
6407
|
init_console_capture();
|
|
6211
6408
|
init_npm_resolver();
|
|
6212
|
-
const AGENT_VERSION = "0.1.
|
|
6213
|
-
const BUILD_COMMIT = "
|
|
6214
|
-
const SDK_VERSION = "0.1.
|
|
6215
|
-
const SDK_BUNDLE_HASH = "
|
|
6216
|
-
const SHARED_VERSION = "0.1.
|
|
6217
|
-
const SHARED_BUNDLE_HASH = "
|
|
6218
|
-
const ENGINE_VERSION = "0.1.
|
|
6219
|
-
const ENGINE_BUNDLE_HASH = "
|
|
6409
|
+
const AGENT_VERSION = "0.1.19";
|
|
6410
|
+
const BUILD_COMMIT = "1590f5e99";
|
|
6411
|
+
const SDK_VERSION = "0.1.19";
|
|
6412
|
+
const SDK_BUNDLE_HASH = "8308089347c304e41b457d3867b17bbff11d6b5cd9706b6823e7abdbd849f33f";
|
|
6413
|
+
const SHARED_VERSION = "0.1.19";
|
|
6414
|
+
const SHARED_BUNDLE_HASH = "5f2c220f24d166b0f13d0620a2e80d19689ac8b683a12154daef44e938fd46a7";
|
|
6415
|
+
const ENGINE_VERSION = "0.1.19";
|
|
6416
|
+
const ENGINE_BUNDLE_HASH = "79ce14640d1798eaaa7cb3aa6c4bc325da3bff1e9f4716936e19614eabb1d858";
|
|
6220
6417
|
initTelemetry({
|
|
6221
6418
|
serviceName: "kici-agent",
|
|
6222
6419
|
otlpEndpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT
|