@agentv/core 4.32.0-next.1 → 4.33.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-N5EU446L.js → chunk-7QB53OPK.js} +1277 -265
- package/dist/chunk-7QB53OPK.js.map +1 -0
- package/dist/{chunk-5RQMJZDJ.js → chunk-EW5X2RGJ.js} +110 -50
- package/dist/chunk-EW5X2RGJ.js.map +1 -0
- package/dist/evaluation/validation/index.cjs +196 -87
- package/dist/evaluation/validation/index.cjs.map +1 -1
- package/dist/evaluation/validation/index.d.cts +3 -1
- package/dist/evaluation/validation/index.d.ts +3 -1
- package/dist/evaluation/validation/index.js +170 -75
- package/dist/evaluation/validation/index.js.map +1 -1
- package/dist/index.cjs +2346 -853
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1826 -62
- package/dist/index.d.ts +1826 -62
- package/dist/index.js +624 -197
- package/dist/index.js.map +1 -1
- package/dist/{ts-eval-loader-Z6IUSDNA.js → ts-eval-loader-EQJX3OLT.js} +3 -3
- package/package.json +2 -2
- package/dist/chunk-5RQMJZDJ.js.map +0 -1
- package/dist/chunk-N5EU446L.js.map +0 -1
- /package/dist/{ts-eval-loader-Z6IUSDNA.js.map → ts-eval-loader-EQJX3OLT.js.map} +0 -0
|
@@ -61,7 +61,9 @@ declare function validateTargetsFile(filePath: string): Promise<ValidationResult
|
|
|
61
61
|
/**
|
|
62
62
|
* Validate a config.yaml file for schema compliance and structural correctness.
|
|
63
63
|
*/
|
|
64
|
-
declare function validateConfigFile(filePath: string
|
|
64
|
+
declare function validateConfigFile(filePath: string, options?: {
|
|
65
|
+
scope?: 'project' | 'global';
|
|
66
|
+
}): Promise<ValidationResult>;
|
|
65
67
|
|
|
66
68
|
/**
|
|
67
69
|
* Validate that file references in eval file content exist.
|
|
@@ -61,7 +61,9 @@ declare function validateTargetsFile(filePath: string): Promise<ValidationResult
|
|
|
61
61
|
/**
|
|
62
62
|
* Validate a config.yaml file for schema compliance and structural correctness.
|
|
63
63
|
*/
|
|
64
|
-
declare function validateConfigFile(filePath: string
|
|
64
|
+
declare function validateConfigFile(filePath: string, options?: {
|
|
65
|
+
scope?: 'project' | 'global';
|
|
66
|
+
}): Promise<ValidationResult>;
|
|
65
67
|
|
|
66
68
|
/**
|
|
67
69
|
* Validate that file references in eval file content exist.
|
|
@@ -6,13 +6,14 @@ import {
|
|
|
6
6
|
buildSearchRoots,
|
|
7
7
|
findDeprecatedCamelCaseTargetWarnings,
|
|
8
8
|
findGitRoot,
|
|
9
|
+
getAgentvConfigDir,
|
|
9
10
|
interpolateEnv,
|
|
10
11
|
isGraderKind,
|
|
11
12
|
loadCasesFromDirectory,
|
|
12
13
|
loadCasesFromFile,
|
|
13
14
|
parseYamlValue,
|
|
14
15
|
resolveFileReference
|
|
15
|
-
} from "../../chunk-
|
|
16
|
+
} from "../../chunk-EW5X2RGJ.js";
|
|
16
17
|
|
|
17
18
|
// src/evaluation/validation/file-type.ts
|
|
18
19
|
import { readFile } from "node:fs/promises";
|
|
@@ -947,6 +948,9 @@ import path4 from "node:path";
|
|
|
947
948
|
function isObject3(value) {
|
|
948
949
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
949
950
|
}
|
|
951
|
+
function isNonEmptyString(value) {
|
|
952
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
953
|
+
}
|
|
950
954
|
var COMMON_SETTINGS = new Set(COMMON_TARGET_SETTINGS);
|
|
951
955
|
var RETRY_SETTINGS = /* @__PURE__ */ new Set([
|
|
952
956
|
"max_retries",
|
|
@@ -1015,6 +1019,7 @@ var GEMINI_SETTINGS = /* @__PURE__ */ new Set([
|
|
|
1015
1019
|
var CODEX_SETTINGS = /* @__PURE__ */ new Set([
|
|
1016
1020
|
...COMMON_SETTINGS,
|
|
1017
1021
|
"model",
|
|
1022
|
+
"model_reasoning_effort",
|
|
1018
1023
|
"executable",
|
|
1019
1024
|
"command",
|
|
1020
1025
|
"binary",
|
|
@@ -1024,8 +1029,7 @@ var CODEX_SETTINGS = /* @__PURE__ */ new Set([
|
|
|
1024
1029
|
"timeout_seconds",
|
|
1025
1030
|
"log_dir",
|
|
1026
1031
|
"log_directory",
|
|
1027
|
-
"
|
|
1028
|
-
"log_output_format",
|
|
1032
|
+
"stream_log",
|
|
1029
1033
|
"system_prompt"
|
|
1030
1034
|
]);
|
|
1031
1035
|
var COPILOT_SDK_SETTINGS = /* @__PURE__ */ new Set([
|
|
@@ -1150,6 +1154,26 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
1150
1154
|
"api_format",
|
|
1151
1155
|
"The 'api_format' field is no longer supported on Azure targets. AgentV always uses Azure's Responses API (`/openai/v1/responses`). If your deployment only exposes /chat/completions, use 'provider: openai' with a deployment-scoped 'base_url' instead."
|
|
1152
1156
|
]
|
|
1157
|
+
]),
|
|
1158
|
+
codex: /* @__PURE__ */ new Map([
|
|
1159
|
+
[
|
|
1160
|
+
"log_format",
|
|
1161
|
+
"The 'log_format' field is no longer supported on Codex targets. Use 'stream_log: raw' for per-event logs or 'stream_log: summary' for consolidated logs."
|
|
1162
|
+
],
|
|
1163
|
+
[
|
|
1164
|
+
"log_output_format",
|
|
1165
|
+
"The 'log_output_format' field is no longer supported on Codex targets. Use 'stream_log: raw' for per-event logs or 'stream_log: summary' for consolidated logs."
|
|
1166
|
+
]
|
|
1167
|
+
]),
|
|
1168
|
+
"codex-cli": /* @__PURE__ */ new Map([
|
|
1169
|
+
[
|
|
1170
|
+
"log_format",
|
|
1171
|
+
"The 'log_format' field is no longer supported on Codex targets. Use 'stream_log: raw' for per-event logs or 'stream_log: summary' for consolidated logs."
|
|
1172
|
+
],
|
|
1173
|
+
[
|
|
1174
|
+
"log_output_format",
|
|
1175
|
+
"The 'log_output_format' field is no longer supported on Codex targets. Use 'stream_log: raw' for per-event logs or 'stream_log: summary' for consolidated logs."
|
|
1176
|
+
]
|
|
1153
1177
|
])
|
|
1154
1178
|
};
|
|
1155
1179
|
const removedForProvider = removedPerProvider[provider];
|
|
@@ -1186,9 +1210,11 @@ async function validateTargetsFile(filePath) {
|
|
|
1186
1210
|
const errors = [];
|
|
1187
1211
|
const absolutePath = path4.resolve(filePath);
|
|
1188
1212
|
let parsed;
|
|
1213
|
+
let rawParsed;
|
|
1189
1214
|
try {
|
|
1190
1215
|
const content = await readFile4(absolutePath, "utf8");
|
|
1191
|
-
|
|
1216
|
+
rawParsed = parseYamlValue(content);
|
|
1217
|
+
parsed = interpolateEnv(rawParsed, process.env);
|
|
1192
1218
|
} catch (error) {
|
|
1193
1219
|
errors.push({
|
|
1194
1220
|
severity: "error",
|
|
@@ -1309,6 +1335,7 @@ async function validateTargetsFile(filePath) {
|
|
|
1309
1335
|
};
|
|
1310
1336
|
}
|
|
1311
1337
|
const targets = parsed.targets;
|
|
1338
|
+
const rawTargets = isObject3(rawParsed) && Array.isArray(rawParsed.targets) ? rawParsed.targets : [];
|
|
1312
1339
|
if (!Array.isArray(targets)) {
|
|
1313
1340
|
errors.push({
|
|
1314
1341
|
severity: "error",
|
|
@@ -1358,7 +1385,9 @@ async function validateTargetsFile(filePath) {
|
|
|
1358
1385
|
});
|
|
1359
1386
|
}
|
|
1360
1387
|
const provider = target.provider;
|
|
1361
|
-
const
|
|
1388
|
+
const rawTarget = rawTargets[i];
|
|
1389
|
+
const rawUseTarget = isObject3(rawTarget) ? rawTarget.use_target : void 0;
|
|
1390
|
+
const hasUseTarget = isNonEmptyString(target.use_target) || isNonEmptyString(rawUseTarget);
|
|
1362
1391
|
const providerValue = typeof provider === "string" ? provider.trim().toLowerCase() : void 0;
|
|
1363
1392
|
const isTemplated = typeof provider === "string" && /^\$\{\{.+\}\}$/.test(provider.trim());
|
|
1364
1393
|
if (!hasUseTarget && (typeof provider !== "string" || provider.trim().length === 0)) {
|
|
@@ -1402,8 +1431,10 @@ async function validateTargetsFile(filePath) {
|
|
|
1402
1431
|
|
|
1403
1432
|
// src/evaluation/validation/config-validator.ts
|
|
1404
1433
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
1405
|
-
|
|
1434
|
+
import path5 from "node:path";
|
|
1435
|
+
async function validateConfigFile(filePath, options = {}) {
|
|
1406
1436
|
const errors = [];
|
|
1437
|
+
const scope = options.scope ?? inferConfigScope(filePath);
|
|
1407
1438
|
try {
|
|
1408
1439
|
const content = await readFile5(filePath, "utf8");
|
|
1409
1440
|
const parsed = interpolateEnv(parseYamlValue(content), process.env);
|
|
@@ -1452,78 +1483,43 @@ async function validateConfigFile(filePath) {
|
|
|
1452
1483
|
});
|
|
1453
1484
|
}
|
|
1454
1485
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1486
|
+
validateResultsConfig(errors, filePath, config.results, "results");
|
|
1487
|
+
const projects = config.projects;
|
|
1488
|
+
if (projects !== void 0) {
|
|
1489
|
+
if (scope === "project") {
|
|
1490
|
+
errors.push({
|
|
1491
|
+
severity: "warning",
|
|
1492
|
+
filePath,
|
|
1493
|
+
location: "projects",
|
|
1494
|
+
message: "Field 'projects' is only valid in $AGENTV_HOME/config.yaml. Ignoring project registry entries in project-local .agentv/config.yaml."
|
|
1495
|
+
});
|
|
1496
|
+
} else if (!Array.isArray(projects)) {
|
|
1458
1497
|
errors.push({
|
|
1459
1498
|
severity: "error",
|
|
1460
1499
|
filePath,
|
|
1461
|
-
location: "
|
|
1462
|
-
message: "Field '
|
|
1500
|
+
location: "projects",
|
|
1501
|
+
message: "Field 'projects' must be an array"
|
|
1463
1502
|
});
|
|
1464
1503
|
} else {
|
|
1465
|
-
|
|
1466
|
-
if (resultsRecord.mode !== "github") {
|
|
1467
|
-
errors.push({
|
|
1468
|
-
severity: "error",
|
|
1469
|
-
filePath,
|
|
1470
|
-
location: "results.mode",
|
|
1471
|
-
message: "Field 'results.mode' must be 'github'"
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
if (typeof resultsRecord.repo !== "string" || resultsRecord.repo.trim().length === 0) {
|
|
1475
|
-
errors.push({
|
|
1476
|
-
severity: "error",
|
|
1477
|
-
filePath,
|
|
1478
|
-
location: "results.repo",
|
|
1479
|
-
message: "Field 'results.repo' must be a non-empty string"
|
|
1480
|
-
});
|
|
1481
|
-
}
|
|
1482
|
-
if (resultsRecord.path !== void 0) {
|
|
1483
|
-
if (typeof resultsRecord.path !== "string" || resultsRecord.path.trim().length === 0) {
|
|
1484
|
-
errors.push({
|
|
1485
|
-
severity: "error",
|
|
1486
|
-
filePath,
|
|
1487
|
-
location: "results.path",
|
|
1488
|
-
message: "Field 'results.path' must be a non-empty string"
|
|
1489
|
-
});
|
|
1490
|
-
} else {
|
|
1491
|
-
const p = resultsRecord.path.trim();
|
|
1492
|
-
const isFilesystemPath = p.startsWith("/") || p.startsWith("~/") || p.startsWith("~\\") || p === "~" || /^[A-Za-z]:[/\\]/.test(p);
|
|
1493
|
-
if (!isFilesystemPath) {
|
|
1494
|
-
errors.push({
|
|
1495
|
-
severity: "error",
|
|
1496
|
-
filePath,
|
|
1497
|
-
location: "results.path",
|
|
1498
|
-
message: `'results.path' must be an absolute or home-relative filesystem path (e.g., ~/data/agentv-results). Found: '${p}'. Remove 'path' to use the default.`
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
if (resultsRecord.auto_push !== void 0 && typeof resultsRecord.auto_push !== "boolean") {
|
|
1504
|
-
errors.push({
|
|
1505
|
-
severity: "error",
|
|
1506
|
-
filePath,
|
|
1507
|
-
location: "results.auto_push",
|
|
1508
|
-
message: "Field 'results.auto_push' must be a boolean"
|
|
1509
|
-
});
|
|
1510
|
-
}
|
|
1511
|
-
if (resultsRecord.branch_prefix !== void 0 && (typeof resultsRecord.branch_prefix !== "string" || resultsRecord.branch_prefix.trim().length === 0)) {
|
|
1512
|
-
errors.push({
|
|
1513
|
-
severity: "error",
|
|
1514
|
-
filePath,
|
|
1515
|
-
location: "results.branch_prefix",
|
|
1516
|
-
message: "Field 'results.branch_prefix' must be a non-empty string"
|
|
1517
|
-
});
|
|
1518
|
-
}
|
|
1504
|
+
validateProjects(errors, filePath, projects);
|
|
1519
1505
|
}
|
|
1520
1506
|
}
|
|
1507
|
+
if (config.results_by_project !== void 0) {
|
|
1508
|
+
errors.push({
|
|
1509
|
+
severity: "warning",
|
|
1510
|
+
filePath,
|
|
1511
|
+
location: "results_by_project",
|
|
1512
|
+
message: "Field 'results_by_project' is deprecated. Put per-project result repo settings under projects[].results in $AGENTV_HOME/config.yaml."
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1521
1515
|
const allowedFields = /* @__PURE__ */ new Set([
|
|
1522
1516
|
"$schema",
|
|
1523
1517
|
"eval_patterns",
|
|
1524
1518
|
"required_version",
|
|
1525
1519
|
"execution",
|
|
1526
1520
|
"results",
|
|
1521
|
+
"projects",
|
|
1522
|
+
"results_by_project",
|
|
1527
1523
|
"dashboard",
|
|
1528
1524
|
"studio"
|
|
1529
1525
|
]);
|
|
@@ -1550,16 +1546,115 @@ async function validateConfigFile(filePath) {
|
|
|
1550
1546
|
return { valid: false, filePath, fileType: "config", errors };
|
|
1551
1547
|
}
|
|
1552
1548
|
}
|
|
1549
|
+
function inferConfigScope(filePath) {
|
|
1550
|
+
const globalConfigPath = path5.resolve(getAgentvConfigDir(), "config.yaml");
|
|
1551
|
+
if (path5.resolve(filePath) === globalConfigPath) {
|
|
1552
|
+
return "global";
|
|
1553
|
+
}
|
|
1554
|
+
return filePath.split(/[\\/]/).includes(".agentv") ? "project" : "global";
|
|
1555
|
+
}
|
|
1556
|
+
function validateProjects(errors, filePath, projects) {
|
|
1557
|
+
projects.forEach((project, index) => {
|
|
1558
|
+
const location = `projects[${index}]`;
|
|
1559
|
+
if (typeof project !== "object" || project === null || Array.isArray(project)) {
|
|
1560
|
+
errors.push({
|
|
1561
|
+
severity: "error",
|
|
1562
|
+
filePath,
|
|
1563
|
+
location,
|
|
1564
|
+
message: `Field '${location}' must be an object`
|
|
1565
|
+
});
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
const projectRecord = project;
|
|
1569
|
+
validateRequiredString(errors, filePath, projectRecord.id, `${location}.id`);
|
|
1570
|
+
validateRequiredString(errors, filePath, projectRecord.name, `${location}.name`);
|
|
1571
|
+
validateRequiredString(errors, filePath, projectRecord.path, `${location}.path`);
|
|
1572
|
+
validateResultsConfig(errors, filePath, projectRecord.results, `${location}.results`);
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
function validateRequiredString(errors, filePath, value, location) {
|
|
1576
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
1577
|
+
errors.push({
|
|
1578
|
+
severity: "error",
|
|
1579
|
+
filePath,
|
|
1580
|
+
location,
|
|
1581
|
+
message: `Field '${location}' must be a non-empty string`
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
function validateResultsConfig(errors, filePath, rawResults, location) {
|
|
1586
|
+
if (rawResults === void 0) {
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
if (typeof rawResults !== "object" || rawResults === null || Array.isArray(rawResults)) {
|
|
1590
|
+
errors.push({
|
|
1591
|
+
severity: "error",
|
|
1592
|
+
filePath,
|
|
1593
|
+
location,
|
|
1594
|
+
message: `Field '${location}' must be an object`
|
|
1595
|
+
});
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
const resultsRecord = rawResults;
|
|
1599
|
+
if (resultsRecord.mode !== "github") {
|
|
1600
|
+
errors.push({
|
|
1601
|
+
severity: "error",
|
|
1602
|
+
filePath,
|
|
1603
|
+
location: `${location}.mode`,
|
|
1604
|
+
message: `Field '${location}.mode' must be 'github'`
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
validateRequiredString(errors, filePath, resultsRecord.repo, `${location}.repo`);
|
|
1608
|
+
if (resultsRecord.path !== void 0) {
|
|
1609
|
+
if (typeof resultsRecord.path !== "string" || resultsRecord.path.trim().length === 0) {
|
|
1610
|
+
errors.push({
|
|
1611
|
+
severity: "error",
|
|
1612
|
+
filePath,
|
|
1613
|
+
location: `${location}.path`,
|
|
1614
|
+
message: `Field '${location}.path' must be a non-empty string`
|
|
1615
|
+
});
|
|
1616
|
+
} else {
|
|
1617
|
+
const p = resultsRecord.path.trim();
|
|
1618
|
+
if (!isFilesystemPath(p)) {
|
|
1619
|
+
errors.push({
|
|
1620
|
+
severity: "error",
|
|
1621
|
+
filePath,
|
|
1622
|
+
location: `${location}.path`,
|
|
1623
|
+
message: `'${location}.path' must be an absolute or home-relative filesystem path (e.g., ~/data/agentv-results). Found: '${p}'. Remove 'path' to use the default.`
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
if (resultsRecord.auto_push !== void 0 && typeof resultsRecord.auto_push !== "boolean") {
|
|
1629
|
+
errors.push({
|
|
1630
|
+
severity: "error",
|
|
1631
|
+
filePath,
|
|
1632
|
+
location: `${location}.auto_push`,
|
|
1633
|
+
message: `Field '${location}.auto_push' must be a boolean`
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
if (resultsRecord.branch_prefix !== void 0 && (typeof resultsRecord.branch_prefix !== "string" || resultsRecord.branch_prefix.trim().length === 0)) {
|
|
1637
|
+
errors.push({
|
|
1638
|
+
severity: "error",
|
|
1639
|
+
filePath,
|
|
1640
|
+
location: `${location}.branch_prefix`,
|
|
1641
|
+
message: `Field '${location}.branch_prefix' must be a non-empty string`
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
function isFilesystemPath(p) {
|
|
1646
|
+
return p.startsWith("/") || p.startsWith("~/") || p.startsWith("~\\") || p === "~" || /^[A-Za-z]:[/\\]/.test(p);
|
|
1647
|
+
}
|
|
1553
1648
|
|
|
1554
1649
|
// src/evaluation/validation/file-reference-validator.ts
|
|
1555
1650
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
1556
|
-
import
|
|
1651
|
+
import path6 from "node:path";
|
|
1557
1652
|
function isObject4(value) {
|
|
1558
1653
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1559
1654
|
}
|
|
1560
1655
|
async function validateFileReferences(evalFilePath) {
|
|
1561
1656
|
const errors = [];
|
|
1562
|
-
const absolutePath =
|
|
1657
|
+
const absolutePath = path6.resolve(evalFilePath);
|
|
1563
1658
|
const gitRoot = await findGitRoot(absolutePath);
|
|
1564
1659
|
if (!gitRoot) {
|
|
1565
1660
|
errors.push({
|
|
@@ -1684,14 +1779,14 @@ async function validateMessagesFileRefs(messages, location, searchRoots, filePat
|
|
|
1684
1779
|
|
|
1685
1780
|
// src/evaluation/validation/workspace-path-validator.ts
|
|
1686
1781
|
import { access, readFile as readFile7 } from "node:fs/promises";
|
|
1687
|
-
import
|
|
1782
|
+
import path7 from "node:path";
|
|
1688
1783
|
function isObject5(value) {
|
|
1689
1784
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1690
1785
|
}
|
|
1691
1786
|
async function validateWorkspacePaths(evalFilePath) {
|
|
1692
1787
|
const errors = [];
|
|
1693
|
-
const absolutePath =
|
|
1694
|
-
const evalDir =
|
|
1788
|
+
const absolutePath = path7.resolve(evalFilePath);
|
|
1789
|
+
const evalDir = path7.dirname(absolutePath);
|
|
1695
1790
|
let parsed;
|
|
1696
1791
|
try {
|
|
1697
1792
|
const content = await readFile7(absolutePath, "utf8");
|
|
@@ -1703,12 +1798,12 @@ async function validateWorkspacePaths(evalFilePath) {
|
|
|
1703
1798
|
const workspaceRaw = parsed.workspace;
|
|
1704
1799
|
if (workspaceRaw === void 0 || workspaceRaw === null) return errors;
|
|
1705
1800
|
if (typeof workspaceRaw === "string") {
|
|
1706
|
-
const workspaceFilePath =
|
|
1801
|
+
const workspaceFilePath = path7.resolve(evalDir, workspaceRaw);
|
|
1707
1802
|
try {
|
|
1708
1803
|
const wsContent = await readFile7(workspaceFilePath, "utf8");
|
|
1709
1804
|
const wsParsed = parseYamlValue(wsContent);
|
|
1710
1805
|
if (isObject5(wsParsed)) {
|
|
1711
|
-
const wsDir =
|
|
1806
|
+
const wsDir = path7.dirname(workspaceFilePath);
|
|
1712
1807
|
await validateWorkspaceObject(wsParsed, wsDir, absolutePath, "workspace", errors);
|
|
1713
1808
|
}
|
|
1714
1809
|
} catch {
|
|
@@ -1721,7 +1816,7 @@ async function validateWorkspacePaths(evalFilePath) {
|
|
|
1721
1816
|
async function validateWorkspaceObject(obj, baseDir, evalFilePath, location, errors) {
|
|
1722
1817
|
const template = obj.template;
|
|
1723
1818
|
if (typeof template === "string") {
|
|
1724
|
-
const templatePath =
|
|
1819
|
+
const templatePath = path7.isAbsolute(template) ? template : path7.resolve(baseDir, template);
|
|
1725
1820
|
if (!await fileExists(templatePath)) {
|
|
1726
1821
|
errors.push({
|
|
1727
1822
|
severity: "error",
|
|
@@ -1737,14 +1832,14 @@ async function validateWorkspaceObject(obj, baseDir, evalFilePath, location, err
|
|
|
1737
1832
|
const hook = hooks[hookName];
|
|
1738
1833
|
if (!isObject5(hook)) continue;
|
|
1739
1834
|
const hookCwdRaw = typeof hook.cwd === "string" ? hook.cwd : void 0;
|
|
1740
|
-
const hookCwd = hookCwdRaw ?
|
|
1835
|
+
const hookCwd = hookCwdRaw ? path7.isAbsolute(hookCwdRaw) ? hookCwdRaw : path7.resolve(baseDir, hookCwdRaw) : baseDir;
|
|
1741
1836
|
const command = hook.command ?? hook.script;
|
|
1742
1837
|
if (!Array.isArray(command)) continue;
|
|
1743
1838
|
for (let i = 0; i < command.length; i++) {
|
|
1744
1839
|
const arg = command[i];
|
|
1745
1840
|
if (typeof arg !== "string") continue;
|
|
1746
1841
|
if (!looksLikeFilePath(arg)) continue;
|
|
1747
|
-
const resolved =
|
|
1842
|
+
const resolved = path7.isAbsolute(arg) ? arg : path7.resolve(hookCwd, arg);
|
|
1748
1843
|
if (!await fileExists(resolved)) {
|
|
1749
1844
|
errors.push({
|
|
1750
1845
|
severity: "error",
|