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