@vaudience/aigentflow-flow-validator 0.19.0 → 0.21.0
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/PARITY.md +114 -35
- package/README.md +3 -3
- package/dist/cli.js +413 -73
- package/dist/index.cjs +409 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +409 -73
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -302,6 +302,17 @@ function isValidGoDuration(input) {
|
|
|
302
302
|
var RESERVED_STEP_ID_CHAR = ".";
|
|
303
303
|
var RESERVED_STEP_ID_ORCHESTRATOR = "orchestrator";
|
|
304
304
|
var DISPLAY_NAME_MAX_LEN = 80;
|
|
305
|
+
var YAML11_BOOL_WORDS = new Set(
|
|
306
|
+
["y", "yes", "on", "n", "no", "off"].flatMap((w) => [
|
|
307
|
+
w,
|
|
308
|
+
w.toUpperCase(),
|
|
309
|
+
w[0].toUpperCase() + w.slice(1)
|
|
310
|
+
])
|
|
311
|
+
);
|
|
312
|
+
function isBoolLike(v) {
|
|
313
|
+
if (v === null || typeof v === "boolean") return true;
|
|
314
|
+
return typeof v === "string" && YAML11_BOOL_WORDS.has(v);
|
|
315
|
+
}
|
|
305
316
|
function validateBasicStructure(flow, issues) {
|
|
306
317
|
if (!issues.nonEmptyStringOf(flow, "aigentflow_version", "")) {
|
|
307
318
|
issues.error({
|
|
@@ -331,6 +342,14 @@ function validateBasicStructure(flow, issues) {
|
|
|
331
342
|
});
|
|
332
343
|
}
|
|
333
344
|
}
|
|
345
|
+
if (flow.strict_templates !== void 0 && !isBoolLike(flow.strict_templates)) {
|
|
346
|
+
issues.error({
|
|
347
|
+
field: "strict_templates",
|
|
348
|
+
message: "strict_templates must be a boolean (true or false)",
|
|
349
|
+
code: "invalid_type",
|
|
350
|
+
suggestion: "Write 'strict_templates: true' or remove the key"
|
|
351
|
+
});
|
|
352
|
+
}
|
|
334
353
|
const start = issues.stringOf(flow, "start", "");
|
|
335
354
|
if (start === null || start === "") {
|
|
336
355
|
issues.error({
|
|
@@ -430,7 +449,7 @@ function validateBasicStructure(flow, issues) {
|
|
|
430
449
|
|
|
431
450
|
// src/spec/aigentflow-spec.json
|
|
432
451
|
var aigentflow_spec_default = {
|
|
433
|
-
specVersion: "2.
|
|
452
|
+
specVersion: "2.827.0",
|
|
434
453
|
inputSchemaVersion: 1,
|
|
435
454
|
executorSchemes: [
|
|
436
455
|
"a2a",
|
|
@@ -454,6 +473,7 @@ var aigentflow_spec_default = {
|
|
|
454
473
|
"geocoding",
|
|
455
474
|
"geovisualize",
|
|
456
475
|
"getmd",
|
|
476
|
+
"here",
|
|
457
477
|
"homeassistant",
|
|
458
478
|
"hosting",
|
|
459
479
|
"http",
|
|
@@ -1255,6 +1275,39 @@ var aigentflow_spec_default = {
|
|
|
1255
1275
|
}
|
|
1256
1276
|
}
|
|
1257
1277
|
},
|
|
1278
|
+
templateDefaultPiped: {
|
|
1279
|
+
code: "template_default_piped",
|
|
1280
|
+
messageFormat: "`default` takes the value FIRST, and a pipe passes the piped value LAST: `%s` is `default <fallback> <value>`, so the fallback is always the result",
|
|
1281
|
+
suggestion: 'write the value first and the fallback second, as a call: `{{ default .x "fallback" }}`'
|
|
1282
|
+
},
|
|
1283
|
+
complianceResidency: {
|
|
1284
|
+
code: "compliance_residency_unenforced",
|
|
1285
|
+
euResidencyCodes: ["EU", "DE", "FR", "IE", "NL", "IT", "ES"],
|
|
1286
|
+
regionLaneProviders: [
|
|
1287
|
+
"bedrock",
|
|
1288
|
+
"google",
|
|
1289
|
+
"azure",
|
|
1290
|
+
"openai",
|
|
1291
|
+
"assemblyai",
|
|
1292
|
+
"speechmatics",
|
|
1293
|
+
"deepgram",
|
|
1294
|
+
"mistral"
|
|
1295
|
+
],
|
|
1296
|
+
aiProtocol: "ai",
|
|
1297
|
+
protocolSeparator: "://",
|
|
1298
|
+
regionParam: "region",
|
|
1299
|
+
enforceRegionParam: "enforce_region",
|
|
1300
|
+
baseUrlParamSuffix: "_base_url",
|
|
1301
|
+
enforceRegionTrueStrings: ["true", "1", "yes"],
|
|
1302
|
+
stepFieldFormat: "steps.%s.executor",
|
|
1303
|
+
loopStepFieldFormat: "steps.%s.loop.steps.%s.executor",
|
|
1304
|
+
orchestratorField: "orchestrator.exons",
|
|
1305
|
+
siteStepFormat: "step %q",
|
|
1306
|
+
siteLoopStepFormat: "loop sub-step %q of step %q",
|
|
1307
|
+
siteOrchestrator: "the orchestrator",
|
|
1308
|
+
messageFormat: "%s calls provider %q, whose default endpoint commits to no jurisdiction, but sets neither region nor enforce_region, so nothing pins it to the declared residency %v. compliance.residency is a catalogue eligibility check, not endpoint evidence",
|
|
1309
|
+
suggestion: "Add `region: eu` and `enforce_region: true` to the call (an orchestrator: the same two keys on the orchestrator block). Prove it afterwards: the step record's diagnostics.region is stamped from the host actually dialled."
|
|
1310
|
+
},
|
|
1258
1311
|
examples: {
|
|
1259
1312
|
limits: {
|
|
1260
1313
|
maxPerFlow: 50,
|
|
@@ -1525,6 +1578,7 @@ var aigentflow_spec_default = {
|
|
|
1525
1578
|
rate_limit: "FlowRateLimitConfig",
|
|
1526
1579
|
start: "scalar",
|
|
1527
1580
|
steps: "map<StepDefinition>",
|
|
1581
|
+
strict_templates: "scalar",
|
|
1528
1582
|
tags: "list<scalar>",
|
|
1529
1583
|
template: "FlowTemplateMetadata",
|
|
1530
1584
|
tool_discovery: "scalar",
|
|
@@ -1850,6 +1904,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
|
|
|
1850
1904
|
familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
|
|
1851
1905
|
families: aigentflow_spec_default.credentialEndpointPairing.families
|
|
1852
1906
|
};
|
|
1907
|
+
var COMPLIANCE_RESIDENCY = {
|
|
1908
|
+
code: aigentflow_spec_default.complianceResidency.code,
|
|
1909
|
+
euResidencyCodes: aigentflow_spec_default.complianceResidency.euResidencyCodes,
|
|
1910
|
+
regionLaneProviders: aigentflow_spec_default.complianceResidency.regionLaneProviders,
|
|
1911
|
+
aiProtocol: aigentflow_spec_default.complianceResidency.aiProtocol,
|
|
1912
|
+
protocolSeparator: aigentflow_spec_default.complianceResidency.protocolSeparator,
|
|
1913
|
+
regionParam: aigentflow_spec_default.complianceResidency.regionParam,
|
|
1914
|
+
enforceRegionParam: aigentflow_spec_default.complianceResidency.enforceRegionParam,
|
|
1915
|
+
baseUrlParamSuffix: aigentflow_spec_default.complianceResidency.baseUrlParamSuffix,
|
|
1916
|
+
enforceRegionTrueStrings: aigentflow_spec_default.complianceResidency.enforceRegionTrueStrings,
|
|
1917
|
+
stepFieldFormat: aigentflow_spec_default.complianceResidency.stepFieldFormat,
|
|
1918
|
+
loopStepFieldFormat: aigentflow_spec_default.complianceResidency.loopStepFieldFormat,
|
|
1919
|
+
orchestratorField: aigentflow_spec_default.complianceResidency.orchestratorField,
|
|
1920
|
+
siteStepFormat: aigentflow_spec_default.complianceResidency.siteStepFormat,
|
|
1921
|
+
siteLoopStepFormat: aigentflow_spec_default.complianceResidency.siteLoopStepFormat,
|
|
1922
|
+
siteOrchestrator: aigentflow_spec_default.complianceResidency.siteOrchestrator,
|
|
1923
|
+
messageFormat: aigentflow_spec_default.complianceResidency.messageFormat,
|
|
1924
|
+
suggestion: aigentflow_spec_default.complianceResidency.suggestion
|
|
1925
|
+
};
|
|
1853
1926
|
var EXAMPLES = {
|
|
1854
1927
|
limits: aigentflow_spec_default.examples.limits,
|
|
1855
1928
|
idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
|
|
@@ -1867,6 +1940,11 @@ var EXAMPLES = {
|
|
|
1867
1940
|
name: p.name,
|
|
1868
1941
|
re: new RegExp(p.expr, p.flags)
|
|
1869
1942
|
}))};
|
|
1943
|
+
var TEMPLATE_DEFAULT_PIPED = {
|
|
1944
|
+
code: aigentflow_spec_default.templateDefaultPiped.code,
|
|
1945
|
+
messageFormat: aigentflow_spec_default.templateDefaultPiped.messageFormat,
|
|
1946
|
+
suggestion: aigentflow_spec_default.templateDefaultPiped.suggestion
|
|
1947
|
+
};
|
|
1870
1948
|
|
|
1871
1949
|
// src/validators/executors.ts
|
|
1872
1950
|
var SCHEME_SEPARATOR = "://";
|
|
@@ -3830,6 +3908,117 @@ function splitPipeline(body) {
|
|
|
3830
3908
|
return stages;
|
|
3831
3909
|
}
|
|
3832
3910
|
|
|
3911
|
+
// src/template/gotmpl-default.ts
|
|
3912
|
+
var FUNCTION_NAME = "default";
|
|
3913
|
+
var PIPE = "|";
|
|
3914
|
+
var OPEN_PAREN = "(";
|
|
3915
|
+
var CLOSE_PAREN = ")";
|
|
3916
|
+
var MAX_NESTING_DEPTH = 100;
|
|
3917
|
+
var PIPELINE_KEYWORDS = /^(?:else\s+if|else\s+with|if|range|with|template|block)(?![\w$.])/;
|
|
3918
|
+
var NO_PIPELINE = /^(?:define|else|end|break|continue)(?![\w$.])/;
|
|
3919
|
+
var DECLARATION = /^\$\w*(?:\s*,\s*\$\w*)*\s*:?=/;
|
|
3920
|
+
function pipedDefaultPipelines(src) {
|
|
3921
|
+
const { actions, fatal } = lexActions(src);
|
|
3922
|
+
if (fatal) return [];
|
|
3923
|
+
const found = /* @__PURE__ */ new Set();
|
|
3924
|
+
try {
|
|
3925
|
+
for (const action of actions) {
|
|
3926
|
+
if (action.isComment || action.body === "") continue;
|
|
3927
|
+
scanAction(action.body, found);
|
|
3928
|
+
}
|
|
3929
|
+
} catch (err) {
|
|
3930
|
+
if (!(err instanceof RangeError)) throw err;
|
|
3931
|
+
return [];
|
|
3932
|
+
}
|
|
3933
|
+
return [...found].sort();
|
|
3934
|
+
}
|
|
3935
|
+
function scanAction(body, found) {
|
|
3936
|
+
let rest = body;
|
|
3937
|
+
const kw = PIPELINE_KEYWORDS.exec(rest);
|
|
3938
|
+
if (!kw && NO_PIPELINE.test(rest)) return;
|
|
3939
|
+
if (kw) {
|
|
3940
|
+
rest = rest.slice(kw[0].length).trimStart();
|
|
3941
|
+
const keyword = kw[0].replace(/\s+/g, " ");
|
|
3942
|
+
if (keyword === "template" || keyword === "block") {
|
|
3943
|
+
const q2 = rest[0];
|
|
3944
|
+
if (q2 === '"' || q2 === "`") {
|
|
3945
|
+
const end = scanString(rest, 0, q2);
|
|
3946
|
+
if (end === -1) return;
|
|
3947
|
+
rest = rest.slice(end + 1).trimStart();
|
|
3948
|
+
}
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
if (rest === "") return;
|
|
3952
|
+
parsePipeline(rest, 0, false, found, 0);
|
|
3953
|
+
}
|
|
3954
|
+
function parsePipeline(src, start, nested, found, depth) {
|
|
3955
|
+
if (depth > MAX_NESTING_DEPTH) return { text: src.slice(start), end: src.length };
|
|
3956
|
+
let i = start;
|
|
3957
|
+
const n = src.length;
|
|
3958
|
+
let decl = "";
|
|
3959
|
+
const decMatch = DECLARATION.exec(src.slice(i));
|
|
3960
|
+
if (decMatch) {
|
|
3961
|
+
decl = decMatch[0].replace(/\s+/g, " ") + " ";
|
|
3962
|
+
i += decMatch[0].length;
|
|
3963
|
+
}
|
|
3964
|
+
const commands = [];
|
|
3965
|
+
let current = [];
|
|
3966
|
+
let firstWords = [];
|
|
3967
|
+
let pipedDefault = false;
|
|
3968
|
+
const pushCommand = () => {
|
|
3969
|
+
if (current.length > 0) {
|
|
3970
|
+
commands.push(current);
|
|
3971
|
+
firstWords.push(current[0]);
|
|
3972
|
+
}
|
|
3973
|
+
current = [];
|
|
3974
|
+
};
|
|
3975
|
+
while (i < n) {
|
|
3976
|
+
const c = src[i];
|
|
3977
|
+
if (c === " " || c === " " || c === "\n" || c === "\r") {
|
|
3978
|
+
i += 1;
|
|
3979
|
+
continue;
|
|
3980
|
+
}
|
|
3981
|
+
if (c === '"' || c === "`" || c === "'") {
|
|
3982
|
+
const end = scanString(src, i, c);
|
|
3983
|
+
const stop = end === -1 ? n - 1 : end;
|
|
3984
|
+
current.push(src.slice(i, stop + 1));
|
|
3985
|
+
i = stop + 1;
|
|
3986
|
+
continue;
|
|
3987
|
+
}
|
|
3988
|
+
if (c === OPEN_PAREN) {
|
|
3989
|
+
const inner = parsePipeline(src, i + 1, true, found, depth + 1);
|
|
3990
|
+
current.push(`(${inner.text})`);
|
|
3991
|
+
i = inner.end;
|
|
3992
|
+
continue;
|
|
3993
|
+
}
|
|
3994
|
+
if (c === CLOSE_PAREN) {
|
|
3995
|
+
if (nested) {
|
|
3996
|
+
i += 1;
|
|
3997
|
+
break;
|
|
3998
|
+
}
|
|
3999
|
+
i += 1;
|
|
4000
|
+
continue;
|
|
4001
|
+
}
|
|
4002
|
+
if (c === PIPE) {
|
|
4003
|
+
pushCommand();
|
|
4004
|
+
i += 1;
|
|
4005
|
+
continue;
|
|
4006
|
+
}
|
|
4007
|
+
let j = i;
|
|
4008
|
+
while (j < n && !/[\s|()"`']/.test(src[j])) j += 1;
|
|
4009
|
+
if (j === i) j = i + 1;
|
|
4010
|
+
current.push(src.slice(i, j));
|
|
4011
|
+
i = j;
|
|
4012
|
+
}
|
|
4013
|
+
pushCommand();
|
|
4014
|
+
firstWords.forEach((word, idx) => {
|
|
4015
|
+
if (idx > 0 && word === FUNCTION_NAME) pipedDefault = true;
|
|
4016
|
+
});
|
|
4017
|
+
const text = decl + commands.map((cmd) => cmd.join(" ")).join(` ${PIPE} `);
|
|
4018
|
+
if (pipedDefault) found.add(text);
|
|
4019
|
+
return { text, end: i };
|
|
4020
|
+
}
|
|
4021
|
+
|
|
3833
4022
|
// src/validators/processingOperations.ts
|
|
3834
4023
|
var PROCESSING_OP_GUARD_KEY = PROCESSING_OPERATIONS.guardKey;
|
|
3835
4024
|
var PROCESSING_PHASES = ["pre_processing", "post_processing"];
|
|
@@ -3976,6 +4165,17 @@ function checkTemplateString(value, field, stepID, issues, stats, opts, demote =
|
|
|
3976
4165
|
});
|
|
3977
4166
|
}
|
|
3978
4167
|
}
|
|
4168
|
+
if (errors.length > 0) return;
|
|
4169
|
+
for (const pipe of pipedDefaultPipelines(value)) {
|
|
4170
|
+
report({
|
|
4171
|
+
field,
|
|
4172
|
+
message: TEMPLATE_DEFAULT_PIPED.messageFormat.replace("%s", () => pipe),
|
|
4173
|
+
code: TEMPLATE_DEFAULT_PIPED.code,
|
|
4174
|
+
stepId: stepID,
|
|
4175
|
+
context: `Template: ${value}`,
|
|
4176
|
+
suggestion: TEMPLATE_DEFAULT_PIPED.suggestion
|
|
4177
|
+
});
|
|
4178
|
+
}
|
|
3979
4179
|
}
|
|
3980
4180
|
function walkStrings2(basePath, value, stepID, issues, stats, opts, check, demote = false) {
|
|
3981
4181
|
if (isString(value)) {
|
|
@@ -5202,6 +5402,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
|
|
|
5202
5402
|
}
|
|
5203
5403
|
}
|
|
5204
5404
|
|
|
5405
|
+
// src/validators/complianceResidency.ts
|
|
5406
|
+
function own2(m, key) {
|
|
5407
|
+
if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
|
|
5408
|
+
return m[key];
|
|
5409
|
+
}
|
|
5410
|
+
function sprintf(format, ...args) {
|
|
5411
|
+
let i = 0;
|
|
5412
|
+
return format.replace(/%[sqv]/g, (verb) => {
|
|
5413
|
+
const arg = args[i++] ?? "";
|
|
5414
|
+
return verb === "%q" ? JSON.stringify(arg) : arg;
|
|
5415
|
+
});
|
|
5416
|
+
}
|
|
5417
|
+
function literalOrEmpty(s) {
|
|
5418
|
+
const t = goTrimSpace2(s);
|
|
5419
|
+
return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
|
|
5420
|
+
}
|
|
5421
|
+
function euOnlyResidency(flow, issues) {
|
|
5422
|
+
const raw = own2(own2(flow, "compliance"), "residency");
|
|
5423
|
+
if (!isArray(raw)) return null;
|
|
5424
|
+
const codes = [];
|
|
5425
|
+
for (let i = 0; i < raw.length; i++) {
|
|
5426
|
+
if (raw[i] === null) continue;
|
|
5427
|
+
const code = issues.stringAt(raw[i], `compliance.residency[${i}]`);
|
|
5428
|
+
if (code === null) return null;
|
|
5429
|
+
codes.push(code);
|
|
5430
|
+
}
|
|
5431
|
+
if (codes.length === 0) return null;
|
|
5432
|
+
const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
|
|
5433
|
+
return codes.every((c) => eu.has(goTrimSpace2(c).toUpperCase())) ? codes : null;
|
|
5434
|
+
}
|
|
5435
|
+
function aiProvider(executor) {
|
|
5436
|
+
const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
|
|
5437
|
+
if (!executor.startsWith(prefix)) return "";
|
|
5438
|
+
const rest = executor.slice(prefix.length);
|
|
5439
|
+
const slash = rest.indexOf("/");
|
|
5440
|
+
const provider = slash > 0 ? rest.slice(0, slash) : "";
|
|
5441
|
+
return provider.includes(TEMPLATE_ACTION_OPEN) ? "" : provider;
|
|
5442
|
+
}
|
|
5443
|
+
function isRegionLane(provider) {
|
|
5444
|
+
const literal = literalOrEmpty(provider);
|
|
5445
|
+
return literal !== "" && COMPLIANCE_RESIDENCY.regionLaneProviders.includes(literal.toLowerCase());
|
|
5446
|
+
}
|
|
5447
|
+
function nonBlankString(m, key) {
|
|
5448
|
+
const v = own2(m, key);
|
|
5449
|
+
return typeof v === "string" && goTrimSpace2(v) !== "";
|
|
5450
|
+
}
|
|
5451
|
+
function queryEnforcesRegion(query) {
|
|
5452
|
+
const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
|
|
5453
|
+
if (typeof v === "boolean") return v;
|
|
5454
|
+
return typeof v === "string" && COMPLIANCE_RESIDENCY.enforceRegionTrueStrings.includes(v);
|
|
5455
|
+
}
|
|
5456
|
+
function flowDirectsEndpoint(flow, provider, issues) {
|
|
5457
|
+
const key = provider.toLowerCase();
|
|
5458
|
+
const inst = own2(own2(flow, "executor_config"), key);
|
|
5459
|
+
if (!isRecord(inst)) return false;
|
|
5460
|
+
const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
|
|
5461
|
+
return baseUrl !== null && goTrimSpace2(baseUrl) !== "";
|
|
5462
|
+
}
|
|
5463
|
+
function callPinsEndpoint(flow, provider, query, issues) {
|
|
5464
|
+
if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
|
|
5465
|
+
if (queryEnforcesRegion(query)) return true;
|
|
5466
|
+
if (nonBlankString(query, provider.toLowerCase() + COMPLIANCE_RESIDENCY.baseUrlParamSuffix)) return true;
|
|
5467
|
+
return flowDirectsEndpoint(flow, provider, issues);
|
|
5468
|
+
}
|
|
5469
|
+
function validateResidencyEnforcement(flow, issues) {
|
|
5470
|
+
const residency = euOnlyResidency(flow, issues);
|
|
5471
|
+
if (residency === null) return;
|
|
5472
|
+
const warn = (site, field, stepId, provider) => {
|
|
5473
|
+
issues.warn({
|
|
5474
|
+
field,
|
|
5475
|
+
...stepId === void 0 ? {} : { stepId },
|
|
5476
|
+
code: COMPLIANCE_RESIDENCY.code,
|
|
5477
|
+
message: sprintf(COMPLIANCE_RESIDENCY.messageFormat, site, provider, `[${residency.join(" ")}]`),
|
|
5478
|
+
suggestion: COMPLIANCE_RESIDENCY.suggestion
|
|
5479
|
+
});
|
|
5480
|
+
};
|
|
5481
|
+
const steps = flow.steps;
|
|
5482
|
+
if (isRecord(steps)) {
|
|
5483
|
+
for (const stepId of Object.keys(steps).sort()) {
|
|
5484
|
+
const step = steps[stepId];
|
|
5485
|
+
if (!isRecord(step)) continue;
|
|
5486
|
+
const calls = [
|
|
5487
|
+
{
|
|
5488
|
+
executor: issues.stringOf(step, "executor", `steps.${stepId}`) ?? "",
|
|
5489
|
+
query: own2(step, "query"),
|
|
5490
|
+
subId: null
|
|
5491
|
+
}
|
|
5492
|
+
];
|
|
5493
|
+
for (const sub of loopSubStepsOfStep(stepId, step)) {
|
|
5494
|
+
calls.push({
|
|
5495
|
+
executor: issues.stringOf(sub.raw, "executor", sub.basePath) ?? "",
|
|
5496
|
+
query: own2(sub.raw, "query"),
|
|
5497
|
+
subId: issues.stringOf(sub.raw, "id", sub.basePath) ?? ""
|
|
5498
|
+
});
|
|
5499
|
+
}
|
|
5500
|
+
for (const call of calls) {
|
|
5501
|
+
const provider = aiProvider(call.executor);
|
|
5502
|
+
if (!isRegionLane(provider)) continue;
|
|
5503
|
+
if (callPinsEndpoint(flow, provider, call.query, issues)) continue;
|
|
5504
|
+
if (call.subId === null) {
|
|
5505
|
+
warn(
|
|
5506
|
+
sprintf(COMPLIANCE_RESIDENCY.siteStepFormat, stepId),
|
|
5507
|
+
sprintf(COMPLIANCE_RESIDENCY.stepFieldFormat, stepId),
|
|
5508
|
+
stepId,
|
|
5509
|
+
provider
|
|
5510
|
+
);
|
|
5511
|
+
} else {
|
|
5512
|
+
warn(
|
|
5513
|
+
sprintf(COMPLIANCE_RESIDENCY.siteLoopStepFormat, call.subId, stepId),
|
|
5514
|
+
sprintf(COMPLIANCE_RESIDENCY.loopStepFieldFormat, stepId, call.subId),
|
|
5515
|
+
stepId,
|
|
5516
|
+
provider
|
|
5517
|
+
);
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
warnOrchestrator(flow, issues, warn);
|
|
5523
|
+
}
|
|
5524
|
+
function warnOrchestrator(flow, issues, warn) {
|
|
5525
|
+
const orch = flow.orchestrator;
|
|
5526
|
+
if (!isRecord(orch)) return;
|
|
5527
|
+
const source = issues.stringOf(orch, "exons", "orchestrator");
|
|
5528
|
+
if (source === null || source === "") return;
|
|
5529
|
+
const report = inspectExonsFrontmatter(source);
|
|
5530
|
+
if (report.parseError !== null || !report.specRead || !report.hasSpec) return;
|
|
5531
|
+
const provider = literalOrEmpty(report.provider);
|
|
5532
|
+
if (!isRegionLane(provider)) return;
|
|
5533
|
+
const region = issues.stringOf(orch, "region", "orchestrator");
|
|
5534
|
+
if (region !== null && goTrimSpace2(region) !== "") return;
|
|
5535
|
+
if (orch.enforce_region === true) return;
|
|
5536
|
+
if (flowDirectsEndpoint(flow, provider, issues)) return;
|
|
5537
|
+
warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
|
|
5538
|
+
}
|
|
5539
|
+
|
|
5205
5540
|
// src/validators/examples.ts
|
|
5206
5541
|
var KEY_EXAMPLES = "examples";
|
|
5207
5542
|
var VISIBILITY_PUBLIC = "public";
|
|
@@ -5279,7 +5614,7 @@ function num(n) {
|
|
|
5279
5614
|
function has(o, key) {
|
|
5280
5615
|
return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
|
|
5281
5616
|
}
|
|
5282
|
-
function
|
|
5617
|
+
function own3(o, key) {
|
|
5283
5618
|
return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
|
|
5284
5619
|
}
|
|
5285
5620
|
function setOwn(o, key, value) {
|
|
@@ -5331,7 +5666,7 @@ function mergePatch(target, patch, depth) {
|
|
|
5331
5666
|
continue;
|
|
5332
5667
|
}
|
|
5333
5668
|
if (isRecord(pv)) {
|
|
5334
|
-
const current =
|
|
5669
|
+
const current = own3(target, k);
|
|
5335
5670
|
const existing = isRecord(current) ? deepCopy(current, 0) : {};
|
|
5336
5671
|
mergePatch(existing, pv, depth + 1);
|
|
5337
5672
|
setOwn(target, k, existing);
|
|
@@ -5351,7 +5686,7 @@ function asFileRef(v) {
|
|
|
5351
5686
|
if (keys.length === 0) return null;
|
|
5352
5687
|
for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
|
|
5353
5688
|
const str = (k) => {
|
|
5354
|
-
const x =
|
|
5689
|
+
const x = own3(v, k);
|
|
5355
5690
|
return typeof x === "string" ? x : "";
|
|
5356
5691
|
};
|
|
5357
5692
|
return {
|
|
@@ -5419,7 +5754,7 @@ var Walker = class _Walker {
|
|
|
5419
5754
|
`the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
|
|
5420
5755
|
);
|
|
5421
5756
|
}
|
|
5422
|
-
const allHeld = examples.every((e) => isRecord(e) &&
|
|
5757
|
+
const allHeld = examples.every((e) => isRecord(e) && own3(e, "hold_out") === true);
|
|
5423
5758
|
if (allHeld) {
|
|
5424
5759
|
this.warn(
|
|
5425
5760
|
"examples_all_held_out",
|
|
@@ -5507,9 +5842,9 @@ var Walker = class _Walker {
|
|
|
5507
5842
|
`example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
|
|
5508
5843
|
);
|
|
5509
5844
|
}
|
|
5510
|
-
this.validateTags(path, label,
|
|
5511
|
-
this.validateWeight(`${path}.weight`, label, numberOf(
|
|
5512
|
-
const minScore = numberOf(
|
|
5845
|
+
this.validateTags(path, label, own3(ex, "tags"));
|
|
5846
|
+
this.validateWeight(`${path}.weight`, label, numberOf(own3(ex, "weight")));
|
|
5847
|
+
const minScore = numberOf(own3(ex, "min_score"));
|
|
5513
5848
|
if (minScore !== void 0 && !scoreInRange(minScore)) {
|
|
5514
5849
|
this.err(
|
|
5515
5850
|
"example_min_score_range",
|
|
@@ -5525,7 +5860,7 @@ var Walker = class _Walker {
|
|
|
5525
5860
|
`example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
|
|
5526
5861
|
);
|
|
5527
5862
|
}
|
|
5528
|
-
const holdOut =
|
|
5863
|
+
const holdOut = own3(ex, "hold_out") === true;
|
|
5529
5864
|
if (holdOut && this.isPublic()) {
|
|
5530
5865
|
this.err(
|
|
5531
5866
|
"example_holdout_in_public_flow",
|
|
@@ -5548,17 +5883,17 @@ var Walker = class _Walker {
|
|
|
5548
5883
|
`example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
|
|
5549
5884
|
);
|
|
5550
5885
|
}
|
|
5551
|
-
const rawInput =
|
|
5886
|
+
const rawInput = own3(ex, "input");
|
|
5552
5887
|
const baseInput = isRecord(rawInput) ? rawInput : null;
|
|
5553
5888
|
if (baseInput !== null) {
|
|
5554
5889
|
this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
|
|
5555
5890
|
}
|
|
5556
|
-
const rawInputRef =
|
|
5891
|
+
const rawInputRef = own3(ex, "input_ref");
|
|
5557
5892
|
if (isRecord(rawInputRef)) {
|
|
5558
5893
|
this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
|
|
5559
5894
|
}
|
|
5560
5895
|
let binaryOnly = false;
|
|
5561
|
-
const expected =
|
|
5896
|
+
const expected = own3(ex, "expected");
|
|
5562
5897
|
if (!has(ex, "expected")) {
|
|
5563
5898
|
this.err(
|
|
5564
5899
|
"example_expected_missing",
|
|
@@ -5577,7 +5912,7 @@ var Walker = class _Walker {
|
|
|
5577
5912
|
"this example can be run but not scored"
|
|
5578
5913
|
);
|
|
5579
5914
|
}
|
|
5580
|
-
this.validateCheckpoints(path, label,
|
|
5915
|
+
this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
|
|
5581
5916
|
this.validateVariants(i, path, label, ex, hasInput, baseInput);
|
|
5582
5917
|
this.scanSecretLike(i, path, ex);
|
|
5583
5918
|
}
|
|
@@ -5637,8 +5972,8 @@ var Walker = class _Walker {
|
|
|
5637
5972
|
);
|
|
5638
5973
|
return;
|
|
5639
5974
|
}
|
|
5640
|
-
const schema =
|
|
5641
|
-
const query =
|
|
5975
|
+
const schema = own3(this.flow, "input_schema");
|
|
5976
|
+
const query = own3(this.flow, "query");
|
|
5642
5977
|
if (isRecord(schema)) {
|
|
5643
5978
|
this.checkInputAgainstSchema(field, label, input, schema, code);
|
|
5644
5979
|
} else if (isRecord(query) && Object.keys(query).length > 0) {
|
|
@@ -5706,29 +6041,29 @@ var Walker = class _Walker {
|
|
|
5706
6041
|
}
|
|
5707
6042
|
}
|
|
5708
6043
|
schemaFields(schema) {
|
|
5709
|
-
const raw =
|
|
6044
|
+
const raw = own3(schema, "fields");
|
|
5710
6045
|
if (!Array.isArray(raw)) return [];
|
|
5711
6046
|
const out = [];
|
|
5712
6047
|
raw.forEach((f, i) => {
|
|
5713
6048
|
if (!isRecord(f)) return;
|
|
5714
6049
|
const base = `input_schema.fields[${i}]`;
|
|
5715
|
-
const enumRaw =
|
|
6050
|
+
const enumRaw = own3(f, "enum");
|
|
5716
6051
|
const enumValues = [];
|
|
5717
6052
|
if (Array.isArray(enumRaw)) {
|
|
5718
6053
|
enumRaw.forEach((e, j) => {
|
|
5719
6054
|
enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
|
|
5720
6055
|
});
|
|
5721
6056
|
}
|
|
5722
|
-
const vw =
|
|
6057
|
+
const vw = own3(f, "visible_when");
|
|
5723
6058
|
out.push({
|
|
5724
6059
|
name: this.s(f, "name", base),
|
|
5725
6060
|
type: this.s(f, "type", base),
|
|
5726
|
-
required:
|
|
6061
|
+
required: own3(f, "required") === true,
|
|
5727
6062
|
enumValues,
|
|
5728
6063
|
visibleWhen: isRecord(vw) ? {
|
|
5729
6064
|
field: this.s(vw, "field", `${base}.visible_when`),
|
|
5730
|
-
equals:
|
|
5731
|
-
in: Array.isArray(
|
|
6065
|
+
equals: own3(vw, "equals"),
|
|
6066
|
+
in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
|
|
5732
6067
|
} : null
|
|
5733
6068
|
});
|
|
5734
6069
|
});
|
|
@@ -5739,7 +6074,7 @@ var Walker = class _Walker {
|
|
|
5739
6074
|
const failures = [];
|
|
5740
6075
|
for (const f of fields) {
|
|
5741
6076
|
if (!isVisible(f, runInput)) continue;
|
|
5742
|
-
const raw =
|
|
6077
|
+
const raw = own3(runInput, f.name);
|
|
5743
6078
|
if (raw === void 0 || raw === null) {
|
|
5744
6079
|
if (f.required) {
|
|
5745
6080
|
failures.push({
|
|
@@ -5850,7 +6185,7 @@ var Walker = class _Walker {
|
|
|
5850
6185
|
/** The names `fields` / `exact` may use, and whether such a list is declared at all. */
|
|
5851
6186
|
outputNamesFor(kind, stepId) {
|
|
5852
6187
|
if (kind === "final") {
|
|
5853
|
-
const out =
|
|
6188
|
+
const out = own3(this.flow, "output");
|
|
5854
6189
|
const names2 = [];
|
|
5855
6190
|
if (Array.isArray(out)) {
|
|
5856
6191
|
out.forEach((item, i) => {
|
|
@@ -5859,10 +6194,10 @@ var Walker = class _Walker {
|
|
|
5859
6194
|
}
|
|
5860
6195
|
return { names: names2, declared: names2.length > 0 };
|
|
5861
6196
|
}
|
|
5862
|
-
const steps =
|
|
5863
|
-
const step = isRecord(steps) ?
|
|
5864
|
-
const schema = isRecord(step) ?
|
|
5865
|
-
const fields = isRecord(schema) ?
|
|
6197
|
+
const steps = own3(this.flow, "steps");
|
|
6198
|
+
const step = isRecord(steps) ? own3(steps, stepId) : void 0;
|
|
6199
|
+
const schema = isRecord(step) ? own3(step, "output_schema") : void 0;
|
|
6200
|
+
const fields = isRecord(schema) ? own3(schema, "fields") : void 0;
|
|
5866
6201
|
if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
|
|
5867
6202
|
const names = [];
|
|
5868
6203
|
fields.forEach((f, i) => {
|
|
@@ -5881,8 +6216,8 @@ var Walker = class _Walker {
|
|
|
5881
6216
|
);
|
|
5882
6217
|
}
|
|
5883
6218
|
const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
|
|
5884
|
-
const fieldsRec =
|
|
5885
|
-
const exactRec =
|
|
6219
|
+
const fieldsRec = own3(e, "fields");
|
|
6220
|
+
const exactRec = own3(e, "exact");
|
|
5886
6221
|
const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
|
|
5887
6222
|
const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
|
|
5888
6223
|
const hasFields = fieldKeys.length > 0;
|
|
@@ -5900,7 +6235,7 @@ var Walker = class _Walker {
|
|
|
5900
6235
|
`a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
|
|
5901
6236
|
);
|
|
5902
6237
|
}
|
|
5903
|
-
const minScore = numberOf(
|
|
6238
|
+
const minScore = numberOf(own3(e, "min_score"));
|
|
5904
6239
|
if (minScore !== void 0 && !scoreInRange(minScore)) {
|
|
5905
6240
|
this.err(
|
|
5906
6241
|
"example_min_score_range",
|
|
@@ -5927,7 +6262,7 @@ var Walker = class _Walker {
|
|
|
5927
6262
|
}
|
|
5928
6263
|
}
|
|
5929
6264
|
}
|
|
5930
|
-
const reference =
|
|
6265
|
+
const reference = own3(e, "reference");
|
|
5931
6266
|
if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
|
|
5932
6267
|
const { names, declared } = this.outputNamesFor(kind, stepId);
|
|
5933
6268
|
const checkKey = (field, key) => {
|
|
@@ -5954,12 +6289,12 @@ var Walker = class _Walker {
|
|
|
5954
6289
|
for (const key of fieldKeys) {
|
|
5955
6290
|
const fpath = `${path}.fields.${key}`;
|
|
5956
6291
|
checkKey(fpath, key);
|
|
5957
|
-
const matcher =
|
|
6292
|
+
const matcher = own3(fieldsRec, key);
|
|
5958
6293
|
if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
|
|
5959
6294
|
}
|
|
5960
6295
|
for (const key of exactKeys) checkKey(`${path}.exact.${key}`, key);
|
|
5961
|
-
const mustNot = this.stringList(
|
|
5962
|
-
const mustNotContain = this.stringList(
|
|
6296
|
+
const mustNot = this.stringList(own3(e, "must_not"), `${path}.must_not`);
|
|
6297
|
+
const mustNotContain = this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`);
|
|
5963
6298
|
const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
|
|
5964
6299
|
if (mustNot.length > L.maxMustNot) {
|
|
5965
6300
|
this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
|
|
@@ -5980,9 +6315,9 @@ var Walker = class _Walker {
|
|
|
5980
6315
|
}
|
|
5981
6316
|
});
|
|
5982
6317
|
for (const key of fieldKeys) {
|
|
5983
|
-
const matcher =
|
|
6318
|
+
const matcher = own3(fieldsRec, key);
|
|
5984
6319
|
if (!isRecord(matcher)) continue;
|
|
5985
|
-
const eq =
|
|
6320
|
+
const eq = own3(matcher, "equals");
|
|
5986
6321
|
if (typeof eq !== "string" || eq === "") continue;
|
|
5987
6322
|
for (const banned of mustNotContain) {
|
|
5988
6323
|
if (banned !== "" && equalFold(banned, eq)) {
|
|
@@ -6042,7 +6377,7 @@ var Walker = class _Walker {
|
|
|
6042
6377
|
}
|
|
6043
6378
|
return;
|
|
6044
6379
|
}
|
|
6045
|
-
const refRec =
|
|
6380
|
+
const refRec = own3(r, "ref");
|
|
6046
6381
|
if (!isRecord(refRec)) return;
|
|
6047
6382
|
const ref = this.fileRefOf(refRec, `${path}.ref`);
|
|
6048
6383
|
this.validateFileRef(`${path}.ref`, ref);
|
|
@@ -6055,22 +6390,22 @@ var Walker = class _Walker {
|
|
|
6055
6390
|
}
|
|
6056
6391
|
}
|
|
6057
6392
|
expectationIsBinaryReferenceOnly(e, path) {
|
|
6058
|
-
const reference =
|
|
6059
|
-
const refRec = isRecord(reference) ?
|
|
6393
|
+
const reference = own3(e, "reference");
|
|
6394
|
+
const refRec = isRecord(reference) ? own3(reference, "ref") : void 0;
|
|
6060
6395
|
if (!isRecord(refRec)) return false;
|
|
6061
6396
|
const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
|
|
6062
6397
|
if (mediaType === "" || isTextualMediaType(mediaType)) return false;
|
|
6063
6398
|
const status = this.s(e, "status", path);
|
|
6064
|
-
const fields =
|
|
6065
|
-
const exact =
|
|
6066
|
-
return this.s(e, "rubric", path) === "" && !(isRecord(fields) && Object.keys(fields).length > 0) && !(isRecord(exact) && Object.keys(exact).length > 0) && this.stringList(
|
|
6399
|
+
const fields = own3(e, "fields");
|
|
6400
|
+
const exact = own3(e, "exact");
|
|
6401
|
+
return this.s(e, "rubric", path) === "" && !(isRecord(fields) && Object.keys(fields).length > 0) && !(isRecord(exact) && Object.keys(exact).length > 0) && this.stringList(own3(e, "must_not"), `${path}.must_not`).length === 0 && this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).length === 0 && (status === "" || status === STATUS_COMPLETED);
|
|
6067
6402
|
}
|
|
6068
6403
|
validateFieldMatcher(path, m) {
|
|
6069
6404
|
const L = EXAMPLES.limits;
|
|
6070
6405
|
const matches = this.s(m, "matches", path);
|
|
6071
|
-
const oneOf =
|
|
6072
|
-
const approx = numberOf(
|
|
6073
|
-
const tolerance = numberOf(
|
|
6406
|
+
const oneOf = own3(m, "one_of");
|
|
6407
|
+
const approx = numberOf(own3(m, "approx"));
|
|
6408
|
+
const tolerance = numberOf(own3(m, "tolerance"));
|
|
6074
6409
|
let operators = 0;
|
|
6075
6410
|
if (has(m, "equals")) operators++;
|
|
6076
6411
|
if (this.s(m, "contains", path) !== "") operators++;
|
|
@@ -6078,7 +6413,7 @@ var Walker = class _Walker {
|
|
|
6078
6413
|
if (matches !== "") operators++;
|
|
6079
6414
|
if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
|
|
6080
6415
|
if (approx !== void 0) operators++;
|
|
6081
|
-
if (typeof
|
|
6416
|
+
if (typeof own3(m, "present") === "boolean") operators++;
|
|
6082
6417
|
if (operators !== 1) {
|
|
6083
6418
|
this.err(
|
|
6084
6419
|
"example_field_matcher_invalid",
|
|
@@ -6105,12 +6440,12 @@ var Walker = class _Walker {
|
|
|
6105
6440
|
// -- checkpoints ------------------------------------------------------
|
|
6106
6441
|
validateCheckpoints(path, label, cps) {
|
|
6107
6442
|
if (!isRecord(cps) || Object.keys(cps).length === 0) return;
|
|
6108
|
-
const stepsRaw =
|
|
6443
|
+
const stepsRaw = own3(this.flow, "steps");
|
|
6109
6444
|
const steps = isRecord(stepsRaw) ? stepsRaw : {};
|
|
6110
6445
|
const stepIds = sortedKeys(steps);
|
|
6111
6446
|
for (const id of sortedKeys(cps)) {
|
|
6112
6447
|
const cpath = `${path}.checkpoints.${id}`;
|
|
6113
|
-
const step =
|
|
6448
|
+
const step = own3(steps, id);
|
|
6114
6449
|
if (!isRecord(step)) {
|
|
6115
6450
|
this.err(
|
|
6116
6451
|
"example_checkpoint_step_unknown",
|
|
@@ -6120,7 +6455,7 @@ var Walker = class _Walker {
|
|
|
6120
6455
|
);
|
|
6121
6456
|
continue;
|
|
6122
6457
|
}
|
|
6123
|
-
const next =
|
|
6458
|
+
const next = own3(step, "next");
|
|
6124
6459
|
if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
|
|
6125
6460
|
this.err(
|
|
6126
6461
|
"example_checkpoint_step_composite",
|
|
@@ -6129,7 +6464,7 @@ var Walker = class _Walker {
|
|
|
6129
6464
|
);
|
|
6130
6465
|
continue;
|
|
6131
6466
|
}
|
|
6132
|
-
const cp =
|
|
6467
|
+
const cp = own3(cps, id);
|
|
6133
6468
|
if (cp === null || cp === void 0) {
|
|
6134
6469
|
this.validateExpectation(cpath, label, {}, "checkpoint", id);
|
|
6135
6470
|
} else if (isRecord(cp)) {
|
|
@@ -6140,7 +6475,7 @@ var Walker = class _Walker {
|
|
|
6140
6475
|
// -- variants ---------------------------------------------------------
|
|
6141
6476
|
validateVariants(i, path, label, ex, hasInput, baseInput) {
|
|
6142
6477
|
const L = EXAMPLES.limits;
|
|
6143
|
-
const variants =
|
|
6478
|
+
const variants = own3(ex, "variants");
|
|
6144
6479
|
if (!Array.isArray(variants) || variants.length === 0) return;
|
|
6145
6480
|
if (variants.length > L.maxVariants) {
|
|
6146
6481
|
this.err(
|
|
@@ -6203,8 +6538,8 @@ var Walker = class _Walker {
|
|
|
6203
6538
|
`example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
|
|
6204
6539
|
);
|
|
6205
6540
|
}
|
|
6206
|
-
this.validateWeight(`${vpath}.weight`, both, numberOf(
|
|
6207
|
-
const patch =
|
|
6541
|
+
this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
|
|
6542
|
+
const patch = own3(v, "input_patch");
|
|
6208
6543
|
const patchRec = isRecord(patch) ? patch : null;
|
|
6209
6544
|
const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
|
|
6210
6545
|
const hasRef = has(v, "input_ref");
|
|
@@ -6221,7 +6556,7 @@ var Walker = class _Walker {
|
|
|
6221
6556
|
`variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
|
|
6222
6557
|
);
|
|
6223
6558
|
}
|
|
6224
|
-
const refRec =
|
|
6559
|
+
const refRec = own3(v, "input_ref");
|
|
6225
6560
|
if (isRecord(refRec)) {
|
|
6226
6561
|
this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
|
|
6227
6562
|
}
|
|
@@ -6236,7 +6571,7 @@ var Walker = class _Walker {
|
|
|
6236
6571
|
this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
|
|
6237
6572
|
}
|
|
6238
6573
|
}
|
|
6239
|
-
const expected =
|
|
6574
|
+
const expected = own3(v, "expected");
|
|
6240
6575
|
if (isRecord(expected)) {
|
|
6241
6576
|
this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
|
|
6242
6577
|
}
|
|
@@ -6247,11 +6582,11 @@ var Walker = class _Walker {
|
|
|
6247
6582
|
* itself supplies. A null patch value deleting a secret is fine.
|
|
6248
6583
|
*/
|
|
6249
6584
|
checkVariantPatch(vpath, label, vlabel, base, patch) {
|
|
6250
|
-
const schema =
|
|
6585
|
+
const schema = own3(this.flow, "input_schema");
|
|
6251
6586
|
if (isRecord(schema)) {
|
|
6252
6587
|
for (const f of this.schemaFields(schema)) {
|
|
6253
6588
|
if (f.type !== TYPE_SECRET) continue;
|
|
6254
|
-
const val =
|
|
6589
|
+
const val = own3(patch, f.name);
|
|
6255
6590
|
if (val !== void 0 && val !== null) {
|
|
6256
6591
|
this.err(
|
|
6257
6592
|
"example_secret_value",
|
|
@@ -6291,18 +6626,18 @@ var Walker = class _Walker {
|
|
|
6291
6626
|
emit(`${path}.title`, this.s(ex, "title", path));
|
|
6292
6627
|
emit(`${path}.guidance`, this.s(ex, "guidance", path));
|
|
6293
6628
|
emit(`${path}.notes`, this.s(ex, "notes", path));
|
|
6294
|
-
const input =
|
|
6629
|
+
const input = own3(ex, "input");
|
|
6295
6630
|
if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
|
|
6296
|
-
const expected =
|
|
6631
|
+
const expected = own3(ex, "expected");
|
|
6297
6632
|
if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
|
|
6298
|
-
const cps =
|
|
6633
|
+
const cps = own3(ex, "checkpoints");
|
|
6299
6634
|
if (isRecord(cps)) {
|
|
6300
6635
|
for (const id of sortedKeys(cps)) {
|
|
6301
|
-
const cp =
|
|
6636
|
+
const cp = own3(cps, id);
|
|
6302
6637
|
if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
|
|
6303
6638
|
}
|
|
6304
6639
|
}
|
|
6305
|
-
const variants =
|
|
6640
|
+
const variants = own3(ex, "variants");
|
|
6306
6641
|
if (Array.isArray(variants)) {
|
|
6307
6642
|
variants.forEach((v, j) => {
|
|
6308
6643
|
if (!isRecord(v)) return;
|
|
@@ -6310,34 +6645,34 @@ var Walker = class _Walker {
|
|
|
6310
6645
|
emit(`${vpath}.title`, this.s(v, "title", vpath));
|
|
6311
6646
|
emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
|
|
6312
6647
|
emit(`${vpath}.provenance`, this.s(v, "provenance", vpath));
|
|
6313
|
-
scanLeaves(`${vpath}.input_patch`,
|
|
6314
|
-
const vexp =
|
|
6648
|
+
scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
|
|
6649
|
+
const vexp = own3(v, "expected");
|
|
6315
6650
|
if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
|
|
6316
6651
|
});
|
|
6317
6652
|
}
|
|
6318
6653
|
}
|
|
6319
6654
|
scanExpectationLeaves(path, e, emit) {
|
|
6320
6655
|
emit(`${path}.rubric`, this.s(e, "rubric", path));
|
|
6321
|
-
const reference =
|
|
6656
|
+
const reference = own3(e, "reference");
|
|
6322
6657
|
if (isRecord(reference)) {
|
|
6323
6658
|
emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
|
|
6324
6659
|
}
|
|
6325
|
-
this.stringList(
|
|
6660
|
+
this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
|
|
6326
6661
|
(s, j) => emit(`${path}.must_not[${j}]`, s)
|
|
6327
6662
|
);
|
|
6328
|
-
this.stringList(
|
|
6663
|
+
this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
|
|
6329
6664
|
(s, j) => emit(`${path}.must_not_contain[${j}]`, s)
|
|
6330
6665
|
);
|
|
6331
|
-
const fields =
|
|
6666
|
+
const fields = own3(e, "fields");
|
|
6332
6667
|
if (isRecord(fields)) {
|
|
6333
6668
|
for (const key of sortedKeys(fields)) {
|
|
6334
|
-
const m =
|
|
6669
|
+
const m = own3(fields, key);
|
|
6335
6670
|
if (!isRecord(m)) continue;
|
|
6336
6671
|
const fpath = `${path}.fields.${key}`;
|
|
6337
|
-
scanLeaves(`${fpath}.equals`,
|
|
6672
|
+
scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
|
|
6338
6673
|
emit(`${fpath}.contains`, this.s(m, "contains", fpath));
|
|
6339
6674
|
emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
|
|
6340
|
-
const oneOf =
|
|
6675
|
+
const oneOf = own3(m, "one_of");
|
|
6341
6676
|
if (Array.isArray(oneOf)) {
|
|
6342
6677
|
oneOf.forEach(
|
|
6343
6678
|
(one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
|
|
@@ -6345,7 +6680,7 @@ var Walker = class _Walker {
|
|
|
6345
6680
|
}
|
|
6346
6681
|
}
|
|
6347
6682
|
}
|
|
6348
|
-
scanLeaves(`${path}.exact`,
|
|
6683
|
+
scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
|
|
6349
6684
|
}
|
|
6350
6685
|
};
|
|
6351
6686
|
function scoreInRange(v) {
|
|
@@ -6461,7 +6796,7 @@ function inputValueFailures(f, raw) {
|
|
|
6461
6796
|
case TYPE_FILE2: {
|
|
6462
6797
|
if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
|
|
6463
6798
|
if (isRecord(raw)) {
|
|
6464
|
-
const ref =
|
|
6799
|
+
const ref = own3(raw, FILE_REF_KEY);
|
|
6465
6800
|
return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
|
|
6466
6801
|
}
|
|
6467
6802
|
return [mismatch(f, TYPE_FILE2)];
|
|
@@ -6544,6 +6879,7 @@ function validateParsed(flow, opts, sources) {
|
|
|
6544
6879
|
validateCredentialEndpointPairing(f, issues);
|
|
6545
6880
|
validateExamples(f, issues);
|
|
6546
6881
|
validateOrchestratorExons(f, issues);
|
|
6882
|
+
validateResidencyEnforcement(f, issues);
|
|
6547
6883
|
validateUnknownKeys(f, issues);
|
|
6548
6884
|
const templateStats = validateTemplates(f, issues, opts);
|
|
6549
6885
|
const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;
|