@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/dist/index.js CHANGED
@@ -992,7 +992,7 @@ var aigentflow_spec_default = {
992
992
  providerAgent: "agent",
993
993
  providerCapability: "capability",
994
994
  agentResource: "run",
995
- capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$",
995
+ capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$",
996
996
  operationUnknown: {
997
997
  code: "atlas_operation_unknown",
998
998
  messageFormat: "step %s uses %s, which is not an Atlas operation. The providers are agent (resource run) and capability (resource: a capability reference).",
@@ -1000,7 +1000,7 @@ var aigentflow_spec_default = {
1000
1000
  },
1001
1001
  agentMissing: {
1002
1002
  code: "atlas_agent_missing",
1003
- messageFormat: "step %s runs an Atlas agent but query.agent is missing or empty.",
1003
+ messageFormat: "step %s runs an Atlas agent but query.agent is missing, empty or not a string.",
1004
1004
  suggestion: "Set query.agent to the agent to run, written out as a literal such as @acme/reporter."
1005
1005
  },
1006
1006
  agentNotLiteral: {
@@ -1026,9 +1026,46 @@ var aigentflow_spec_default = {
1026
1026
  capabilityRefInvalid: {
1027
1027
  code: "atlas_capability_ref_invalid",
1028
1028
  messageFormat: "step %s uses atlas://capability/%s, which is not a valid capability reference.",
1029
- suggestion: "A capability reference starts with a letter or digit and continues with letters, digits and _ . : - up to 128 characters in all."
1029
+ suggestion: "A capability reference starts with a letter or digit and continues with letters, digits, _ and - up to 128 characters in all."
1030
+ },
1031
+ modelNotLiteral: {
1032
+ code: "atlas_model_not_literal",
1033
+ 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.",
1034
+ suggestion: "Write the model choice out as literals. Data may go into the prompt or the inputs instead."
1035
+ },
1036
+ paramRefused: {
1037
+ code: "atlas_param_refused",
1038
+ messageFormat: "step %s sets %s under query. Atlas decides these itself, so a step may not set them.",
1039
+ suggestion: "Remove these keys from the query.",
1040
+ agentKeys: [
1041
+ "api_key",
1042
+ "attribution",
1043
+ "base_url",
1044
+ "host",
1045
+ "idempotency_key",
1046
+ "org_id",
1047
+ "person",
1048
+ "untrusted_input",
1049
+ "untrusted_input_override",
1050
+ "url",
1051
+ "user_id"
1052
+ ],
1053
+ capabilityKeys: [
1054
+ "attribution",
1055
+ "idempotency_key",
1056
+ "untrusted_input",
1057
+ "untrusted_input_override"
1058
+ ]
1030
1059
  }
1031
1060
  },
1061
+ reservedInputNames: {
1062
+ prefix: "__",
1063
+ code: "reserved_input_name",
1064
+ 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.",
1065
+ suggestion: 'Rename the input so it does not start with "__".',
1066
+ queryFieldFormat: "query.%s",
1067
+ schemaFieldFormat: "input_schema.fields.%s"
1068
+ },
1032
1069
  flowDataReservedKeys: {
1033
1070
  code: "flow_data_key_reserved",
1034
1071
  fieldFormat: "data.%s",
@@ -2084,7 +2121,23 @@ var ATLAS_EXECUTOR = {
2084
2121
  capabilitiesNotLiteral: atlas.capabilitiesNotLiteral,
2085
2122
  promptMissing: atlas.promptMissing,
2086
2123
  promptBoth: atlas.promptBoth,
2087
- capabilityRefInvalid: atlas.capabilityRefInvalid
2124
+ capabilityRefInvalid: atlas.capabilityRefInvalid,
2125
+ modelNotLiteral: atlas.modelNotLiteral,
2126
+ paramRefused: {
2127
+ code: atlas.paramRefused.code,
2128
+ messageFormat: atlas.paramRefused.messageFormat,
2129
+ suggestion: atlas.paramRefused.suggestion,
2130
+ agentKeys: atlas.paramRefused.agentKeys,
2131
+ capabilityKeys: atlas.paramRefused.capabilityKeys
2132
+ }
2133
+ };
2134
+ var RESERVED_INPUT_NAMES = {
2135
+ prefix: aigentflow_spec_default.reservedInputNames.prefix,
2136
+ code: aigentflow_spec_default.reservedInputNames.code,
2137
+ messageFormat: aigentflow_spec_default.reservedInputNames.messageFormat,
2138
+ suggestion: aigentflow_spec_default.reservedInputNames.suggestion,
2139
+ queryFieldFormat: aigentflow_spec_default.reservedInputNames.queryFieldFormat,
2140
+ schemaFieldFormat: aigentflow_spec_default.reservedInputNames.schemaFieldFormat
2088
2141
  };
2089
2142
 
2090
2143
  // src/validators/executors.ts
@@ -2151,10 +2204,12 @@ function checkExecutor(executor, field, stepID, issues) {
2151
2204
  }
2152
2205
  function checkAtlasStep(executor, query, stepField, stepID, issues) {
2153
2206
  if (executor.includes(TEMPLATE_ACTION_OPEN)) return;
2154
- const m = EXECUTOR_URL_PATTERN.exec(executor);
2155
- if (m === null || m[1] !== ATLAS_EXECUTOR.scheme) return;
2156
- const provider = m[2];
2157
- const resource = m[3];
2207
+ const prefix = `${ATLAS_EXECUTOR.scheme}://`;
2208
+ if (!executor.startsWith(prefix)) return;
2209
+ const rest = executor.slice(prefix.length);
2210
+ const slash = rest.indexOf("/");
2211
+ const provider = slash < 0 ? rest : rest.slice(0, slash);
2212
+ const resource = slash < 0 ? "" : rest.slice(slash + 1);
2158
2213
  const quoted = JSON.stringify(stepID);
2159
2214
  const report = (rule, ...args) => {
2160
2215
  let message = rule.messageFormat.replace("%s", () => quoted);
@@ -2168,31 +2223,41 @@ function checkAtlasStep(executor, query, stepField, stepID, issues) {
2168
2223
  });
2169
2224
  };
2170
2225
  const q2 = isRecord(query) ? query : {};
2226
+ let refusedKeys = ATLAS_EXECUTOR.paramRefused.capabilityKeys;
2171
2227
  if (provider === ATLAS_EXECUTOR.providerCapability) {
2172
2228
  if (!ATLAS_EXECUTOR.capabilityRefPattern.test(resource)) {
2173
2229
  report(ATLAS_EXECUTOR.capabilityRefInvalid, resource);
2174
2230
  }
2175
2231
  } else if (provider === ATLAS_EXECUTOR.providerAgent && resource === ATLAS_EXECUTOR.agentResource) {
2232
+ refusedKeys = ATLAS_EXECUTOR.paramRefused.agentKeys;
2176
2233
  const agent = q2.agent;
2177
- if (typeof agent !== "string" || agent === "") {
2234
+ if (typeof agent !== "string" || agent.trim() === "") {
2178
2235
  report(ATLAS_EXECUTOR.agentMissing);
2179
2236
  } else if (agent.includes(TEMPLATE_ACTION_OPEN)) {
2180
2237
  report(ATLAS_EXECUTOR.agentNotLiteral);
2181
2238
  }
2182
- const prompt = q2.prompt;
2183
- const promptTemplate = q2.prompt_template;
2184
- const hasPrompt = prompt !== void 0 && prompt !== null && prompt !== "";
2185
- const hasTemplate = promptTemplate !== void 0 && promptTemplate !== null && promptTemplate !== "";
2239
+ const hasPrompt = atlasTextPresent(q2.prompt);
2240
+ const hasTemplate = atlasTextPresent(q2.prompt_template);
2186
2241
  if (!hasPrompt && !hasTemplate) report(ATLAS_EXECUTOR.promptMissing);
2187
2242
  else if (hasPrompt && hasTemplate) report(ATLAS_EXECUTOR.promptBoth);
2243
+ if (anyTemplate(q2.model)) report(ATLAS_EXECUTOR.modelNotLiteral);
2188
2244
  } else {
2189
2245
  report(ATLAS_EXECUTOR.operationUnknown, executor);
2190
2246
  return;
2191
2247
  }
2192
- const caps = q2.capabilities;
2193
- if (Array.isArray(caps) && caps.some((c) => typeof c === "string" && c.includes(TEMPLATE_ACTION_OPEN))) {
2194
- report(ATLAS_EXECUTOR.capabilitiesNotLiteral);
2195
- }
2248
+ if (anyTemplate(q2.capabilities)) report(ATLAS_EXECUTOR.capabilitiesNotLiteral);
2249
+ const refused = refusedKeys.filter((key) => Object.prototype.hasOwnProperty.call(q2, key)).sort();
2250
+ if (refused.length > 0) report(ATLAS_EXECUTOR.paramRefused, refused.join(", "));
2251
+ }
2252
+ function anyTemplate(v) {
2253
+ if (typeof v === "string") return v.includes(TEMPLATE_ACTION_OPEN);
2254
+ if (Array.isArray(v)) return v.some(anyTemplate);
2255
+ if (isRecord(v)) return Object.values(v).some(anyTemplate);
2256
+ return false;
2257
+ }
2258
+ function atlasTextPresent(v) {
2259
+ if (v === void 0 || v === null) return false;
2260
+ return typeof v !== "string" || v.trim() !== "";
2196
2261
  }
2197
2262
  function checkFunctionOperation(executor, field, stepID, templated, issues) {
2198
2263
  if (templated) return;
@@ -3878,6 +3943,37 @@ function validateInputSchema(flow, issues) {
3878
3943
  validateSchemaDefinition(flow.input_schema, "input_schema", issues);
3879
3944
  }
3880
3945
 
3946
+ // src/validators/reservedInputs.ts
3947
+ function formatField(format, name) {
3948
+ return format.replace("%s", () => name);
3949
+ }
3950
+ function validateReservedInputNames(flow, issues) {
3951
+ const rule = RESERVED_INPUT_NAMES;
3952
+ const report = (name, fieldFormat) => {
3953
+ issues.error({
3954
+ field: formatField(fieldFormat, name),
3955
+ message: rule.messageFormat.replace("%s", () => JSON.stringify(name)),
3956
+ code: rule.code,
3957
+ suggestion: rule.suggestion
3958
+ });
3959
+ };
3960
+ const query = flow.query;
3961
+ if (isRecord(query)) {
3962
+ for (const name of Object.keys(query).sort()) {
3963
+ if (name.startsWith(rule.prefix)) report(name, rule.queryFieldFormat);
3964
+ }
3965
+ }
3966
+ const schema = flow.input_schema;
3967
+ const fields = isRecord(schema) ? schema.fields : void 0;
3968
+ if (!Array.isArray(fields)) return;
3969
+ for (const f of fields) {
3970
+ if (!isRecord(f)) continue;
3971
+ if (typeof f.name === "string" && f.name.startsWith(rule.prefix)) {
3972
+ report(f.name, rule.schemaFieldFormat);
3973
+ }
3974
+ }
3975
+ }
3976
+
3881
3977
  // src/validators/outputSchema.ts
3882
3978
  function validateOutputSchemas(flow, issues) {
3883
3979
  const steps = flow.steps;
@@ -4992,7 +5088,7 @@ var CODE2 = "server_owned_query_key";
4992
5088
  var KEY_QUERY = "query";
4993
5089
  var KEY_ID = "id";
4994
5090
  var SERVER_OWNED = new Set(SERVER_OWNED_QUERY_KEYS.keys);
4995
- function formatField(format, ...args) {
5091
+ function formatField2(format, ...args) {
4996
5092
  let i = 0;
4997
5093
  return format.replace(/%s/g, () => args[i++] ?? "");
4998
5094
  }
@@ -5010,7 +5106,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
5010
5106
  issues,
5011
5107
  stepID,
5012
5108
  key,
5013
- formatField(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
5109
+ formatField2(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
5014
5110
  );
5015
5111
  }
5016
5112
  }
@@ -5024,7 +5120,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
5024
5120
  issues,
5025
5121
  stepID,
5026
5122
  key,
5027
- formatField(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
5123
+ formatField2(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
5028
5124
  );
5029
5125
  }
5030
5126
  }
@@ -5291,7 +5387,7 @@ function own(m, key) {
5291
5387
  if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5292
5388
  return m[key];
5293
5389
  }
5294
- function formatField2(format, ...args) {
5390
+ function formatField3(format, ...args) {
5295
5391
  let i = 0;
5296
5392
  return format.replace(/%s/g, () => args[i++] ?? "");
5297
5393
  }
@@ -5313,14 +5409,14 @@ function credentialEndpointSteps(flow, issues) {
5313
5409
  out.push({
5314
5410
  executor: issues.stringOf(step, KEY_EXECUTOR, `steps.${stepId}`) ?? "",
5315
5411
  query: own(step, KEY_QUERY2),
5316
- field: (key) => formatField2(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
5412
+ field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
5317
5413
  });
5318
5414
  for (const sub of loopSubStepsOfStep(stepId, step)) {
5319
5415
  const subId = issues.stringOf(sub.raw, KEY_ID2, sub.basePath) ?? "";
5320
5416
  out.push({
5321
5417
  executor: issues.stringOf(sub.raw, KEY_EXECUTOR, sub.basePath) ?? "",
5322
5418
  query: own(sub.raw, KEY_QUERY2),
5323
- field: (key) => formatField2(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
5419
+ field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
5324
5420
  });
5325
5421
  }
5326
5422
  }
@@ -5384,7 +5480,7 @@ function validateAI(flow, steps, issues) {
5384
5480
  if ((stepsUsing.get(provider) ?? 0) > 0 && (stepsWithoutOwnKey.get(provider) ?? 0) === 0) {
5385
5481
  continue;
5386
5482
  }
5387
- warnStoredShape(issues, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
5483
+ warnStoredShape(issues, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
5388
5484
  }
5389
5485
  }
5390
5486
  function warnStoredShape(issues, field, provider) {
@@ -5431,7 +5527,7 @@ function familySecret(flow, family, step, issues) {
5431
5527
  if (apiKey !== "" && listHas(family.secretParams, family.configApiKeyParam)) {
5432
5528
  return {
5433
5529
  envName: serverEnvRef(family, apiKey),
5434
- field: formatField2(
5530
+ field: formatField3(
5435
5531
  CREDENTIAL_ENDPOINT_PAIRING.executorConfigKeyFieldFormat,
5436
5532
  configKey,
5437
5533
  CREDENTIAL_ENDPOINT_PAIRING.executorConfigApiKeyField
@@ -5444,7 +5540,7 @@ function familySecret(flow, family, step, issues) {
5444
5540
  if (v !== null) {
5445
5541
  return {
5446
5542
  envName: serverEnvRef(family, v),
5447
- field: formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
5543
+ field: formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
5448
5544
  };
5449
5545
  }
5450
5546
  }
@@ -5470,13 +5566,13 @@ function familyAuthorEndpoint(flow, family, step, issues) {
5470
5566
  if (inst === null) continue;
5471
5567
  const baseUrl = configStringField(inst, configKey, CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlField, issues);
5472
5568
  if (baseUrl !== "" && listHas(family.endpointParams, family.configBaseUrlParam)) {
5473
- return decide(baseUrl, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
5569
+ return decide(baseUrl, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
5474
5570
  }
5475
5571
  const extra = own(inst, EXECUTOR_CONFIG_ENV_SCOPES.extraKey);
5476
5572
  for (const key of family.endpointParams) {
5477
5573
  const v = nonEmptyEndpoint(extra, key);
5478
5574
  if (v !== null)
5479
- return decide(v, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
5575
+ return decide(v, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
5480
5576
  }
5481
5577
  }
5482
5578
  return null;
@@ -7187,6 +7283,7 @@ function validateParsed(flow, opts, sources) {
7187
7283
  validateOrchestratorCampaign(f, issues, opts);
7188
7284
  validateCredentialBindings(f, issues);
7189
7285
  validateInputSchema(f, issues);
7286
+ validateReservedInputNames(f, issues);
7190
7287
  validateOutputSchemas(f, issues);
7191
7288
  validateQualityGates(f, issues);
7192
7289
  validateProcessingOperations(f, issues);