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