@serverless-dna/sop-agents 0.1.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/dist/agent-discovery.d.ts +21 -0
  4. package/dist/agent-discovery.d.ts.map +1 -0
  5. package/dist/agent-discovery.js +97 -0
  6. package/dist/agent-discovery.js.map +1 -0
  7. package/dist/agents/discovery.d.ts +21 -0
  8. package/dist/agents/discovery.d.ts.map +1 -0
  9. package/dist/agents/discovery.js +97 -0
  10. package/dist/agents/discovery.js.map +1 -0
  11. package/dist/agents/sop-loader.d.ts +20 -0
  12. package/dist/agents/sop-loader.d.ts.map +1 -0
  13. package/dist/agents/sop-loader.js +150 -0
  14. package/dist/agents/sop-loader.js.map +1 -0
  15. package/dist/agents/tool-generator.d.ts +66 -0
  16. package/dist/agents/tool-generator.d.ts.map +1 -0
  17. package/dist/agents/tool-generator.js +171 -0
  18. package/dist/agents/tool-generator.js.map +1 -0
  19. package/dist/default-orchestrator.d.ts +7 -0
  20. package/dist/default-orchestrator.d.ts.map +1 -0
  21. package/dist/default-orchestrator.js +50 -0
  22. package/dist/default-orchestrator.js.map +1 -0
  23. package/dist/errors.d.ts +51 -0
  24. package/dist/errors.d.ts.map +1 -0
  25. package/dist/errors.js +80 -0
  26. package/dist/errors.js.map +1 -0
  27. package/dist/index.d.ts +10 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +18 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/logger.d.ts +26 -0
  32. package/dist/logger.d.ts.map +1 -0
  33. package/dist/logger.js +89 -0
  34. package/dist/logger.js.map +1 -0
  35. package/dist/model-factory.d.ts +36 -0
  36. package/dist/model-factory.d.ts.map +1 -0
  37. package/dist/model-factory.js +55 -0
  38. package/dist/model-factory.js.map +1 -0
  39. package/dist/orchestrator/default-orchestrator.d.ts +7 -0
  40. package/dist/orchestrator/default-orchestrator.d.ts.map +1 -0
  41. package/dist/orchestrator/default-orchestrator.js +50 -0
  42. package/dist/orchestrator/default-orchestrator.js.map +1 -0
  43. package/dist/orchestrator/orchestrator.d.ts +47 -0
  44. package/dist/orchestrator/orchestrator.d.ts.map +1 -0
  45. package/dist/orchestrator/orchestrator.js +276 -0
  46. package/dist/orchestrator/orchestrator.js.map +1 -0
  47. package/dist/orchestrator.d.ts +50 -0
  48. package/dist/orchestrator.d.ts.map +1 -0
  49. package/dist/orchestrator.js +281 -0
  50. package/dist/orchestrator.js.map +1 -0
  51. package/dist/sop-loader.d.ts +20 -0
  52. package/dist/sop-loader.d.ts.map +1 -0
  53. package/dist/sop-loader.js +150 -0
  54. package/dist/sop-loader.js.map +1 -0
  55. package/dist/tool-generator.d.ts +66 -0
  56. package/dist/tool-generator.d.ts.map +1 -0
  57. package/dist/tool-generator.js +171 -0
  58. package/dist/tool-generator.js.map +1 -0
  59. package/dist/types/errors.d.ts +51 -0
  60. package/dist/types/errors.d.ts.map +1 -0
  61. package/dist/types/errors.js +80 -0
  62. package/dist/types/errors.js.map +1 -0
  63. package/dist/types/types.d.ts +160 -0
  64. package/dist/types/types.d.ts.map +1 -0
  65. package/dist/types/types.js +2 -0
  66. package/dist/types/types.js.map +1 -0
  67. package/dist/types.d.ts +157 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +2 -0
  70. package/dist/types.js.map +1 -0
  71. package/package.json +68 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Serverless DNA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # SOP Agents
2
+
3
+ **Multi-agent orchestration for [Strands Agents](https://github.com/strands-agents/sdk-python), defined in plain text. Write what your agents do. Write how they collaborate. Done.**
4
+
5
+ 📖 Read the announcement: [Introducing Strands Agent SOPs](https://aws.amazon.com/blogs/opensource/introducing-strands-agent-sops-natural-language-workflows-for-ai-agents/) on the AWS Open Source Blog
6
+
7
+ ```markdown
8
+ <!-- sops/researcher.md -->
9
+ ---
10
+ name: researcher
11
+ description: Researches topics and gathers information
12
+ version: 1.0.0
13
+ type: agent
14
+ ---
15
+ # Research Agent
16
+
17
+ ## Overview
18
+
19
+ You are a research specialist focused on gathering accurate information.
20
+
21
+ ## Steps
22
+
23
+ ### 1. Analyze the Topic
24
+
25
+ Understand what information is needed and identify reliable sources.
26
+
27
+ **Constraints:**
28
+ - You MUST use authoritative sources
29
+ - You SHOULD cross-reference multiple sources
30
+
31
+ ### 2. Gather and Synthesize
32
+
33
+ Collect relevant information and organize it clearly.
34
+
35
+ **Constraints:**
36
+ - You MUST cite your sources
37
+ - You MUST distinguish facts from speculation
38
+ ```
39
+
40
+ ```markdown
41
+ <!-- sops/writer.md -->
42
+ ---
43
+ name: writer
44
+ description: Writes content based on research and requirements
45
+ version: 1.0.0
46
+ type: agent
47
+ ---
48
+ # Writer Agent
49
+
50
+ ## Overview
51
+
52
+ You are a skilled writer who transforms research into engaging content.
53
+
54
+ ## Steps
55
+
56
+ ### 1. Review the Input
57
+
58
+ Understand the research findings and target audience.
59
+
60
+ **Constraints:**
61
+ - You MUST NOT invent facts because the output must be grounded in provided research
62
+ - You SHOULD adapt tone to the target audience
63
+
64
+ ### 2. Write and Polish
65
+
66
+ Create clear, engaging content from the source material.
67
+
68
+ **Constraints:**
69
+ - You MUST maintain factual accuracy
70
+ - You SHOULD use clear, accessible language
71
+ ```
72
+
73
+ ```typescript
74
+ // That's it. Now they work together automatically.
75
+ const orchestrator = await createOrchestrator({ directory: "./sops" });
76
+
77
+ const result = await orchestrator.invoke(
78
+ "Research quantum computing breakthroughs in 2025 and write a blog post about them"
79
+ );
80
+ // The orchestrator reads your request, calls researcher, passes results to writer,
81
+ // and returns the finished blog post.
82
+ ```
83
+
84
+ No glue code. No tool definitions. No agent-to-agent wiring. Just describe what each agent does, and the orchestrator figures out how to coordinate them.
85
+
86
+ ## Why?
87
+
88
+ Building multi-agent systems usually means:
89
+ - Writing tool schemas and type definitions
90
+ - Manually wiring agents together
91
+ - Hardcoding orchestration logic
92
+ - Rebuilding when requirements change
93
+
94
+ With SOP Agents, you write markdown files. The library handles the rest.
95
+
96
+ **Model-driven orchestration** means the LLM decides how to coordinate agents at runtime—not you at build time. Traditional approaches lock you into predefined flows. Here, the orchestrator reasons about each request and picks the best path. Add a new agent? It's immediately available. Rephrase your request? The orchestrator adapts. No rewiring required.
97
+
98
+ ## Install
99
+
100
+ ```bash
101
+ npm install @serverless-dna/sop-agents
102
+ ```
103
+
104
+ Requires AWS credentials for Amazon Bedrock (the default model provider):
105
+
106
+ ```bash
107
+ aws login # or aws configure
108
+ ```
109
+
110
+ ## How It Works
111
+
112
+ 1. **You write SOPs** - Markdown files describing what each agent does
113
+ 2. **Library generates tools** - Each SOP becomes a callable tool with typed inputs
114
+ 3. **Orchestrator coordinates** - A master agent reads requests and delegates to the right agents
115
+ 4. **Agents execute** - Each agent runs with its SOP as the system prompt
116
+
117
+ The orchestrator is itself an agent—defined the same way. It sees your request, looks at the available agent tools, and decides which to call and in what order. No flowcharts, no state machines—just LLM reasoning.
118
+
119
+ **Out of the box**, the library includes a default orchestrator that analyzes your request and selects the right agent(s) to handle it. One agent, multiple agents in sequence, or a back-and-forth—it figures out what's needed.
120
+
121
+ **Want more control?** Write your own orchestrator SOP:
122
+
123
+ ```markdown
124
+ <!-- sops/orchestrator.md -->
125
+ ---
126
+ name: orchestrator
127
+ description: Coordinates research and writing tasks
128
+ type: orchestrator
129
+ ---
130
+ # Content Pipeline Orchestrator
131
+
132
+ You coordinate a content creation pipeline.
133
+
134
+ ## Steps
135
+
136
+ 1. Always start with the researcher to gather facts
137
+ 2. Pass research findings to the writer
138
+ 3. If the writer needs clarification, go back to the researcher
139
+ 4. Review the final output for accuracy before returning
140
+
141
+ Never skip research. Never let the writer make up facts.
142
+ ```
143
+
144
+ Plain English orchestration. Override the default when you need specific workflows.
145
+
@@ -0,0 +1,21 @@
1
+ import type { SOPDefinition } from "./types.js";
2
+ /**
3
+ * Scans a directory for SOP files and builds an agent registry.
4
+ * Excludes orchestrator SOPs (type: orchestrator).
5
+ *
6
+ * @param directory - Path to scan (default: "./sops")
7
+ * @returns Map of agent name to SOPDefinition (excludes orchestrators)
8
+ * @throws DirectoryNotFoundError if directory doesn't exist
9
+ */
10
+ export declare function discoverAgents(directory?: string): Promise<Map<string, SOPDefinition>>;
11
+ /**
12
+ * Finds the orchestrator SOP in a directory.
13
+ * Returns the built-in default orchestrator if none is found.
14
+ *
15
+ * @param directory - Path to scan (default: "./sops")
16
+ * @returns The orchestrator SOPDefinition (user-defined or default)
17
+ * @throws DirectoryNotFoundError if directory doesn't exist
18
+ * @throws MultipleOrchestratorsError if more than one orchestrator found
19
+ */
20
+ export declare function findOrchestrator(directory?: string): Promise<SOPDefinition>;
21
+ //# sourceMappingURL=agent-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-discovery.d.ts","sourceRoot":"","sources":["../src/agent-discovery.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CACnC,SAAS,SAAW,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CA0CrC;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACrC,SAAS,SAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CA4CxB"}
@@ -0,0 +1,97 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { DEFAULT_ORCHESTRATOR } from "./default-orchestrator.js";
4
+ import { DirectoryNotFoundError, MultipleOrchestratorsError } from "./errors.js";
5
+ import { loadSOP } from "./sop-loader.js";
6
+ /**
7
+ * Scans a directory for SOP files and builds an agent registry.
8
+ * Excludes orchestrator SOPs (type: orchestrator).
9
+ *
10
+ * @param directory - Path to scan (default: "./sops")
11
+ * @returns Map of agent name to SOPDefinition (excludes orchestrators)
12
+ * @throws DirectoryNotFoundError if directory doesn't exist
13
+ */
14
+ export async function discoverAgents(directory = "./sops") {
15
+ // Check if directory exists
16
+ if (!fs.existsSync(directory)) {
17
+ throw new DirectoryNotFoundError(directory);
18
+ }
19
+ const stats = fs.statSync(directory);
20
+ if (!stats.isDirectory()) {
21
+ throw new DirectoryNotFoundError(directory);
22
+ }
23
+ // Find all .md files in the directory
24
+ const files = fs.readdirSync(directory);
25
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
26
+ // Log warning for empty directories
27
+ if (mdFiles.length === 0) {
28
+ console.warn(`Warning: No .md files found in directory: ${directory}`);
29
+ return new Map();
30
+ }
31
+ const registry = new Map();
32
+ // Load each file and filter out orchestrators
33
+ for (const file of mdFiles) {
34
+ const filepath = path.join(directory, file);
35
+ try {
36
+ const sop = await loadSOP(filepath);
37
+ // Filter out orchestrator SOPs
38
+ if (sop.type !== "orchestrator") {
39
+ registry.set(sop.name, sop);
40
+ }
41
+ }
42
+ catch (error) {
43
+ // Log error and continue processing other files
44
+ const errorMessage = error instanceof Error ? error.message : String(error);
45
+ console.error(`Error loading SOP file ${filepath}: ${errorMessage}`);
46
+ }
47
+ }
48
+ return registry;
49
+ }
50
+ /**
51
+ * Finds the orchestrator SOP in a directory.
52
+ * Returns the built-in default orchestrator if none is found.
53
+ *
54
+ * @param directory - Path to scan (default: "./sops")
55
+ * @returns The orchestrator SOPDefinition (user-defined or default)
56
+ * @throws DirectoryNotFoundError if directory doesn't exist
57
+ * @throws MultipleOrchestratorsError if more than one orchestrator found
58
+ */
59
+ export async function findOrchestrator(directory = "./sops") {
60
+ // Check if directory exists
61
+ if (!fs.existsSync(directory)) {
62
+ throw new DirectoryNotFoundError(directory);
63
+ }
64
+ const stats = fs.statSync(directory);
65
+ if (!stats.isDirectory()) {
66
+ throw new DirectoryNotFoundError(directory);
67
+ }
68
+ // Find all .md files in the directory
69
+ const files = fs.readdirSync(directory);
70
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
71
+ const orchestrators = [];
72
+ const orchestratorFiles = [];
73
+ // Load each file and find orchestrators
74
+ for (const file of mdFiles) {
75
+ const filepath = path.join(directory, file);
76
+ try {
77
+ const sop = await loadSOP(filepath);
78
+ if (sop.type === "orchestrator") {
79
+ orchestrators.push(sop);
80
+ orchestratorFiles.push(filepath);
81
+ }
82
+ }
83
+ catch (_error) {
84
+ // Skip invalid files when searching for orchestrator
85
+ }
86
+ }
87
+ // Check for multiple orchestrators
88
+ if (orchestrators.length > 1) {
89
+ throw new MultipleOrchestratorsError(directory, orchestratorFiles);
90
+ }
91
+ // Return user-defined orchestrator or fall back to default
92
+ if (orchestrators.length === 1) {
93
+ return orchestrators[0];
94
+ }
95
+ return DEFAULT_ORCHESTRATOR;
96
+ }
97
+ //# sourceMappingURL=agent-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-discovery.js","sourceRoot":"","sources":["../src/agent-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { SOPDefinition } from "../types/types.js";
2
+ /**
3
+ * Scans a directory for SOP files and builds an agent registry.
4
+ * Excludes orchestrator SOPs (type: orchestrator).
5
+ *
6
+ * @param directory - Path to scan (default: "./sops")
7
+ * @returns Map of agent name to SOPDefinition (excludes orchestrators)
8
+ * @throws DirectoryNotFoundError if directory doesn't exist
9
+ */
10
+ export declare function discoverAgents(directory?: string): Promise<Map<string, SOPDefinition>>;
11
+ /**
12
+ * Finds the orchestrator SOP in a directory.
13
+ * Returns the built-in default orchestrator if none is found.
14
+ *
15
+ * @param directory - Path to scan (default: "./sops")
16
+ * @returns The orchestrator SOPDefinition (user-defined or default)
17
+ * @throws DirectoryNotFoundError if directory doesn't exist
18
+ * @throws MultipleOrchestratorsError if more than one orchestrator found
19
+ */
20
+ export declare function findOrchestrator(directory?: string): Promise<SOPDefinition>;
21
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/agents/discovery.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CACnC,SAAS,SAAW,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CA0CrC;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACrC,SAAS,SAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CA4CxB"}
@@ -0,0 +1,97 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { DEFAULT_ORCHESTRATOR } from "../orchestrator/default-orchestrator.js";
4
+ import { DirectoryNotFoundError, MultipleOrchestratorsError, } from "../types/errors.js";
5
+ import { loadSOP } from "./sop-loader.js";
6
+ /**
7
+ * Scans a directory for SOP files and builds an agent registry.
8
+ * Excludes orchestrator SOPs (type: orchestrator).
9
+ *
10
+ * @param directory - Path to scan (default: "./sops")
11
+ * @returns Map of agent name to SOPDefinition (excludes orchestrators)
12
+ * @throws DirectoryNotFoundError if directory doesn't exist
13
+ */
14
+ export async function discoverAgents(directory = "./sops") {
15
+ // Check if directory exists
16
+ if (!fs.existsSync(directory)) {
17
+ throw new DirectoryNotFoundError(directory);
18
+ }
19
+ const stats = fs.statSync(directory);
20
+ if (!stats.isDirectory()) {
21
+ throw new DirectoryNotFoundError(directory);
22
+ }
23
+ // Find all .md files in the directory
24
+ const files = fs.readdirSync(directory);
25
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
26
+ // Log warning for empty directories
27
+ if (mdFiles.length === 0) {
28
+ console.warn(`Warning: No .md files found in directory: ${directory}`);
29
+ return new Map();
30
+ }
31
+ const registry = new Map();
32
+ // Load each file and filter out orchestrators
33
+ for (const file of mdFiles) {
34
+ const filepath = path.join(directory, file);
35
+ try {
36
+ const sop = await loadSOP(filepath);
37
+ // Filter out orchestrator SOPs
38
+ if (sop.type !== "orchestrator") {
39
+ registry.set(sop.name, sop);
40
+ }
41
+ }
42
+ catch (error) {
43
+ // Log error and continue processing other files
44
+ const errorMessage = error instanceof Error ? error.message : String(error);
45
+ console.error(`Error loading SOP file ${filepath}: ${errorMessage}`);
46
+ }
47
+ }
48
+ return registry;
49
+ }
50
+ /**
51
+ * Finds the orchestrator SOP in a directory.
52
+ * Returns the built-in default orchestrator if none is found.
53
+ *
54
+ * @param directory - Path to scan (default: "./sops")
55
+ * @returns The orchestrator SOPDefinition (user-defined or default)
56
+ * @throws DirectoryNotFoundError if directory doesn't exist
57
+ * @throws MultipleOrchestratorsError if more than one orchestrator found
58
+ */
59
+ export async function findOrchestrator(directory = "./sops") {
60
+ // Check if directory exists
61
+ if (!fs.existsSync(directory)) {
62
+ throw new DirectoryNotFoundError(directory);
63
+ }
64
+ const stats = fs.statSync(directory);
65
+ if (!stats.isDirectory()) {
66
+ throw new DirectoryNotFoundError(directory);
67
+ }
68
+ // Find all .md files in the directory
69
+ const files = fs.readdirSync(directory);
70
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
71
+ const orchestrators = [];
72
+ const orchestratorFiles = [];
73
+ // Load each file and find orchestrators
74
+ for (const file of mdFiles) {
75
+ const filepath = path.join(directory, file);
76
+ try {
77
+ const sop = await loadSOP(filepath);
78
+ if (sop.type === "orchestrator") {
79
+ orchestrators.push(sop);
80
+ orchestratorFiles.push(filepath);
81
+ }
82
+ }
83
+ catch (_error) {
84
+ // Skip invalid files when searching for orchestrator
85
+ }
86
+ }
87
+ // Check for multiple orchestrators
88
+ if (orchestrators.length > 1) {
89
+ throw new MultipleOrchestratorsError(directory, orchestratorFiles);
90
+ }
91
+ // Return user-defined orchestrator or fall back to default
92
+ if (orchestrators.length === 1) {
93
+ return orchestrators[0];
94
+ }
95
+ return DEFAULT_ORCHESTRATOR;
96
+ }
97
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/agents/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import type { InputDef, SOPDefinition, SOPFrontmatter } from "../types/types.js";
3
+ /**
4
+ * Validates frontmatter data against the SOPFrontmatter schema
5
+ * @throws FrontmatterValidationError if validation fails
6
+ */
7
+ export declare function validateFrontmatter(data: unknown, filepath: string): SOPFrontmatter;
8
+ /**
9
+ * Generates a Zod schema from input definitions
10
+ * Always includes a required 'task' field
11
+ */
12
+ export declare function generateZodSchema(inputs?: Record<string, InputDef>): z.ZodObject<z.ZodRawShape>;
13
+ /**
14
+ * Loads and parses an SOP file
15
+ * @throws FileNotFoundError if file doesn't exist
16
+ * @throws FrontmatterParseError if YAML is malformed
17
+ * @throws FrontmatterValidationError if frontmatter validation fails
18
+ */
19
+ export declare function loadSOP(filepath: string): Promise<SOPDefinition>;
20
+ //# sourceMappingURL=sop-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sop-loader.d.ts","sourceRoot":"","sources":["../../src/agents/sop-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,KAAK,EACX,QAAQ,EACR,aAAa,EACb,cAAc,EACd,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,GACd,cAAc,CA4EhB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC/B,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAoD5B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA6CtE"}
@@ -0,0 +1,150 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import matter from "gray-matter";
4
+ import { z } from "zod";
5
+ import { FileNotFoundError, FrontmatterParseError, FrontmatterValidationError, } from "../types/errors.js";
6
+ /**
7
+ * Validates frontmatter data against the SOPFrontmatter schema
8
+ * @throws FrontmatterValidationError if validation fails
9
+ */
10
+ export function validateFrontmatter(data, filepath) {
11
+ if (typeof data !== "object" || data === null) {
12
+ throw new FrontmatterValidationError(filepath, "frontmatter", "must be an object");
13
+ }
14
+ const obj = data;
15
+ // Validate required 'name' field
16
+ if (!("name" in obj) || obj.name === undefined || obj.name === null) {
17
+ throw new FrontmatterValidationError(filepath, "name", "is required but missing");
18
+ }
19
+ if (typeof obj.name !== "string" || obj.name.trim() === "") {
20
+ throw new FrontmatterValidationError(filepath, "name", "must be a non-empty string");
21
+ }
22
+ // Validate required 'description' field
23
+ if (!("description" in obj) ||
24
+ obj.description === undefined ||
25
+ obj.description === null) {
26
+ throw new FrontmatterValidationError(filepath, "description", "is required but missing");
27
+ }
28
+ if (typeof obj.description !== "string" || obj.description.trim() === "") {
29
+ throw new FrontmatterValidationError(filepath, "description", "must be a non-empty string");
30
+ }
31
+ // Validate 'type' field if present
32
+ if ("type" in obj && obj.type !== undefined) {
33
+ if (obj.type !== "agent" && obj.type !== "orchestrator") {
34
+ throw new FrontmatterValidationError(filepath, "type", 'must be either "agent" or "orchestrator"');
35
+ }
36
+ }
37
+ // Validate optional fields
38
+ const version = typeof obj.version === "string" ? obj.version : undefined;
39
+ const tools = Array.isArray(obj.tools) ? obj.tools : undefined;
40
+ const inputs = typeof obj.inputs === "object" && obj.inputs !== null
41
+ ? obj.inputs
42
+ : undefined;
43
+ const model = typeof obj.model === "string" ? obj.model : undefined;
44
+ return {
45
+ name: obj.name,
46
+ description: obj.description,
47
+ version,
48
+ tools,
49
+ inputs,
50
+ type: obj.type ?? "agent", // Default to "agent"
51
+ model,
52
+ };
53
+ }
54
+ /**
55
+ * Generates a Zod schema from input definitions
56
+ * Always includes a required 'task' field
57
+ */
58
+ export function generateZodSchema(inputs) {
59
+ const shape = {
60
+ task: z.string().describe("The specific task to perform"),
61
+ };
62
+ if (inputs) {
63
+ for (const [fieldName, inputDef] of Object.entries(inputs)) {
64
+ let fieldSchema;
65
+ // Map InputDef type to Zod type
66
+ switch (inputDef.type) {
67
+ case "string":
68
+ fieldSchema = z.string();
69
+ break;
70
+ case "number":
71
+ fieldSchema = z.number();
72
+ break;
73
+ case "boolean":
74
+ fieldSchema = z.boolean();
75
+ break;
76
+ case "enum":
77
+ if (inputDef.values && inputDef.values.length > 0) {
78
+ fieldSchema = z.enum(inputDef.values);
79
+ }
80
+ else {
81
+ fieldSchema = z.string();
82
+ }
83
+ break;
84
+ case "list":
85
+ fieldSchema = z.array(z.string());
86
+ break;
87
+ default:
88
+ fieldSchema = z.string();
89
+ }
90
+ // Apply description
91
+ fieldSchema = fieldSchema.describe(inputDef.description);
92
+ // Apply default value if specified
93
+ if (inputDef.default !== undefined) {
94
+ fieldSchema = fieldSchema.default(inputDef.default);
95
+ }
96
+ // Apply optional if required is false
97
+ if (inputDef.required === false) {
98
+ fieldSchema = fieldSchema.optional();
99
+ }
100
+ shape[fieldName] = fieldSchema;
101
+ }
102
+ }
103
+ return z.object(shape);
104
+ }
105
+ /**
106
+ * Loads and parses an SOP file
107
+ * @throws FileNotFoundError if file doesn't exist
108
+ * @throws FrontmatterParseError if YAML is malformed
109
+ * @throws FrontmatterValidationError if frontmatter validation fails
110
+ */
111
+ export async function loadSOP(filepath) {
112
+ // Check if file exists
113
+ if (!fs.existsSync(filepath)) {
114
+ throw new FileNotFoundError(filepath);
115
+ }
116
+ // Read file content
117
+ const content = fs.readFileSync(filepath, "utf-8");
118
+ // Parse with gray-matter
119
+ let parsed;
120
+ try {
121
+ parsed = matter(content);
122
+ }
123
+ catch (error) {
124
+ const errorMessage = error instanceof Error ? error.message : String(error);
125
+ throw new FrontmatterParseError(filepath, errorMessage);
126
+ }
127
+ // Validate frontmatter
128
+ const frontmatter = validateFrontmatter(parsed.data, filepath);
129
+ // Check if name matches filename (log warning if not)
130
+ const filename = path.basename(filepath, ".md");
131
+ if (frontmatter.name !== filename) {
132
+ console.warn(`Warning: SOP name "${frontmatter.name}" does not match filename "${filename}" in ${filepath}`);
133
+ }
134
+ // Generate Zod schema from inputs
135
+ const zodSchema = generateZodSchema(frontmatter.inputs);
136
+ // Return complete SOPDefinition
137
+ return {
138
+ name: frontmatter.name,
139
+ description: frontmatter.description,
140
+ version: frontmatter.version ?? "1.0.0",
141
+ tools: frontmatter.tools ?? [],
142
+ inputs: frontmatter.inputs ?? {},
143
+ body: parsed.content.trim(),
144
+ filepath,
145
+ type: frontmatter.type ?? "agent",
146
+ zodSchema,
147
+ model: frontmatter.model,
148
+ };
149
+ }
150
+ //# sourceMappingURL=sop-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sop-loader.js","sourceRoot":"","sources":["../../src/agents/sop-loader.ts"],"names":[],"mappings":"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"}