@vaudience/aigentflow-flow-validator 0.26.0 → 0.28.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 +96 -4
- package/README.md +5 -2
- package/dist/cli.js +599 -398
- package/dist/index.cjs +592 -389
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +592 -389
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -455,11 +455,10 @@ function validateBasicStructure(flow, issues) {
|
|
|
455
455
|
// src/spec/aigentflow-spec.json
|
|
456
456
|
var aigentflow_spec_default = {
|
|
457
457
|
$comment: "Vendored enum surface mirrored from the AIgentFlow Go reference implementation. Regenerate / review on every flow-YAML schema change. See PARITY.md. Values here are public protocol/type names only.",
|
|
458
|
-
specVersion: "2.
|
|
458
|
+
specVersion: "2.837.0",
|
|
459
459
|
inputSchemaVersion: 1,
|
|
460
460
|
executorSchemes: [
|
|
461
461
|
"a2a",
|
|
462
|
-
"agent",
|
|
463
462
|
"ai",
|
|
464
463
|
"aiv",
|
|
465
464
|
"async",
|
|
@@ -473,7 +472,6 @@ var aigentflow_spec_default = {
|
|
|
473
472
|
"email",
|
|
474
473
|
"eurostat",
|
|
475
474
|
"eval",
|
|
476
|
-
"exons",
|
|
477
475
|
"flow",
|
|
478
476
|
"function",
|
|
479
477
|
"gdelt",
|
|
@@ -488,6 +486,7 @@ var aigentflow_spec_default = {
|
|
|
488
486
|
"messenger",
|
|
489
487
|
"mock",
|
|
490
488
|
"mqtt",
|
|
489
|
+
"nexus",
|
|
491
490
|
"opencorporates",
|
|
492
491
|
"openmeteo",
|
|
493
492
|
"overpass",
|
|
@@ -558,12 +557,9 @@ var aigentflow_spec_default = {
|
|
|
558
557
|
"step_failed",
|
|
559
558
|
"mission_started",
|
|
560
559
|
"mission_completed",
|
|
561
|
-
"dfm_suggestion",
|
|
562
560
|
"timer",
|
|
563
561
|
"request_turn",
|
|
564
562
|
"mission_recovered",
|
|
565
|
-
"campaign_child_completed",
|
|
566
|
-
"campaign_child_failed",
|
|
567
563
|
"human_response",
|
|
568
564
|
"human_input"
|
|
569
565
|
],
|
|
@@ -579,15 +575,6 @@ var aigentflow_spec_default = {
|
|
|
579
575
|
"aif_ask_human",
|
|
580
576
|
"aif_flow_list",
|
|
581
577
|
"aif_mission_reflect",
|
|
582
|
-
"aif_signal_complete",
|
|
583
|
-
"aif_signal_need_human",
|
|
584
|
-
"aif_signal_delegate",
|
|
585
|
-
"aif_signal_need_tool",
|
|
586
|
-
"aif_signal_modify_flow",
|
|
587
|
-
"aif_campaign_spawn",
|
|
588
|
-
"aif_campaign_status",
|
|
589
|
-
"aif_campaign_results",
|
|
590
|
-
"aif_campaign_cancel",
|
|
591
578
|
"aif_memory_plan",
|
|
592
579
|
"aif_memory_record",
|
|
593
580
|
"aif_memory_recall",
|
|
@@ -758,30 +745,94 @@ var aigentflow_spec_default = {
|
|
|
758
745
|
"fn_urldecode"
|
|
759
746
|
],
|
|
760
747
|
orchestratorToolAllow: {
|
|
761
|
-
$comment: "An orchestrator tool is offered only if it passes BOTH orchestrator.tools (empty = every tool) AND the inline exons definition's tools.allow (absent = no narrowing).
|
|
748
|
+
$comment: "An orchestrator tool is offered only if it passes BOTH orchestrator.tools (empty = every tool) AND the inline exons definition's tools.allow (absent = no narrowing). Only the lifecycle tools are exempt from tools.allow. A removed signal or campaign tool name (removedSignalSurfaces.tools, removedCampaignSurfaces.tools) is never reported as withheld: it is refused as signal_removed / campaign_removed. Reference: validateOrchestratorToolAllowWithholds (v2.760.0, signal and campaign arms removed in 2.834.0 / 2.836.0).",
|
|
762
749
|
warningField: "orchestrator.exons",
|
|
763
750
|
askHumanTool: "aif_ask_human",
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
751
|
+
lifecycleTools: [
|
|
752
|
+
"aif_mission_complete",
|
|
753
|
+
"aif_mission_fail",
|
|
754
|
+
"aif_request_turn"
|
|
755
|
+
]
|
|
756
|
+
},
|
|
757
|
+
exons: {
|
|
758
|
+
$comment: "The orchestrator's inline .exons document is still judged at the save door (orchestrator stays). A document opens with frontmatterDelimiter. Steps no longer carry inline .exons documents: the exons:// executor was removed (see removedAgentSurfaces).",
|
|
759
|
+
frontmatterDelimiter: "---"
|
|
760
|
+
},
|
|
761
|
+
removedAgentSurfaces: {
|
|
762
|
+
$comment: "AIgentFlow no longer runs agents of its own. executor_removed (ERROR): a step or loop sub-step whose executor scheme (text before '://', whitespace-trimmed, lower-cased) is in removedSchemes, or a top-level key in flowKeys (field = the key). agentic_param_removed (ERROR): an ai:// step or loop sub-step whose query carries ANY key of aiParams, on presence alone (null and false included); ONE finding per step, the keys sorted and joined by ', '. Only the paramScheme scheme is checked for params. A templated executor (containing templateActionOpen) is not judged. A step on a removed scheme yields ONLY executor_removed: no unknown_executor_scheme, executor-URL shape or inline-exons finding. Fields: steps.<id> and steps.<id>.loop.steps[<index>]. Not refused: aiv://, nexus:// (alias atlas://), ai:// tools / tool_choice / autofix / content_parts / stream, flow-level tool_discovery / discoverable_tools, the orchestrator block's own keys. Messages fill %s (the step id as written in the finding, then the scheme or the key list).",
|
|
763
|
+
removedSchemes: ["exons", "agent"],
|
|
764
|
+
paramScheme: "ai",
|
|
765
|
+
aiParams: [
|
|
766
|
+
"agentic",
|
|
767
|
+
"deny_tools",
|
|
768
|
+
"discoverable_tools",
|
|
769
|
+
"enable_signals",
|
|
770
|
+
"guardrails",
|
|
771
|
+
"max_tool_calls",
|
|
772
|
+
"max_tool_turns",
|
|
773
|
+
"mcp_server_url",
|
|
774
|
+
"parallel_tool_calls",
|
|
775
|
+
"require_confirmation",
|
|
776
|
+
"timeout_seconds",
|
|
777
|
+
"tool_auth_token",
|
|
778
|
+
"tool_discovery"
|
|
779
|
+
],
|
|
780
|
+
flowKeys: ["exons_uploads"],
|
|
781
|
+
executorRemovedCode: "executor_removed",
|
|
782
|
+
agenticParamRemovedCode: "agentic_param_removed",
|
|
783
|
+
schemeMessageFormat: "step %q uses %s://, which AIgentFlow no longer runs: its own agent chains were removed",
|
|
784
|
+
paramsMessageFormat: "step %q sets %s on ai://: AIgentFlow's own agent loop (agentic mode) was removed, so these parameters no longer exist",
|
|
785
|
+
flowKeyMessageFormat: "the flow-level key %q belonged to a removed agent surface and is no longer read",
|
|
786
|
+
suggestion: `Rebuild the step: a tool-using agent becomes nexus://agent/run (agent: "@org/name", prompt, capabilities); one tool becomes nexus://capability/<ref>; a plain prompt becomes ai://<provider>/chat or a prompt-only aiv://<org>/<name>. A nexus:// step acts as the person responsible for the run: who started it, who last saved its schedule or webhook trigger, or a flow:// child's parent. What cannot be converted: a run with no person (one started by a service or key that names nobody; share links no longer exist), and a step that needs an inline .exons spec, an arbitrary MCP server URL or signals. For those, start the flow from a person, a schedule or a trigger, or use a routine in Nexus`
|
|
787
|
+
},
|
|
788
|
+
removedSignalSurfaces: {
|
|
789
|
+
$comment: "AIgentFlow 2.834.0 removed agent signals and dynamic flow modification (DFM). signal_removed (ERROR): (a) orchestrator.enable_signals: true (field orchestrator.enable_signals); (b) one of tools named in orchestrator.tools, orchestrator.deny_tools, orchestrator.require_approval_for (field = that list) or in the orchestrator .exons definition's tools.allow (field orchestrator.exons) - ONE finding per list, the removed names in list order, each once; (c) stepKey on a step or loop sub-step whose scheme is stepKeyScheme (field steps.<id> / steps.<id>.loop.steps[<index>]). flow_modification_removed (ERROR): (a) orchestrator.triggers holds a trigger of a type in triggers (ONE finding, field orchestrator.triggers); (b) flowModificationStepKey in a step's or loop sub-step's query (any scheme). Step keys are judged on map PRESENCE (null and false included). Steps skipped: templated executors, removed schemes (removedAgentSurfaces.removedSchemes) and the schemes in stepSkipSchemes (a flow:// query carries the CHILD's inputs). removed_key_ignored (WARNING, never an error): checkpoint.pre_dfm with any non-null value, and orchestrator.enable_signals: false. A YAML null on either block key is absent. Tool and trigger names match exactly and case-sensitively. The removed names left the orchestrator tool and trigger registries, but they are TOLERATED by the unknown-name checks, and enable_signals / pre_dfm stay in knownKeys, so the only finding is the new code. Order: the orchestrator block (enable_signals, then the lists, then triggers), then steps by id with loop sub-steps after their parent. Reference: aigentflow.removed.signalsurfaces.go.",
|
|
790
|
+
signalRemovedCode: "signal_removed",
|
|
791
|
+
flowModificationRemovedCode: "flow_modification_removed",
|
|
792
|
+
removedKeyIgnoredCode: "removed_key_ignored",
|
|
793
|
+
tools: [
|
|
767
794
|
"aif_signal_complete",
|
|
768
795
|
"aif_signal_need_human",
|
|
769
796
|
"aif_signal_delegate",
|
|
770
797
|
"aif_signal_need_tool",
|
|
771
798
|
"aif_signal_modify_flow"
|
|
772
799
|
],
|
|
773
|
-
|
|
774
|
-
"
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
800
|
+
triggers: [
|
|
801
|
+
"dfm_suggestion"
|
|
802
|
+
],
|
|
803
|
+
stepKey: "enable_signals",
|
|
804
|
+
stepKeyScheme: "aiv",
|
|
805
|
+
flowModificationStepKey: "flow_modification_allowed",
|
|
806
|
+
stepSkipSchemes: [
|
|
807
|
+
"flow"
|
|
808
|
+
],
|
|
809
|
+
enableSignalsMessage: "the orchestrator sets enable_signals: true: AIgentFlow's agent signals were removed in 2.834.0, so the tools it asks for no longer exist",
|
|
810
|
+
toolNamesMessageFormat: "%s names %s: AIgentFlow's agent signal tools were removed in 2.834.0",
|
|
811
|
+
stepKeyMessageFormat: "step %q sets enable_signals: AIgentFlow's agent signals were removed in 2.834.0, so the parameter no longer exists",
|
|
812
|
+
triggersMessage: "orchestrator.triggers names dfm_suggestion: dynamic flow modification was removed in 2.834.0, so nothing raises that trigger",
|
|
813
|
+
flowModificationStepMessageFormat: "step %q sets flow_modification_allowed: dynamic flow modification was removed in 2.834.0",
|
|
814
|
+
ignoredKeyMessageFormat: "%s is ignored: it configured AIgentFlow's agent signals / dynamic flow modification, removed in 2.834.0. AIgentFlow may have written this key into the flow itself; the flow runs as if it were absent",
|
|
815
|
+
ignoredKeySuggestion: "Remove the key; nothing reads it",
|
|
816
|
+
suggestion: "Signals and dynamic flow modification were removed in 2.834.0. aif_signal_need_human: add an async://human/<operation> step where the person must answer (inside a nexus://agent/run step, the atlas approval wait asks the person). aif_signal_delegate: run the other work as a flow:// step, or route with next: conditions. aif_signal_complete: an orchestrator ends the mission with aif_mission_complete. aif_signal_need_tool: no replacement; give the agent the capability in atlas. aif_signal_modify_flow, dfm_suggestion and flow_modification_allowed: no replacement; declare every step the flow may run and choose between them with next: conditions"
|
|
779
817
|
},
|
|
780
|
-
|
|
781
|
-
$comment: "
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
818
|
+
removedCampaignSurfaces: {
|
|
819
|
+
$comment: "AIgentFlow 2.836.0 removed campaigns. campaign_removed (ERROR): (a) the flow-root key flowKey with ANY non-null value (field campaign; the block is refused whole and nothing inside it is judged: no campaign rule, retired-key or unknown-key finding); (b) one of tools in orchestrator.tools, orchestrator.deny_tools, orchestrator.require_approval_for (field = the list) or the orchestrator .exons definition's tools.allow (field orchestrator.exons) - ONE finding per list, names in list order, each once; (c) orchestrator.triggers holding a trigger of a type in triggers (ONE finding, field orchestrator.triggers, the removed types in order, each once). Steps are never judged. Names match exactly and case-sensitively, and are tolerated by the unknown-name checks. There is no removed_key_ignored warning for campaigns. Order: block, then the lists (tools, deny_tools, require_approval_for, tools.allow), then triggers. Reference: aigentflow.removed.campaignsurfaces.go.",
|
|
820
|
+
code: "campaign_removed",
|
|
821
|
+
flowKey: "campaign",
|
|
822
|
+
tools: [
|
|
823
|
+
"aif_campaign_spawn",
|
|
824
|
+
"aif_campaign_status",
|
|
825
|
+
"aif_campaign_results",
|
|
826
|
+
"aif_campaign_cancel"
|
|
827
|
+
],
|
|
828
|
+
triggers: [
|
|
829
|
+
"campaign_child_completed",
|
|
830
|
+
"campaign_child_failed"
|
|
831
|
+
],
|
|
832
|
+
blockMessage: "the flow declares a campaign: block: campaigns were removed in 2.836.0, so nothing would spawn or track its child missions",
|
|
833
|
+
toolNamesMessageFormat: "%s names %s: AIgentFlow's campaign tools were removed in 2.836.0",
|
|
834
|
+
triggersMessageFormat: "orchestrator.triggers names %s: campaigns were removed in 2.836.0, so no child mission raises that trigger",
|
|
835
|
+
suggestion: "Campaigns were removed in 2.836.0. Fan the work out inside one flow instead: a for_each step whose executor is flow://stored/<flow_id> runs the child flow once per item and hands the next step every result (.data.<step>, in item order), so a coordinator -> workers -> synthesiser campaign becomes a plan step -> a for_each over flow:// -> a synthesis step (a fixed set of different workers is next: parallel: with a rendezvous). When each worker is an agent, make the worker a nexus://agent/run step (the for_each step itself, or a step of the child flow): it runs as the person responsible for the run, and a flow:// child inherits its parent's. Delete the campaign: block, the aif_campaign_* tool names and the campaign_child_* triggers"
|
|
785
836
|
},
|
|
786
837
|
executorConfigEnvScopes: {
|
|
787
838
|
$comment: "executor_config may expand only the environment variables of the key it is written under. A value is a reference when it starts with referencePrefix and ends with referenceSuffix around a non-empty name. Checked fields: fields, plus every string value of extra (prefixed extraFieldPrefix in the message). A key absent from scopes has an EMPTY scope and refuses every reference. scopes is the reference's executorConfigEnvScope evaluated for every key with a non-empty scope. Reference: ValidateExecutorConfigEnvScopes (v2.597.0).",
|
|
@@ -1008,20 +1059,21 @@ var aigentflow_spec_default = {
|
|
|
1008
1059
|
]
|
|
1009
1060
|
},
|
|
1010
1061
|
atlasExecutor: {
|
|
1011
|
-
$comment: "
|
|
1012
|
-
scheme: "
|
|
1062
|
+
$comment: "nexus://<provider>/<resource> (alias atlas://, the same rules for both spellings since AIgentFlow 2.835.0; the scheme match is exact and case-sensitive against scheme and aliases): calls an agent or a capability in Nexus. An AigentChat-shaped nexus://<org>/<agent> (the executor removed in 2.819.0) is atlas_operation_unknown. Codes keep the atlas_ prefix. 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 the scheme.",
|
|
1063
|
+
scheme: "nexus",
|
|
1064
|
+
aliases: ["atlas"],
|
|
1013
1065
|
providerAgent: "agent",
|
|
1014
1066
|
providerCapability: "capability",
|
|
1015
1067
|
agentResource: "run",
|
|
1016
1068
|
capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$",
|
|
1017
1069
|
operationUnknown: {
|
|
1018
1070
|
code: "atlas_operation_unknown",
|
|
1019
|
-
messageFormat: "step %s uses %s, which is not
|
|
1020
|
-
suggestion: "Use
|
|
1071
|
+
messageFormat: "step %s uses %s, which is not a Nexus operation. The providers are agent (resource run) and capability (resource: a capability reference).",
|
|
1072
|
+
suggestion: "Use nexus://agent/run or nexus://capability/<capability-ref>."
|
|
1021
1073
|
},
|
|
1022
1074
|
agentMissing: {
|
|
1023
1075
|
code: "atlas_agent_missing",
|
|
1024
|
-
messageFormat: "step %s runs
|
|
1076
|
+
messageFormat: "step %s runs a Nexus agent but query.agent is missing, empty or not a string.",
|
|
1025
1077
|
suggestion: "Set query.agent to the agent to run, written out as a literal such as @acme/reporter."
|
|
1026
1078
|
},
|
|
1027
1079
|
agentNotLiteral: {
|
|
@@ -1036,7 +1088,7 @@ var aigentflow_spec_default = {
|
|
|
1036
1088
|
},
|
|
1037
1089
|
promptMissing: {
|
|
1038
1090
|
code: "atlas_prompt_missing",
|
|
1039
|
-
messageFormat: "step %s runs
|
|
1091
|
+
messageFormat: "step %s runs a Nexus agent with neither query.prompt nor query.prompt_template.",
|
|
1040
1092
|
suggestion: "Set exactly one of query.prompt or query.prompt_template."
|
|
1041
1093
|
},
|
|
1042
1094
|
promptBoth: {
|
|
@@ -1046,7 +1098,7 @@ var aigentflow_spec_default = {
|
|
|
1046
1098
|
},
|
|
1047
1099
|
capabilityRefInvalid: {
|
|
1048
1100
|
code: "atlas_capability_ref_invalid",
|
|
1049
|
-
messageFormat: "step %s uses
|
|
1101
|
+
messageFormat: "step %s uses nexus://capability/%s, which is not a valid capability reference.",
|
|
1050
1102
|
suggestion: "A capability reference starts with a letter or digit and continues with letters, digits, _ and - up to 128 characters in all."
|
|
1051
1103
|
},
|
|
1052
1104
|
modelNotLiteral: {
|
|
@@ -1643,20 +1695,6 @@ var aigentflow_spec_default = {
|
|
|
1643
1695
|
BillingConfig: {
|
|
1644
1696
|
max_credits: "scalar"
|
|
1645
1697
|
},
|
|
1646
|
-
CampaignChildFlowDef: {
|
|
1647
|
-
alias: "scalar",
|
|
1648
|
-
flow_id: "scalar",
|
|
1649
|
-
flow_name: "scalar"
|
|
1650
|
-
},
|
|
1651
|
-
CampaignConfig: {
|
|
1652
|
-
child_flows: "list<CampaignChildFlowDef>",
|
|
1653
|
-
max_concurrent: "scalar",
|
|
1654
|
-
max_credits_per_child: "scalar",
|
|
1655
|
-
max_depth: "scalar",
|
|
1656
|
-
max_total_children: "scalar",
|
|
1657
|
-
on_children_complete: "scalar",
|
|
1658
|
-
shared_memory: "scalar"
|
|
1659
|
-
},
|
|
1660
1698
|
Checkpoint: {
|
|
1661
1699
|
exact: "map<any>",
|
|
1662
1700
|
fields: "map<FieldMatcher>",
|
|
@@ -1790,7 +1828,7 @@ var aigentflow_spec_default = {
|
|
|
1790
1828
|
Flow: {
|
|
1791
1829
|
aigentflow_version: "scalar",
|
|
1792
1830
|
billing: "BillingConfig",
|
|
1793
|
-
campaign: "
|
|
1831
|
+
campaign: "any",
|
|
1794
1832
|
checkpoint: "CheckpointConfig",
|
|
1795
1833
|
classification: "FlowClassification",
|
|
1796
1834
|
compliance: "FlowCompliance",
|
|
@@ -2105,19 +2143,64 @@ var KNOWN_KEYS = aigentflow_spec_default.knownKeys;
|
|
|
2105
2143
|
var ORCHESTRATOR_TOOL_ALLOW = {
|
|
2106
2144
|
warningField: aigentflow_spec_default.orchestratorToolAllow.warningField,
|
|
2107
2145
|
askHumanTool: aigentflow_spec_default.orchestratorToolAllow.askHumanTool,
|
|
2108
|
-
|
|
2109
|
-
lifecycleTools: aigentflow_spec_default.orchestratorToolAllow.lifecycleTools,
|
|
2110
|
-
signalTools: aigentflow_spec_default.orchestratorToolAllow.signalTools,
|
|
2111
|
-
campaignTools: aigentflow_spec_default.orchestratorToolAllow.campaignTools
|
|
2146
|
+
lifecycleTools: aigentflow_spec_default.orchestratorToolAllow.lifecycleTools
|
|
2112
2147
|
};
|
|
2113
2148
|
var EXONS = {
|
|
2114
|
-
/** A step's document is judged only on an executor with this prefix. */
|
|
2115
|
-
executorPrefix: aigentflow_spec_default.exons.executorPrefix,
|
|
2116
|
-
/** The step `query` parameter that carries the document. */
|
|
2117
|
-
documentParam: aigentflow_spec_default.exons.documentParam,
|
|
2118
2149
|
/** The YAML frontmatter delimiter line. */
|
|
2119
2150
|
frontmatterDelimiter: aigentflow_spec_default.exons.frontmatterDelimiter
|
|
2120
2151
|
};
|
|
2152
|
+
var removed = aigentflow_spec_default.removedAgentSurfaces;
|
|
2153
|
+
var REMOVED_AGENT_SURFACES = {
|
|
2154
|
+
schemes: new Set(removed.removedSchemes),
|
|
2155
|
+
paramScheme: removed.paramScheme,
|
|
2156
|
+
aiParams: new Set(removed.aiParams),
|
|
2157
|
+
flowKeys: removed.flowKeys,
|
|
2158
|
+
executorRemovedCode: removed.executorRemovedCode,
|
|
2159
|
+
agenticParamRemovedCode: removed.agenticParamRemovedCode,
|
|
2160
|
+
schemeMessageFormat: removed.schemeMessageFormat,
|
|
2161
|
+
paramsMessageFormat: removed.paramsMessageFormat,
|
|
2162
|
+
flowKeyMessageFormat: removed.flowKeyMessageFormat,
|
|
2163
|
+
suggestion: removed.suggestion
|
|
2164
|
+
};
|
|
2165
|
+
var signal = aigentflow_spec_default.removedSignalSurfaces;
|
|
2166
|
+
var REMOVED_SIGNAL_SURFACES = {
|
|
2167
|
+
signalRemovedCode: signal.signalRemovedCode,
|
|
2168
|
+
flowModificationRemovedCode: signal.flowModificationRemovedCode,
|
|
2169
|
+
removedKeyIgnoredCode: signal.removedKeyIgnoredCode,
|
|
2170
|
+
tools: signal.tools,
|
|
2171
|
+
triggers: signal.triggers,
|
|
2172
|
+
stepKey: signal.stepKey,
|
|
2173
|
+
stepKeyScheme: signal.stepKeyScheme,
|
|
2174
|
+
flowModificationStepKey: signal.flowModificationStepKey,
|
|
2175
|
+
stepSkipSchemes: new Set(signal.stepSkipSchemes),
|
|
2176
|
+
enableSignalsMessage: signal.enableSignalsMessage,
|
|
2177
|
+
toolNamesMessageFormat: signal.toolNamesMessageFormat,
|
|
2178
|
+
stepKeyMessageFormat: signal.stepKeyMessageFormat,
|
|
2179
|
+
triggersMessage: signal.triggersMessage,
|
|
2180
|
+
flowModificationStepMessageFormat: signal.flowModificationStepMessageFormat,
|
|
2181
|
+
ignoredKeyMessageFormat: signal.ignoredKeyMessageFormat,
|
|
2182
|
+
ignoredKeySuggestion: signal.ignoredKeySuggestion,
|
|
2183
|
+
suggestion: signal.suggestion
|
|
2184
|
+
};
|
|
2185
|
+
var campaign = aigentflow_spec_default.removedCampaignSurfaces;
|
|
2186
|
+
var REMOVED_CAMPAIGN_SURFACES = {
|
|
2187
|
+
code: campaign.code,
|
|
2188
|
+
flowKey: campaign.flowKey,
|
|
2189
|
+
tools: campaign.tools,
|
|
2190
|
+
triggers: campaign.triggers,
|
|
2191
|
+
blockMessage: campaign.blockMessage,
|
|
2192
|
+
toolNamesMessageFormat: campaign.toolNamesMessageFormat,
|
|
2193
|
+
triggersMessageFormat: campaign.triggersMessageFormat,
|
|
2194
|
+
suggestion: campaign.suggestion
|
|
2195
|
+
};
|
|
2196
|
+
var REMOVED_ORCHESTRATOR_TOOLS = /* @__PURE__ */ new Set([
|
|
2197
|
+
...signal.tools,
|
|
2198
|
+
...campaign.tools
|
|
2199
|
+
]);
|
|
2200
|
+
var REMOVED_ORCHESTRATOR_TRIGGERS = /* @__PURE__ */ new Set([
|
|
2201
|
+
...signal.triggers,
|
|
2202
|
+
...campaign.triggers
|
|
2203
|
+
]);
|
|
2121
2204
|
var EXECUTOR_CONFIG_ENV_SCOPES = {
|
|
2122
2205
|
referencePrefix: aigentflow_spec_default.executorConfigEnvScopes.referencePrefix,
|
|
2123
2206
|
referenceSuffix: aigentflow_spec_default.executorConfigEnvScopes.referenceSuffix,
|
|
@@ -2214,6 +2297,8 @@ var FUNCTION_OPERATIONS = {
|
|
|
2214
2297
|
var atlas = aigentflow_spec_default.atlasExecutor;
|
|
2215
2298
|
var ATLAS_EXECUTOR = {
|
|
2216
2299
|
scheme: atlas.scheme,
|
|
2300
|
+
/** The canonical scheme (nexus) and its aliases (atlas): one set of rules. */
|
|
2301
|
+
schemes: /* @__PURE__ */ new Set([atlas.scheme, ...atlas.aliases]),
|
|
2217
2302
|
providerAgent: atlas.providerAgent,
|
|
2218
2303
|
providerCapability: atlas.providerCapability,
|
|
2219
2304
|
agentResource: atlas.agentResource,
|
|
@@ -2243,6 +2328,223 @@ var RESERVED_INPUT_NAMES = {
|
|
|
2243
2328
|
schemaFieldFormat: aigentflow_spec_default.reservedInputNames.schemaFieldFormat
|
|
2244
2329
|
};
|
|
2245
2330
|
|
|
2331
|
+
// src/validators/exons.ts
|
|
2332
|
+
import { isMap as isMap2, isScalar as isScalar2, isSeq as isSeq2, parseAllDocuments } from "yaml";
|
|
2333
|
+
var CODE_PARSE_FAILED = "orchestrator_exons_parse_failed";
|
|
2334
|
+
var CODE_NO_PROVIDER = "orchestrator_exons_no_provider";
|
|
2335
|
+
var CODE_RESOURCES = "exons_resources_unhonoured";
|
|
2336
|
+
var CODE_TOOL_WITHHELD = "orchestrator_tool_withheld";
|
|
2337
|
+
var EXONS_OPEN_DELIM = "{~";
|
|
2338
|
+
var EXONS_LEGACY_CONFIG_OPEN = "{~exons.config~}";
|
|
2339
|
+
var UTF8_BOM = "\uFEFF";
|
|
2340
|
+
var MAX_ALIAS_COUNT2 = 100;
|
|
2341
|
+
var UNREAD = {
|
|
2342
|
+
parseError: null,
|
|
2343
|
+
specRead: false,
|
|
2344
|
+
hasSpec: false,
|
|
2345
|
+
provider: "",
|
|
2346
|
+
toolsAllowDeclared: false,
|
|
2347
|
+
toolsAllow: [],
|
|
2348
|
+
resources: []
|
|
2349
|
+
};
|
|
2350
|
+
var GO_SPACE = "\\t\\n\\v\\f\\r \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000";
|
|
2351
|
+
var GO_TRIM_SPACE = new RegExp(`^[${GO_SPACE}]+|[${GO_SPACE}]+$`, "g");
|
|
2352
|
+
function goTrimSpace(s) {
|
|
2353
|
+
return s.replace(GO_TRIM_SPACE, "");
|
|
2354
|
+
}
|
|
2355
|
+
function extractExonsFrontmatter(source) {
|
|
2356
|
+
const delim = EXONS.frontmatterDelimiter;
|
|
2357
|
+
let start = source.startsWith(UTF8_BOM) ? source.slice(UTF8_BOM.length) : source;
|
|
2358
|
+
start = start.replace(/^[ \t]+/, "");
|
|
2359
|
+
if (start.startsWith(EXONS_LEGACY_CONFIG_OPEN)) {
|
|
2360
|
+
return {
|
|
2361
|
+
frontmatter: "",
|
|
2362
|
+
hasFrontmatter: false,
|
|
2363
|
+
parseError: "legacy JSON config block detected; use YAML frontmatter"
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
if (!start.startsWith(delim)) return { frontmatter: "", hasFrontmatter: false, parseError: null };
|
|
2367
|
+
let rest = start.slice(delim.length);
|
|
2368
|
+
if (rest.startsWith("\n")) rest = rest.slice(1);
|
|
2369
|
+
else if (rest.startsWith("\r\n")) rest = rest.slice(2);
|
|
2370
|
+
else return { frontmatter: "", hasFrontmatter: false, parseError: null };
|
|
2371
|
+
let pos = 0;
|
|
2372
|
+
while (pos <= rest.length) {
|
|
2373
|
+
const line = rest.slice(pos);
|
|
2374
|
+
if (line.startsWith(delim)) {
|
|
2375
|
+
const after = line.slice(delim.length);
|
|
2376
|
+
if (after === "" || after[0] === "\n" || after[0] === "\r") {
|
|
2377
|
+
return {
|
|
2378
|
+
frontmatter: goTrimSpace(rest.slice(0, pos)),
|
|
2379
|
+
hasFrontmatter: true,
|
|
2380
|
+
parseError: null
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
const nl = line.indexOf("\n");
|
|
2385
|
+
if (nl < 0) break;
|
|
2386
|
+
pos += nl + 1;
|
|
2387
|
+
}
|
|
2388
|
+
return {
|
|
2389
|
+
frontmatter: "",
|
|
2390
|
+
hasFrontmatter: true,
|
|
2391
|
+
parseError: "YAML frontmatter not properly closed"
|
|
2392
|
+
};
|
|
2393
|
+
}
|
|
2394
|
+
function retagScalars(node) {
|
|
2395
|
+
if (isMap2(node)) {
|
|
2396
|
+
for (const pair of node.items) {
|
|
2397
|
+
retagScalars(pair.key);
|
|
2398
|
+
retagScalars(pair.value);
|
|
2399
|
+
}
|
|
2400
|
+
} else if (isSeq2(node)) {
|
|
2401
|
+
for (const item of node.items) retagScalars(item);
|
|
2402
|
+
} else if (isScalar2(node) && (typeof node.value === "number" || typeof node.value === "boolean") && typeof node.source === "string") {
|
|
2403
|
+
node.value = node.source;
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
var DecodeError = class extends Error {
|
|
2407
|
+
};
|
|
2408
|
+
function goString(v) {
|
|
2409
|
+
if (v === null || v === void 0) return "";
|
|
2410
|
+
if (isString(v)) return v;
|
|
2411
|
+
throw new DecodeError("not a string");
|
|
2412
|
+
}
|
|
2413
|
+
function goStringList(v) {
|
|
2414
|
+
if (v === null || v === void 0) return null;
|
|
2415
|
+
if (!isArray(v)) throw new DecodeError("not a list");
|
|
2416
|
+
return v.filter((item) => item !== null).map(goString);
|
|
2417
|
+
}
|
|
2418
|
+
function goStruct(v) {
|
|
2419
|
+
if (v === null || v === void 0) return null;
|
|
2420
|
+
if (!isRecord(v)) throw new DecodeError("not a mapping");
|
|
2421
|
+
return v;
|
|
2422
|
+
}
|
|
2423
|
+
function decodeSpecFields(frontmatter) {
|
|
2424
|
+
let value;
|
|
2425
|
+
try {
|
|
2426
|
+
const docs = parseAllDocuments(frontmatter, { merge: true });
|
|
2427
|
+
const doc = Array.isArray(docs) ? docs[0] : void 0;
|
|
2428
|
+
if (doc === void 0) {
|
|
2429
|
+
value = null;
|
|
2430
|
+
} else {
|
|
2431
|
+
if (doc.errors.length > 0) return null;
|
|
2432
|
+
retagScalars(doc.contents);
|
|
2433
|
+
value = doc.toJS({ maxAliasCount: MAX_ALIAS_COUNT2 });
|
|
2434
|
+
}
|
|
2435
|
+
} catch {
|
|
2436
|
+
return null;
|
|
2437
|
+
}
|
|
2438
|
+
try {
|
|
2439
|
+
const root = goStruct(value) ?? {};
|
|
2440
|
+
const execution = goStruct(root.execution);
|
|
2441
|
+
const tools = goStruct(root.tools);
|
|
2442
|
+
const requirements = goStruct(root.requirements);
|
|
2443
|
+
const allow = tools === null ? null : goStringList(tools.allow);
|
|
2444
|
+
let resources = [];
|
|
2445
|
+
if (requirements !== null) {
|
|
2446
|
+
const raw = requirements.resources;
|
|
2447
|
+
if (raw !== null && raw !== void 0) {
|
|
2448
|
+
if (!isArray(raw)) throw new DecodeError("not a list");
|
|
2449
|
+
resources = raw.filter((entry) => entry !== null).map((entry) => {
|
|
2450
|
+
const r = goStruct(entry) ?? {};
|
|
2451
|
+
return { ref: goString(r.ref), kind: goString(r.kind), scope: goString(r.scope) };
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
return {
|
|
2456
|
+
provider: execution === null ? "" : goString(execution.provider),
|
|
2457
|
+
toolsAllowDeclared: allow !== null,
|
|
2458
|
+
toolsAllow: allow ?? [],
|
|
2459
|
+
resources
|
|
2460
|
+
};
|
|
2461
|
+
} catch (e) {
|
|
2462
|
+
if (e instanceof DecodeError) return null;
|
|
2463
|
+
throw e;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
function inspectExonsFrontmatter(source) {
|
|
2467
|
+
const fm = extractExonsFrontmatter(source);
|
|
2468
|
+
if (fm.parseError !== null) return { ...UNREAD, parseError: fm.parseError };
|
|
2469
|
+
if (!fm.hasFrontmatter || fm.frontmatter === "") return { ...UNREAD, specRead: true };
|
|
2470
|
+
if (fm.frontmatter.includes(EXONS_OPEN_DELIM)) return { ...UNREAD };
|
|
2471
|
+
const fields = decodeSpecFields(fm.frontmatter);
|
|
2472
|
+
if (fields === null) return { ...UNREAD };
|
|
2473
|
+
return { parseError: null, specRead: true, hasSpec: true, ...fields };
|
|
2474
|
+
}
|
|
2475
|
+
function validateOrchestratorExons(flow, issues) {
|
|
2476
|
+
const orch = flow.orchestrator;
|
|
2477
|
+
if (!isRecord(orch)) return;
|
|
2478
|
+
const source = issues.stringOf(orch, "exons", "orchestrator");
|
|
2479
|
+
if (source === null || source === "") return;
|
|
2480
|
+
const field = "orchestrator.exons";
|
|
2481
|
+
const report = inspectExonsFrontmatter(source);
|
|
2482
|
+
if (report.parseError !== null) {
|
|
2483
|
+
issues.error({
|
|
2484
|
+
field,
|
|
2485
|
+
code: CODE_PARSE_FAILED,
|
|
2486
|
+
message: `orchestrator: failed to parse exons spec: ${report.parseError}`
|
|
2487
|
+
});
|
|
2488
|
+
return;
|
|
2489
|
+
}
|
|
2490
|
+
if (!report.specRead) return;
|
|
2491
|
+
if (!report.hasSpec) {
|
|
2492
|
+
issues.error({
|
|
2493
|
+
field,
|
|
2494
|
+
code: CODE_PARSE_FAILED,
|
|
2495
|
+
message: "orchestrator: failed to parse exons spec: the document has no frontmatter spec",
|
|
2496
|
+
suggestion: "Start the document with a --- frontmatter block that sets execution.provider"
|
|
2497
|
+
});
|
|
2498
|
+
return;
|
|
2499
|
+
}
|
|
2500
|
+
if (report.provider === "") {
|
|
2501
|
+
issues.error({
|
|
2502
|
+
field,
|
|
2503
|
+
code: CODE_NO_PROVIDER,
|
|
2504
|
+
message: "orchestrator: exons spec must have execution.provider set"
|
|
2505
|
+
});
|
|
2506
|
+
}
|
|
2507
|
+
if (report.resources.length > 0) {
|
|
2508
|
+
const refs = report.resources.map((r) => `${JSON.stringify(r.ref)} (kind ${r.kind})`);
|
|
2509
|
+
issues.error({
|
|
2510
|
+
field,
|
|
2511
|
+
code: CODE_RESOURCES,
|
|
2512
|
+
message: "the orchestrator's exons spec declares requirements.resources that AIgentFlow cannot honour, so it is refused rather than run without the narrowing it asks for: " + refs.join("; "),
|
|
2513
|
+
suggestion: "Remove requirements.resources, and narrow the agent with tools.mcp_servers and tools.allow"
|
|
2514
|
+
});
|
|
2515
|
+
}
|
|
2516
|
+
warnOrchestratorToolWithheld(orch, report, issues);
|
|
2517
|
+
}
|
|
2518
|
+
function warnOrchestratorToolWithheld(orch, report, issues) {
|
|
2519
|
+
if (!report.toolsAllowDeclared) return;
|
|
2520
|
+
const cfg = ORCHESTRATOR_TOOL_ALLOW;
|
|
2521
|
+
const exempt = new Set(cfg.lifecycleTools);
|
|
2522
|
+
const allow = new Set(report.toolsAllow);
|
|
2523
|
+
const withheld = (name) => !allow.has(name) && !exempt.has(name) && !REMOVED_ORCHESTRATOR_TOOLS.has(name);
|
|
2524
|
+
const warn = (message) => issues.warn({ field: cfg.warningField, code: CODE_TOOL_WITHHELD, message });
|
|
2525
|
+
const named = [];
|
|
2526
|
+
if (isArray(orch.tools)) {
|
|
2527
|
+
orch.tools.forEach((raw, i) => {
|
|
2528
|
+
const name = issues.stringAt(raw, `orchestrator.tools[${i}]`);
|
|
2529
|
+
if (name !== null) named.push(name);
|
|
2530
|
+
});
|
|
2531
|
+
}
|
|
2532
|
+
if (named.length > 0) {
|
|
2533
|
+
for (const name of named) {
|
|
2534
|
+
if (!withheld(name)) continue;
|
|
2535
|
+
warn(
|
|
2536
|
+
`orchestrator tool '${name}' is named in orchestrator.tools but the orchestrator's exons definition's tools.allow does not name it, so it is never offered: a tool must pass both lists. Add '${name}' to tools.allow, or remove it from orchestrator.tools.`
|
|
2537
|
+
);
|
|
2538
|
+
}
|
|
2539
|
+
return;
|
|
2540
|
+
}
|
|
2541
|
+
if (withheld(cfg.askHumanTool)) {
|
|
2542
|
+
warn(
|
|
2543
|
+
`the orchestrator's exons definition has a tools.allow list that does not name ${cfg.askHumanTool}, so this orchestrator can never ask a person a question: human intervention is off. Add ${cfg.askHumanTool} to tools.allow if a human should be reachable, or ignore this if the orchestrator is meant to run unattended.`
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2246
2548
|
// src/validators/executors.ts
|
|
2247
2549
|
var SCHEME_SEPARATOR = "://";
|
|
2248
2550
|
var UNKNOWN_SCHEME_BASE = (scheme) => `Unknown executor scheme '${scheme}'. It may be valid in a newer AIgentFlow release, or it could be a typo.`;
|
|
@@ -2305,11 +2607,61 @@ function checkExecutor(executor, field, stepID, issues) {
|
|
|
2305
2607
|
}
|
|
2306
2608
|
checkFunctionOperation(executor, field, stepID, templated, issues);
|
|
2307
2609
|
}
|
|
2610
|
+
function removedExecutorScheme(executor) {
|
|
2611
|
+
if (executor.includes(TEMPLATE_ACTION_OPEN)) return "";
|
|
2612
|
+
const trimmed = goTrimSpace(executor);
|
|
2613
|
+
const at = trimmed.indexOf(SCHEME_SEPARATOR);
|
|
2614
|
+
return at < 0 ? "" : trimmed.slice(0, at).toLowerCase();
|
|
2615
|
+
}
|
|
2616
|
+
function checkRemovedSurfaces(executor, query, field, stepID, issues) {
|
|
2617
|
+
const cfg = REMOVED_AGENT_SURFACES;
|
|
2618
|
+
const quoted = JSON.stringify(stepID);
|
|
2619
|
+
const scheme = removedExecutorScheme(executor);
|
|
2620
|
+
if (cfg.schemes.has(scheme)) {
|
|
2621
|
+
issues.error({
|
|
2622
|
+
field,
|
|
2623
|
+
message: fillRemovedMessage(cfg.schemeMessageFormat, quoted, scheme),
|
|
2624
|
+
code: cfg.executorRemovedCode,
|
|
2625
|
+
stepId: stepID,
|
|
2626
|
+
suggestion: cfg.suggestion
|
|
2627
|
+
});
|
|
2628
|
+
return true;
|
|
2629
|
+
}
|
|
2630
|
+
if (scheme !== cfg.paramScheme || !isRecord(query)) return false;
|
|
2631
|
+
const found = Object.keys(query).filter((key) => cfg.aiParams.has(key)).sort();
|
|
2632
|
+
if (found.length > 0) {
|
|
2633
|
+
issues.error({
|
|
2634
|
+
field,
|
|
2635
|
+
message: fillRemovedMessage(cfg.paramsMessageFormat, quoted, found.join(", ")),
|
|
2636
|
+
code: cfg.agenticParamRemovedCode,
|
|
2637
|
+
stepId: stepID,
|
|
2638
|
+
suggestion: cfg.suggestion
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
return false;
|
|
2642
|
+
}
|
|
2643
|
+
function fillRemovedMessage(format, ...args) {
|
|
2644
|
+
let i = 0;
|
|
2645
|
+
return format.replace(/%[qs]/g, () => args[i++] ?? "");
|
|
2646
|
+
}
|
|
2647
|
+
function validateRemovedFlowKeys(flow, issues) {
|
|
2648
|
+
const cfg = REMOVED_AGENT_SURFACES;
|
|
2649
|
+
for (const key of cfg.flowKeys) {
|
|
2650
|
+
if (Object.prototype.hasOwnProperty.call(flow, key)) {
|
|
2651
|
+
issues.error({
|
|
2652
|
+
field: key,
|
|
2653
|
+
message: fillRemovedMessage(cfg.flowKeyMessageFormat, JSON.stringify(key)),
|
|
2654
|
+
code: cfg.executorRemovedCode,
|
|
2655
|
+
suggestion: cfg.suggestion
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2308
2660
|
function checkAtlasStep(executor, query, stepField, stepID, issues) {
|
|
2309
2661
|
if (executor.includes(TEMPLATE_ACTION_OPEN)) return;
|
|
2310
|
-
const
|
|
2311
|
-
if (!executor.
|
|
2312
|
-
const rest = executor.slice(
|
|
2662
|
+
const sep = executor.indexOf(SCHEME_SEPARATOR);
|
|
2663
|
+
if (sep < 0 || !ATLAS_EXECUTOR.schemes.has(executor.slice(0, sep))) return;
|
|
2664
|
+
const rest = executor.slice(sep + SCHEME_SEPARATOR.length);
|
|
2313
2665
|
const slash = rest.indexOf("/");
|
|
2314
2666
|
const provider = slash < 0 ? rest : rest.slice(0, slash);
|
|
2315
2667
|
const resource = slash < 0 ? "" : rest.slice(slash + 1);
|
|
@@ -2385,7 +2737,9 @@ function validateExecutors(flow, issues) {
|
|
|
2385
2737
|
const step = rawStep;
|
|
2386
2738
|
const executor = issues.stringOf(step, "executor", `steps.${stepID}`);
|
|
2387
2739
|
if (executor !== null && executor !== "") {
|
|
2388
|
-
|
|
2740
|
+
if (!checkRemovedSurfaces(executor, step.query, `steps.${stepID}`, stepID, issues)) {
|
|
2741
|
+
checkExecutor(executor, `steps.${stepID}.executor`, stepID, issues);
|
|
2742
|
+
}
|
|
2389
2743
|
checkAtlasStep(executor, step.query, `steps.${stepID}`, stepID, issues);
|
|
2390
2744
|
}
|
|
2391
2745
|
const loop = step.loop;
|
|
@@ -2397,12 +2751,14 @@ function validateExecutors(flow, issues) {
|
|
|
2397
2751
|
const subID = issues.stringOf(subStep, "id", subPath) ?? String(i);
|
|
2398
2752
|
const subExecutor = issues.stringOf(subStep, "executor", subPath);
|
|
2399
2753
|
if (subExecutor !== null && subExecutor !== "") {
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2754
|
+
if (!checkRemovedSurfaces(subExecutor, subStep.query, subPath, `${stepID}.${subID}`, issues)) {
|
|
2755
|
+
checkExecutor(
|
|
2756
|
+
subExecutor,
|
|
2757
|
+
`steps.${stepID}.loop.steps[${i}].executor`,
|
|
2758
|
+
`${stepID}.${subID}`,
|
|
2759
|
+
issues
|
|
2760
|
+
);
|
|
2761
|
+
}
|
|
2406
2762
|
checkAtlasStep(subExecutor, subStep.query, subPath, `${stepID}.${subID}`, issues);
|
|
2407
2763
|
}
|
|
2408
2764
|
});
|
|
@@ -3518,49 +3874,6 @@ function flowHasOrchestratorYieldEdge(flow) {
|
|
|
3518
3874
|
}
|
|
3519
3875
|
return false;
|
|
3520
3876
|
}
|
|
3521
|
-
var GO_INT64_FLOAT_LIMIT = 2 ** 63;
|
|
3522
|
-
function decodeGoInt(v) {
|
|
3523
|
-
if (typeof v !== "number" || Number.isNaN(v)) return null;
|
|
3524
|
-
if (v >= GO_INT64_FLOAT_LIMIT) return null;
|
|
3525
|
-
if (v === -Infinity) return -GO_INT64_FLOAT_LIMIT;
|
|
3526
|
-
return Math.trunc(v);
|
|
3527
|
-
}
|
|
3528
|
-
function validateCampaignChildFlows(campaign, issues) {
|
|
3529
|
-
const field = "campaign.child_flows";
|
|
3530
|
-
const raw = campaign.child_flows;
|
|
3531
|
-
if (raw !== void 0 && raw !== null && !Array.isArray(raw)) {
|
|
3532
|
-
issues.error({ field, message: "campaign.child_flows must be a list", code: "invalid_type" });
|
|
3533
|
-
return;
|
|
3534
|
-
}
|
|
3535
|
-
const entries = (Array.isArray(raw) ? raw : []).map((entry, i) => ({ entry, i })).filter(({ entry }) => entry !== null);
|
|
3536
|
-
if (entries.length === 0) {
|
|
3537
|
-
issues.error({
|
|
3538
|
-
field,
|
|
3539
|
-
message: "campaign requires at least one entry in child_flows",
|
|
3540
|
-
code: "campaign_no_child_flows"
|
|
3541
|
-
});
|
|
3542
|
-
return;
|
|
3543
|
-
}
|
|
3544
|
-
for (const { entry, i } of entries) {
|
|
3545
|
-
if (!isRecord(entry)) {
|
|
3546
|
-
issues.error({
|
|
3547
|
-
field: `${field}[${i}]`,
|
|
3548
|
-
message: "each campaign.child_flows entry must be a mapping",
|
|
3549
|
-
code: "invalid_type"
|
|
3550
|
-
});
|
|
3551
|
-
continue;
|
|
3552
|
-
}
|
|
3553
|
-
const id = issues.stringOf(entry, "flow_id", `${field}[${i}]`);
|
|
3554
|
-
const name = issues.stringOf(entry, "flow_name", `${field}[${i}]`);
|
|
3555
|
-
if (id !== null && id !== "" || name !== null && name !== "") continue;
|
|
3556
|
-
issues.error({
|
|
3557
|
-
field: `${field}[${i}]`,
|
|
3558
|
-
message: `campaign.child_flows[${i}] needs a flow_id or a flow_name`,
|
|
3559
|
-
code: "campaign_child_flow_no_id",
|
|
3560
|
-
suggestion: "Name the child flow with flow_name, or pin it with flow_id"
|
|
3561
|
-
});
|
|
3562
|
-
}
|
|
3563
|
-
}
|
|
3564
3877
|
function validateOrchestratorCampaign(flow, issues, opts) {
|
|
3565
3878
|
const hasOrchestrator = isRecord(flow.orchestrator);
|
|
3566
3879
|
if (hasOrchestrator) {
|
|
@@ -3616,6 +3929,7 @@ function validateOrchestratorCampaign(flow, issues, opts) {
|
|
|
3616
3929
|
const trigger = rawTrigger;
|
|
3617
3930
|
const base = `orchestrator.triggers[${i}]`;
|
|
3618
3931
|
const type = issues.stringOf(trigger, "type", base);
|
|
3932
|
+
if (type !== null && REMOVED_ORCHESTRATOR_TRIGGERS.has(type)) return;
|
|
3619
3933
|
if (type === null || !ORCHESTRATOR_TRIGGERS.has(type)) {
|
|
3620
3934
|
issues.error({
|
|
3621
3935
|
field: `${base}.type`,
|
|
@@ -3646,7 +3960,9 @@ function validateOrchestratorCampaign(flow, issues, opts) {
|
|
|
3646
3960
|
if (Array.isArray(orch.tools)) {
|
|
3647
3961
|
orch.tools.forEach((raw, i) => {
|
|
3648
3962
|
const tool = issues.stringAt(raw, `orchestrator.tools[${i}]`);
|
|
3649
|
-
if (tool === null || ORCHESTRATOR_TOOLS.has(tool))
|
|
3963
|
+
if (tool === null || ORCHESTRATOR_TOOLS.has(tool) || REMOVED_ORCHESTRATOR_TOOLS.has(tool)) {
|
|
3964
|
+
return;
|
|
3965
|
+
}
|
|
3650
3966
|
const finding = {
|
|
3651
3967
|
field: `orchestrator.tools[${i}]`,
|
|
3652
3968
|
message: `Unrecognised orchestrator tool name '${tool}'`,
|
|
@@ -3654,58 +3970,17 @@ function validateOrchestratorCampaign(flow, issues, opts) {
|
|
|
3654
3970
|
};
|
|
3655
3971
|
if (opts.strictRegistries) {
|
|
3656
3972
|
issues.error(finding);
|
|
3657
|
-
} else {
|
|
3658
|
-
issues.warn(finding);
|
|
3659
|
-
}
|
|
3660
|
-
});
|
|
3661
|
-
}
|
|
3662
|
-
if (orch.agentic === false) {
|
|
3663
|
-
issues.warn({
|
|
3664
|
-
field: "orchestrator.agentic",
|
|
3665
|
-
message: "orchestrator is most useful with agentic: true",
|
|
3666
|
-
code: "orchestrator_not_agentic"
|
|
3667
|
-
});
|
|
3668
|
-
}
|
|
3669
|
-
}
|
|
3670
|
-
if (flow.campaign !== void 0 && flow.campaign !== null) {
|
|
3671
|
-
if (!hasOrchestrator) {
|
|
3672
|
-
issues.error({
|
|
3673
|
-
field: "campaign",
|
|
3674
|
-
message: "campaign requires an orchestrator block",
|
|
3675
|
-
code: "campaign_requires_orchestrator"
|
|
3676
|
-
});
|
|
3677
|
-
}
|
|
3678
|
-
const campaign = flow.campaign;
|
|
3679
|
-
if (isRecord(campaign)) {
|
|
3680
|
-
const cap = campaign.max_credits_per_child;
|
|
3681
|
-
if (cap !== void 0 && cap !== null) {
|
|
3682
|
-
const decoded = decodeGoInt(cap);
|
|
3683
|
-
if (decoded === null) {
|
|
3684
|
-
issues.error({
|
|
3685
|
-
field: "campaign.max_credits_per_child",
|
|
3686
|
-
message: `campaign.max_credits_per_child must be a number of credits, got '${String(cap)}'`,
|
|
3687
|
-
code: "invalid_type"
|
|
3688
|
-
});
|
|
3689
|
-
} else if (decoded < 0) {
|
|
3690
|
-
issues.error({
|
|
3691
|
-
field: "campaign.max_credits_per_child",
|
|
3692
|
-
message: "campaign: max_credits_per_child must be >= 0",
|
|
3693
|
-
code: "campaign_invalid_max_credits_per_child"
|
|
3694
|
-
});
|
|
3973
|
+
} else {
|
|
3974
|
+
issues.warn(finding);
|
|
3695
3975
|
}
|
|
3696
|
-
}
|
|
3697
|
-
validateCampaignChildFlows(campaign, issues);
|
|
3976
|
+
});
|
|
3698
3977
|
}
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
message: `campaign.on_children_complete references unknown step '${target}'`,
|
|
3706
|
-
code: "campaign_handoff_step_unknown"
|
|
3707
|
-
});
|
|
3708
|
-
}
|
|
3978
|
+
if (orch.agentic === false) {
|
|
3979
|
+
issues.warn({
|
|
3980
|
+
field: "orchestrator.agentic",
|
|
3981
|
+
message: "orchestrator is most useful with agentic: true",
|
|
3982
|
+
code: "orchestrator_not_agentic"
|
|
3983
|
+
});
|
|
3709
3984
|
}
|
|
3710
3985
|
}
|
|
3711
3986
|
}
|
|
@@ -4833,10 +5108,6 @@ var CODE_UNKNOWN_YAML_KEY = "unknown_yaml_key";
|
|
|
4833
5108
|
var KEY_BUDGET = "budget";
|
|
4834
5109
|
var KEY_MAX_RETRIES = "max_retries";
|
|
4835
5110
|
var REMOVED_IN = "v2.721.0";
|
|
4836
|
-
var KEY_BUDGET_MAX_PER_CHILD = "budget_max_per_child";
|
|
4837
|
-
var BUDGET_MAX_PER_CHILD_REMOVED_IN = "v2.728.0";
|
|
4838
|
-
var BUDGET_MAX_PER_CHILD_MESSAGE = `\`campaign.budget_max_per_child\` (USD) was removed from the grammar in AIgentFlow ${BUDGET_MAX_PER_CHILD_REMOVED_IN} because it capped nothing, and AIgentFlow refuses to save a flow that declares it.`;
|
|
4839
|
-
var BUDGET_MAX_PER_CHILD_SUGGESTION = "Use `campaign.max_credits_per_child: N` (a whole number of credits) \u2014 it is checked before each agentic turn of a child, and a spawn may lower it with `max_credits`.";
|
|
4840
5111
|
var BUDGET_MESSAGE = `The flow-level \`budget:\` key was removed from the grammar in AIgentFlow ${REMOVED_IN} because nothing read it (it limited no spend), and AIgentFlow refuses to save a flow that declares it.`;
|
|
4841
5112
|
var BUDGET_SUGGESTION = "Delete it. To cap spend use `billing: { max_credits: N }` \u2014 it caps the credit reservation and refuses further agentic turns (agentic ai://, exons://, the orchestrator); plain chat steps and flow:// sub-flows are not checked against it.";
|
|
4842
5113
|
function maxRetriesMessage(owner) {
|
|
@@ -4864,15 +5135,6 @@ function validateRetiredKeys(flow, issues) {
|
|
|
4864
5135
|
suggestion: MAX_RETRIES_SUGGESTION
|
|
4865
5136
|
});
|
|
4866
5137
|
}
|
|
4867
|
-
const campaign = root.campaign;
|
|
4868
|
-
if (isRecord(campaign) && declares(campaign, KEY_BUDGET_MAX_PER_CHILD)) {
|
|
4869
|
-
issues.error({
|
|
4870
|
-
field: `campaign.${KEY_BUDGET_MAX_PER_CHILD}`,
|
|
4871
|
-
message: BUDGET_MAX_PER_CHILD_MESSAGE,
|
|
4872
|
-
code: CODE_UNKNOWN_YAML_KEY,
|
|
4873
|
-
suggestion: BUDGET_MAX_PER_CHILD_SUGGESTION
|
|
4874
|
-
});
|
|
4875
|
-
}
|
|
4876
5138
|
const steps = flow.steps;
|
|
4877
5139
|
if (!isRecord(steps)) return;
|
|
4878
5140
|
for (const [stepID, rawStep] of Object.entries(steps)) {
|
|
@@ -5240,9 +5502,9 @@ function refuse(issues, stepId, key, field) {
|
|
|
5240
5502
|
}
|
|
5241
5503
|
|
|
5242
5504
|
// src/validators/goUrl.ts
|
|
5243
|
-
var
|
|
5244
|
-
var GO_TRIM_SPACE_RE = new RegExp(`^[${
|
|
5245
|
-
function
|
|
5505
|
+
var GO_SPACE2 = "\\t\\n\\v\\f\\r \\u0085\\u00A0\\u1680\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000";
|
|
5506
|
+
var GO_TRIM_SPACE_RE = new RegExp(`^[${GO_SPACE2}]+|[${GO_SPACE2}]+$`, "g");
|
|
5507
|
+
function goTrimSpace2(s) {
|
|
5246
5508
|
return s.replace(GO_TRIM_SPACE_RE, "");
|
|
5247
5509
|
}
|
|
5248
5510
|
function goToLower(s) {
|
|
@@ -5465,7 +5727,7 @@ function goQueryKeys(rawQuery) {
|
|
|
5465
5727
|
return keys;
|
|
5466
5728
|
}
|
|
5467
5729
|
function goEndpointOrigin(raw, defaultPorts, protocolSeparator) {
|
|
5468
|
-
const trimmed =
|
|
5730
|
+
const trimmed = goTrimSpace2(raw);
|
|
5469
5731
|
const u = goParseSchemeHost(trimmed);
|
|
5470
5732
|
if (u === null || u.scheme === "" || u.host === "") {
|
|
5471
5733
|
return goToLower(trimmed.replace(/\/+$/, ""));
|
|
@@ -5700,227 +5962,164 @@ function validateFamilies(flow, steps, issues) {
|
|
|
5700
5962
|
}
|
|
5701
5963
|
}
|
|
5702
5964
|
|
|
5703
|
-
// src/validators/
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
var CODE_TOOL_WITHHELD = "orchestrator_tool_withheld";
|
|
5709
|
-
var EXONS_OPEN_DELIM = "{~";
|
|
5710
|
-
var EXONS_LEGACY_CONFIG_OPEN = "{~exons.config~}";
|
|
5711
|
-
var UTF8_BOM = "\uFEFF";
|
|
5712
|
-
var MAX_ALIAS_COUNT2 = 100;
|
|
5713
|
-
var UNREAD = {
|
|
5714
|
-
parseError: null,
|
|
5715
|
-
specRead: false,
|
|
5716
|
-
hasSpec: false,
|
|
5717
|
-
provider: "",
|
|
5718
|
-
toolsAllowDeclared: false,
|
|
5719
|
-
toolsAllow: [],
|
|
5720
|
-
resources: []
|
|
5721
|
-
};
|
|
5722
|
-
var GO_SPACE2 = "\\t\\n\\v\\f\\r \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000";
|
|
5723
|
-
var GO_TRIM_SPACE = new RegExp(`^[${GO_SPACE2}]+|[${GO_SPACE2}]+$`, "g");
|
|
5724
|
-
function goTrimSpace2(s) {
|
|
5725
|
-
return s.replace(GO_TRIM_SPACE, "");
|
|
5965
|
+
// src/validators/removedSignalCampaign.ts
|
|
5966
|
+
var TEMPLATE_ACTION_OPEN3 = "{{";
|
|
5967
|
+
function fill(format, ...args) {
|
|
5968
|
+
let i = 0;
|
|
5969
|
+
return format.replace(/%[qs]/g, () => args[i++] ?? "");
|
|
5726
5970
|
}
|
|
5727
|
-
function
|
|
5728
|
-
const
|
|
5729
|
-
|
|
5730
|
-
start = start.replace(/^[ \t]+/, "");
|
|
5731
|
-
if (start.startsWith(EXONS_LEGACY_CONFIG_OPEN)) {
|
|
5732
|
-
return {
|
|
5733
|
-
frontmatter: "",
|
|
5734
|
-
hasFrontmatter: false,
|
|
5735
|
-
parseError: "legacy JSON config block detected; use YAML frontmatter"
|
|
5736
|
-
};
|
|
5737
|
-
}
|
|
5738
|
-
if (!start.startsWith(delim)) return { frontmatter: "", hasFrontmatter: false, parseError: null };
|
|
5739
|
-
let rest = start.slice(delim.length);
|
|
5740
|
-
if (rest.startsWith("\n")) rest = rest.slice(1);
|
|
5741
|
-
else if (rest.startsWith("\r\n")) rest = rest.slice(2);
|
|
5742
|
-
else return { frontmatter: "", hasFrontmatter: false, parseError: null };
|
|
5743
|
-
let pos = 0;
|
|
5744
|
-
while (pos <= rest.length) {
|
|
5745
|
-
const line = rest.slice(pos);
|
|
5746
|
-
if (line.startsWith(delim)) {
|
|
5747
|
-
const after = line.slice(delim.length);
|
|
5748
|
-
if (after === "" || after[0] === "\n" || after[0] === "\r") {
|
|
5749
|
-
return {
|
|
5750
|
-
frontmatter: goTrimSpace2(rest.slice(0, pos)),
|
|
5751
|
-
hasFrontmatter: true,
|
|
5752
|
-
parseError: null
|
|
5753
|
-
};
|
|
5754
|
-
}
|
|
5755
|
-
}
|
|
5756
|
-
const nl = line.indexOf("\n");
|
|
5757
|
-
if (nl < 0) break;
|
|
5758
|
-
pos += nl + 1;
|
|
5759
|
-
}
|
|
5760
|
-
return {
|
|
5761
|
-
frontmatter: "",
|
|
5762
|
-
hasFrontmatter: true,
|
|
5763
|
-
parseError: "YAML frontmatter not properly closed"
|
|
5764
|
-
};
|
|
5971
|
+
function stringEntries(m, key) {
|
|
5972
|
+
const raw = m[key];
|
|
5973
|
+
return Array.isArray(raw) ? raw.filter((v) => typeof v === "string") : [];
|
|
5765
5974
|
}
|
|
5766
|
-
function
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
} else if (isSeq2(node)) {
|
|
5773
|
-
for (const item of node.items) retagScalars(item);
|
|
5774
|
-
} else if (isScalar2(node) && (typeof node.value === "number" || typeof node.value === "boolean") && typeof node.source === "string") {
|
|
5775
|
-
node.value = node.source;
|
|
5975
|
+
function triggerTypes(orch) {
|
|
5976
|
+
const raw = orch.triggers;
|
|
5977
|
+
if (!Array.isArray(raw)) return [];
|
|
5978
|
+
const out = [];
|
|
5979
|
+
for (const t of raw) {
|
|
5980
|
+
if (isRecord(t) && typeof t.type === "string") out.push(t.type);
|
|
5776
5981
|
}
|
|
5982
|
+
return out;
|
|
5777
5983
|
}
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
if (isString(v)) return v;
|
|
5783
|
-
throw new DecodeError("not a string");
|
|
5784
|
-
}
|
|
5785
|
-
function goStringList(v) {
|
|
5786
|
-
if (v === null || v === void 0) return null;
|
|
5787
|
-
if (!isArray(v)) throw new DecodeError("not a list");
|
|
5788
|
-
return v.filter((item) => item !== null).map(goString);
|
|
5789
|
-
}
|
|
5790
|
-
function goStruct(v) {
|
|
5791
|
-
if (v === null || v === void 0) return null;
|
|
5792
|
-
if (!isRecord(v)) throw new DecodeError("not a mapping");
|
|
5793
|
-
return v;
|
|
5794
|
-
}
|
|
5795
|
-
function decodeSpecFields(frontmatter) {
|
|
5796
|
-
let value;
|
|
5797
|
-
try {
|
|
5798
|
-
const docs = parseAllDocuments(frontmatter, { merge: true });
|
|
5799
|
-
const doc = Array.isArray(docs) ? docs[0] : void 0;
|
|
5800
|
-
if (doc === void 0) {
|
|
5801
|
-
value = null;
|
|
5802
|
-
} else {
|
|
5803
|
-
if (doc.errors.length > 0) return null;
|
|
5804
|
-
retagScalars(doc.contents);
|
|
5805
|
-
value = doc.toJS({ maxAliasCount: MAX_ALIAS_COUNT2 });
|
|
5806
|
-
}
|
|
5807
|
-
} catch {
|
|
5808
|
-
return null;
|
|
5809
|
-
}
|
|
5810
|
-
try {
|
|
5811
|
-
const root = goStruct(value) ?? {};
|
|
5812
|
-
const execution = goStruct(root.execution);
|
|
5813
|
-
const tools = goStruct(root.tools);
|
|
5814
|
-
const requirements = goStruct(root.requirements);
|
|
5815
|
-
const allow = tools === null ? null : goStringList(tools.allow);
|
|
5816
|
-
let resources = [];
|
|
5817
|
-
if (requirements !== null) {
|
|
5818
|
-
const raw = requirements.resources;
|
|
5819
|
-
if (raw !== null && raw !== void 0) {
|
|
5820
|
-
if (!isArray(raw)) throw new DecodeError("not a list");
|
|
5821
|
-
resources = raw.filter((entry) => entry !== null).map((entry) => {
|
|
5822
|
-
const r = goStruct(entry) ?? {};
|
|
5823
|
-
return { ref: goString(r.ref), kind: goString(r.kind), scope: goString(r.scope) };
|
|
5824
|
-
});
|
|
5825
|
-
}
|
|
5826
|
-
}
|
|
5827
|
-
return {
|
|
5828
|
-
provider: execution === null ? "" : goString(execution.provider),
|
|
5829
|
-
toolsAllowDeclared: allow !== null,
|
|
5830
|
-
toolsAllow: allow ?? [],
|
|
5831
|
-
resources
|
|
5832
|
-
};
|
|
5833
|
-
} catch (e) {
|
|
5834
|
-
if (e instanceof DecodeError) return null;
|
|
5835
|
-
throw e;
|
|
5984
|
+
function namesIn(names, removed2) {
|
|
5985
|
+
const found = [];
|
|
5986
|
+
for (const name of names) {
|
|
5987
|
+
if (removed2.includes(name) && !found.includes(name)) found.push(name);
|
|
5836
5988
|
}
|
|
5989
|
+
return found;
|
|
5837
5990
|
}
|
|
5838
|
-
function
|
|
5839
|
-
const
|
|
5840
|
-
if (
|
|
5841
|
-
if (!fm.hasFrontmatter || fm.frontmatter === "") return { ...UNREAD, specRead: true };
|
|
5842
|
-
if (fm.frontmatter.includes(EXONS_OPEN_DELIM)) return { ...UNREAD };
|
|
5843
|
-
const fields = decodeSpecFields(fm.frontmatter);
|
|
5844
|
-
if (fields === null) return { ...UNREAD };
|
|
5845
|
-
return { parseError: null, specRead: true, hasSpec: true, ...fields };
|
|
5846
|
-
}
|
|
5847
|
-
function validateOrchestratorExons(flow, issues) {
|
|
5848
|
-
const orch = flow.orchestrator;
|
|
5849
|
-
if (!isRecord(orch)) return;
|
|
5850
|
-
const source = issues.stringOf(orch, "exons", "orchestrator");
|
|
5851
|
-
if (source === null || source === "") return;
|
|
5852
|
-
const field = "orchestrator.exons";
|
|
5991
|
+
function orchestratorToolsAllow(orch) {
|
|
5992
|
+
const source = orch.exons;
|
|
5993
|
+
if (typeof source !== "string" || source === "") return [];
|
|
5853
5994
|
const report = inspectExonsFrontmatter(source);
|
|
5854
|
-
if (report.parseError !== null)
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5995
|
+
if (report.parseError !== null || !report.specRead || !report.toolsAllowDeclared) return [];
|
|
5996
|
+
return [...report.toolsAllow];
|
|
5997
|
+
}
|
|
5998
|
+
function validateRemovedOrchestratorSurfaces(flow, issues) {
|
|
5999
|
+
const sig = REMOVED_SIGNAL_SURFACES;
|
|
6000
|
+
const camp = REMOVED_CAMPAIGN_SURFACES;
|
|
6001
|
+
const orch = isRecord(flow.orchestrator) ? flow.orchestrator : null;
|
|
6002
|
+
const lists = orch === null ? [] : [
|
|
6003
|
+
...["tools", "deny_tools", "require_approval_for"].map((key) => ({
|
|
6004
|
+
field: `orchestrator.${key}`,
|
|
6005
|
+
names: stringEntries(orch, key)
|
|
6006
|
+
})),
|
|
6007
|
+
{ field: "orchestrator.exons", names: orchestratorToolsAllow(orch) }
|
|
6008
|
+
];
|
|
6009
|
+
if (orch !== null) {
|
|
6010
|
+
if (orch.enable_signals === true) {
|
|
6011
|
+
issues.error({
|
|
6012
|
+
field: "orchestrator.enable_signals",
|
|
6013
|
+
code: sig.signalRemovedCode,
|
|
6014
|
+
message: sig.enableSignalsMessage,
|
|
6015
|
+
suggestion: sig.suggestion
|
|
6016
|
+
});
|
|
6017
|
+
}
|
|
6018
|
+
for (const list of lists) {
|
|
6019
|
+
const named = namesIn(list.names, sig.tools);
|
|
6020
|
+
if (named.length === 0) continue;
|
|
6021
|
+
issues.error({
|
|
6022
|
+
field: list.field,
|
|
6023
|
+
code: sig.signalRemovedCode,
|
|
6024
|
+
message: fill(sig.toolNamesMessageFormat, list.field, named.join(", ")),
|
|
6025
|
+
suggestion: sig.suggestion
|
|
6026
|
+
});
|
|
6027
|
+
}
|
|
6028
|
+
if (namesIn(triggerTypes(orch), sig.triggers).length > 0) {
|
|
6029
|
+
issues.error({
|
|
6030
|
+
field: "orchestrator.triggers",
|
|
6031
|
+
code: sig.flowModificationRemovedCode,
|
|
6032
|
+
message: sig.triggersMessage,
|
|
6033
|
+
suggestion: sig.suggestion
|
|
6034
|
+
});
|
|
6035
|
+
}
|
|
5878
6036
|
}
|
|
5879
|
-
|
|
5880
|
-
|
|
6037
|
+
const block = flow[camp.flowKey];
|
|
6038
|
+
if (block !== void 0 && block !== null) {
|
|
5881
6039
|
issues.error({
|
|
5882
|
-
field,
|
|
5883
|
-
code:
|
|
5884
|
-
message:
|
|
5885
|
-
suggestion:
|
|
5886
|
-
});
|
|
5887
|
-
}
|
|
5888
|
-
warnOrchestratorToolWithheld(flow, orch, report, issues);
|
|
5889
|
-
}
|
|
5890
|
-
function warnOrchestratorToolWithheld(flow, orch, report, issues) {
|
|
5891
|
-
if (!report.toolsAllowDeclared) return;
|
|
5892
|
-
const cfg = ORCHESTRATOR_TOOL_ALLOW;
|
|
5893
|
-
const exempt = new Set(cfg.lifecycleTools);
|
|
5894
|
-
const signals = typeof orch.enable_signals === "boolean" ? orch.enable_signals : cfg.enableSignalsDefault;
|
|
5895
|
-
if (signals) for (const t of cfg.signalTools) exempt.add(t);
|
|
5896
|
-
const allow = new Set(report.toolsAllow);
|
|
5897
|
-
const withheld = (name) => !allow.has(name) && !exempt.has(name);
|
|
5898
|
-
const warn = (message) => issues.warn({ field: cfg.warningField, code: CODE_TOOL_WITHHELD, message });
|
|
5899
|
-
const named = [];
|
|
5900
|
-
if (isArray(orch.tools)) {
|
|
5901
|
-
orch.tools.forEach((raw, i) => {
|
|
5902
|
-
const name = issues.stringAt(raw, `orchestrator.tools[${i}]`);
|
|
5903
|
-
if (name !== null) named.push(name);
|
|
6040
|
+
field: camp.flowKey,
|
|
6041
|
+
code: camp.code,
|
|
6042
|
+
message: camp.blockMessage,
|
|
6043
|
+
suggestion: camp.suggestion
|
|
5904
6044
|
});
|
|
5905
6045
|
}
|
|
5906
|
-
if (
|
|
5907
|
-
for (const
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
6046
|
+
if (orch !== null) {
|
|
6047
|
+
for (const list of lists) {
|
|
6048
|
+
const named = namesIn(list.names, camp.tools);
|
|
6049
|
+
if (named.length === 0) continue;
|
|
6050
|
+
issues.error({
|
|
6051
|
+
field: list.field,
|
|
6052
|
+
code: camp.code,
|
|
6053
|
+
message: fill(camp.toolNamesMessageFormat, list.field, named.join(", ")),
|
|
6054
|
+
suggestion: camp.suggestion
|
|
6055
|
+
});
|
|
6056
|
+
}
|
|
6057
|
+
const triggers = namesIn(triggerTypes(orch), camp.triggers);
|
|
6058
|
+
if (triggers.length > 0) {
|
|
6059
|
+
issues.error({
|
|
6060
|
+
field: "orchestrator.triggers",
|
|
6061
|
+
code: camp.code,
|
|
6062
|
+
message: fill(camp.triggersMessageFormat, triggers.join(", ")),
|
|
6063
|
+
suggestion: camp.suggestion
|
|
6064
|
+
});
|
|
5912
6065
|
}
|
|
5913
|
-
return;
|
|
5914
6066
|
}
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
);
|
|
6067
|
+
const judgeStep = (executor, query, field, stepID) => {
|
|
6068
|
+
if (typeof executor !== "string" || executor === "") return;
|
|
6069
|
+
if (executor.includes(TEMPLATE_ACTION_OPEN3)) return;
|
|
6070
|
+
const scheme = removedExecutorScheme(executor);
|
|
6071
|
+
if (REMOVED_AGENT_SURFACES.schemes.has(scheme) || sig.stepSkipSchemes.has(scheme)) return;
|
|
6072
|
+
if (!isRecord(query)) return;
|
|
6073
|
+
const quoted = JSON.stringify(stepID);
|
|
6074
|
+
if (Object.prototype.hasOwnProperty.call(query, sig.flowModificationStepKey)) {
|
|
6075
|
+
issues.error({
|
|
6076
|
+
field,
|
|
6077
|
+
code: sig.flowModificationRemovedCode,
|
|
6078
|
+
stepId: stepID,
|
|
6079
|
+
message: fill(sig.flowModificationStepMessageFormat, quoted),
|
|
6080
|
+
suggestion: sig.suggestion
|
|
6081
|
+
});
|
|
6082
|
+
}
|
|
6083
|
+
if (scheme === sig.stepKeyScheme && Object.prototype.hasOwnProperty.call(query, sig.stepKey)) {
|
|
6084
|
+
issues.error({
|
|
6085
|
+
field,
|
|
6086
|
+
code: sig.signalRemovedCode,
|
|
6087
|
+
stepId: stepID,
|
|
6088
|
+
message: fill(sig.stepKeyMessageFormat, quoted),
|
|
6089
|
+
suggestion: sig.suggestion
|
|
6090
|
+
});
|
|
6091
|
+
}
|
|
6092
|
+
};
|
|
6093
|
+
const steps = flow.steps;
|
|
6094
|
+
if (isRecord(steps)) {
|
|
6095
|
+
for (const stepID of Object.keys(steps).sort()) {
|
|
6096
|
+
const step = steps[stepID];
|
|
6097
|
+
if (!isRecord(step)) continue;
|
|
6098
|
+
judgeStep(step.executor, step.query, `steps.${stepID}`, stepID);
|
|
6099
|
+
const loop = step.loop;
|
|
6100
|
+
if (!isRecord(loop) || !Array.isArray(loop.steps)) continue;
|
|
6101
|
+
loop.steps.forEach((sub, i) => {
|
|
6102
|
+
if (!isRecord(sub)) return;
|
|
6103
|
+
const subID = issues.stringOf(sub, "id", `steps.${stepID}.loop.steps[${i}]`) ?? String(i);
|
|
6104
|
+
judgeStep(
|
|
6105
|
+
sub.executor,
|
|
6106
|
+
sub.query,
|
|
6107
|
+
`steps.${stepID}.loop.steps[${i}]`,
|
|
6108
|
+
`${stepID}.${subID}`
|
|
6109
|
+
);
|
|
6110
|
+
});
|
|
6111
|
+
}
|
|
5919
6112
|
}
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
)
|
|
6113
|
+
const ignored = (field) => issues.warn({
|
|
6114
|
+
field,
|
|
6115
|
+
code: sig.removedKeyIgnoredCode,
|
|
6116
|
+
message: fill(sig.ignoredKeyMessageFormat, field),
|
|
6117
|
+
suggestion: sig.ignoredKeySuggestion
|
|
6118
|
+
});
|
|
6119
|
+
if (orch !== null && orch.enable_signals === false) ignored("orchestrator.enable_signals");
|
|
6120
|
+
const checkpoint = flow.checkpoint;
|
|
6121
|
+
if (isRecord(checkpoint) && checkpoint.pre_dfm !== void 0 && checkpoint.pre_dfm !== null) {
|
|
6122
|
+
ignored("checkpoint.pre_dfm");
|
|
5924
6123
|
}
|
|
5925
6124
|
}
|
|
5926
6125
|
|
|
@@ -5937,7 +6136,7 @@ function sprintf(format, ...args) {
|
|
|
5937
6136
|
});
|
|
5938
6137
|
}
|
|
5939
6138
|
function literalOrEmpty(s) {
|
|
5940
|
-
const t =
|
|
6139
|
+
const t = goTrimSpace(s);
|
|
5941
6140
|
return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
|
|
5942
6141
|
}
|
|
5943
6142
|
function euOnlyResidency(flow, issues) {
|
|
@@ -5952,7 +6151,7 @@ function euOnlyResidency(flow, issues) {
|
|
|
5952
6151
|
}
|
|
5953
6152
|
if (codes.length === 0) return null;
|
|
5954
6153
|
const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
|
|
5955
|
-
return codes.every((c) => eu.has(
|
|
6154
|
+
return codes.every((c) => eu.has(goTrimSpace(c).toUpperCase())) ? codes : null;
|
|
5956
6155
|
}
|
|
5957
6156
|
function aiProvider(executor) {
|
|
5958
6157
|
const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
|
|
@@ -5968,7 +6167,7 @@ function isRegionLane(provider) {
|
|
|
5968
6167
|
}
|
|
5969
6168
|
function nonBlankString(m, key) {
|
|
5970
6169
|
const v = own2(m, key);
|
|
5971
|
-
return typeof v === "string" &&
|
|
6170
|
+
return typeof v === "string" && goTrimSpace(v) !== "";
|
|
5972
6171
|
}
|
|
5973
6172
|
function queryEnforcesRegion(query) {
|
|
5974
6173
|
const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
|
|
@@ -5980,7 +6179,7 @@ function flowDirectsEndpoint(flow, provider, issues) {
|
|
|
5980
6179
|
const inst = own2(own2(flow, "executor_config"), key);
|
|
5981
6180
|
if (!isRecord(inst)) return false;
|
|
5982
6181
|
const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
|
|
5983
|
-
return baseUrl !== null &&
|
|
6182
|
+
return baseUrl !== null && goTrimSpace(baseUrl) !== "";
|
|
5984
6183
|
}
|
|
5985
6184
|
function callPinsEndpoint(flow, provider, query, issues) {
|
|
5986
6185
|
if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
|
|
@@ -6053,7 +6252,7 @@ function warnOrchestrator(flow, issues, warn) {
|
|
|
6053
6252
|
const provider = literalOrEmpty(report.provider);
|
|
6054
6253
|
if (!isRegionLane(provider)) return;
|
|
6055
6254
|
const region = issues.stringOf(orch, "region", "orchestrator");
|
|
6056
|
-
if (region !== null &&
|
|
6255
|
+
if (region !== null && goTrimSpace(region) !== "") return;
|
|
6057
6256
|
if (orch.enforce_region === true) return;
|
|
6058
6257
|
if (flowDirectsEndpoint(flow, provider, issues)) return;
|
|
6059
6258
|
warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
|
|
@@ -6219,7 +6418,7 @@ function asFileRef(v) {
|
|
|
6219
6418
|
};
|
|
6220
6419
|
}
|
|
6221
6420
|
function isTextualMediaType(mediaType) {
|
|
6222
|
-
const base = goToLower(
|
|
6421
|
+
const base = goToLower(goTrimSpace2((mediaType.split(";")[0] ?? "").toString()));
|
|
6223
6422
|
if (base.startsWith("text/")) return true;
|
|
6224
6423
|
if (base.endsWith("+json") || base.endsWith("+xml")) return true;
|
|
6225
6424
|
return TEXTUAL_MEDIA_BASES.has(base);
|
|
@@ -6323,7 +6522,7 @@ var Walker = class _Walker {
|
|
|
6323
6522
|
}
|
|
6324
6523
|
}
|
|
6325
6524
|
const title = this.s(ex, "title", path);
|
|
6326
|
-
if (
|
|
6525
|
+
if (goTrimSpace2(title) === "") {
|
|
6327
6526
|
this.err(
|
|
6328
6527
|
"example_title_missing",
|
|
6329
6528
|
`${path}.title`,
|
|
@@ -6340,7 +6539,7 @@ var Walker = class _Walker {
|
|
|
6340
6539
|
}
|
|
6341
6540
|
}
|
|
6342
6541
|
const guidance = this.s(ex, "guidance", path);
|
|
6343
|
-
if (
|
|
6542
|
+
if (goTrimSpace2(guidance) === "") {
|
|
6344
6543
|
this.warn(
|
|
6345
6544
|
"example_guidance_missing",
|
|
6346
6545
|
`${path}.guidance`,
|
|
@@ -6767,7 +6966,7 @@ var Walker = class _Walker {
|
|
|
6767
6966
|
}
|
|
6768
6967
|
const rubric = this.s(e, "rubric", path);
|
|
6769
6968
|
if (rubric !== "") {
|
|
6770
|
-
if (
|
|
6969
|
+
if (goTrimSpace2(rubric) === "") {
|
|
6771
6970
|
this.err(
|
|
6772
6971
|
"example_rubric_empty",
|
|
6773
6972
|
`${path}.rubric`,
|
|
@@ -6822,7 +7021,7 @@ var Walker = class _Walker {
|
|
|
6822
7021
|
this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
|
|
6823
7022
|
}
|
|
6824
7023
|
mustNot.forEach((item, j) => {
|
|
6825
|
-
if (
|
|
7024
|
+
if (goTrimSpace2(item) === "" || runeCount(item) > L.maxMustNotRunes) {
|
|
6826
7025
|
this.err("example_must_not_invalid", `${path}.must_not[${j}]`, mustNotMsg);
|
|
6827
7026
|
}
|
|
6828
7027
|
});
|
|
@@ -7377,6 +7576,7 @@ function validateParsed(flow, opts, sources) {
|
|
|
7377
7576
|
const f = flow;
|
|
7378
7577
|
validateBasicStructure(f, issues);
|
|
7379
7578
|
validateRetiredKeys(f, issues);
|
|
7579
|
+
validateRemovedFlowKeys(f, issues);
|
|
7380
7580
|
validateExecutors(f, issues);
|
|
7381
7581
|
validateQuerySchema(f, issues);
|
|
7382
7582
|
validateResponseExpectations(f, issues);
|
|
@@ -7400,6 +7600,7 @@ function validateParsed(flow, opts, sources) {
|
|
|
7400
7600
|
validateCredentialEndpointPairing(f, issues);
|
|
7401
7601
|
validateExamples(f, issues);
|
|
7402
7602
|
validateOrchestratorExons(f, issues);
|
|
7603
|
+
validateRemovedOrchestratorSurfaces(f, issues);
|
|
7403
7604
|
validateResidencyEnforcement(f, issues);
|
|
7404
7605
|
validateUnknownKeys(f, issues);
|
|
7405
7606
|
const templateStats = validateTemplates(f, issues, opts);
|