@vaudience/aigentflow-flow-validator 0.25.0 → 0.26.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 +37 -0
- package/dist/cli.js +127 -29
- package/dist/index.cjs +125 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +125 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/PARITY.md
CHANGED
|
@@ -6,6 +6,43 @@ discipline for keeping the two in sync.
|
|
|
6
6
|
|
|
7
7
|
**Tracks AIgentFlow flow schema: `v2.831.0`** (`SPEC_VERSION` in [`src/spec/aigentflow-spec.json`](./src/spec/aigentflow-spec.json)), which adds the rule `unknown_function_operation` and a clearer `unknown_executor_scheme` message (package 0.23.0, below). Earlier: the rule `flow_data_key_reserved` (package 0.22.0). Earlier: the `here` executor scheme, the `strict_templates` flow key and the rule `template_default_piped` (package 0.21.0). Earlier: the warning `compliance_residency_unenforced` (package 0.20.0). `orchestrator.region` / `orchestrator.enforce_region` (package 0.19.0). Earlier: the AigentChat executor was removed (package 0.18.0). Earlier additions: the `examples:` block (package 0.17.0), `server_owned_query_key` (package 0.15.1) from the AIgentFlow release after v2.790.0, `credential_endpoint_unpaired` (package 0.15.2) from AIgentFlow v2.793.0 and the release after it, and `display_name_too_long` (package 0.15.3) from AIgentFlow v2.802.0.
|
|
8
8
|
|
|
9
|
+
> package 0.26.0 — **three new rules, and the atlas rules brought in line with the reference.**
|
|
10
|
+
> `reserved_input_name` (error): an input the flow declares under the top-level `query:` map, or as an
|
|
11
|
+
> `input_schema` field name, that starts with two underscores. That namespace belongs to the platform
|
|
12
|
+
> (the acting person, the credential manifest, the untrusted-input marker), and a value or default
|
|
13
|
+
> written under such a name is never delivered. Every name the platform reserves today starts with
|
|
14
|
+
> `__`; one leading underscore (`_private`) or an inner `__` (`a__b`) is an ordinary name. Fields:
|
|
15
|
+
> `query.<name>` (names sorted) and `input_schema.fields.<name>` (file order), no step id. The schema
|
|
16
|
+
> field is addressed by **name**, not by index like this port's other `input_schema` findings, because
|
|
17
|
+
> the reference reports it that way and a host that merges several verdicts drops a finding only when
|
|
18
|
+
> code and field both match. `atlas_model_not_literal` (error): an `atlas://agent/run` step whose
|
|
19
|
+
> `query.model` holds a string containing `{{` anywhere (provider, model, reasoning_effort, or any
|
|
20
|
+
> nested value). The model choice is fixed in the flow, never computed from input.
|
|
21
|
+
> `atlas_param_refused` (error): **one** finding per atlas step listing, sorted, the `query` keys the
|
|
22
|
+
> platform owns. An agent run refuses `api_key`, `attribution`, `base_url`, `host`, `idempotency_key`,
|
|
23
|
+
> `org_id`, `person`, `untrusted_input`, `untrusted_input_override`, `url`, `user_id`; a capability step
|
|
24
|
+
> refuses only `attribution`, `idempotency_key`, `untrusted_input`, `untrusted_input_override` (its
|
|
25
|
+
> query is the tool's own arguments, so a `url` is legitimate there). The key sets live in the spec
|
|
26
|
+
> block `atlasExecutor.paramRefused`; the reserved-name prefix in the new top-level block
|
|
27
|
+
> `reservedInputNames`.
|
|
28
|
+
>
|
|
29
|
+
> _Alignments (the reference is authoritative; the old behaviour was looser)._ `agent`, `prompt` and
|
|
30
|
+
> `prompt_template` are present only when they are non-empty strings **after trimming whitespace**: an
|
|
31
|
+
> `agent` that is not a string (`42`) is missing, `prompt: " "` is absent, and `prompt: ""` next to a
|
|
32
|
+
> `prompt_template` is **not** `atlas_prompt_both`. The `{{` check on `capabilities` is deep (any
|
|
33
|
+
> string entry or nested string) and applies to every `atlas://` step with a valid operation. The
|
|
34
|
+
> capability reference pattern is now `^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$` (a dot or colon is refused).
|
|
35
|
+
> An `atlas://` URL that the shared executor-URL shape refuses is no longer skipped by the atlas
|
|
36
|
+
> rules: it is split at the first slash after `atlas://` and judged (a reference with a dot is
|
|
37
|
+
> `atlas_capability_ref_invalid`, `atlas://agent/run/extra` is `atlas_operation_unknown`); the shape's own
|
|
38
|
+
> `invalid_executor_url` finding is still reported beside it. The scheme match stays exact. The
|
|
39
|
+
> `atlas_agent_missing` message now ends "missing, empty or not a string". `specVersion` is unchanged
|
|
40
|
+
> (`2.831.0`). Modules: `validators/executors.ts`, `validators/reservedInputs.ts`. Gates: thirteen new
|
|
41
|
+
> shared fixtures (one invalid per code, the valid ones forbid every atlas code, `reserved_input_name`
|
|
42
|
+
> and `unknown_executor_scheme`), byte-identical with the Go port, and
|
|
43
|
+
> `test/v0260-atlas-contract.test.ts`. On the 227 bundled example flows plus the six atlas examples,
|
|
44
|
+
> both ports report zero new findings and agree finding for finding (0 errors, 36 warnings).
|
|
45
|
+
|
|
9
46
|
> package 0.25.0 — **the `atlas://` executor scheme and seven rules**. `atlas` becomes a known
|
|
10
47
|
> scheme (no `unknown_executor_scheme` warning). The URL form is `atlas://<provider>/<resource>`:
|
|
11
48
|
> provider `agent` has the single resource `run`, provider `capability` takes a capability reference
|
package/dist/cli.js
CHANGED
|
@@ -1008,12 +1008,12 @@ var aigentflow_spec_default = {
|
|
|
1008
1008
|
]
|
|
1009
1009
|
},
|
|
1010
1010
|
atlasExecutor: {
|
|
1011
|
-
$comment: "atlas://<provider>/<resource>: calls into the Atlas platform. Providers are agent (the one resource is run) and capability (the resource is a capability reference). All findings are ERRORS, field = the step (loop sub-steps use the composite step id and the sub-step path). Templated executors, unparsable URLs and other schemes are skipped. A literal agent and literal capabilities keep a step from being steered by data: query.agent and every string in query.capabilities may not contain templateActionOpen, while prompt, inputs and capability args may. A message format takes the quoted step id first.",
|
|
1011
|
+
$comment: "atlas://<provider>/<resource>: calls into the Atlas platform. Providers are agent (the one resource is run) and capability (the resource is a capability reference). All findings are ERRORS, field = the step (loop sub-steps use the composite step id and the sub-step path). Templated executors, unparsable URLs and other schemes are skipped. A literal agent and literal capabilities keep a step from being steered by data: query.agent and every string anywhere in query.capabilities and query.model may not contain templateActionOpen, while prompt, inputs and capability args may. agent, prompt and prompt_template count as present only when they are non-empty strings after trimming whitespace. A message format takes the quoted step id first. A URL the shared executor-URL shape refuses (a dot or colon in a reference, say) is still judged here, split at the first slash after atlas://.",
|
|
1012
1012
|
scheme: "atlas",
|
|
1013
1013
|
providerAgent: "agent",
|
|
1014
1014
|
providerCapability: "capability",
|
|
1015
1015
|
agentResource: "run",
|
|
1016
|
-
capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_
|
|
1016
|
+
capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$",
|
|
1017
1017
|
operationUnknown: {
|
|
1018
1018
|
code: "atlas_operation_unknown",
|
|
1019
1019
|
messageFormat: "step %s uses %s, which is not an Atlas operation. The providers are agent (resource run) and capability (resource: a capability reference).",
|
|
@@ -1021,7 +1021,7 @@ var aigentflow_spec_default = {
|
|
|
1021
1021
|
},
|
|
1022
1022
|
agentMissing: {
|
|
1023
1023
|
code: "atlas_agent_missing",
|
|
1024
|
-
messageFormat: "step %s runs an Atlas agent but query.agent is missing or
|
|
1024
|
+
messageFormat: "step %s runs an Atlas agent but query.agent is missing, empty or not a string.",
|
|
1025
1025
|
suggestion: "Set query.agent to the agent to run, written out as a literal such as @acme/reporter."
|
|
1026
1026
|
},
|
|
1027
1027
|
agentNotLiteral: {
|
|
@@ -1047,9 +1047,47 @@ var aigentflow_spec_default = {
|
|
|
1047
1047
|
capabilityRefInvalid: {
|
|
1048
1048
|
code: "atlas_capability_ref_invalid",
|
|
1049
1049
|
messageFormat: "step %s uses atlas://capability/%s, which is not a valid capability reference.",
|
|
1050
|
-
suggestion: "A capability reference starts with a letter or digit and continues with letters, digits
|
|
1050
|
+
suggestion: "A capability reference starts with a letter or digit and continues with letters, digits, _ and - up to 128 characters in all."
|
|
1051
|
+
},
|
|
1052
|
+
modelNotLiteral: {
|
|
1053
|
+
code: "atlas_model_not_literal",
|
|
1054
|
+
messageFormat: "step %s computes a value of query.model from a template. The provider, model and reasoning_effort must be fixed literals, never derived from input.",
|
|
1055
|
+
suggestion: "Write the model choice out as literals. Data may go into the prompt or the inputs instead."
|
|
1056
|
+
},
|
|
1057
|
+
paramRefused: {
|
|
1058
|
+
code: "atlas_param_refused",
|
|
1059
|
+
messageFormat: "step %s sets %s under query. Atlas decides these itself, so a step may not set them.",
|
|
1060
|
+
suggestion: "Remove these keys from the query.",
|
|
1061
|
+
agentKeys: [
|
|
1062
|
+
"api_key",
|
|
1063
|
+
"attribution",
|
|
1064
|
+
"base_url",
|
|
1065
|
+
"host",
|
|
1066
|
+
"idempotency_key",
|
|
1067
|
+
"org_id",
|
|
1068
|
+
"person",
|
|
1069
|
+
"untrusted_input",
|
|
1070
|
+
"untrusted_input_override",
|
|
1071
|
+
"url",
|
|
1072
|
+
"user_id"
|
|
1073
|
+
],
|
|
1074
|
+
capabilityKeys: [
|
|
1075
|
+
"attribution",
|
|
1076
|
+
"idempotency_key",
|
|
1077
|
+
"untrusted_input",
|
|
1078
|
+
"untrusted_input_override"
|
|
1079
|
+
]
|
|
1051
1080
|
}
|
|
1052
1081
|
},
|
|
1082
|
+
reservedInputNames: {
|
|
1083
|
+
$comment: "reserved_input_name (ERROR): an input the flow declares under the top-level query: map, or as an input_schema field name, that starts with prefix. The platform keeps that namespace for values it writes itself (the acting person, the credential manifest, the untrusted-input marker); a value or default written under such a name is never delivered. Every name the platform reserves today starts with the prefix. Matching is exact and case-sensitive: one leading underscore is an ordinary name. Findings carry no step id. queryFieldFormat takes the input name; schemaFieldFormat takes the field name as written (a non-string name is skipped). Query names are reported sorted, then schema fields in file order.",
|
|
1084
|
+
prefix: "__",
|
|
1085
|
+
code: "reserved_input_name",
|
|
1086
|
+
messageFormat: "the input %s starts with two underscores. That namespace belongs to the platform (the acting person, the credential manifest, the untrusted-input marker): a flow cannot declare an input there, and a value or default written under such a name is never delivered.",
|
|
1087
|
+
suggestion: 'Rename the input so it does not start with "__".',
|
|
1088
|
+
queryFieldFormat: "query.%s",
|
|
1089
|
+
schemaFieldFormat: "input_schema.fields.%s"
|
|
1090
|
+
},
|
|
1053
1091
|
flowDataReservedKeys: {
|
|
1054
1092
|
$comment: "flow_data_key_reserved (ERROR, no loop demotion): a key of the top-level data: map that names engine state. data: is seeded into the mission's .data namespace, where the engine keeps its own bookkeeping, so a flow declaring such a key would forge it. Matching is exact and case-sensitive. A key is reserved when it is one of exact (each with its reason), or starts with one of prefixes (checked in order, first wins; each with its reason). The finding's field is fieldFormat with the key; the message is messageFormat with the key (JSON-quoted, as Go's %q) then the reason; the suggestion is verbatim. Findings are sorted by key. Reference: FlowDataKeyReservation, validateFlowDataKeysAreNotReserved (aigentflow#247 review).",
|
|
1055
1093
|
code: "flow_data_key_reserved",
|
|
@@ -2186,7 +2224,23 @@ var ATLAS_EXECUTOR = {
|
|
|
2186
2224
|
capabilitiesNotLiteral: atlas.capabilitiesNotLiteral,
|
|
2187
2225
|
promptMissing: atlas.promptMissing,
|
|
2188
2226
|
promptBoth: atlas.promptBoth,
|
|
2189
|
-
capabilityRefInvalid: atlas.capabilityRefInvalid
|
|
2227
|
+
capabilityRefInvalid: atlas.capabilityRefInvalid,
|
|
2228
|
+
modelNotLiteral: atlas.modelNotLiteral,
|
|
2229
|
+
paramRefused: {
|
|
2230
|
+
code: atlas.paramRefused.code,
|
|
2231
|
+
messageFormat: atlas.paramRefused.messageFormat,
|
|
2232
|
+
suggestion: atlas.paramRefused.suggestion,
|
|
2233
|
+
agentKeys: atlas.paramRefused.agentKeys,
|
|
2234
|
+
capabilityKeys: atlas.paramRefused.capabilityKeys
|
|
2235
|
+
}
|
|
2236
|
+
};
|
|
2237
|
+
var RESERVED_INPUT_NAMES = {
|
|
2238
|
+
prefix: aigentflow_spec_default.reservedInputNames.prefix,
|
|
2239
|
+
code: aigentflow_spec_default.reservedInputNames.code,
|
|
2240
|
+
messageFormat: aigentflow_spec_default.reservedInputNames.messageFormat,
|
|
2241
|
+
suggestion: aigentflow_spec_default.reservedInputNames.suggestion,
|
|
2242
|
+
queryFieldFormat: aigentflow_spec_default.reservedInputNames.queryFieldFormat,
|
|
2243
|
+
schemaFieldFormat: aigentflow_spec_default.reservedInputNames.schemaFieldFormat
|
|
2190
2244
|
};
|
|
2191
2245
|
|
|
2192
2246
|
// src/validators/executors.ts
|
|
@@ -2253,10 +2307,12 @@ function checkExecutor(executor, field, stepID, issues) {
|
|
|
2253
2307
|
}
|
|
2254
2308
|
function checkAtlasStep(executor, query, stepField, stepID, issues) {
|
|
2255
2309
|
if (executor.includes(TEMPLATE_ACTION_OPEN)) return;
|
|
2256
|
-
const
|
|
2257
|
-
if (
|
|
2258
|
-
const
|
|
2259
|
-
const
|
|
2310
|
+
const prefix = `${ATLAS_EXECUTOR.scheme}://`;
|
|
2311
|
+
if (!executor.startsWith(prefix)) return;
|
|
2312
|
+
const rest = executor.slice(prefix.length);
|
|
2313
|
+
const slash = rest.indexOf("/");
|
|
2314
|
+
const provider = slash < 0 ? rest : rest.slice(0, slash);
|
|
2315
|
+
const resource = slash < 0 ? "" : rest.slice(slash + 1);
|
|
2260
2316
|
const quoted = JSON.stringify(stepID);
|
|
2261
2317
|
const report = (rule, ...args) => {
|
|
2262
2318
|
let message = rule.messageFormat.replace("%s", () => quoted);
|
|
@@ -2270,31 +2326,41 @@ function checkAtlasStep(executor, query, stepField, stepID, issues) {
|
|
|
2270
2326
|
});
|
|
2271
2327
|
};
|
|
2272
2328
|
const q2 = isRecord(query) ? query : {};
|
|
2329
|
+
let refusedKeys = ATLAS_EXECUTOR.paramRefused.capabilityKeys;
|
|
2273
2330
|
if (provider === ATLAS_EXECUTOR.providerCapability) {
|
|
2274
2331
|
if (!ATLAS_EXECUTOR.capabilityRefPattern.test(resource)) {
|
|
2275
2332
|
report(ATLAS_EXECUTOR.capabilityRefInvalid, resource);
|
|
2276
2333
|
}
|
|
2277
2334
|
} else if (provider === ATLAS_EXECUTOR.providerAgent && resource === ATLAS_EXECUTOR.agentResource) {
|
|
2335
|
+
refusedKeys = ATLAS_EXECUTOR.paramRefused.agentKeys;
|
|
2278
2336
|
const agent = q2.agent;
|
|
2279
|
-
if (typeof agent !== "string" || agent === "") {
|
|
2337
|
+
if (typeof agent !== "string" || agent.trim() === "") {
|
|
2280
2338
|
report(ATLAS_EXECUTOR.agentMissing);
|
|
2281
2339
|
} else if (agent.includes(TEMPLATE_ACTION_OPEN)) {
|
|
2282
2340
|
report(ATLAS_EXECUTOR.agentNotLiteral);
|
|
2283
2341
|
}
|
|
2284
|
-
const
|
|
2285
|
-
const
|
|
2286
|
-
const hasPrompt = prompt !== void 0 && prompt !== null && prompt !== "";
|
|
2287
|
-
const hasTemplate = promptTemplate !== void 0 && promptTemplate !== null && promptTemplate !== "";
|
|
2342
|
+
const hasPrompt = atlasTextPresent(q2.prompt);
|
|
2343
|
+
const hasTemplate = atlasTextPresent(q2.prompt_template);
|
|
2288
2344
|
if (!hasPrompt && !hasTemplate) report(ATLAS_EXECUTOR.promptMissing);
|
|
2289
2345
|
else if (hasPrompt && hasTemplate) report(ATLAS_EXECUTOR.promptBoth);
|
|
2346
|
+
if (anyTemplate(q2.model)) report(ATLAS_EXECUTOR.modelNotLiteral);
|
|
2290
2347
|
} else {
|
|
2291
2348
|
report(ATLAS_EXECUTOR.operationUnknown, executor);
|
|
2292
2349
|
return;
|
|
2293
2350
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2351
|
+
if (anyTemplate(q2.capabilities)) report(ATLAS_EXECUTOR.capabilitiesNotLiteral);
|
|
2352
|
+
const refused = refusedKeys.filter((key) => Object.prototype.hasOwnProperty.call(q2, key)).sort();
|
|
2353
|
+
if (refused.length > 0) report(ATLAS_EXECUTOR.paramRefused, refused.join(", "));
|
|
2354
|
+
}
|
|
2355
|
+
function anyTemplate(v) {
|
|
2356
|
+
if (typeof v === "string") return v.includes(TEMPLATE_ACTION_OPEN);
|
|
2357
|
+
if (Array.isArray(v)) return v.some(anyTemplate);
|
|
2358
|
+
if (isRecord(v)) return Object.values(v).some(anyTemplate);
|
|
2359
|
+
return false;
|
|
2360
|
+
}
|
|
2361
|
+
function atlasTextPresent(v) {
|
|
2362
|
+
if (v === void 0 || v === null) return false;
|
|
2363
|
+
return typeof v !== "string" || v.trim() !== "";
|
|
2298
2364
|
}
|
|
2299
2365
|
function checkFunctionOperation(executor, field, stepID, templated, issues) {
|
|
2300
2366
|
if (templated) return;
|
|
@@ -3980,6 +4046,37 @@ function validateInputSchema(flow, issues) {
|
|
|
3980
4046
|
validateSchemaDefinition(flow.input_schema, "input_schema", issues);
|
|
3981
4047
|
}
|
|
3982
4048
|
|
|
4049
|
+
// src/validators/reservedInputs.ts
|
|
4050
|
+
function formatField(format, name) {
|
|
4051
|
+
return format.replace("%s", () => name);
|
|
4052
|
+
}
|
|
4053
|
+
function validateReservedInputNames(flow, issues) {
|
|
4054
|
+
const rule = RESERVED_INPUT_NAMES;
|
|
4055
|
+
const report = (name, fieldFormat) => {
|
|
4056
|
+
issues.error({
|
|
4057
|
+
field: formatField(fieldFormat, name),
|
|
4058
|
+
message: rule.messageFormat.replace("%s", () => JSON.stringify(name)),
|
|
4059
|
+
code: rule.code,
|
|
4060
|
+
suggestion: rule.suggestion
|
|
4061
|
+
});
|
|
4062
|
+
};
|
|
4063
|
+
const query = flow.query;
|
|
4064
|
+
if (isRecord(query)) {
|
|
4065
|
+
for (const name of Object.keys(query).sort()) {
|
|
4066
|
+
if (name.startsWith(rule.prefix)) report(name, rule.queryFieldFormat);
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
4069
|
+
const schema = flow.input_schema;
|
|
4070
|
+
const fields = isRecord(schema) ? schema.fields : void 0;
|
|
4071
|
+
if (!Array.isArray(fields)) return;
|
|
4072
|
+
for (const f of fields) {
|
|
4073
|
+
if (!isRecord(f)) continue;
|
|
4074
|
+
if (typeof f.name === "string" && f.name.startsWith(rule.prefix)) {
|
|
4075
|
+
report(f.name, rule.schemaFieldFormat);
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
|
|
3983
4080
|
// src/validators/outputSchema.ts
|
|
3984
4081
|
function validateOutputSchemas(flow, issues) {
|
|
3985
4082
|
const steps = flow.steps;
|
|
@@ -5094,7 +5191,7 @@ var CODE2 = "server_owned_query_key";
|
|
|
5094
5191
|
var KEY_QUERY = "query";
|
|
5095
5192
|
var KEY_ID = "id";
|
|
5096
5193
|
var SERVER_OWNED = new Set(SERVER_OWNED_QUERY_KEYS.keys);
|
|
5097
|
-
function
|
|
5194
|
+
function formatField2(format, ...args) {
|
|
5098
5195
|
let i = 0;
|
|
5099
5196
|
return format.replace(/%s/g, () => args[i++] ?? "");
|
|
5100
5197
|
}
|
|
@@ -5112,7 +5209,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
|
|
|
5112
5209
|
issues,
|
|
5113
5210
|
stepID,
|
|
5114
5211
|
key,
|
|
5115
|
-
|
|
5212
|
+
formatField2(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
|
|
5116
5213
|
);
|
|
5117
5214
|
}
|
|
5118
5215
|
}
|
|
@@ -5126,7 +5223,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
|
|
|
5126
5223
|
issues,
|
|
5127
5224
|
stepID,
|
|
5128
5225
|
key,
|
|
5129
|
-
|
|
5226
|
+
formatField2(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
|
|
5130
5227
|
);
|
|
5131
5228
|
}
|
|
5132
5229
|
}
|
|
@@ -5395,7 +5492,7 @@ function own(m, key) {
|
|
|
5395
5492
|
if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
|
|
5396
5493
|
return m[key];
|
|
5397
5494
|
}
|
|
5398
|
-
function
|
|
5495
|
+
function formatField3(format, ...args) {
|
|
5399
5496
|
let i = 0;
|
|
5400
5497
|
return format.replace(/%s/g, () => args[i++] ?? "");
|
|
5401
5498
|
}
|
|
@@ -5417,14 +5514,14 @@ function credentialEndpointSteps(flow, issues) {
|
|
|
5417
5514
|
out.push({
|
|
5418
5515
|
executor: issues.stringOf(step, KEY_EXECUTOR, `steps.${stepId}`) ?? "",
|
|
5419
5516
|
query: own(step, KEY_QUERY2),
|
|
5420
|
-
field: (key) =>
|
|
5517
|
+
field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
|
|
5421
5518
|
});
|
|
5422
5519
|
for (const sub of loopSubStepsOfStep(stepId, step)) {
|
|
5423
5520
|
const subId = issues.stringOf(sub.raw, KEY_ID2, sub.basePath) ?? "";
|
|
5424
5521
|
out.push({
|
|
5425
5522
|
executor: issues.stringOf(sub.raw, KEY_EXECUTOR, sub.basePath) ?? "",
|
|
5426
5523
|
query: own(sub.raw, KEY_QUERY2),
|
|
5427
|
-
field: (key) =>
|
|
5524
|
+
field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
|
|
5428
5525
|
});
|
|
5429
5526
|
}
|
|
5430
5527
|
}
|
|
@@ -5488,7 +5585,7 @@ function validateAI(flow, steps, issues) {
|
|
|
5488
5585
|
if ((stepsUsing.get(provider) ?? 0) > 0 && (stepsWithoutOwnKey.get(provider) ?? 0) === 0) {
|
|
5489
5586
|
continue;
|
|
5490
5587
|
}
|
|
5491
|
-
warnStoredShape(issues,
|
|
5588
|
+
warnStoredShape(issues, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
|
|
5492
5589
|
}
|
|
5493
5590
|
}
|
|
5494
5591
|
function warnStoredShape(issues, field, provider) {
|
|
@@ -5535,7 +5632,7 @@ function familySecret(flow, family, step, issues) {
|
|
|
5535
5632
|
if (apiKey !== "" && listHas(family.secretParams, family.configApiKeyParam)) {
|
|
5536
5633
|
return {
|
|
5537
5634
|
envName: serverEnvRef(family, apiKey),
|
|
5538
|
-
field:
|
|
5635
|
+
field: formatField3(
|
|
5539
5636
|
CREDENTIAL_ENDPOINT_PAIRING.executorConfigKeyFieldFormat,
|
|
5540
5637
|
configKey,
|
|
5541
5638
|
CREDENTIAL_ENDPOINT_PAIRING.executorConfigApiKeyField
|
|
@@ -5548,7 +5645,7 @@ function familySecret(flow, family, step, issues) {
|
|
|
5548
5645
|
if (v !== null) {
|
|
5549
5646
|
return {
|
|
5550
5647
|
envName: serverEnvRef(family, v),
|
|
5551
|
-
field:
|
|
5648
|
+
field: formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
|
|
5552
5649
|
};
|
|
5553
5650
|
}
|
|
5554
5651
|
}
|
|
@@ -5574,13 +5671,13 @@ function familyAuthorEndpoint(flow, family, step, issues) {
|
|
|
5574
5671
|
if (inst === null) continue;
|
|
5575
5672
|
const baseUrl = configStringField(inst, configKey, CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlField, issues);
|
|
5576
5673
|
if (baseUrl !== "" && listHas(family.endpointParams, family.configBaseUrlParam)) {
|
|
5577
|
-
return decide(baseUrl,
|
|
5674
|
+
return decide(baseUrl, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
|
|
5578
5675
|
}
|
|
5579
5676
|
const extra = own(inst, EXECUTOR_CONFIG_ENV_SCOPES.extraKey);
|
|
5580
5677
|
for (const key of family.endpointParams) {
|
|
5581
5678
|
const v = nonEmptyEndpoint(extra, key);
|
|
5582
5679
|
if (v !== null)
|
|
5583
|
-
return decide(v,
|
|
5680
|
+
return decide(v, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
|
|
5584
5681
|
}
|
|
5585
5682
|
}
|
|
5586
5683
|
return null;
|
|
@@ -7291,6 +7388,7 @@ function validateParsed(flow, opts, sources) {
|
|
|
7291
7388
|
validateOrchestratorCampaign(f, issues, opts);
|
|
7292
7389
|
validateCredentialBindings(f, issues);
|
|
7293
7390
|
validateInputSchema(f, issues);
|
|
7391
|
+
validateReservedInputNames(f, issues);
|
|
7294
7392
|
validateOutputSchemas(f, issues);
|
|
7295
7393
|
validateQualityGates(f, issues);
|
|
7296
7394
|
validateProcessingOperations(f, issues);
|
package/dist/index.cjs
CHANGED
|
@@ -994,7 +994,7 @@ var aigentflow_spec_default = {
|
|
|
994
994
|
providerAgent: "agent",
|
|
995
995
|
providerCapability: "capability",
|
|
996
996
|
agentResource: "run",
|
|
997
|
-
capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_
|
|
997
|
+
capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$",
|
|
998
998
|
operationUnknown: {
|
|
999
999
|
code: "atlas_operation_unknown",
|
|
1000
1000
|
messageFormat: "step %s uses %s, which is not an Atlas operation. The providers are agent (resource run) and capability (resource: a capability reference).",
|
|
@@ -1002,7 +1002,7 @@ var aigentflow_spec_default = {
|
|
|
1002
1002
|
},
|
|
1003
1003
|
agentMissing: {
|
|
1004
1004
|
code: "atlas_agent_missing",
|
|
1005
|
-
messageFormat: "step %s runs an Atlas agent but query.agent is missing or
|
|
1005
|
+
messageFormat: "step %s runs an Atlas agent but query.agent is missing, empty or not a string.",
|
|
1006
1006
|
suggestion: "Set query.agent to the agent to run, written out as a literal such as @acme/reporter."
|
|
1007
1007
|
},
|
|
1008
1008
|
agentNotLiteral: {
|
|
@@ -1028,9 +1028,46 @@ var aigentflow_spec_default = {
|
|
|
1028
1028
|
capabilityRefInvalid: {
|
|
1029
1029
|
code: "atlas_capability_ref_invalid",
|
|
1030
1030
|
messageFormat: "step %s uses atlas://capability/%s, which is not a valid capability reference.",
|
|
1031
|
-
suggestion: "A capability reference starts with a letter or digit and continues with letters, digits
|
|
1031
|
+
suggestion: "A capability reference starts with a letter or digit and continues with letters, digits, _ and - up to 128 characters in all."
|
|
1032
|
+
},
|
|
1033
|
+
modelNotLiteral: {
|
|
1034
|
+
code: "atlas_model_not_literal",
|
|
1035
|
+
messageFormat: "step %s computes a value of query.model from a template. The provider, model and reasoning_effort must be fixed literals, never derived from input.",
|
|
1036
|
+
suggestion: "Write the model choice out as literals. Data may go into the prompt or the inputs instead."
|
|
1037
|
+
},
|
|
1038
|
+
paramRefused: {
|
|
1039
|
+
code: "atlas_param_refused",
|
|
1040
|
+
messageFormat: "step %s sets %s under query. Atlas decides these itself, so a step may not set them.",
|
|
1041
|
+
suggestion: "Remove these keys from the query.",
|
|
1042
|
+
agentKeys: [
|
|
1043
|
+
"api_key",
|
|
1044
|
+
"attribution",
|
|
1045
|
+
"base_url",
|
|
1046
|
+
"host",
|
|
1047
|
+
"idempotency_key",
|
|
1048
|
+
"org_id",
|
|
1049
|
+
"person",
|
|
1050
|
+
"untrusted_input",
|
|
1051
|
+
"untrusted_input_override",
|
|
1052
|
+
"url",
|
|
1053
|
+
"user_id"
|
|
1054
|
+
],
|
|
1055
|
+
capabilityKeys: [
|
|
1056
|
+
"attribution",
|
|
1057
|
+
"idempotency_key",
|
|
1058
|
+
"untrusted_input",
|
|
1059
|
+
"untrusted_input_override"
|
|
1060
|
+
]
|
|
1032
1061
|
}
|
|
1033
1062
|
},
|
|
1063
|
+
reservedInputNames: {
|
|
1064
|
+
prefix: "__",
|
|
1065
|
+
code: "reserved_input_name",
|
|
1066
|
+
messageFormat: "the input %s starts with two underscores. That namespace belongs to the platform (the acting person, the credential manifest, the untrusted-input marker): a flow cannot declare an input there, and a value or default written under such a name is never delivered.",
|
|
1067
|
+
suggestion: 'Rename the input so it does not start with "__".',
|
|
1068
|
+
queryFieldFormat: "query.%s",
|
|
1069
|
+
schemaFieldFormat: "input_schema.fields.%s"
|
|
1070
|
+
},
|
|
1034
1071
|
flowDataReservedKeys: {
|
|
1035
1072
|
code: "flow_data_key_reserved",
|
|
1036
1073
|
fieldFormat: "data.%s",
|
|
@@ -2086,7 +2123,23 @@ var ATLAS_EXECUTOR = {
|
|
|
2086
2123
|
capabilitiesNotLiteral: atlas.capabilitiesNotLiteral,
|
|
2087
2124
|
promptMissing: atlas.promptMissing,
|
|
2088
2125
|
promptBoth: atlas.promptBoth,
|
|
2089
|
-
capabilityRefInvalid: atlas.capabilityRefInvalid
|
|
2126
|
+
capabilityRefInvalid: atlas.capabilityRefInvalid,
|
|
2127
|
+
modelNotLiteral: atlas.modelNotLiteral,
|
|
2128
|
+
paramRefused: {
|
|
2129
|
+
code: atlas.paramRefused.code,
|
|
2130
|
+
messageFormat: atlas.paramRefused.messageFormat,
|
|
2131
|
+
suggestion: atlas.paramRefused.suggestion,
|
|
2132
|
+
agentKeys: atlas.paramRefused.agentKeys,
|
|
2133
|
+
capabilityKeys: atlas.paramRefused.capabilityKeys
|
|
2134
|
+
}
|
|
2135
|
+
};
|
|
2136
|
+
var RESERVED_INPUT_NAMES = {
|
|
2137
|
+
prefix: aigentflow_spec_default.reservedInputNames.prefix,
|
|
2138
|
+
code: aigentflow_spec_default.reservedInputNames.code,
|
|
2139
|
+
messageFormat: aigentflow_spec_default.reservedInputNames.messageFormat,
|
|
2140
|
+
suggestion: aigentflow_spec_default.reservedInputNames.suggestion,
|
|
2141
|
+
queryFieldFormat: aigentflow_spec_default.reservedInputNames.queryFieldFormat,
|
|
2142
|
+
schemaFieldFormat: aigentflow_spec_default.reservedInputNames.schemaFieldFormat
|
|
2090
2143
|
};
|
|
2091
2144
|
|
|
2092
2145
|
// src/validators/executors.ts
|
|
@@ -2153,10 +2206,12 @@ function checkExecutor(executor, field, stepID, issues) {
|
|
|
2153
2206
|
}
|
|
2154
2207
|
function checkAtlasStep(executor, query, stepField, stepID, issues) {
|
|
2155
2208
|
if (executor.includes(TEMPLATE_ACTION_OPEN)) return;
|
|
2156
|
-
const
|
|
2157
|
-
if (
|
|
2158
|
-
const
|
|
2159
|
-
const
|
|
2209
|
+
const prefix = `${ATLAS_EXECUTOR.scheme}://`;
|
|
2210
|
+
if (!executor.startsWith(prefix)) return;
|
|
2211
|
+
const rest = executor.slice(prefix.length);
|
|
2212
|
+
const slash = rest.indexOf("/");
|
|
2213
|
+
const provider = slash < 0 ? rest : rest.slice(0, slash);
|
|
2214
|
+
const resource = slash < 0 ? "" : rest.slice(slash + 1);
|
|
2160
2215
|
const quoted = JSON.stringify(stepID);
|
|
2161
2216
|
const report = (rule, ...args) => {
|
|
2162
2217
|
let message = rule.messageFormat.replace("%s", () => quoted);
|
|
@@ -2170,31 +2225,41 @@ function checkAtlasStep(executor, query, stepField, stepID, issues) {
|
|
|
2170
2225
|
});
|
|
2171
2226
|
};
|
|
2172
2227
|
const q2 = isRecord(query) ? query : {};
|
|
2228
|
+
let refusedKeys = ATLAS_EXECUTOR.paramRefused.capabilityKeys;
|
|
2173
2229
|
if (provider === ATLAS_EXECUTOR.providerCapability) {
|
|
2174
2230
|
if (!ATLAS_EXECUTOR.capabilityRefPattern.test(resource)) {
|
|
2175
2231
|
report(ATLAS_EXECUTOR.capabilityRefInvalid, resource);
|
|
2176
2232
|
}
|
|
2177
2233
|
} else if (provider === ATLAS_EXECUTOR.providerAgent && resource === ATLAS_EXECUTOR.agentResource) {
|
|
2234
|
+
refusedKeys = ATLAS_EXECUTOR.paramRefused.agentKeys;
|
|
2178
2235
|
const agent = q2.agent;
|
|
2179
|
-
if (typeof agent !== "string" || agent === "") {
|
|
2236
|
+
if (typeof agent !== "string" || agent.trim() === "") {
|
|
2180
2237
|
report(ATLAS_EXECUTOR.agentMissing);
|
|
2181
2238
|
} else if (agent.includes(TEMPLATE_ACTION_OPEN)) {
|
|
2182
2239
|
report(ATLAS_EXECUTOR.agentNotLiteral);
|
|
2183
2240
|
}
|
|
2184
|
-
const
|
|
2185
|
-
const
|
|
2186
|
-
const hasPrompt = prompt !== void 0 && prompt !== null && prompt !== "";
|
|
2187
|
-
const hasTemplate = promptTemplate !== void 0 && promptTemplate !== null && promptTemplate !== "";
|
|
2241
|
+
const hasPrompt = atlasTextPresent(q2.prompt);
|
|
2242
|
+
const hasTemplate = atlasTextPresent(q2.prompt_template);
|
|
2188
2243
|
if (!hasPrompt && !hasTemplate) report(ATLAS_EXECUTOR.promptMissing);
|
|
2189
2244
|
else if (hasPrompt && hasTemplate) report(ATLAS_EXECUTOR.promptBoth);
|
|
2245
|
+
if (anyTemplate(q2.model)) report(ATLAS_EXECUTOR.modelNotLiteral);
|
|
2190
2246
|
} else {
|
|
2191
2247
|
report(ATLAS_EXECUTOR.operationUnknown, executor);
|
|
2192
2248
|
return;
|
|
2193
2249
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2250
|
+
if (anyTemplate(q2.capabilities)) report(ATLAS_EXECUTOR.capabilitiesNotLiteral);
|
|
2251
|
+
const refused = refusedKeys.filter((key) => Object.prototype.hasOwnProperty.call(q2, key)).sort();
|
|
2252
|
+
if (refused.length > 0) report(ATLAS_EXECUTOR.paramRefused, refused.join(", "));
|
|
2253
|
+
}
|
|
2254
|
+
function anyTemplate(v) {
|
|
2255
|
+
if (typeof v === "string") return v.includes(TEMPLATE_ACTION_OPEN);
|
|
2256
|
+
if (Array.isArray(v)) return v.some(anyTemplate);
|
|
2257
|
+
if (isRecord(v)) return Object.values(v).some(anyTemplate);
|
|
2258
|
+
return false;
|
|
2259
|
+
}
|
|
2260
|
+
function atlasTextPresent(v) {
|
|
2261
|
+
if (v === void 0 || v === null) return false;
|
|
2262
|
+
return typeof v !== "string" || v.trim() !== "";
|
|
2198
2263
|
}
|
|
2199
2264
|
function checkFunctionOperation(executor, field, stepID, templated, issues) {
|
|
2200
2265
|
if (templated) return;
|
|
@@ -3880,6 +3945,37 @@ function validateInputSchema(flow, issues) {
|
|
|
3880
3945
|
validateSchemaDefinition(flow.input_schema, "input_schema", issues);
|
|
3881
3946
|
}
|
|
3882
3947
|
|
|
3948
|
+
// src/validators/reservedInputs.ts
|
|
3949
|
+
function formatField(format, name) {
|
|
3950
|
+
return format.replace("%s", () => name);
|
|
3951
|
+
}
|
|
3952
|
+
function validateReservedInputNames(flow, issues) {
|
|
3953
|
+
const rule = RESERVED_INPUT_NAMES;
|
|
3954
|
+
const report = (name, fieldFormat) => {
|
|
3955
|
+
issues.error({
|
|
3956
|
+
field: formatField(fieldFormat, name),
|
|
3957
|
+
message: rule.messageFormat.replace("%s", () => JSON.stringify(name)),
|
|
3958
|
+
code: rule.code,
|
|
3959
|
+
suggestion: rule.suggestion
|
|
3960
|
+
});
|
|
3961
|
+
};
|
|
3962
|
+
const query = flow.query;
|
|
3963
|
+
if (isRecord(query)) {
|
|
3964
|
+
for (const name of Object.keys(query).sort()) {
|
|
3965
|
+
if (name.startsWith(rule.prefix)) report(name, rule.queryFieldFormat);
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
const schema = flow.input_schema;
|
|
3969
|
+
const fields = isRecord(schema) ? schema.fields : void 0;
|
|
3970
|
+
if (!Array.isArray(fields)) return;
|
|
3971
|
+
for (const f of fields) {
|
|
3972
|
+
if (!isRecord(f)) continue;
|
|
3973
|
+
if (typeof f.name === "string" && f.name.startsWith(rule.prefix)) {
|
|
3974
|
+
report(f.name, rule.schemaFieldFormat);
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
|
|
3883
3979
|
// src/validators/outputSchema.ts
|
|
3884
3980
|
function validateOutputSchemas(flow, issues) {
|
|
3885
3981
|
const steps = flow.steps;
|
|
@@ -4994,7 +5090,7 @@ var CODE2 = "server_owned_query_key";
|
|
|
4994
5090
|
var KEY_QUERY = "query";
|
|
4995
5091
|
var KEY_ID = "id";
|
|
4996
5092
|
var SERVER_OWNED = new Set(SERVER_OWNED_QUERY_KEYS.keys);
|
|
4997
|
-
function
|
|
5093
|
+
function formatField2(format, ...args) {
|
|
4998
5094
|
let i = 0;
|
|
4999
5095
|
return format.replace(/%s/g, () => args[i++] ?? "");
|
|
5000
5096
|
}
|
|
@@ -5012,7 +5108,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
|
|
|
5012
5108
|
issues,
|
|
5013
5109
|
stepID,
|
|
5014
5110
|
key,
|
|
5015
|
-
|
|
5111
|
+
formatField2(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
|
|
5016
5112
|
);
|
|
5017
5113
|
}
|
|
5018
5114
|
}
|
|
@@ -5026,7 +5122,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
|
|
|
5026
5122
|
issues,
|
|
5027
5123
|
stepID,
|
|
5028
5124
|
key,
|
|
5029
|
-
|
|
5125
|
+
formatField2(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
|
|
5030
5126
|
);
|
|
5031
5127
|
}
|
|
5032
5128
|
}
|
|
@@ -5293,7 +5389,7 @@ function own(m, key) {
|
|
|
5293
5389
|
if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
|
|
5294
5390
|
return m[key];
|
|
5295
5391
|
}
|
|
5296
|
-
function
|
|
5392
|
+
function formatField3(format, ...args) {
|
|
5297
5393
|
let i = 0;
|
|
5298
5394
|
return format.replace(/%s/g, () => args[i++] ?? "");
|
|
5299
5395
|
}
|
|
@@ -5315,14 +5411,14 @@ function credentialEndpointSteps(flow, issues) {
|
|
|
5315
5411
|
out.push({
|
|
5316
5412
|
executor: issues.stringOf(step, KEY_EXECUTOR, `steps.${stepId}`) ?? "",
|
|
5317
5413
|
query: own(step, KEY_QUERY2),
|
|
5318
|
-
field: (key) =>
|
|
5414
|
+
field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
|
|
5319
5415
|
});
|
|
5320
5416
|
for (const sub of loopSubStepsOfStep(stepId, step)) {
|
|
5321
5417
|
const subId = issues.stringOf(sub.raw, KEY_ID2, sub.basePath) ?? "";
|
|
5322
5418
|
out.push({
|
|
5323
5419
|
executor: issues.stringOf(sub.raw, KEY_EXECUTOR, sub.basePath) ?? "",
|
|
5324
5420
|
query: own(sub.raw, KEY_QUERY2),
|
|
5325
|
-
field: (key) =>
|
|
5421
|
+
field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
|
|
5326
5422
|
});
|
|
5327
5423
|
}
|
|
5328
5424
|
}
|
|
@@ -5386,7 +5482,7 @@ function validateAI(flow, steps, issues) {
|
|
|
5386
5482
|
if ((stepsUsing.get(provider) ?? 0) > 0 && (stepsWithoutOwnKey.get(provider) ?? 0) === 0) {
|
|
5387
5483
|
continue;
|
|
5388
5484
|
}
|
|
5389
|
-
warnStoredShape(issues,
|
|
5485
|
+
warnStoredShape(issues, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
|
|
5390
5486
|
}
|
|
5391
5487
|
}
|
|
5392
5488
|
function warnStoredShape(issues, field, provider) {
|
|
@@ -5433,7 +5529,7 @@ function familySecret(flow, family, step, issues) {
|
|
|
5433
5529
|
if (apiKey !== "" && listHas(family.secretParams, family.configApiKeyParam)) {
|
|
5434
5530
|
return {
|
|
5435
5531
|
envName: serverEnvRef(family, apiKey),
|
|
5436
|
-
field:
|
|
5532
|
+
field: formatField3(
|
|
5437
5533
|
CREDENTIAL_ENDPOINT_PAIRING.executorConfigKeyFieldFormat,
|
|
5438
5534
|
configKey,
|
|
5439
5535
|
CREDENTIAL_ENDPOINT_PAIRING.executorConfigApiKeyField
|
|
@@ -5446,7 +5542,7 @@ function familySecret(flow, family, step, issues) {
|
|
|
5446
5542
|
if (v !== null) {
|
|
5447
5543
|
return {
|
|
5448
5544
|
envName: serverEnvRef(family, v),
|
|
5449
|
-
field:
|
|
5545
|
+
field: formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
|
|
5450
5546
|
};
|
|
5451
5547
|
}
|
|
5452
5548
|
}
|
|
@@ -5472,13 +5568,13 @@ function familyAuthorEndpoint(flow, family, step, issues) {
|
|
|
5472
5568
|
if (inst === null) continue;
|
|
5473
5569
|
const baseUrl = configStringField(inst, configKey, CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlField, issues);
|
|
5474
5570
|
if (baseUrl !== "" && listHas(family.endpointParams, family.configBaseUrlParam)) {
|
|
5475
|
-
return decide(baseUrl,
|
|
5571
|
+
return decide(baseUrl, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
|
|
5476
5572
|
}
|
|
5477
5573
|
const extra = own(inst, EXECUTOR_CONFIG_ENV_SCOPES.extraKey);
|
|
5478
5574
|
for (const key of family.endpointParams) {
|
|
5479
5575
|
const v = nonEmptyEndpoint(extra, key);
|
|
5480
5576
|
if (v !== null)
|
|
5481
|
-
return decide(v,
|
|
5577
|
+
return decide(v, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
|
|
5482
5578
|
}
|
|
5483
5579
|
}
|
|
5484
5580
|
return null;
|
|
@@ -7189,6 +7285,7 @@ function validateParsed(flow, opts, sources) {
|
|
|
7189
7285
|
validateOrchestratorCampaign(f, issues, opts);
|
|
7190
7286
|
validateCredentialBindings(f, issues);
|
|
7191
7287
|
validateInputSchema(f, issues);
|
|
7288
|
+
validateReservedInputNames(f, issues);
|
|
7192
7289
|
validateOutputSchemas(f, issues);
|
|
7193
7290
|
validateQualityGates(f, issues);
|
|
7194
7291
|
validateProcessingOperations(f, issues);
|