@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.js CHANGED
@@ -457,6 +457,7 @@ var aigentflow_spec_default = {
457
457
  "ai",
458
458
  "aiv",
459
459
  "async",
460
+ "atlas",
460
461
  "browser",
461
462
  "chart",
462
463
  "db",
@@ -986,6 +987,85 @@ var aigentflow_spec_default = {
986
987
  "utils/parse-date"
987
988
  ]
988
989
  },
990
+ atlasExecutor: {
991
+ scheme: "atlas",
992
+ providerAgent: "agent",
993
+ providerCapability: "capability",
994
+ agentResource: "run",
995
+ capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$",
996
+ operationUnknown: {
997
+ code: "atlas_operation_unknown",
998
+ messageFormat: "step %s uses %s, which is not an Atlas operation. The providers are agent (resource run) and capability (resource: a capability reference).",
999
+ suggestion: "Use atlas://agent/run or atlas://capability/<capability-ref>."
1000
+ },
1001
+ agentMissing: {
1002
+ code: "atlas_agent_missing",
1003
+ messageFormat: "step %s runs an Atlas agent but query.agent is missing, empty or not a string.",
1004
+ suggestion: "Set query.agent to the agent to run, written out as a literal such as @acme/reporter."
1005
+ },
1006
+ agentNotLiteral: {
1007
+ code: "atlas_agent_not_literal",
1008
+ messageFormat: "step %s computes query.agent from a template. The agent must be a fixed literal, never derived from input.",
1009
+ suggestion: "Write the agent out as a literal such as @acme/reporter. Data may go into the prompt or the inputs instead."
1010
+ },
1011
+ capabilitiesNotLiteral: {
1012
+ code: "atlas_capabilities_not_literal",
1013
+ messageFormat: "step %s computes an entry of query.capabilities from a template. Capabilities must be fixed literals, never derived from input.",
1014
+ suggestion: "Write each capability out as a literal. Data may go into the prompt or the inputs instead."
1015
+ },
1016
+ promptMissing: {
1017
+ code: "atlas_prompt_missing",
1018
+ messageFormat: "step %s runs an Atlas agent with neither query.prompt nor query.prompt_template.",
1019
+ suggestion: "Set exactly one of query.prompt or query.prompt_template."
1020
+ },
1021
+ promptBoth: {
1022
+ code: "atlas_prompt_both",
1023
+ messageFormat: "step %s sets both query.prompt and query.prompt_template.",
1024
+ suggestion: "Keep exactly one of query.prompt or query.prompt_template."
1025
+ },
1026
+ capabilityRefInvalid: {
1027
+ code: "atlas_capability_ref_invalid",
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."
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
+ ]
1059
+ }
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
+ },
989
1069
  flowDataReservedKeys: {
990
1070
  code: "flow_data_key_reserved",
991
1071
  fieldFormat: "data.%s",
@@ -2028,6 +2108,37 @@ var FUNCTION_OPERATIONS = {
2028
2108
  operations: new Set(aigentflow_spec_default.functionOperations.operations),
2029
2109
  sorted: aigentflow_spec_default.functionOperations.operations
2030
2110
  };
2111
+ var atlas = aigentflow_spec_default.atlasExecutor;
2112
+ var ATLAS_EXECUTOR = {
2113
+ scheme: atlas.scheme,
2114
+ providerAgent: atlas.providerAgent,
2115
+ providerCapability: atlas.providerCapability,
2116
+ agentResource: atlas.agentResource,
2117
+ capabilityRefPattern: new RegExp(atlas.capabilityRefPattern),
2118
+ operationUnknown: atlas.operationUnknown,
2119
+ agentMissing: atlas.agentMissing,
2120
+ agentNotLiteral: atlas.agentNotLiteral,
2121
+ capabilitiesNotLiteral: atlas.capabilitiesNotLiteral,
2122
+ promptMissing: atlas.promptMissing,
2123
+ promptBoth: atlas.promptBoth,
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
2141
+ };
2031
2142
 
2032
2143
  // src/validators/executors.ts
2033
2144
  var SCHEME_SEPARATOR = "://";
@@ -2091,6 +2202,63 @@ function checkExecutor(executor, field, stepID, issues) {
2091
2202
  }
2092
2203
  checkFunctionOperation(executor, field, stepID, templated, issues);
2093
2204
  }
2205
+ function checkAtlasStep(executor, query, stepField, stepID, issues) {
2206
+ if (executor.includes(TEMPLATE_ACTION_OPEN)) return;
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);
2213
+ const quoted = JSON.stringify(stepID);
2214
+ const report = (rule, ...args) => {
2215
+ let message = rule.messageFormat.replace("%s", () => quoted);
2216
+ for (const a of args) message = message.replace("%s", () => a);
2217
+ issues.error({
2218
+ field: stepField,
2219
+ message,
2220
+ code: rule.code,
2221
+ stepId: stepID,
2222
+ suggestion: rule.suggestion
2223
+ });
2224
+ };
2225
+ const q2 = isRecord(query) ? query : {};
2226
+ let refusedKeys = ATLAS_EXECUTOR.paramRefused.capabilityKeys;
2227
+ if (provider === ATLAS_EXECUTOR.providerCapability) {
2228
+ if (!ATLAS_EXECUTOR.capabilityRefPattern.test(resource)) {
2229
+ report(ATLAS_EXECUTOR.capabilityRefInvalid, resource);
2230
+ }
2231
+ } else if (provider === ATLAS_EXECUTOR.providerAgent && resource === ATLAS_EXECUTOR.agentResource) {
2232
+ refusedKeys = ATLAS_EXECUTOR.paramRefused.agentKeys;
2233
+ const agent = q2.agent;
2234
+ if (typeof agent !== "string" || agent.trim() === "") {
2235
+ report(ATLAS_EXECUTOR.agentMissing);
2236
+ } else if (agent.includes(TEMPLATE_ACTION_OPEN)) {
2237
+ report(ATLAS_EXECUTOR.agentNotLiteral);
2238
+ }
2239
+ const hasPrompt = atlasTextPresent(q2.prompt);
2240
+ const hasTemplate = atlasTextPresent(q2.prompt_template);
2241
+ if (!hasPrompt && !hasTemplate) report(ATLAS_EXECUTOR.promptMissing);
2242
+ else if (hasPrompt && hasTemplate) report(ATLAS_EXECUTOR.promptBoth);
2243
+ if (anyTemplate(q2.model)) report(ATLAS_EXECUTOR.modelNotLiteral);
2244
+ } else {
2245
+ report(ATLAS_EXECUTOR.operationUnknown, executor);
2246
+ return;
2247
+ }
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() !== "";
2261
+ }
2094
2262
  function checkFunctionOperation(executor, field, stepID, templated, issues) {
2095
2263
  if (templated) return;
2096
2264
  const m = EXECUTOR_URL_PATTERN.exec(executor);
@@ -2115,6 +2283,7 @@ function validateExecutors(flow, issues) {
2115
2283
  const executor = issues.stringOf(step, "executor", `steps.${stepID}`);
2116
2284
  if (executor !== null && executor !== "") {
2117
2285
  checkExecutor(executor, `steps.${stepID}.executor`, stepID, issues);
2286
+ checkAtlasStep(executor, step.query, `steps.${stepID}`, stepID, issues);
2118
2287
  }
2119
2288
  const loop = step.loop;
2120
2289
  if (isRecord(loop) && Array.isArray(loop.steps)) {
@@ -2131,6 +2300,7 @@ function validateExecutors(flow, issues) {
2131
2300
  `${stepID}.${subID}`,
2132
2301
  issues
2133
2302
  );
2303
+ checkAtlasStep(subExecutor, subStep.query, subPath, `${stepID}.${subID}`, issues);
2134
2304
  }
2135
2305
  });
2136
2306
  }
@@ -3773,6 +3943,37 @@ function validateInputSchema(flow, issues) {
3773
3943
  validateSchemaDefinition(flow.input_schema, "input_schema", issues);
3774
3944
  }
3775
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
+
3776
3977
  // src/validators/outputSchema.ts
3777
3978
  function validateOutputSchemas(flow, issues) {
3778
3979
  const steps = flow.steps;
@@ -4887,7 +5088,7 @@ var CODE2 = "server_owned_query_key";
4887
5088
  var KEY_QUERY = "query";
4888
5089
  var KEY_ID = "id";
4889
5090
  var SERVER_OWNED = new Set(SERVER_OWNED_QUERY_KEYS.keys);
4890
- function formatField(format, ...args) {
5091
+ function formatField2(format, ...args) {
4891
5092
  let i = 0;
4892
5093
  return format.replace(/%s/g, () => args[i++] ?? "");
4893
5094
  }
@@ -4905,7 +5106,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
4905
5106
  issues,
4906
5107
  stepID,
4907
5108
  key,
4908
- formatField(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
5109
+ formatField2(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
4909
5110
  );
4910
5111
  }
4911
5112
  }
@@ -4919,7 +5120,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
4919
5120
  issues,
4920
5121
  stepID,
4921
5122
  key,
4922
- formatField(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
5123
+ formatField2(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
4923
5124
  );
4924
5125
  }
4925
5126
  }
@@ -5186,7 +5387,7 @@ function own(m, key) {
5186
5387
  if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5187
5388
  return m[key];
5188
5389
  }
5189
- function formatField2(format, ...args) {
5390
+ function formatField3(format, ...args) {
5190
5391
  let i = 0;
5191
5392
  return format.replace(/%s/g, () => args[i++] ?? "");
5192
5393
  }
@@ -5208,14 +5409,14 @@ function credentialEndpointSteps(flow, issues) {
5208
5409
  out.push({
5209
5410
  executor: issues.stringOf(step, KEY_EXECUTOR, `steps.${stepId}`) ?? "",
5210
5411
  query: own(step, KEY_QUERY2),
5211
- field: (key) => formatField2(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
5412
+ field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
5212
5413
  });
5213
5414
  for (const sub of loopSubStepsOfStep(stepId, step)) {
5214
5415
  const subId = issues.stringOf(sub.raw, KEY_ID2, sub.basePath) ?? "";
5215
5416
  out.push({
5216
5417
  executor: issues.stringOf(sub.raw, KEY_EXECUTOR, sub.basePath) ?? "",
5217
5418
  query: own(sub.raw, KEY_QUERY2),
5218
- field: (key) => formatField2(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
5419
+ field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
5219
5420
  });
5220
5421
  }
5221
5422
  }
@@ -5279,7 +5480,7 @@ function validateAI(flow, steps, issues) {
5279
5480
  if ((stepsUsing.get(provider) ?? 0) > 0 && (stepsWithoutOwnKey.get(provider) ?? 0) === 0) {
5280
5481
  continue;
5281
5482
  }
5282
- warnStoredShape(issues, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
5483
+ warnStoredShape(issues, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
5283
5484
  }
5284
5485
  }
5285
5486
  function warnStoredShape(issues, field, provider) {
@@ -5326,7 +5527,7 @@ function familySecret(flow, family, step, issues) {
5326
5527
  if (apiKey !== "" && listHas(family.secretParams, family.configApiKeyParam)) {
5327
5528
  return {
5328
5529
  envName: serverEnvRef(family, apiKey),
5329
- field: formatField2(
5530
+ field: formatField3(
5330
5531
  CREDENTIAL_ENDPOINT_PAIRING.executorConfigKeyFieldFormat,
5331
5532
  configKey,
5332
5533
  CREDENTIAL_ENDPOINT_PAIRING.executorConfigApiKeyField
@@ -5339,7 +5540,7 @@ function familySecret(flow, family, step, issues) {
5339
5540
  if (v !== null) {
5340
5541
  return {
5341
5542
  envName: serverEnvRef(family, v),
5342
- field: formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
5543
+ field: formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
5343
5544
  };
5344
5545
  }
5345
5546
  }
@@ -5365,13 +5566,13 @@ function familyAuthorEndpoint(flow, family, step, issues) {
5365
5566
  if (inst === null) continue;
5366
5567
  const baseUrl = configStringField(inst, configKey, CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlField, issues);
5367
5568
  if (baseUrl !== "" && listHas(family.endpointParams, family.configBaseUrlParam)) {
5368
- return decide(baseUrl, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
5569
+ return decide(baseUrl, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
5369
5570
  }
5370
5571
  const extra = own(inst, EXECUTOR_CONFIG_ENV_SCOPES.extraKey);
5371
5572
  for (const key of family.endpointParams) {
5372
5573
  const v = nonEmptyEndpoint(extra, key);
5373
5574
  if (v !== null)
5374
- return decide(v, formatField2(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
5575
+ return decide(v, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
5375
5576
  }
5376
5577
  }
5377
5578
  return null;
@@ -7082,6 +7283,7 @@ function validateParsed(flow, opts, sources) {
7082
7283
  validateOrchestratorCampaign(f, issues, opts);
7083
7284
  validateCredentialBindings(f, issues);
7084
7285
  validateInputSchema(f, issues);
7286
+ validateReservedInputNames(f, issues);
7085
7287
  validateOutputSchemas(f, issues);
7086
7288
  validateQualityGates(f, issues);
7087
7289
  validateProcessingOperations(f, issues);