@vaudience/aigentflow-flow-validator 0.24.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.cjs CHANGED
@@ -459,6 +459,7 @@ var aigentflow_spec_default = {
459
459
  "ai",
460
460
  "aiv",
461
461
  "async",
462
+ "atlas",
462
463
  "browser",
463
464
  "chart",
464
465
  "db",
@@ -988,6 +989,85 @@ var aigentflow_spec_default = {
988
989
  "utils/parse-date"
989
990
  ]
990
991
  },
992
+ atlasExecutor: {
993
+ scheme: "atlas",
994
+ providerAgent: "agent",
995
+ providerCapability: "capability",
996
+ agentResource: "run",
997
+ capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$",
998
+ operationUnknown: {
999
+ code: "atlas_operation_unknown",
1000
+ messageFormat: "step %s uses %s, which is not an Atlas operation. The providers are agent (resource run) and capability (resource: a capability reference).",
1001
+ suggestion: "Use atlas://agent/run or atlas://capability/<capability-ref>."
1002
+ },
1003
+ agentMissing: {
1004
+ code: "atlas_agent_missing",
1005
+ messageFormat: "step %s runs an Atlas agent but query.agent is missing, empty or not a string.",
1006
+ suggestion: "Set query.agent to the agent to run, written out as a literal such as @acme/reporter."
1007
+ },
1008
+ agentNotLiteral: {
1009
+ code: "atlas_agent_not_literal",
1010
+ messageFormat: "step %s computes query.agent from a template. The agent must be a fixed literal, never derived from input.",
1011
+ suggestion: "Write the agent out as a literal such as @acme/reporter. Data may go into the prompt or the inputs instead."
1012
+ },
1013
+ capabilitiesNotLiteral: {
1014
+ code: "atlas_capabilities_not_literal",
1015
+ messageFormat: "step %s computes an entry of query.capabilities from a template. Capabilities must be fixed literals, never derived from input.",
1016
+ suggestion: "Write each capability out as a literal. Data may go into the prompt or the inputs instead."
1017
+ },
1018
+ promptMissing: {
1019
+ code: "atlas_prompt_missing",
1020
+ messageFormat: "step %s runs an Atlas agent with neither query.prompt nor query.prompt_template.",
1021
+ suggestion: "Set exactly one of query.prompt or query.prompt_template."
1022
+ },
1023
+ promptBoth: {
1024
+ code: "atlas_prompt_both",
1025
+ messageFormat: "step %s sets both query.prompt and query.prompt_template.",
1026
+ suggestion: "Keep exactly one of query.prompt or query.prompt_template."
1027
+ },
1028
+ capabilityRefInvalid: {
1029
+ code: "atlas_capability_ref_invalid",
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, _ 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
+ ]
1061
+ }
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
+ },
991
1071
  flowDataReservedKeys: {
992
1072
  code: "flow_data_key_reserved",
993
1073
  fieldFormat: "data.%s",
@@ -2030,6 +2110,37 @@ var FUNCTION_OPERATIONS = {
2030
2110
  operations: new Set(aigentflow_spec_default.functionOperations.operations),
2031
2111
  sorted: aigentflow_spec_default.functionOperations.operations
2032
2112
  };
2113
+ var atlas = aigentflow_spec_default.atlasExecutor;
2114
+ var ATLAS_EXECUTOR = {
2115
+ scheme: atlas.scheme,
2116
+ providerAgent: atlas.providerAgent,
2117
+ providerCapability: atlas.providerCapability,
2118
+ agentResource: atlas.agentResource,
2119
+ capabilityRefPattern: new RegExp(atlas.capabilityRefPattern),
2120
+ operationUnknown: atlas.operationUnknown,
2121
+ agentMissing: atlas.agentMissing,
2122
+ agentNotLiteral: atlas.agentNotLiteral,
2123
+ capabilitiesNotLiteral: atlas.capabilitiesNotLiteral,
2124
+ promptMissing: atlas.promptMissing,
2125
+ promptBoth: atlas.promptBoth,
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
2143
+ };
2033
2144
 
2034
2145
  // src/validators/executors.ts
2035
2146
  var SCHEME_SEPARATOR = "://";
@@ -2093,6 +2204,63 @@ function checkExecutor(executor, field, stepID, issues) {
2093
2204
  }
2094
2205
  checkFunctionOperation(executor, field, stepID, templated, issues);
2095
2206
  }
2207
+ function checkAtlasStep(executor, query, stepField, stepID, issues) {
2208
+ if (executor.includes(TEMPLATE_ACTION_OPEN)) return;
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);
2215
+ const quoted = JSON.stringify(stepID);
2216
+ const report = (rule, ...args) => {
2217
+ let message = rule.messageFormat.replace("%s", () => quoted);
2218
+ for (const a of args) message = message.replace("%s", () => a);
2219
+ issues.error({
2220
+ field: stepField,
2221
+ message,
2222
+ code: rule.code,
2223
+ stepId: stepID,
2224
+ suggestion: rule.suggestion
2225
+ });
2226
+ };
2227
+ const q2 = isRecord(query) ? query : {};
2228
+ let refusedKeys = ATLAS_EXECUTOR.paramRefused.capabilityKeys;
2229
+ if (provider === ATLAS_EXECUTOR.providerCapability) {
2230
+ if (!ATLAS_EXECUTOR.capabilityRefPattern.test(resource)) {
2231
+ report(ATLAS_EXECUTOR.capabilityRefInvalid, resource);
2232
+ }
2233
+ } else if (provider === ATLAS_EXECUTOR.providerAgent && resource === ATLAS_EXECUTOR.agentResource) {
2234
+ refusedKeys = ATLAS_EXECUTOR.paramRefused.agentKeys;
2235
+ const agent = q2.agent;
2236
+ if (typeof agent !== "string" || agent.trim() === "") {
2237
+ report(ATLAS_EXECUTOR.agentMissing);
2238
+ } else if (agent.includes(TEMPLATE_ACTION_OPEN)) {
2239
+ report(ATLAS_EXECUTOR.agentNotLiteral);
2240
+ }
2241
+ const hasPrompt = atlasTextPresent(q2.prompt);
2242
+ const hasTemplate = atlasTextPresent(q2.prompt_template);
2243
+ if (!hasPrompt && !hasTemplate) report(ATLAS_EXECUTOR.promptMissing);
2244
+ else if (hasPrompt && hasTemplate) report(ATLAS_EXECUTOR.promptBoth);
2245
+ if (anyTemplate(q2.model)) report(ATLAS_EXECUTOR.modelNotLiteral);
2246
+ } else {
2247
+ report(ATLAS_EXECUTOR.operationUnknown, executor);
2248
+ return;
2249
+ }
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() !== "";
2263
+ }
2096
2264
  function checkFunctionOperation(executor, field, stepID, templated, issues) {
2097
2265
  if (templated) return;
2098
2266
  const m = EXECUTOR_URL_PATTERN.exec(executor);
@@ -2117,6 +2285,7 @@ function validateExecutors(flow, issues) {
2117
2285
  const executor = issues.stringOf(step, "executor", `steps.${stepID}`);
2118
2286
  if (executor !== null && executor !== "") {
2119
2287
  checkExecutor(executor, `steps.${stepID}.executor`, stepID, issues);
2288
+ checkAtlasStep(executor, step.query, `steps.${stepID}`, stepID, issues);
2120
2289
  }
2121
2290
  const loop = step.loop;
2122
2291
  if (isRecord(loop) && Array.isArray(loop.steps)) {
@@ -2133,6 +2302,7 @@ function validateExecutors(flow, issues) {
2133
2302
  `${stepID}.${subID}`,
2134
2303
  issues
2135
2304
  );
2305
+ checkAtlasStep(subExecutor, subStep.query, subPath, `${stepID}.${subID}`, issues);
2136
2306
  }
2137
2307
  });
2138
2308
  }
@@ -3775,6 +3945,37 @@ function validateInputSchema(flow, issues) {
3775
3945
  validateSchemaDefinition(flow.input_schema, "input_schema", issues);
3776
3946
  }
3777
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
+
3778
3979
  // src/validators/outputSchema.ts
3779
3980
  function validateOutputSchemas(flow, issues) {
3780
3981
  const steps = flow.steps;
@@ -4889,7 +5090,7 @@ var CODE2 = "server_owned_query_key";
4889
5090
  var KEY_QUERY = "query";
4890
5091
  var KEY_ID = "id";
4891
5092
  var SERVER_OWNED = new Set(SERVER_OWNED_QUERY_KEYS.keys);
4892
- function formatField(format, ...args) {
5093
+ function formatField2(format, ...args) {
4893
5094
  let i = 0;
4894
5095
  return format.replace(/%s/g, () => args[i++] ?? "");
4895
5096
  }
@@ -4907,7 +5108,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
4907
5108
  issues,
4908
5109
  stepID,
4909
5110
  key,
4910
- formatField(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
5111
+ formatField2(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
4911
5112
  );
4912
5113
  }
4913
5114
  }
@@ -4921,7 +5122,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
4921
5122
  issues,
4922
5123
  stepID,
4923
5124
  key,
4924
- formatField(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
5125
+ formatField2(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
4925
5126
  );
4926
5127
  }
4927
5128
  }
@@ -5188,7 +5389,7 @@ function own(m, key) {
5188
5389
  if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5189
5390
  return m[key];
5190
5391
  }
5191
- function formatField2(format, ...args) {
5392
+ function formatField3(format, ...args) {
5192
5393
  let i = 0;
5193
5394
  return format.replace(/%s/g, () => args[i++] ?? "");
5194
5395
  }
@@ -5210,14 +5411,14 @@ function credentialEndpointSteps(flow, issues) {
5210
5411
  out.push({
5211
5412
  executor: issues.stringOf(step, KEY_EXECUTOR, `steps.${stepId}`) ?? "",
5212
5413
  query: own(step, KEY_QUERY2),
5213
- field: (key) => formatField2(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
5414
+ field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
5214
5415
  });
5215
5416
  for (const sub of loopSubStepsOfStep(stepId, step)) {
5216
5417
  const subId = issues.stringOf(sub.raw, KEY_ID2, sub.basePath) ?? "";
5217
5418
  out.push({
5218
5419
  executor: issues.stringOf(sub.raw, KEY_EXECUTOR, sub.basePath) ?? "",
5219
5420
  query: own(sub.raw, KEY_QUERY2),
5220
- field: (key) => formatField2(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
5421
+ field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
5221
5422
  });
5222
5423
  }
5223
5424
  }
@@ -5281,7 +5482,7 @@ function validateAI(flow, steps, issues) {
5281
5482
  if ((stepsUsing.get(provider) ?? 0) > 0 && (stepsWithoutOwnKey.get(provider) ?? 0) === 0) {
5282
5483
  continue;
5283
5484
  }
5284
- warnStoredShape(issues, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
5485
+ warnStoredShape(issues, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
5285
5486
  }
5286
5487
  }
5287
5488
  function warnStoredShape(issues, field, provider) {
@@ -5328,7 +5529,7 @@ function familySecret(flow, family, step, issues) {
5328
5529
  if (apiKey !== "" && listHas(family.secretParams, family.configApiKeyParam)) {
5329
5530
  return {
5330
5531
  envName: serverEnvRef(family, apiKey),
5331
- field: formatField2(
5532
+ field: formatField3(
5332
5533
  CREDENTIAL_ENDPOINT_PAIRING.executorConfigKeyFieldFormat,
5333
5534
  configKey,
5334
5535
  CREDENTIAL_ENDPOINT_PAIRING.executorConfigApiKeyField
@@ -5341,7 +5542,7 @@ function familySecret(flow, family, step, issues) {
5341
5542
  if (v !== null) {
5342
5543
  return {
5343
5544
  envName: serverEnvRef(family, v),
5344
- field: formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
5545
+ field: formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
5345
5546
  };
5346
5547
  }
5347
5548
  }
@@ -5367,13 +5568,13 @@ function familyAuthorEndpoint(flow, family, step, issues) {
5367
5568
  if (inst === null) continue;
5368
5569
  const baseUrl = configStringField(inst, configKey, CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlField, issues);
5369
5570
  if (baseUrl !== "" && listHas(family.endpointParams, family.configBaseUrlParam)) {
5370
- return decide(baseUrl, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
5571
+ return decide(baseUrl, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
5371
5572
  }
5372
5573
  const extra = own(inst, EXECUTOR_CONFIG_ENV_SCOPES.extraKey);
5373
5574
  for (const key of family.endpointParams) {
5374
5575
  const v = nonEmptyEndpoint(extra, key);
5375
5576
  if (v !== null)
5376
- return decide(v, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
5577
+ return decide(v, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
5377
5578
  }
5378
5579
  }
5379
5580
  return null;
@@ -7084,6 +7285,7 @@ function validateParsed(flow, opts, sources) {
7084
7285
  validateOrchestratorCampaign(f, issues, opts);
7085
7286
  validateCredentialBindings(f, issues);
7086
7287
  validateInputSchema(f, issues);
7288
+ validateReservedInputNames(f, issues);
7087
7289
  validateOutputSchemas(f, issues);
7088
7290
  validateQualityGates(f, issues);
7089
7291
  validateProcessingOperations(f, issues);