@vaudience/aigentflow-flow-validator 0.19.0 → 0.20.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 +73 -35
- package/README.md +2 -2
- package/dist/cli.js +257 -73
- package/dist/index.cjs +256 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +256 -73
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -430,7 +430,7 @@ function validateBasicStructure(flow, issues) {
|
|
|
430
430
|
|
|
431
431
|
// src/spec/aigentflow-spec.json
|
|
432
432
|
var aigentflow_spec_default = {
|
|
433
|
-
specVersion: "2.
|
|
433
|
+
specVersion: "2.821.0",
|
|
434
434
|
inputSchemaVersion: 1,
|
|
435
435
|
executorSchemes: [
|
|
436
436
|
"a2a",
|
|
@@ -1255,6 +1255,34 @@ var aigentflow_spec_default = {
|
|
|
1255
1255
|
}
|
|
1256
1256
|
}
|
|
1257
1257
|
},
|
|
1258
|
+
complianceResidency: {
|
|
1259
|
+
code: "compliance_residency_unenforced",
|
|
1260
|
+
euResidencyCodes: ["EU", "DE", "FR", "IE", "NL", "IT", "ES"],
|
|
1261
|
+
regionLaneProviders: [
|
|
1262
|
+
"bedrock",
|
|
1263
|
+
"google",
|
|
1264
|
+
"azure",
|
|
1265
|
+
"openai",
|
|
1266
|
+
"assemblyai",
|
|
1267
|
+
"speechmatics",
|
|
1268
|
+
"deepgram",
|
|
1269
|
+
"mistral"
|
|
1270
|
+
],
|
|
1271
|
+
aiProtocol: "ai",
|
|
1272
|
+
protocolSeparator: "://",
|
|
1273
|
+
regionParam: "region",
|
|
1274
|
+
enforceRegionParam: "enforce_region",
|
|
1275
|
+
baseUrlParamSuffix: "_base_url",
|
|
1276
|
+
enforceRegionTrueStrings: ["true", "1", "yes"],
|
|
1277
|
+
stepFieldFormat: "steps.%s.executor",
|
|
1278
|
+
loopStepFieldFormat: "steps.%s.loop.steps.%s.executor",
|
|
1279
|
+
orchestratorField: "orchestrator.exons",
|
|
1280
|
+
siteStepFormat: "step %q",
|
|
1281
|
+
siteLoopStepFormat: "loop sub-step %q of step %q",
|
|
1282
|
+
siteOrchestrator: "the orchestrator",
|
|
1283
|
+
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",
|
|
1284
|
+
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."
|
|
1285
|
+
},
|
|
1258
1286
|
examples: {
|
|
1259
1287
|
limits: {
|
|
1260
1288
|
maxPerFlow: 50,
|
|
@@ -1850,6 +1878,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
|
|
|
1850
1878
|
familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
|
|
1851
1879
|
families: aigentflow_spec_default.credentialEndpointPairing.families
|
|
1852
1880
|
};
|
|
1881
|
+
var COMPLIANCE_RESIDENCY = {
|
|
1882
|
+
code: aigentflow_spec_default.complianceResidency.code,
|
|
1883
|
+
euResidencyCodes: aigentflow_spec_default.complianceResidency.euResidencyCodes,
|
|
1884
|
+
regionLaneProviders: aigentflow_spec_default.complianceResidency.regionLaneProviders,
|
|
1885
|
+
aiProtocol: aigentflow_spec_default.complianceResidency.aiProtocol,
|
|
1886
|
+
protocolSeparator: aigentflow_spec_default.complianceResidency.protocolSeparator,
|
|
1887
|
+
regionParam: aigentflow_spec_default.complianceResidency.regionParam,
|
|
1888
|
+
enforceRegionParam: aigentflow_spec_default.complianceResidency.enforceRegionParam,
|
|
1889
|
+
baseUrlParamSuffix: aigentflow_spec_default.complianceResidency.baseUrlParamSuffix,
|
|
1890
|
+
enforceRegionTrueStrings: aigentflow_spec_default.complianceResidency.enforceRegionTrueStrings,
|
|
1891
|
+
stepFieldFormat: aigentflow_spec_default.complianceResidency.stepFieldFormat,
|
|
1892
|
+
loopStepFieldFormat: aigentflow_spec_default.complianceResidency.loopStepFieldFormat,
|
|
1893
|
+
orchestratorField: aigentflow_spec_default.complianceResidency.orchestratorField,
|
|
1894
|
+
siteStepFormat: aigentflow_spec_default.complianceResidency.siteStepFormat,
|
|
1895
|
+
siteLoopStepFormat: aigentflow_spec_default.complianceResidency.siteLoopStepFormat,
|
|
1896
|
+
siteOrchestrator: aigentflow_spec_default.complianceResidency.siteOrchestrator,
|
|
1897
|
+
messageFormat: aigentflow_spec_default.complianceResidency.messageFormat,
|
|
1898
|
+
suggestion: aigentflow_spec_default.complianceResidency.suggestion
|
|
1899
|
+
};
|
|
1853
1900
|
var EXAMPLES = {
|
|
1854
1901
|
limits: aigentflow_spec_default.examples.limits,
|
|
1855
1902
|
idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
|
|
@@ -5202,6 +5249,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
|
|
|
5202
5249
|
}
|
|
5203
5250
|
}
|
|
5204
5251
|
|
|
5252
|
+
// src/validators/complianceResidency.ts
|
|
5253
|
+
function own2(m, key) {
|
|
5254
|
+
if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
|
|
5255
|
+
return m[key];
|
|
5256
|
+
}
|
|
5257
|
+
function sprintf(format, ...args) {
|
|
5258
|
+
let i = 0;
|
|
5259
|
+
return format.replace(/%[sqv]/g, (verb) => {
|
|
5260
|
+
const arg = args[i++] ?? "";
|
|
5261
|
+
return verb === "%q" ? JSON.stringify(arg) : arg;
|
|
5262
|
+
});
|
|
5263
|
+
}
|
|
5264
|
+
function literalOrEmpty(s) {
|
|
5265
|
+
const t = goTrimSpace2(s);
|
|
5266
|
+
return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
|
|
5267
|
+
}
|
|
5268
|
+
function euOnlyResidency(flow, issues) {
|
|
5269
|
+
const raw = own2(own2(flow, "compliance"), "residency");
|
|
5270
|
+
if (!isArray(raw)) return null;
|
|
5271
|
+
const codes = [];
|
|
5272
|
+
for (let i = 0; i < raw.length; i++) {
|
|
5273
|
+
if (raw[i] === null) continue;
|
|
5274
|
+
const code = issues.stringAt(raw[i], `compliance.residency[${i}]`);
|
|
5275
|
+
if (code === null) return null;
|
|
5276
|
+
codes.push(code);
|
|
5277
|
+
}
|
|
5278
|
+
if (codes.length === 0) return null;
|
|
5279
|
+
const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
|
|
5280
|
+
return codes.every((c) => eu.has(goTrimSpace2(c).toUpperCase())) ? codes : null;
|
|
5281
|
+
}
|
|
5282
|
+
function aiProvider(executor) {
|
|
5283
|
+
const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
|
|
5284
|
+
if (!executor.startsWith(prefix)) return "";
|
|
5285
|
+
const rest = executor.slice(prefix.length);
|
|
5286
|
+
const slash = rest.indexOf("/");
|
|
5287
|
+
const provider = slash > 0 ? rest.slice(0, slash) : "";
|
|
5288
|
+
return provider.includes(TEMPLATE_ACTION_OPEN) ? "" : provider;
|
|
5289
|
+
}
|
|
5290
|
+
function isRegionLane(provider) {
|
|
5291
|
+
const literal = literalOrEmpty(provider);
|
|
5292
|
+
return literal !== "" && COMPLIANCE_RESIDENCY.regionLaneProviders.includes(literal.toLowerCase());
|
|
5293
|
+
}
|
|
5294
|
+
function nonBlankString(m, key) {
|
|
5295
|
+
const v = own2(m, key);
|
|
5296
|
+
return typeof v === "string" && goTrimSpace2(v) !== "";
|
|
5297
|
+
}
|
|
5298
|
+
function queryEnforcesRegion(query) {
|
|
5299
|
+
const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
|
|
5300
|
+
if (typeof v === "boolean") return v;
|
|
5301
|
+
return typeof v === "string" && COMPLIANCE_RESIDENCY.enforceRegionTrueStrings.includes(v);
|
|
5302
|
+
}
|
|
5303
|
+
function flowDirectsEndpoint(flow, provider, issues) {
|
|
5304
|
+
const key = provider.toLowerCase();
|
|
5305
|
+
const inst = own2(own2(flow, "executor_config"), key);
|
|
5306
|
+
if (!isRecord(inst)) return false;
|
|
5307
|
+
const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
|
|
5308
|
+
return baseUrl !== null && goTrimSpace2(baseUrl) !== "";
|
|
5309
|
+
}
|
|
5310
|
+
function callPinsEndpoint(flow, provider, query, issues) {
|
|
5311
|
+
if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
|
|
5312
|
+
if (queryEnforcesRegion(query)) return true;
|
|
5313
|
+
if (nonBlankString(query, provider.toLowerCase() + COMPLIANCE_RESIDENCY.baseUrlParamSuffix)) return true;
|
|
5314
|
+
return flowDirectsEndpoint(flow, provider, issues);
|
|
5315
|
+
}
|
|
5316
|
+
function validateResidencyEnforcement(flow, issues) {
|
|
5317
|
+
const residency = euOnlyResidency(flow, issues);
|
|
5318
|
+
if (residency === null) return;
|
|
5319
|
+
const warn = (site, field, stepId, provider) => {
|
|
5320
|
+
issues.warn({
|
|
5321
|
+
field,
|
|
5322
|
+
...stepId === void 0 ? {} : { stepId },
|
|
5323
|
+
code: COMPLIANCE_RESIDENCY.code,
|
|
5324
|
+
message: sprintf(COMPLIANCE_RESIDENCY.messageFormat, site, provider, `[${residency.join(" ")}]`),
|
|
5325
|
+
suggestion: COMPLIANCE_RESIDENCY.suggestion
|
|
5326
|
+
});
|
|
5327
|
+
};
|
|
5328
|
+
const steps = flow.steps;
|
|
5329
|
+
if (isRecord(steps)) {
|
|
5330
|
+
for (const stepId of Object.keys(steps).sort()) {
|
|
5331
|
+
const step = steps[stepId];
|
|
5332
|
+
if (!isRecord(step)) continue;
|
|
5333
|
+
const calls = [
|
|
5334
|
+
{
|
|
5335
|
+
executor: issues.stringOf(step, "executor", `steps.${stepId}`) ?? "",
|
|
5336
|
+
query: own2(step, "query"),
|
|
5337
|
+
subId: null
|
|
5338
|
+
}
|
|
5339
|
+
];
|
|
5340
|
+
for (const sub of loopSubStepsOfStep(stepId, step)) {
|
|
5341
|
+
calls.push({
|
|
5342
|
+
executor: issues.stringOf(sub.raw, "executor", sub.basePath) ?? "",
|
|
5343
|
+
query: own2(sub.raw, "query"),
|
|
5344
|
+
subId: issues.stringOf(sub.raw, "id", sub.basePath) ?? ""
|
|
5345
|
+
});
|
|
5346
|
+
}
|
|
5347
|
+
for (const call of calls) {
|
|
5348
|
+
const provider = aiProvider(call.executor);
|
|
5349
|
+
if (!isRegionLane(provider)) continue;
|
|
5350
|
+
if (callPinsEndpoint(flow, provider, call.query, issues)) continue;
|
|
5351
|
+
if (call.subId === null) {
|
|
5352
|
+
warn(
|
|
5353
|
+
sprintf(COMPLIANCE_RESIDENCY.siteStepFormat, stepId),
|
|
5354
|
+
sprintf(COMPLIANCE_RESIDENCY.stepFieldFormat, stepId),
|
|
5355
|
+
stepId,
|
|
5356
|
+
provider
|
|
5357
|
+
);
|
|
5358
|
+
} else {
|
|
5359
|
+
warn(
|
|
5360
|
+
sprintf(COMPLIANCE_RESIDENCY.siteLoopStepFormat, call.subId, stepId),
|
|
5361
|
+
sprintf(COMPLIANCE_RESIDENCY.loopStepFieldFormat, stepId, call.subId),
|
|
5362
|
+
stepId,
|
|
5363
|
+
provider
|
|
5364
|
+
);
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
}
|
|
5368
|
+
}
|
|
5369
|
+
warnOrchestrator(flow, issues, warn);
|
|
5370
|
+
}
|
|
5371
|
+
function warnOrchestrator(flow, issues, warn) {
|
|
5372
|
+
const orch = flow.orchestrator;
|
|
5373
|
+
if (!isRecord(orch)) return;
|
|
5374
|
+
const source = issues.stringOf(orch, "exons", "orchestrator");
|
|
5375
|
+
if (source === null || source === "") return;
|
|
5376
|
+
const report = inspectExonsFrontmatter(source);
|
|
5377
|
+
if (report.parseError !== null || !report.specRead || !report.hasSpec) return;
|
|
5378
|
+
const provider = literalOrEmpty(report.provider);
|
|
5379
|
+
if (!isRegionLane(provider)) return;
|
|
5380
|
+
const region = issues.stringOf(orch, "region", "orchestrator");
|
|
5381
|
+
if (region !== null && goTrimSpace2(region) !== "") return;
|
|
5382
|
+
if (orch.enforce_region === true) return;
|
|
5383
|
+
if (flowDirectsEndpoint(flow, provider, issues)) return;
|
|
5384
|
+
warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
|
|
5385
|
+
}
|
|
5386
|
+
|
|
5205
5387
|
// src/validators/examples.ts
|
|
5206
5388
|
var KEY_EXAMPLES = "examples";
|
|
5207
5389
|
var VISIBILITY_PUBLIC = "public";
|
|
@@ -5279,7 +5461,7 @@ function num(n) {
|
|
|
5279
5461
|
function has(o, key) {
|
|
5280
5462
|
return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
|
|
5281
5463
|
}
|
|
5282
|
-
function
|
|
5464
|
+
function own3(o, key) {
|
|
5283
5465
|
return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
|
|
5284
5466
|
}
|
|
5285
5467
|
function setOwn(o, key, value) {
|
|
@@ -5331,7 +5513,7 @@ function mergePatch(target, patch, depth) {
|
|
|
5331
5513
|
continue;
|
|
5332
5514
|
}
|
|
5333
5515
|
if (isRecord(pv)) {
|
|
5334
|
-
const current =
|
|
5516
|
+
const current = own3(target, k);
|
|
5335
5517
|
const existing = isRecord(current) ? deepCopy(current, 0) : {};
|
|
5336
5518
|
mergePatch(existing, pv, depth + 1);
|
|
5337
5519
|
setOwn(target, k, existing);
|
|
@@ -5351,7 +5533,7 @@ function asFileRef(v) {
|
|
|
5351
5533
|
if (keys.length === 0) return null;
|
|
5352
5534
|
for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
|
|
5353
5535
|
const str = (k) => {
|
|
5354
|
-
const x =
|
|
5536
|
+
const x = own3(v, k);
|
|
5355
5537
|
return typeof x === "string" ? x : "";
|
|
5356
5538
|
};
|
|
5357
5539
|
return {
|
|
@@ -5419,7 +5601,7 @@ var Walker = class _Walker {
|
|
|
5419
5601
|
`the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
|
|
5420
5602
|
);
|
|
5421
5603
|
}
|
|
5422
|
-
const allHeld = examples.every((e) => isRecord(e) &&
|
|
5604
|
+
const allHeld = examples.every((e) => isRecord(e) && own3(e, "hold_out") === true);
|
|
5423
5605
|
if (allHeld) {
|
|
5424
5606
|
this.warn(
|
|
5425
5607
|
"examples_all_held_out",
|
|
@@ -5507,9 +5689,9 @@ var Walker = class _Walker {
|
|
|
5507
5689
|
`example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
|
|
5508
5690
|
);
|
|
5509
5691
|
}
|
|
5510
|
-
this.validateTags(path, label,
|
|
5511
|
-
this.validateWeight(`${path}.weight`, label, numberOf(
|
|
5512
|
-
const minScore = numberOf(
|
|
5692
|
+
this.validateTags(path, label, own3(ex, "tags"));
|
|
5693
|
+
this.validateWeight(`${path}.weight`, label, numberOf(own3(ex, "weight")));
|
|
5694
|
+
const minScore = numberOf(own3(ex, "min_score"));
|
|
5513
5695
|
if (minScore !== void 0 && !scoreInRange(minScore)) {
|
|
5514
5696
|
this.err(
|
|
5515
5697
|
"example_min_score_range",
|
|
@@ -5525,7 +5707,7 @@ var Walker = class _Walker {
|
|
|
5525
5707
|
`example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
|
|
5526
5708
|
);
|
|
5527
5709
|
}
|
|
5528
|
-
const holdOut =
|
|
5710
|
+
const holdOut = own3(ex, "hold_out") === true;
|
|
5529
5711
|
if (holdOut && this.isPublic()) {
|
|
5530
5712
|
this.err(
|
|
5531
5713
|
"example_holdout_in_public_flow",
|
|
@@ -5548,17 +5730,17 @@ var Walker = class _Walker {
|
|
|
5548
5730
|
`example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
|
|
5549
5731
|
);
|
|
5550
5732
|
}
|
|
5551
|
-
const rawInput =
|
|
5733
|
+
const rawInput = own3(ex, "input");
|
|
5552
5734
|
const baseInput = isRecord(rawInput) ? rawInput : null;
|
|
5553
5735
|
if (baseInput !== null) {
|
|
5554
5736
|
this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
|
|
5555
5737
|
}
|
|
5556
|
-
const rawInputRef =
|
|
5738
|
+
const rawInputRef = own3(ex, "input_ref");
|
|
5557
5739
|
if (isRecord(rawInputRef)) {
|
|
5558
5740
|
this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
|
|
5559
5741
|
}
|
|
5560
5742
|
let binaryOnly = false;
|
|
5561
|
-
const expected =
|
|
5743
|
+
const expected = own3(ex, "expected");
|
|
5562
5744
|
if (!has(ex, "expected")) {
|
|
5563
5745
|
this.err(
|
|
5564
5746
|
"example_expected_missing",
|
|
@@ -5577,7 +5759,7 @@ var Walker = class _Walker {
|
|
|
5577
5759
|
"this example can be run but not scored"
|
|
5578
5760
|
);
|
|
5579
5761
|
}
|
|
5580
|
-
this.validateCheckpoints(path, label,
|
|
5762
|
+
this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
|
|
5581
5763
|
this.validateVariants(i, path, label, ex, hasInput, baseInput);
|
|
5582
5764
|
this.scanSecretLike(i, path, ex);
|
|
5583
5765
|
}
|
|
@@ -5637,8 +5819,8 @@ var Walker = class _Walker {
|
|
|
5637
5819
|
);
|
|
5638
5820
|
return;
|
|
5639
5821
|
}
|
|
5640
|
-
const schema =
|
|
5641
|
-
const query =
|
|
5822
|
+
const schema = own3(this.flow, "input_schema");
|
|
5823
|
+
const query = own3(this.flow, "query");
|
|
5642
5824
|
if (isRecord(schema)) {
|
|
5643
5825
|
this.checkInputAgainstSchema(field, label, input, schema, code);
|
|
5644
5826
|
} else if (isRecord(query) && Object.keys(query).length > 0) {
|
|
@@ -5706,29 +5888,29 @@ var Walker = class _Walker {
|
|
|
5706
5888
|
}
|
|
5707
5889
|
}
|
|
5708
5890
|
schemaFields(schema) {
|
|
5709
|
-
const raw =
|
|
5891
|
+
const raw = own3(schema, "fields");
|
|
5710
5892
|
if (!Array.isArray(raw)) return [];
|
|
5711
5893
|
const out = [];
|
|
5712
5894
|
raw.forEach((f, i) => {
|
|
5713
5895
|
if (!isRecord(f)) return;
|
|
5714
5896
|
const base = `input_schema.fields[${i}]`;
|
|
5715
|
-
const enumRaw =
|
|
5897
|
+
const enumRaw = own3(f, "enum");
|
|
5716
5898
|
const enumValues = [];
|
|
5717
5899
|
if (Array.isArray(enumRaw)) {
|
|
5718
5900
|
enumRaw.forEach((e, j) => {
|
|
5719
5901
|
enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
|
|
5720
5902
|
});
|
|
5721
5903
|
}
|
|
5722
|
-
const vw =
|
|
5904
|
+
const vw = own3(f, "visible_when");
|
|
5723
5905
|
out.push({
|
|
5724
5906
|
name: this.s(f, "name", base),
|
|
5725
5907
|
type: this.s(f, "type", base),
|
|
5726
|
-
required:
|
|
5908
|
+
required: own3(f, "required") === true,
|
|
5727
5909
|
enumValues,
|
|
5728
5910
|
visibleWhen: isRecord(vw) ? {
|
|
5729
5911
|
field: this.s(vw, "field", `${base}.visible_when`),
|
|
5730
|
-
equals:
|
|
5731
|
-
in: Array.isArray(
|
|
5912
|
+
equals: own3(vw, "equals"),
|
|
5913
|
+
in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
|
|
5732
5914
|
} : null
|
|
5733
5915
|
});
|
|
5734
5916
|
});
|
|
@@ -5739,7 +5921,7 @@ var Walker = class _Walker {
|
|
|
5739
5921
|
const failures = [];
|
|
5740
5922
|
for (const f of fields) {
|
|
5741
5923
|
if (!isVisible(f, runInput)) continue;
|
|
5742
|
-
const raw =
|
|
5924
|
+
const raw = own3(runInput, f.name);
|
|
5743
5925
|
if (raw === void 0 || raw === null) {
|
|
5744
5926
|
if (f.required) {
|
|
5745
5927
|
failures.push({
|
|
@@ -5850,7 +6032,7 @@ var Walker = class _Walker {
|
|
|
5850
6032
|
/** The names `fields` / `exact` may use, and whether such a list is declared at all. */
|
|
5851
6033
|
outputNamesFor(kind, stepId) {
|
|
5852
6034
|
if (kind === "final") {
|
|
5853
|
-
const out =
|
|
6035
|
+
const out = own3(this.flow, "output");
|
|
5854
6036
|
const names2 = [];
|
|
5855
6037
|
if (Array.isArray(out)) {
|
|
5856
6038
|
out.forEach((item, i) => {
|
|
@@ -5859,10 +6041,10 @@ var Walker = class _Walker {
|
|
|
5859
6041
|
}
|
|
5860
6042
|
return { names: names2, declared: names2.length > 0 };
|
|
5861
6043
|
}
|
|
5862
|
-
const steps =
|
|
5863
|
-
const step = isRecord(steps) ?
|
|
5864
|
-
const schema = isRecord(step) ?
|
|
5865
|
-
const fields = isRecord(schema) ?
|
|
6044
|
+
const steps = own3(this.flow, "steps");
|
|
6045
|
+
const step = isRecord(steps) ? own3(steps, stepId) : void 0;
|
|
6046
|
+
const schema = isRecord(step) ? own3(step, "output_schema") : void 0;
|
|
6047
|
+
const fields = isRecord(schema) ? own3(schema, "fields") : void 0;
|
|
5866
6048
|
if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
|
|
5867
6049
|
const names = [];
|
|
5868
6050
|
fields.forEach((f, i) => {
|
|
@@ -5881,8 +6063,8 @@ var Walker = class _Walker {
|
|
|
5881
6063
|
);
|
|
5882
6064
|
}
|
|
5883
6065
|
const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
|
|
5884
|
-
const fieldsRec =
|
|
5885
|
-
const exactRec =
|
|
6066
|
+
const fieldsRec = own3(e, "fields");
|
|
6067
|
+
const exactRec = own3(e, "exact");
|
|
5886
6068
|
const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
|
|
5887
6069
|
const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
|
|
5888
6070
|
const hasFields = fieldKeys.length > 0;
|
|
@@ -5900,7 +6082,7 @@ var Walker = class _Walker {
|
|
|
5900
6082
|
`a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
|
|
5901
6083
|
);
|
|
5902
6084
|
}
|
|
5903
|
-
const minScore = numberOf(
|
|
6085
|
+
const minScore = numberOf(own3(e, "min_score"));
|
|
5904
6086
|
if (minScore !== void 0 && !scoreInRange(minScore)) {
|
|
5905
6087
|
this.err(
|
|
5906
6088
|
"example_min_score_range",
|
|
@@ -5927,7 +6109,7 @@ var Walker = class _Walker {
|
|
|
5927
6109
|
}
|
|
5928
6110
|
}
|
|
5929
6111
|
}
|
|
5930
|
-
const reference =
|
|
6112
|
+
const reference = own3(e, "reference");
|
|
5931
6113
|
if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
|
|
5932
6114
|
const { names, declared } = this.outputNamesFor(kind, stepId);
|
|
5933
6115
|
const checkKey = (field, key) => {
|
|
@@ -5954,12 +6136,12 @@ var Walker = class _Walker {
|
|
|
5954
6136
|
for (const key of fieldKeys) {
|
|
5955
6137
|
const fpath = `${path}.fields.${key}`;
|
|
5956
6138
|
checkKey(fpath, key);
|
|
5957
|
-
const matcher =
|
|
6139
|
+
const matcher = own3(fieldsRec, key);
|
|
5958
6140
|
if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
|
|
5959
6141
|
}
|
|
5960
6142
|
for (const key of exactKeys) checkKey(`${path}.exact.${key}`, key);
|
|
5961
|
-
const mustNot = this.stringList(
|
|
5962
|
-
const mustNotContain = this.stringList(
|
|
6143
|
+
const mustNot = this.stringList(own3(e, "must_not"), `${path}.must_not`);
|
|
6144
|
+
const mustNotContain = this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`);
|
|
5963
6145
|
const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
|
|
5964
6146
|
if (mustNot.length > L.maxMustNot) {
|
|
5965
6147
|
this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
|
|
@@ -5980,9 +6162,9 @@ var Walker = class _Walker {
|
|
|
5980
6162
|
}
|
|
5981
6163
|
});
|
|
5982
6164
|
for (const key of fieldKeys) {
|
|
5983
|
-
const matcher =
|
|
6165
|
+
const matcher = own3(fieldsRec, key);
|
|
5984
6166
|
if (!isRecord(matcher)) continue;
|
|
5985
|
-
const eq =
|
|
6167
|
+
const eq = own3(matcher, "equals");
|
|
5986
6168
|
if (typeof eq !== "string" || eq === "") continue;
|
|
5987
6169
|
for (const banned of mustNotContain) {
|
|
5988
6170
|
if (banned !== "" && equalFold(banned, eq)) {
|
|
@@ -6042,7 +6224,7 @@ var Walker = class _Walker {
|
|
|
6042
6224
|
}
|
|
6043
6225
|
return;
|
|
6044
6226
|
}
|
|
6045
|
-
const refRec =
|
|
6227
|
+
const refRec = own3(r, "ref");
|
|
6046
6228
|
if (!isRecord(refRec)) return;
|
|
6047
6229
|
const ref = this.fileRefOf(refRec, `${path}.ref`);
|
|
6048
6230
|
this.validateFileRef(`${path}.ref`, ref);
|
|
@@ -6055,22 +6237,22 @@ var Walker = class _Walker {
|
|
|
6055
6237
|
}
|
|
6056
6238
|
}
|
|
6057
6239
|
expectationIsBinaryReferenceOnly(e, path) {
|
|
6058
|
-
const reference =
|
|
6059
|
-
const refRec = isRecord(reference) ?
|
|
6240
|
+
const reference = own3(e, "reference");
|
|
6241
|
+
const refRec = isRecord(reference) ? own3(reference, "ref") : void 0;
|
|
6060
6242
|
if (!isRecord(refRec)) return false;
|
|
6061
6243
|
const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
|
|
6062
6244
|
if (mediaType === "" || isTextualMediaType(mediaType)) return false;
|
|
6063
6245
|
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(
|
|
6246
|
+
const fields = own3(e, "fields");
|
|
6247
|
+
const exact = own3(e, "exact");
|
|
6248
|
+
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
6249
|
}
|
|
6068
6250
|
validateFieldMatcher(path, m) {
|
|
6069
6251
|
const L = EXAMPLES.limits;
|
|
6070
6252
|
const matches = this.s(m, "matches", path);
|
|
6071
|
-
const oneOf =
|
|
6072
|
-
const approx = numberOf(
|
|
6073
|
-
const tolerance = numberOf(
|
|
6253
|
+
const oneOf = own3(m, "one_of");
|
|
6254
|
+
const approx = numberOf(own3(m, "approx"));
|
|
6255
|
+
const tolerance = numberOf(own3(m, "tolerance"));
|
|
6074
6256
|
let operators = 0;
|
|
6075
6257
|
if (has(m, "equals")) operators++;
|
|
6076
6258
|
if (this.s(m, "contains", path) !== "") operators++;
|
|
@@ -6078,7 +6260,7 @@ var Walker = class _Walker {
|
|
|
6078
6260
|
if (matches !== "") operators++;
|
|
6079
6261
|
if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
|
|
6080
6262
|
if (approx !== void 0) operators++;
|
|
6081
|
-
if (typeof
|
|
6263
|
+
if (typeof own3(m, "present") === "boolean") operators++;
|
|
6082
6264
|
if (operators !== 1) {
|
|
6083
6265
|
this.err(
|
|
6084
6266
|
"example_field_matcher_invalid",
|
|
@@ -6105,12 +6287,12 @@ var Walker = class _Walker {
|
|
|
6105
6287
|
// -- checkpoints ------------------------------------------------------
|
|
6106
6288
|
validateCheckpoints(path, label, cps) {
|
|
6107
6289
|
if (!isRecord(cps) || Object.keys(cps).length === 0) return;
|
|
6108
|
-
const stepsRaw =
|
|
6290
|
+
const stepsRaw = own3(this.flow, "steps");
|
|
6109
6291
|
const steps = isRecord(stepsRaw) ? stepsRaw : {};
|
|
6110
6292
|
const stepIds = sortedKeys(steps);
|
|
6111
6293
|
for (const id of sortedKeys(cps)) {
|
|
6112
6294
|
const cpath = `${path}.checkpoints.${id}`;
|
|
6113
|
-
const step =
|
|
6295
|
+
const step = own3(steps, id);
|
|
6114
6296
|
if (!isRecord(step)) {
|
|
6115
6297
|
this.err(
|
|
6116
6298
|
"example_checkpoint_step_unknown",
|
|
@@ -6120,7 +6302,7 @@ var Walker = class _Walker {
|
|
|
6120
6302
|
);
|
|
6121
6303
|
continue;
|
|
6122
6304
|
}
|
|
6123
|
-
const next =
|
|
6305
|
+
const next = own3(step, "next");
|
|
6124
6306
|
if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
|
|
6125
6307
|
this.err(
|
|
6126
6308
|
"example_checkpoint_step_composite",
|
|
@@ -6129,7 +6311,7 @@ var Walker = class _Walker {
|
|
|
6129
6311
|
);
|
|
6130
6312
|
continue;
|
|
6131
6313
|
}
|
|
6132
|
-
const cp =
|
|
6314
|
+
const cp = own3(cps, id);
|
|
6133
6315
|
if (cp === null || cp === void 0) {
|
|
6134
6316
|
this.validateExpectation(cpath, label, {}, "checkpoint", id);
|
|
6135
6317
|
} else if (isRecord(cp)) {
|
|
@@ -6140,7 +6322,7 @@ var Walker = class _Walker {
|
|
|
6140
6322
|
// -- variants ---------------------------------------------------------
|
|
6141
6323
|
validateVariants(i, path, label, ex, hasInput, baseInput) {
|
|
6142
6324
|
const L = EXAMPLES.limits;
|
|
6143
|
-
const variants =
|
|
6325
|
+
const variants = own3(ex, "variants");
|
|
6144
6326
|
if (!Array.isArray(variants) || variants.length === 0) return;
|
|
6145
6327
|
if (variants.length > L.maxVariants) {
|
|
6146
6328
|
this.err(
|
|
@@ -6203,8 +6385,8 @@ var Walker = class _Walker {
|
|
|
6203
6385
|
`example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
|
|
6204
6386
|
);
|
|
6205
6387
|
}
|
|
6206
|
-
this.validateWeight(`${vpath}.weight`, both, numberOf(
|
|
6207
|
-
const patch =
|
|
6388
|
+
this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
|
|
6389
|
+
const patch = own3(v, "input_patch");
|
|
6208
6390
|
const patchRec = isRecord(patch) ? patch : null;
|
|
6209
6391
|
const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
|
|
6210
6392
|
const hasRef = has(v, "input_ref");
|
|
@@ -6221,7 +6403,7 @@ var Walker = class _Walker {
|
|
|
6221
6403
|
`variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
|
|
6222
6404
|
);
|
|
6223
6405
|
}
|
|
6224
|
-
const refRec =
|
|
6406
|
+
const refRec = own3(v, "input_ref");
|
|
6225
6407
|
if (isRecord(refRec)) {
|
|
6226
6408
|
this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
|
|
6227
6409
|
}
|
|
@@ -6236,7 +6418,7 @@ var Walker = class _Walker {
|
|
|
6236
6418
|
this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
|
|
6237
6419
|
}
|
|
6238
6420
|
}
|
|
6239
|
-
const expected =
|
|
6421
|
+
const expected = own3(v, "expected");
|
|
6240
6422
|
if (isRecord(expected)) {
|
|
6241
6423
|
this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
|
|
6242
6424
|
}
|
|
@@ -6247,11 +6429,11 @@ var Walker = class _Walker {
|
|
|
6247
6429
|
* itself supplies. A null patch value deleting a secret is fine.
|
|
6248
6430
|
*/
|
|
6249
6431
|
checkVariantPatch(vpath, label, vlabel, base, patch) {
|
|
6250
|
-
const schema =
|
|
6432
|
+
const schema = own3(this.flow, "input_schema");
|
|
6251
6433
|
if (isRecord(schema)) {
|
|
6252
6434
|
for (const f of this.schemaFields(schema)) {
|
|
6253
6435
|
if (f.type !== TYPE_SECRET) continue;
|
|
6254
|
-
const val =
|
|
6436
|
+
const val = own3(patch, f.name);
|
|
6255
6437
|
if (val !== void 0 && val !== null) {
|
|
6256
6438
|
this.err(
|
|
6257
6439
|
"example_secret_value",
|
|
@@ -6291,18 +6473,18 @@ var Walker = class _Walker {
|
|
|
6291
6473
|
emit(`${path}.title`, this.s(ex, "title", path));
|
|
6292
6474
|
emit(`${path}.guidance`, this.s(ex, "guidance", path));
|
|
6293
6475
|
emit(`${path}.notes`, this.s(ex, "notes", path));
|
|
6294
|
-
const input =
|
|
6476
|
+
const input = own3(ex, "input");
|
|
6295
6477
|
if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
|
|
6296
|
-
const expected =
|
|
6478
|
+
const expected = own3(ex, "expected");
|
|
6297
6479
|
if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
|
|
6298
|
-
const cps =
|
|
6480
|
+
const cps = own3(ex, "checkpoints");
|
|
6299
6481
|
if (isRecord(cps)) {
|
|
6300
6482
|
for (const id of sortedKeys(cps)) {
|
|
6301
|
-
const cp =
|
|
6483
|
+
const cp = own3(cps, id);
|
|
6302
6484
|
if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
|
|
6303
6485
|
}
|
|
6304
6486
|
}
|
|
6305
|
-
const variants =
|
|
6487
|
+
const variants = own3(ex, "variants");
|
|
6306
6488
|
if (Array.isArray(variants)) {
|
|
6307
6489
|
variants.forEach((v, j) => {
|
|
6308
6490
|
if (!isRecord(v)) return;
|
|
@@ -6310,34 +6492,34 @@ var Walker = class _Walker {
|
|
|
6310
6492
|
emit(`${vpath}.title`, this.s(v, "title", vpath));
|
|
6311
6493
|
emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
|
|
6312
6494
|
emit(`${vpath}.provenance`, this.s(v, "provenance", vpath));
|
|
6313
|
-
scanLeaves(`${vpath}.input_patch`,
|
|
6314
|
-
const vexp =
|
|
6495
|
+
scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
|
|
6496
|
+
const vexp = own3(v, "expected");
|
|
6315
6497
|
if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
|
|
6316
6498
|
});
|
|
6317
6499
|
}
|
|
6318
6500
|
}
|
|
6319
6501
|
scanExpectationLeaves(path, e, emit) {
|
|
6320
6502
|
emit(`${path}.rubric`, this.s(e, "rubric", path));
|
|
6321
|
-
const reference =
|
|
6503
|
+
const reference = own3(e, "reference");
|
|
6322
6504
|
if (isRecord(reference)) {
|
|
6323
6505
|
emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
|
|
6324
6506
|
}
|
|
6325
|
-
this.stringList(
|
|
6507
|
+
this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
|
|
6326
6508
|
(s, j) => emit(`${path}.must_not[${j}]`, s)
|
|
6327
6509
|
);
|
|
6328
|
-
this.stringList(
|
|
6510
|
+
this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
|
|
6329
6511
|
(s, j) => emit(`${path}.must_not_contain[${j}]`, s)
|
|
6330
6512
|
);
|
|
6331
|
-
const fields =
|
|
6513
|
+
const fields = own3(e, "fields");
|
|
6332
6514
|
if (isRecord(fields)) {
|
|
6333
6515
|
for (const key of sortedKeys(fields)) {
|
|
6334
|
-
const m =
|
|
6516
|
+
const m = own3(fields, key);
|
|
6335
6517
|
if (!isRecord(m)) continue;
|
|
6336
6518
|
const fpath = `${path}.fields.${key}`;
|
|
6337
|
-
scanLeaves(`${fpath}.equals`,
|
|
6519
|
+
scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
|
|
6338
6520
|
emit(`${fpath}.contains`, this.s(m, "contains", fpath));
|
|
6339
6521
|
emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
|
|
6340
|
-
const oneOf =
|
|
6522
|
+
const oneOf = own3(m, "one_of");
|
|
6341
6523
|
if (Array.isArray(oneOf)) {
|
|
6342
6524
|
oneOf.forEach(
|
|
6343
6525
|
(one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
|
|
@@ -6345,7 +6527,7 @@ var Walker = class _Walker {
|
|
|
6345
6527
|
}
|
|
6346
6528
|
}
|
|
6347
6529
|
}
|
|
6348
|
-
scanLeaves(`${path}.exact`,
|
|
6530
|
+
scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
|
|
6349
6531
|
}
|
|
6350
6532
|
};
|
|
6351
6533
|
function scoreInRange(v) {
|
|
@@ -6461,7 +6643,7 @@ function inputValueFailures(f, raw) {
|
|
|
6461
6643
|
case TYPE_FILE2: {
|
|
6462
6644
|
if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
|
|
6463
6645
|
if (isRecord(raw)) {
|
|
6464
|
-
const ref =
|
|
6646
|
+
const ref = own3(raw, FILE_REF_KEY);
|
|
6465
6647
|
return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
|
|
6466
6648
|
}
|
|
6467
6649
|
return [mismatch(f, TYPE_FILE2)];
|
|
@@ -6544,6 +6726,7 @@ function validateParsed(flow, opts, sources) {
|
|
|
6544
6726
|
validateCredentialEndpointPairing(f, issues);
|
|
6545
6727
|
validateExamples(f, issues);
|
|
6546
6728
|
validateOrchestratorExons(f, issues);
|
|
6729
|
+
validateResidencyEnforcement(f, issues);
|
|
6547
6730
|
validateUnknownKeys(f, issues);
|
|
6548
6731
|
const templateStats = validateTemplates(f, issues, opts);
|
|
6549
6732
|
const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;
|