beth-copilot 1.0.14 → 1.0.16

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 (236) hide show
  1. package/CHANGELOG.md +195 -177
  2. package/README.md +528 -185
  3. package/bin/cli.js +47 -0
  4. package/dist/cli/commands/doctor.e2e.test.d.ts +8 -0
  5. package/dist/cli/commands/doctor.e2e.test.d.ts.map +1 -0
  6. package/dist/cli/commands/doctor.e2e.test.js +428 -0
  7. package/dist/cli/commands/doctor.e2e.test.js.map +1 -0
  8. package/dist/cli/commands/doctor.test.js +1 -1
  9. package/dist/cli/commands/help.e2e.test.d.ts +9 -0
  10. package/dist/cli/commands/help.e2e.test.d.ts.map +1 -0
  11. package/dist/cli/commands/help.e2e.test.js +150 -0
  12. package/dist/cli/commands/help.e2e.test.js.map +1 -0
  13. package/dist/cli/commands/init.test.d.ts +6 -0
  14. package/dist/cli/commands/init.test.d.ts.map +1 -0
  15. package/dist/cli/commands/init.test.js +289 -0
  16. package/dist/cli/commands/init.test.js.map +1 -0
  17. package/dist/cli/commands/mcp.e2e.test.d.ts +9 -0
  18. package/dist/cli/commands/mcp.e2e.test.d.ts.map +1 -0
  19. package/dist/cli/commands/mcp.e2e.test.js +139 -0
  20. package/dist/cli/commands/mcp.e2e.test.js.map +1 -0
  21. package/dist/cli/commands/pipeline.e2e.test.d.ts +9 -0
  22. package/dist/cli/commands/pipeline.e2e.test.d.ts.map +1 -0
  23. package/dist/cli/commands/pipeline.e2e.test.js +192 -0
  24. package/dist/cli/commands/pipeline.e2e.test.js.map +1 -0
  25. package/dist/cli/commands/quickstart.test.d.ts +6 -0
  26. package/dist/cli/commands/quickstart.test.d.ts.map +1 -0
  27. package/dist/cli/commands/quickstart.test.js +232 -0
  28. package/dist/cli/commands/quickstart.test.js.map +1 -0
  29. package/dist/core/agents/frontmatter.test.d.ts +8 -0
  30. package/dist/core/agents/frontmatter.test.d.ts.map +1 -0
  31. package/dist/core/agents/frontmatter.test.js +589 -0
  32. package/dist/core/agents/frontmatter.test.js.map +1 -0
  33. package/dist/core/agents/handoffs.test.d.ts +8 -0
  34. package/dist/core/agents/handoffs.test.d.ts.map +1 -0
  35. package/dist/core/agents/handoffs.test.js +320 -0
  36. package/dist/core/agents/handoffs.test.js.map +1 -0
  37. package/dist/core/agents/loader.test.js +1 -1
  38. package/dist/core/agents/suite.test.d.ts +8 -0
  39. package/dist/core/agents/suite.test.d.ts.map +1 -0
  40. package/dist/core/agents/suite.test.js +207 -0
  41. package/dist/core/agents/suite.test.js.map +1 -0
  42. package/dist/core/agents/tools.test.d.ts +8 -0
  43. package/dist/core/agents/tools.test.d.ts.map +1 -0
  44. package/dist/core/agents/tools.test.js +332 -0
  45. package/dist/core/agents/tools.test.js.map +1 -0
  46. package/dist/core/context.d.ts +171 -0
  47. package/dist/core/context.d.ts.map +1 -0
  48. package/dist/core/context.js +353 -0
  49. package/dist/core/context.js.map +1 -0
  50. package/dist/core/context.test.d.ts +8 -0
  51. package/dist/core/context.test.d.ts.map +1 -0
  52. package/dist/core/context.test.js +253 -0
  53. package/dist/core/context.test.js.map +1 -0
  54. package/dist/core/handoffs.d.ts +151 -0
  55. package/dist/core/handoffs.d.ts.map +1 -0
  56. package/dist/core/handoffs.js +220 -0
  57. package/dist/core/handoffs.js.map +1 -0
  58. package/dist/core/handoffs.test.d.ts +8 -0
  59. package/dist/core/handoffs.test.d.ts.map +1 -0
  60. package/dist/core/handoffs.test.js +231 -0
  61. package/dist/core/handoffs.test.js.map +1 -0
  62. package/dist/core/orchestrator.d.ts +246 -0
  63. package/dist/core/orchestrator.d.ts.map +1 -0
  64. package/dist/core/orchestrator.js +514 -0
  65. package/dist/core/orchestrator.js.map +1 -0
  66. package/dist/core/orchestrator.test.d.ts +8 -0
  67. package/dist/core/orchestrator.test.d.ts.map +1 -0
  68. package/dist/core/orchestrator.test.js +517 -0
  69. package/dist/core/orchestrator.test.js.map +1 -0
  70. package/dist/core/router.d.ts +102 -0
  71. package/dist/core/router.d.ts.map +1 -0
  72. package/dist/core/router.js +178 -0
  73. package/dist/core/router.js.map +1 -0
  74. package/dist/core/router.test.d.ts +8 -0
  75. package/dist/core/router.test.d.ts.map +1 -0
  76. package/dist/core/router.test.js +215 -0
  77. package/dist/core/router.test.js.map +1 -0
  78. package/dist/index.d.ts +9 -0
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +7 -0
  81. package/dist/index.js.map +1 -1
  82. package/dist/init.test.js +288 -0
  83. package/dist/providers/azure.d.ts +147 -0
  84. package/dist/providers/azure.d.ts.map +1 -0
  85. package/dist/providers/azure.js +491 -0
  86. package/dist/providers/azure.js.map +1 -0
  87. package/dist/providers/azure.test.d.ts +11 -0
  88. package/dist/providers/azure.test.d.ts.map +1 -0
  89. package/dist/providers/azure.test.js +330 -0
  90. package/dist/providers/azure.test.js.map +1 -0
  91. package/dist/providers/config.d.ts +87 -0
  92. package/dist/providers/config.d.ts.map +1 -0
  93. package/dist/providers/config.js +193 -0
  94. package/dist/providers/config.js.map +1 -0
  95. package/dist/providers/config.test.d.ts +7 -0
  96. package/dist/providers/config.test.d.ts.map +1 -0
  97. package/dist/providers/config.test.js +370 -0
  98. package/dist/providers/config.test.js.map +1 -0
  99. package/dist/providers/index.d.ts +18 -0
  100. package/dist/providers/index.d.ts.map +1 -0
  101. package/dist/providers/index.js +14 -0
  102. package/dist/providers/index.js.map +1 -0
  103. package/dist/providers/interface.d.ts +191 -0
  104. package/dist/providers/interface.d.ts.map +1 -0
  105. package/dist/providers/interface.js +94 -0
  106. package/dist/providers/interface.js.map +1 -0
  107. package/dist/providers/retry.d.ts +128 -0
  108. package/dist/providers/retry.d.ts.map +1 -0
  109. package/dist/providers/retry.js +205 -0
  110. package/dist/providers/retry.js.map +1 -0
  111. package/dist/providers/retry.test.d.ts +7 -0
  112. package/dist/providers/retry.test.d.ts.map +1 -0
  113. package/dist/providers/retry.test.js +439 -0
  114. package/dist/providers/retry.test.js.map +1 -0
  115. package/dist/providers/streaming.d.ts +157 -0
  116. package/dist/providers/streaming.d.ts.map +1 -0
  117. package/dist/providers/streaming.js +233 -0
  118. package/dist/providers/streaming.js.map +1 -0
  119. package/dist/providers/streaming.test.d.ts +7 -0
  120. package/dist/providers/streaming.test.d.ts.map +1 -0
  121. package/dist/providers/streaming.test.js +372 -0
  122. package/dist/providers/streaming.test.js.map +1 -0
  123. package/dist/providers/types.d.ts +209 -0
  124. package/dist/providers/types.d.ts.map +1 -0
  125. package/dist/providers/types.js +53 -0
  126. package/dist/providers/types.js.map +1 -0
  127. package/dist/providers/types.test.d.ts +7 -0
  128. package/dist/providers/types.test.d.ts.map +1 -0
  129. package/dist/providers/types.test.js +141 -0
  130. package/dist/providers/types.test.js.map +1 -0
  131. package/dist/tools/cli/beads.d.ts +27 -0
  132. package/dist/tools/cli/beads.d.ts.map +1 -0
  133. package/dist/tools/cli/beads.js +172 -0
  134. package/dist/tools/cli/beads.js.map +1 -0
  135. package/dist/tools/cli/beads.test.d.ts +8 -0
  136. package/dist/tools/cli/beads.test.d.ts.map +1 -0
  137. package/dist/tools/cli/beads.test.js +264 -0
  138. package/dist/tools/cli/beads.test.js.map +1 -0
  139. package/dist/tools/cli/editFile.d.ts +17 -0
  140. package/dist/tools/cli/editFile.d.ts.map +1 -0
  141. package/dist/tools/cli/editFile.js +125 -0
  142. package/dist/tools/cli/editFile.js.map +1 -0
  143. package/dist/tools/cli/editFile.test.d.ts +8 -0
  144. package/dist/tools/cli/editFile.test.d.ts.map +1 -0
  145. package/dist/tools/cli/editFile.test.js +177 -0
  146. package/dist/tools/cli/editFile.test.js.map +1 -0
  147. package/dist/tools/cli/readFile.d.ts +25 -0
  148. package/dist/tools/cli/readFile.d.ts.map +1 -0
  149. package/dist/tools/cli/readFile.js +118 -0
  150. package/dist/tools/cli/readFile.js.map +1 -0
  151. package/dist/tools/cli/readFile.test.d.ts +8 -0
  152. package/dist/tools/cli/readFile.test.d.ts.map +1 -0
  153. package/dist/tools/cli/readFile.test.js +194 -0
  154. package/dist/tools/cli/readFile.test.js.map +1 -0
  155. package/dist/tools/cli/search.d.ts +16 -0
  156. package/dist/tools/cli/search.d.ts.map +1 -0
  157. package/dist/tools/cli/search.js +261 -0
  158. package/dist/tools/cli/search.js.map +1 -0
  159. package/dist/tools/cli/search.test.d.ts +8 -0
  160. package/dist/tools/cli/search.test.d.ts.map +1 -0
  161. package/dist/tools/cli/search.test.js +172 -0
  162. package/dist/tools/cli/search.test.js.map +1 -0
  163. package/dist/tools/cli/subagent.d.ts +43 -0
  164. package/dist/tools/cli/subagent.d.ts.map +1 -0
  165. package/dist/tools/cli/subagent.js +99 -0
  166. package/dist/tools/cli/subagent.js.map +1 -0
  167. package/dist/tools/cli/subagent.test.d.ts +8 -0
  168. package/dist/tools/cli/subagent.test.d.ts.map +1 -0
  169. package/dist/tools/cli/subagent.test.js +190 -0
  170. package/dist/tools/cli/subagent.test.js.map +1 -0
  171. package/dist/tools/cli/terminal.d.ts +19 -0
  172. package/dist/tools/cli/terminal.d.ts.map +1 -0
  173. package/dist/tools/cli/terminal.js +164 -0
  174. package/dist/tools/cli/terminal.js.map +1 -0
  175. package/dist/tools/cli/terminal.test.d.ts +8 -0
  176. package/dist/tools/cli/terminal.test.d.ts.map +1 -0
  177. package/dist/tools/cli/terminal.test.js +161 -0
  178. package/dist/tools/cli/terminal.test.js.map +1 -0
  179. package/dist/tools/index.d.ts +25 -0
  180. package/dist/tools/index.d.ts.map +1 -0
  181. package/dist/tools/index.js +41 -0
  182. package/dist/tools/index.js.map +1 -0
  183. package/dist/tools/interface.d.ts +64 -0
  184. package/dist/tools/interface.d.ts.map +1 -0
  185. package/dist/tools/interface.js +37 -0
  186. package/dist/tools/interface.js.map +1 -0
  187. package/dist/tools/interface.test.d.ts +7 -0
  188. package/dist/tools/interface.test.d.ts.map +1 -0
  189. package/dist/tools/interface.test.js +179 -0
  190. package/dist/tools/interface.test.js.map +1 -0
  191. package/dist/tools/mcp/bridge.d.ts +48 -0
  192. package/dist/tools/mcp/bridge.d.ts.map +1 -0
  193. package/dist/tools/mcp/bridge.js +128 -0
  194. package/dist/tools/mcp/bridge.js.map +1 -0
  195. package/dist/tools/mcp/bridge.test.d.ts +8 -0
  196. package/dist/tools/mcp/bridge.test.d.ts.map +1 -0
  197. package/dist/tools/mcp/bridge.test.js +300 -0
  198. package/dist/tools/mcp/bridge.test.js.map +1 -0
  199. package/dist/tools/mcp/client.d.ts +135 -0
  200. package/dist/tools/mcp/client.d.ts.map +1 -0
  201. package/dist/tools/mcp/client.js +263 -0
  202. package/dist/tools/mcp/client.js.map +1 -0
  203. package/dist/tools/mcp/client.test.d.ts +8 -0
  204. package/dist/tools/mcp/client.test.d.ts.map +1 -0
  205. package/dist/tools/mcp/client.test.js +390 -0
  206. package/dist/tools/mcp/client.test.js.map +1 -0
  207. package/dist/tools/registry.d.ts +82 -0
  208. package/dist/tools/registry.d.ts.map +1 -0
  209. package/dist/tools/registry.js +99 -0
  210. package/dist/tools/registry.js.map +1 -0
  211. package/dist/tools/registry.test.d.ts +7 -0
  212. package/dist/tools/registry.test.d.ts.map +1 -0
  213. package/dist/tools/registry.test.js +199 -0
  214. package/dist/tools/registry.test.js.map +1 -0
  215. package/dist/tools/suite.test.d.ts +11 -0
  216. package/dist/tools/suite.test.d.ts.map +1 -0
  217. package/dist/tools/suite.test.js +119 -0
  218. package/dist/tools/suite.test.js.map +1 -0
  219. package/dist/tools/types.d.ts +75 -0
  220. package/dist/tools/types.d.ts.map +1 -0
  221. package/dist/tools/types.js +30 -0
  222. package/dist/tools/types.js.map +1 -0
  223. package/dist/tools/types.test.d.ts +7 -0
  224. package/dist/tools/types.test.d.ts.map +1 -0
  225. package/dist/tools/types.test.js +178 -0
  226. package/dist/tools/types.test.js.map +1 -0
  227. package/package.json +60 -56
  228. package/sbom.json +3302 -8
  229. package/templates/.github/agents/beth.agent.md +329 -329
  230. package/templates/.github/agents/developer.agent.md +572 -572
  231. package/templates/.github/agents/product-manager.agent.md +272 -272
  232. package/templates/.github/agents/researcher.agent.md +338 -338
  233. package/templates/.github/agents/security-reviewer.agent.md +465 -465
  234. package/templates/.github/agents/tester.agent.md +496 -496
  235. package/templates/.github/agents/ux-designer.agent.md +393 -393
  236. package/templates/mcp.json.example +4 -0
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Handoff Validation Tests
3
+ *
4
+ * Tests for agent handoff configuration validation.
5
+ * Handoff interface: { label, agent, prompt, send? }
6
+ */
7
+ import { describe, it, beforeEach, afterEach } from 'node:test';
8
+ import assert from 'node:assert';
9
+ import { join } from 'node:path';
10
+ import { mkdirSync, writeFileSync, rmSync, existsSync } from 'node:fs';
11
+ import { loadAgent, loadAgents } from './loader.js';
12
+ // Test fixtures directory
13
+ const TEST_DIR = join(process.cwd(), 'test-fixtures-handoffs');
14
+ const TEMPLATES_AGENTS_DIR = join(process.cwd(), 'templates', '.github', 'agents');
15
+ /**
16
+ * Type guard to check if loadAgent result is an error
17
+ */
18
+ function isError(result) {
19
+ return 'error' in result;
20
+ }
21
+ /**
22
+ * Create agent file with raw YAML content for more control
23
+ */
24
+ function createTestAgentRaw(filename, yamlContent) {
25
+ const filePath = join(TEST_DIR, filename);
26
+ const content = `---
27
+ ${yamlContent}
28
+ ---
29
+
30
+ # Test Agent
31
+
32
+ This is a test agent body.
33
+ `;
34
+ writeFileSync(filePath, content, 'utf-8');
35
+ return filePath;
36
+ }
37
+ describe('Handoff Validation', () => {
38
+ beforeEach(() => {
39
+ if (!existsSync(TEST_DIR)) {
40
+ mkdirSync(TEST_DIR, { recursive: true });
41
+ }
42
+ });
43
+ afterEach(() => {
44
+ if (existsSync(TEST_DIR)) {
45
+ rmSync(TEST_DIR, { recursive: true, force: true });
46
+ }
47
+ });
48
+ describe('Valid handoff configurations', () => {
49
+ it('1. Valid handoff with all required fields (label, agent, prompt) passes', () => {
50
+ const filePath = createTestAgentRaw('valid-handoff.agent.md', `
51
+ name: Test Agent
52
+ handoffs:
53
+ - label: Switch to Developer
54
+ agent: developer
55
+ prompt: Continue implementing the feature
56
+ `);
57
+ const result = loadAgent(filePath);
58
+ assert.ok(!('error' in result), `Should pass validation: ${JSON.stringify(result)}`);
59
+ const { agent } = result;
60
+ assert.strictEqual(agent.frontmatter.handoffs?.length, 1);
61
+ assert.strictEqual(agent.frontmatter.handoffs[0].label, 'Switch to Developer');
62
+ assert.strictEqual(agent.frontmatter.handoffs[0].agent, 'developer');
63
+ assert.strictEqual(agent.frontmatter.handoffs[0].prompt, 'Continue implementing the feature');
64
+ });
65
+ it('2. Valid handoff with optional send: true passes', () => {
66
+ const filePath = createTestAgentRaw('handoff-send-true.agent.md', `
67
+ name: Test Agent
68
+ handoffs:
69
+ - label: Auto-send to Developer
70
+ agent: developer
71
+ prompt: Start immediately
72
+ send: true
73
+ `);
74
+ const result = loadAgent(filePath);
75
+ assert.ok(!('error' in result), `Should pass validation: ${JSON.stringify(result)}`);
76
+ const { agent } = result;
77
+ assert.strictEqual(agent.frontmatter.handoffs?.[0].send, true);
78
+ });
79
+ it('3. Valid handoff with optional send: false passes', () => {
80
+ const filePath = createTestAgentRaw('handoff-send-false.agent.md', `
81
+ name: Test Agent
82
+ handoffs:
83
+ - label: Prepare for Developer
84
+ agent: developer
85
+ prompt: Review before sending
86
+ send: false
87
+ `);
88
+ const result = loadAgent(filePath);
89
+ assert.ok(!('error' in result), `Should pass validation: ${JSON.stringify(result)}`);
90
+ const { agent } = result;
91
+ assert.strictEqual(agent.frontmatter.handoffs?.[0].send, false);
92
+ });
93
+ it('7. Empty handoffs array is valid', () => {
94
+ const filePath = createTestAgentRaw('empty-handoffs.agent.md', `
95
+ name: Test Agent
96
+ handoffs: []
97
+ `);
98
+ const result = loadAgent(filePath);
99
+ assert.ok(!('error' in result), `Should pass validation: ${JSON.stringify(result)}`);
100
+ const { agent } = result;
101
+ assert.ok(Array.isArray(agent.frontmatter.handoffs));
102
+ assert.strictEqual(agent.frontmatter.handoffs?.length, 0);
103
+ });
104
+ it('8. Multiple handoffs in array all get validated', () => {
105
+ const filePath = createTestAgentRaw('multiple-handoffs.agent.md', `
106
+ name: Test Agent
107
+ handoffs:
108
+ - label: To Developer
109
+ agent: developer
110
+ prompt: Implement this
111
+ - label: To Tester
112
+ agent: tester
113
+ prompt: Test this
114
+ - label: To Designer
115
+ agent: ux-designer
116
+ prompt: Design this
117
+ `);
118
+ const result = loadAgent(filePath);
119
+ assert.ok(!('error' in result), `Should pass validation: ${JSON.stringify(result)}`);
120
+ const { agent } = result;
121
+ assert.strictEqual(agent.frontmatter.handoffs?.length, 3);
122
+ assert.strictEqual(agent.frontmatter.handoffs[0].agent, 'developer');
123
+ assert.strictEqual(agent.frontmatter.handoffs[1].agent, 'tester');
124
+ assert.strictEqual(agent.frontmatter.handoffs[2].agent, 'ux-designer');
125
+ });
126
+ it('13. Handoff with extra fields (ignored) passes', () => {
127
+ const filePath = createTestAgentRaw('handoff-extra-fields.agent.md', `
128
+ name: Test Agent
129
+ handoffs:
130
+ - label: To Developer
131
+ agent: developer
132
+ prompt: Do the thing
133
+ extraField: should be ignored
134
+ anotherExtra: also ignored
135
+ `);
136
+ const result = loadAgent(filePath);
137
+ assert.ok(!('error' in result), `Should pass validation: ${JSON.stringify(result)}`);
138
+ const { agent } = result;
139
+ assert.strictEqual(agent.frontmatter.handoffs?.length, 1);
140
+ // Extra fields should be ignored in the normalized output
141
+ assert.strictEqual(agent.frontmatter.handoffs[0].label, 'To Developer');
142
+ assert.strictEqual(agent.frontmatter.handoffs[0].agent, 'developer');
143
+ assert.strictEqual(agent.frontmatter.handoffs[0].prompt, 'Do the thing');
144
+ });
145
+ });
146
+ describe('Invalid handoff configurations', () => {
147
+ it('4. Handoff missing label fails validation', () => {
148
+ const filePath = createTestAgentRaw('missing-label.agent.md', `
149
+ name: Test Agent
150
+ handoffs:
151
+ - agent: developer
152
+ prompt: Do work
153
+ `);
154
+ const result = loadAgent(filePath);
155
+ assert.ok(isError(result), 'Should fail validation');
156
+ assert.ok(result.error.message.includes('missing required fields') ||
157
+ result.error.message.includes('label'), `Error should mention missing fields: ${result.error.message}`);
158
+ });
159
+ it('5. Handoff missing agent fails validation', () => {
160
+ const filePath = createTestAgentRaw('missing-agent.agent.md', `
161
+ name: Test Agent
162
+ handoffs:
163
+ - label: To Someone
164
+ prompt: Do work
165
+ `);
166
+ const result = loadAgent(filePath);
167
+ assert.ok(isError(result), 'Should fail validation');
168
+ assert.ok(result.error.message.includes('missing required fields') ||
169
+ result.error.message.includes('agent'), `Error should mention missing fields: ${result.error.message}`);
170
+ });
171
+ it('6. Handoff missing prompt fails validation', () => {
172
+ const filePath = createTestAgentRaw('missing-prompt.agent.md', `
173
+ name: Test Agent
174
+ handoffs:
175
+ - label: To Developer
176
+ agent: developer
177
+ `);
178
+ const result = loadAgent(filePath);
179
+ assert.ok(isError(result), 'Should fail validation');
180
+ assert.ok(result.error.message.includes('missing required fields') ||
181
+ result.error.message.includes('prompt'), `Error should mention missing fields: ${result.error.message}`);
182
+ });
183
+ it('9. Handoff with empty string label fails validation', () => {
184
+ const filePath = createTestAgentRaw('empty-label.agent.md', `
185
+ name: Test Agent
186
+ handoffs:
187
+ - label: ""
188
+ agent: developer
189
+ prompt: Do work
190
+ `);
191
+ const result = loadAgent(filePath);
192
+ assert.ok(isError(result), 'Should fail validation for empty label');
193
+ assert.ok(result.error.message.includes('missing required fields') ||
194
+ result.error.message.includes('label'), `Error should mention missing/empty fields: ${result.error.message}`);
195
+ });
196
+ it('10. Handoff with empty string agent fails validation', () => {
197
+ const filePath = createTestAgentRaw('empty-agent.agent.md', `
198
+ name: Test Agent
199
+ handoffs:
200
+ - label: To Someone
201
+ agent: ""
202
+ prompt: Do work
203
+ `);
204
+ const result = loadAgent(filePath);
205
+ assert.ok(isError(result), 'Should fail validation for empty agent');
206
+ assert.ok(result.error.message.includes('missing required fields') ||
207
+ result.error.message.includes('agent'), `Error should mention missing/empty fields: ${result.error.message}`);
208
+ });
209
+ it('11. Handoff with empty string prompt fails validation', () => {
210
+ const filePath = createTestAgentRaw('empty-prompt.agent.md', `
211
+ name: Test Agent
212
+ handoffs:
213
+ - label: To Developer
214
+ agent: developer
215
+ prompt: ""
216
+ `);
217
+ const result = loadAgent(filePath);
218
+ assert.ok(isError(result), 'Should fail validation for empty prompt');
219
+ assert.ok(result.error.message.includes('missing required fields') ||
220
+ result.error.message.includes('prompt'), `Error should mention missing/empty fields: ${result.error.message}`);
221
+ });
222
+ it('12. Non-array handoffs value fails', () => {
223
+ const filePath = createTestAgentRaw('non-array-handoffs.agent.md', `
224
+ name: Test Agent
225
+ handoffs: "not an array"
226
+ `);
227
+ const result = loadAgent(filePath);
228
+ assert.ok(isError(result), 'Should fail validation for non-array handoffs');
229
+ assert.ok(result.error.message.includes('must be an array'), `Error should mention array requirement: ${result.error.message}`);
230
+ });
231
+ it('Non-array handoffs value (object) fails', () => {
232
+ const filePath = createTestAgentRaw('object-handoffs.agent.md', `
233
+ name: Test Agent
234
+ handoffs:
235
+ label: Single handoff as object
236
+ agent: developer
237
+ prompt: This is wrong
238
+ `);
239
+ const result = loadAgent(filePath);
240
+ // YAML interprets this as an object with keys, not an array
241
+ assert.ok(isError(result), 'Should fail validation for object handoffs');
242
+ assert.ok(result.error.message.includes('must be an array'), `Error should mention array requirement: ${result.error.message}`);
243
+ });
244
+ it('8. Multiple handoffs - second one invalid fails entire validation', () => {
245
+ const filePath = createTestAgentRaw('second-invalid.agent.md', `
246
+ name: Test Agent
247
+ handoffs:
248
+ - label: Valid One
249
+ agent: developer
250
+ prompt: This is valid
251
+ - label: Invalid One
252
+ agent: tester
253
+ `);
254
+ const result = loadAgent(filePath);
255
+ assert.ok(isError(result), 'Should fail when any handoff is invalid');
256
+ assert.ok(result.error.message.includes('index 1') ||
257
+ result.error.message.includes('missing required fields'), `Error should indicate which handoff failed: ${result.error.message}`);
258
+ });
259
+ });
260
+ describe('Real agent files validation', () => {
261
+ it('14. Test actual agent files have valid handoffs pointing to existing agents', () => {
262
+ const result = loadAgents(TEMPLATES_AGENTS_DIR);
263
+ // Should load without errors
264
+ assert.strictEqual(result.errors.length, 0, `Agent loading errors: ${JSON.stringify(result.errors)}`);
265
+ // Build set of all agent IDs
266
+ const agentIds = new Set(result.agents.map((a) => a.id.toLowerCase()));
267
+ // Check every handoff references an existing agent
268
+ const handoffErrors = [];
269
+ for (const agent of result.agents) {
270
+ const handoffs = agent.frontmatter.handoffs ?? [];
271
+ for (const handoff of handoffs) {
272
+ const targetAgent = handoff.agent.toLowerCase();
273
+ if (!agentIds.has(targetAgent)) {
274
+ handoffErrors.push(`Agent '${agent.id}' has handoff to non-existent agent '${handoff.agent}'`);
275
+ }
276
+ // Also verify required fields are present and non-empty
277
+ if (!handoff.label || handoff.label.trim() === '') {
278
+ handoffErrors.push(`Agent '${agent.id}' has handoff with empty label`);
279
+ }
280
+ if (!handoff.agent || handoff.agent.trim() === '') {
281
+ handoffErrors.push(`Agent '${agent.id}' has handoff with empty agent`);
282
+ }
283
+ if (!handoff.prompt || handoff.prompt.trim() === '') {
284
+ handoffErrors.push(`Agent '${agent.id}' has handoff with empty prompt`);
285
+ }
286
+ }
287
+ }
288
+ assert.strictEqual(handoffErrors.length, 0, `Handoff validation errors:\n${handoffErrors.join('\n')}`);
289
+ });
290
+ it('All agents with handoffs have at least label, agent, and prompt', () => {
291
+ const result = loadAgents(TEMPLATES_AGENTS_DIR);
292
+ for (const agent of result.agents) {
293
+ if (!agent.frontmatter.handoffs)
294
+ continue;
295
+ for (let i = 0; i < agent.frontmatter.handoffs.length; i++) {
296
+ const handoff = agent.frontmatter.handoffs[i];
297
+ assert.ok(typeof handoff.label === 'string' && handoff.label.length > 0, `${agent.id} handoff[${i}] should have non-empty label`);
298
+ assert.ok(typeof handoff.agent === 'string' && handoff.agent.length > 0, `${agent.id} handoff[${i}] should have non-empty agent`);
299
+ assert.ok(typeof handoff.prompt === 'string' && handoff.prompt.length > 0, `${agent.id} handoff[${i}] should have non-empty prompt`);
300
+ // send should be boolean or undefined
301
+ if (handoff.send !== undefined) {
302
+ assert.strictEqual(typeof handoff.send, 'boolean', `${agent.id} handoff[${i}].send should be boolean if present`);
303
+ }
304
+ }
305
+ }
306
+ });
307
+ it('Beth agent has handoffs to all expected specialists', () => {
308
+ const result = loadAgents(TEMPLATES_AGENTS_DIR);
309
+ const beth = result.agents.find((a) => a.id === 'beth');
310
+ assert.ok(beth, 'Beth agent should exist');
311
+ assert.ok(beth.frontmatter.handoffs, 'Beth should have handoffs');
312
+ const handoffTargets = beth.frontmatter.handoffs.map((h) => h.agent.toLowerCase());
313
+ const expectedTargets = ['developer', 'product-manager', 'ux-designer', 'tester', 'researcher'];
314
+ for (const expected of expectedTargets) {
315
+ assert.ok(handoffTargets.includes(expected), `Beth should have handoff to ${expected}`);
316
+ }
317
+ });
318
+ });
319
+ });
320
+ //# sourceMappingURL=handoffs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoffs.test.js","sourceRoot":"","sources":["../../../src/core/agents/handoffs.test.ts"],"names":[],"mappings":"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"}
@@ -37,7 +37,7 @@ describe('Agent Loader', () => {
37
37
  assert.strictEqual(agent.id, 'beth');
38
38
  assert.strictEqual(agent.frontmatter.name, 'Beth');
39
39
  assert.ok(agent.frontmatter.description?.includes('orchestrator'));
40
- assert.strictEqual(agent.frontmatter.model, 'Claude Opus 4.5');
40
+ assert.strictEqual(agent.frontmatter.model, 'Claude Opus 4.6');
41
41
  assert.strictEqual(agent.frontmatter.infer, true);
42
42
  assert.ok(Array.isArray(agent.frontmatter.tools));
43
43
  assert.ok(Array.isArray(agent.frontmatter.handoffs));
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Agent Suite Integration Tests
3
+ *
4
+ * Validates the complete Beth agent suite is coherent and functional together.
5
+ * Tests all 7 agents: beth, developer, product-manager, researcher, security-reviewer, tester, ux-designer
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=suite.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suite.test.d.ts","sourceRoot":"","sources":["../../../src/core/agents/suite.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Agent Suite Integration Tests
3
+ *
4
+ * Validates the complete Beth agent suite is coherent and functional together.
5
+ * Tests all 7 agents: beth, developer, product-manager, researcher, security-reviewer, tester, ux-designer
6
+ */
7
+ import { describe, it } from 'node:test';
8
+ import assert from 'node:assert';
9
+ import { join } from 'node:path';
10
+ import { loadAgents, getAgentById, getInferableAgents, } from './loader.js';
11
+ // Test against templates directory - the source of truth for agent definitions
12
+ const TEMPLATES_AGENTS_DIR = join(process.cwd(), 'templates', '.github', 'agents');
13
+ // Expected agent IDs (from filenames)
14
+ const EXPECTED_AGENT_IDS = [
15
+ 'beth',
16
+ 'developer',
17
+ 'product-manager',
18
+ 'researcher',
19
+ 'security-reviewer',
20
+ 'tester',
21
+ 'ux-designer',
22
+ ];
23
+ const EXPECTED_AGENT_COUNT = 7;
24
+ describe('Agent Suite Integration Tests', () => {
25
+ // Load agents once for all tests
26
+ const result = loadAgents(TEMPLATES_AGENTS_DIR);
27
+ describe('Suite Loading', () => {
28
+ it('1. All 7 agent files load without errors', () => {
29
+ assert.strictEqual(result.errors.length, 0, `Agent loading errors: ${JSON.stringify(result.errors, null, 2)}`);
30
+ assert.strictEqual(result.agents.length, EXPECTED_AGENT_COUNT, `Expected ${EXPECTED_AGENT_COUNT} agents, got ${result.agents.length}`);
31
+ });
32
+ it('15. Agent file count matches expected (7 agents)', () => {
33
+ assert.strictEqual(result.agents.length, EXPECTED_AGENT_COUNT, `Expected exactly ${EXPECTED_AGENT_COUNT} agents`);
34
+ const loadedIds = result.agents.map((a) => a.id).sort();
35
+ const expectedIds = [...EXPECTED_AGENT_IDS].sort();
36
+ assert.deepStrictEqual(loadedIds, expectedIds, 'Agent IDs should match expected set');
37
+ });
38
+ });
39
+ describe('Required Fields', () => {
40
+ it('2. All agents have required name field', () => {
41
+ for (const agent of result.agents) {
42
+ assert.ok(agent.frontmatter.name, `Agent ${agent.id} is missing required 'name' field`);
43
+ assert.strictEqual(typeof agent.frontmatter.name, 'string', `Agent ${agent.id} 'name' must be a string`);
44
+ assert.ok(agent.frontmatter.name.length > 0, `Agent ${agent.id} 'name' must be non-empty`);
45
+ }
46
+ });
47
+ it('3. All agents have description field', () => {
48
+ for (const agent of result.agents) {
49
+ assert.ok(agent.frontmatter.description, `Agent ${agent.id} is missing 'description' field`);
50
+ assert.strictEqual(typeof agent.frontmatter.description, 'string', `Agent ${agent.id} 'description' must be a string`);
51
+ assert.ok(agent.frontmatter.description.length > 0, `Agent ${agent.id} 'description' must be non-empty`);
52
+ }
53
+ });
54
+ it('14. All markdown bodies are non-empty', () => {
55
+ for (const agent of result.agents) {
56
+ assert.ok(agent.body, `Agent ${agent.id} has no body content`);
57
+ assert.ok(agent.body.length > 50, `Agent ${agent.id} body is too short (${agent.body.length} chars), expected substantial instructions`);
58
+ }
59
+ });
60
+ });
61
+ describe('Beth Agent Specifics', () => {
62
+ it('4. Beth agent has infer: true (can be invoked as subagent)', () => {
63
+ const beth = getAgentById(result, 'beth');
64
+ assert.ok(beth, 'Beth agent must exist');
65
+ assert.strictEqual(beth.frontmatter.infer, true, 'Beth must have infer: true to be invokable as subagent');
66
+ });
67
+ it('5. Beth agent has agent tool for subagent invocation', () => {
68
+ const beth = getAgentById(result, 'beth');
69
+ assert.ok(beth, 'Beth agent must exist');
70
+ assert.ok(Array.isArray(beth.frontmatter.tools), 'Beth must have tools array');
71
+ // The 'agent' tool is what enables spawning subagents in VS Code agents
72
+ assert.ok(beth.frontmatter.tools.includes('agent'), `Beth must have 'agent' tool for subagent invocation. Found tools: ${beth.frontmatter.tools.join(', ')}`);
73
+ });
74
+ });
75
+ describe('Uniqueness Constraints', () => {
76
+ it('6. All agent names are unique', () => {
77
+ const names = result.agents.map((a) => a.frontmatter.name);
78
+ const uniqueNames = new Set(names);
79
+ assert.strictEqual(uniqueNames.size, names.length, `Duplicate agent names found: ${findDuplicates(names).join(', ')}`);
80
+ });
81
+ it('7. All agent IDs (from filename) are unique', () => {
82
+ const ids = result.agents.map((a) => a.id);
83
+ const uniqueIds = new Set(ids);
84
+ assert.strictEqual(uniqueIds.size, ids.length, `Duplicate agent IDs found: ${findDuplicates(ids).join(', ')}`);
85
+ });
86
+ });
87
+ describe('Handoff Validation', () => {
88
+ it('8. Handoff references are valid (target agents exist)', () => {
89
+ const agentIds = new Set(result.agents.map((a) => a.id));
90
+ for (const agent of result.agents) {
91
+ const handoffs = agent.frontmatter.handoffs ?? [];
92
+ for (const handoff of handoffs) {
93
+ assert.ok(agentIds.has(handoff.agent), `Agent ${agent.id} has handoff to non-existent agent '${handoff.agent}'. ` +
94
+ `Valid agents: ${[...agentIds].join(', ')}`);
95
+ }
96
+ }
97
+ });
98
+ it('9. No circular handoff chains (single handoff does not create infinite loop)', () => {
99
+ // Build handoff graph
100
+ const handoffGraph = new Map();
101
+ for (const agent of result.agents) {
102
+ const targets = (agent.frontmatter.handoffs ?? []).map((h) => h.agent);
103
+ handoffGraph.set(agent.id, targets);
104
+ }
105
+ // Check for self-referential handoffs (immediate loop)
106
+ for (const agent of result.agents) {
107
+ const targets = handoffGraph.get(agent.id) ?? [];
108
+ assert.ok(!targets.includes(agent.id), `Agent ${agent.id} has self-referential handoff (hands off to itself)`);
109
+ }
110
+ // Note: Bidirectional handoffs (A -> B and B -> A) are allowed
111
+ // They represent valid collaboration patterns, not infinite loops
112
+ // The warning is that a single handoff chain shouldn't loop back
113
+ });
114
+ });
115
+ describe('Subagent Configuration', () => {
116
+ it('10. All agents that can be invoked as subagents have infer: true', () => {
117
+ const inferableAgents = getInferableAgents(result);
118
+ // Verify all returned agents actually have infer: true
119
+ for (const agent of inferableAgents) {
120
+ assert.strictEqual(agent.frontmatter.infer, true, `Agent ${agent.id} returned by getInferableAgents but doesn't have infer: true`);
121
+ }
122
+ // Beth should be in the list
123
+ const bethInferable = inferableAgents.some((a) => a.id === 'beth');
124
+ assert.ok(bethInferable, 'Beth must be inferable (have infer: true)');
125
+ });
126
+ });
127
+ describe('Agent-Specific Tool Requirements', () => {
128
+ it('11. Developer agent has edit tools (editFiles, createFile)', () => {
129
+ const developer = getAgentById(result, 'developer');
130
+ assert.ok(developer, 'Developer agent must exist');
131
+ assert.ok(Array.isArray(developer.frontmatter.tools), 'Developer must have tools array');
132
+ const tools = developer.frontmatter.tools;
133
+ assert.ok(tools.includes('editFiles'), `Developer must have 'editFiles' tool. Found: ${tools.join(', ')}`);
134
+ assert.ok(tools.includes('createFile'), `Developer must have 'createFile' tool. Found: ${tools.join(', ')}`);
135
+ });
136
+ it('12. Security-reviewer agent exists and has appropriate tools', () => {
137
+ const securityReviewer = getAgentById(result, 'security-reviewer');
138
+ assert.ok(securityReviewer, 'Security-reviewer agent must exist');
139
+ assert.ok(securityReviewer.frontmatter.name, 'Security-reviewer must have a name');
140
+ assert.ok(securityReviewer.frontmatter.description, 'Security-reviewer must have a description');
141
+ // Security reviewer should have code analysis tools
142
+ const tools = securityReviewer.frontmatter.tools ?? [];
143
+ assert.ok(tools.length > 0, 'Security-reviewer should have tools for code analysis');
144
+ // Should have at least codebase or textSearch for finding vulnerabilities
145
+ const hasAnalysisTools = tools.some((t) => ['codebase', 'textSearch', 'readFile', 'fileSearch'].includes(t));
146
+ assert.ok(hasAnalysisTools, `Security-reviewer should have analysis tools. Found: ${tools.join(', ')}`);
147
+ });
148
+ });
149
+ describe('Role Differentiation', () => {
150
+ it('13. Product-manager and ux-designer are distinct agents', () => {
151
+ const productManager = getAgentById(result, 'product-manager');
152
+ const uxDesigner = getAgentById(result, 'ux-designer');
153
+ assert.ok(productManager, 'Product-manager agent must exist');
154
+ assert.ok(uxDesigner, 'UX-designer agent must exist');
155
+ // Different IDs
156
+ assert.notStrictEqual(productManager.id, uxDesigner.id, 'Product-manager and UX-designer must have different IDs');
157
+ // Different names
158
+ assert.notStrictEqual(productManager.frontmatter.name, uxDesigner.frontmatter.name, 'Product-manager and UX-designer must have different names');
159
+ // Different descriptions (they serve different purposes)
160
+ assert.notStrictEqual(productManager.frontmatter.description, uxDesigner.frontmatter.description, 'Product-manager and UX-designer should have different descriptions');
161
+ // Different body content (different instructions)
162
+ assert.notStrictEqual(productManager.body, uxDesigner.body, 'Product-manager and UX-designer must have different instructions');
163
+ });
164
+ });
165
+ describe('Cross-Agent Consistency', () => {
166
+ it('All expected agents are present and loadable', () => {
167
+ for (const expectedId of EXPECTED_AGENT_IDS) {
168
+ const agent = getAgentById(result, expectedId);
169
+ assert.ok(agent, `Expected agent '${expectedId}' is missing from the suite`);
170
+ }
171
+ });
172
+ it('All agents can be found by getAgentById', () => {
173
+ for (const agent of result.agents) {
174
+ const found = getAgentById(result, agent.id);
175
+ assert.ok(found, `Agent ${agent.id} should be findable by ID`);
176
+ assert.strictEqual(found.id, agent.id);
177
+ }
178
+ });
179
+ it('Agent handoff network is well-connected (Beth has handoffs to specialists)', () => {
180
+ const beth = getAgentById(result, 'beth');
181
+ assert.ok(beth, 'Beth must exist');
182
+ const bethHandoffs = beth.frontmatter.handoffs ?? [];
183
+ const handoffTargets = new Set(bethHandoffs.map((h) => h.agent));
184
+ // Beth should be able to hand off to at least the core specialist agents
185
+ const coreSpecialists = ['developer', 'product-manager', 'ux-designer'];
186
+ for (const specialist of coreSpecialists) {
187
+ assert.ok(handoffTargets.has(specialist), `Beth should have handoff to ${specialist}. ` +
188
+ `Found handoffs to: ${[...handoffTargets].join(', ')}`);
189
+ }
190
+ });
191
+ });
192
+ });
193
+ /**
194
+ * Helper to find duplicate values in an array.
195
+ */
196
+ function findDuplicates(arr) {
197
+ const seen = new Set();
198
+ const duplicates = new Set();
199
+ for (const item of arr) {
200
+ if (seen.has(item)) {
201
+ duplicates.add(item);
202
+ }
203
+ seen.add(item);
204
+ }
205
+ return [...duplicates];
206
+ }
207
+ //# sourceMappingURL=suite.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suite.test.js","sourceRoot":"","sources":["../../../src/core/agents/suite.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,UAAU,EACV,YAAY,EACZ,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,+EAA+E;AAC/E,MAAM,oBAAoB,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAEnF,sCAAsC;AACtC,MAAM,kBAAkB,GAAG;IACzB,MAAM;IACN,WAAW;IACX,iBAAiB;IACjB,YAAY;IACZ,mBAAmB;IACnB,QAAQ;IACR,aAAa;CACL,CAAC;AAEX,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAE/B,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,iCAAiC;IACjC,MAAM,MAAM,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAEhD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,MAAM,CAAC,MAAM,EACpB,CAAC,EACD,yBAAyB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAClE,CAAC;YACF,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,MAAM,CAAC,MAAM,EACpB,oBAAoB,EACpB,YAAY,oBAAoB,gBAAgB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CACvE,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,MAAM,CAAC,MAAM,EACpB,oBAAoB,EACpB,oBAAoB,oBAAoB,SAAS,CAClD,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,WAAW,GAAG,CAAC,GAAG,kBAAkB,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,qCAAqC,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,WAAW,CAAC,IAAI,EACtB,SAAS,KAAK,CAAC,EAAE,mCAAmC,CACrD,CAAC;gBACF,MAAM,CAAC,WAAW,CAChB,OAAO,KAAK,CAAC,WAAW,CAAC,IAAI,EAC7B,QAAQ,EACR,SAAS,KAAK,CAAC,EAAE,0BAA0B,CAC5C,CAAC;gBACF,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EACjC,SAAS,KAAK,CAAC,EAAE,2BAA2B,CAC7C,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,WAAW,CAAC,WAAW,EAC7B,SAAS,KAAK,CAAC,EAAE,iCAAiC,CACnD,CAAC;gBACF,MAAM,CAAC,WAAW,CAChB,OAAO,KAAK,CAAC,WAAW,CAAC,WAAW,EACpC,QAAQ,EACR,SAAS,KAAK,CAAC,EAAE,iCAAiC,CACnD,CAAC;gBACF,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EACxC,SAAS,KAAK,CAAC,EAAE,kCAAkC,CACpD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,IAAI,EACV,SAAS,KAAK,CAAC,EAAE,sBAAsB,CACxC,CAAC;gBACF,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,EACtB,SAAS,KAAK,CAAC,EAAE,uBAAuB,KAAK,CAAC,IAAI,CAAC,MAAM,4CAA4C,CACtG,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;YACpE,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;YACzC,MAAM,CAAC,WAAW,CAChB,IAAI,CAAC,WAAW,CAAC,KAAK,EACtB,IAAI,EACJ,wDAAwD,CACzD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;YACzC,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EACrC,4BAA4B,CAC7B,CAAC;YACF,wEAAwE;YACxE,MAAM,CAAC,EAAE,CACP,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EACxC,qEAAqE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzG,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAC3D,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YAEnC,MAAM,CAAC,WAAW,CAChB,WAAW,CAAC,IAAI,EAChB,KAAK,CAAC,MAAM,EACZ,gCAAgC,cAAc,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnE,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YAE/B,MAAM,CAAC,WAAW,CAChB,SAAS,CAAC,IAAI,EACd,GAAG,CAAC,MAAM,EACV,8BAA8B,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/D,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAEzD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC;gBAElD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,MAAM,CAAC,EAAE,CACP,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAC3B,SAAS,KAAK,CAAC,EAAE,uCAAuC,OAAO,CAAC,KAAK,KAAK;wBACxE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9C,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;YACtF,sBAAsB;YACtB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;YAEjD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBACvE,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACtC,CAAC;YAED,uDAAuD;YACvD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;gBACjD,MAAM,CAAC,EAAE,CACP,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAC3B,SAAS,KAAK,CAAC,EAAE,qDAAqD,CACvE,CAAC;YACJ,CAAC;YAED,+DAA+D;YAC/D,kEAAkE;YAClE,iEAAiE;QACnE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;YAC1E,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAEnD,uDAAuD;YACvD,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;gBACpC,MAAM,CAAC,WAAW,CAChB,KAAK,CAAC,WAAW,CAAC,KAAK,EACvB,IAAI,EACJ,SAAS,KAAK,CAAC,EAAE,8DAA8D,CAChF,CAAC;YACJ,CAAC;YAED,6BAA6B;YAC7B,MAAM,aAAa,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;YACnE,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,2CAA2C,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;YACpE,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YACpD,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,4BAA4B,CAAC,CAAC;YACnD,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,EAC1C,iCAAiC,CAClC,CAAC;YAEF,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC;YAC1C,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,EAC3B,gDAAgD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnE,CAAC;YACF,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAC5B,iDAAiD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpE,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACtE,MAAM,gBAAgB,GAAG,YAAY,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;YACnE,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,oCAAoC,CAAC,CAAC;YAElE,MAAM,CAAC,EAAE,CACP,gBAAgB,CAAC,WAAW,CAAC,IAAI,EACjC,oCAAoC,CACrC,CAAC;YACF,MAAM,CAAC,EAAE,CACP,gBAAgB,CAAC,WAAW,CAAC,WAAW,EACxC,2CAA2C,CAC5C,CAAC;YAEF,oDAAoD;YACpD,MAAM,KAAK,GAAG,gBAAgB,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,MAAM,GAAG,CAAC,EAChB,uDAAuD,CACxD,CAAC;YAEF,0EAA0E;YAC1E,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACxC,CAAC,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CACjE,CAAC;YACF,MAAM,CAAC,EAAE,CACP,gBAAgB,EAChB,wDAAwD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3E,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;YAC/D,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YAEvD,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,kCAAkC,CAAC,CAAC;YAC9D,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,8BAA8B,CAAC,CAAC;YAEtD,gBAAgB;YAChB,MAAM,CAAC,cAAc,CACnB,cAAc,CAAC,EAAE,EACjB,UAAU,CAAC,EAAE,EACb,yDAAyD,CAC1D,CAAC;YAEF,kBAAkB;YAClB,MAAM,CAAC,cAAc,CACnB,cAAc,CAAC,WAAW,CAAC,IAAI,EAC/B,UAAU,CAAC,WAAW,CAAC,IAAI,EAC3B,2DAA2D,CAC5D,CAAC;YAEF,yDAAyD;YACzD,MAAM,CAAC,cAAc,CACnB,cAAc,CAAC,WAAW,CAAC,WAAW,EACtC,UAAU,CAAC,WAAW,CAAC,WAAW,EAClC,oEAAoE,CACrE,CAAC;YAEF,kDAAkD;YAClD,MAAM,CAAC,cAAc,CACnB,cAAc,CAAC,IAAI,EACnB,UAAU,CAAC,IAAI,EACf,kEAAkE,CACnE,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,KAAK,MAAM,UAAU,IAAI,kBAAkB,EAAE,CAAC;gBAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAC/C,MAAM,CAAC,EAAE,CACP,KAAK,EACL,mBAAmB,UAAU,6BAA6B,CAC3D,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,CAAC,EAAE,2BAA2B,CAAC,CAAC;gBAC/D,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;YACpF,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAEnC,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC;YACrD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YAEjE,yEAAyE;YACzE,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,iBAAiB,EAAE,aAAa,CAAC,CAAC;YACxE,KAAK,MAAM,UAAU,IAAI,eAAe,EAAE,CAAC;gBACzC,MAAM,CAAC,EAAE,CACP,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,EAC9B,+BAA+B,UAAU,IAAI;oBAC3C,sBAAsB,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,cAAc,CAAC,GAAa;IACnC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Agent Tools and Model Validation Tests
3
+ *
4
+ * Tests for agent tools array and model field parsing/validation.
5
+ * Run with: node --test dist/core/agents/tools.test.js
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.test.d.ts","sourceRoot":"","sources":["../../../src/core/agents/tools.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}