akm-cli 0.9.10 → 0.9.11
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/CHANGELOG.md +60 -0
- package/STABILITY.md +22 -14
- package/dist/commands/health/checks.js +23 -7
- package/dist/commands/health/improve-metrics.js +12 -0
- package/dist/commands/improve/distill/quality-gate.js +13 -5
- package/dist/commands/improve/eval-cases.js +9 -2
- package/dist/commands/improve/improve.js +19 -4
- package/dist/commands/improve/loop-stages.js +13 -3
- package/dist/commands/tasks/tasks-cli.js +32 -0
- package/dist/commands/tasks/validate.js +186 -0
- package/dist/commands/url-checker.js +75 -16
- package/dist/core/bundle-id.js +7 -1
- package/dist/core/config/schema/engines.js +17 -0
- package/dist/core/improve-result.js +8 -0
- package/dist/core/paths.js +112 -0
- package/dist/indexer/search/search-source.js +3 -2
- package/dist/integrations/agent/engine-resolution.js +92 -3
- package/dist/integrations/agent/execution-lowering.js +15 -2
- package/dist/integrations/agent/runner-dispatch.js +16 -3
- package/dist/integrations/agent/runner.js +2 -0
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/scripts/akm-migrate-node.js +1043 -822
- package/dist/scripts/akm-migrate.js +1043 -822
- package/dist/tasks/scheduler-sync.js +51 -25
- package/dist/workflows/exec/dispatch-redaction.js +21 -7
- package/docs/integration/bundling-akm.md +1 -1
- package/docs/migration/v0.8-to-v0.9.md +32 -0
- package/docs/reference/cli.md +31 -5
- package/docs/reference/configuration.md +12 -2
- package/docs/reference/data-and-telemetry.md +1 -1
- package/docs/reference/tasks.md +8 -0
- package/package.json +1 -1
- package/schemas/akm-config.json +8 -0
|
@@ -7123,6 +7123,136 @@ var init_errors = __esm(() => {
|
|
|
7123
7123
|
};
|
|
7124
7124
|
});
|
|
7125
7125
|
|
|
7126
|
+
// src/core/asset/asset-ref.ts
|
|
7127
|
+
import path from "path";
|
|
7128
|
+
function validateName(name) {
|
|
7129
|
+
if (!name)
|
|
7130
|
+
throw new UsageError("Empty asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
7131
|
+
if (name.includes("\x00"))
|
|
7132
|
+
throw new UsageError("Null byte in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
7133
|
+
if (/^[A-Za-z]:/.test(name))
|
|
7134
|
+
throw new UsageError("Windows drive path in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
7135
|
+
const slashName = name.replace(/\\/g, "/");
|
|
7136
|
+
if (slashName === ".." || slashName.startsWith("../")) {
|
|
7137
|
+
throw new UsageError("Path traversal in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
7138
|
+
}
|
|
7139
|
+
if (slashName.split("/").some((seg) => seg === "." || seg === "..")) {
|
|
7140
|
+
throw new UsageError("Asset name cannot contain relative path segments.", "MISSING_REQUIRED_ARGUMENT");
|
|
7141
|
+
}
|
|
7142
|
+
const normalized = path.posix.normalize(slashName);
|
|
7143
|
+
if (path.posix.isAbsolute(normalized))
|
|
7144
|
+
throw new UsageError("Absolute path in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
7145
|
+
if (normalized === ".." || normalized.startsWith("../")) {
|
|
7146
|
+
throw new UsageError("Path traversal in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
7147
|
+
}
|
|
7148
|
+
}
|
|
7149
|
+
function normalizeName(name) {
|
|
7150
|
+
return path.posix.normalize(name.replace(/\\/g, "/"));
|
|
7151
|
+
}
|
|
7152
|
+
function isBundleSlug(s) {
|
|
7153
|
+
return BUNDLE_SLUG_RE.test(s);
|
|
7154
|
+
}
|
|
7155
|
+
function normalizeConceptId(raw) {
|
|
7156
|
+
const nfc = raw.normalize("NFC");
|
|
7157
|
+
if (nfc.includes("#")) {
|
|
7158
|
+
throw new UsageError("`#` is reserved for the export fragment in a concept id.", "MISSING_REQUIRED_ARGUMENT");
|
|
7159
|
+
}
|
|
7160
|
+
validateName(nfc);
|
|
7161
|
+
return normalizeName(nfc);
|
|
7162
|
+
}
|
|
7163
|
+
function makeBundleRef(bundle, conceptId, fragment) {
|
|
7164
|
+
const normalized = normalizeConceptId(conceptId);
|
|
7165
|
+
let out = normalized;
|
|
7166
|
+
if (bundle) {
|
|
7167
|
+
if (!BUNDLE_SLUG_RE.test(bundle)) {
|
|
7168
|
+
throw new UsageError(`Invalid bundle slug "${bundle}". A bundle slug may not contain ':', '.', '#', '/', or whitespace.`, "MISSING_REQUIRED_ARGUMENT");
|
|
7169
|
+
}
|
|
7170
|
+
out = `${bundle}//${normalized}`;
|
|
7171
|
+
}
|
|
7172
|
+
if (fragment)
|
|
7173
|
+
out = `${out}#${fragment}`;
|
|
7174
|
+
return out;
|
|
7175
|
+
}
|
|
7176
|
+
function bundleRefToString(ref) {
|
|
7177
|
+
return makeBundleRef(ref.bundle, ref.conceptId, ref.fragment);
|
|
7178
|
+
}
|
|
7179
|
+
function parseBundleRef(ref) {
|
|
7180
|
+
const trimmed = ref.trim();
|
|
7181
|
+
if (!trimmed)
|
|
7182
|
+
throw new UsageError("Empty ref.", "MISSING_REQUIRED_ARGUMENT");
|
|
7183
|
+
let bundle;
|
|
7184
|
+
let body = trimmed;
|
|
7185
|
+
const boundary = trimmed.indexOf("//");
|
|
7186
|
+
if (boundary >= 0) {
|
|
7187
|
+
bundle = trimmed.slice(0, boundary);
|
|
7188
|
+
body = trimmed.slice(boundary + 2);
|
|
7189
|
+
if (!bundle)
|
|
7190
|
+
throw new UsageError("Empty bundle in ref.", "MISSING_REQUIRED_ARGUMENT");
|
|
7191
|
+
if (!BUNDLE_SLUG_RE.test(bundle)) {
|
|
7192
|
+
throw new UsageError(`Invalid bundle slug "${bundle}" in ref "${trimmed}". A bundle slug may not contain ':', '.', '#', '/', or whitespace.`, "MISSING_REQUIRED_ARGUMENT");
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
let fragment;
|
|
7196
|
+
const hash = body.indexOf("#");
|
|
7197
|
+
if (hash >= 0) {
|
|
7198
|
+
fragment = body.slice(hash + 1) || undefined;
|
|
7199
|
+
body = body.slice(0, hash);
|
|
7200
|
+
}
|
|
7201
|
+
if (!body) {
|
|
7202
|
+
throw new UsageError(`Invalid ref "${trimmed}". Expected [bundle//]conceptId, e.g. knowledge/guide or core//skills/review`, "MISSING_REQUIRED_ARGUMENT");
|
|
7203
|
+
}
|
|
7204
|
+
const conceptId = normalizeConceptId(body);
|
|
7205
|
+
return { bundle: bundle || undefined, conceptId, fragment };
|
|
7206
|
+
}
|
|
7207
|
+
var BUNDLE_SLUG_RE;
|
|
7208
|
+
var init_asset_ref = __esm(() => {
|
|
7209
|
+
init_errors();
|
|
7210
|
+
BUNDLE_SLUG_RE = /^[^\s:.#/]+$/;
|
|
7211
|
+
});
|
|
7212
|
+
|
|
7213
|
+
// src/core/bundle-id.ts
|
|
7214
|
+
import crypto2 from "crypto";
|
|
7215
|
+
import path2 from "path";
|
|
7216
|
+
function slugForPath(sourcePath) {
|
|
7217
|
+
const resolved = path2.resolve(sourcePath);
|
|
7218
|
+
const base = path2.basename(resolved).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7219
|
+
if (base.length > 0)
|
|
7220
|
+
return base;
|
|
7221
|
+
return `bundle-${shortHash(resolved)}`;
|
|
7222
|
+
}
|
|
7223
|
+
function deriveBundleId(registryId, sourcePath, usedIds) {
|
|
7224
|
+
const preferred = registryId && registryId.length > 0 && isBundleSlug(registryId) ? registryId : slugForPath(sourcePath);
|
|
7225
|
+
const id = ensureUniqueId(preferred, sourcePath, usedIds);
|
|
7226
|
+
usedIds.add(id);
|
|
7227
|
+
return id;
|
|
7228
|
+
}
|
|
7229
|
+
function deriveBundleIds(sources) {
|
|
7230
|
+
const usedIds = new Set;
|
|
7231
|
+
const reservedIds = new Set(sources.flatMap((source) => source.registryId && isBundleSlug(source.registryId) ? [source.registryId] : []));
|
|
7232
|
+
return sources.map((source) => {
|
|
7233
|
+
const id = source.registryId && isBundleSlug(source.registryId) ? deriveBundleId(source.registryId, source.path, usedIds) : deriveBundleId(undefined, source.path, new Set([...usedIds, ...reservedIds]));
|
|
7234
|
+
usedIds.add(id);
|
|
7235
|
+
return id;
|
|
7236
|
+
});
|
|
7237
|
+
}
|
|
7238
|
+
function ensureUniqueId(preferred, sourcePath, used) {
|
|
7239
|
+
if (!used.has(preferred))
|
|
7240
|
+
return preferred;
|
|
7241
|
+
const suffixed = `${preferred}-${shortHash(path2.resolve(sourcePath))}`;
|
|
7242
|
+
if (!used.has(suffixed))
|
|
7243
|
+
return suffixed;
|
|
7244
|
+
let n = 2;
|
|
7245
|
+
while (used.has(`${suffixed}-${n}`))
|
|
7246
|
+
n++;
|
|
7247
|
+
return `${suffixed}-${n}`;
|
|
7248
|
+
}
|
|
7249
|
+
function shortHash(input) {
|
|
7250
|
+
return crypto2.createHash("sha256").update(input).digest("hex").slice(0, 8);
|
|
7251
|
+
}
|
|
7252
|
+
var init_bundle_id = __esm(() => {
|
|
7253
|
+
init_asset_ref();
|
|
7254
|
+
});
|
|
7255
|
+
|
|
7126
7256
|
// src/core/platform.ts
|
|
7127
7257
|
var IS_WINDOWS;
|
|
7128
7258
|
var init_platform = __esm(() => {
|
|
@@ -7131,7 +7261,7 @@ var init_platform = __esm(() => {
|
|
|
7131
7261
|
|
|
7132
7262
|
// src/core/paths.ts
|
|
7133
7263
|
import os from "os";
|
|
7134
|
-
import
|
|
7264
|
+
import path3 from "path";
|
|
7135
7265
|
function isUnderBunTest(env) {
|
|
7136
7266
|
return env.BUN_TEST === "1" || env.NODE_ENV === "test";
|
|
7137
7267
|
}
|
|
@@ -7148,37 +7278,37 @@ function getConfigDir(env = process.env, platform = process.platform) {
|
|
|
7148
7278
|
if (platform === "win32") {
|
|
7149
7279
|
const appData = env.APPDATA?.trim();
|
|
7150
7280
|
if (appData)
|
|
7151
|
-
return
|
|
7281
|
+
return path3.join(appData, "akm");
|
|
7152
7282
|
} else {
|
|
7153
7283
|
const xdgConfigHome2 = env.XDG_CONFIG_HOME?.trim();
|
|
7154
7284
|
if (xdgConfigHome2)
|
|
7155
|
-
return
|
|
7285
|
+
return path3.join(xdgConfigHome2, "akm");
|
|
7156
7286
|
}
|
|
7157
7287
|
const stashOverride = env.AKM_BUNDLE_DIR?.trim();
|
|
7158
7288
|
if (stashOverride && isTransientStashPath(stashOverride)) {
|
|
7159
|
-
return
|
|
7289
|
+
return path3.join(stashOverride, ".akm");
|
|
7160
7290
|
}
|
|
7161
7291
|
if (platform === "win32") {
|
|
7162
7292
|
const appData = env.APPDATA?.trim();
|
|
7163
7293
|
if (appData)
|
|
7164
|
-
return
|
|
7294
|
+
return path3.join(appData, "akm");
|
|
7165
7295
|
const userProfile = env.USERPROFILE?.trim();
|
|
7166
7296
|
if (!userProfile) {
|
|
7167
7297
|
throw new ConfigError("Unable to determine config directory. Set APPDATA or USERPROFILE.", "CONFIG_DIR_UNRESOLVABLE");
|
|
7168
7298
|
}
|
|
7169
|
-
return
|
|
7299
|
+
return path3.join(userProfile, "AppData", "Roaming", "akm");
|
|
7170
7300
|
}
|
|
7171
7301
|
const xdgConfigHome = env.XDG_CONFIG_HOME?.trim();
|
|
7172
7302
|
if (xdgConfigHome)
|
|
7173
|
-
return
|
|
7303
|
+
return path3.join(xdgConfigHome, "akm");
|
|
7174
7304
|
const home = env.HOME?.trim();
|
|
7175
7305
|
if (!home) {
|
|
7176
7306
|
throw new ConfigError("Unable to determine config directory. Set XDG_CONFIG_HOME or HOME.", "CONFIG_DIR_UNRESOLVABLE");
|
|
7177
7307
|
}
|
|
7178
|
-
return
|
|
7308
|
+
return path3.join(home, ".config", "akm");
|
|
7179
7309
|
}
|
|
7180
7310
|
function getConfigPath(env = process.env) {
|
|
7181
|
-
return
|
|
7311
|
+
return path3.join(getConfigDir(env), "config.json");
|
|
7182
7312
|
}
|
|
7183
7313
|
function getCacheDir(env = process.env) {
|
|
7184
7314
|
const override = env.AKM_CACHE_DIR?.trim();
|
|
@@ -7187,22 +7317,22 @@ function getCacheDir(env = process.env) {
|
|
|
7187
7317
|
if (IS_WINDOWS) {
|
|
7188
7318
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
7189
7319
|
if (localAppData)
|
|
7190
|
-
return
|
|
7320
|
+
return path3.join(localAppData, "akm");
|
|
7191
7321
|
const userProfile = env.USERPROFILE?.trim();
|
|
7192
7322
|
if (userProfile)
|
|
7193
|
-
return
|
|
7323
|
+
return path3.join(userProfile, "AppData", "Local", "akm");
|
|
7194
7324
|
const appData = env.APPDATA?.trim();
|
|
7195
7325
|
if (appData) {
|
|
7196
|
-
return
|
|
7326
|
+
return path3.join(appData, "..", "Local", "akm");
|
|
7197
7327
|
}
|
|
7198
7328
|
} else {
|
|
7199
7329
|
const xdgCacheHome = env.XDG_CACHE_HOME?.trim();
|
|
7200
7330
|
if (xdgCacheHome)
|
|
7201
|
-
return
|
|
7331
|
+
return path3.join(xdgCacheHome, "akm");
|
|
7202
7332
|
}
|
|
7203
7333
|
const stashOverride = env.AKM_BUNDLE_DIR?.trim();
|
|
7204
7334
|
if (stashOverride && isTransientStashPath(stashOverride)) {
|
|
7205
|
-
return
|
|
7335
|
+
return path3.join(stashOverride, ".akm", "cache");
|
|
7206
7336
|
}
|
|
7207
7337
|
if (IS_WINDOWS) {
|
|
7208
7338
|
throw new ConfigError("Unable to determine cache directory. Set LOCALAPPDATA, USERPROFILE, or APPDATA.", "CONFIG_DIR_UNRESOLVABLE");
|
|
@@ -7210,11 +7340,11 @@ function getCacheDir(env = process.env) {
|
|
|
7210
7340
|
const home = env.HOME?.trim();
|
|
7211
7341
|
if (!home)
|
|
7212
7342
|
return homelessFallbackDir("akm-cache");
|
|
7213
|
-
return
|
|
7343
|
+
return path3.join(home, ".cache", "akm");
|
|
7214
7344
|
}
|
|
7215
7345
|
function homelessFallbackDir(kind) {
|
|
7216
7346
|
const uid = typeof process.getuid === "function" ? process.getuid() : undefined;
|
|
7217
|
-
return
|
|
7347
|
+
return path3.join(os.tmpdir(), uid === undefined ? kind : `${kind}-${uid}`);
|
|
7218
7348
|
}
|
|
7219
7349
|
function getDataDir(env = process.env, platform = process.platform) {
|
|
7220
7350
|
const override = env.AKM_DATA_DIR?.trim();
|
|
@@ -7226,38 +7356,83 @@ function getDataDir(env = process.env, platform = process.platform) {
|
|
|
7226
7356
|
if (platform === "win32") {
|
|
7227
7357
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
7228
7358
|
if (localAppData)
|
|
7229
|
-
return
|
|
7359
|
+
return path3.join(localAppData, "akm", "data");
|
|
7230
7360
|
const userProfile = env.USERPROFILE?.trim();
|
|
7231
7361
|
if (userProfile)
|
|
7232
|
-
return
|
|
7362
|
+
return path3.join(userProfile, "AppData", "Local", "akm", "data");
|
|
7233
7363
|
const appData = env.APPDATA?.trim();
|
|
7234
7364
|
if (!appData) {
|
|
7235
7365
|
throw new ConfigError("Unable to determine data directory. Set LOCALAPPDATA, USERPROFILE, or APPDATA.", "CONFIG_DIR_UNRESOLVABLE");
|
|
7236
7366
|
}
|
|
7237
|
-
return
|
|
7367
|
+
return path3.join(appData, "..", "Local", "akm", "data");
|
|
7238
7368
|
}
|
|
7239
7369
|
const xdgDataHome = env.XDG_DATA_HOME?.trim();
|
|
7240
7370
|
if (xdgDataHome)
|
|
7241
|
-
return
|
|
7371
|
+
return path3.join(xdgDataHome, "akm");
|
|
7242
7372
|
const home = env.HOME?.trim();
|
|
7243
7373
|
if (!home)
|
|
7244
7374
|
return homelessFallbackDir("akm-data");
|
|
7245
|
-
return
|
|
7375
|
+
return path3.join(home, ".local", "share", "akm");
|
|
7246
7376
|
}
|
|
7247
7377
|
function getDbPath(env = process.env) {
|
|
7248
|
-
return
|
|
7378
|
+
return path3.join(getDataDir(env), "index.db");
|
|
7249
7379
|
}
|
|
7250
7380
|
function getMaintenanceBarrierPath() {
|
|
7251
|
-
return
|
|
7381
|
+
return path3.join(getDataDir(), "maintenance.barrier.lock");
|
|
7252
7382
|
}
|
|
7253
7383
|
function getLockfilePath() {
|
|
7254
|
-
return
|
|
7384
|
+
return path3.join(getDataDir(), "akm.lock");
|
|
7255
7385
|
}
|
|
7256
7386
|
function getRegistryCacheDir() {
|
|
7257
|
-
return
|
|
7387
|
+
return path3.join(getCacheDir(), "registry");
|
|
7258
7388
|
}
|
|
7259
7389
|
function getRegistryIndexCacheDir() {
|
|
7260
|
-
return
|
|
7390
|
+
return path3.join(getCacheDir(), "registry-index");
|
|
7391
|
+
}
|
|
7392
|
+
function getStateDir(env = process.env, platform = process.platform) {
|
|
7393
|
+
const override = env.AKM_STATE_DIR?.trim();
|
|
7394
|
+
if (override)
|
|
7395
|
+
return override;
|
|
7396
|
+
if (platform === "win32") {
|
|
7397
|
+
const localAppData = env.LOCALAPPDATA?.trim();
|
|
7398
|
+
if (localAppData)
|
|
7399
|
+
return path3.join(localAppData, "akm", "state");
|
|
7400
|
+
const userProfile = env.USERPROFILE?.trim();
|
|
7401
|
+
if (userProfile)
|
|
7402
|
+
return path3.join(userProfile, "AppData", "Local", "akm", "state");
|
|
7403
|
+
const appData = env.APPDATA?.trim();
|
|
7404
|
+
if (!appData) {
|
|
7405
|
+
throw new ConfigError("Unable to determine state directory. Set LOCALAPPDATA, USERPROFILE, or APPDATA.", "CONFIG_DIR_UNRESOLVABLE");
|
|
7406
|
+
}
|
|
7407
|
+
return path3.join(appData, "..", "Local", "akm", "state");
|
|
7408
|
+
}
|
|
7409
|
+
const xdgStateHome = env.XDG_STATE_HOME?.trim();
|
|
7410
|
+
if (xdgStateHome)
|
|
7411
|
+
return path3.join(xdgStateHome, "akm");
|
|
7412
|
+
const home = env.HOME?.trim();
|
|
7413
|
+
if (!home)
|
|
7414
|
+
return homelessFallbackDir("akm-state");
|
|
7415
|
+
return path3.join(home, ".local", "state", "akm");
|
|
7416
|
+
}
|
|
7417
|
+
function getStashStateKey(stashDir) {
|
|
7418
|
+
const resolved = path3.resolve(stashDir).replace(/\\/g, "/");
|
|
7419
|
+
const normalized = IS_WINDOWS ? resolved.toLowerCase() : resolved;
|
|
7420
|
+
return shortHash(normalized);
|
|
7421
|
+
}
|
|
7422
|
+
function stashScopedDir(base, stashDir) {
|
|
7423
|
+
return path3.join(base, getStashStateKey(stashDir));
|
|
7424
|
+
}
|
|
7425
|
+
function getDistillRejectedDir(stashDir) {
|
|
7426
|
+
return stashScopedDir(path3.join(getStateDir(), "improve", "distill-rejected"), stashDir);
|
|
7427
|
+
}
|
|
7428
|
+
function getEvalCasesDir(stashDir) {
|
|
7429
|
+
return stashScopedDir(path3.join(getStateDir(), "improve", "eval-cases"), stashDir);
|
|
7430
|
+
}
|
|
7431
|
+
function getMeasurementVerdictsDir(stashDir) {
|
|
7432
|
+
return stashScopedDir(path3.join(getStateDir(), "improve", "measurement", "verdicts"), stashDir);
|
|
7433
|
+
}
|
|
7434
|
+
function getUnresolvedSourcesDir(stashDir) {
|
|
7435
|
+
return stashScopedDir(path3.join(getCacheDir(), "index", "unresolved-sources"), stashDir);
|
|
7261
7436
|
}
|
|
7262
7437
|
function getDefaultStashDir(env = process.env) {
|
|
7263
7438
|
const override = env.AKM_BUNDLE_DIR?.trim();
|
|
@@ -7266,24 +7441,25 @@ function getDefaultStashDir(env = process.env) {
|
|
|
7266
7441
|
if (IS_WINDOWS) {
|
|
7267
7442
|
const userProfile = env.USERPROFILE?.trim();
|
|
7268
7443
|
if (userProfile)
|
|
7269
|
-
return
|
|
7270
|
-
return
|
|
7444
|
+
return path3.join(userProfile, "Documents", "akm");
|
|
7445
|
+
return path3.join("C:\\", "akm");
|
|
7271
7446
|
}
|
|
7272
7447
|
const home = env.HOME?.trim();
|
|
7273
7448
|
if (!home) {
|
|
7274
7449
|
throw new ConfigError("Unable to determine default bundle directory. Set HOME.", "STASH_DIR_NOT_FOUND");
|
|
7275
7450
|
}
|
|
7276
|
-
return
|
|
7451
|
+
return path3.join(home, "akm");
|
|
7277
7452
|
}
|
|
7278
7453
|
var init_paths = __esm(() => {
|
|
7454
|
+
init_bundle_id();
|
|
7279
7455
|
init_errors();
|
|
7280
7456
|
init_platform();
|
|
7281
7457
|
});
|
|
7282
7458
|
|
|
7283
7459
|
// src/core/common.ts
|
|
7284
|
-
import
|
|
7460
|
+
import crypto3 from "crypto";
|
|
7285
7461
|
import fs from "fs";
|
|
7286
|
-
import
|
|
7462
|
+
import path4 from "path";
|
|
7287
7463
|
function isHttpUrl(value) {
|
|
7288
7464
|
return !!value && /^https?:\/\//.test(value);
|
|
7289
7465
|
}
|
|
@@ -7361,7 +7537,7 @@ function stripJsonComments(text) {
|
|
|
7361
7537
|
return result;
|
|
7362
7538
|
}
|
|
7363
7539
|
function writeFileAtomic(target, content, mode) {
|
|
7364
|
-
const tmp = `${target}.tmp.${process.pid}.${
|
|
7540
|
+
const tmp = `${target}.tmp.${process.pid}.${crypto3.randomBytes(8).toString("hex")}`;
|
|
7365
7541
|
const data = typeof content === "string" ? Buffer.from(content) : content;
|
|
7366
7542
|
const fileMode = mode ?? 384;
|
|
7367
7543
|
let fd;
|
|
@@ -7416,7 +7592,7 @@ function writeFileAtomic(target, content, mode) {
|
|
|
7416
7592
|
if (process.platform !== "win32") {
|
|
7417
7593
|
let dirFd;
|
|
7418
7594
|
try {
|
|
7419
|
-
dirFd = fs.openSync(
|
|
7595
|
+
dirFd = fs.openSync(path4.dirname(target), "r");
|
|
7420
7596
|
} catch (error) {
|
|
7421
7597
|
if (hasErrnoCode(error, "EINVAL") || hasErrnoCode(error, "ENOTSUP"))
|
|
7422
7598
|
return;
|
|
@@ -7449,7 +7625,7 @@ function resolveStashDir(env = process.env) {
|
|
|
7449
7625
|
throw new ConfigError(`No bundle directory found. Run "akm bundle create" to create one at ${defaultDir}.`, "STASH_DIR_NOT_FOUND");
|
|
7450
7626
|
}
|
|
7451
7627
|
function validateStashDir(raw) {
|
|
7452
|
-
const stashDir =
|
|
7628
|
+
const stashDir = path4.resolve(raw);
|
|
7453
7629
|
let stat;
|
|
7454
7630
|
try {
|
|
7455
7631
|
stat = fs.statSync(stashDir);
|
|
@@ -7495,8 +7671,8 @@ function readStashDirFromConfig() {
|
|
|
7495
7671
|
const componentConfig = component;
|
|
7496
7672
|
if (typeof componentConfig.root !== "string")
|
|
7497
7673
|
return bundlePath;
|
|
7498
|
-
const bundleRoot =
|
|
7499
|
-
const componentRoot =
|
|
7674
|
+
const bundleRoot = path4.resolve(bundlePath);
|
|
7675
|
+
const componentRoot = path4.resolve(bundleRoot, componentConfig.root);
|
|
7500
7676
|
if (!isWithin(componentRoot, bundleRoot)) {
|
|
7501
7677
|
throw new ConfigError(`Component root "${componentConfig.root}" escapes bundle "${defaultBundle}".`, "INVALID_CONFIG_FILE");
|
|
7502
7678
|
}
|
|
@@ -7541,30 +7717,30 @@ function isAkmRegistryCachePath(filePath) {
|
|
|
7541
7717
|
return isWithin(filePath, getRegistryCacheDir()) || isWithin(filePath, getRegistryIndexCacheDir());
|
|
7542
7718
|
}
|
|
7543
7719
|
function isContainedResolvedPath(resolvedCandidate, resolvedRoot) {
|
|
7544
|
-
const rel =
|
|
7720
|
+
const rel = path4.relative(normalizeFsPathForComparison(resolvedRoot), normalizeFsPathForComparison(resolvedCandidate));
|
|
7545
7721
|
if (rel === "")
|
|
7546
7722
|
return true;
|
|
7547
|
-
if (
|
|
7723
|
+
if (path4.isAbsolute(rel))
|
|
7548
7724
|
return false;
|
|
7549
7725
|
return rel.split(/[/\\]+/)[0] !== "..";
|
|
7550
7726
|
}
|
|
7551
7727
|
function safeRealpath(p) {
|
|
7552
|
-
const resolved =
|
|
7728
|
+
const resolved = path4.resolve(p);
|
|
7553
7729
|
try {
|
|
7554
7730
|
return fs.realpathSync(resolved);
|
|
7555
7731
|
} catch {
|
|
7556
7732
|
const suffix = [];
|
|
7557
7733
|
let current = resolved;
|
|
7558
7734
|
for (;; ) {
|
|
7559
|
-
const parent =
|
|
7735
|
+
const parent = path4.dirname(current);
|
|
7560
7736
|
if (parent === current) {
|
|
7561
7737
|
return resolved;
|
|
7562
7738
|
}
|
|
7563
|
-
suffix.unshift(
|
|
7739
|
+
suffix.unshift(path4.basename(current));
|
|
7564
7740
|
current = parent;
|
|
7565
7741
|
try {
|
|
7566
7742
|
const realParent = fs.realpathSync(current);
|
|
7567
|
-
return
|
|
7743
|
+
return path4.join(realParent, ...suffix);
|
|
7568
7744
|
} catch {}
|
|
7569
7745
|
}
|
|
7570
7746
|
}
|
|
@@ -7878,7 +8054,7 @@ var init_recognition_util = __esm(() => {
|
|
|
7878
8054
|
|
|
7879
8055
|
// src/core/asset/asset-placement.ts
|
|
7880
8056
|
import fs2 from "fs";
|
|
7881
|
-
import
|
|
8057
|
+
import path7 from "path";
|
|
7882
8058
|
function placementSpecFor(type) {
|
|
7883
8059
|
return PLACEMENT_SPECS[type];
|
|
7884
8060
|
}
|
|
@@ -7902,10 +8078,10 @@ function deriveCanonicalAssetName(assetType, typeRoot, filePath) {
|
|
|
7902
8078
|
return PLACEMENT_SPECS[assetType]?.toCanonicalName(typeRoot, filePath);
|
|
7903
8079
|
}
|
|
7904
8080
|
function deriveCanonicalAssetNameFromStashRoot(assetType, stashRoot, filePath) {
|
|
7905
|
-
const relPath = toPosix(
|
|
8081
|
+
const relPath = toPosix(path7.relative(stashRoot, filePath));
|
|
7906
8082
|
const segments = relPath.split("/").filter(Boolean);
|
|
7907
8083
|
const firstSegment = segments[0];
|
|
7908
|
-
const typeRoot = firstSegment !== undefined && firstSegment === stashDirFor(assetType) ?
|
|
8084
|
+
const typeRoot = firstSegment !== undefined && firstSegment === stashDirFor(assetType) ? path7.join(stashRoot, firstSegment) : stashRoot;
|
|
7909
8085
|
return deriveCanonicalAssetName(assetType, typeRoot, filePath);
|
|
7910
8086
|
}
|
|
7911
8087
|
function assetPathForName(assetType, typeRoot, name) {
|
|
@@ -7924,8 +8100,8 @@ function assetPathCandidatesForName(assetType, typeRoot, name) {
|
|
|
7924
8100
|
const base = name === "default" ? "" : name.endsWith("/default") ? name.slice(0, -"default".length) : undefined;
|
|
7925
8101
|
if (base === undefined)
|
|
7926
8102
|
return [primary];
|
|
7927
|
-
const dotForm =
|
|
7928
|
-
const namedForm =
|
|
8103
|
+
const dotForm = path7.join(typeRoot, base, ".env");
|
|
8104
|
+
const namedForm = path7.join(typeRoot, base, "default.env");
|
|
7929
8105
|
return [...new Set([primary, dotForm, namedForm])];
|
|
7930
8106
|
}
|
|
7931
8107
|
var workflowSpec, markdownSpec, scriptSpec, BUILTIN_PLACEMENT_SPECS, PLACEMENT_SPECS;
|
|
@@ -7933,9 +8109,9 @@ var init_asset_placement = __esm(() => {
|
|
|
7933
8109
|
init_common();
|
|
7934
8110
|
init_recognition_util();
|
|
7935
8111
|
workflowSpec = {
|
|
7936
|
-
isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS.includes(
|
|
8112
|
+
isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS.includes(path7.extname(fileName).toLowerCase()),
|
|
7937
8113
|
toCanonicalName: (typeRoot, filePath) => {
|
|
7938
|
-
const rel = toPosix(
|
|
8114
|
+
const rel = toPosix(path7.relative(typeRoot, filePath));
|
|
7939
8115
|
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
7940
8116
|
if (rel.toLowerCase().endsWith(ext))
|
|
7941
8117
|
return rel.slice(0, -ext.length);
|
|
@@ -7946,43 +8122,43 @@ var init_asset_placement = __esm(() => {
|
|
|
7946
8122
|
const lower = name.toLowerCase();
|
|
7947
8123
|
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
7948
8124
|
if (lower.endsWith(ext))
|
|
7949
|
-
return
|
|
8125
|
+
return path7.join(typeRoot, name);
|
|
7950
8126
|
}
|
|
7951
8127
|
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
7952
|
-
const candidate =
|
|
8128
|
+
const candidate = path7.join(typeRoot, `${name}${ext}`);
|
|
7953
8129
|
if (fs2.existsSync(candidate))
|
|
7954
8130
|
return candidate;
|
|
7955
8131
|
}
|
|
7956
|
-
return
|
|
8132
|
+
return path7.join(typeRoot, `${name}.md`);
|
|
7957
8133
|
}
|
|
7958
8134
|
};
|
|
7959
8135
|
markdownSpec = {
|
|
7960
|
-
isRelevantFile: (fileName) =>
|
|
8136
|
+
isRelevantFile: (fileName) => path7.extname(fileName).toLowerCase() === ".md",
|
|
7961
8137
|
toCanonicalName: (typeRoot, filePath) => {
|
|
7962
|
-
const rel = toPosix(
|
|
8138
|
+
const rel = toPosix(path7.relative(typeRoot, filePath));
|
|
7963
8139
|
return rel.endsWith(".md") ? rel.slice(0, -3) : rel;
|
|
7964
8140
|
},
|
|
7965
8141
|
toAssetPath: (typeRoot, name) => {
|
|
7966
8142
|
const withExt = name.endsWith(".md") ? name : `${name}.md`;
|
|
7967
|
-
return
|
|
8143
|
+
return path7.join(typeRoot, withExt);
|
|
7968
8144
|
}
|
|
7969
8145
|
};
|
|
7970
8146
|
scriptSpec = {
|
|
7971
|
-
isRelevantFile: (fileName) => SCRIPT_EXTENSIONS.has(
|
|
7972
|
-
toCanonicalName: (typeRoot, filePath) => toPosix(
|
|
7973
|
-
toAssetPath: (typeRoot, name) =>
|
|
8147
|
+
isRelevantFile: (fileName) => SCRIPT_EXTENSIONS.has(path7.extname(fileName).toLowerCase()),
|
|
8148
|
+
toCanonicalName: (typeRoot, filePath) => toPosix(path7.relative(typeRoot, filePath)),
|
|
8149
|
+
toAssetPath: (typeRoot, name) => path7.join(typeRoot, name)
|
|
7974
8150
|
};
|
|
7975
8151
|
BUILTIN_PLACEMENT_SPECS = {
|
|
7976
8152
|
skill: {
|
|
7977
8153
|
stashDir: "skills",
|
|
7978
8154
|
isRelevantFile: (fileName) => fileName === "SKILL.md",
|
|
7979
8155
|
toCanonicalName: (typeRoot, filePath) => {
|
|
7980
|
-
const relDir = toPosix(
|
|
8156
|
+
const relDir = toPosix(path7.dirname(path7.relative(typeRoot, filePath)));
|
|
7981
8157
|
if (!relDir || relDir === ".")
|
|
7982
8158
|
return;
|
|
7983
8159
|
return relDir;
|
|
7984
8160
|
},
|
|
7985
|
-
toAssetPath: (typeRoot, name) =>
|
|
8161
|
+
toAssetPath: (typeRoot, name) => path7.join(typeRoot, name, "SKILL.md")
|
|
7986
8162
|
},
|
|
7987
8163
|
command: { stashDir: "commands", ...markdownSpec },
|
|
7988
8164
|
agent: { stashDir: "agents", ...markdownSpec },
|
|
@@ -7995,10 +8171,10 @@ var init_asset_placement = __esm(() => {
|
|
|
7995
8171
|
stashDir: "env",
|
|
7996
8172
|
isRelevantFile: (fileName) => fileName === ".env" || fileName.endsWith(".env"),
|
|
7997
8173
|
toCanonicalName: (typeRoot, filePath) => {
|
|
7998
|
-
const rel = toPosix(
|
|
7999
|
-
const fileName =
|
|
8174
|
+
const rel = toPosix(path7.relative(typeRoot, filePath));
|
|
8175
|
+
const fileName = path7.basename(rel);
|
|
8000
8176
|
if (fileName === ".env") {
|
|
8001
|
-
const dir =
|
|
8177
|
+
const dir = path7.dirname(rel);
|
|
8002
8178
|
return dir === "." || dir === "" ? "default" : `${dir}/default`;
|
|
8003
8179
|
}
|
|
8004
8180
|
const stripped = rel.endsWith(".env") ? rel.slice(0, -4) : rel;
|
|
@@ -8006,27 +8182,27 @@ var init_asset_placement = __esm(() => {
|
|
|
8006
8182
|
},
|
|
8007
8183
|
toAssetPath: (typeRoot, name) => {
|
|
8008
8184
|
if (name === "default")
|
|
8009
|
-
return
|
|
8010
|
-
return
|
|
8185
|
+
return path7.join(typeRoot, ".env");
|
|
8186
|
+
return path7.join(typeRoot, name.endsWith(".env") ? name : `${name}.env`);
|
|
8011
8187
|
}
|
|
8012
8188
|
},
|
|
8013
8189
|
secret: {
|
|
8014
8190
|
stashDir: "secrets",
|
|
8015
8191
|
isRelevantFile: (fileName) => !fileName.endsWith(".lock") && !fileName.endsWith(".sensitive"),
|
|
8016
|
-
toCanonicalName: (typeRoot, filePath) => toPosix(
|
|
8017
|
-
toAssetPath: (typeRoot, name) =>
|
|
8192
|
+
toCanonicalName: (typeRoot, filePath) => toPosix(path7.relative(typeRoot, filePath)),
|
|
8193
|
+
toAssetPath: (typeRoot, name) => path7.join(typeRoot, name)
|
|
8018
8194
|
},
|
|
8019
8195
|
lesson: { stashDir: "lessons", ...markdownSpec },
|
|
8020
8196
|
task: {
|
|
8021
8197
|
stashDir: "tasks",
|
|
8022
|
-
isRelevantFile: (fileName) =>
|
|
8198
|
+
isRelevantFile: (fileName) => path7.extname(fileName).toLowerCase() === ".yml",
|
|
8023
8199
|
toCanonicalName: (typeRoot, filePath) => {
|
|
8024
|
-
const rel = toPosix(
|
|
8200
|
+
const rel = toPosix(path7.relative(typeRoot, filePath));
|
|
8025
8201
|
return rel.toLowerCase().endsWith(".yml") ? rel.slice(0, -4) : rel;
|
|
8026
8202
|
},
|
|
8027
8203
|
toAssetPath: (typeRoot, name) => {
|
|
8028
8204
|
const withExt = name.toLowerCase().endsWith(".yml") ? name : `${name}.yml`;
|
|
8029
|
-
return
|
|
8205
|
+
return path7.join(typeRoot, withExt);
|
|
8030
8206
|
}
|
|
8031
8207
|
},
|
|
8032
8208
|
session: { stashDir: "sessions", ...markdownSpec },
|
|
@@ -8035,93 +8211,6 @@ var init_asset_placement = __esm(() => {
|
|
|
8035
8211
|
PLACEMENT_SPECS = { ...BUILTIN_PLACEMENT_SPECS };
|
|
8036
8212
|
});
|
|
8037
8213
|
|
|
8038
|
-
// src/core/asset/asset-ref.ts
|
|
8039
|
-
import path6 from "path";
|
|
8040
|
-
function validateName(name) {
|
|
8041
|
-
if (!name)
|
|
8042
|
-
throw new UsageError("Empty asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
8043
|
-
if (name.includes("\x00"))
|
|
8044
|
-
throw new UsageError("Null byte in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
8045
|
-
if (/^[A-Za-z]:/.test(name))
|
|
8046
|
-
throw new UsageError("Windows drive path in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
8047
|
-
const slashName = name.replace(/\\/g, "/");
|
|
8048
|
-
if (slashName === ".." || slashName.startsWith("../")) {
|
|
8049
|
-
throw new UsageError("Path traversal in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
8050
|
-
}
|
|
8051
|
-
if (slashName.split("/").some((seg) => seg === "." || seg === "..")) {
|
|
8052
|
-
throw new UsageError("Asset name cannot contain relative path segments.", "MISSING_REQUIRED_ARGUMENT");
|
|
8053
|
-
}
|
|
8054
|
-
const normalized = path6.posix.normalize(slashName);
|
|
8055
|
-
if (path6.posix.isAbsolute(normalized))
|
|
8056
|
-
throw new UsageError("Absolute path in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
8057
|
-
if (normalized === ".." || normalized.startsWith("../")) {
|
|
8058
|
-
throw new UsageError("Path traversal in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
8059
|
-
}
|
|
8060
|
-
}
|
|
8061
|
-
function normalizeName(name) {
|
|
8062
|
-
return path6.posix.normalize(name.replace(/\\/g, "/"));
|
|
8063
|
-
}
|
|
8064
|
-
function isBundleSlug(s) {
|
|
8065
|
-
return BUNDLE_SLUG_RE.test(s);
|
|
8066
|
-
}
|
|
8067
|
-
function normalizeConceptId(raw) {
|
|
8068
|
-
const nfc = raw.normalize("NFC");
|
|
8069
|
-
if (nfc.includes("#")) {
|
|
8070
|
-
throw new UsageError("`#` is reserved for the export fragment in a concept id.", "MISSING_REQUIRED_ARGUMENT");
|
|
8071
|
-
}
|
|
8072
|
-
validateName(nfc);
|
|
8073
|
-
return normalizeName(nfc);
|
|
8074
|
-
}
|
|
8075
|
-
function makeBundleRef(bundle, conceptId, fragment) {
|
|
8076
|
-
const normalized = normalizeConceptId(conceptId);
|
|
8077
|
-
let out = normalized;
|
|
8078
|
-
if (bundle) {
|
|
8079
|
-
if (!BUNDLE_SLUG_RE.test(bundle)) {
|
|
8080
|
-
throw new UsageError(`Invalid bundle slug "${bundle}". A bundle slug may not contain ':', '.', '#', '/', or whitespace.`, "MISSING_REQUIRED_ARGUMENT");
|
|
8081
|
-
}
|
|
8082
|
-
out = `${bundle}//${normalized}`;
|
|
8083
|
-
}
|
|
8084
|
-
if (fragment)
|
|
8085
|
-
out = `${out}#${fragment}`;
|
|
8086
|
-
return out;
|
|
8087
|
-
}
|
|
8088
|
-
function bundleRefToString(ref) {
|
|
8089
|
-
return makeBundleRef(ref.bundle, ref.conceptId, ref.fragment);
|
|
8090
|
-
}
|
|
8091
|
-
function parseBundleRef(ref) {
|
|
8092
|
-
const trimmed = ref.trim();
|
|
8093
|
-
if (!trimmed)
|
|
8094
|
-
throw new UsageError("Empty ref.", "MISSING_REQUIRED_ARGUMENT");
|
|
8095
|
-
let bundle;
|
|
8096
|
-
let body = trimmed;
|
|
8097
|
-
const boundary = trimmed.indexOf("//");
|
|
8098
|
-
if (boundary >= 0) {
|
|
8099
|
-
bundle = trimmed.slice(0, boundary);
|
|
8100
|
-
body = trimmed.slice(boundary + 2);
|
|
8101
|
-
if (!bundle)
|
|
8102
|
-
throw new UsageError("Empty bundle in ref.", "MISSING_REQUIRED_ARGUMENT");
|
|
8103
|
-
if (!BUNDLE_SLUG_RE.test(bundle)) {
|
|
8104
|
-
throw new UsageError(`Invalid bundle slug "${bundle}" in ref "${trimmed}". A bundle slug may not contain ':', '.', '#', '/', or whitespace.`, "MISSING_REQUIRED_ARGUMENT");
|
|
8105
|
-
}
|
|
8106
|
-
}
|
|
8107
|
-
let fragment;
|
|
8108
|
-
const hash = body.indexOf("#");
|
|
8109
|
-
if (hash >= 0) {
|
|
8110
|
-
fragment = body.slice(hash + 1) || undefined;
|
|
8111
|
-
body = body.slice(0, hash);
|
|
8112
|
-
}
|
|
8113
|
-
if (!body) {
|
|
8114
|
-
throw new UsageError(`Invalid ref "${trimmed}". Expected [bundle//]conceptId, e.g. knowledge/guide or core//skills/review`, "MISSING_REQUIRED_ARGUMENT");
|
|
8115
|
-
}
|
|
8116
|
-
const conceptId = normalizeConceptId(body);
|
|
8117
|
-
return { bundle: bundle || undefined, conceptId, fragment };
|
|
8118
|
-
}
|
|
8119
|
-
var BUNDLE_SLUG_RE;
|
|
8120
|
-
var init_asset_ref = __esm(() => {
|
|
8121
|
-
init_errors();
|
|
8122
|
-
BUNDLE_SLUG_RE = /^[^\s:.#/]+$/;
|
|
8123
|
-
});
|
|
8124
|
-
|
|
8125
8214
|
// src/core/asset/resolve-ref.ts
|
|
8126
8215
|
function conceptIdFromTypeName(type, name) {
|
|
8127
8216
|
const stashDir = stashDirFor(type);
|
|
@@ -8185,13 +8274,13 @@ function validateExtraParams(value) {
|
|
|
8185
8274
|
}
|
|
8186
8275
|
const issues = [];
|
|
8187
8276
|
const seen = new WeakSet;
|
|
8188
|
-
const visit2 = (entry,
|
|
8277
|
+
const visit2 = (entry, path8) => {
|
|
8189
8278
|
if (Array.isArray(entry)) {
|
|
8190
8279
|
if (seen.has(entry))
|
|
8191
8280
|
return;
|
|
8192
8281
|
seen.add(entry);
|
|
8193
8282
|
entry.forEach((child, index) => {
|
|
8194
|
-
visit2(child, [...
|
|
8283
|
+
visit2(child, [...path8, index]);
|
|
8195
8284
|
});
|
|
8196
8285
|
return;
|
|
8197
8286
|
}
|
|
@@ -8202,7 +8291,7 @@ function validateExtraParams(value) {
|
|
|
8202
8291
|
seen.add(entry);
|
|
8203
8292
|
for (const [key, child] of Object.entries(entry)) {
|
|
8204
8293
|
const normalized = normalizeExtraParamKey(key);
|
|
8205
|
-
if (
|
|
8294
|
+
if (path8.length === 0 && PROTECTED_TOP_LEVEL_KEYS.has(normalized)) {
|
|
8206
8295
|
const remedy = protectedKeyRemedy(normalized);
|
|
8207
8296
|
issues.push({
|
|
8208
8297
|
path: [key],
|
|
@@ -8210,9 +8299,9 @@ function validateExtraParams(value) {
|
|
|
8210
8299
|
});
|
|
8211
8300
|
}
|
|
8212
8301
|
if (CREDENTIAL_KEYS.has(normalized)) {
|
|
8213
|
-
issues.push({ path: [...
|
|
8302
|
+
issues.push({ path: [...path8, key], message: `${key} cannot carry credentials` });
|
|
8214
8303
|
}
|
|
8215
|
-
visit2(child, [...
|
|
8304
|
+
visit2(child, [...path8, key]);
|
|
8216
8305
|
}
|
|
8217
8306
|
};
|
|
8218
8307
|
visit2(value, []);
|
|
@@ -8405,13 +8494,13 @@ var init_warn = __esm(() => {
|
|
|
8405
8494
|
});
|
|
8406
8495
|
|
|
8407
8496
|
// src/core/write-provenance.ts
|
|
8408
|
-
import
|
|
8497
|
+
import path16 from "path";
|
|
8409
8498
|
function recordWrittenPath(filePath) {
|
|
8410
8499
|
if (activeJournals.size === 0 || !filePath)
|
|
8411
8500
|
return;
|
|
8412
8501
|
let absolute;
|
|
8413
8502
|
try {
|
|
8414
|
-
absolute =
|
|
8503
|
+
absolute = path16.resolve(filePath);
|
|
8415
8504
|
} catch {
|
|
8416
8505
|
return;
|
|
8417
8506
|
}
|
|
@@ -8519,7 +8608,7 @@ var init_frontmatter = __esm(() => {
|
|
|
8519
8608
|
|
|
8520
8609
|
// src/indexer/passes/metadata.ts
|
|
8521
8610
|
import fs13 from "fs";
|
|
8522
|
-
import
|
|
8611
|
+
import path18 from "path";
|
|
8523
8612
|
function normalizeQuality(raw) {
|
|
8524
8613
|
if (KNOWN_QUALITY_VALUES.has(raw))
|
|
8525
8614
|
return raw;
|
|
@@ -9279,7 +9368,7 @@ function projectMarkdownContent(body, truncationInfo) {
|
|
|
9279
9368
|
return truncateUnicodeSafe(text, MARKDOWN_CONTENT_MAX_CHARS);
|
|
9280
9369
|
}
|
|
9281
9370
|
function applyPreContributorFields(entry, file, ctx, pkgMeta) {
|
|
9282
|
-
const ext =
|
|
9371
|
+
const ext = path18.extname(file).toLowerCase();
|
|
9283
9372
|
if (pkgMeta) {
|
|
9284
9373
|
if (pkgMeta.description && !entry.description) {
|
|
9285
9374
|
entry.description = pkgMeta.description;
|
|
@@ -9325,8 +9414,8 @@ function applyPreContributorFields(entry, file, ctx, pkgMeta) {
|
|
|
9325
9414
|
}
|
|
9326
9415
|
}
|
|
9327
9416
|
function applyPostContributorFields(entry, file, canonicalName, dirPath) {
|
|
9328
|
-
const ext =
|
|
9329
|
-
const baseName =
|
|
9417
|
+
const ext = path18.extname(file).toLowerCase();
|
|
9418
|
+
const baseName = path18.basename(file, ext);
|
|
9330
9419
|
if (!entry.description) {
|
|
9331
9420
|
entry.description = fileNameToDescription(baseName);
|
|
9332
9421
|
entry.source = "filename";
|
|
@@ -9338,7 +9427,7 @@ function applyPostContributorFields(entry, file, canonicalName, dirPath) {
|
|
|
9338
9427
|
entry.tags = [...entry.tags ?? [], ...extractDirTagsFromName(canonicalName)];
|
|
9339
9428
|
entry.tags = normalizeTerms(entry.tags ?? []);
|
|
9340
9429
|
entry.aliases = mergeAliases(entry.aliases, buildAliases(canonicalName, entry.tags));
|
|
9341
|
-
entry.filename =
|
|
9430
|
+
entry.filename = path18.basename(file);
|
|
9342
9431
|
}
|
|
9343
9432
|
function buildMetadataSkipWarning(filePath, assetType, error) {
|
|
9344
9433
|
const detail = error instanceof Error ? error.message : String(error);
|
|
@@ -9370,7 +9459,7 @@ function buildAliases(name, tags) {
|
|
|
9370
9459
|
return Array.from(aliases);
|
|
9371
9460
|
}
|
|
9372
9461
|
function extractPackageMetadata(dirPath) {
|
|
9373
|
-
const pkgPath =
|
|
9462
|
+
const pkgPath = path18.join(dirPath, "package.json");
|
|
9374
9463
|
if (!fs13.existsSync(pkgPath))
|
|
9375
9464
|
return null;
|
|
9376
9465
|
try {
|
|
@@ -9392,11 +9481,11 @@ function fileNameToDescription(fileName) {
|
|
|
9392
9481
|
return fileName.replace(/[-_]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().trim();
|
|
9393
9482
|
}
|
|
9394
9483
|
function extractTagsFromPath(filePath, rootDir) {
|
|
9395
|
-
const rel =
|
|
9396
|
-
const parts = rel.split(
|
|
9484
|
+
const rel = path18.relative(rootDir, filePath);
|
|
9485
|
+
const parts = rel.split(path18.sep);
|
|
9397
9486
|
const tags = new Set;
|
|
9398
9487
|
for (const part of parts) {
|
|
9399
|
-
const name = part.replace(
|
|
9488
|
+
const name = part.replace(path18.extname(part), "");
|
|
9400
9489
|
for (const token of name.split(/[-_./\\]+/)) {
|
|
9401
9490
|
const clean = token.toLowerCase().trim();
|
|
9402
9491
|
if (clean && clean.length > 1)
|
|
@@ -9428,27 +9517,27 @@ var init_metadata = __esm(() => {
|
|
|
9428
9517
|
});
|
|
9429
9518
|
|
|
9430
9519
|
// src/execution/record.ts
|
|
9431
|
-
function snapshotStrictRecord(value,
|
|
9520
|
+
function snapshotStrictRecord(value, path19, options = {}) {
|
|
9432
9521
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
9433
|
-
throw new TypeError(`${
|
|
9522
|
+
throw new TypeError(`${path19} must be an object`);
|
|
9434
9523
|
}
|
|
9435
9524
|
const prototype = Object.getPrototypeOf(value);
|
|
9436
9525
|
if (prototype !== Object.prototype && prototype !== null) {
|
|
9437
|
-
throw new TypeError(`${
|
|
9526
|
+
throw new TypeError(`${path19} must use a plain or null prototype`);
|
|
9438
9527
|
}
|
|
9439
9528
|
const out = Object.create(null);
|
|
9440
9529
|
for (const key of Reflect.ownKeys(value)) {
|
|
9441
9530
|
const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
|
|
9442
9531
|
if (!descriptor)
|
|
9443
|
-
throw new TypeError(`${
|
|
9532
|
+
throw new TypeError(`${path19}.${String(key)} must have a stable own descriptor`);
|
|
9444
9533
|
if (typeof key === "symbol" && !options.allowedSymbols?.has(key)) {
|
|
9445
|
-
throw new TypeError(`${
|
|
9534
|
+
throw new TypeError(`${path19} contains unsupported symbol field: ${String(key)}`);
|
|
9446
9535
|
}
|
|
9447
9536
|
if (!("value" in descriptor)) {
|
|
9448
|
-
throw new TypeError(`${
|
|
9537
|
+
throw new TypeError(`${path19}.${String(key)} must be an enumerable data property, not an accessor`);
|
|
9449
9538
|
}
|
|
9450
9539
|
if (typeof key === "string" && !descriptor.enumerable) {
|
|
9451
|
-
throw new TypeError(`${
|
|
9540
|
+
throw new TypeError(`${path19}.${key} must be an enumerable data property, not a non-enumerable field`);
|
|
9452
9541
|
}
|
|
9453
9542
|
Object.defineProperty(out, key, {
|
|
9454
9543
|
value: descriptor.value,
|
|
@@ -9459,14 +9548,14 @@ function snapshotStrictRecord(value, path18, options = {}) {
|
|
|
9459
9548
|
}
|
|
9460
9549
|
return Object.freeze(out);
|
|
9461
9550
|
}
|
|
9462
|
-
function assertSnapshotKeys(value, allowed,
|
|
9551
|
+
function assertSnapshotKeys(value, allowed, path19, allowedSymbols = new Set) {
|
|
9463
9552
|
const allowedKeys = new Set(allowed);
|
|
9464
9553
|
for (const key of Reflect.ownKeys(value)) {
|
|
9465
9554
|
if (typeof key === "symbol") {
|
|
9466
9555
|
if (!allowedSymbols.has(key))
|
|
9467
|
-
throw new TypeError(`${
|
|
9556
|
+
throw new TypeError(`${path19} contains unsupported field: ${String(key)}`);
|
|
9468
9557
|
} else if (!allowedKeys.has(key)) {
|
|
9469
|
-
throw new TypeError(`${
|
|
9558
|
+
throw new TypeError(`${path19} contains unsupported field: ${key}`);
|
|
9470
9559
|
}
|
|
9471
9560
|
}
|
|
9472
9561
|
}
|
|
@@ -9474,9 +9563,9 @@ function assertSnapshotKeys(value, allowed, path18, allowedSymbols = new Set) {
|
|
|
9474
9563
|
// node_modules/dotenv/lib/main.js
|
|
9475
9564
|
var require_main = __commonJS((exports, module) => {
|
|
9476
9565
|
var fs14 = __require("fs");
|
|
9477
|
-
var
|
|
9566
|
+
var path19 = __require("path");
|
|
9478
9567
|
var os2 = __require("os");
|
|
9479
|
-
var
|
|
9568
|
+
var crypto4 = __require("crypto");
|
|
9480
9569
|
var TIPS = [
|
|
9481
9570
|
"\u25C8 encrypted .env [www.dotenvx.com]",
|
|
9482
9571
|
"\u25C8 secrets for agents [www.dotenvx.com]",
|
|
@@ -9615,7 +9704,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
9615
9704
|
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
9616
9705
|
}
|
|
9617
9706
|
} else {
|
|
9618
|
-
possibleVaultPath =
|
|
9707
|
+
possibleVaultPath = path19.resolve(process.cwd(), ".env.vault");
|
|
9619
9708
|
}
|
|
9620
9709
|
if (fs14.existsSync(possibleVaultPath)) {
|
|
9621
9710
|
return possibleVaultPath;
|
|
@@ -9623,7 +9712,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
9623
9712
|
return null;
|
|
9624
9713
|
}
|
|
9625
9714
|
function _resolveHome(envPath) {
|
|
9626
|
-
return envPath[0] === "~" ?
|
|
9715
|
+
return envPath[0] === "~" ? path19.join(os2.homedir(), envPath.slice(1)) : envPath;
|
|
9627
9716
|
}
|
|
9628
9717
|
function _configVault(options) {
|
|
9629
9718
|
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
@@ -9640,7 +9729,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
9640
9729
|
return { parsed };
|
|
9641
9730
|
}
|
|
9642
9731
|
function configDotenv(options) {
|
|
9643
|
-
const dotenvPath =
|
|
9732
|
+
const dotenvPath = path19.resolve(process.cwd(), ".env");
|
|
9644
9733
|
let encoding = "utf8";
|
|
9645
9734
|
let processEnv = process.env;
|
|
9646
9735
|
if (options && options.processEnv != null) {
|
|
@@ -9668,13 +9757,13 @@ var require_main = __commonJS((exports, module) => {
|
|
|
9668
9757
|
}
|
|
9669
9758
|
let lastError;
|
|
9670
9759
|
const parsedAll = {};
|
|
9671
|
-
for (const
|
|
9760
|
+
for (const path20 of optionPaths) {
|
|
9672
9761
|
try {
|
|
9673
|
-
const parsed = DotenvModule.parse(fs14.readFileSync(
|
|
9762
|
+
const parsed = DotenvModule.parse(fs14.readFileSync(path20, { encoding }));
|
|
9674
9763
|
DotenvModule.populate(parsedAll, parsed, options);
|
|
9675
9764
|
} catch (e) {
|
|
9676
9765
|
if (debug) {
|
|
9677
|
-
_debug(`failed to load ${
|
|
9766
|
+
_debug(`failed to load ${path20} ${e.message}`);
|
|
9678
9767
|
}
|
|
9679
9768
|
lastError = e;
|
|
9680
9769
|
}
|
|
@@ -9687,7 +9776,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
9687
9776
|
const shortPaths = [];
|
|
9688
9777
|
for (const filePath of optionPaths) {
|
|
9689
9778
|
try {
|
|
9690
|
-
const relative =
|
|
9779
|
+
const relative = path19.relative(process.cwd(), filePath);
|
|
9691
9780
|
shortPaths.push(relative);
|
|
9692
9781
|
} catch (e) {
|
|
9693
9782
|
if (debug) {
|
|
@@ -9722,7 +9811,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
9722
9811
|
const authTag = ciphertext.subarray(-16);
|
|
9723
9812
|
ciphertext = ciphertext.subarray(12, -16);
|
|
9724
9813
|
try {
|
|
9725
|
-
const aesgcm =
|
|
9814
|
+
const aesgcm = crypto4.createDecipheriv("aes-256-gcm", key, nonce);
|
|
9726
9815
|
aesgcm.setAuthTag(authTag);
|
|
9727
9816
|
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
9728
9817
|
} catch (error) {
|
|
@@ -9826,7 +9915,7 @@ var init_time = __esm(() => {
|
|
|
9826
9915
|
|
|
9827
9916
|
// src/tasks/source/bounded-document.ts
|
|
9828
9917
|
import fs14 from "fs";
|
|
9829
|
-
import
|
|
9918
|
+
import path19 from "path";
|
|
9830
9919
|
import { types as utilTypes } from "util";
|
|
9831
9920
|
function own2(value, key) {
|
|
9832
9921
|
return Object.hasOwn(value, key);
|
|
@@ -9997,7 +10086,7 @@ function parseTools(value, ctx) {
|
|
|
9997
10086
|
sourceError(ctx, ["akm", "tools"], "must be a string, string array, mapping, or null.");
|
|
9998
10087
|
}
|
|
9999
10088
|
function validateWorkingDirectory(value, ctx) {
|
|
10000
|
-
if (value.trim().length === 0 || value.includes("\x00") ||
|
|
10089
|
+
if (value.trim().length === 0 || value.includes("\x00") || path19.posix.isAbsolute(value.replaceAll("\\", "/")) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\")) {
|
|
10001
10090
|
sourceError(ctx, ["working-directory"], "must be a non-empty relative path contained by the workspace root.");
|
|
10002
10091
|
}
|
|
10003
10092
|
const segments = value.replaceAll("\\", "/").split("/");
|
|
@@ -10011,7 +10100,7 @@ function validateWorkingDirectory(value, ctx) {
|
|
|
10011
10100
|
let realCandidate;
|
|
10012
10101
|
try {
|
|
10013
10102
|
realRoot = fs14.realpathSync(ctx.workspaceRoot);
|
|
10014
|
-
const candidate =
|
|
10103
|
+
const candidate = path19.resolve(realRoot, value);
|
|
10015
10104
|
const stat = fs14.statSync(candidate);
|
|
10016
10105
|
if (!stat.isDirectory())
|
|
10017
10106
|
sourceError(ctx, ["working-directory"], "must resolve to a directory.");
|
|
@@ -10021,8 +10110,8 @@ function validateWorkingDirectory(value, ctx) {
|
|
|
10021
10110
|
throw cause;
|
|
10022
10111
|
sourceError(ctx, ["working-directory"], `cannot be physically verified: ${cause instanceof Error ? cause.message : String(cause)}.`);
|
|
10023
10112
|
}
|
|
10024
|
-
const relative =
|
|
10025
|
-
if (relative.startsWith("..") ||
|
|
10113
|
+
const relative = path19.relative(realRoot, realCandidate);
|
|
10114
|
+
if (relative.startsWith("..") || path19.isAbsolute(relative)) {
|
|
10026
10115
|
sourceError(ctx, ["working-directory"], "resolves outside the workspace root and is not physically contained.");
|
|
10027
10116
|
}
|
|
10028
10117
|
}
|
|
@@ -10191,34 +10280,34 @@ function checkJsonSchemaDefinition(schema) {
|
|
|
10191
10280
|
checkDefinitionNode(schema, [], issues, 0);
|
|
10192
10281
|
return issues;
|
|
10193
10282
|
}
|
|
10194
|
-
function pointerFor(
|
|
10195
|
-
return
|
|
10283
|
+
function pointerFor(path20) {
|
|
10284
|
+
return path20.length === 0 ? "$" : `$.${path20.map(String).join(".")}`;
|
|
10196
10285
|
}
|
|
10197
|
-
function pushIssue(issues,
|
|
10198
|
-
issues.push({ path: [...
|
|
10286
|
+
function pushIssue(issues, path20, keyword, kind, message) {
|
|
10287
|
+
issues.push({ path: [...path20], pointer: pointerFor(path20), keyword, kind, message });
|
|
10199
10288
|
}
|
|
10200
10289
|
function isSupportedEnumValue(value) {
|
|
10201
10290
|
return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
|
|
10202
10291
|
}
|
|
10203
|
-
function checkDefinitionNode(schema,
|
|
10292
|
+
function checkDefinitionNode(schema, path20, issues, depth) {
|
|
10204
10293
|
if (depth > MAX_DEFINITION_DEPTH) {
|
|
10205
|
-
pushIssue(issues,
|
|
10294
|
+
pushIssue(issues, path20, "(depth)", "malformed", `schema nesting exceeds the depth limit of ${MAX_DEFINITION_DEPTH}`);
|
|
10206
10295
|
return;
|
|
10207
10296
|
}
|
|
10208
10297
|
for (const keyword of Object.keys(schema)) {
|
|
10209
10298
|
if (UNSUPPORTED_KEYWORDS.has(keyword)) {
|
|
10210
10299
|
const hint = UNSUPPORTED_KEYWORD_HINTS.get(keyword);
|
|
10211
|
-
pushIssue(issues, [...
|
|
10300
|
+
pushIssue(issues, [...path20, keyword], keyword, "unsupported", `keyword "${keyword}" is not enforced by the workflow schema subset \u2014 the schema would silently not ` + `constrain what it looks like it constrains${hint ? `; ${hint}` : ""}`);
|
|
10212
10301
|
}
|
|
10213
10302
|
}
|
|
10214
10303
|
const declared = schema.type;
|
|
10215
10304
|
if (declared !== undefined) {
|
|
10216
10305
|
const names = Array.isArray(declared) ? declared : [declared];
|
|
10217
10306
|
if (names.length === 0) {
|
|
10218
|
-
pushIssue(issues, [...
|
|
10307
|
+
pushIssue(issues, [...path20, "type"], "type", "malformed", `"type" must name at least one type`);
|
|
10219
10308
|
}
|
|
10220
10309
|
for (const [index, name] of names.entries()) {
|
|
10221
|
-
const namePath = Array.isArray(declared) ? [...
|
|
10310
|
+
const namePath = Array.isArray(declared) ? [...path20, "type", index] : [...path20, "type"];
|
|
10222
10311
|
if (typeof name !== "string") {
|
|
10223
10312
|
pushIssue(issues, namePath, "type", "malformed", `"type" must be a string or an array of strings`);
|
|
10224
10313
|
} else if (!KNOWN_TYPE_NAMES.has(name)) {
|
|
@@ -10228,12 +10317,12 @@ function checkDefinitionNode(schema, path19, issues, depth) {
|
|
|
10228
10317
|
}
|
|
10229
10318
|
if (schema.enum !== undefined) {
|
|
10230
10319
|
if (!Array.isArray(schema.enum) || schema.enum.length === 0) {
|
|
10231
|
-
pushIssue(issues, [...
|
|
10320
|
+
pushIssue(issues, [...path20, "enum"], "enum", "malformed", `"enum" must be a non-empty array of allowed values`);
|
|
10232
10321
|
} else {
|
|
10233
10322
|
schema.enum.forEach((value, index) => {
|
|
10234
10323
|
if (isSupportedEnumValue(value))
|
|
10235
10324
|
return;
|
|
10236
|
-
pushIssue(issues, [...
|
|
10325
|
+
pushIssue(issues, [...path20, "enum", index], "enum", "unsupported", `"enum" values must be JSON primitives (string, finite number, boolean, or null) in the workflow ` + `schema subset \u2014 object and array enum members cannot be matched by the runtime subset`);
|
|
10237
10326
|
});
|
|
10238
10327
|
}
|
|
10239
10328
|
}
|
|
@@ -10242,68 +10331,68 @@ function checkDefinitionNode(schema, path19, issues, depth) {
|
|
|
10242
10331
|
if (branches === undefined)
|
|
10243
10332
|
continue;
|
|
10244
10333
|
if (!Array.isArray(branches) || branches.length === 0) {
|
|
10245
|
-
pushIssue(issues, [...
|
|
10334
|
+
pushIssue(issues, [...path20, keyword], keyword, "malformed", `"${keyword}" must be a non-empty array of schema objects`);
|
|
10246
10335
|
continue;
|
|
10247
10336
|
}
|
|
10248
10337
|
branches.forEach((branch, index) => {
|
|
10249
10338
|
if (isRecord(branch)) {
|
|
10250
|
-
checkDefinitionNode(branch, [...
|
|
10339
|
+
checkDefinitionNode(branch, [...path20, keyword, index], issues, depth + 1);
|
|
10251
10340
|
} else {
|
|
10252
|
-
pushIssue(issues, [...
|
|
10341
|
+
pushIssue(issues, [...path20, keyword, index], keyword, "malformed", `"${keyword}[${index}]" must be a schema object`);
|
|
10253
10342
|
}
|
|
10254
10343
|
});
|
|
10255
10344
|
}
|
|
10256
10345
|
if (schema.not !== undefined) {
|
|
10257
10346
|
if (isRecord(schema.not)) {
|
|
10258
|
-
checkDefinitionNode(schema.not, [...
|
|
10347
|
+
checkDefinitionNode(schema.not, [...path20, "not"], issues, depth + 1);
|
|
10259
10348
|
} else {
|
|
10260
|
-
pushIssue(issues, [...
|
|
10349
|
+
pushIssue(issues, [...path20, "not"], "not", "malformed", `"not" must be a schema object`);
|
|
10261
10350
|
}
|
|
10262
10351
|
}
|
|
10263
10352
|
if (schema.required !== undefined) {
|
|
10264
10353
|
if (!Array.isArray(schema.required) || !schema.required.every((key) => typeof key === "string")) {
|
|
10265
|
-
pushIssue(issues, [...
|
|
10354
|
+
pushIssue(issues, [...path20, "required"], "required", "malformed", `"required" must be an array of property-name strings`);
|
|
10266
10355
|
}
|
|
10267
10356
|
}
|
|
10268
10357
|
if (schema.properties !== undefined) {
|
|
10269
10358
|
if (!isRecord(schema.properties)) {
|
|
10270
|
-
pushIssue(issues, [...
|
|
10359
|
+
pushIssue(issues, [...path20, "properties"], "properties", "malformed", `"properties" must be an object mapping property names to schemas`);
|
|
10271
10360
|
} else {
|
|
10272
10361
|
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
10273
10362
|
if (isRecord(propSchema)) {
|
|
10274
|
-
checkDefinitionNode(propSchema, [...
|
|
10363
|
+
checkDefinitionNode(propSchema, [...path20, "properties", key], issues, depth + 1);
|
|
10275
10364
|
} else {
|
|
10276
|
-
pushIssue(issues, [...
|
|
10365
|
+
pushIssue(issues, [...path20, "properties", key], "properties", "malformed", `property ${JSON.stringify(key)} must be a schema object`);
|
|
10277
10366
|
}
|
|
10278
10367
|
}
|
|
10279
10368
|
}
|
|
10280
10369
|
}
|
|
10281
10370
|
if (schema.items !== undefined) {
|
|
10282
10371
|
if (isRecord(schema.items)) {
|
|
10283
|
-
checkDefinitionNode(schema.items, [...
|
|
10372
|
+
checkDefinitionNode(schema.items, [...path20, "items"], issues, depth + 1);
|
|
10284
10373
|
} else if (Array.isArray(schema.items)) {
|
|
10285
|
-
pushIssue(issues, [...
|
|
10374
|
+
pushIssue(issues, [...path20, "items"], "items", "unsupported", `tuple-form "items" (an array of schemas) is not enforced by the workflow schema subset \u2014 use a single schema object`);
|
|
10286
10375
|
} else {
|
|
10287
|
-
pushIssue(issues, [...
|
|
10376
|
+
pushIssue(issues, [...path20, "items"], "items", "malformed", `"items" must be a schema object`);
|
|
10288
10377
|
}
|
|
10289
10378
|
}
|
|
10290
10379
|
if (schema.additionalProperties !== undefined && typeof schema.additionalProperties !== "boolean") {
|
|
10291
10380
|
if (isRecord(schema.additionalProperties)) {
|
|
10292
|
-
pushIssue(issues, [...
|
|
10381
|
+
pushIssue(issues, [...path20, "additionalProperties"], "additionalProperties", "unsupported", `schema-form "additionalProperties" is not enforced by the workflow schema subset \u2014 only "additionalProperties: false" is`);
|
|
10293
10382
|
} else {
|
|
10294
|
-
pushIssue(issues, [...
|
|
10383
|
+
pushIssue(issues, [...path20, "additionalProperties"], "additionalProperties", "malformed", `"additionalProperties" must be a boolean (only "false" is enforced)`);
|
|
10295
10384
|
}
|
|
10296
10385
|
}
|
|
10297
10386
|
for (const keyword of ["minItems", "maxItems", "minLength", "maxLength"]) {
|
|
10298
10387
|
const value = schema[keyword];
|
|
10299
10388
|
if (value !== undefined && (typeof value !== "number" || !Number.isInteger(value) || value < 0)) {
|
|
10300
|
-
pushIssue(issues, [...
|
|
10389
|
+
pushIssue(issues, [...path20, keyword], keyword, "malformed", `"${keyword}" must be a non-negative integer`);
|
|
10301
10390
|
}
|
|
10302
10391
|
}
|
|
10303
10392
|
for (const keyword of ["minimum", "maximum"]) {
|
|
10304
10393
|
const value = schema[keyword];
|
|
10305
10394
|
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value))) {
|
|
10306
|
-
pushIssue(issues, [...
|
|
10395
|
+
pushIssue(issues, [...path20, keyword], keyword, "malformed", `"${keyword}" must be a finite number`);
|
|
10307
10396
|
}
|
|
10308
10397
|
}
|
|
10309
10398
|
}
|
|
@@ -10328,9 +10417,9 @@ function matchesType(actual, expected) {
|
|
|
10328
10417
|
return true;
|
|
10329
10418
|
return expected === "number" && actual === "integer";
|
|
10330
10419
|
}
|
|
10331
|
-
function branchErrors(value, schema,
|
|
10420
|
+
function branchErrors(value, schema, path20, ctx) {
|
|
10332
10421
|
const errors3 = [];
|
|
10333
|
-
validateNode(value, schema,
|
|
10422
|
+
validateNode(value, schema, path20, { ...ctx, errors: errors3, depth: ctx.depth + 1 });
|
|
10334
10423
|
return errors3;
|
|
10335
10424
|
}
|
|
10336
10425
|
function combinatorBranches(schema, keyword) {
|
|
@@ -10345,9 +10434,9 @@ function summarizeBranchFailures(failures) {
|
|
|
10345
10434
|
shown.push(`\u2026${failures.length - shown.length} more`);
|
|
10346
10435
|
return shown.join("; ");
|
|
10347
10436
|
}
|
|
10348
|
-
function validateCombinators(value, schema,
|
|
10437
|
+
function validateCombinators(value, schema, path20, ctx) {
|
|
10349
10438
|
for (const branch of combinatorBranches(schema, "allOf")) {
|
|
10350
|
-
ctx.errors.push(...branchErrors(value, branch,
|
|
10439
|
+
ctx.errors.push(...branchErrors(value, branch, path20, ctx));
|
|
10351
10440
|
}
|
|
10352
10441
|
for (const keyword of ["anyOf", "oneOf"]) {
|
|
10353
10442
|
const branches = combinatorBranches(schema, keyword);
|
|
@@ -10356,27 +10445,27 @@ function validateCombinators(value, schema, path19, ctx) {
|
|
|
10356
10445
|
const failures = [];
|
|
10357
10446
|
const matched = [];
|
|
10358
10447
|
branches.forEach((branch, index) => {
|
|
10359
|
-
const errors3 = branchErrors(value, branch,
|
|
10448
|
+
const errors3 = branchErrors(value, branch, path20, ctx);
|
|
10360
10449
|
if (errors3.length === 0)
|
|
10361
10450
|
matched.push(index + 1);
|
|
10362
10451
|
else
|
|
10363
10452
|
failures.push({ index, errors: errors3 });
|
|
10364
10453
|
});
|
|
10365
10454
|
if (matched.length === 0) {
|
|
10366
|
-
ctx.errors.push(`${
|
|
10455
|
+
ctx.errors.push(`${path20}: value matches none of the ${branches.length} "${keyword}" schemas (${summarizeBranchFailures(failures)})`);
|
|
10367
10456
|
} else if (keyword === "oneOf" && matched.length > 1) {
|
|
10368
|
-
ctx.errors.push(`${
|
|
10457
|
+
ctx.errors.push(`${path20}: value matches ${matched.length} "oneOf" schemas (branches ${matched.join(", ")}); exactly one must match`);
|
|
10369
10458
|
}
|
|
10370
10459
|
}
|
|
10371
10460
|
const not = schema.not;
|
|
10372
|
-
if (isRecord(not) && branchErrors(value, not,
|
|
10373
|
-
ctx.errors.push(`${
|
|
10461
|
+
if (isRecord(not) && branchErrors(value, not, path20, ctx).length === 0) {
|
|
10462
|
+
ctx.errors.push(`${path20}: value must not match the "not" schema`);
|
|
10374
10463
|
}
|
|
10375
10464
|
}
|
|
10376
|
-
function validateNode(value, schema,
|
|
10465
|
+
function validateNode(value, schema, path20, ctx) {
|
|
10377
10466
|
const errors3 = ctx.errors;
|
|
10378
10467
|
if (ctx.depth > MAX_DEFINITION_DEPTH) {
|
|
10379
|
-
errors3.push(`${
|
|
10468
|
+
errors3.push(`${path20}: schema nesting exceeds the depth limit of ${MAX_DEFINITION_DEPTH}`);
|
|
10380
10469
|
return;
|
|
10381
10470
|
}
|
|
10382
10471
|
if (--ctx.budget.nodes < 0)
|
|
@@ -10386,47 +10475,47 @@ function validateNode(value, schema, path19, ctx) {
|
|
|
10386
10475
|
if (typeof declared === "string" || Array.isArray(declared)) {
|
|
10387
10476
|
const expected = (Array.isArray(declared) ? declared : [declared]).filter((t) => typeof t === "string");
|
|
10388
10477
|
if (expected.length > 0 && !expected.some((t) => matchesType(actual, t))) {
|
|
10389
|
-
errors3.push(`${
|
|
10478
|
+
errors3.push(`${path20}: expected type ${expected.join(" | ")}, got ${actual}`);
|
|
10390
10479
|
return;
|
|
10391
10480
|
}
|
|
10392
10481
|
}
|
|
10393
10482
|
if (Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
10394
10483
|
const allowed = schema.enum;
|
|
10395
10484
|
if (!allowed.some((candidate) => candidate === value)) {
|
|
10396
|
-
errors3.push(ctx.redactValues ? `${
|
|
10485
|
+
errors3.push(ctx.redactValues ? `${path20}: value is not one of ${JSON.stringify(allowed)}` : `${path20}: value ${JSON.stringify(value)} is not one of ${JSON.stringify(allowed)}`);
|
|
10397
10486
|
return;
|
|
10398
10487
|
}
|
|
10399
10488
|
}
|
|
10400
|
-
validateCombinators(value, schema,
|
|
10489
|
+
validateCombinators(value, schema, path20, ctx);
|
|
10401
10490
|
if (actual === "string" && typeof value === "string") {
|
|
10402
10491
|
if (typeof schema.minLength === "number" && value.length < schema.minLength) {
|
|
10403
|
-
errors3.push(`${
|
|
10492
|
+
errors3.push(`${path20}: string shorter than minLength ${schema.minLength}`);
|
|
10404
10493
|
}
|
|
10405
10494
|
if (typeof schema.maxLength === "number" && value.length > schema.maxLength) {
|
|
10406
|
-
errors3.push(`${
|
|
10495
|
+
errors3.push(`${path20}: string longer than maxLength ${schema.maxLength}`);
|
|
10407
10496
|
}
|
|
10408
10497
|
return;
|
|
10409
10498
|
}
|
|
10410
10499
|
if ((actual === "number" || actual === "integer") && typeof value === "number") {
|
|
10411
10500
|
if (typeof schema.minimum === "number" && value < schema.minimum) {
|
|
10412
|
-
errors3.push(ctx.redactValues ? `${
|
|
10501
|
+
errors3.push(ctx.redactValues ? `${path20}: value is below minimum ${schema.minimum}` : `${path20}: ${value} is below minimum ${schema.minimum}`);
|
|
10413
10502
|
}
|
|
10414
10503
|
if (typeof schema.maximum === "number" && value > schema.maximum) {
|
|
10415
|
-
errors3.push(ctx.redactValues ? `${
|
|
10504
|
+
errors3.push(ctx.redactValues ? `${path20}: value is above maximum ${schema.maximum}` : `${path20}: ${value} is above maximum ${schema.maximum}`);
|
|
10416
10505
|
}
|
|
10417
10506
|
return;
|
|
10418
10507
|
}
|
|
10419
10508
|
if (actual === "array" && Array.isArray(value)) {
|
|
10420
10509
|
if (typeof schema.minItems === "number" && value.length < schema.minItems) {
|
|
10421
|
-
errors3.push(`${
|
|
10510
|
+
errors3.push(`${path20}: array has fewer than minItems ${schema.minItems}`);
|
|
10422
10511
|
}
|
|
10423
10512
|
if (typeof schema.maxItems === "number" && value.length > schema.maxItems) {
|
|
10424
|
-
errors3.push(`${
|
|
10513
|
+
errors3.push(`${path20}: array has more than maxItems ${schema.maxItems}`);
|
|
10425
10514
|
}
|
|
10426
10515
|
const items = schema.items;
|
|
10427
10516
|
if (items && typeof items === "object" && !Array.isArray(items)) {
|
|
10428
10517
|
value.forEach((element, index) => {
|
|
10429
|
-
validateNode(element, items, `${
|
|
10518
|
+
validateNode(element, items, `${path20}[${index}]`, {
|
|
10430
10519
|
...ctx,
|
|
10431
10520
|
depth: ctx.depth + 1
|
|
10432
10521
|
});
|
|
@@ -10440,7 +10529,7 @@ function validateNode(value, schema, path19, ctx) {
|
|
|
10440
10529
|
if (Array.isArray(schema.required)) {
|
|
10441
10530
|
for (const key of schema.required) {
|
|
10442
10531
|
if (typeof key === "string" && !Object.hasOwn(record, key)) {
|
|
10443
|
-
errors3.push(`${
|
|
10532
|
+
errors3.push(`${path20}: missing required property "${key}"`);
|
|
10444
10533
|
}
|
|
10445
10534
|
}
|
|
10446
10535
|
}
|
|
@@ -10449,7 +10538,7 @@ function validateNode(value, schema, path19, ctx) {
|
|
|
10449
10538
|
if (!Object.hasOwn(record, key))
|
|
10450
10539
|
continue;
|
|
10451
10540
|
if (propSchema && typeof propSchema === "object" && !Array.isArray(propSchema)) {
|
|
10452
|
-
validateNode(record[key], propSchema, `${
|
|
10541
|
+
validateNode(record[key], propSchema, `${path20}.${key}`, {
|
|
10453
10542
|
...ctx,
|
|
10454
10543
|
depth: ctx.depth + 1
|
|
10455
10544
|
});
|
|
@@ -10459,7 +10548,7 @@ function validateNode(value, schema, path19, ctx) {
|
|
|
10459
10548
|
if (schema.additionalProperties === false) {
|
|
10460
10549
|
for (const key of Object.keys(record)) {
|
|
10461
10550
|
if (!properties || !Object.hasOwn(properties, key)) {
|
|
10462
|
-
errors3.push(`${
|
|
10551
|
+
errors3.push(`${path20}: unexpected property "${key}" (additionalProperties: false)`);
|
|
10463
10552
|
}
|
|
10464
10553
|
}
|
|
10465
10554
|
}
|
|
@@ -10640,10 +10729,10 @@ function parseReference(source) {
|
|
|
10640
10729
|
if (!output || output.name !== "output") {
|
|
10641
10730
|
return { ok: false, message: `Expected ".output" after "steps.${stepId.name}" in "${text}".` };
|
|
10642
10731
|
}
|
|
10643
|
-
const
|
|
10644
|
-
if (!
|
|
10645
|
-
return { ok: false, message:
|
|
10646
|
-
return { ok: true, expr: { kind: "stepOutput", stepId: stepId.name, path:
|
|
10732
|
+
const path22 = parsePath(text, output.end);
|
|
10733
|
+
if (!path22.ok)
|
|
10734
|
+
return { ok: false, message: path22.message };
|
|
10735
|
+
return { ok: true, expr: { kind: "stepOutput", stepId: stepId.name, path: path22.path } };
|
|
10647
10736
|
}
|
|
10648
10737
|
default:
|
|
10649
10738
|
return { ok: false, message: `Unknown root "${root.name}" in "${text}"; ${GRAMMAR_HINT}.` };
|
|
@@ -10658,7 +10747,7 @@ function readIdent(text, start) {
|
|
|
10658
10747
|
return { name: text.slice(start, end), end };
|
|
10659
10748
|
}
|
|
10660
10749
|
function parsePath(text, start) {
|
|
10661
|
-
const
|
|
10750
|
+
const path22 = [];
|
|
10662
10751
|
let i = start;
|
|
10663
10752
|
while (i < text.length) {
|
|
10664
10753
|
const char = text[i];
|
|
@@ -10667,7 +10756,7 @@ function parsePath(text, start) {
|
|
|
10667
10756
|
if (!ident) {
|
|
10668
10757
|
return { ok: false, message: `Invalid path segment after "." at position ${i} in "${text}".` };
|
|
10669
10758
|
}
|
|
10670
|
-
|
|
10759
|
+
path22.push(ident.name);
|
|
10671
10760
|
i = ident.end;
|
|
10672
10761
|
} else if (char === "[") {
|
|
10673
10762
|
let j = i + 1;
|
|
@@ -10679,13 +10768,13 @@ function parsePath(text, start) {
|
|
|
10679
10768
|
message: `Invalid indexer at position ${i} in "${text}" \u2014 expected [<non-negative integer>].`
|
|
10680
10769
|
};
|
|
10681
10770
|
}
|
|
10682
|
-
|
|
10771
|
+
path22.push(Number.parseInt(text.slice(i + 1, j), 10));
|
|
10683
10772
|
i = j + 1;
|
|
10684
10773
|
} else {
|
|
10685
10774
|
return { ok: false, message: `Unexpected character "${char}" at position ${i} in "${text}".` };
|
|
10686
10775
|
}
|
|
10687
10776
|
}
|
|
10688
|
-
return { ok: true, path:
|
|
10777
|
+
return { ok: true, path: path22 };
|
|
10689
10778
|
}
|
|
10690
10779
|
function formatReference(expr) {
|
|
10691
10780
|
switch (expr.kind) {
|
|
@@ -11058,7 +11147,7 @@ var init_uses = __esm(() => {
|
|
|
11058
11147
|
|
|
11059
11148
|
// src/workflows/source-ir/semantics.ts
|
|
11060
11149
|
import fs15 from "fs";
|
|
11061
|
-
import
|
|
11150
|
+
import path22 from "path";
|
|
11062
11151
|
function canonicalizeWorkflowCron(value) {
|
|
11063
11152
|
const canonical = value.trim().split(/\s+/).join(" ");
|
|
11064
11153
|
if (canonical.startsWith("@") || canonical.split(" ").length !== 5) {
|
|
@@ -11094,7 +11183,7 @@ function canonicalizeWorkflowWorkingDirectory(value, workspaceRoot) {
|
|
|
11094
11183
|
}
|
|
11095
11184
|
const portable = value.replaceAll("\\", "/");
|
|
11096
11185
|
const segments = portable.split("/");
|
|
11097
|
-
if (
|
|
11186
|
+
if (path22.posix.isAbsolute(portable) || path22.win32.isAbsolute(value) || portable.startsWith("~") || segments.some((segment) => segment === "" || segment === "..")) {
|
|
11098
11187
|
throw new WorkflowSourceSemanticError("working-directory-escape", "working-directory must be relative and contained.");
|
|
11099
11188
|
}
|
|
11100
11189
|
const withoutDots = segments.filter((segment) => segment !== ".");
|
|
@@ -11174,13 +11263,13 @@ function verifyPhysicalContainment(workspaceRoot, relative) {
|
|
|
11174
11263
|
} catch {
|
|
11175
11264
|
throw new WorkflowSourceSemanticError("working-directory-unverifiable", "Workspace root cannot be physically verified.");
|
|
11176
11265
|
}
|
|
11177
|
-
const candidate =
|
|
11266
|
+
const candidate = path22.resolve(root, ...relative.split("/"));
|
|
11178
11267
|
if (!contained(root, candidate)) {
|
|
11179
11268
|
throw new WorkflowSourceSemanticError("working-directory-escape", "working-directory escapes the workspace.");
|
|
11180
11269
|
}
|
|
11181
11270
|
let current = root;
|
|
11182
11271
|
for (const segment of relative === "." ? [] : relative.split("/")) {
|
|
11183
|
-
current =
|
|
11272
|
+
current = path22.join(current, segment);
|
|
11184
11273
|
try {
|
|
11185
11274
|
const entry = fs15.lstatSync(current);
|
|
11186
11275
|
if (entry.isSymbolicLink()) {
|
|
@@ -11223,8 +11312,8 @@ function verifyPhysicalContainment(workspaceRoot, relative) {
|
|
|
11223
11312
|
}
|
|
11224
11313
|
}
|
|
11225
11314
|
function contained(root, candidate) {
|
|
11226
|
-
const relative =
|
|
11227
|
-
return relative === "" || !relative.startsWith(`..${
|
|
11315
|
+
const relative = path22.relative(root, candidate);
|
|
11316
|
+
return relative === "" || !relative.startsWith(`..${path22.sep}`) && relative !== ".." && !path22.isAbsolute(relative);
|
|
11228
11317
|
}
|
|
11229
11318
|
var TOKEN_SAFE_RUN, WorkflowSourceSemanticError;
|
|
11230
11319
|
var init_semantics = __esm(() => {
|
|
@@ -12058,7 +12147,7 @@ function parseWorkflow(markdown, source) {
|
|
|
12058
12147
|
};
|
|
12059
12148
|
}
|
|
12060
12149
|
const errors3 = [];
|
|
12061
|
-
const
|
|
12150
|
+
const path23 = source.path;
|
|
12062
12151
|
const lines = markdown.split(/\r?\n/);
|
|
12063
12152
|
const totalLines = lines.length;
|
|
12064
12153
|
const fmBlock = parseFrontmatterBlock(markdown);
|
|
@@ -12110,7 +12199,7 @@ function parseWorkflow(markdown, source) {
|
|
|
12110
12199
|
return 2;
|
|
12111
12200
|
};
|
|
12112
12201
|
const ctx = {
|
|
12113
|
-
filePath:
|
|
12202
|
+
filePath: path23,
|
|
12114
12203
|
errors: errors3,
|
|
12115
12204
|
...source.validateExecCwd ? { validateExecCwd: source.validateExecCwd } : {},
|
|
12116
12205
|
lineAt,
|
|
@@ -12123,10 +12212,10 @@ function parseWorkflow(markdown, source) {
|
|
|
12123
12212
|
if (range) {
|
|
12124
12213
|
const start = Math.max(1, lineCounter2.linePos(range[0]).line + lineOffset);
|
|
12125
12214
|
const end = Math.max(start, lineCounter2.linePos(Math.max(range[0], range[1] - 1)).line + lineOffset);
|
|
12126
|
-
return { path:
|
|
12215
|
+
return { path: path23, start, end };
|
|
12127
12216
|
}
|
|
12128
12217
|
}
|
|
12129
|
-
return { path:
|
|
12218
|
+
return { path: path23, start: frontmatterEndLine, end: frontmatterEndLine };
|
|
12130
12219
|
},
|
|
12131
12220
|
err: (p, message) => errors3.push({ line: lineAt(p), message }),
|
|
12132
12221
|
errAtLine: (line, message) => errors3.push({ line, message })
|
|
@@ -12150,7 +12239,7 @@ function parseWorkflow(markdown, source) {
|
|
|
12150
12239
|
const parsedSteps = parseSteps(ctx, root.steps);
|
|
12151
12240
|
const toc = parseMarkdownToc(markdown);
|
|
12152
12241
|
const declaredIds = new Set(parsedSteps.map((s) => s.id));
|
|
12153
|
-
const { sections, preamble } = bindStepSections(toc.headings, lines, fmBlock.bodyStartLine, totalLines,
|
|
12242
|
+
const { sections, preamble } = bindStepSections(toc.headings, lines, fmBlock.bodyStartLine, totalLines, path23, declaredIds, errors3);
|
|
12154
12243
|
const steps = parsedSteps.map((step, index) => {
|
|
12155
12244
|
const section = sections.get(step.id);
|
|
12156
12245
|
if (!section) {
|
|
@@ -12194,14 +12283,14 @@ function parseWorkflow(markdown, source) {
|
|
|
12194
12283
|
...budget ? { budget } : {},
|
|
12195
12284
|
steps,
|
|
12196
12285
|
...preamble ? { preamble } : {},
|
|
12197
|
-
source: { path:
|
|
12286
|
+
source: { path: path23, lineCount: totalLines }
|
|
12198
12287
|
};
|
|
12199
12288
|
runSemanticChecks(draft, root, frontmatterEndLine, errors3);
|
|
12200
12289
|
if (errors3.length > 0)
|
|
12201
12290
|
return { ok: false, errors: sortErrors(errors3) };
|
|
12202
12291
|
return { ok: true, document: draft };
|
|
12203
12292
|
}
|
|
12204
|
-
function bindStepSections(headings, lines, bodyStartLine, totalLines,
|
|
12293
|
+
function bindStepSections(headings, lines, bodyStartLine, totalLines, path23, declaredIds, errors3) {
|
|
12205
12294
|
const sections = new Map;
|
|
12206
12295
|
const h2s = headings.filter((h) => h.level === 2);
|
|
12207
12296
|
const firstH2Line = h2s[0]?.line;
|
|
@@ -12225,24 +12314,24 @@ function bindStepSections(headings, lines, bodyStartLine, totalLines, path22, de
|
|
|
12225
12314
|
continue;
|
|
12226
12315
|
}
|
|
12227
12316
|
const sectionEnd = findNextHeadingAtOrAboveLevel(headings, i, 2, totalLines);
|
|
12228
|
-
const gate = findGateSubsection(headings, i, sectionEnd,
|
|
12317
|
+
const gate = findGateSubsection(headings, i, sectionEnd, path23, h.text, errors3);
|
|
12229
12318
|
const instructionsEnd = gate ? gate.headingLine - 1 : sectionEnd;
|
|
12230
12319
|
const instructionsText = sliceProseLines(lines, h.line + 1, instructionsEnd);
|
|
12231
12320
|
const section = { headingLine: h.line };
|
|
12232
12321
|
if (instructionsText) {
|
|
12233
|
-
section.instructions = { text: instructionsText, source: { path:
|
|
12322
|
+
section.instructions = { text: instructionsText, source: { path: path23, start: h.line + 1, end: instructionsEnd } };
|
|
12234
12323
|
}
|
|
12235
12324
|
if (gate) {
|
|
12236
12325
|
const gateText = sliceProseLines(lines, gate.bodyStart, gate.bodyEnd);
|
|
12237
12326
|
if (gateText) {
|
|
12238
|
-
section.gateRubric = { text: gateText, source: { path:
|
|
12327
|
+
section.gateRubric = { text: gateText, source: { path: path23, start: gate.bodyStart, end: gate.bodyEnd } };
|
|
12239
12328
|
}
|
|
12240
12329
|
}
|
|
12241
12330
|
sections.set(h.text, section);
|
|
12242
12331
|
}
|
|
12243
12332
|
return { sections, preamble: preambleRaw || undefined };
|
|
12244
12333
|
}
|
|
12245
|
-
function findGateSubsection(headings, stepHeadingIndex, sectionEnd,
|
|
12334
|
+
function findGateSubsection(headings, stepHeadingIndex, sectionEnd, path23, stepId, errors3) {
|
|
12246
12335
|
let found;
|
|
12247
12336
|
for (let j = stepHeadingIndex + 1;j < headings.length; j++) {
|
|
12248
12337
|
const h = headings[j];
|
|
@@ -12324,19 +12413,19 @@ function checkEnvelopeFields(ctx, root, fmEndLine) {
|
|
|
12324
12413
|
ctx.err(["stale_after"], `Workflow frontmatter "stale_after" must be a string.`);
|
|
12325
12414
|
}
|
|
12326
12415
|
}
|
|
12327
|
-
function checkActorStamp(ctx, value,
|
|
12416
|
+
function checkActorStamp(ctx, value, path23, label) {
|
|
12328
12417
|
if (value === undefined)
|
|
12329
12418
|
return;
|
|
12330
12419
|
if (!isRecord(value)) {
|
|
12331
|
-
ctx.err(
|
|
12420
|
+
ctx.err(path23, `Workflow frontmatter ${label} must be a mapping with a non-empty "by".`);
|
|
12332
12421
|
return;
|
|
12333
12422
|
}
|
|
12334
|
-
checkUnknownKeys(ctx, value,
|
|
12423
|
+
checkUnknownKeys(ctx, value, path23, ACTOR_STAMP_KEYS, `${label} actor stamp`);
|
|
12335
12424
|
if (typeof value.by !== "string" || value.by.length === 0) {
|
|
12336
|
-
ctx.err([...
|
|
12425
|
+
ctx.err([...path23, "by"], `Workflow frontmatter ${label} must be a mapping with a non-empty "by".`);
|
|
12337
12426
|
}
|
|
12338
12427
|
if (value.at !== undefined && typeof value.at !== "string") {
|
|
12339
|
-
ctx.err([...
|
|
12428
|
+
ctx.err([...path23, "at"], `Workflow frontmatter ${label} actor stamp "at" must be a string.`);
|
|
12340
12429
|
}
|
|
12341
12430
|
}
|
|
12342
12431
|
function readTags2(ctx, value, fmEndLine) {
|
|
@@ -12389,38 +12478,38 @@ function parseOutputs(ctx, raw) {
|
|
|
12389
12478
|
}
|
|
12390
12479
|
const outputs = {};
|
|
12391
12480
|
for (const [outputName, value] of Object.entries(raw)) {
|
|
12392
|
-
const
|
|
12481
|
+
const path23 = ["outputs", outputName];
|
|
12393
12482
|
if (!INPUT_NAME_PATTERN.test(outputName)) {
|
|
12394
|
-
ctx.err(
|
|
12483
|
+
ctx.err(path23, `Output name "${outputName}" is invalid. Use letters, digits, and underscores, starting with a letter or ` + `underscore, so "steps.<child>.output.${outputName}" can address it.`);
|
|
12395
12484
|
continue;
|
|
12396
12485
|
}
|
|
12397
12486
|
if (!isRecord(value)) {
|
|
12398
|
-
ctx.err(
|
|
12487
|
+
ctx.err(path23, `Output "${outputName}" must be a mapping with "from" (and optional "schema").`);
|
|
12399
12488
|
continue;
|
|
12400
12489
|
}
|
|
12401
|
-
checkUnknownKeys(ctx, value,
|
|
12490
|
+
checkUnknownKeys(ctx, value, path23, OUTPUT_ENTRY_KEYS, `output "${outputName}"`);
|
|
12402
12491
|
if (typeof value.from !== "string" || value.from.trim() === "") {
|
|
12403
|
-
ctx.err([...
|
|
12492
|
+
ctx.err([...path23, "from"], `Output "${outputName}" must declare "from": a steps.<id>.output(.<seg>)* reference.`);
|
|
12404
12493
|
continue;
|
|
12405
12494
|
}
|
|
12406
12495
|
const parsedFrom = parseReference(value.from);
|
|
12407
12496
|
if (!parsedFrom.ok) {
|
|
12408
|
-
ctx.err([...
|
|
12497
|
+
ctx.err([...path23, "from"], `Output "${outputName}" "from": ${parsedFrom.message}`);
|
|
12409
12498
|
continue;
|
|
12410
12499
|
}
|
|
12411
12500
|
if (parsedFrom.expr.kind !== "stepOutput") {
|
|
12412
|
-
ctx.err([...
|
|
12501
|
+
ctx.err([...path23, "from"], `Output "${outputName}" "from" must reference a step output (steps.<id>.output...), not a param \u2014 an ` + `output projects a step artifact, never a param (got "${value.from}").`);
|
|
12413
12502
|
continue;
|
|
12414
12503
|
}
|
|
12415
12504
|
const entry = { from: value.from };
|
|
12416
12505
|
if (value.schema !== undefined) {
|
|
12417
12506
|
if (!isRecord(value.schema)) {
|
|
12418
|
-
ctx.err([...
|
|
12507
|
+
ctx.err([...path23, "schema"], `Output "${outputName}" "schema" must be a JSON Schema object.`);
|
|
12419
12508
|
} else {
|
|
12420
12509
|
if (jsonBytes(value.schema) > WORKFLOW_MAX_SCHEMA_BYTES) {
|
|
12421
|
-
ctx.err([...
|
|
12510
|
+
ctx.err([...path23, "schema"], `Output "${outputName}" schema exceeds the 256 KiB resource limit.`);
|
|
12422
12511
|
}
|
|
12423
|
-
checkSchemaDefinition(ctx, value.schema, [...
|
|
12512
|
+
checkSchemaDefinition(ctx, value.schema, [...path23, "schema"], `Output "${outputName}" schema`);
|
|
12424
12513
|
entry.schema = value.schema;
|
|
12425
12514
|
}
|
|
12426
12515
|
}
|
|
@@ -12431,15 +12520,15 @@ function parseOutputs(ctx, raw) {
|
|
|
12431
12520
|
function parseDefaults(ctx, raw) {
|
|
12432
12521
|
if (raw === undefined)
|
|
12433
12522
|
return;
|
|
12434
|
-
const
|
|
12523
|
+
const path23 = ["defaults"];
|
|
12435
12524
|
if (!isRecord(raw)) {
|
|
12436
|
-
ctx.err(
|
|
12525
|
+
ctx.err(path23, `"defaults" must be a mapping with any of: ${DEFAULTS_KEYS.join(", ")}.`);
|
|
12437
12526
|
return;
|
|
12438
12527
|
}
|
|
12439
|
-
checkUnknownKeys(ctx, raw,
|
|
12528
|
+
checkUnknownKeys(ctx, raw, path23, DEFAULTS_KEYS, `"defaults"`);
|
|
12440
12529
|
const defaults = {};
|
|
12441
12530
|
if (raw.engine !== undefined) {
|
|
12442
|
-
const engine = parseEngineName(ctx, raw.engine, [...
|
|
12531
|
+
const engine = parseEngineName(ctx, raw.engine, [...path23, "engine"], `"defaults.engine"`);
|
|
12443
12532
|
if (engine !== undefined)
|
|
12444
12533
|
defaults.engine = engine;
|
|
12445
12534
|
}
|
|
@@ -12447,15 +12536,15 @@ function parseDefaults(ctx, raw) {
|
|
|
12447
12536
|
if (typeof raw.model === "string" && raw.model.trim() !== "")
|
|
12448
12537
|
defaults.model = raw.model.trim();
|
|
12449
12538
|
else
|
|
12450
|
-
ctx.err([...
|
|
12539
|
+
ctx.err([...path23, "model"], `"defaults.model" must be a non-empty string (a model alias or exact id).`);
|
|
12451
12540
|
}
|
|
12452
|
-
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...
|
|
12541
|
+
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...path23, "timeout"], `"defaults.timeout"`);
|
|
12453
12542
|
if (timeoutMs !== undefined)
|
|
12454
12543
|
defaults.timeoutMs = timeoutMs;
|
|
12455
|
-
const onError = parseEnumField(ctx, raw.on_error, [...
|
|
12544
|
+
const onError = parseEnumField(ctx, raw.on_error, [...path23, "on_error"], `"defaults.on_error"`, PROGRAM_ON_ERROR);
|
|
12456
12545
|
if (onError !== undefined)
|
|
12457
12546
|
defaults.onError = onError;
|
|
12458
|
-
const llm = parseLlmOverrides(ctx, raw.llm, [...
|
|
12547
|
+
const llm = parseLlmOverrides(ctx, raw.llm, [...path23, "llm"], `"defaults.llm"`);
|
|
12459
12548
|
if (llm !== undefined)
|
|
12460
12549
|
defaults.llm = llm;
|
|
12461
12550
|
return Object.keys(defaults).length > 0 ? defaults : undefined;
|
|
@@ -12463,25 +12552,25 @@ function parseDefaults(ctx, raw) {
|
|
|
12463
12552
|
function parseBudget(ctx, raw) {
|
|
12464
12553
|
if (raw === undefined)
|
|
12465
12554
|
return;
|
|
12466
|
-
const
|
|
12555
|
+
const path23 = ["budget"];
|
|
12467
12556
|
if (!isRecord(raw)) {
|
|
12468
|
-
ctx.err(
|
|
12557
|
+
ctx.err(path23, `"budget" must be a mapping with any of: ${BUDGET_KEYS.join(", ")}.`);
|
|
12469
12558
|
return;
|
|
12470
12559
|
}
|
|
12471
|
-
checkUnknownKeys(ctx, raw,
|
|
12560
|
+
checkUnknownKeys(ctx, raw, path23, BUDGET_KEYS, `"budget"`);
|
|
12472
12561
|
const budget = {};
|
|
12473
12562
|
if (raw.max_tokens !== undefined) {
|
|
12474
12563
|
if (typeof raw.max_tokens === "number" && Number.isInteger(raw.max_tokens) && raw.max_tokens >= 1) {
|
|
12475
12564
|
budget.maxTokens = raw.max_tokens;
|
|
12476
12565
|
} else {
|
|
12477
|
-
ctx.err([...
|
|
12566
|
+
ctx.err([...path23, "max_tokens"], `"budget.max_tokens" must be an integer >= 1.`);
|
|
12478
12567
|
}
|
|
12479
12568
|
}
|
|
12480
12569
|
if (raw.max_units !== undefined) {
|
|
12481
12570
|
if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1) {
|
|
12482
12571
|
budget.maxUnits = raw.max_units;
|
|
12483
12572
|
} else {
|
|
12484
|
-
ctx.err([...
|
|
12573
|
+
ctx.err([...path23, "max_units"], `"budget.max_units" must be an integer >= 1.`);
|
|
12485
12574
|
}
|
|
12486
12575
|
}
|
|
12487
12576
|
return Object.keys(budget).length > 0 ? budget : undefined;
|
|
@@ -12501,49 +12590,49 @@ function parseSteps(ctx, raw) {
|
|
|
12501
12590
|
const seenIds = new Map;
|
|
12502
12591
|
const routeChecks = [];
|
|
12503
12592
|
raw.forEach((rawStep, index) => {
|
|
12504
|
-
const
|
|
12593
|
+
const path23 = ["steps", index];
|
|
12505
12594
|
if (!isRecord(rawStep)) {
|
|
12506
|
-
ctx.err(
|
|
12595
|
+
ctx.err(path23, `Step ${index + 1} must be a mapping with an "id".`);
|
|
12507
12596
|
return;
|
|
12508
12597
|
}
|
|
12509
12598
|
const label = typeof rawStep.id === "string" && rawStep.id !== "" ? `Step "${rawStep.id}"` : `Step ${index + 1}`;
|
|
12510
|
-
checkUnknownKeys(ctx, rawStep,
|
|
12599
|
+
checkUnknownKeys(ctx, rawStep, path23, STEP_KEYS, label);
|
|
12511
12600
|
let id = "";
|
|
12512
12601
|
if (typeof rawStep.id !== "string" || rawStep.id === "") {
|
|
12513
|
-
ctx.err([...
|
|
12602
|
+
ctx.err([...path23, "id"], `${label} requires a non-empty string "id".`);
|
|
12514
12603
|
} else if (!PROGRAM_STEP_ID_PATTERN.test(rawStep.id)) {
|
|
12515
|
-
ctx.err([...
|
|
12604
|
+
ctx.err([...path23, "id"], `${label} has an invalid id "${rawStep.id}". A step id cannot be referenced from steps.${rawStep.id}.output ` + `unless it matches [A-Za-z_][A-Za-z0-9_-]* (a letter or underscore first, then letters, digits, ` + `underscores, or dashes; no dots, no leading digit).`);
|
|
12516
12605
|
} else {
|
|
12517
12606
|
id = rawStep.id;
|
|
12518
12607
|
const firstIndex = seenIds.get(id);
|
|
12519
12608
|
if (firstIndex !== undefined) {
|
|
12520
|
-
ctx.err([...
|
|
12609
|
+
ctx.err([...path23, "id"], `Duplicate step id "${id}" (first used by step ${firstIndex + 1}). Step ids must be unique.`);
|
|
12521
12610
|
} else {
|
|
12522
12611
|
seenIds.set(id, index);
|
|
12523
12612
|
}
|
|
12524
12613
|
}
|
|
12525
12614
|
const declaredKinds = ["map", "route"].filter((kind) => rawStep[kind] !== undefined);
|
|
12526
12615
|
if (declaredKinds.length > 1) {
|
|
12527
|
-
ctx.err(
|
|
12616
|
+
ctx.err(path23, `${label} must declare at most one of "map" or "route" (found ${declaredKinds.join(" + ")}).`);
|
|
12528
12617
|
}
|
|
12529
12618
|
const isRoute = rawStep.route !== undefined;
|
|
12530
12619
|
const isMapStep = rawStep.map !== undefined;
|
|
12531
12620
|
if (isRoute && rawStep.unit !== undefined) {
|
|
12532
|
-
ctx.err(
|
|
12621
|
+
ctx.err(path23, `${label} is a route step and cannot also declare "unit" (route steps dispatch no unit).`);
|
|
12533
12622
|
}
|
|
12534
12623
|
if (isMapStep && rawStep.unit !== undefined) {
|
|
12535
|
-
ctx.err(
|
|
12624
|
+
ctx.err(path23, `${label} is a map step; the per-item dispatch-override bag belongs at "map.unit", not top-level "unit".`);
|
|
12536
12625
|
}
|
|
12537
12626
|
if (isRoute && rawStep.inputs !== undefined) {
|
|
12538
|
-
ctx.err(
|
|
12539
|
-
}
|
|
12540
|
-
const unit = rawStep.unit !== undefined && !isRoute && !isMapStep ? parseUnit(ctx, rawStep.unit, [...
|
|
12541
|
-
const map = isMapStep ? parseMap(ctx, rawStep.map, [...
|
|
12542
|
-
const route = isRoute ? parseRoute(ctx, rawStep.route, [...
|
|
12543
|
-
const inputs = !isRoute ? parseInputs(ctx, rawStep.inputs, [...
|
|
12544
|
-
const output = parseSchemaObject(ctx, rawStep.output, [...
|
|
12545
|
-
const gate = rawStep.gate !== undefined ? parseGate(ctx, rawStep.gate, [...
|
|
12546
|
-
const step = { id, source: ctx.refAt(
|
|
12627
|
+
ctx.err(path23, `${label} is a route step and cannot declare "inputs" (route steps dispatch no unit).`);
|
|
12628
|
+
}
|
|
12629
|
+
const unit = rawStep.unit !== undefined && !isRoute && !isMapStep ? parseUnit(ctx, rawStep.unit, [...path23, "unit"], label) : undefined;
|
|
12630
|
+
const map = isMapStep ? parseMap(ctx, rawStep.map, [...path23, "map"], label) : undefined;
|
|
12631
|
+
const route = isRoute ? parseRoute(ctx, rawStep.route, [...path23, "route"], label, index, routeChecks) : undefined;
|
|
12632
|
+
const inputs = !isRoute ? parseInputs(ctx, rawStep.inputs, [...path23, "inputs"], label) : undefined;
|
|
12633
|
+
const output = parseSchemaObject(ctx, rawStep.output, [...path23, "output"], `${label} "output"`);
|
|
12634
|
+
const gate = rawStep.gate !== undefined ? parseGate(ctx, rawStep.gate, [...path23, "gate"], label) : undefined;
|
|
12635
|
+
const step = { id, source: ctx.refAt(path23) };
|
|
12547
12636
|
if (unit)
|
|
12548
12637
|
step.unit = unit;
|
|
12549
12638
|
if (map)
|
|
@@ -12575,25 +12664,25 @@ function parseSteps(ctx, raw) {
|
|
|
12575
12664
|
}
|
|
12576
12665
|
return steps;
|
|
12577
12666
|
}
|
|
12578
|
-
function parseUnit(ctx, raw,
|
|
12667
|
+
function parseUnit(ctx, raw, path23, stepLabel) {
|
|
12579
12668
|
if (!isRecord(raw)) {
|
|
12580
|
-
ctx.err(
|
|
12669
|
+
ctx.err(path23, `${stepLabel} "unit" must be a mapping (a dispatch-override bag).`);
|
|
12581
12670
|
return;
|
|
12582
12671
|
}
|
|
12583
|
-
checkUnknownKeys(ctx, raw,
|
|
12584
|
-
const unit = { source: ctx.refAt(
|
|
12672
|
+
checkUnknownKeys(ctx, raw, path23, UNIT_KEYS, `${stepLabel} "unit"`);
|
|
12673
|
+
const unit = { source: ctx.refAt(path23) };
|
|
12585
12674
|
if (raw.exec !== undefined) {
|
|
12586
|
-
const exec = parseExec(ctx, raw.exec, [...
|
|
12675
|
+
const exec = parseExec(ctx, raw.exec, [...path23, "exec"], stepLabel);
|
|
12587
12676
|
if (exec !== undefined)
|
|
12588
12677
|
unit.exec = exec;
|
|
12589
12678
|
for (const key of UNIT_ENGINE_KEYS) {
|
|
12590
12679
|
if (raw[key] === undefined)
|
|
12591
12680
|
continue;
|
|
12592
|
-
ctx.err([...
|
|
12681
|
+
ctx.err([...path23, key], `${stepLabel} "unit" declares both "exec" and "${key}". An exec unit runs a shell command and never ` + `reaches an engine, so "${key}" would have no effect \u2014 remove one of the two.`);
|
|
12593
12682
|
}
|
|
12594
12683
|
}
|
|
12595
12684
|
if (raw.engine !== undefined) {
|
|
12596
|
-
const engine = parseEngineName(ctx, raw.engine, [...
|
|
12685
|
+
const engine = parseEngineName(ctx, raw.engine, [...path23, "engine"], `${stepLabel} "engine"`);
|
|
12597
12686
|
if (engine !== undefined)
|
|
12598
12687
|
unit.engine = engine;
|
|
12599
12688
|
}
|
|
@@ -12601,21 +12690,21 @@ function parseUnit(ctx, raw, path22, stepLabel) {
|
|
|
12601
12690
|
if (typeof raw.model === "string" && raw.model.trim() !== "")
|
|
12602
12691
|
unit.model = raw.model.trim();
|
|
12603
12692
|
else
|
|
12604
|
-
ctx.err([...
|
|
12693
|
+
ctx.err([...path23, "model"], `${stepLabel} "model" must be a non-empty string (a model alias or exact id).`);
|
|
12605
12694
|
}
|
|
12606
|
-
const llm = parseLlmOverrides(ctx, raw.llm, [...
|
|
12695
|
+
const llm = parseLlmOverrides(ctx, raw.llm, [...path23, "llm"], `${stepLabel} "llm"`);
|
|
12607
12696
|
if (llm !== undefined)
|
|
12608
12697
|
unit.llm = llm;
|
|
12609
|
-
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...
|
|
12698
|
+
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...path23, "timeout"], `${stepLabel} "timeout"`);
|
|
12610
12699
|
if (timeoutMs !== undefined)
|
|
12611
12700
|
unit.timeoutMs = timeoutMs;
|
|
12612
|
-
const retry = parseRetry(ctx, raw.retry, [...
|
|
12701
|
+
const retry = parseRetry(ctx, raw.retry, [...path23, "retry"], stepLabel);
|
|
12613
12702
|
if (retry !== undefined)
|
|
12614
12703
|
unit.retry = retry;
|
|
12615
|
-
const onError = parseEnumField(ctx, raw.on_error, [...
|
|
12704
|
+
const onError = parseEnumField(ctx, raw.on_error, [...path23, "on_error"], `${stepLabel} "on_error"`, PROGRAM_ON_ERROR);
|
|
12616
12705
|
if (onError !== undefined)
|
|
12617
12706
|
unit.onError = onError;
|
|
12618
|
-
const output = parseSchemaObject(ctx, raw.output, [...
|
|
12707
|
+
const output = parseSchemaObject(ctx, raw.output, [...path23, "output"], `${stepLabel} unit "output"`);
|
|
12619
12708
|
if (output !== undefined)
|
|
12620
12709
|
unit.output = output;
|
|
12621
12710
|
if (raw.env !== undefined) {
|
|
@@ -12623,87 +12712,87 @@ function parseUnit(ctx, raw, path22, stepLabel) {
|
|
|
12623
12712
|
const envRefs = raw.env.map((entry) => entry.trim());
|
|
12624
12713
|
const duplicate = envRefs.find((ref, i) => envRefs.indexOf(ref) !== i);
|
|
12625
12714
|
if (duplicate !== undefined) {
|
|
12626
|
-
ctx.err([...
|
|
12715
|
+
ctx.err([...path23, "env"], `${stepLabel} "env" contains a duplicate entry: "${duplicate}".`);
|
|
12627
12716
|
} else {
|
|
12628
12717
|
unit.env = envRefs;
|
|
12629
12718
|
}
|
|
12630
12719
|
} else {
|
|
12631
|
-
ctx.err([...
|
|
12720
|
+
ctx.err([...path23, "env"], `${stepLabel} "env" must be a list of non-empty env asset refs.`);
|
|
12632
12721
|
}
|
|
12633
12722
|
}
|
|
12634
|
-
const isolation = parseEnumField(ctx, raw.isolation, [...
|
|
12723
|
+
const isolation = parseEnumField(ctx, raw.isolation, [...path23, "isolation"], `${stepLabel} "isolation"`, PROGRAM_ISOLATION_KINDS);
|
|
12635
12724
|
if (isolation !== undefined)
|
|
12636
12725
|
unit.isolation = isolation;
|
|
12637
12726
|
return unit;
|
|
12638
12727
|
}
|
|
12639
|
-
function parseExec(ctx, raw,
|
|
12728
|
+
function parseExec(ctx, raw, path23, stepLabel) {
|
|
12640
12729
|
if (!isRecord(raw)) {
|
|
12641
|
-
ctx.err(
|
|
12730
|
+
ctx.err(path23, `${stepLabel} "exec" must be a mapping with a "command" argv list.`);
|
|
12642
12731
|
return;
|
|
12643
12732
|
}
|
|
12644
|
-
checkUnknownKeys(ctx, raw,
|
|
12645
|
-
const command = parseExecCommand(ctx, raw.command, [...
|
|
12733
|
+
checkUnknownKeys(ctx, raw, path23, EXEC_KEYS, `${stepLabel} "exec"`);
|
|
12734
|
+
const command = parseExecCommand(ctx, raw.command, [...path23, "command"], stepLabel);
|
|
12646
12735
|
if (command === undefined)
|
|
12647
12736
|
return;
|
|
12648
12737
|
const exec = { command };
|
|
12649
|
-
const cwd = parseExecCwd(ctx, raw.cwd, [...
|
|
12738
|
+
const cwd = parseExecCwd(ctx, raw.cwd, [...path23, "cwd"], stepLabel);
|
|
12650
12739
|
if (cwd !== undefined)
|
|
12651
12740
|
exec.cwd = cwd;
|
|
12652
|
-
const passEnv = parseExecPassEnv(ctx, raw.pass_env, [...
|
|
12741
|
+
const passEnv = parseExecPassEnv(ctx, raw.pass_env, [...path23, "pass_env"], stepLabel);
|
|
12653
12742
|
if (passEnv !== undefined)
|
|
12654
12743
|
exec.passEnv = passEnv;
|
|
12655
12744
|
return exec;
|
|
12656
12745
|
}
|
|
12657
|
-
function parseExecPassEnv(ctx, raw,
|
|
12746
|
+
function parseExecPassEnv(ctx, raw, path23, stepLabel) {
|
|
12658
12747
|
if (raw === undefined)
|
|
12659
12748
|
return;
|
|
12660
12749
|
if (!Array.isArray(raw) || raw.length === 0) {
|
|
12661
|
-
ctx.err(
|
|
12750
|
+
ctx.err(path23, `${stepLabel} "exec.pass_env" must be a non-empty list of environment variable NAMES to copy through from ` + `akm's own environment, e.g. pass_env: [CARGO_HOME]. Values never appear here \u2014 use "env:" bindings for those.`);
|
|
12662
12751
|
return;
|
|
12663
12752
|
}
|
|
12664
12753
|
const names = [];
|
|
12665
12754
|
for (const [index, entry] of raw.entries()) {
|
|
12666
12755
|
if (typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry)) {
|
|
12667
|
-
ctx.err(
|
|
12756
|
+
ctx.err(path23, `${stepLabel} "exec.pass_env[${index}]" must be an environment variable name matching ` + `${WORKFLOW_ENV_VAR_NAME_PATTERN.source}.`);
|
|
12668
12757
|
return;
|
|
12669
12758
|
}
|
|
12670
12759
|
if (names.includes(entry)) {
|
|
12671
|
-
ctx.err(
|
|
12760
|
+
ctx.err(path23, `${stepLabel} "exec.pass_env" lists "${entry}" more than once.`);
|
|
12672
12761
|
return;
|
|
12673
12762
|
}
|
|
12674
12763
|
names.push(entry);
|
|
12675
12764
|
}
|
|
12676
12765
|
return names;
|
|
12677
12766
|
}
|
|
12678
|
-
function parseExecCommand(ctx, raw,
|
|
12767
|
+
function parseExecCommand(ctx, raw, path23, stepLabel) {
|
|
12679
12768
|
if (!Array.isArray(raw) || raw.length === 0) {
|
|
12680
|
-
ctx.err(
|
|
12769
|
+
ctx.err(path23, `${stepLabel} "exec" requires "command": a non-empty argv list, e.g. command: ["bun", "run", "test:unit"]. ` + `A single shell string is not accepted \u2014 the command is spawned directly, never through a shell.`);
|
|
12681
12770
|
return;
|
|
12682
12771
|
}
|
|
12683
12772
|
const argv = [];
|
|
12684
12773
|
for (const [index, entry] of raw.entries()) {
|
|
12685
12774
|
if (typeof entry !== "string" || entry === "") {
|
|
12686
|
-
ctx.err(
|
|
12775
|
+
ctx.err(path23, `${stepLabel} "exec.command[${index}]" must be a non-empty string.`);
|
|
12687
12776
|
return;
|
|
12688
12777
|
}
|
|
12689
12778
|
if (entry.includes("\x00")) {
|
|
12690
|
-
ctx.err([...
|
|
12779
|
+
ctx.err([...path23, index], `${stepLabel} "exec.command[${index}]" may not contain NUL bytes.`);
|
|
12691
12780
|
return;
|
|
12692
12781
|
}
|
|
12693
12782
|
argv.push(entry);
|
|
12694
12783
|
}
|
|
12695
12784
|
return argv;
|
|
12696
12785
|
}
|
|
12697
|
-
function parseExecCwd(ctx, raw,
|
|
12786
|
+
function parseExecCwd(ctx, raw, path23, stepLabel) {
|
|
12698
12787
|
if (raw === undefined)
|
|
12699
12788
|
return;
|
|
12700
12789
|
if (typeof raw !== "string" || raw.trim() === "") {
|
|
12701
|
-
ctx.err(
|
|
12790
|
+
ctx.err(path23, `${stepLabel} "exec.cwd" must be a non-empty relative path inside the unit's working directory.`);
|
|
12702
12791
|
return;
|
|
12703
12792
|
}
|
|
12704
12793
|
const value = raw.trim();
|
|
12705
12794
|
if (!isContainedRelativePath(value)) {
|
|
12706
|
-
ctx.err(
|
|
12795
|
+
ctx.err(path23, `${stepLabel} "exec.cwd" (${JSON.stringify(value)}) must be a RELATIVE path inside the unit's working ` + `directory \u2014 absolute paths, Windows drive letters, "~", and ".." segments are rejected.`);
|
|
12707
12796
|
return;
|
|
12708
12797
|
}
|
|
12709
12798
|
if (ctx.validateExecCwd) {
|
|
@@ -12711,7 +12800,7 @@ function parseExecCwd(ctx, raw, path22, stepLabel) {
|
|
|
12711
12800
|
if (!semantic.ok) {
|
|
12712
12801
|
ctx.errors.push({
|
|
12713
12802
|
code: semantic.code,
|
|
12714
|
-
line: ctx.lineAt(
|
|
12803
|
+
line: ctx.lineAt(path23),
|
|
12715
12804
|
message: semantic.message
|
|
12716
12805
|
});
|
|
12717
12806
|
return;
|
|
@@ -12720,29 +12809,29 @@ function parseExecCwd(ctx, raw, path22, stepLabel) {
|
|
|
12720
12809
|
}
|
|
12721
12810
|
return value;
|
|
12722
12811
|
}
|
|
12723
|
-
function parseMap(ctx, raw,
|
|
12812
|
+
function parseMap(ctx, raw, path23, stepLabel) {
|
|
12724
12813
|
if (!isRecord(raw)) {
|
|
12725
|
-
ctx.err(
|
|
12814
|
+
ctx.err(path23, `${stepLabel} "map" must be a mapping with an "over" key.`);
|
|
12726
12815
|
return;
|
|
12727
12816
|
}
|
|
12728
|
-
checkUnknownKeys(ctx, raw,
|
|
12817
|
+
checkUnknownKeys(ctx, raw, path23, MAP_KEYS, `${stepLabel} "map"`);
|
|
12729
12818
|
let over = "";
|
|
12730
12819
|
if (typeof raw.over === "string" && raw.over.trim() !== "") {
|
|
12731
12820
|
over = raw.over.trim();
|
|
12732
|
-
checkReferenceSyntax(ctx, over, [...
|
|
12821
|
+
checkReferenceSyntax(ctx, over, [...path23, "over"], `${stepLabel} "over"`);
|
|
12733
12822
|
} else {
|
|
12734
|
-
ctx.err([...
|
|
12823
|
+
ctx.err([...path23, "over"], `${stepLabel} "map" requires "over": a reference naming the item list (e.g. steps.discover.output.files).`);
|
|
12735
12824
|
}
|
|
12736
12825
|
let concurrency;
|
|
12737
12826
|
if (raw.concurrency !== undefined) {
|
|
12738
12827
|
if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0) {
|
|
12739
12828
|
concurrency = Math.min(raw.concurrency, WORKFLOW_MAX_CONCURRENCY);
|
|
12740
12829
|
} else {
|
|
12741
|
-
ctx.err([...
|
|
12830
|
+
ctx.err([...path23, "concurrency"], `${stepLabel} "concurrency" must be a positive integer.`);
|
|
12742
12831
|
}
|
|
12743
12832
|
}
|
|
12744
|
-
const reducer = parseEnumField(ctx, raw.reducer, [...
|
|
12745
|
-
const unit = raw.unit !== undefined ? parseUnit(ctx, raw.unit, [...
|
|
12833
|
+
const reducer = parseEnumField(ctx, raw.reducer, [...path23, "reducer"], `${stepLabel} "reducer"`, PROGRAM_REDUCERS);
|
|
12834
|
+
const unit = raw.unit !== undefined ? parseUnit(ctx, raw.unit, [...path23, "unit"], stepLabel) : undefined;
|
|
12746
12835
|
const map = { over };
|
|
12747
12836
|
if (concurrency !== undefined)
|
|
12748
12837
|
map.concurrency = concurrency;
|
|
@@ -12752,21 +12841,21 @@ function parseMap(ctx, raw, path22, stepLabel) {
|
|
|
12752
12841
|
map.unit = unit;
|
|
12753
12842
|
return map;
|
|
12754
12843
|
}
|
|
12755
|
-
function parseRoute(ctx, raw,
|
|
12844
|
+
function parseRoute(ctx, raw, path23, stepLabel, stepIndex, routeChecks) {
|
|
12756
12845
|
if (!isRecord(raw)) {
|
|
12757
|
-
ctx.err(
|
|
12846
|
+
ctx.err(path23, `${stepLabel} "route" must be a mapping with "input" and "when" keys.`);
|
|
12758
12847
|
return;
|
|
12759
12848
|
}
|
|
12760
|
-
checkUnknownKeys(ctx, raw,
|
|
12849
|
+
checkUnknownKeys(ctx, raw, path23, ROUTE_KEYS, `${stepLabel} "route"`);
|
|
12761
12850
|
let input = "";
|
|
12762
12851
|
if (typeof raw.input === "string" && raw.input.trim() !== "") {
|
|
12763
12852
|
input = raw.input.trim();
|
|
12764
|
-
checkReferenceSyntax(ctx, input, [...
|
|
12853
|
+
checkReferenceSyntax(ctx, input, [...path23, "input"], `${stepLabel} "route.input"`);
|
|
12765
12854
|
} else {
|
|
12766
|
-
ctx.err([...
|
|
12855
|
+
ctx.err([...path23, "input"], `${stepLabel} "route" requires "input": a reference naming the value to route on.`);
|
|
12767
12856
|
}
|
|
12768
12857
|
const check = { stepIndex, stepLabel, branches: [] };
|
|
12769
|
-
const whenPath = [...
|
|
12858
|
+
const whenPath = [...path23, "when"];
|
|
12770
12859
|
if (!Array.isArray(raw.when) || raw.when.length === 0) {
|
|
12771
12860
|
ctx.err(whenPath, `${stepLabel} "route" requires "when": a non-empty list of { match, step } branches (e.g. when: [{ match: pass, step: ship }]).`);
|
|
12772
12861
|
} else {
|
|
@@ -12807,9 +12896,9 @@ function parseRoute(ctx, raw, path22, stepLabel, stepIndex, routeChecks) {
|
|
|
12807
12896
|
if (raw.default !== undefined) {
|
|
12808
12897
|
if (typeof raw.default === "string" && raw.default.trim() !== "") {
|
|
12809
12898
|
defaultStepId = raw.default.trim();
|
|
12810
|
-
check.defaultTarget = { stepId: defaultStepId, line: ctx.lineAt([...
|
|
12899
|
+
check.defaultTarget = { stepId: defaultStepId, line: ctx.lineAt([...path23, "default"]) };
|
|
12811
12900
|
} else {
|
|
12812
|
-
ctx.err([...
|
|
12901
|
+
ctx.err([...path23, "default"], `${stepLabel} "route.default" must be a step id string.`);
|
|
12813
12902
|
}
|
|
12814
12903
|
}
|
|
12815
12904
|
routeChecks.push(check);
|
|
@@ -12818,70 +12907,70 @@ function parseRoute(ctx, raw, path22, stepLabel, stepIndex, routeChecks) {
|
|
|
12818
12907
|
route.defaultStepId = defaultStepId;
|
|
12819
12908
|
return route;
|
|
12820
12909
|
}
|
|
12821
|
-
function parseInputs(ctx, raw,
|
|
12910
|
+
function parseInputs(ctx, raw, path23, stepLabel) {
|
|
12822
12911
|
if (raw === undefined)
|
|
12823
12912
|
return;
|
|
12824
12913
|
if (!Array.isArray(raw) || raw.length === 0) {
|
|
12825
|
-
ctx.err(
|
|
12914
|
+
ctx.err(path23, `${stepLabel} "inputs" must be a non-empty list of reference strings.`);
|
|
12826
12915
|
return;
|
|
12827
12916
|
}
|
|
12828
12917
|
const out = [];
|
|
12829
12918
|
const seen = new Set;
|
|
12830
12919
|
raw.forEach((entry, i) => {
|
|
12831
12920
|
if (typeof entry !== "string" || entry.trim() === "") {
|
|
12832
|
-
ctx.err([...
|
|
12921
|
+
ctx.err([...path23, i], `${stepLabel} "inputs[${i}]" must be a non-empty reference string.`);
|
|
12833
12922
|
return;
|
|
12834
12923
|
}
|
|
12835
12924
|
const value = entry.trim();
|
|
12836
12925
|
if (seen.has(value)) {
|
|
12837
|
-
ctx.err([...
|
|
12926
|
+
ctx.err([...path23, i], `${stepLabel} "inputs[${i}]" duplicates an earlier entry: "${value}".`);
|
|
12838
12927
|
return;
|
|
12839
12928
|
}
|
|
12840
12929
|
seen.add(value);
|
|
12841
|
-
checkReferenceSyntax(ctx, value, [...
|
|
12930
|
+
checkReferenceSyntax(ctx, value, [...path23, i], `${stepLabel} "inputs[${i}]"`);
|
|
12842
12931
|
out.push(value);
|
|
12843
12932
|
});
|
|
12844
12933
|
return out.length > 0 ? out : undefined;
|
|
12845
12934
|
}
|
|
12846
|
-
function parseGate(ctx, raw,
|
|
12935
|
+
function parseGate(ctx, raw, path23, stepLabel) {
|
|
12847
12936
|
if (!isRecord(raw)) {
|
|
12848
|
-
ctx.err(
|
|
12937
|
+
ctx.err(path23, `${stepLabel} "gate" must be a mapping with any of: ${GATE_KEYS.join(", ")}.`);
|
|
12849
12938
|
return;
|
|
12850
12939
|
}
|
|
12851
|
-
checkUnknownKeys(ctx, raw,
|
|
12940
|
+
checkUnknownKeys(ctx, raw, path23, GATE_KEYS, `${stepLabel} "gate"`);
|
|
12852
12941
|
const gate = {};
|
|
12853
12942
|
if (raw.max_loops !== undefined) {
|
|
12854
12943
|
if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1) {
|
|
12855
12944
|
gate.maxLoops = raw.max_loops;
|
|
12856
12945
|
} else {
|
|
12857
|
-
ctx.err([...
|
|
12946
|
+
ctx.err([...path23, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer of at least 1.`);
|
|
12858
12947
|
}
|
|
12859
12948
|
}
|
|
12860
12949
|
return gate;
|
|
12861
12950
|
}
|
|
12862
|
-
function parseEngineName(ctx, raw,
|
|
12951
|
+
function parseEngineName(ctx, raw, path23, label) {
|
|
12863
12952
|
if (typeof raw !== "string" || raw.trim() === "") {
|
|
12864
|
-
ctx.err(
|
|
12953
|
+
ctx.err(path23, `${label} must be a non-empty engine name.`);
|
|
12865
12954
|
return;
|
|
12866
12955
|
}
|
|
12867
12956
|
const name = raw.trim();
|
|
12868
12957
|
if (!WORKFLOW_ENGINE_NAME_PATTERN.test(name) || name.length > WORKFLOW_MAX_ENGINE_NAME_LENGTH) {
|
|
12869
|
-
ctx.err(
|
|
12958
|
+
ctx.err(path23, `${label} has an invalid engine name ${JSON.stringify(name)}. Engine names are lowercase words of letters ` + `and digits separated by single dashes, starting with a letter (e.g. "code-review-llm"), at most ` + `${WORKFLOW_MAX_ENGINE_NAME_LENGTH} characters.`);
|
|
12870
12959
|
return;
|
|
12871
12960
|
}
|
|
12872
12961
|
return name;
|
|
12873
12962
|
}
|
|
12874
|
-
function parseRetry(ctx, raw,
|
|
12963
|
+
function parseRetry(ctx, raw, path23, stepLabel) {
|
|
12875
12964
|
if (raw === undefined)
|
|
12876
12965
|
return;
|
|
12877
12966
|
if (!isRecord(raw)) {
|
|
12878
|
-
ctx.err(
|
|
12967
|
+
ctx.err(path23, `${stepLabel} "retry" must be a mapping: { max: <n>, on: [<failure_reason>, \u2026] }.`);
|
|
12879
12968
|
return;
|
|
12880
12969
|
}
|
|
12881
|
-
checkUnknownKeys(ctx, raw,
|
|
12970
|
+
checkUnknownKeys(ctx, raw, path23, RETRY_KEYS, `${stepLabel} "retry"`);
|
|
12882
12971
|
let ok = true;
|
|
12883
12972
|
if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0)) {
|
|
12884
|
-
ctx.err([...
|
|
12973
|
+
ctx.err([...path23, "max"], `${stepLabel} "retry.max" is required and must be a non-negative integer.`);
|
|
12885
12974
|
ok = false;
|
|
12886
12975
|
}
|
|
12887
12976
|
const on = [];
|
|
@@ -12890,27 +12979,27 @@ function parseRetry(ctx, raw, path22, stepLabel) {
|
|
|
12890
12979
|
if (typeof reason === "string" && PROGRAM_RETRY_REASONS.includes(reason)) {
|
|
12891
12980
|
on.push(reason);
|
|
12892
12981
|
} else {
|
|
12893
|
-
ctx.err([...
|
|
12982
|
+
ctx.err([...path23, "on", i], `${stepLabel} "retry.on" has unknown failure reason ${JSON.stringify(reason)}. Valid reasons: ${PROGRAM_RETRY_REASONS.join(", ")}.`);
|
|
12894
12983
|
ok = false;
|
|
12895
12984
|
}
|
|
12896
12985
|
});
|
|
12897
12986
|
} else {
|
|
12898
|
-
ctx.err([...
|
|
12987
|
+
ctx.err([...path23, "on"], `${stepLabel} "retry.on" is required and must be a non-empty list of failure reasons (${PROGRAM_RETRY_REASONS.join(", ")}).`);
|
|
12899
12988
|
ok = false;
|
|
12900
12989
|
}
|
|
12901
12990
|
return ok ? { max: raw.max, on } : undefined;
|
|
12902
12991
|
}
|
|
12903
|
-
function parseTimeoutField(ctx, raw,
|
|
12992
|
+
function parseTimeoutField(ctx, raw, path23, label) {
|
|
12904
12993
|
if (raw === undefined)
|
|
12905
12994
|
return;
|
|
12906
12995
|
if (typeof raw === "number") {
|
|
12907
12996
|
if (Number.isInteger(raw) && raw > 0)
|
|
12908
|
-
return checkTimeoutCeiling(ctx, raw,
|
|
12909
|
-
ctx.err(
|
|
12997
|
+
return checkTimeoutCeiling(ctx, raw, path23, label, String(raw));
|
|
12998
|
+
ctx.err(path23, `${label} has a non-positive timeout ${JSON.stringify(raw)}. ${TIMEOUT_HINT}.`);
|
|
12910
12999
|
return;
|
|
12911
13000
|
}
|
|
12912
13001
|
if (typeof raw !== "string") {
|
|
12913
|
-
ctx.err(
|
|
13002
|
+
ctx.err(path23, `${label} must be a duration string. ${TIMEOUT_HINT}.`);
|
|
12914
13003
|
return;
|
|
12915
13004
|
}
|
|
12916
13005
|
const value = raw.trim().toLowerCase();
|
|
@@ -12918,37 +13007,37 @@ function parseTimeoutField(ctx, raw, path22, label) {
|
|
|
12918
13007
|
return null;
|
|
12919
13008
|
const match = value.match(TIMEOUT_VALUE);
|
|
12920
13009
|
if (!match) {
|
|
12921
|
-
ctx.err(
|
|
13010
|
+
ctx.err(path23, `${label} has an invalid timeout "${raw}". ${TIMEOUT_HINT}.`);
|
|
12922
13011
|
return;
|
|
12923
13012
|
}
|
|
12924
13013
|
const n = Number.parseInt(match[1], 10);
|
|
12925
13014
|
const unit = match[2] ?? "ms";
|
|
12926
13015
|
const timeoutMs = unit === "m" ? n * 60000 : unit === "s" ? n * 1000 : n;
|
|
12927
13016
|
if (timeoutMs <= 0) {
|
|
12928
|
-
ctx.err(
|
|
13017
|
+
ctx.err(path23, `${label} has a non-positive timeout "${raw}". Use a positive duration or "none".`);
|
|
12929
13018
|
return;
|
|
12930
13019
|
}
|
|
12931
|
-
return checkTimeoutCeiling(ctx, timeoutMs,
|
|
13020
|
+
return checkTimeoutCeiling(ctx, timeoutMs, path23, label, raw);
|
|
12932
13021
|
}
|
|
12933
|
-
function checkTimeoutCeiling(ctx, timeoutMs,
|
|
13022
|
+
function checkTimeoutCeiling(ctx, timeoutMs, path23, label, raw) {
|
|
12934
13023
|
if (timeoutMs <= WORKFLOW_MAX_TIMEOUT_MS)
|
|
12935
13024
|
return timeoutMs;
|
|
12936
|
-
ctx.err(
|
|
13025
|
+
ctx.err(path23, `${label} has a timeout "${raw}" above the maximum of ${WORKFLOW_MAX_TIMEOUT_MS} ms (about 24.8 days). ` + `Use a shorter duration or "none" for no timeout.`);
|
|
12937
13026
|
return;
|
|
12938
13027
|
}
|
|
12939
|
-
function parseEnumField(ctx, raw,
|
|
13028
|
+
function parseEnumField(ctx, raw, path23, label, allowed) {
|
|
12940
13029
|
if (raw === undefined)
|
|
12941
13030
|
return;
|
|
12942
13031
|
if (typeof raw === "string" && allowed.includes(raw))
|
|
12943
13032
|
return raw;
|
|
12944
|
-
ctx.err(
|
|
13033
|
+
ctx.err(path23, `${label} must be one of: ${allowed.join(" | ")} (got ${JSON.stringify(raw)}).`);
|
|
12945
13034
|
return;
|
|
12946
13035
|
}
|
|
12947
|
-
function parseLlmOverrides(ctx, raw,
|
|
13036
|
+
function parseLlmOverrides(ctx, raw, path23, label) {
|
|
12948
13037
|
if (raw === undefined)
|
|
12949
13038
|
return;
|
|
12950
13039
|
if (!isRecord(raw)) {
|
|
12951
|
-
ctx.err(
|
|
13040
|
+
ctx.err(path23, `${label} must be a mapping of LLM invocation overrides.`);
|
|
12952
13041
|
return;
|
|
12953
13042
|
}
|
|
12954
13043
|
const keys2 = [
|
|
@@ -12960,36 +13049,36 @@ function parseLlmOverrides(ctx, raw, path22, label) {
|
|
|
12960
13049
|
"enable_thinking",
|
|
12961
13050
|
"reasoning_effort"
|
|
12962
13051
|
];
|
|
12963
|
-
checkUnknownKeys(ctx, raw,
|
|
13052
|
+
checkUnknownKeys(ctx, raw, path23, keys2, label);
|
|
12964
13053
|
const result = {};
|
|
12965
13054
|
if (raw.temperature !== undefined) {
|
|
12966
13055
|
if (typeof raw.temperature === "number" && Number.isFinite(raw.temperature))
|
|
12967
13056
|
result.temperature = raw.temperature;
|
|
12968
13057
|
else
|
|
12969
|
-
ctx.err([...
|
|
13058
|
+
ctx.err([...path23, "temperature"], `${label}.temperature must be a finite number.`);
|
|
12970
13059
|
}
|
|
12971
13060
|
if (raw.max_tokens !== undefined) {
|
|
12972
13061
|
if (typeof raw.max_tokens === "number" && Number.isInteger(raw.max_tokens) && raw.max_tokens > 0) {
|
|
12973
13062
|
result.maxTokens = raw.max_tokens;
|
|
12974
13063
|
} else
|
|
12975
|
-
ctx.err([...
|
|
13064
|
+
ctx.err([...path23, "max_tokens"], `${label}.max_tokens must be a positive integer.`);
|
|
12976
13065
|
}
|
|
12977
13066
|
if (raw.supports_json_schema !== undefined) {
|
|
12978
13067
|
if (typeof raw.supports_json_schema === "boolean")
|
|
12979
13068
|
result.supportsJsonSchema = raw.supports_json_schema;
|
|
12980
13069
|
else
|
|
12981
|
-
ctx.err([...
|
|
13070
|
+
ctx.err([...path23, "supports_json_schema"], `${label}.supports_json_schema must be a boolean.`);
|
|
12982
13071
|
}
|
|
12983
13072
|
if (raw.extra_params !== undefined) {
|
|
12984
13073
|
if (!isRecord(raw.extra_params)) {
|
|
12985
|
-
ctx.err([...
|
|
13074
|
+
ctx.err([...path23, "extra_params"], `${label}.extra_params must be a JSON object.`);
|
|
12986
13075
|
} else {
|
|
12987
13076
|
const issues = validateExtraParams(raw.extra_params);
|
|
12988
13077
|
for (const issue of issues) {
|
|
12989
|
-
ctx.err([...
|
|
13078
|
+
ctx.err([...path23, "extra_params", ...issue.path], `${formatExtraParamsIssue(`${label}.extra_params`, issue)}.`);
|
|
12990
13079
|
}
|
|
12991
13080
|
if (jsonBytes(raw.extra_params) > WORKFLOW_MAX_EXTRA_PARAMS_BYTES) {
|
|
12992
|
-
ctx.err([...
|
|
13081
|
+
ctx.err([...path23, "extra_params"], `${label}.extra_params exceeds the 64 KiB resource limit.`);
|
|
12993
13082
|
}
|
|
12994
13083
|
if (issues.length === 0 && jsonBytes(raw.extra_params) <= WORKFLOW_MAX_EXTRA_PARAMS_BYTES) {
|
|
12995
13084
|
result.extraParams = raw.extra_params;
|
|
@@ -13000,38 +13089,38 @@ function parseLlmOverrides(ctx, raw, path22, label) {
|
|
|
13000
13089
|
if (typeof raw.context_length === "number" && Number.isInteger(raw.context_length) && raw.context_length > 0) {
|
|
13001
13090
|
result.contextLength = raw.context_length;
|
|
13002
13091
|
} else
|
|
13003
|
-
ctx.err([...
|
|
13092
|
+
ctx.err([...path23, "context_length"], `${label}.context_length must be a positive integer.`);
|
|
13004
13093
|
}
|
|
13005
13094
|
if (raw.enable_thinking !== undefined) {
|
|
13006
13095
|
if (typeof raw.enable_thinking === "boolean")
|
|
13007
13096
|
result.enableThinking = raw.enable_thinking;
|
|
13008
13097
|
else
|
|
13009
|
-
ctx.err([...
|
|
13098
|
+
ctx.err([...path23, "enable_thinking"], `${label}.enable_thinking must be a boolean.`);
|
|
13010
13099
|
}
|
|
13011
13100
|
if (raw.reasoning_effort !== undefined) {
|
|
13012
13101
|
if (typeof raw.reasoning_effort === "string" && raw.reasoning_effort.trim().length > 0) {
|
|
13013
13102
|
result.reasoningEffort = raw.reasoning_effort;
|
|
13014
13103
|
} else
|
|
13015
|
-
ctx.err([...
|
|
13104
|
+
ctx.err([...path23, "reasoning_effort"], `${label}.reasoning_effort must be a non-empty string.`);
|
|
13016
13105
|
}
|
|
13017
13106
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
13018
13107
|
}
|
|
13019
|
-
function parseSchemaObject(ctx, raw,
|
|
13108
|
+
function parseSchemaObject(ctx, raw, path23, label) {
|
|
13020
13109
|
if (raw === undefined)
|
|
13021
13110
|
return;
|
|
13022
13111
|
if (!isRecord(raw)) {
|
|
13023
|
-
ctx.err(
|
|
13112
|
+
ctx.err(path23, `${label} must be a JSON Schema object (e.g. { type: object, properties: { \u2026 } }).`);
|
|
13024
13113
|
return;
|
|
13025
13114
|
}
|
|
13026
13115
|
if (jsonBytes(raw) > WORKFLOW_MAX_SCHEMA_BYTES) {
|
|
13027
|
-
ctx.err(
|
|
13116
|
+
ctx.err(path23, `${label} exceeds the 256 KiB resource limit.`);
|
|
13028
13117
|
}
|
|
13029
|
-
checkSchemaDefinition(ctx, raw,
|
|
13118
|
+
checkSchemaDefinition(ctx, raw, path23, label);
|
|
13030
13119
|
return raw;
|
|
13031
13120
|
}
|
|
13032
|
-
function checkSchemaDefinition(ctx, schema,
|
|
13121
|
+
function checkSchemaDefinition(ctx, schema, path23, label) {
|
|
13033
13122
|
for (const issue of checkJsonSchemaDefinition(schema)) {
|
|
13034
|
-
const issuePath = [...
|
|
13123
|
+
const issuePath = [...path23, ...issue.path];
|
|
13035
13124
|
if (issue.kind === "unsupported") {
|
|
13036
13125
|
ctx.err(issuePath, `${label} (at ${issue.pointer}): ${issue.message}. Supported JSON Schema keywords: ` + `${JSON_SCHEMA_SUBSET_SUPPORTED_KEYWORDS}.`);
|
|
13037
13126
|
} else {
|
|
@@ -13039,15 +13128,15 @@ function checkSchemaDefinition(ctx, schema, path22, label) {
|
|
|
13039
13128
|
}
|
|
13040
13129
|
}
|
|
13041
13130
|
}
|
|
13042
|
-
function checkReferenceSyntax(ctx, text,
|
|
13131
|
+
function checkReferenceSyntax(ctx, text, path23, label) {
|
|
13043
13132
|
const result = parseReference(text);
|
|
13044
13133
|
if (!result.ok)
|
|
13045
|
-
ctx.err(
|
|
13134
|
+
ctx.err(path23, `${label}: ${result.message}`);
|
|
13046
13135
|
}
|
|
13047
|
-
function checkUnknownKeys(ctx, obj,
|
|
13136
|
+
function checkUnknownKeys(ctx, obj, path23, allowed, label) {
|
|
13048
13137
|
for (const key of Object.keys(obj)) {
|
|
13049
13138
|
if (!allowed.includes(key)) {
|
|
13050
|
-
ctx.err([...
|
|
13139
|
+
ctx.err([...path23, key], `Unknown ${label} key "${key}". Allowed keys: ${allowed.join(", ")}.`);
|
|
13051
13140
|
}
|
|
13052
13141
|
}
|
|
13053
13142
|
}
|
|
@@ -13107,7 +13196,7 @@ var init_parser = __esm(() => {
|
|
|
13107
13196
|
});
|
|
13108
13197
|
|
|
13109
13198
|
// src/workflows/source-ir/result.ts
|
|
13110
|
-
function sourceFailureResult(cause,
|
|
13199
|
+
function sourceFailureResult(cause, path23) {
|
|
13111
13200
|
if (cause instanceof WorkflowSourceFailure)
|
|
13112
13201
|
return { ok: false, errors: [cause.error] };
|
|
13113
13202
|
return {
|
|
@@ -13116,7 +13205,7 @@ function sourceFailureResult(cause, path22) {
|
|
|
13116
13205
|
{
|
|
13117
13206
|
code: "invalid-workflow-source",
|
|
13118
13207
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
13119
|
-
path:
|
|
13208
|
+
path: path23,
|
|
13120
13209
|
line: 1
|
|
13121
13210
|
}
|
|
13122
13211
|
]
|
|
@@ -13767,7 +13856,7 @@ var init_triggers = __esm(() => {
|
|
|
13767
13856
|
});
|
|
13768
13857
|
|
|
13769
13858
|
// src/workflows/source-ir/compile.ts
|
|
13770
|
-
import
|
|
13859
|
+
import path23 from "path";
|
|
13771
13860
|
function compileGithubWorkflowSource(source, options) {
|
|
13772
13861
|
try {
|
|
13773
13862
|
return {
|
|
@@ -13851,7 +13940,7 @@ function compileMarkdownWorkflowSource(source, options) {
|
|
|
13851
13940
|
}
|
|
13852
13941
|
}
|
|
13853
13942
|
function compileWorkflowSource(source, options) {
|
|
13854
|
-
const extension =
|
|
13943
|
+
const extension = path23.extname(options.path).toLowerCase();
|
|
13855
13944
|
if (extension === ".md")
|
|
13856
13945
|
return compileMarkdownWorkflowSource(source, options);
|
|
13857
13946
|
if (extension === ".yml")
|
|
@@ -13929,7 +14018,7 @@ function markdownName(source, filePath) {
|
|
|
13929
14018
|
const title = body.match(/^#\s+(.+?)\s*$/m)?.[1]?.trim();
|
|
13930
14019
|
if (title)
|
|
13931
14020
|
return title;
|
|
13932
|
-
return
|
|
14021
|
+
return path23.basename(filePath, path23.extname(filePath));
|
|
13933
14022
|
}
|
|
13934
14023
|
function wholeSourceSpan2(source, filePath) {
|
|
13935
14024
|
return { path: filePath, start: 1, end: Math.max(1, source.split(/\r?\n/).length) };
|
|
@@ -67988,13 +68077,13 @@ function flattenForText(value, path, lines) {
|
|
|
67988
68077
|
}
|
|
67989
68078
|
|
|
67990
68079
|
// src/output/html-render.ts
|
|
67991
|
-
import
|
|
68080
|
+
import path6 from "path";
|
|
67992
68081
|
// src/runtime.ts
|
|
67993
68082
|
import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
|
|
67994
68083
|
init_common();
|
|
67995
68084
|
import { createWriteStream, statfsSync } from "fs";
|
|
67996
68085
|
import { createRequire } from "module";
|
|
67997
|
-
import
|
|
68086
|
+
import path5 from "path";
|
|
67998
68087
|
import { Readable } from "stream";
|
|
67999
68088
|
import { pipeline } from "stream/promises";
|
|
68000
68089
|
import { fileURLToPath } from "url";
|
|
@@ -68080,11 +68169,11 @@ async function writeResponseToFileCapped(filePath, res, options) {
|
|
|
68080
68169
|
}
|
|
68081
68170
|
}
|
|
68082
68171
|
function getDirname(importMetaUrl) {
|
|
68083
|
-
return
|
|
68172
|
+
return path5.dirname(fileURLToPath(importMetaUrl));
|
|
68084
68173
|
}
|
|
68085
|
-
function statfsType(
|
|
68174
|
+
function statfsType(path6) {
|
|
68086
68175
|
try {
|
|
68087
|
-
return statfsSync(
|
|
68176
|
+
return statfsSync(path6).type;
|
|
68088
68177
|
} catch {
|
|
68089
68178
|
return;
|
|
68090
68179
|
}
|
|
@@ -68111,7 +68200,7 @@ function toBuffer(data) {
|
|
|
68111
68200
|
}
|
|
68112
68201
|
|
|
68113
68202
|
// src/output/html-render.ts
|
|
68114
|
-
var TEMPLATES_DIR =
|
|
68203
|
+
var TEMPLATES_DIR = path6.join(getDirname(import.meta.url), "../assets/templates/html");
|
|
68115
68204
|
|
|
68116
68205
|
// src/output/command-registry.ts
|
|
68117
68206
|
function createCommandRegistry() {
|
|
@@ -68696,6 +68785,7 @@ var PASSTHROUGH_COMMANDS = [
|
|
|
68696
68785
|
"task-run",
|
|
68697
68786
|
"task-sync",
|
|
68698
68787
|
"task-sync-dry-run",
|
|
68788
|
+
"task-validate",
|
|
68699
68789
|
"update",
|
|
68700
68790
|
"upgrade",
|
|
68701
68791
|
"workflow-abandon",
|
|
@@ -69281,16 +69371,16 @@ function formatConfigPlain(r) {
|
|
|
69281
69371
|
const lines = [];
|
|
69282
69372
|
const walk = (obj, prefix) => {
|
|
69283
69373
|
for (const [k, v] of Object.entries(obj)) {
|
|
69284
|
-
const
|
|
69374
|
+
const path7 = prefix ? `${prefix}.${k}` : k;
|
|
69285
69375
|
if (v === null || v === undefined) {
|
|
69286
|
-
lines.push(`${
|
|
69376
|
+
lines.push(`${path7}=`);
|
|
69287
69377
|
} else if (Array.isArray(v)) {
|
|
69288
|
-
lines.push(`${
|
|
69378
|
+
lines.push(`${path7}=${JSON.stringify(v)}`);
|
|
69289
69379
|
} else if (typeof v === "object") {
|
|
69290
|
-
walk(v,
|
|
69380
|
+
walk(v, path7);
|
|
69291
69381
|
} else {
|
|
69292
|
-
const rendered = typeof v === "string" && /^registries\.\d+\.url$/u.test(
|
|
69293
|
-
lines.push(`${
|
|
69382
|
+
const rendered = typeof v === "string" && /^registries\.\d+\.url$/u.test(path7) ? formatRegistryUrl(v) : String(v);
|
|
69383
|
+
lines.push(`${path7}=${rendered}`);
|
|
69294
69384
|
}
|
|
69295
69385
|
}
|
|
69296
69386
|
};
|
|
@@ -70798,27 +70888,7 @@ var GLOBAL_OUTPUT_ARGS = {
|
|
|
70798
70888
|
init_errors();
|
|
70799
70889
|
|
|
70800
70890
|
// scripts/akm-migrate/help.txt
|
|
70801
|
-
var help_default =
|
|
70802
|
-
|
|
70803
|
-
The one migration tool for an akm installation. Every historical shape akm
|
|
70804
|
-
has ever written lives here; the CLI proper reads only current schemas.
|
|
70805
|
-
\`status\` and \`apply\` run every step, in order, and print one combined JSON
|
|
70806
|
-
plan (exit 1 when any step is blocked):
|
|
70807
|
-
|
|
70808
|
-
1. legacy config \`extraParams\` keys lifted onto first-class engine fields
|
|
70809
|
-
2. pending state.db migrations, historical-destructive ones included,
|
|
70810
|
-
with a verified sibling safety copy (the only path that admits them)
|
|
70811
|
-
3. task-v2 files to task v3, then task-v3 files to task source v4
|
|
70812
|
-
4. superseded pre-0.9.0 \`.akm\` residue and stale filesystem transactions
|
|
70813
|
-
|
|
70814
|
-
\`akm migrate status|apply\` wraps this executable; \`akm upgrade\` runs
|
|
70815
|
-
\`apply\` after its install step, so an image that ships akm can put either
|
|
70816
|
-
in its entrypoint (a current installation is a no-op).
|
|
70817
|
-
|
|
70818
|
-
Commands:
|
|
70819
|
-
status Inspect every pending migration without changing anything.
|
|
70820
|
-
apply [--dry-run] Back up and apply every pending migration.
|
|
70821
|
-
`;
|
|
70891
|
+
var help_default = "Usage: akm-migrate <command> [options]\n\nThe one migration tool for an akm installation. Every historical shape akm\nhas ever written lives here; the CLI proper reads only current schemas.\n`status` and `apply` run every step, in order, and print one combined JSON\nplan (exit 1 when any step is blocked):\n\n 1. legacy config `extraParams` keys lifted onto first-class engine fields\n 2. pending state.db migrations, historical-destructive ones included,\n with a verified sibling safety copy (the only path that admits them)\n 3. task-v2 files to task v3, then task-v3 files to task source v4\n 4. superseded pre-0.9.0 `.akm` residue and stale filesystem transactions\n 5. live `.akm` writers relocated to `$STATE`/`$CACHE`, for every local\n bundle (distill-rejected, eval-cases, measurement verdicts, and stale\n improve-pipeline locks \u2014 a lock a live run still holds is left alone)\n\n`akm migrate status|apply` wraps this executable; `akm upgrade` runs\n`apply` after its install step, so an image that ships akm can put either\nin its entrypoint (a current installation is a no-op).\n\nCommands:\n status Inspect every pending migration without changing anything.\n apply [--dry-run] Back up and apply every pending migration.\n";
|
|
70822
70892
|
|
|
70823
70893
|
// scripts/akm-migrate/run-migrate.ts
|
|
70824
70894
|
init_common();
|
|
@@ -70830,14 +70900,14 @@ init_extra_params();
|
|
|
70830
70900
|
|
|
70831
70901
|
// src/core/config/config-io.ts
|
|
70832
70902
|
import fs4 from "fs";
|
|
70833
|
-
import
|
|
70903
|
+
import path9 from "path";
|
|
70834
70904
|
init_common();
|
|
70835
70905
|
init_errors();
|
|
70836
70906
|
|
|
70837
70907
|
// src/core/file-lock.ts
|
|
70838
70908
|
import { randomUUID } from "crypto";
|
|
70839
70909
|
import fs3 from "fs";
|
|
70840
|
-
import
|
|
70910
|
+
import path8 from "path";
|
|
70841
70911
|
|
|
70842
70912
|
// src/storage/database.ts
|
|
70843
70913
|
import { createRequire as createRequire2 } from "module";
|
|
@@ -70861,12 +70931,12 @@ function selectProvider() {
|
|
|
70861
70931
|
}
|
|
70862
70932
|
return provider;
|
|
70863
70933
|
}
|
|
70864
|
-
function openDatabase(
|
|
70865
|
-
return selectProvider().open(
|
|
70934
|
+
function openDatabase(path8, opts) {
|
|
70935
|
+
return selectProvider().open(path8, opts);
|
|
70866
70936
|
}
|
|
70867
|
-
function openBunDatabase(
|
|
70937
|
+
function openBunDatabase(path8, opts) {
|
|
70868
70938
|
const { Database: BunDatabase } = loadBunSqlite();
|
|
70869
|
-
const db = opts ? new BunDatabase(
|
|
70939
|
+
const db = opts ? new BunDatabase(path8, bunOptions(opts)) : new BunDatabase(path8);
|
|
70870
70940
|
return db;
|
|
70871
70941
|
}
|
|
70872
70942
|
function bunOptions(opts) {
|
|
@@ -70922,7 +70992,7 @@ function loadBetterSqlite3() {
|
|
|
70922
70992
|
}
|
|
70923
70993
|
return betterSqlite3Ctor;
|
|
70924
70994
|
}
|
|
70925
|
-
function openNodeDatabase(
|
|
70995
|
+
function openNodeDatabase(path8, opts) {
|
|
70926
70996
|
const BetterSqlite3 = loadBetterSqlite3();
|
|
70927
70997
|
const options = {};
|
|
70928
70998
|
if (opts?.readonly !== undefined)
|
|
@@ -70931,7 +71001,7 @@ function openNodeDatabase(path7, opts) {
|
|
|
70931
71001
|
options.fileMustExist = true;
|
|
70932
71002
|
let db;
|
|
70933
71003
|
try {
|
|
70934
|
-
db = opts ? new BetterSqlite3(
|
|
71004
|
+
db = opts ? new BetterSqlite3(path8, options) : new BetterSqlite3(path8);
|
|
70935
71005
|
} catch (err) {
|
|
70936
71006
|
const raw = err instanceof Error ? err.message : String(err);
|
|
70937
71007
|
const remedy = abiMismatchRemedy(raw);
|
|
@@ -70979,7 +71049,7 @@ function sameIdentity(left, right) {
|
|
|
70979
71049
|
return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs;
|
|
70980
71050
|
}
|
|
70981
71051
|
function operationMutexPath(lockPath) {
|
|
70982
|
-
return
|
|
71052
|
+
return path8.join(path8.dirname(lockPath), `.${path8.basename(lockPath)}.operations.sensitive`);
|
|
70983
71053
|
}
|
|
70984
71054
|
function withLockOperationMutex(lockPath, run) {
|
|
70985
71055
|
const db = openDatabase(operationMutexPath(lockPath));
|
|
@@ -71198,14 +71268,14 @@ var MAX_CONFIG_BACKUPS = 5;
|
|
|
71198
71268
|
function backupExistingConfig(configPath, now = new Date) {
|
|
71199
71269
|
if (!fs4.existsSync(configPath))
|
|
71200
71270
|
return;
|
|
71201
|
-
const backupDir =
|
|
71271
|
+
const backupDir = path9.join(getCacheDir(), "config-backups");
|
|
71202
71272
|
fs4.mkdirSync(backupDir, { recursive: true, mode: 448 });
|
|
71203
71273
|
fs4.chmodSync(backupDir, 448);
|
|
71204
71274
|
const timestamp = now.toISOString().replace(/[.:]/g, "-");
|
|
71205
71275
|
let sequence = 0;
|
|
71206
71276
|
let timestamped;
|
|
71207
71277
|
while (true) {
|
|
71208
|
-
timestamped =
|
|
71278
|
+
timestamped = path9.join(backupDir, `config-${timestamp}${sequence === 0 ? "" : `-${sequence}`}.json`);
|
|
71209
71279
|
try {
|
|
71210
71280
|
fs4.copyFileSync(configPath, timestamped, fs4.constants.COPYFILE_EXCL);
|
|
71211
71281
|
break;
|
|
@@ -71215,7 +71285,7 @@ function backupExistingConfig(configPath, now = new Date) {
|
|
|
71215
71285
|
sequence++;
|
|
71216
71286
|
}
|
|
71217
71287
|
}
|
|
71218
|
-
const latest =
|
|
71288
|
+
const latest = path9.join(backupDir, "config.latest.json");
|
|
71219
71289
|
fs4.copyFileSync(configPath, latest);
|
|
71220
71290
|
fs4.chmodSync(timestamped, 384);
|
|
71221
71291
|
fs4.chmodSync(latest, 384);
|
|
@@ -71236,7 +71306,7 @@ function pruneToNewest(dir, keep, select) {
|
|
|
71236
71306
|
return;
|
|
71237
71307
|
}
|
|
71238
71308
|
const candidates = entries.filter(select).map((entry) => {
|
|
71239
|
-
const full =
|
|
71309
|
+
const full = path9.join(dir, entry.name);
|
|
71240
71310
|
let mtime = 0;
|
|
71241
71311
|
try {
|
|
71242
71312
|
mtime = fs4.statSync(full).mtimeMs;
|
|
@@ -71250,7 +71320,7 @@ function pruneToNewest(dir, keep, select) {
|
|
|
71250
71320
|
}
|
|
71251
71321
|
}
|
|
71252
71322
|
function getConfigLockPath() {
|
|
71253
|
-
return
|
|
71323
|
+
return path9.join(getConfigDir(), "config.json.lck");
|
|
71254
71324
|
}
|
|
71255
71325
|
var CONFIG_LOCK_MAX_RETRIES = 40;
|
|
71256
71326
|
var CONFIG_LOCK_RETRY_DELAY_MS = 50;
|
|
@@ -71260,7 +71330,7 @@ function sleepSyncMs(ms) {
|
|
|
71260
71330
|
function acquireConfigLock() {
|
|
71261
71331
|
const lockPath = getConfigLockPath();
|
|
71262
71332
|
try {
|
|
71263
|
-
fs4.mkdirSync(
|
|
71333
|
+
fs4.mkdirSync(path9.dirname(lockPath), { recursive: true });
|
|
71264
71334
|
} catch {}
|
|
71265
71335
|
for (let attempt = 0;attempt < CONFIG_LOCK_MAX_RETRIES; attempt++) {
|
|
71266
71336
|
try {
|
|
@@ -71765,8 +71835,8 @@ function getErrorMap() {
|
|
|
71765
71835
|
}
|
|
71766
71836
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
71767
71837
|
var makeIssue = (params) => {
|
|
71768
|
-
const { data, path:
|
|
71769
|
-
const fullPath = [...
|
|
71838
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
71839
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
71770
71840
|
const fullIssue = {
|
|
71771
71841
|
...issueData,
|
|
71772
71842
|
path: fullPath
|
|
@@ -71878,11 +71948,11 @@ var errorUtil;
|
|
|
71878
71948
|
|
|
71879
71949
|
// node_modules/zod/v3/types.js
|
|
71880
71950
|
class ParseInputLazyPath {
|
|
71881
|
-
constructor(parent, value,
|
|
71951
|
+
constructor(parent, value, path10, key) {
|
|
71882
71952
|
this._cachedPath = [];
|
|
71883
71953
|
this.parent = parent;
|
|
71884
71954
|
this.data = value;
|
|
71885
|
-
this._path =
|
|
71955
|
+
this._path = path10;
|
|
71886
71956
|
this._key = key;
|
|
71887
71957
|
}
|
|
71888
71958
|
get path() {
|
|
@@ -75390,6 +75460,7 @@ var LlmEngineSchema = exports_external.object({
|
|
|
75390
75460
|
endpoint: chatCompletionsEndpoint,
|
|
75391
75461
|
model: nonEmptyString,
|
|
75392
75462
|
apiKey: exports_external.string().regex(ENV_REFERENCE_PATTERN, `apiKey must be $VAR or \${VAR}`).optional(),
|
|
75463
|
+
apiKeyFile: nonEmptyString.optional(),
|
|
75393
75464
|
temperature: exports_external.number().finite().optional(),
|
|
75394
75465
|
maxTokens: positiveInt.optional(),
|
|
75395
75466
|
timeoutMs: timeoutMsField,
|
|
@@ -75403,6 +75474,13 @@ var LlmEngineSchema = exports_external.object({
|
|
|
75403
75474
|
if (key in value)
|
|
75404
75475
|
ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: [key], message: `${key} is not valid on an LLM engine` });
|
|
75405
75476
|
}
|
|
75477
|
+
if (value.apiKey !== undefined && value.apiKeyFile !== undefined) {
|
|
75478
|
+
ctx.addIssue({
|
|
75479
|
+
code: exports_external.ZodIssueCode.custom,
|
|
75480
|
+
path: ["apiKeyFile"],
|
|
75481
|
+
message: "apiKey and apiKeyFile cannot both be set"
|
|
75482
|
+
});
|
|
75483
|
+
}
|
|
75406
75484
|
});
|
|
75407
75485
|
var AgentEngineSchema = exports_external.object({
|
|
75408
75486
|
kind: exports_external.literal("agent"),
|
|
@@ -75420,6 +75498,7 @@ var AgentEngineSchema = exports_external.object({
|
|
|
75420
75498
|
"provider",
|
|
75421
75499
|
"endpoint",
|
|
75422
75500
|
"apiKey",
|
|
75501
|
+
"apiKeyFile",
|
|
75423
75502
|
"temperature",
|
|
75424
75503
|
"maxTokens",
|
|
75425
75504
|
"concurrency",
|
|
@@ -76157,7 +76236,7 @@ var AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
|
|
|
76157
76236
|
// src/core/config/config-sources.ts
|
|
76158
76237
|
init_errors();
|
|
76159
76238
|
import { createHash } from "crypto";
|
|
76160
|
-
import
|
|
76239
|
+
import path10 from "path";
|
|
76161
76240
|
function bundleComponentConfig(bundle) {
|
|
76162
76241
|
if (!bundle?.components)
|
|
76163
76242
|
return;
|
|
@@ -76168,7 +76247,20 @@ function bundleComponentConfig(bundle) {
|
|
|
76168
76247
|
return components[0];
|
|
76169
76248
|
}
|
|
76170
76249
|
function bundleContentRoot(entryPath, componentRoot) {
|
|
76171
|
-
return
|
|
76250
|
+
return path10.resolve(entryPath, componentRoot ?? ".");
|
|
76251
|
+
}
|
|
76252
|
+
function bundleContentRoots(config) {
|
|
76253
|
+
const bundles = config.bundles ?? {};
|
|
76254
|
+
const out = [];
|
|
76255
|
+
for (const [id, entry] of Object.entries(bundles)) {
|
|
76256
|
+
if (typeof entry.path !== "string" || entry.path.length === 0)
|
|
76257
|
+
continue;
|
|
76258
|
+
out.push({ id, contentRoot: bundleContentRoot(entry.path, bundleComponentConfig(entry)?.root) });
|
|
76259
|
+
}
|
|
76260
|
+
return out;
|
|
76261
|
+
}
|
|
76262
|
+
function bundleKeyForContentRoot(config, resolvedContentRoot) {
|
|
76263
|
+
return bundleContentRoots(config).find((entry) => entry.contentRoot === resolvedContentRoot)?.id;
|
|
76172
76264
|
}
|
|
76173
76265
|
function bundlesToSourceEntries(config) {
|
|
76174
76266
|
const bundles = config.bundles;
|
|
@@ -76481,7 +76573,7 @@ init_paths();
|
|
|
76481
76573
|
// src/core/state-db.ts
|
|
76482
76574
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
76483
76575
|
import fs9 from "fs";
|
|
76484
|
-
import
|
|
76576
|
+
import path13 from "path";
|
|
76485
76577
|
|
|
76486
76578
|
// src/storage/engines/sqlite-migrations.ts
|
|
76487
76579
|
function assertMigrationRegistry(migrations) {
|
|
@@ -76650,7 +76742,7 @@ function withImmediateWriteLock(db, fn) {
|
|
|
76650
76742
|
|
|
76651
76743
|
// src/storage/managed-db.ts
|
|
76652
76744
|
import fs7 from "fs";
|
|
76653
|
-
import
|
|
76745
|
+
import path11 from "path";
|
|
76654
76746
|
|
|
76655
76747
|
// src/storage/sqlite-pragmas.ts
|
|
76656
76748
|
init_warn();
|
|
@@ -76724,7 +76816,7 @@ function warnNetworkFallbackOnce(dataDir) {
|
|
|
76724
76816
|
|
|
76725
76817
|
// src/storage/managed-db.ts
|
|
76726
76818
|
function openManagedDatabase(spec) {
|
|
76727
|
-
const dir =
|
|
76819
|
+
const dir = path11.dirname(spec.path);
|
|
76728
76820
|
if (spec.create !== false && !fs7.existsSync(dir)) {
|
|
76729
76821
|
fs7.mkdirSync(dir, { recursive: true });
|
|
76730
76822
|
}
|
|
@@ -76762,13 +76854,13 @@ function withManagedDb(open, fn, opts) {
|
|
|
76762
76854
|
import { AsyncLocalStorage } from "async_hooks";
|
|
76763
76855
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
76764
76856
|
import fs8 from "fs";
|
|
76765
|
-
import
|
|
76857
|
+
import path12 from "path";
|
|
76766
76858
|
init_errors();
|
|
76767
76859
|
init_paths();
|
|
76768
76860
|
var heldBarrierContext = new AsyncLocalStorage;
|
|
76769
76861
|
function tryAcquireMaintenanceBarrier() {
|
|
76770
76862
|
const lockPath = getMaintenanceBarrierPath();
|
|
76771
|
-
fs8.mkdirSync(
|
|
76863
|
+
fs8.mkdirSync(path12.dirname(lockPath), { recursive: true });
|
|
76772
76864
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
76773
76865
|
const ownership = tryAcquireLockSync(lockPath, createLockPayload({ purpose: "maintenance-start" }));
|
|
76774
76866
|
if (ownership) {
|
|
@@ -76819,9 +76911,9 @@ function withMaintenanceStartBarrierSyncWait(run) {
|
|
|
76819
76911
|
}
|
|
76820
76912
|
function acquireMaintenanceActivitySync(name) {
|
|
76821
76913
|
return withMaintenanceStartBarrierSyncWait(() => {
|
|
76822
|
-
const directory =
|
|
76914
|
+
const directory = path12.join(path12.dirname(getMaintenanceBarrierPath()), "maintenance-activities");
|
|
76823
76915
|
fs8.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
76824
|
-
const lockPath =
|
|
76916
|
+
const lockPath = path12.join(directory, `${name}-${process.pid}-${randomUUID2()}.lock`);
|
|
76825
76917
|
const ownership = tryAcquireLockSync(lockPath, createLockPayload({ purpose: name }));
|
|
76826
76918
|
if (!ownership) {
|
|
76827
76919
|
throw new ConfigError(`Could not register AKM maintenance activity at ${lockPath}.`, "INVALID_CONFIG_FILE");
|
|
@@ -77587,7 +77679,7 @@ function runMigrations2(db, options) {
|
|
|
77587
77679
|
|
|
77588
77680
|
// src/core/state-db.ts
|
|
77589
77681
|
function getStateDbPath() {
|
|
77590
|
-
return
|
|
77682
|
+
return path13.join(getDataDir(), "state.db");
|
|
77591
77683
|
}
|
|
77592
77684
|
function safetyCopyTimestamp() {
|
|
77593
77685
|
return new Date().toISOString().replaceAll(/[^0-9]/g, "");
|
|
@@ -77772,7 +77864,7 @@ function createHistoricalStateSafetyCopy(source, migrationId) {
|
|
|
77772
77864
|
fs9.fchmodSync(reservation.fd, finalMode);
|
|
77773
77865
|
fs9.fsyncSync(reservation.fd);
|
|
77774
77866
|
assertOwnedFileReservation(reservation, "Reserved state.db safety copy");
|
|
77775
|
-
fsyncDirectory(
|
|
77867
|
+
fsyncDirectory(path13.dirname(reservation.path));
|
|
77776
77868
|
closeFileIdentity(reservation);
|
|
77777
77869
|
return reservation.path;
|
|
77778
77870
|
} catch (error) {
|
|
@@ -77790,11 +77882,11 @@ function openStateDatabase(dbPath, options) {
|
|
|
77790
77882
|
if (resolvedPath === ":memory:") {
|
|
77791
77883
|
return openManagedDatabase({
|
|
77792
77884
|
path: resolvedPath,
|
|
77793
|
-
pragmas: { dataDir:
|
|
77885
|
+
pragmas: { dataDir: path13.dirname(resolvedPath) },
|
|
77794
77886
|
init: (db) => runMigrations2(db, { freshDatabase: true })
|
|
77795
77887
|
});
|
|
77796
77888
|
}
|
|
77797
|
-
const isCanonical =
|
|
77889
|
+
const isCanonical = path13.resolve(resolvedPath) === path13.resolve(canonicalPath);
|
|
77798
77890
|
const releaseActivity = isCanonical ? acquireMaintenanceActivitySync("state-db") : undefined;
|
|
77799
77891
|
let freshReservation;
|
|
77800
77892
|
let existingSource;
|
|
@@ -77802,7 +77894,7 @@ function openStateDatabase(dbPath, options) {
|
|
|
77802
77894
|
let existingUnversionedDatabase = false;
|
|
77803
77895
|
let stateSafetyCopyCreated = false;
|
|
77804
77896
|
try {
|
|
77805
|
-
fs9.mkdirSync(
|
|
77897
|
+
fs9.mkdirSync(path13.dirname(resolvedPath), { recursive: true });
|
|
77806
77898
|
freshReservation = reserveFreshStateDatabase(resolvedPath);
|
|
77807
77899
|
if (!freshReservation) {
|
|
77808
77900
|
existingSource = openExistingStateDatabaseSource(resolvedPath);
|
|
@@ -77823,7 +77915,7 @@ function openStateDatabase(dbPath, options) {
|
|
|
77823
77915
|
const boundSource = existingSource;
|
|
77824
77916
|
openedDb = openManagedDatabase({
|
|
77825
77917
|
path: boundSource ? sqliteBoundFilePath(boundSource) : resolvedPath,
|
|
77826
|
-
pragmas: { dataDir:
|
|
77918
|
+
pragmas: { dataDir: path13.dirname(resolvedPath) },
|
|
77827
77919
|
init: (db2) => {
|
|
77828
77920
|
runMigrations2(db2, {
|
|
77829
77921
|
freshDatabase: !!freshReservation,
|
|
@@ -78024,7 +78116,7 @@ function applyConfigExtraParamsLift(configPath) {
|
|
|
78024
78116
|
|
|
78025
78117
|
// scripts/akm-migrate/migrate/dead-residue.ts
|
|
78026
78118
|
import fs10 from "fs";
|
|
78027
|
-
import
|
|
78119
|
+
import path14 from "path";
|
|
78028
78120
|
var DEAD_RESIDUE_PATHS = [
|
|
78029
78121
|
{ name: "proposals", reason: "superseded by the `proposals` table in $DATA/state.db (0.9.0)" },
|
|
78030
78122
|
{ prefix: "runs.archived-", reason: "orphaned archive of a directory that no longer exists" },
|
|
@@ -78046,7 +78138,7 @@ function dirSizeBytes(target) {
|
|
|
78046
78138
|
return 0;
|
|
78047
78139
|
}
|
|
78048
78140
|
for (const entry of entries) {
|
|
78049
|
-
const entryPath =
|
|
78141
|
+
const entryPath = path14.join(target, entry.name);
|
|
78050
78142
|
if (entry.isDirectory()) {
|
|
78051
78143
|
total += dirSizeBytes(entryPath);
|
|
78052
78144
|
} else if (entry.isFile()) {
|
|
@@ -78062,7 +78154,7 @@ function sizeOf(target) {
|
|
|
78062
78154
|
return st.isDirectory() ? dirSizeBytes(target) : st.size;
|
|
78063
78155
|
}
|
|
78064
78156
|
function findDeadResidueEntries(stashDir) {
|
|
78065
|
-
const akmDir =
|
|
78157
|
+
const akmDir = path14.join(stashDir, ".akm");
|
|
78066
78158
|
let names;
|
|
78067
78159
|
try {
|
|
78068
78160
|
names = fs10.readdirSync(akmDir);
|
|
@@ -78075,14 +78167,14 @@ function findDeadResidueEntries(stashDir) {
|
|
|
78075
78167
|
for (const name of matches) {
|
|
78076
78168
|
if (!names.includes(name))
|
|
78077
78169
|
continue;
|
|
78078
|
-
const absolutePath =
|
|
78170
|
+
const absolutePath = path14.join(akmDir, name);
|
|
78079
78171
|
let sizeBytes;
|
|
78080
78172
|
try {
|
|
78081
78173
|
sizeBytes = sizeOf(absolutePath);
|
|
78082
78174
|
} catch {
|
|
78083
78175
|
continue;
|
|
78084
78176
|
}
|
|
78085
|
-
found.push({ relativePath:
|
|
78177
|
+
found.push({ relativePath: path14.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
|
|
78086
78178
|
}
|
|
78087
78179
|
}
|
|
78088
78180
|
return found;
|
|
@@ -78109,7 +78201,7 @@ init_paths();
|
|
|
78109
78201
|
init_warn();
|
|
78110
78202
|
import { createHash as createHash2, randomUUID as randomUUID4 } from "crypto";
|
|
78111
78203
|
import fs11 from "fs";
|
|
78112
|
-
import
|
|
78204
|
+
import path15 from "path";
|
|
78113
78205
|
var kinds = new Map;
|
|
78114
78206
|
function registerTxnKind(kind, handler3) {
|
|
78115
78207
|
kinds.set(kind, handler3);
|
|
@@ -78153,18 +78245,18 @@ function writeTxnFileDurably(filePath, content, mode = 384) {
|
|
|
78153
78245
|
fs11.writeFileSync(tempPath, content, { mode });
|
|
78154
78246
|
fsyncTxnFile(tempPath);
|
|
78155
78247
|
fs11.renameSync(tempPath, filePath);
|
|
78156
|
-
fsyncTxnDir(
|
|
78248
|
+
fsyncTxnDir(path15.dirname(filePath));
|
|
78157
78249
|
}
|
|
78158
78250
|
function canonicalTxnRoot(root) {
|
|
78159
78251
|
try {
|
|
78160
|
-
return fs11.realpathSync(
|
|
78252
|
+
return fs11.realpathSync(path15.resolve(root));
|
|
78161
78253
|
} catch {
|
|
78162
|
-
return
|
|
78254
|
+
return path15.resolve(root);
|
|
78163
78255
|
}
|
|
78164
78256
|
}
|
|
78165
78257
|
function txnNamespaceDir(root) {
|
|
78166
78258
|
const ns = txnHash(canonicalTxnRoot(root)).slice(0, 24);
|
|
78167
|
-
return
|
|
78259
|
+
return path15.join(getDataDir(), "txn", ns);
|
|
78168
78260
|
}
|
|
78169
78261
|
function advanceTxn(txn, phase) {
|
|
78170
78262
|
const handler3 = requireKind(txn.journal.kind);
|
|
@@ -78180,7 +78272,7 @@ function cleanupTxn(dir) {
|
|
|
78180
78272
|
try {
|
|
78181
78273
|
fs11.rmSync(dir, { recursive: true, force: true });
|
|
78182
78274
|
try {
|
|
78183
|
-
fs11.rmdirSync(
|
|
78275
|
+
fs11.rmdirSync(path15.dirname(dir));
|
|
78184
78276
|
} catch {}
|
|
78185
78277
|
return null;
|
|
78186
78278
|
} catch (error) {
|
|
@@ -78202,8 +78294,8 @@ function sweepJournallessTxnDir(dir, graceMs = TXN_SWEEP_GRACE_MS) {
|
|
|
78202
78294
|
}
|
|
78203
78295
|
}
|
|
78204
78296
|
function isWithinTxnRoot(candidate, root) {
|
|
78205
|
-
const rel =
|
|
78206
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
78297
|
+
const rel = path15.relative(path15.resolve(root), path15.resolve(candidate));
|
|
78298
|
+
return rel !== "" && !rel.startsWith("..") && !path15.isAbsolute(rel);
|
|
78207
78299
|
}
|
|
78208
78300
|
function readJournal(journalPath) {
|
|
78209
78301
|
let journal;
|
|
@@ -78244,8 +78336,8 @@ async function recoverTxnsForRoot(root, filter) {
|
|
|
78244
78336
|
for (const entry of fs11.readdirSync(nsDir, { withFileTypes: true })) {
|
|
78245
78337
|
if (!entry.isDirectory())
|
|
78246
78338
|
continue;
|
|
78247
|
-
const dir =
|
|
78248
|
-
const journalPath =
|
|
78339
|
+
const dir = path15.join(nsDir, entry.name);
|
|
78340
|
+
const journalPath = path15.join(dir, "journal.json");
|
|
78249
78341
|
if (!fs11.existsSync(journalPath)) {
|
|
78250
78342
|
sweepJournallessTxnDir(dir);
|
|
78251
78343
|
continue;
|
|
@@ -78274,7 +78366,7 @@ async function recoverTxnsForRoot(root, filter) {
|
|
|
78274
78366
|
return recovered;
|
|
78275
78367
|
}
|
|
78276
78368
|
function listTxnJournalsTolerant(predicate) {
|
|
78277
|
-
const home =
|
|
78369
|
+
const home = path15.join(getDataDir(), "txn");
|
|
78278
78370
|
const matches = [];
|
|
78279
78371
|
const unreadableMtimes = [];
|
|
78280
78372
|
if (!fs11.existsSync(home))
|
|
@@ -78282,11 +78374,11 @@ function listTxnJournalsTolerant(predicate) {
|
|
|
78282
78374
|
for (const ns of fs11.readdirSync(home, { withFileTypes: true })) {
|
|
78283
78375
|
if (!ns.isDirectory())
|
|
78284
78376
|
continue;
|
|
78285
|
-
const nsDir =
|
|
78377
|
+
const nsDir = path15.join(home, ns.name);
|
|
78286
78378
|
for (const entry of fs11.readdirSync(nsDir, { withFileTypes: true })) {
|
|
78287
78379
|
if (!entry.isDirectory())
|
|
78288
78380
|
continue;
|
|
78289
|
-
const journalPath =
|
|
78381
|
+
const journalPath = path15.join(nsDir, entry.name, "journal.json");
|
|
78290
78382
|
let mtimeMs;
|
|
78291
78383
|
try {
|
|
78292
78384
|
mtimeMs = fs11.statSync(journalPath).mtimeMs;
|
|
@@ -78315,7 +78407,7 @@ import path60 from "path";
|
|
|
78315
78407
|
init_frontmatter();
|
|
78316
78408
|
init_common();
|
|
78317
78409
|
import fs12 from "fs";
|
|
78318
|
-
import
|
|
78410
|
+
import path17 from "path";
|
|
78319
78411
|
|
|
78320
78412
|
// src/core/adapter/adapters/shared.ts
|
|
78321
78413
|
init_frontmatter();
|
|
@@ -78624,10 +78716,10 @@ var agentSkillsAdapter = {
|
|
|
78624
78716
|
recognize,
|
|
78625
78717
|
validate,
|
|
78626
78718
|
readCandidates(c, conceptId) {
|
|
78627
|
-
return [{ path:
|
|
78719
|
+
return [{ path: path17.join(c.root, conceptId, SKILL_MANIFEST), conceptId }];
|
|
78628
78720
|
},
|
|
78629
78721
|
placeNew(c, conceptId) {
|
|
78630
|
-
return
|
|
78722
|
+
return path17.join(c.root, conceptId, SKILL_MANIFEST);
|
|
78631
78723
|
},
|
|
78632
78724
|
looksLikeRoot(root) {
|
|
78633
78725
|
let entries;
|
|
@@ -78640,7 +78732,7 @@ var agentSkillsAdapter = {
|
|
|
78640
78732
|
if (!entry.isDirectory())
|
|
78641
78733
|
return false;
|
|
78642
78734
|
try {
|
|
78643
|
-
return fs12.existsSync(
|
|
78735
|
+
return fs12.existsSync(path17.join(root, entry.name, SKILL_MANIFEST));
|
|
78644
78736
|
} catch {
|
|
78645
78737
|
return false;
|
|
78646
78738
|
}
|
|
@@ -78653,66 +78745,66 @@ init_metadata();
|
|
|
78653
78745
|
init_asset_placement();
|
|
78654
78746
|
init_frontmatter();
|
|
78655
78747
|
import fs16 from "fs";
|
|
78656
|
-
import
|
|
78748
|
+
import path25 from "path";
|
|
78657
78749
|
|
|
78658
78750
|
// src/core/adapter/execution-source.ts
|
|
78659
78751
|
init_dist();
|
|
78660
78752
|
import { createHash as createHash4 } from "crypto";
|
|
78661
78753
|
|
|
78662
78754
|
// src/execution/json.ts
|
|
78663
|
-
function fail(
|
|
78664
|
-
throw new TypeError(`${
|
|
78755
|
+
function fail(path19, detail) {
|
|
78756
|
+
throw new TypeError(`${path19} ${detail}`);
|
|
78665
78757
|
}
|
|
78666
|
-
function cloneExecutionJson(value,
|
|
78758
|
+
function cloneExecutionJson(value, path19 = "execution value", ancestors = new Set) {
|
|
78667
78759
|
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
78668
78760
|
return value;
|
|
78669
78761
|
if (typeof value === "number") {
|
|
78670
78762
|
if (!Number.isFinite(value))
|
|
78671
|
-
fail(
|
|
78763
|
+
fail(path19, "must contain only finite numbers");
|
|
78672
78764
|
return value;
|
|
78673
78765
|
}
|
|
78674
78766
|
if (value === undefined)
|
|
78675
|
-
fail(
|
|
78767
|
+
fail(path19, "must be omitted rather than set to undefined");
|
|
78676
78768
|
if (typeof value !== "object")
|
|
78677
|
-
fail(
|
|
78769
|
+
fail(path19, "must be JSON-safe");
|
|
78678
78770
|
if (ancestors.has(value))
|
|
78679
|
-
fail(
|
|
78771
|
+
fail(path19, "must not contain a cycle");
|
|
78680
78772
|
const nextAncestors = new Set(ancestors);
|
|
78681
78773
|
nextAncestors.add(value);
|
|
78682
78774
|
if (Array.isArray(value)) {
|
|
78683
78775
|
if (Object.getPrototypeOf(value) !== Array.prototype)
|
|
78684
|
-
fail(
|
|
78776
|
+
fail(path19, "array must use the standard Array prototype");
|
|
78685
78777
|
const ownKeys = Reflect.ownKeys(value);
|
|
78686
78778
|
const lengthDescriptor = Reflect.getOwnPropertyDescriptor(value, "length");
|
|
78687
78779
|
if (!lengthDescriptor || !("value" in lengthDescriptor) || typeof lengthDescriptor.value !== "number" || !Number.isInteger(lengthDescriptor.value) || lengthDescriptor.value < 0) {
|
|
78688
|
-
fail(
|
|
78780
|
+
fail(path19, "array length must be a stable nonnegative integer data property");
|
|
78689
78781
|
}
|
|
78690
78782
|
const length = lengthDescriptor.value;
|
|
78691
78783
|
if (ownKeys.length !== length + 1) {
|
|
78692
|
-
fail(
|
|
78784
|
+
fail(path19, "array must be dense and contain no non-index properties");
|
|
78693
78785
|
}
|
|
78694
78786
|
for (const key of ownKeys) {
|
|
78695
78787
|
if (key === "length")
|
|
78696
78788
|
continue;
|
|
78697
78789
|
if (typeof key !== "string" || !/^(?:0|[1-9]\d*)$/.test(key) || Number(key) >= length) {
|
|
78698
|
-
fail(
|
|
78790
|
+
fail(path19, "array must contain only canonical index properties");
|
|
78699
78791
|
}
|
|
78700
78792
|
}
|
|
78701
78793
|
const cloned2 = [];
|
|
78702
78794
|
for (let index = 0;index < length; index++) {
|
|
78703
78795
|
const descriptor = Reflect.getOwnPropertyDescriptor(value, String(index));
|
|
78704
78796
|
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
78705
|
-
fail(
|
|
78797
|
+
fail(path19, "array must be dense enumerable data properties");
|
|
78706
78798
|
}
|
|
78707
|
-
cloned2.push(cloneExecutionJson(descriptor.value, `${
|
|
78799
|
+
cloned2.push(cloneExecutionJson(descriptor.value, `${path19}[${index}]`, nextAncestors));
|
|
78708
78800
|
}
|
|
78709
78801
|
return Object.freeze(cloned2);
|
|
78710
78802
|
}
|
|
78711
|
-
const snapshot = snapshotStrictRecord(value,
|
|
78803
|
+
const snapshot = snapshotStrictRecord(value, path19);
|
|
78712
78804
|
const cloned = Object.create(null);
|
|
78713
78805
|
for (const [key, child] of Object.entries(snapshot)) {
|
|
78714
78806
|
Object.defineProperty(cloned, key, {
|
|
78715
|
-
value: cloneExecutionJson(child, `${
|
|
78807
|
+
value: cloneExecutionJson(child, `${path19}.${key}`, nextAncestors),
|
|
78716
78808
|
enumerable: true,
|
|
78717
78809
|
configurable: false,
|
|
78718
78810
|
writable: false
|
|
@@ -78720,10 +78812,10 @@ function cloneExecutionJson(value, path18 = "execution value", ancestors = new S
|
|
|
78720
78812
|
}
|
|
78721
78813
|
return Object.freeze(cloned);
|
|
78722
78814
|
}
|
|
78723
|
-
function cloneExecutionJsonObject(value,
|
|
78724
|
-
const cloned = cloneExecutionJson(value,
|
|
78815
|
+
function cloneExecutionJsonObject(value, path19) {
|
|
78816
|
+
const cloned = cloneExecutionJson(value, path19);
|
|
78725
78817
|
if (cloned === null || Array.isArray(cloned) || typeof cloned !== "object") {
|
|
78726
|
-
fail(
|
|
78818
|
+
fail(path19, "must be a JSON object");
|
|
78727
78819
|
}
|
|
78728
78820
|
return cloned;
|
|
78729
78821
|
}
|
|
@@ -78737,11 +78829,11 @@ var WINDOWS_DRIVE_PREFIX_PATTERN = /^[A-Za-z]:/;
|
|
|
78737
78829
|
var RESERVED_EXTENSION_OWNERS = new Set(["__proto__", "constructor", "prototype", "tostring"]);
|
|
78738
78830
|
var renderedSourceBrand = Symbol("akm.adapter-rendered-execution-source");
|
|
78739
78831
|
var renderedSourceInstances = new WeakSet;
|
|
78740
|
-
function requireRecord(value,
|
|
78741
|
-
return snapshotStrictRecord(value,
|
|
78832
|
+
function requireRecord(value, path19) {
|
|
78833
|
+
return snapshotStrictRecord(value, path19);
|
|
78742
78834
|
}
|
|
78743
|
-
function assertOnlyKeys(value, allowed,
|
|
78744
|
-
assertSnapshotKeys(value, allowed,
|
|
78835
|
+
function assertOnlyKeys(value, allowed, path19) {
|
|
78836
|
+
assertSnapshotKeys(value, allowed, path19);
|
|
78745
78837
|
}
|
|
78746
78838
|
function validateExtensionOwner(owner) {
|
|
78747
78839
|
const normalized = owner.toLowerCase();
|
|
@@ -78757,16 +78849,16 @@ function frozenNullPrototypeMap(entries) {
|
|
|
78757
78849
|
return Object.freeze(out);
|
|
78758
78850
|
}
|
|
78759
78851
|
function cloneExtensionEntry(value, index) {
|
|
78760
|
-
const
|
|
78761
|
-
const cloned = cloneExecutionJson(value,
|
|
78852
|
+
const path19 = `extension entry ${index}`;
|
|
78853
|
+
const cloned = cloneExecutionJson(value, path19);
|
|
78762
78854
|
if (!Array.isArray(cloned) || cloned.length !== 2) {
|
|
78763
|
-
throw new TypeError(`${
|
|
78855
|
+
throw new TypeError(`${path19} must be a two-element [owner, values] array`);
|
|
78764
78856
|
}
|
|
78765
78857
|
const [owner, values] = cloned;
|
|
78766
78858
|
if (typeof owner !== "string")
|
|
78767
|
-
throw new TypeError(`${
|
|
78859
|
+
throw new TypeError(`${path19} owner must be a string`);
|
|
78768
78860
|
if (values === null || Array.isArray(values) || typeof values !== "object") {
|
|
78769
|
-
throw new TypeError(`${
|
|
78861
|
+
throw new TypeError(`${path19} values must be a JSON object`);
|
|
78770
78862
|
}
|
|
78771
78863
|
return [owner, values];
|
|
78772
78864
|
}
|
|
@@ -78784,18 +78876,18 @@ function createAdapterExtensions(first, second, ...rest) {
|
|
|
78784
78876
|
}
|
|
78785
78877
|
return frozenNullPrototypeMap(cloned);
|
|
78786
78878
|
}
|
|
78787
|
-
function cloneAdapterExtensions(value,
|
|
78788
|
-
const record = requireRecord(value,
|
|
78789
|
-
const entries = Object.entries(record).map(([owner, fields]) => [owner, cloneExecutionJsonObject(fields, `${
|
|
78879
|
+
function cloneAdapterExtensions(value, path19) {
|
|
78880
|
+
const record = requireRecord(value, path19);
|
|
78881
|
+
const entries = Object.entries(record).map(([owner, fields]) => [owner, cloneExecutionJsonObject(fields, `${path19}.${owner}`)]);
|
|
78790
78882
|
const [first, ...rest] = entries;
|
|
78791
78883
|
return first ? createAdapterExtensions(first, ...rest) : frozenNullPrototypeMap([]);
|
|
78792
78884
|
}
|
|
78793
|
-
function requireCanonicalString(value,
|
|
78885
|
+
function requireCanonicalString(value, path19) {
|
|
78794
78886
|
if (typeof value !== "string" || value.length === 0 || !isWellFormedUnicode(value) || value.normalize("NFC") !== value) {
|
|
78795
|
-
throw new TypeError(`${
|
|
78887
|
+
throw new TypeError(`${path19} must be a non-empty NFC string`);
|
|
78796
78888
|
}
|
|
78797
78889
|
if (hasUnsafeIdentityCharacter(value)) {
|
|
78798
|
-
throw new TypeError(`${
|
|
78890
|
+
throw new TypeError(`${path19} must not contain Unicode control or dangerous format characters`);
|
|
78799
78891
|
}
|
|
78800
78892
|
return value;
|
|
78801
78893
|
}
|
|
@@ -78822,38 +78914,38 @@ function isWellFormedUnicode(value) {
|
|
|
78822
78914
|
}
|
|
78823
78915
|
return true;
|
|
78824
78916
|
}
|
|
78825
|
-
function validateCanonicalIdentity(input,
|
|
78826
|
-
assertOnlyKeys(input, ["ref", "bundle", "adapter", "file", "hash"],
|
|
78827
|
-
const ref = requireCanonicalString(input.ref, `${
|
|
78828
|
-
const bundle = requireCanonicalString(input.bundle, `${
|
|
78829
|
-
const adapter = requireCanonicalString(input.adapter, `${
|
|
78830
|
-
const file = requireCanonicalString(input.file, `${
|
|
78831
|
-
const hash = requireCanonicalString(input.hash, `${
|
|
78917
|
+
function validateCanonicalIdentity(input, path19) {
|
|
78918
|
+
assertOnlyKeys(input, ["ref", "bundle", "adapter", "file", "hash"], path19);
|
|
78919
|
+
const ref = requireCanonicalString(input.ref, `${path19}.ref`);
|
|
78920
|
+
const bundle = requireCanonicalString(input.bundle, `${path19}.bundle`);
|
|
78921
|
+
const adapter = requireCanonicalString(input.adapter, `${path19}.adapter`);
|
|
78922
|
+
const file = requireCanonicalString(input.file, `${path19}.file`);
|
|
78923
|
+
const hash = requireCanonicalString(input.hash, `${path19}.hash`);
|
|
78832
78924
|
let parsed;
|
|
78833
78925
|
try {
|
|
78834
78926
|
parsed = parseBundleRef(ref);
|
|
78835
78927
|
} catch (cause) {
|
|
78836
|
-
throw new TypeError(`${
|
|
78928
|
+
throw new TypeError(`${path19}.ref is not a canonical bundle ref`, { cause });
|
|
78837
78929
|
}
|
|
78838
78930
|
if (parsed.bundle === undefined || parsed.bundle !== bundle || parsed.fragment !== undefined || !isBundleSlug(bundle) || bundleRefToString(parsed) !== ref) {
|
|
78839
|
-
throw new TypeError(`${
|
|
78931
|
+
throw new TypeError(`${path19}.ref must round-trip as the same fully-qualified bundle ref without a fragment`);
|
|
78840
78932
|
}
|
|
78841
78933
|
if (!EXECUTION_ADAPTER_ID_PATTERN.test(adapter)) {
|
|
78842
|
-
throw new TypeError(`${
|
|
78934
|
+
throw new TypeError(`${path19}.adapter must use the current lowercase kebab-case adapter identifier grammar`);
|
|
78843
78935
|
}
|
|
78844
78936
|
const segments = file.split("/");
|
|
78845
78937
|
if (file.startsWith("/") || WINDOWS_DRIVE_PREFIX_PATTERN.test(file) || file.includes("\\") || segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
78846
|
-
throw new TypeError(`${
|
|
78938
|
+
throw new TypeError(`${path19}.file must be a normalized relative POSIX path`);
|
|
78847
78939
|
}
|
|
78848
78940
|
if (!/^[a-f0-9]{64}$/.test(hash))
|
|
78849
|
-
throw new TypeError(`${
|
|
78941
|
+
throw new TypeError(`${path19}.hash must be a SHA-256 hex digest`);
|
|
78850
78942
|
return { ref, bundle, adapter, file, hash };
|
|
78851
78943
|
}
|
|
78852
78944
|
function createExecutionSourceIdentity(input) {
|
|
78853
78945
|
return Object.freeze(validateCanonicalIdentity(requireRecord(input, "execution source identity"), "execution source identity"));
|
|
78854
78946
|
}
|
|
78855
|
-
function cloneUnresolvedExecutionDefaults(input,
|
|
78856
|
-
const record = requireRecord(input,
|
|
78947
|
+
function cloneUnresolvedExecutionDefaults(input, path19 = "execution source defaults") {
|
|
78948
|
+
const record = requireRecord(input, path19);
|
|
78857
78949
|
assertOnlyKeys(record, [
|
|
78858
78950
|
"agent",
|
|
78859
78951
|
"engine",
|
|
@@ -78865,47 +78957,47 @@ function cloneUnresolvedExecutionDefaults(input, path18 = "execution source defa
|
|
|
78865
78957
|
"workspace",
|
|
78866
78958
|
"environment",
|
|
78867
78959
|
"runtime"
|
|
78868
|
-
],
|
|
78869
|
-
const json = { ...cloneExecutionJsonObject(record,
|
|
78960
|
+
], path19);
|
|
78961
|
+
const json = { ...cloneExecutionJsonObject(record, path19) };
|
|
78870
78962
|
for (const key of ["agent", "engine", "model", "workspace"]) {
|
|
78871
78963
|
const value = json[key];
|
|
78872
78964
|
if (value !== undefined && value !== null && typeof value !== "string") {
|
|
78873
|
-
throw new TypeError(`${
|
|
78965
|
+
throw new TypeError(`${path19}.${key} must be a string or null`);
|
|
78874
78966
|
}
|
|
78875
78967
|
}
|
|
78876
78968
|
const timeout = json.timeout;
|
|
78877
78969
|
if (timeout !== undefined && timeout !== null && typeof timeout !== "string" && typeof timeout !== "number") {
|
|
78878
|
-
throw new TypeError(`${
|
|
78970
|
+
throw new TypeError(`${path19}.timeout must be a string, number, or null`);
|
|
78879
78971
|
}
|
|
78880
78972
|
for (const key of ["inference", "outputSchema", "runtime"]) {
|
|
78881
78973
|
const value = json[key];
|
|
78882
78974
|
if (value !== undefined && value !== null && (Array.isArray(value) || typeof value !== "object")) {
|
|
78883
|
-
throw new TypeError(`${
|
|
78975
|
+
throw new TypeError(`${path19}.${key} must be an object or null`);
|
|
78884
78976
|
}
|
|
78885
78977
|
}
|
|
78886
78978
|
const environment = json.environment;
|
|
78887
78979
|
if (environment !== undefined && environment !== null) {
|
|
78888
78980
|
if (Array.isArray(environment) || typeof environment !== "object") {
|
|
78889
|
-
throw new TypeError(`${
|
|
78981
|
+
throw new TypeError(`${path19}.environment must be an object or null`);
|
|
78890
78982
|
}
|
|
78891
78983
|
if (Object.values(environment).some((value) => typeof value !== "string")) {
|
|
78892
|
-
throw new TypeError(`${
|
|
78984
|
+
throw new TypeError(`${path19}.environment values must be strings`);
|
|
78893
78985
|
}
|
|
78894
78986
|
}
|
|
78895
78987
|
if (Object.hasOwn(json, "tools"))
|
|
78896
|
-
json.tools = cloneToolSelection(json.tools, `${
|
|
78988
|
+
json.tools = cloneToolSelection(json.tools, `${path19}.tools`);
|
|
78897
78989
|
return Object.freeze(json);
|
|
78898
78990
|
}
|
|
78899
|
-
function cloneToolSelection(value,
|
|
78991
|
+
function cloneToolSelection(value, path19 = "tools") {
|
|
78900
78992
|
if (value === null || typeof value === "string")
|
|
78901
78993
|
return value;
|
|
78902
|
-
const cloned = cloneExecutionJson(value,
|
|
78994
|
+
const cloned = cloneExecutionJson(value, path19);
|
|
78903
78995
|
if (Array.isArray(cloned)) {
|
|
78904
78996
|
if (cloned.some((tool) => typeof tool !== "string"))
|
|
78905
|
-
throw new TypeError(`${
|
|
78997
|
+
throw new TypeError(`${path19} array values must be strings`);
|
|
78906
78998
|
return cloned;
|
|
78907
78999
|
}
|
|
78908
|
-
return cloneExecutionJsonObject(cloned,
|
|
79000
|
+
return cloneExecutionJsonObject(cloned, path19);
|
|
78909
79001
|
}
|
|
78910
79002
|
function createAdapterRenderedExecutionSource(input) {
|
|
78911
79003
|
const record = requireRecord(input, "adapter-rendered execution source");
|
|
@@ -79014,34 +79106,34 @@ function parseExecutionMarkdown(raw) {
|
|
|
79014
79106
|
function own(data, key) {
|
|
79015
79107
|
return Object.hasOwn(data, key);
|
|
79016
79108
|
}
|
|
79017
|
-
function requireMetadataMapping(value,
|
|
79109
|
+
function requireMetadataMapping(value, path19) {
|
|
79018
79110
|
try {
|
|
79019
|
-
return snapshotStrictRecord(value,
|
|
79111
|
+
return snapshotStrictRecord(value, path19);
|
|
79020
79112
|
} catch (cause) {
|
|
79021
|
-
throw new TypeError(`${
|
|
79113
|
+
throw new TypeError(`${path19} must be a mapping with enumerable data fields`, { cause });
|
|
79022
79114
|
}
|
|
79023
79115
|
}
|
|
79024
|
-
function nullableString(value,
|
|
79116
|
+
function nullableString(value, path19) {
|
|
79025
79117
|
if (value !== null && typeof value !== "string")
|
|
79026
|
-
throw new TypeError(`${
|
|
79118
|
+
throw new TypeError(`${path19} must be a string or null`);
|
|
79027
79119
|
return value;
|
|
79028
79120
|
}
|
|
79029
|
-
function nullableObject(value,
|
|
79030
|
-
return value === null ? null : cloneExecutionJsonObject(value,
|
|
79121
|
+
function nullableObject(value, path19) {
|
|
79122
|
+
return value === null ? null : cloneExecutionJsonObject(value, path19);
|
|
79031
79123
|
}
|
|
79032
|
-
function nullableEnvironment(value,
|
|
79124
|
+
function nullableEnvironment(value, path19) {
|
|
79033
79125
|
if (value === null)
|
|
79034
79126
|
return null;
|
|
79035
|
-
const environment = cloneExecutionJsonObject(value,
|
|
79127
|
+
const environment = cloneExecutionJsonObject(value, path19);
|
|
79036
79128
|
if (Object.values(environment).some((entry) => typeof entry !== "string")) {
|
|
79037
|
-
throw new TypeError(`${
|
|
79129
|
+
throw new TypeError(`${path19} values must be strings`);
|
|
79038
79130
|
}
|
|
79039
79131
|
return environment;
|
|
79040
79132
|
}
|
|
79041
|
-
function nullableTimeout(value,
|
|
79042
|
-
const timeout = cloneExecutionJson(value,
|
|
79133
|
+
function nullableTimeout(value, path19) {
|
|
79134
|
+
const timeout = cloneExecutionJson(value, path19);
|
|
79043
79135
|
if (timeout !== null && typeof timeout !== "string" && typeof timeout !== "number") {
|
|
79044
|
-
throw new TypeError(`${
|
|
79136
|
+
throw new TypeError(`${path19} must be a string, number, or null`);
|
|
79045
79137
|
}
|
|
79046
79138
|
return timeout;
|
|
79047
79139
|
}
|
|
@@ -79485,7 +79577,7 @@ function recognizeMatch(file) {
|
|
|
79485
79577
|
}
|
|
79486
79578
|
|
|
79487
79579
|
// src/core/adapter/adapters/akm-lint.ts
|
|
79488
|
-
import
|
|
79580
|
+
import path24 from "path";
|
|
79489
79581
|
|
|
79490
79582
|
// src/commands/lint/env-key-rules.ts
|
|
79491
79583
|
init_env();
|
|
@@ -79608,28 +79700,28 @@ var MOVE_TO_ENV = "Workflow params are copied verbatim into every native unit ex
|
|
|
79608
79700
|
function detectSecretShapedParams(params) {
|
|
79609
79701
|
const warnings = [];
|
|
79610
79702
|
const seen = new Set;
|
|
79611
|
-
const push = (
|
|
79612
|
-
if (seen.has(
|
|
79703
|
+
const push = (path20, why) => {
|
|
79704
|
+
if (seen.has(path20))
|
|
79613
79705
|
return;
|
|
79614
|
-
seen.add(
|
|
79615
|
-
warnings.push(`Run param "${
|
|
79706
|
+
seen.add(path20);
|
|
79707
|
+
warnings.push(`Run param "${path20}" ${why}. ${MOVE_TO_ENV} (Heuristic warning; params are declared non-secret.)`);
|
|
79616
79708
|
};
|
|
79617
|
-
const walk = (value,
|
|
79709
|
+
const walk = (value, path20, key) => {
|
|
79618
79710
|
if (key !== null && keyLooksSecret(key))
|
|
79619
|
-
push(
|
|
79711
|
+
push(path20, "has a secret-suggesting name");
|
|
79620
79712
|
if (typeof value === "string") {
|
|
79621
79713
|
if (valueLooksSecret(value))
|
|
79622
|
-
push(
|
|
79714
|
+
push(path20, "has a secret-shaped value (long, high-entropy string)");
|
|
79623
79715
|
return;
|
|
79624
79716
|
}
|
|
79625
79717
|
if (Array.isArray(value)) {
|
|
79626
79718
|
for (let i = 0;i < value.length; i++)
|
|
79627
|
-
walk(value[i], `${
|
|
79719
|
+
walk(value[i], `${path20}[${i}]`, null);
|
|
79628
79720
|
return;
|
|
79629
79721
|
}
|
|
79630
79722
|
if (value && typeof value === "object") {
|
|
79631
79723
|
for (const [k, v] of Object.entries(value)) {
|
|
79632
|
-
walk(v,
|
|
79724
|
+
walk(v, path20 ? `${path20}.${k}` : k, k);
|
|
79633
79725
|
}
|
|
79634
79726
|
}
|
|
79635
79727
|
};
|
|
@@ -80077,8 +80169,8 @@ init_dist();
|
|
|
80077
80169
|
init_asset_ref();
|
|
80078
80170
|
init_extra_params();
|
|
80079
80171
|
init_resource_limits();
|
|
80080
|
-
import
|
|
80081
|
-
import
|
|
80172
|
+
import crypto4 from "crypto";
|
|
80173
|
+
import path20 from "path";
|
|
80082
80174
|
|
|
80083
80175
|
// src/tasks/task-id.ts
|
|
80084
80176
|
init_errors();
|
|
@@ -80520,7 +80612,7 @@ var KNOWN_PROMPT_REF_FAMILIES = new Set([
|
|
|
80520
80612
|
"workflows"
|
|
80521
80613
|
]);
|
|
80522
80614
|
function hash(bytes) {
|
|
80523
|
-
return
|
|
80615
|
+
return crypto4.createHash("sha256").update(bytes).digest("hex");
|
|
80524
80616
|
}
|
|
80525
80617
|
function base(input) {
|
|
80526
80618
|
return {
|
|
@@ -80679,7 +80771,7 @@ function addSharedNonPromptOverrides(data, akm) {
|
|
|
80679
80771
|
}
|
|
80680
80772
|
function promptSourceKind(raw) {
|
|
80681
80773
|
const trimmed = raw.trim();
|
|
80682
|
-
if (trimmed.startsWith("./") || trimmed.startsWith("../") ||
|
|
80774
|
+
if (trimmed.startsWith("./") || trimmed.startsWith("../") || path20.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
|
|
80683
80775
|
return "file";
|
|
80684
80776
|
}
|
|
80685
80777
|
try {
|
|
@@ -80786,7 +80878,7 @@ function planLegacyTaskDataToV3(input, data) {
|
|
|
80786
80878
|
return blocked(input, "read-only-source", !input.writable ? "the owning source is not writable" : "the source file or publication directory is read-only");
|
|
80787
80879
|
}
|
|
80788
80880
|
try {
|
|
80789
|
-
validateTaskId(
|
|
80881
|
+
validateTaskId(path20.basename(input.filePath, ".yml"));
|
|
80790
80882
|
} catch (cause) {
|
|
80791
80883
|
return blocked(input, "invalid-v2-task", cause instanceof Error ? cause.message : String(cause));
|
|
80792
80884
|
}
|
|
@@ -80856,7 +80948,7 @@ function planTaskToV3File(input) {
|
|
|
80856
80948
|
return planLegacyTaskDataToV3(input, data);
|
|
80857
80949
|
}
|
|
80858
80950
|
function generationFor(files) {
|
|
80859
|
-
const digest =
|
|
80951
|
+
const digest = crypto4.createHash("sha256");
|
|
80860
80952
|
digest.update("akm-task-to-v3-plan-v1\x00");
|
|
80861
80953
|
for (const file of files) {
|
|
80862
80954
|
digest.update(file.filePath);
|
|
@@ -80890,7 +80982,7 @@ function taskToV3PlanFromOutcomes(outcomes) {
|
|
|
80890
80982
|
for (let index = 1;index < files.length; index += 1) {
|
|
80891
80983
|
const previous = files[index - 1];
|
|
80892
80984
|
const current = files[index];
|
|
80893
|
-
if (previous && current &&
|
|
80985
|
+
if (previous && current && path20.resolve(previous.filePath) === path20.resolve(current.filePath)) {
|
|
80894
80986
|
throw new Error(`duplicate task migration file path: ${current.filePath}`);
|
|
80895
80987
|
}
|
|
80896
80988
|
}
|
|
@@ -80900,7 +80992,7 @@ function planTaskToV3Migration(inputs) {
|
|
|
80900
80992
|
const sorted = [...inputs].sort((left, right) => left.filePath < right.filePath ? -1 : left.filePath > right.filePath ? 1 : 0);
|
|
80901
80993
|
let previous;
|
|
80902
80994
|
for (const current of sorted) {
|
|
80903
|
-
if (previous &&
|
|
80995
|
+
if (previous && path20.resolve(previous.filePath) === path20.resolve(current.filePath)) {
|
|
80904
80996
|
throw new Error(`duplicate task migration file path: ${current.filePath}`);
|
|
80905
80997
|
}
|
|
80906
80998
|
previous = current;
|
|
@@ -80911,8 +81003,8 @@ function planTaskToV3Migration(inputs) {
|
|
|
80911
81003
|
// src/tasks/source/task-to-v4.ts
|
|
80912
81004
|
init_dist();
|
|
80913
81005
|
init_bounded_document();
|
|
80914
|
-
import
|
|
80915
|
-
import
|
|
81006
|
+
import crypto5 from "crypto";
|
|
81007
|
+
import path21 from "path";
|
|
80916
81008
|
var V3_TOP_LEVEL_KEYS = new Set([
|
|
80917
81009
|
"version",
|
|
80918
81010
|
"name",
|
|
@@ -80958,7 +81050,7 @@ var AKM_HOIST_KEYS = [
|
|
|
80958
81050
|
"maxRetries"
|
|
80959
81051
|
];
|
|
80960
81052
|
function hash2(bytes) {
|
|
80961
|
-
return
|
|
81053
|
+
return crypto5.createHash("sha256").update(bytes).digest("hex");
|
|
80962
81054
|
}
|
|
80963
81055
|
function causeMessage(cause) {
|
|
80964
81056
|
return cause instanceof Error ? cause.message : String(cause);
|
|
@@ -81227,7 +81319,7 @@ function planTaskToV4File(input) {
|
|
|
81227
81319
|
return planV3DataToV4(input, data);
|
|
81228
81320
|
}
|
|
81229
81321
|
function generationFor2(files) {
|
|
81230
|
-
const digest =
|
|
81322
|
+
const digest = crypto5.createHash("sha256");
|
|
81231
81323
|
digest.update("akm-task-to-v4-plan-v1\x00");
|
|
81232
81324
|
for (const file of files) {
|
|
81233
81325
|
digest.update(file.filePath);
|
|
@@ -81264,7 +81356,7 @@ function taskToV4PlanFromOutcomes(outcomes) {
|
|
|
81264
81356
|
for (let index = 1;index < files.length; index += 1) {
|
|
81265
81357
|
const previous = files[index - 1];
|
|
81266
81358
|
const current = files[index];
|
|
81267
|
-
if (previous && current &&
|
|
81359
|
+
if (previous && current && path21.resolve(previous.filePath) === path21.resolve(current.filePath)) {
|
|
81268
81360
|
throw new Error(`duplicate task migration file path: ${current.filePath}`);
|
|
81269
81361
|
}
|
|
81270
81362
|
}
|
|
@@ -81274,7 +81366,7 @@ function planTaskToV4Migration(inputs) {
|
|
|
81274
81366
|
const sorted = [...inputs].sort((left, right) => left.filePath < right.filePath ? -1 : left.filePath > right.filePath ? 1 : 0);
|
|
81275
81367
|
let previous;
|
|
81276
81368
|
for (const current of sorted) {
|
|
81277
|
-
if (previous &&
|
|
81369
|
+
if (previous && path21.resolve(previous.filePath) === path21.resolve(current.filePath)) {
|
|
81278
81370
|
throw new Error(`duplicate task migration file path: ${current.filePath}`);
|
|
81279
81371
|
}
|
|
81280
81372
|
previous = current;
|
|
@@ -81589,7 +81681,7 @@ function checkInvalidTypeValue(data, allowedTypes) {
|
|
|
81589
81681
|
return `type field has invalid value '${value}'; expected one of: ${allowedTypes.join(", ")}`;
|
|
81590
81682
|
}
|
|
81591
81683
|
function suggestSlug(filePath) {
|
|
81592
|
-
return
|
|
81684
|
+
return path24.basename(filePath, ".md").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
81593
81685
|
}
|
|
81594
81686
|
function nameOrTypeDiagnostics(relPath, data, frontmatter, allowedTypes) {
|
|
81595
81687
|
const missingFieldDetail = checkMissingNameOrType(data, frontmatter);
|
|
@@ -81629,7 +81721,7 @@ function collectSuppressedKeys(raw) {
|
|
|
81629
81721
|
function dangerousEnvKeyDiagnostics(type, relPath, raw) {
|
|
81630
81722
|
if (type !== "env" && type !== "secret")
|
|
81631
81723
|
return [];
|
|
81632
|
-
const baseNameWithExt =
|
|
81724
|
+
const baseNameWithExt = path24.basename(relPath);
|
|
81633
81725
|
if (!baseNameWithExt.endsWith(".env"))
|
|
81634
81726
|
return [];
|
|
81635
81727
|
const ref = conceptIdForStashFile(type, ".", relPath);
|
|
@@ -81775,7 +81867,7 @@ function workflowFrontendDiagnostics(relPath, raw, parsePath2) {
|
|
|
81775
81867
|
}
|
|
81776
81868
|
return { errors: errors3, warnings };
|
|
81777
81869
|
}
|
|
81778
|
-
const compiled = compileWorkflowPlan(result.ir,
|
|
81870
|
+
const compiled = compileWorkflowPlan(result.ir, path24.basename(parsePath2, path24.extname(parsePath2)));
|
|
81779
81871
|
if (!compiled.ok) {
|
|
81780
81872
|
for (const err of compiled.errors) {
|
|
81781
81873
|
errors3.push({
|
|
@@ -82093,13 +82185,13 @@ function isReservedFileName(name) {
|
|
|
82093
82185
|
}
|
|
82094
82186
|
var WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
|
|
82095
82187
|
function akmStashAbstains(root, absPath) {
|
|
82096
|
-
const relPath =
|
|
82097
|
-
if (!relPath || relPath.startsWith("..") ||
|
|
82188
|
+
const relPath = path25.relative(root, absPath);
|
|
82189
|
+
if (!relPath || relPath.startsWith("..") || path25.isAbsolute(relPath))
|
|
82098
82190
|
return false;
|
|
82099
82191
|
const segments = relPath.split(/[\\/]+/).filter(Boolean);
|
|
82100
82192
|
if (segments.length === 0)
|
|
82101
82193
|
return false;
|
|
82102
|
-
if (segments[0] === "env" && (absPath.endsWith(".env") ||
|
|
82194
|
+
if (segments[0] === "env" && (absPath.endsWith(".env") || path25.basename(absPath) === ".env")) {
|
|
82103
82195
|
if (fs16.existsSync(absPath.replace(/\.env$/, ".sensitive")))
|
|
82104
82196
|
return true;
|
|
82105
82197
|
}
|
|
@@ -82206,7 +82298,7 @@ function recognize2(c, file) {
|
|
|
82206
82298
|
return null;
|
|
82207
82299
|
const stashDir = stashDirFor(match.type);
|
|
82208
82300
|
const canonicalName = stashDir !== undefined ? conceptId.slice(stashDir.length + 1) : conceptId;
|
|
82209
|
-
const dirPath =
|
|
82301
|
+
const dirPath = path25.dirname(file.absPath);
|
|
82210
82302
|
const entry = {
|
|
82211
82303
|
name: canonicalName,
|
|
82212
82304
|
type: match.type,
|
|
@@ -82252,13 +82344,13 @@ function renderExecutionSource(c, file) {
|
|
|
82252
82344
|
});
|
|
82253
82345
|
}
|
|
82254
82346
|
function buildOverlayContext(root, relPathInput, raw) {
|
|
82255
|
-
const absPath =
|
|
82256
|
-
const relPath =
|
|
82257
|
-
const ext =
|
|
82258
|
-
const fileName =
|
|
82259
|
-
const parentDirAbs =
|
|
82260
|
-
const parentDir =
|
|
82261
|
-
const relDir =
|
|
82347
|
+
const absPath = path25.join(root, relPathInput);
|
|
82348
|
+
const relPath = path25.relative(root, absPath).replace(/\\/g, "/");
|
|
82349
|
+
const ext = path25.extname(absPath).toLowerCase();
|
|
82350
|
+
const fileName = path25.basename(absPath);
|
|
82351
|
+
const parentDirAbs = path25.dirname(absPath);
|
|
82352
|
+
const parentDir = path25.basename(parentDirAbs);
|
|
82353
|
+
const relDir = path25.dirname(relPath).replace(/\\/g, "/");
|
|
82262
82354
|
const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter((seg) => seg.length > 0);
|
|
82263
82355
|
let cachedFrontmatter;
|
|
82264
82356
|
let frontmatterComputed = false;
|
|
@@ -82356,13 +82448,13 @@ var akmAdapter = {
|
|
|
82356
82448
|
const posix = conceptId.replace(/\\/g, "/");
|
|
82357
82449
|
const slash = posix.indexOf("/");
|
|
82358
82450
|
if (slash <= 0)
|
|
82359
|
-
return [{ path:
|
|
82451
|
+
return [{ path: path25.join(c.root, `${posix}.md`), conceptId: posix }];
|
|
82360
82452
|
const head = posix.slice(0, slash);
|
|
82361
82453
|
const rest = posix.slice(slash + 1);
|
|
82362
82454
|
const type = stashDirToType(head);
|
|
82363
82455
|
if (type === undefined || rest.length === 0)
|
|
82364
82456
|
return [];
|
|
82365
|
-
const canonical = assetPathCandidatesForName(type,
|
|
82457
|
+
const canonical = assetPathCandidatesForName(type, path25.join(c.root, head), rest);
|
|
82366
82458
|
const loose = assetPathCandidatesForName(type, c.root, rest);
|
|
82367
82459
|
return [...new Set([...canonical, ...loose])].map((candidatePath) => ({
|
|
82368
82460
|
path: candidatePath,
|
|
@@ -82377,18 +82469,18 @@ var akmAdapter = {
|
|
|
82377
82469
|
const rest = posix.slice(slash + 1);
|
|
82378
82470
|
const type = stashDirToType(head);
|
|
82379
82471
|
if (type !== undefined && rest.length > 0) {
|
|
82380
|
-
const typeDir =
|
|
82472
|
+
const typeDir = path25.join(c.root, head);
|
|
82381
82473
|
return assetPathForName(type, typeDir, rest);
|
|
82382
82474
|
}
|
|
82383
82475
|
}
|
|
82384
|
-
return
|
|
82476
|
+
return path25.join(c.root, `${posix}.md`);
|
|
82385
82477
|
},
|
|
82386
82478
|
directoryList(_c) {
|
|
82387
82479
|
return [...new Set(stashDirNames())];
|
|
82388
82480
|
},
|
|
82389
82481
|
looksLikeRoot(root) {
|
|
82390
82482
|
try {
|
|
82391
|
-
if (fs16.statSync(
|
|
82483
|
+
if (fs16.statSync(path25.join(root, ".stash")).isDirectory())
|
|
82392
82484
|
return true;
|
|
82393
82485
|
} catch {}
|
|
82394
82486
|
const ownedDirNames = new Set(stashDirNames());
|
|
@@ -82406,10 +82498,10 @@ var akmAdapter = {
|
|
|
82406
82498
|
return false;
|
|
82407
82499
|
const expectedType = stashDirToType(only.name);
|
|
82408
82500
|
try {
|
|
82409
|
-
const markdown = fs16.readdirSync(
|
|
82501
|
+
const markdown = fs16.readdirSync(path25.join(root, only.name), { withFileTypes: true }).find((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".md"));
|
|
82410
82502
|
if (!markdown)
|
|
82411
82503
|
return true;
|
|
82412
|
-
const data = parseFrontmatter(fs16.readFileSync(
|
|
82504
|
+
const data = parseFrontmatter(fs16.readFileSync(path25.join(root, only.name, markdown.name), "utf8")).data;
|
|
82413
82505
|
const declaredType = typeof data.type === "string" ? data.type.trim() : "";
|
|
82414
82506
|
return !declaredType || declaredType === expectedType;
|
|
82415
82507
|
} catch {
|
|
@@ -82420,7 +82512,7 @@ var akmAdapter = {
|
|
|
82420
82512
|
|
|
82421
82513
|
// src/core/adapter/adapters/akm-task-adapter.ts
|
|
82422
82514
|
import fs17 from "fs";
|
|
82423
|
-
import
|
|
82515
|
+
import path26 from "path";
|
|
82424
82516
|
init_common();
|
|
82425
82517
|
var COMPONENT_ID2 = "main";
|
|
82426
82518
|
var TASK_EXT = TASK_EXTENSION;
|
|
@@ -82451,7 +82543,7 @@ async function validate3(c, changes, ctx) {
|
|
|
82451
82543
|
const raw = change.after ?? await ctx.readFile(change.path);
|
|
82452
82544
|
if (typeof raw !== "string")
|
|
82453
82545
|
continue;
|
|
82454
|
-
const ext =
|
|
82546
|
+
const ext = path26.extname(change.path).toLowerCase();
|
|
82455
82547
|
if (ext !== TASK_EXT && ext !== TASK_NEAR_MISS_EXTENSION)
|
|
82456
82548
|
continue;
|
|
82457
82549
|
const relPath = toPosix(change.path);
|
|
@@ -82486,13 +82578,13 @@ var akmTaskAdapter = {
|
|
|
82486
82578
|
readCandidates(c, conceptId) {
|
|
82487
82579
|
const posix = toPosix(conceptId).replace(/\.ya?ml$/i, "");
|
|
82488
82580
|
return [
|
|
82489
|
-
{ path:
|
|
82490
|
-
{ path:
|
|
82581
|
+
{ path: path26.join(c.root, `${posix}.yml`), conceptId: posix },
|
|
82582
|
+
{ path: path26.join(c.root, `${posix}.yaml`), conceptId: posix }
|
|
82491
82583
|
];
|
|
82492
82584
|
},
|
|
82493
82585
|
placeNew(c, conceptId) {
|
|
82494
82586
|
const posix = toPosix(conceptId);
|
|
82495
|
-
return
|
|
82587
|
+
return path26.join(c.root, /\.yml$/i.test(posix) ? posix : `${posix}.yml`);
|
|
82496
82588
|
},
|
|
82497
82589
|
directoryList() {
|
|
82498
82590
|
return ["."];
|
|
@@ -82505,11 +82597,11 @@ var akmTaskAdapter = {
|
|
|
82505
82597
|
return false;
|
|
82506
82598
|
}
|
|
82507
82599
|
for (const entry of entries) {
|
|
82508
|
-
if (!entry.isFile() ||
|
|
82600
|
+
if (!entry.isFile() || path26.extname(entry.name).toLowerCase() !== TASK_EXT)
|
|
82509
82601
|
continue;
|
|
82510
82602
|
let raw;
|
|
82511
82603
|
try {
|
|
82512
|
-
raw = fs17.readFileSync(
|
|
82604
|
+
raw = fs17.readFileSync(path26.join(root, entry.name), "utf8");
|
|
82513
82605
|
} catch {
|
|
82514
82606
|
continue;
|
|
82515
82607
|
}
|
|
@@ -82527,7 +82619,7 @@ init_compile();
|
|
|
82527
82619
|
init_frontmatter();
|
|
82528
82620
|
init_common();
|
|
82529
82621
|
import fs18 from "fs";
|
|
82530
|
-
import
|
|
82622
|
+
import path27 from "path";
|
|
82531
82623
|
var COMPONENT_ID3 = "main";
|
|
82532
82624
|
var WORKFLOW_EXTS = new Set([".md", ".yml"]);
|
|
82533
82625
|
function conceptIdOf(relPath) {
|
|
@@ -82581,8 +82673,8 @@ async function validate4(c, changes, ctx) {
|
|
|
82581
82673
|
const raw = change.after ?? await ctx.readFile(change.path);
|
|
82582
82674
|
if (typeof raw !== "string")
|
|
82583
82675
|
continue;
|
|
82584
|
-
const ext =
|
|
82585
|
-
if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(
|
|
82676
|
+
const ext = path27.extname(change.path).toLowerCase();
|
|
82677
|
+
if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(path27.basename(change.path)))
|
|
82586
82678
|
continue;
|
|
82587
82679
|
const relPath = toPosix(change.path);
|
|
82588
82680
|
if (ext === ".yml") {
|
|
@@ -82611,12 +82703,12 @@ function hasTopLevelWorkflowFile(root, entries) {
|
|
|
82611
82703
|
for (const entry of entries) {
|
|
82612
82704
|
if (!entry.isFile())
|
|
82613
82705
|
continue;
|
|
82614
|
-
const ext =
|
|
82706
|
+
const ext = path27.extname(entry.name).toLowerCase();
|
|
82615
82707
|
if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(entry.name))
|
|
82616
82708
|
continue;
|
|
82617
82709
|
let raw;
|
|
82618
82710
|
try {
|
|
82619
|
-
raw = fs18.readFileSync(
|
|
82711
|
+
raw = fs18.readFileSync(path27.join(root, entry.name), "utf8");
|
|
82620
82712
|
} catch {
|
|
82621
82713
|
continue;
|
|
82622
82714
|
}
|
|
@@ -82636,16 +82728,16 @@ var akmWorkflowAdapter = {
|
|
|
82636
82728
|
readCandidates(c, conceptId) {
|
|
82637
82729
|
const posix = toPosix(conceptId);
|
|
82638
82730
|
const canonical = posix.replace(/\.(?:md|yml)$/i, "");
|
|
82639
|
-
return /\.(?:md|yml)$/i.test(posix) ? [{ path:
|
|
82640
|
-
{ path:
|
|
82641
|
-
{ path:
|
|
82731
|
+
return /\.(?:md|yml)$/i.test(posix) ? [{ path: path27.join(c.root, posix), conceptId: canonical }] : [
|
|
82732
|
+
{ path: path27.join(c.root, `${posix}.md`), conceptId: canonical },
|
|
82733
|
+
{ path: path27.join(c.root, `${posix}.yml`), conceptId: canonical }
|
|
82642
82734
|
];
|
|
82643
82735
|
},
|
|
82644
82736
|
placeNew(c, conceptId) {
|
|
82645
82737
|
const posix = toPosix(conceptId);
|
|
82646
82738
|
if (/\.(?:md|yml)$/i.test(posix))
|
|
82647
|
-
return
|
|
82648
|
-
return
|
|
82739
|
+
return path27.join(c.root, posix);
|
|
82740
|
+
return path27.join(c.root, `${posix}.md`);
|
|
82649
82741
|
},
|
|
82650
82742
|
directoryList() {
|
|
82651
82743
|
return ["."];
|
|
@@ -82663,10 +82755,10 @@ var akmWorkflowAdapter = {
|
|
|
82663
82755
|
|
|
82664
82756
|
// src/core/adapter/adapters/claude-adapter.ts
|
|
82665
82757
|
import fs19 from "fs";
|
|
82666
|
-
import
|
|
82758
|
+
import path29 from "path";
|
|
82667
82759
|
|
|
82668
82760
|
// src/core/adapter/adapters/tool-dir-shared.ts
|
|
82669
|
-
import
|
|
82761
|
+
import path28 from "path";
|
|
82670
82762
|
init_frontmatter();
|
|
82671
82763
|
init_common();
|
|
82672
82764
|
var CANONICAL_COMMAND_DIR = "commands";
|
|
@@ -82688,7 +82780,7 @@ function classify(relPath, layout) {
|
|
|
82688
82780
|
return { type: "instruction", conceptId: layout.instructionConceptId, name: layout.instructionConceptId };
|
|
82689
82781
|
}
|
|
82690
82782
|
const head = segs[0];
|
|
82691
|
-
const ext =
|
|
82783
|
+
const ext = path28.extname(base3).toLowerCase();
|
|
82692
82784
|
if (layout.skillDirs.has(head)) {
|
|
82693
82785
|
if (segs.length === 3 && base3 === SKILL_MANIFEST2) {
|
|
82694
82786
|
return { type: "skill", conceptId: `${segs[0]}/${segs[1]}`, name: segs[1] };
|
|
@@ -82737,24 +82829,24 @@ function recognizeToolDir(layout, c, file) {
|
|
|
82737
82829
|
function placeNewToolDir(layout, c, conceptId) {
|
|
82738
82830
|
const posix = toPosix(conceptId);
|
|
82739
82831
|
if (posix === layout.instructionConceptId)
|
|
82740
|
-
return
|
|
82832
|
+
return path28.join(c.root, layout.instructionFile);
|
|
82741
82833
|
const segs = posix.split("/").filter((s) => s.length > 0);
|
|
82742
82834
|
const head = segs[0];
|
|
82743
82835
|
const rest = segs.slice(1).join("/");
|
|
82744
82836
|
if (rest.length > 0) {
|
|
82745
82837
|
if (layout.skillDirs.has(head))
|
|
82746
|
-
return
|
|
82838
|
+
return path28.join(c.root, CANONICAL_SKILL_DIR, rest, SKILL_MANIFEST2);
|
|
82747
82839
|
if (layout.commandDirs.has(head))
|
|
82748
|
-
return
|
|
82840
|
+
return path28.join(c.root, CANONICAL_COMMAND_DIR, `${rest}.md`);
|
|
82749
82841
|
if (layout.agentDirs.has(head))
|
|
82750
|
-
return
|
|
82842
|
+
return path28.join(c.root, CANONICAL_AGENT_DIR, `${rest}.md`);
|
|
82751
82843
|
}
|
|
82752
|
-
return
|
|
82844
|
+
return path28.join(c.root, `${posix}.md`);
|
|
82753
82845
|
}
|
|
82754
82846
|
function readCandidatesToolDir(layout, c, conceptId) {
|
|
82755
82847
|
const posix = toPosix(conceptId);
|
|
82756
82848
|
if (posix === layout.instructionConceptId) {
|
|
82757
|
-
return [{ path:
|
|
82849
|
+
return [{ path: path28.join(c.root, layout.instructionFile), conceptId: posix }];
|
|
82758
82850
|
}
|
|
82759
82851
|
const segs = posix.split("/").filter((segment) => segment.length > 0);
|
|
82760
82852
|
const head = segs[0];
|
|
@@ -82762,10 +82854,10 @@ function readCandidatesToolDir(layout, c, conceptId) {
|
|
|
82762
82854
|
if (!head || !rest)
|
|
82763
82855
|
return [];
|
|
82764
82856
|
if (layout.skillDirs.has(head)) {
|
|
82765
|
-
return segs.length === 2 ? [{ path:
|
|
82857
|
+
return segs.length === 2 ? [{ path: path28.join(c.root, head, rest, SKILL_MANIFEST2), conceptId: posix }] : [];
|
|
82766
82858
|
}
|
|
82767
82859
|
if (layout.commandDirs.has(head) || layout.agentDirs.has(head)) {
|
|
82768
|
-
return [{ path:
|
|
82860
|
+
return [{ path: path28.join(c.root, head, `${rest}.md`), conceptId: posix }];
|
|
82769
82861
|
}
|
|
82770
82862
|
return [];
|
|
82771
82863
|
}
|
|
@@ -82877,12 +82969,12 @@ function dirExists(p) {
|
|
|
82877
82969
|
}
|
|
82878
82970
|
function claudeLooksLikeRoot(root) {
|
|
82879
82971
|
try {
|
|
82880
|
-
if (!fs19.existsSync(
|
|
82972
|
+
if (!fs19.existsSync(path29.join(root, "CLAUDE.md")))
|
|
82881
82973
|
return false;
|
|
82882
82974
|
} catch {
|
|
82883
82975
|
return false;
|
|
82884
82976
|
}
|
|
82885
|
-
return ["commands", "agents", "skills"].some((d) => dirExists(
|
|
82977
|
+
return ["commands", "agents", "skills"].some((d) => dirExists(path29.join(root, d)));
|
|
82886
82978
|
}
|
|
82887
82979
|
var claudeAdapter = makeToolDirAdapter(LAYOUT, claudeLooksLikeRoot);
|
|
82888
82980
|
|
|
@@ -82890,7 +82982,7 @@ var claudeAdapter = makeToolDirAdapter(LAYOUT, claudeLooksLikeRoot);
|
|
|
82890
82982
|
init_asset_placement();
|
|
82891
82983
|
init_common();
|
|
82892
82984
|
import fs20 from "fs";
|
|
82893
|
-
import
|
|
82985
|
+
import path30 from "path";
|
|
82894
82986
|
var COMPONENT_ID4 = "main";
|
|
82895
82987
|
var ENV_DIR = "env";
|
|
82896
82988
|
var SECRETS_DIR = "secrets";
|
|
@@ -82992,7 +83084,7 @@ var dotenvAdapter = {
|
|
|
82992
83084
|
const type = typeForStashDir(head);
|
|
82993
83085
|
if (type !== "env" && type !== "secret" || rest.length === 0)
|
|
82994
83086
|
return [];
|
|
82995
|
-
const primaries = assetPathCandidatesForName(type,
|
|
83087
|
+
const primaries = assetPathCandidatesForName(type, path30.join(c.root, head), rest);
|
|
82996
83088
|
const expanded = primaries.flatMap((primary) => type === "env" ? [primary, primary.replace(/\.env$/i, ".sensitive")] : [primary, `${primary}.sensitive`, `${primary}.lock`]);
|
|
82997
83089
|
return expanded.map((candidatePath) => ({ path: candidatePath, conceptId: posix }));
|
|
82998
83090
|
},
|
|
@@ -83004,10 +83096,10 @@ var dotenvAdapter = {
|
|
|
83004
83096
|
const rest = posix.slice(slash + 1);
|
|
83005
83097
|
const type = typeForStashDir(head);
|
|
83006
83098
|
if ((type === "env" || type === "secret") && rest.length > 0) {
|
|
83007
|
-
return assetPathForName(type,
|
|
83099
|
+
return assetPathForName(type, path30.join(c.root, head), rest);
|
|
83008
83100
|
}
|
|
83009
83101
|
}
|
|
83010
|
-
return
|
|
83102
|
+
return path30.join(c.root, posix);
|
|
83011
83103
|
},
|
|
83012
83104
|
directoryList() {
|
|
83013
83105
|
return [ENV_DIR, SECRETS_DIR];
|
|
@@ -83032,7 +83124,7 @@ var dotenvAdapter = {
|
|
|
83032
83124
|
init_frontmatter();
|
|
83033
83125
|
init_common();
|
|
83034
83126
|
init_recognition_util();
|
|
83035
|
-
import
|
|
83127
|
+
import path31 from "path";
|
|
83036
83128
|
var COMPONENT_ID5 = "main";
|
|
83037
83129
|
var DOCUMENT_EXTENSIONS = new Set([".md", ".markdown", ".txt", ".text"]);
|
|
83038
83130
|
function isReserved2(base3) {
|
|
@@ -83098,17 +83190,17 @@ var genericFilesAdapter = {
|
|
|
83098
83190
|
validate: validate6,
|
|
83099
83191
|
readCandidates(c, conceptId) {
|
|
83100
83192
|
const posix = toPosix(conceptId);
|
|
83101
|
-
const extension =
|
|
83193
|
+
const extension = path31.extname(posix).toLowerCase();
|
|
83102
83194
|
const documentCandidates = [...DOCUMENT_EXTENSIONS].map((candidateExtension) => ({
|
|
83103
|
-
path:
|
|
83195
|
+
path: path31.join(c.root, `${posix}${candidateExtension}`),
|
|
83104
83196
|
conceptId: posix
|
|
83105
83197
|
}));
|
|
83106
|
-
return DOCUMENT_EXTENSIONS.has(extension) ? documentCandidates : [{ path:
|
|
83198
|
+
return DOCUMENT_EXTENSIONS.has(extension) ? documentCandidates : [{ path: path31.join(c.root, posix), conceptId: posix }, ...documentCandidates];
|
|
83107
83199
|
},
|
|
83108
83200
|
placeNew(c, conceptId) {
|
|
83109
83201
|
const posix = toPosix(conceptId);
|
|
83110
|
-
const hasExt =
|
|
83111
|
-
return
|
|
83202
|
+
const hasExt = path31.extname(posix) !== "";
|
|
83203
|
+
return path31.join(c.root, hasExt ? posix : `${posix}.md`);
|
|
83112
83204
|
},
|
|
83113
83205
|
looksLikeRoot() {
|
|
83114
83206
|
return false;
|
|
@@ -83120,7 +83212,7 @@ init_dist();
|
|
|
83120
83212
|
init_frontmatter();
|
|
83121
83213
|
init_common();
|
|
83122
83214
|
import fs21 from "fs";
|
|
83123
|
-
import
|
|
83215
|
+
import path32 from "path";
|
|
83124
83216
|
var WIKI_COMPONENT_ID = "main";
|
|
83125
83217
|
var WIKI_SOURCE_TYPE = "wiki-source";
|
|
83126
83218
|
var DEFAULT_PAGE_KIND = "note";
|
|
@@ -83178,7 +83270,7 @@ function resolveXref(xref, bundleId) {
|
|
|
83178
83270
|
return target.length > 0 ? target : null;
|
|
83179
83271
|
}
|
|
83180
83272
|
function resolveBodyLinks(body, fileRelPath) {
|
|
83181
|
-
const dir =
|
|
83273
|
+
const dir = path32.posix.dirname(toPosix(fileRelPath));
|
|
83182
83274
|
const linkRe = /\[[^\]]*\]\(([^)]+)\)/g;
|
|
83183
83275
|
const out = [];
|
|
83184
83276
|
const seen = new Set;
|
|
@@ -83204,10 +83296,10 @@ function resolveBodyLinks(body, fileRelPath) {
|
|
|
83204
83296
|
continue;
|
|
83205
83297
|
let resolved;
|
|
83206
83298
|
if (target.startsWith("/")) {
|
|
83207
|
-
resolved =
|
|
83299
|
+
resolved = path32.posix.normalize(target.slice(1));
|
|
83208
83300
|
} else {
|
|
83209
83301
|
const base3 = dir === "." ? "" : dir;
|
|
83210
|
-
resolved =
|
|
83302
|
+
resolved = path32.posix.normalize(path32.posix.join(base3, target));
|
|
83211
83303
|
}
|
|
83212
83304
|
if (resolved.startsWith("../") || resolved === ".." || resolved.startsWith("/"))
|
|
83213
83305
|
continue;
|
|
@@ -83389,19 +83481,19 @@ var llmWikiAdapter = {
|
|
|
83389
83481
|
validate: validate7,
|
|
83390
83482
|
readCandidates(c, conceptId) {
|
|
83391
83483
|
const canonical = toPosix(conceptId).replace(/\.md$/i, "");
|
|
83392
|
-
return [{ path:
|
|
83484
|
+
return [{ path: path32.join(c.root, `${canonical}.md`), conceptId: canonical }];
|
|
83393
83485
|
},
|
|
83394
83486
|
placeNew(c, conceptId) {
|
|
83395
|
-
return
|
|
83487
|
+
return path32.join(c.root, `${conceptId}.md`);
|
|
83396
83488
|
},
|
|
83397
83489
|
directoryList(_c) {
|
|
83398
83490
|
return ["."];
|
|
83399
83491
|
},
|
|
83400
83492
|
looksLikeRoot(root) {
|
|
83401
83493
|
try {
|
|
83402
|
-
if (!fs21.existsSync(
|
|
83494
|
+
if (!fs21.existsSync(path32.join(root, "schema.md")))
|
|
83403
83495
|
return false;
|
|
83404
|
-
return fs21.statSync(
|
|
83496
|
+
return fs21.statSync(path32.join(root, PAGES_SUBDIR)).isDirectory();
|
|
83405
83497
|
} catch {
|
|
83406
83498
|
return false;
|
|
83407
83499
|
}
|
|
@@ -83412,7 +83504,7 @@ var llmWikiAdapter = {
|
|
|
83412
83504
|
init_frontmatter();
|
|
83413
83505
|
init_common();
|
|
83414
83506
|
import fs22 from "fs";
|
|
83415
|
-
import
|
|
83507
|
+
import path33 from "path";
|
|
83416
83508
|
var CONSUMED_FRONTMATTER_KEYS = [
|
|
83417
83509
|
"type",
|
|
83418
83510
|
"title",
|
|
@@ -83484,7 +83576,7 @@ function isReservedFileName2(name) {
|
|
|
83484
83576
|
return RESERVED_FILES.has(name.toLowerCase());
|
|
83485
83577
|
}
|
|
83486
83578
|
function resolveOkfLinks(body, fileRelPath) {
|
|
83487
|
-
const dir =
|
|
83579
|
+
const dir = path33.posix.dirname(toPosix(fileRelPath));
|
|
83488
83580
|
const definitions = new Map;
|
|
83489
83581
|
for (const match of body.matchAll(/^\s*\[([^\]]+)\]:\s*(\S+)/gm)) {
|
|
83490
83582
|
definitions.set(match[1].trim().toLowerCase(), match[2]);
|
|
@@ -83522,10 +83614,10 @@ function resolveOkfLinks(body, fileRelPath) {
|
|
|
83522
83614
|
continue;
|
|
83523
83615
|
let resolved;
|
|
83524
83616
|
if (target.startsWith("/")) {
|
|
83525
|
-
resolved =
|
|
83617
|
+
resolved = path33.posix.normalize(target.slice(1));
|
|
83526
83618
|
} else {
|
|
83527
83619
|
const base3 = dir === "." ? "" : dir;
|
|
83528
|
-
resolved =
|
|
83620
|
+
resolved = path33.posix.normalize(path33.posix.join(base3, target));
|
|
83529
83621
|
}
|
|
83530
83622
|
if (resolved.startsWith("../") || resolved === ".." || resolved.startsWith("/"))
|
|
83531
83623
|
continue;
|
|
@@ -83653,13 +83745,13 @@ var okfAdapter = {
|
|
|
83653
83745
|
validate: validate8,
|
|
83654
83746
|
readCandidates(c, conceptId) {
|
|
83655
83747
|
const canonical = conceptId.replace(/\\/g, "/").replace(/\.md$/i, "");
|
|
83656
|
-
return [{ path:
|
|
83748
|
+
return [{ path: path33.join(c.root, `${canonical}.md`), conceptId: canonical }];
|
|
83657
83749
|
},
|
|
83658
83750
|
directoryList(_c) {
|
|
83659
83751
|
return ["."];
|
|
83660
83752
|
},
|
|
83661
83753
|
looksLikeRoot(root) {
|
|
83662
|
-
if (fs22.existsSync(
|
|
83754
|
+
if (fs22.existsSync(path33.join(root, "index.md")))
|
|
83663
83755
|
return true;
|
|
83664
83756
|
const stack = [root];
|
|
83665
83757
|
while (stack.length > 0) {
|
|
@@ -83675,7 +83767,7 @@ var okfAdapter = {
|
|
|
83675
83767
|
for (const entry of entries) {
|
|
83676
83768
|
if (entry.isSymbolicLink() || entry.name === ".git")
|
|
83677
83769
|
continue;
|
|
83678
|
-
const absolute =
|
|
83770
|
+
const absolute = path33.join(current, entry.name);
|
|
83679
83771
|
if (entry.isDirectory()) {
|
|
83680
83772
|
stack.push(absolute);
|
|
83681
83773
|
continue;
|
|
@@ -83693,7 +83785,7 @@ var okfAdapter = {
|
|
|
83693
83785
|
|
|
83694
83786
|
// src/core/adapter/adapters/opencode-adapter.ts
|
|
83695
83787
|
import fs23 from "fs";
|
|
83696
|
-
import
|
|
83788
|
+
import path34 from "path";
|
|
83697
83789
|
var LAYOUT2 = {
|
|
83698
83790
|
adapterId: "opencode",
|
|
83699
83791
|
componentId: ".opencode",
|
|
@@ -83720,11 +83812,11 @@ function dirExists2(p) {
|
|
|
83720
83812
|
}
|
|
83721
83813
|
}
|
|
83722
83814
|
function opencodeLooksLikeRoot(root) {
|
|
83723
|
-
if (CONFIG_FILES.some((f) => fileExists(
|
|
83815
|
+
if (CONFIG_FILES.some((f) => fileExists(path34.join(root, f))))
|
|
83724
83816
|
return true;
|
|
83725
|
-
if (!fileExists(
|
|
83817
|
+
if (!fileExists(path34.join(root, "AGENTS.md")))
|
|
83726
83818
|
return false;
|
|
83727
|
-
return TOOL_DIRS.some((d) => dirExists2(
|
|
83819
|
+
return TOOL_DIRS.some((d) => dirExists2(path34.join(root, d)));
|
|
83728
83820
|
}
|
|
83729
83821
|
var opencodeAdapter = makeToolDirAdapter(LAYOUT2, opencodeLooksLikeRoot);
|
|
83730
83822
|
|
|
@@ -83733,7 +83825,7 @@ init_dist();
|
|
|
83733
83825
|
init_frontmatter();
|
|
83734
83826
|
init_common();
|
|
83735
83827
|
import fs24 from "fs";
|
|
83736
|
-
import
|
|
83828
|
+
import path35 from "path";
|
|
83737
83829
|
var COMPONENT_ID6 = "main";
|
|
83738
83830
|
var PAGES_PREFIX = "stash/knowledge/";
|
|
83739
83831
|
var MANIFEST_FILE = "manifest.json";
|
|
@@ -83821,12 +83913,12 @@ var websiteSnapshotAdapter = {
|
|
|
83821
83913
|
validate: validate9,
|
|
83822
83914
|
readCandidates(c, conceptId) {
|
|
83823
83915
|
const canonical = toPosix(conceptId).replace(/\.md$/i, "");
|
|
83824
|
-
return [{ path:
|
|
83916
|
+
return [{ path: path35.join(c.root, PAGES_PREFIX, `${canonical}.md`), conceptId: canonical }];
|
|
83825
83917
|
},
|
|
83826
83918
|
looksLikeRoot(root) {
|
|
83827
83919
|
let raw;
|
|
83828
83920
|
try {
|
|
83829
|
-
raw = fs24.readFileSync(
|
|
83921
|
+
raw = fs24.readFileSync(path35.join(root, MANIFEST_FILE), "utf8");
|
|
83830
83922
|
} catch {
|
|
83831
83923
|
return false;
|
|
83832
83924
|
}
|
|
@@ -83939,7 +84031,7 @@ function isSourceWriteActivated(source) {
|
|
|
83939
84031
|
|
|
83940
84032
|
// src/core/adapter/detect-adapter.ts
|
|
83941
84033
|
import fs25 from "fs";
|
|
83942
|
-
import
|
|
84034
|
+
import path36 from "path";
|
|
83943
84035
|
var SHADOWABLE_ADAPTER_IDS = new Set(["agent-skills", "claude", "opencode"]);
|
|
83944
84036
|
function hasExtraAkmContent(root, winnerId) {
|
|
83945
84037
|
const akm = adapterForId("akm");
|
|
@@ -83961,13 +84053,13 @@ function hasExtraAkmContent(root, winnerId) {
|
|
|
83961
84053
|
continue;
|
|
83962
84054
|
if (winnerId === "agent-skills") {
|
|
83963
84055
|
try {
|
|
83964
|
-
if (fs25.statSync(
|
|
84056
|
+
if (fs25.statSync(path36.join(root, entry.name, "SKILL.md")).isFile())
|
|
83965
84057
|
continue;
|
|
83966
84058
|
} catch {}
|
|
83967
84059
|
}
|
|
83968
84060
|
let children;
|
|
83969
84061
|
try {
|
|
83970
|
-
children = fs25.readdirSync(
|
|
84062
|
+
children = fs25.readdirSync(path36.join(root, entry.name), { withFileTypes: true });
|
|
83971
84063
|
} catch {
|
|
83972
84064
|
continue;
|
|
83973
84065
|
}
|
|
@@ -83992,48 +84084,7 @@ function detectAdapterId(root, fallback = "akm") {
|
|
|
83992
84084
|
|
|
83993
84085
|
// src/indexer/installations.ts
|
|
83994
84086
|
init_asset_placement();
|
|
83995
|
-
|
|
83996
|
-
// src/core/bundle-id.ts
|
|
83997
|
-
init_asset_ref();
|
|
83998
|
-
import crypto5 from "crypto";
|
|
83999
|
-
import path36 from "path";
|
|
84000
|
-
function slugForPath(sourcePath) {
|
|
84001
|
-
const resolved = path36.resolve(sourcePath);
|
|
84002
|
-
const base3 = path36.basename(resolved).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
84003
|
-
if (base3.length > 0)
|
|
84004
|
-
return base3;
|
|
84005
|
-
return `bundle-${shortHash(resolved)}`;
|
|
84006
|
-
}
|
|
84007
|
-
function deriveBundleId(registryId, sourcePath, usedIds) {
|
|
84008
|
-
const preferred = registryId && registryId.length > 0 && isBundleSlug(registryId) ? registryId : slugForPath(sourcePath);
|
|
84009
|
-
const id = ensureUniqueId(preferred, sourcePath, usedIds);
|
|
84010
|
-
usedIds.add(id);
|
|
84011
|
-
return id;
|
|
84012
|
-
}
|
|
84013
|
-
function deriveBundleIds(sources) {
|
|
84014
|
-
const usedIds = new Set;
|
|
84015
|
-
const reservedIds = new Set(sources.flatMap((source) => source.registryId && isBundleSlug(source.registryId) ? [source.registryId] : []));
|
|
84016
|
-
return sources.map((source) => {
|
|
84017
|
-
const id = source.registryId && isBundleSlug(source.registryId) ? deriveBundleId(source.registryId, source.path, usedIds) : deriveBundleId(undefined, source.path, new Set([...usedIds, ...reservedIds]));
|
|
84018
|
-
usedIds.add(id);
|
|
84019
|
-
return id;
|
|
84020
|
-
});
|
|
84021
|
-
}
|
|
84022
|
-
function ensureUniqueId(preferred, sourcePath, used) {
|
|
84023
|
-
if (!used.has(preferred))
|
|
84024
|
-
return preferred;
|
|
84025
|
-
const suffixed = `${preferred}-${shortHash(path36.resolve(sourcePath))}`;
|
|
84026
|
-
if (!used.has(suffixed))
|
|
84027
|
-
return suffixed;
|
|
84028
|
-
let n = 2;
|
|
84029
|
-
while (used.has(`${suffixed}-${n}`))
|
|
84030
|
-
n++;
|
|
84031
|
-
return `${suffixed}-${n}`;
|
|
84032
|
-
}
|
|
84033
|
-
function shortHash(input) {
|
|
84034
|
-
return crypto5.createHash("sha256").update(input).digest("hex").slice(0, 8);
|
|
84035
|
-
}
|
|
84036
|
-
// src/indexer/installations.ts
|
|
84087
|
+
init_bundle_id();
|
|
84037
84088
|
var FALLBACK_ADAPTER_ID = "akm";
|
|
84038
84089
|
function deriveInstallations(sources) {
|
|
84039
84090
|
const ids = deriveBundleIds(sources);
|
|
@@ -84072,6 +84123,7 @@ function deriveEntryProvenance(bundle, type, name, adapterConceptId) {
|
|
|
84072
84123
|
// src/indexer/search/search-source.ts
|
|
84073
84124
|
init_common();
|
|
84074
84125
|
import path49 from "path";
|
|
84126
|
+
init_paths();
|
|
84075
84127
|
|
|
84076
84128
|
// src/core/write-source.ts
|
|
84077
84129
|
import fs36 from "fs";
|
|
@@ -87042,6 +87094,7 @@ function buildGithubTargetAliases(canonicalUrl) {
|
|
|
87042
87094
|
// src/core/write-source.ts
|
|
87043
87095
|
init_asset_placement();
|
|
87044
87096
|
init_resolve_ref();
|
|
87097
|
+
init_bundle_id();
|
|
87045
87098
|
init_common();
|
|
87046
87099
|
init_errors();
|
|
87047
87100
|
init_warn();
|
|
@@ -92252,14 +92305,14 @@ function resolveSourceEntries(overrideStashDir, existingConfig) {
|
|
|
92252
92305
|
const component = bundleComponentConfig(config.bundles?.[entry.name ?? ""]);
|
|
92253
92306
|
const contentRoot = resolveEntryContentDir(entry);
|
|
92254
92307
|
if (contentRoot == null) {
|
|
92255
|
-
const unresolvedPath = path49.join(implicitStashDir ?? process.cwd(),
|
|
92308
|
+
const unresolvedPath = path49.join(getUnresolvedSourcesDir(implicitStashDir ?? process.cwd()), entry.name ?? entry.type);
|
|
92256
92309
|
addSource(unresolvedPath, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter, true);
|
|
92257
92310
|
continue;
|
|
92258
92311
|
}
|
|
92259
92312
|
const dir = path49.resolve(contentRoot, component?.root ?? ".");
|
|
92260
92313
|
if (!isWithin(dir, contentRoot)) {
|
|
92261
92314
|
warn(`Warning: component root "${component?.root}" escapes bundle "${entry.name}"; skipping source.`);
|
|
92262
|
-
const unresolvedPath = path49.join(contentRoot,
|
|
92315
|
+
const unresolvedPath = path49.join(getUnresolvedSourcesDir(contentRoot), entry.name ?? entry.type);
|
|
92263
92316
|
addSource(unresolvedPath, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter, true);
|
|
92264
92317
|
continue;
|
|
92265
92318
|
}
|
|
@@ -95429,31 +95482,178 @@ async function recoverStaleTxns(stashDir) {
|
|
|
95429
95482
|
return recovered.map(journalToEntry);
|
|
95430
95483
|
}
|
|
95431
95484
|
|
|
95485
|
+
// scripts/akm-migrate/migrate/writer-relocation.ts
|
|
95486
|
+
import fs48 from "fs";
|
|
95487
|
+
import path61 from "path";
|
|
95488
|
+
init_paths();
|
|
95489
|
+
function relocationSpecs(stashDir) {
|
|
95490
|
+
return [
|
|
95491
|
+
{ key: "distillRejected", oldRelative: "distill-rejected", newDir: getDistillRejectedDir(stashDir) },
|
|
95492
|
+
{ key: "evalCases", oldRelative: "eval-cases", newDir: getEvalCasesDir(stashDir) },
|
|
95493
|
+
{
|
|
95494
|
+
key: "measurementVerdicts",
|
|
95495
|
+
oldRelative: ["measurement", "verdicts"],
|
|
95496
|
+
newDir: getMeasurementVerdictsDir(stashDir)
|
|
95497
|
+
}
|
|
95498
|
+
];
|
|
95499
|
+
}
|
|
95500
|
+
var LOCK_NAMES = ["improve.lock", "consolidate.lock", "reflect-distill.lock", "triage.lock"];
|
|
95501
|
+
function mutexSiblingName(lockName) {
|
|
95502
|
+
return `.${lockName}.operations.sensitive`;
|
|
95503
|
+
}
|
|
95504
|
+
function fileCountIfExists(dir) {
|
|
95505
|
+
let entries;
|
|
95506
|
+
try {
|
|
95507
|
+
entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
95508
|
+
} catch {
|
|
95509
|
+
return;
|
|
95510
|
+
}
|
|
95511
|
+
return entries.filter((entry) => entry.isFile()).length;
|
|
95512
|
+
}
|
|
95513
|
+
function statFileIfExists(filePath) {
|
|
95514
|
+
try {
|
|
95515
|
+
const stat = fs48.statSync(filePath);
|
|
95516
|
+
return stat.isFile() ? stat : undefined;
|
|
95517
|
+
} catch {
|
|
95518
|
+
return;
|
|
95519
|
+
}
|
|
95520
|
+
}
|
|
95521
|
+
function classifyLockArtifacts(akmDir) {
|
|
95522
|
+
const removable = [];
|
|
95523
|
+
const skipped = [];
|
|
95524
|
+
for (const lockName of LOCK_NAMES) {
|
|
95525
|
+
const lockPath = path61.join(akmDir, lockName);
|
|
95526
|
+
const mutexPath = path61.join(akmDir, mutexSiblingName(lockName));
|
|
95527
|
+
const lockStat = statFileIfExists(lockPath);
|
|
95528
|
+
const mutexStat = statFileIfExists(mutexPath);
|
|
95529
|
+
if (!lockStat) {
|
|
95530
|
+
if (mutexStat)
|
|
95531
|
+
removable.push({ path: mutexPath, sizeBytes: mutexStat.size });
|
|
95532
|
+
continue;
|
|
95533
|
+
}
|
|
95534
|
+
const probe = probeLock(lockPath);
|
|
95535
|
+
if (probe.state === "held") {
|
|
95536
|
+
skipped.push({ path: lockPath, reason: "held", holderPid: probe.holderPid });
|
|
95537
|
+
continue;
|
|
95538
|
+
}
|
|
95539
|
+
if (probe.state === "inaccessible") {
|
|
95540
|
+
skipped.push({ path: lockPath, reason: "inaccessible" });
|
|
95541
|
+
continue;
|
|
95542
|
+
}
|
|
95543
|
+
if (probe.state === "absent")
|
|
95544
|
+
continue;
|
|
95545
|
+
removable.push({ path: lockPath, sizeBytes: lockStat.size });
|
|
95546
|
+
if (mutexStat)
|
|
95547
|
+
removable.push({ path: mutexPath, sizeBytes: mutexStat.size });
|
|
95548
|
+
}
|
|
95549
|
+
return { removable, skipped };
|
|
95550
|
+
}
|
|
95551
|
+
function findWriterRelocationEntries(stashDir) {
|
|
95552
|
+
const akmDir = path61.join(stashDir, ".akm");
|
|
95553
|
+
const directories = [];
|
|
95554
|
+
for (const spec of relocationSpecs(stashDir)) {
|
|
95555
|
+
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95556
|
+
const oldPath = path61.join(akmDir, ...relativeParts);
|
|
95557
|
+
const fileCount = fileCountIfExists(oldPath);
|
|
95558
|
+
if (fileCount === undefined || fileCount === 0)
|
|
95559
|
+
continue;
|
|
95560
|
+
directories.push({ key: spec.key, oldPath, newPath: spec.newDir, fileCount });
|
|
95561
|
+
}
|
|
95562
|
+
const { removable, skipped } = classifyLockArtifacts(akmDir);
|
|
95563
|
+
return { directories, lockArtifacts: removable, skippedLocks: skipped };
|
|
95564
|
+
}
|
|
95565
|
+
function moveFile(oldFilePath, newFilePath) {
|
|
95566
|
+
try {
|
|
95567
|
+
fs48.renameSync(oldFilePath, newFilePath);
|
|
95568
|
+
} catch (error2) {
|
|
95569
|
+
if (error2.code !== "EXDEV")
|
|
95570
|
+
throw error2;
|
|
95571
|
+
fs48.copyFileSync(oldFilePath, newFilePath);
|
|
95572
|
+
fs48.rmSync(oldFilePath, { force: true });
|
|
95573
|
+
}
|
|
95574
|
+
}
|
|
95575
|
+
function moveDirectoryContents(entry) {
|
|
95576
|
+
const errors3 = [];
|
|
95577
|
+
let moved = 0;
|
|
95578
|
+
fs48.mkdirSync(entry.newPath, { recursive: true });
|
|
95579
|
+
let names;
|
|
95580
|
+
try {
|
|
95581
|
+
names = fs48.readdirSync(entry.oldPath).sort();
|
|
95582
|
+
} catch {
|
|
95583
|
+
return { key: entry.key, oldPath: entry.oldPath, newPath: entry.newPath, moved: 0, errors: [] };
|
|
95584
|
+
}
|
|
95585
|
+
for (const name of names) {
|
|
95586
|
+
const oldFilePath = path61.join(entry.oldPath, name);
|
|
95587
|
+
const newFilePath = path61.join(entry.newPath, name);
|
|
95588
|
+
let oldStat;
|
|
95589
|
+
try {
|
|
95590
|
+
oldStat = fs48.lstatSync(oldFilePath);
|
|
95591
|
+
} catch {
|
|
95592
|
+
continue;
|
|
95593
|
+
}
|
|
95594
|
+
if (!oldStat.isFile())
|
|
95595
|
+
continue;
|
|
95596
|
+
if (fs48.existsSync(newFilePath))
|
|
95597
|
+
continue;
|
|
95598
|
+
try {
|
|
95599
|
+
moveFile(oldFilePath, newFilePath);
|
|
95600
|
+
moved += 1;
|
|
95601
|
+
} catch (error2) {
|
|
95602
|
+
errors3.push(`${name}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
95603
|
+
}
|
|
95604
|
+
}
|
|
95605
|
+
return { key: entry.key, oldPath: entry.oldPath, newPath: entry.newPath, moved, errors: errors3 };
|
|
95606
|
+
}
|
|
95607
|
+
function removeIfEmptyDir(dir) {
|
|
95608
|
+
try {
|
|
95609
|
+
if (fs48.readdirSync(dir).length === 0)
|
|
95610
|
+
fs48.rmdirSync(dir);
|
|
95611
|
+
} catch {}
|
|
95612
|
+
}
|
|
95613
|
+
function removeLockArtifact(entry) {
|
|
95614
|
+
try {
|
|
95615
|
+
fs48.rmSync(entry.path, { force: true });
|
|
95616
|
+
return { path: entry.path, removed: true };
|
|
95617
|
+
} catch (error2) {
|
|
95618
|
+
return { path: entry.path, removed: false, error: error2 instanceof Error ? error2.message : String(error2) };
|
|
95619
|
+
}
|
|
95620
|
+
}
|
|
95621
|
+
function applyWriterRelocation(stashDir) {
|
|
95622
|
+
const { directories, lockArtifacts, skippedLocks } = findWriterRelocationEntries(stashDir);
|
|
95623
|
+
const directoryResults = directories.map(moveDirectoryContents);
|
|
95624
|
+
const lockResults = lockArtifacts.map(removeLockArtifact);
|
|
95625
|
+
for (const spec of relocationSpecs(stashDir)) {
|
|
95626
|
+
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95627
|
+
removeIfEmptyDir(path61.join(stashDir, ".akm", ...relativeParts));
|
|
95628
|
+
}
|
|
95629
|
+
return { directories: directoryResults, lockArtifacts: lockResults, skippedLocks };
|
|
95630
|
+
}
|
|
95631
|
+
|
|
95432
95632
|
// scripts/akm-migrate/task-migrate.ts
|
|
95433
95633
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
95434
|
-
import
|
|
95634
|
+
import fs53 from "fs";
|
|
95435
95635
|
import os5 from "os";
|
|
95436
|
-
import
|
|
95636
|
+
import path64 from "path";
|
|
95437
95637
|
init_errors();
|
|
95438
95638
|
init_paths();
|
|
95439
95639
|
|
|
95440
95640
|
// scripts/akm-migrate/migrate/task-files-to-v3.ts
|
|
95441
95641
|
init_errors();
|
|
95442
95642
|
import crypto6 from "crypto";
|
|
95443
|
-
import
|
|
95444
|
-
import
|
|
95643
|
+
import fs50 from "fs";
|
|
95644
|
+
import path62 from "path";
|
|
95445
95645
|
|
|
95446
95646
|
// scripts/akm-migrate/migrate/durable-fs.ts
|
|
95447
|
-
import
|
|
95647
|
+
import fs49 from "fs";
|
|
95448
95648
|
function fsyncDirectoryPortable(directory) {
|
|
95449
95649
|
if (process.platform === "win32")
|
|
95450
95650
|
return;
|
|
95451
95651
|
try {
|
|
95452
|
-
const fd =
|
|
95652
|
+
const fd = fs49.openSync(directory, "r");
|
|
95453
95653
|
try {
|
|
95454
|
-
|
|
95654
|
+
fs49.fsyncSync(fd);
|
|
95455
95655
|
} finally {
|
|
95456
|
-
|
|
95656
|
+
fs49.closeSync(fd);
|
|
95457
95657
|
}
|
|
95458
95658
|
} catch (cause) {
|
|
95459
95659
|
const code = cause.code;
|
|
@@ -95467,25 +95667,25 @@ function migrationError(detail) {
|
|
|
95467
95667
|
return new ConfigError(`Task migration to v3 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
95468
95668
|
}
|
|
95469
95669
|
function contained2(root2, candidate) {
|
|
95470
|
-
const relative =
|
|
95471
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
95670
|
+
const relative = path62.relative(root2, candidate);
|
|
95671
|
+
return relative === "" || !relative.startsWith("..") && !path62.isAbsolute(relative);
|
|
95472
95672
|
}
|
|
95473
95673
|
function realDirectory(filePath) {
|
|
95474
|
-
const stat =
|
|
95674
|
+
const stat = fs50.lstatSync(filePath);
|
|
95475
95675
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
95476
95676
|
throw migrationError(`${filePath} must be a real directory.`);
|
|
95477
|
-
return
|
|
95677
|
+
return fs50.realpathSync(filePath);
|
|
95478
95678
|
}
|
|
95479
95679
|
function snapshot(filePath) {
|
|
95480
|
-
const stat =
|
|
95680
|
+
const stat = fs50.lstatSync(filePath);
|
|
95481
95681
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
95482
95682
|
throw migrationError(`${filePath} must be a real file.`);
|
|
95483
|
-
const bytes =
|
|
95683
|
+
const bytes = fs50.readFileSync(filePath);
|
|
95484
95684
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
95485
95685
|
}
|
|
95486
95686
|
function writable(filePath) {
|
|
95487
95687
|
try {
|
|
95488
|
-
|
|
95688
|
+
fs50.accessSync(filePath, fs50.constants.W_OK);
|
|
95489
95689
|
return true;
|
|
95490
95690
|
} catch {
|
|
95491
95691
|
return false;
|
|
@@ -95498,12 +95698,12 @@ function walkTasks(root2, tasksDir, out) {
|
|
|
95498
95698
|
throw migrationError(`${root2.root} resolves outside bundle ${root2.bundleId}.`);
|
|
95499
95699
|
}
|
|
95500
95700
|
const visit2 = (directory) => {
|
|
95501
|
-
const physicalDirectory =
|
|
95701
|
+
const physicalDirectory = fs50.realpathSync(directory);
|
|
95502
95702
|
if (!contained2(physicalRoot, physicalDirectory)) {
|
|
95503
95703
|
throw migrationError(`${directory} resolves outside bundle ${root2.bundleId}.`);
|
|
95504
95704
|
}
|
|
95505
|
-
for (const entry of
|
|
95506
|
-
const candidate =
|
|
95705
|
+
for (const entry of fs50.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
95706
|
+
const candidate = path62.join(directory, entry.name);
|
|
95507
95707
|
if (entry.isSymbolicLink())
|
|
95508
95708
|
throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
|
|
95509
95709
|
if (entry.isDirectory()) {
|
|
@@ -95513,7 +95713,7 @@ function walkTasks(root2, tasksDir, out) {
|
|
|
95513
95713
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
95514
95714
|
continue;
|
|
95515
95715
|
const current = snapshot(candidate);
|
|
95516
|
-
const parent =
|
|
95716
|
+
const parent = path62.dirname(candidate);
|
|
95517
95717
|
out.push({
|
|
95518
95718
|
filePath: candidate,
|
|
95519
95719
|
bytes: current.bytes,
|
|
@@ -95529,9 +95729,9 @@ function walkTasks(root2, tasksDir, out) {
|
|
|
95529
95729
|
function inspectTaskToV3Files(roots) {
|
|
95530
95730
|
const files = [];
|
|
95531
95731
|
for (const root2 of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
95532
|
-
const tasksDir = root2.layout === "akm-task" ? root2.root :
|
|
95732
|
+
const tasksDir = root2.layout === "akm-task" ? root2.root : path62.join(root2.root, "tasks");
|
|
95533
95733
|
try {
|
|
95534
|
-
const stat =
|
|
95734
|
+
const stat = fs50.lstatSync(tasksDir);
|
|
95535
95735
|
if (stat.isSymbolicLink())
|
|
95536
95736
|
throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
95537
95737
|
if (!stat.isDirectory())
|
|
@@ -95546,33 +95746,33 @@ function inspectTaskToV3Files(roots) {
|
|
|
95546
95746
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
95547
95747
|
}
|
|
95548
95748
|
function hashPath(filePath) {
|
|
95549
|
-
return crypto6.createHash("sha256").update(
|
|
95749
|
+
return crypto6.createHash("sha256").update(path62.resolve(filePath)).digest("hex").slice(0, 16);
|
|
95550
95750
|
}
|
|
95551
95751
|
function taskMigrationBackupPath(backupRoot, filePath) {
|
|
95552
|
-
return
|
|
95752
|
+
return path62.join(backupRoot, "files", `${hashPath(filePath)}-${path62.basename(filePath)}`);
|
|
95553
95753
|
}
|
|
95554
95754
|
function writeDurable(filePath, bytes, mode, exclusive = false) {
|
|
95555
|
-
|
|
95755
|
+
fs50.mkdirSync(path62.dirname(filePath), { recursive: true });
|
|
95556
95756
|
const flags = exclusive ? "wx" : "w";
|
|
95557
|
-
const fd =
|
|
95757
|
+
const fd = fs50.openSync(filePath, flags, mode);
|
|
95558
95758
|
try {
|
|
95559
|
-
|
|
95560
|
-
|
|
95759
|
+
fs50.writeFileSync(fd, bytes);
|
|
95760
|
+
fs50.fsyncSync(fd);
|
|
95561
95761
|
} finally {
|
|
95562
|
-
|
|
95762
|
+
fs50.closeSync(fd);
|
|
95563
95763
|
}
|
|
95564
|
-
|
|
95565
|
-
fsyncDirectoryPortable(
|
|
95764
|
+
fs50.chmodSync(filePath, mode);
|
|
95765
|
+
fsyncDirectoryPortable(path62.dirname(filePath));
|
|
95566
95766
|
}
|
|
95567
95767
|
function replaceAtomically(filePath, bytes, mode) {
|
|
95568
|
-
const temporary =
|
|
95768
|
+
const temporary = path62.join(path62.dirname(filePath), `.${path62.basename(filePath)}.migrate-${crypto6.randomUUID()}`);
|
|
95569
95769
|
try {
|
|
95570
95770
|
writeDurable(temporary, bytes, mode, true);
|
|
95571
|
-
|
|
95572
|
-
fsyncDirectoryPortable(
|
|
95771
|
+
fs50.renameSync(temporary, filePath);
|
|
95772
|
+
fsyncDirectoryPortable(path62.dirname(filePath));
|
|
95573
95773
|
} finally {
|
|
95574
95774
|
try {
|
|
95575
|
-
|
|
95775
|
+
fs50.unlinkSync(temporary);
|
|
95576
95776
|
} catch (cause) {
|
|
95577
95777
|
if (cause.code !== "ENOENT")
|
|
95578
95778
|
throw cause;
|
|
@@ -95611,7 +95811,7 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
95611
95811
|
const current = snapshot(change.filePath);
|
|
95612
95812
|
if (!current.bytes.equals(change.after))
|
|
95613
95813
|
continue;
|
|
95614
|
-
replaceAtomically(change.filePath,
|
|
95814
|
+
replaceAtomically(change.filePath, fs50.readFileSync(taskMigrationBackupPath(options.backupRoot, change.filePath)), change.mode);
|
|
95615
95815
|
}
|
|
95616
95816
|
throw cause;
|
|
95617
95817
|
}
|
|
@@ -95621,31 +95821,31 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
95621
95821
|
// scripts/akm-migrate/migrate/task-files-to-v4.ts
|
|
95622
95822
|
init_errors();
|
|
95623
95823
|
import crypto7 from "crypto";
|
|
95624
|
-
import
|
|
95625
|
-
import
|
|
95824
|
+
import fs51 from "fs";
|
|
95825
|
+
import path63 from "path";
|
|
95626
95826
|
function migrationError2(detail) {
|
|
95627
95827
|
return new ConfigError(`Task migration to v4 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
95628
95828
|
}
|
|
95629
95829
|
function contained3(root2, candidate) {
|
|
95630
|
-
const relative =
|
|
95631
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
95830
|
+
const relative = path63.relative(root2, candidate);
|
|
95831
|
+
return relative === "" || !relative.startsWith("..") && !path63.isAbsolute(relative);
|
|
95632
95832
|
}
|
|
95633
95833
|
function realDirectory2(filePath) {
|
|
95634
|
-
const stat =
|
|
95834
|
+
const stat = fs51.lstatSync(filePath);
|
|
95635
95835
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
95636
95836
|
throw migrationError2(`${filePath} must be a real directory.`);
|
|
95637
|
-
return
|
|
95837
|
+
return fs51.realpathSync(filePath);
|
|
95638
95838
|
}
|
|
95639
95839
|
function snapshot2(filePath) {
|
|
95640
|
-
const stat =
|
|
95840
|
+
const stat = fs51.lstatSync(filePath);
|
|
95641
95841
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
95642
95842
|
throw migrationError2(`${filePath} must be a real file.`);
|
|
95643
|
-
const bytes =
|
|
95843
|
+
const bytes = fs51.readFileSync(filePath);
|
|
95644
95844
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
95645
95845
|
}
|
|
95646
95846
|
function writable2(filePath) {
|
|
95647
95847
|
try {
|
|
95648
|
-
|
|
95848
|
+
fs51.accessSync(filePath, fs51.constants.W_OK);
|
|
95649
95849
|
return true;
|
|
95650
95850
|
} catch {
|
|
95651
95851
|
return false;
|
|
@@ -95658,12 +95858,12 @@ function walkTasks2(root2, tasksDir, out) {
|
|
|
95658
95858
|
throw migrationError2(`${root2.root} resolves outside bundle ${root2.bundleId}.`);
|
|
95659
95859
|
}
|
|
95660
95860
|
const visit2 = (directory) => {
|
|
95661
|
-
const physicalDirectory =
|
|
95861
|
+
const physicalDirectory = fs51.realpathSync(directory);
|
|
95662
95862
|
if (!contained3(physicalRoot, physicalDirectory)) {
|
|
95663
95863
|
throw migrationError2(`${directory} resolves outside bundle ${root2.bundleId}.`);
|
|
95664
95864
|
}
|
|
95665
|
-
for (const entry of
|
|
95666
|
-
const candidate =
|
|
95865
|
+
for (const entry of fs51.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
95866
|
+
const candidate = path63.join(directory, entry.name);
|
|
95667
95867
|
if (entry.isSymbolicLink())
|
|
95668
95868
|
throw migrationError2(`task migration does not follow symbolic link ${candidate}.`);
|
|
95669
95869
|
if (entry.isDirectory()) {
|
|
@@ -95673,7 +95873,7 @@ function walkTasks2(root2, tasksDir, out) {
|
|
|
95673
95873
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
95674
95874
|
continue;
|
|
95675
95875
|
const current = snapshot2(candidate);
|
|
95676
|
-
const parent =
|
|
95876
|
+
const parent = path63.dirname(candidate);
|
|
95677
95877
|
out.push({
|
|
95678
95878
|
filePath: candidate,
|
|
95679
95879
|
bytes: current.bytes,
|
|
@@ -95689,9 +95889,9 @@ function walkTasks2(root2, tasksDir, out) {
|
|
|
95689
95889
|
function inspectTaskToV4Files(roots) {
|
|
95690
95890
|
const files = [];
|
|
95691
95891
|
for (const root2 of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
95692
|
-
const tasksDir = root2.layout === "akm-task" ? root2.root :
|
|
95892
|
+
const tasksDir = root2.layout === "akm-task" ? root2.root : path63.join(root2.root, "tasks");
|
|
95693
95893
|
try {
|
|
95694
|
-
const stat =
|
|
95894
|
+
const stat = fs51.lstatSync(tasksDir);
|
|
95695
95895
|
if (stat.isSymbolicLink())
|
|
95696
95896
|
throw migrationError2(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
95697
95897
|
if (!stat.isDirectory())
|
|
@@ -95706,33 +95906,33 @@ function inspectTaskToV4Files(roots) {
|
|
|
95706
95906
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
95707
95907
|
}
|
|
95708
95908
|
function hashPath2(filePath) {
|
|
95709
|
-
return crypto7.createHash("sha256").update(
|
|
95909
|
+
return crypto7.createHash("sha256").update(path63.resolve(filePath)).digest("hex").slice(0, 16);
|
|
95710
95910
|
}
|
|
95711
95911
|
function taskMigrationBackupPathV4(backupRoot, filePath) {
|
|
95712
|
-
return
|
|
95912
|
+
return path63.join(backupRoot, "files", `${hashPath2(filePath)}-${path63.basename(filePath)}`);
|
|
95713
95913
|
}
|
|
95714
95914
|
function writeDurable2(filePath, bytes, mode, exclusive = false) {
|
|
95715
|
-
|
|
95915
|
+
fs51.mkdirSync(path63.dirname(filePath), { recursive: true });
|
|
95716
95916
|
const flags = exclusive ? "wx" : "w";
|
|
95717
|
-
const fd =
|
|
95917
|
+
const fd = fs51.openSync(filePath, flags, mode);
|
|
95718
95918
|
try {
|
|
95719
|
-
|
|
95720
|
-
|
|
95919
|
+
fs51.writeFileSync(fd, bytes);
|
|
95920
|
+
fs51.fsyncSync(fd);
|
|
95721
95921
|
} finally {
|
|
95722
|
-
|
|
95922
|
+
fs51.closeSync(fd);
|
|
95723
95923
|
}
|
|
95724
|
-
|
|
95725
|
-
fsyncDirectoryPortable(
|
|
95924
|
+
fs51.chmodSync(filePath, mode);
|
|
95925
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
95726
95926
|
}
|
|
95727
95927
|
function replaceAtomically2(filePath, bytes, mode) {
|
|
95728
|
-
const temporary =
|
|
95928
|
+
const temporary = path63.join(path63.dirname(filePath), `.${path63.basename(filePath)}.migrate-${crypto7.randomUUID()}`);
|
|
95729
95929
|
try {
|
|
95730
95930
|
writeDurable2(temporary, bytes, mode, true);
|
|
95731
|
-
|
|
95732
|
-
fsyncDirectoryPortable(
|
|
95931
|
+
fs51.renameSync(temporary, filePath);
|
|
95932
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
95733
95933
|
} finally {
|
|
95734
95934
|
try {
|
|
95735
|
-
|
|
95935
|
+
fs51.unlinkSync(temporary);
|
|
95736
95936
|
} catch (cause) {
|
|
95737
95937
|
if (cause.code !== "ENOENT")
|
|
95738
95938
|
throw cause;
|
|
@@ -95771,7 +95971,7 @@ function applyTaskToV4MigrationPlan(plan, options) {
|
|
|
95771
95971
|
const current = snapshot2(change.filePath);
|
|
95772
95972
|
if (!current.bytes.equals(change.after))
|
|
95773
95973
|
continue;
|
|
95774
|
-
replaceAtomically2(change.filePath,
|
|
95974
|
+
replaceAtomically2(change.filePath, fs51.readFileSync(taskMigrationBackupPathV4(options.backupRoot, change.filePath)), change.mode);
|
|
95775
95975
|
}
|
|
95776
95976
|
throw cause;
|
|
95777
95977
|
}
|
|
@@ -95783,12 +95983,12 @@ function expandTilde(value) {
|
|
|
95783
95983
|
if (value === "~")
|
|
95784
95984
|
return os5.homedir();
|
|
95785
95985
|
if (value.startsWith("~/") || value.startsWith("~\\"))
|
|
95786
|
-
return
|
|
95986
|
+
return path64.join(os5.homedir(), value.slice(2));
|
|
95787
95987
|
return value;
|
|
95788
95988
|
}
|
|
95789
95989
|
function existingDirectory(target) {
|
|
95790
95990
|
try {
|
|
95791
|
-
return
|
|
95991
|
+
return fs53.statSync(target).isDirectory();
|
|
95792
95992
|
} catch (cause) {
|
|
95793
95993
|
if (cause.code === "ENOENT")
|
|
95794
95994
|
return false;
|
|
@@ -95809,21 +96009,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
|
|
|
95809
96009
|
const source = sources.get(bundleId);
|
|
95810
96010
|
if (!source)
|
|
95811
96011
|
continue;
|
|
95812
|
-
const configuredRoot = source.type === "filesystem" && source.path ?
|
|
96012
|
+
const configuredRoot = source.type === "filesystem" && source.path ? path64.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
|
|
95813
96013
|
if (!configuredRoot || !existingDirectory(configuredRoot))
|
|
95814
96014
|
continue;
|
|
95815
|
-
const bundleRoot =
|
|
96015
|
+
const bundleRoot = path64.resolve(configuredRoot);
|
|
95816
96016
|
const component = bundleComponentConfig(bundle);
|
|
95817
|
-
const componentRoot =
|
|
95818
|
-
const relative =
|
|
95819
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
96017
|
+
const componentRoot = path64.resolve(bundleRoot, component?.root ?? ".");
|
|
96018
|
+
const relative = path64.relative(bundleRoot, componentRoot);
|
|
96019
|
+
if (relative === ".." || relative.startsWith(`..${path64.sep}`) || path64.isAbsolute(relative)) {
|
|
95820
96020
|
throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
|
|
95821
96021
|
}
|
|
95822
96022
|
if (!existingDirectory(componentRoot))
|
|
95823
96023
|
continue;
|
|
95824
96024
|
const adapter = component?.adapter ?? detectAdapterId(componentRoot, "");
|
|
95825
96025
|
if (!component?.adapter && adapter === "") {
|
|
95826
|
-
const flatTasks =
|
|
96026
|
+
const flatTasks = fs53.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
|
|
95827
96027
|
if (flatTasks.length > 0) {
|
|
95828
96028
|
throw new ConfigError(`Task migration cannot classify top-level task file(s) ${flatTasks.join(", ")} in bundle ${bundleId}; configure adapter "akm-task" or move them under tasks/.`, "INVALID_CONFIG_FILE");
|
|
95829
96029
|
}
|
|
@@ -95895,8 +96095,8 @@ function applyTaskV3Migration() {
|
|
|
95895
96095
|
const before = inspectCurrentTaskPlan();
|
|
95896
96096
|
if (before.result.taskV3Migration.changed === 0)
|
|
95897
96097
|
return before.result;
|
|
95898
|
-
const backupRoot =
|
|
95899
|
-
const backupPath =
|
|
96098
|
+
const backupRoot = path64.join(getDataDir(), "backups", "task-v3");
|
|
96099
|
+
const backupPath = path64.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
95900
96100
|
const applied = applyTaskToV3MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
95901
96101
|
const after = inspectCurrentTaskPlan().result;
|
|
95902
96102
|
if (after.taskV3Migration.changed > 0) {
|
|
@@ -95952,8 +96152,8 @@ function applyTaskV4Migration() {
|
|
|
95952
96152
|
const before = inspectCurrentTaskV4Plan();
|
|
95953
96153
|
if (before.result.taskV4Migration.changed === 0)
|
|
95954
96154
|
return before.result;
|
|
95955
|
-
const backupRoot =
|
|
95956
|
-
const backupPath =
|
|
96155
|
+
const backupRoot = path64.join(getDataDir(), "backups", "task-v4");
|
|
96156
|
+
const backupPath = path64.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
95957
96157
|
const applied = applyTaskToV4MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
95958
96158
|
const after = inspectCurrentTaskV4Plan().result;
|
|
95959
96159
|
if (after.taskV4Migration.changed > 0) {
|
|
@@ -95981,6 +96181,22 @@ function stashDirIfConfigured() {
|
|
|
95981
96181
|
throw error2;
|
|
95982
96182
|
}
|
|
95983
96183
|
}
|
|
96184
|
+
function writerRelocationTargets(defaultStashDir) {
|
|
96185
|
+
const config = loadConfig();
|
|
96186
|
+
const seen = new Set;
|
|
96187
|
+
const targets = [];
|
|
96188
|
+
if (defaultStashDir !== undefined) {
|
|
96189
|
+
targets.push({ id: bundleKeyForContentRoot(config, defaultStashDir) ?? "default", dir: defaultStashDir });
|
|
96190
|
+
seen.add(defaultStashDir);
|
|
96191
|
+
}
|
|
96192
|
+
for (const { id, contentRoot } of bundleContentRoots(config)) {
|
|
96193
|
+
if (seen.has(contentRoot))
|
|
96194
|
+
continue;
|
|
96195
|
+
seen.add(contentRoot);
|
|
96196
|
+
targets.push({ id, dir: contentRoot });
|
|
96197
|
+
}
|
|
96198
|
+
return targets;
|
|
96199
|
+
}
|
|
95984
96200
|
async function runMigration(options) {
|
|
95985
96201
|
const { apply } = options;
|
|
95986
96202
|
const configPath = getConfigPath();
|
|
@@ -96001,10 +96217,15 @@ async function runMigration(options) {
|
|
|
96001
96217
|
const stashDir = stashDirIfConfigured();
|
|
96002
96218
|
const taskV3 = apply ? applyTaskV3Migration() : inspectMigrationPlan();
|
|
96003
96219
|
const taskV4 = apply ? applyTaskV4Migration() : inspectTaskV4MigrationStatus();
|
|
96004
|
-
const stashSections =
|
|
96005
|
-
|
|
96006
|
-
|
|
96007
|
-
|
|
96220
|
+
const stashSections = {};
|
|
96221
|
+
if (stashDir !== undefined) {
|
|
96222
|
+
stashSections.deadResidue = apply ? { removed: removeDeadResidue(stashDir) } : { pending: findDeadResidueEntries(stashDir) };
|
|
96223
|
+
stashSections.staleTxns = apply ? { recovered: await recoverStaleTxns(stashDir) } : { pending: findStaleTxnEntries(stashDir) };
|
|
96224
|
+
}
|
|
96225
|
+
const relocationTargets = writerRelocationTargets(stashDir);
|
|
96226
|
+
if (relocationTargets.length > 0) {
|
|
96227
|
+
stashSections.writerRelocation = apply ? { relocated: Object.fromEntries(relocationTargets.map(({ id, dir }) => [id, applyWriterRelocation(dir)])) } : { pending: Object.fromEntries(relocationTargets.map(({ id, dir }) => [id, findWriterRelocationEntries(dir)])) };
|
|
96228
|
+
}
|
|
96008
96229
|
const stateStatus = "pending" in stateMigrations && stateMigrations.pending.length > 0 ? "ready" : "current";
|
|
96009
96230
|
return {
|
|
96010
96231
|
schemaVersion: 1,
|