beth-copilot 1.0.15 → 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 (136) hide show
  1. package/README.md +197 -77
  2. package/bin/cli.js +47 -0
  3. package/dist/core/context.d.ts +171 -0
  4. package/dist/core/context.d.ts.map +1 -0
  5. package/dist/core/context.js +353 -0
  6. package/dist/core/context.js.map +1 -0
  7. package/dist/core/context.test.d.ts +8 -0
  8. package/dist/core/context.test.d.ts.map +1 -0
  9. package/dist/core/context.test.js +253 -0
  10. package/dist/core/context.test.js.map +1 -0
  11. package/dist/core/handoffs.d.ts +151 -0
  12. package/dist/core/handoffs.d.ts.map +1 -0
  13. package/dist/core/handoffs.js +220 -0
  14. package/dist/core/handoffs.js.map +1 -0
  15. package/dist/core/handoffs.test.d.ts +8 -0
  16. package/dist/core/handoffs.test.d.ts.map +1 -0
  17. package/dist/core/handoffs.test.js +231 -0
  18. package/dist/core/handoffs.test.js.map +1 -0
  19. package/dist/core/orchestrator.d.ts +246 -0
  20. package/dist/core/orchestrator.d.ts.map +1 -0
  21. package/dist/core/orchestrator.js +514 -0
  22. package/dist/core/orchestrator.js.map +1 -0
  23. package/dist/core/orchestrator.test.d.ts +8 -0
  24. package/dist/core/orchestrator.test.d.ts.map +1 -0
  25. package/dist/core/orchestrator.test.js +517 -0
  26. package/dist/core/orchestrator.test.js.map +1 -0
  27. package/dist/core/router.d.ts +102 -0
  28. package/dist/core/router.d.ts.map +1 -0
  29. package/dist/core/router.js +178 -0
  30. package/dist/core/router.js.map +1 -0
  31. package/dist/core/router.test.d.ts +8 -0
  32. package/dist/core/router.test.d.ts.map +1 -0
  33. package/dist/core/router.test.js +215 -0
  34. package/dist/core/router.test.js.map +1 -0
  35. package/dist/index.d.ts +9 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +7 -0
  38. package/dist/index.js.map +1 -1
  39. package/dist/tools/cli/beads.d.ts +27 -0
  40. package/dist/tools/cli/beads.d.ts.map +1 -0
  41. package/dist/tools/cli/beads.js +172 -0
  42. package/dist/tools/cli/beads.js.map +1 -0
  43. package/dist/tools/cli/beads.test.d.ts +8 -0
  44. package/dist/tools/cli/beads.test.d.ts.map +1 -0
  45. package/dist/tools/cli/beads.test.js +264 -0
  46. package/dist/tools/cli/beads.test.js.map +1 -0
  47. package/dist/tools/cli/editFile.d.ts +17 -0
  48. package/dist/tools/cli/editFile.d.ts.map +1 -0
  49. package/dist/tools/cli/editFile.js +125 -0
  50. package/dist/tools/cli/editFile.js.map +1 -0
  51. package/dist/tools/cli/editFile.test.d.ts +8 -0
  52. package/dist/tools/cli/editFile.test.d.ts.map +1 -0
  53. package/dist/tools/cli/editFile.test.js +177 -0
  54. package/dist/tools/cli/editFile.test.js.map +1 -0
  55. package/dist/tools/cli/readFile.d.ts +25 -0
  56. package/dist/tools/cli/readFile.d.ts.map +1 -0
  57. package/dist/tools/cli/readFile.js +118 -0
  58. package/dist/tools/cli/readFile.js.map +1 -0
  59. package/dist/tools/cli/readFile.test.d.ts +8 -0
  60. package/dist/tools/cli/readFile.test.d.ts.map +1 -0
  61. package/dist/tools/cli/readFile.test.js +194 -0
  62. package/dist/tools/cli/readFile.test.js.map +1 -0
  63. package/dist/tools/cli/search.d.ts +16 -0
  64. package/dist/tools/cli/search.d.ts.map +1 -0
  65. package/dist/tools/cli/search.js +261 -0
  66. package/dist/tools/cli/search.js.map +1 -0
  67. package/dist/tools/cli/search.test.d.ts +8 -0
  68. package/dist/tools/cli/search.test.d.ts.map +1 -0
  69. package/dist/tools/cli/search.test.js +172 -0
  70. package/dist/tools/cli/search.test.js.map +1 -0
  71. package/dist/tools/cli/subagent.d.ts +43 -0
  72. package/dist/tools/cli/subagent.d.ts.map +1 -0
  73. package/dist/tools/cli/subagent.js +99 -0
  74. package/dist/tools/cli/subagent.js.map +1 -0
  75. package/dist/tools/cli/subagent.test.d.ts +8 -0
  76. package/dist/tools/cli/subagent.test.d.ts.map +1 -0
  77. package/dist/tools/cli/subagent.test.js +190 -0
  78. package/dist/tools/cli/subagent.test.js.map +1 -0
  79. package/dist/tools/cli/terminal.d.ts +19 -0
  80. package/dist/tools/cli/terminal.d.ts.map +1 -0
  81. package/dist/tools/cli/terminal.js +164 -0
  82. package/dist/tools/cli/terminal.js.map +1 -0
  83. package/dist/tools/cli/terminal.test.d.ts +8 -0
  84. package/dist/tools/cli/terminal.test.d.ts.map +1 -0
  85. package/dist/tools/cli/terminal.test.js +161 -0
  86. package/dist/tools/cli/terminal.test.js.map +1 -0
  87. package/dist/tools/index.d.ts +25 -0
  88. package/dist/tools/index.d.ts.map +1 -0
  89. package/dist/tools/index.js +41 -0
  90. package/dist/tools/index.js.map +1 -0
  91. package/dist/tools/interface.d.ts +64 -0
  92. package/dist/tools/interface.d.ts.map +1 -0
  93. package/dist/tools/interface.js +37 -0
  94. package/dist/tools/interface.js.map +1 -0
  95. package/dist/tools/interface.test.d.ts +7 -0
  96. package/dist/tools/interface.test.d.ts.map +1 -0
  97. package/dist/tools/interface.test.js +179 -0
  98. package/dist/tools/interface.test.js.map +1 -0
  99. package/dist/tools/mcp/bridge.d.ts +48 -0
  100. package/dist/tools/mcp/bridge.d.ts.map +1 -0
  101. package/dist/tools/mcp/bridge.js +128 -0
  102. package/dist/tools/mcp/bridge.js.map +1 -0
  103. package/dist/tools/mcp/bridge.test.d.ts +8 -0
  104. package/dist/tools/mcp/bridge.test.d.ts.map +1 -0
  105. package/dist/tools/mcp/bridge.test.js +300 -0
  106. package/dist/tools/mcp/bridge.test.js.map +1 -0
  107. package/dist/tools/mcp/client.d.ts +135 -0
  108. package/dist/tools/mcp/client.d.ts.map +1 -0
  109. package/dist/tools/mcp/client.js +263 -0
  110. package/dist/tools/mcp/client.js.map +1 -0
  111. package/dist/tools/mcp/client.test.d.ts +8 -0
  112. package/dist/tools/mcp/client.test.d.ts.map +1 -0
  113. package/dist/tools/mcp/client.test.js +390 -0
  114. package/dist/tools/mcp/client.test.js.map +1 -0
  115. package/dist/tools/registry.d.ts +82 -0
  116. package/dist/tools/registry.d.ts.map +1 -0
  117. package/dist/tools/registry.js +99 -0
  118. package/dist/tools/registry.js.map +1 -0
  119. package/dist/tools/registry.test.d.ts +7 -0
  120. package/dist/tools/registry.test.d.ts.map +1 -0
  121. package/dist/tools/registry.test.js +199 -0
  122. package/dist/tools/registry.test.js.map +1 -0
  123. package/dist/tools/suite.test.d.ts +11 -0
  124. package/dist/tools/suite.test.d.ts.map +1 -0
  125. package/dist/tools/suite.test.js +119 -0
  126. package/dist/tools/suite.test.js.map +1 -0
  127. package/dist/tools/types.d.ts +75 -0
  128. package/dist/tools/types.d.ts.map +1 -0
  129. package/dist/tools/types.js +30 -0
  130. package/dist/tools/types.js.map +1 -0
  131. package/dist/tools/types.test.d.ts +7 -0
  132. package/dist/tools/types.test.d.ts.map +1 -0
  133. package/dist/tools/types.test.js +178 -0
  134. package/dist/tools/types.test.js.map +1 -0
  135. package/package.json +2 -2
  136. package/sbom.json +209 -209
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Agent Router
3
+ *
4
+ * Routes user requests to the appropriate agent based on:
5
+ * 1. Explicit @agent mentions in user input
6
+ * 2. Active handoff targets from the current agent
7
+ * 3. Skill trigger matching
8
+ * 4. Default to the orchestrator (Beth)
9
+ *
10
+ * Also provides agent lookup utilities for the orchestrator.
11
+ */
12
+ import { findMatchingSkills, buildTriggerMap } from './skills/loader.js';
13
+ // =============================================================================
14
+ // AgentRouter
15
+ // =============================================================================
16
+ /**
17
+ * Routes requests to the appropriate agent.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const router = new AgentRouter(agentLoadResult, skillLoadResult, 'beth');
22
+ *
23
+ * const result = router.route('@developer implement login page');
24
+ * // result.agent.id === 'developer'
25
+ * // result.reason === 'mention'
26
+ * // result.cleanedPrompt === 'implement login page'
27
+ *
28
+ * const result2 = router.route('create a prd for auth');
29
+ * // result2.matchedSkills contains the PRD skill
30
+ * ```
31
+ */
32
+ export class AgentRouter {
33
+ /** Map of agent ID → agent definition */
34
+ agents;
35
+ /** Map of agent name (lowercase) → agent ID for lookup */
36
+ nameToId;
37
+ /** Skill trigger map for matching */
38
+ triggerMap;
39
+ /** Default agent ID (typically 'beth') */
40
+ defaultAgentId;
41
+ constructor(agentResult, skillResult, defaultAgentId = 'beth') {
42
+ this.agents = new Map();
43
+ this.nameToId = new Map();
44
+ this.defaultAgentId = defaultAgentId;
45
+ for (const agent of agentResult.agents) {
46
+ this.agents.set(agent.id, agent);
47
+ // Map both ID and name for flexible lookup
48
+ this.nameToId.set(agent.id.toLowerCase(), agent.id);
49
+ if (agent.frontmatter.name) {
50
+ this.nameToId.set(agent.frontmatter.name.toLowerCase(), agent.id);
51
+ }
52
+ }
53
+ this.triggerMap = buildTriggerMap(skillResult);
54
+ }
55
+ // ===========================================================================
56
+ // Routing
57
+ // ===========================================================================
58
+ /**
59
+ * Route a user message to the appropriate agent.
60
+ *
61
+ * @param userMessage - The user's input text
62
+ * @param currentAgentId - The currently active agent (for handoff context)
63
+ * @returns Routing result with selected agent and matched skills
64
+ */
65
+ route(userMessage, currentAgentId) {
66
+ // 1. Check for explicit @mention
67
+ const mentionResult = this.checkMention(userMessage);
68
+ if (mentionResult) {
69
+ return {
70
+ ...mentionResult,
71
+ matchedSkills: this.findSkills(mentionResult.cleanedPrompt ?? userMessage),
72
+ };
73
+ }
74
+ // 2. Find matching skills
75
+ const matchedSkills = this.findSkills(userMessage);
76
+ // 3. Use current agent if one is active (stay in context)
77
+ if (currentAgentId) {
78
+ const currentAgent = this.agents.get(currentAgentId);
79
+ if (currentAgent) {
80
+ return {
81
+ agent: currentAgent,
82
+ reason: 'default',
83
+ matchedSkills,
84
+ };
85
+ }
86
+ }
87
+ // 4. Default to orchestrator
88
+ const defaultAgent = this.getDefaultAgent();
89
+ return {
90
+ agent: defaultAgent,
91
+ reason: 'default',
92
+ matchedSkills,
93
+ };
94
+ }
95
+ /**
96
+ * Route directly to a specific agent by ID or name.
97
+ *
98
+ * @param agentIdOrName - Agent ID or display name
99
+ * @returns The agent definition, or undefined if not found
100
+ */
101
+ resolveAgent(agentIdOrName) {
102
+ // Try direct ID lookup first
103
+ const direct = this.agents.get(agentIdOrName);
104
+ if (direct)
105
+ return direct;
106
+ // Try name-based lookup (case-insensitive)
107
+ const id = this.nameToId.get(agentIdOrName.toLowerCase());
108
+ if (id)
109
+ return this.agents.get(id);
110
+ return undefined;
111
+ }
112
+ /**
113
+ * Get all registered agents.
114
+ */
115
+ getAgents() {
116
+ return [...this.agents.values()];
117
+ }
118
+ /**
119
+ * Get agents that can be invoked as subagents (infer: true).
120
+ */
121
+ getInferableAgents() {
122
+ return [...this.agents.values()].filter((a) => a.frontmatter.infer === true);
123
+ }
124
+ /**
125
+ * Get the default orchestrator agent.
126
+ */
127
+ getDefaultAgent() {
128
+ const agent = this.agents.get(this.defaultAgentId);
129
+ if (!agent) {
130
+ // Fallback: return the first agent
131
+ const first = this.agents.values().next().value;
132
+ if (!first) {
133
+ throw new Error('No agents loaded — cannot route requests');
134
+ }
135
+ return first;
136
+ }
137
+ return agent;
138
+ }
139
+ /**
140
+ * Check if a specific agent is registered.
141
+ */
142
+ hasAgent(agentIdOrName) {
143
+ return this.resolveAgent(agentIdOrName) !== undefined;
144
+ }
145
+ // ===========================================================================
146
+ // Internal Routing Logic
147
+ // ===========================================================================
148
+ /**
149
+ * Check for @agent mention in user input.
150
+ *
151
+ * Matches patterns like:
152
+ * - "@developer implement the login page"
153
+ * - "@product-manager create a PRD"
154
+ * - "@Beth plan a feature"
155
+ */
156
+ checkMention(userMessage) {
157
+ const mentionMatch = userMessage.match(/^@(\S+)\s*(.*)/s);
158
+ if (!mentionMatch)
159
+ return null;
160
+ const mentionName = mentionMatch[1];
161
+ const restOfMessage = mentionMatch[2].trim();
162
+ const agent = this.resolveAgent(mentionName);
163
+ if (!agent)
164
+ return null;
165
+ return {
166
+ agent,
167
+ reason: 'mention',
168
+ cleanedPrompt: restOfMessage || userMessage,
169
+ };
170
+ }
171
+ /**
172
+ * Find skills whose triggers match the user message.
173
+ */
174
+ findSkills(userMessage) {
175
+ return findMatchingSkills(userMessage, this.triggerMap);
176
+ }
177
+ }
178
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/core/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * AgentRouter Tests
3
+ *
4
+ * Tests for agent routing: @mention parsing, skill trigger matching,
5
+ * agent resolution, and default routing behavior.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=router.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.test.d.ts","sourceRoot":"","sources":["../../src/core/router.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,215 @@
1
+ /**
2
+ * AgentRouter Tests
3
+ *
4
+ * Tests for agent routing: @mention parsing, skill trigger matching,
5
+ * agent resolution, and default routing behavior.
6
+ */
7
+ import { describe, it } from 'node:test';
8
+ import assert from 'node:assert';
9
+ import { AgentRouter } from './router.js';
10
+ // =============================================================================
11
+ // Test Fixtures
12
+ // =============================================================================
13
+ function createAgent(id, name, infer) {
14
+ return {
15
+ id,
16
+ frontmatter: {
17
+ name,
18
+ description: `${name} agent`,
19
+ tools: ['readFile'],
20
+ infer,
21
+ handoffs: [
22
+ { label: 'Test Handoff', agent: 'tester', prompt: 'Test this' },
23
+ ],
24
+ },
25
+ body: `# ${name}`,
26
+ sourcePath: `/agents/${id}.agent.md`,
27
+ };
28
+ }
29
+ function createSkill(id, name, triggers) {
30
+ return {
31
+ id,
32
+ frontmatter: { name, description: `Triggers on: ${triggers.join(', ')}` },
33
+ body: `Skill content for ${name}`,
34
+ sourcePath: `/skills/${id}/SKILL.md`,
35
+ triggers,
36
+ };
37
+ }
38
+ function createTestRouter(agents, skills, defaultId) {
39
+ const agentResult = {
40
+ agents: agents ?? [
41
+ createAgent('beth', 'Beth', true),
42
+ createAgent('developer', 'developer', true),
43
+ createAgent('tester', 'tester', true),
44
+ createAgent('product-manager', 'product-manager', true),
45
+ createAgent('ux-designer', 'ux-designer', true),
46
+ ],
47
+ errors: [],
48
+ };
49
+ const skillResult = {
50
+ skills: skills ?? [
51
+ createSkill('prd', 'PRD Generation', ['create a prd', 'product requirements']),
52
+ createSkill('shadcn-ui', 'shadcn/ui', ['shadcn', 'ui component']),
53
+ ],
54
+ errors: [],
55
+ };
56
+ return new AgentRouter(agentResult, skillResult, defaultId ?? 'beth');
57
+ }
58
+ // =============================================================================
59
+ // Tests
60
+ // =============================================================================
61
+ describe('AgentRouter', () => {
62
+ describe('Construction', () => {
63
+ it('should create with agents and skills', () => {
64
+ const router = createTestRouter();
65
+ assert.ok(router.hasAgent('beth'));
66
+ assert.ok(router.hasAgent('developer'));
67
+ assert.strictEqual(router.getAgents().length, 5);
68
+ });
69
+ it('should handle empty agents', () => {
70
+ assert.throws(() => {
71
+ const router = createTestRouter([]);
72
+ router.route('hello');
73
+ }, /No agents loaded/);
74
+ });
75
+ });
76
+ describe('Route by @mention', () => {
77
+ it('should route @developer to developer agent', () => {
78
+ const router = createTestRouter();
79
+ const result = router.route('@developer implement login');
80
+ assert.strictEqual(result.agent.id, 'developer');
81
+ assert.strictEqual(result.reason, 'mention');
82
+ assert.strictEqual(result.cleanedPrompt, 'implement login');
83
+ });
84
+ it('should route @Beth to Beth agent (case-insensitive name)', () => {
85
+ const router = createTestRouter();
86
+ const result = router.route('@Beth plan a feature');
87
+ assert.strictEqual(result.agent.id, 'beth');
88
+ assert.strictEqual(result.reason, 'mention');
89
+ assert.strictEqual(result.cleanedPrompt, 'plan a feature');
90
+ });
91
+ it('should route @product-manager correctly', () => {
92
+ const router = createTestRouter();
93
+ const result = router.route('@product-manager create a PRD');
94
+ assert.strictEqual(result.agent.id, 'product-manager');
95
+ assert.strictEqual(result.reason, 'mention');
96
+ });
97
+ it('should fall through to default for unknown @mention', () => {
98
+ const router = createTestRouter();
99
+ const result = router.route('@unknown-agent do something');
100
+ // Unknown mention falls through to default behavior
101
+ assert.strictEqual(result.reason, 'default');
102
+ });
103
+ it('should handle @mention with no trailing text', () => {
104
+ const router = createTestRouter();
105
+ const result = router.route('@developer');
106
+ // '@developer' without trailing text — the match won't capture the second group
107
+ // This should fall through since the regex requires whitespace after the mention
108
+ assert.ok(result.agent !== undefined);
109
+ });
110
+ });
111
+ describe('Route with skill matching', () => {
112
+ it('should find matching skills in user message', () => {
113
+ const router = createTestRouter();
114
+ const result = router.route('create a prd for authentication');
115
+ assert.ok(result.matchedSkills.length > 0);
116
+ assert.strictEqual(result.matchedSkills[0].id, 'prd');
117
+ });
118
+ it('should find shadcn skills', () => {
119
+ const router = createTestRouter();
120
+ const result = router.route('add a shadcn button component');
121
+ assert.ok(result.matchedSkills.length > 0);
122
+ assert.strictEqual(result.matchedSkills[0].id, 'shadcn-ui');
123
+ });
124
+ it('should return empty skills when no triggers match', () => {
125
+ const router = createTestRouter();
126
+ const result = router.route('hello world');
127
+ assert.strictEqual(result.matchedSkills.length, 0);
128
+ });
129
+ it('should combine @mention routing with skill matching', () => {
130
+ const router = createTestRouter();
131
+ const result = router.route('@developer create a shadcn button');
132
+ assert.strictEqual(result.agent.id, 'developer');
133
+ assert.strictEqual(result.reason, 'mention');
134
+ assert.ok(result.matchedSkills.length > 0);
135
+ });
136
+ });
137
+ describe('Default routing', () => {
138
+ it('should default to Beth when no mention or current agent', () => {
139
+ const router = createTestRouter();
140
+ const result = router.route('do something');
141
+ assert.strictEqual(result.agent.id, 'beth');
142
+ assert.strictEqual(result.reason, 'default');
143
+ });
144
+ it('should stay with current agent when one is active', () => {
145
+ const router = createTestRouter();
146
+ const result = router.route('do something else', 'developer');
147
+ assert.strictEqual(result.agent.id, 'developer');
148
+ assert.strictEqual(result.reason, 'default');
149
+ });
150
+ it('@mention should override current agent', () => {
151
+ const router = createTestRouter();
152
+ const result = router.route('@tester test this', 'developer');
153
+ assert.strictEqual(result.agent.id, 'tester');
154
+ assert.strictEqual(result.reason, 'mention');
155
+ });
156
+ });
157
+ describe('Agent resolution', () => {
158
+ it('should resolve by ID', () => {
159
+ const router = createTestRouter();
160
+ const agent = router.resolveAgent('developer');
161
+ assert.strictEqual(agent?.id, 'developer');
162
+ });
163
+ it('should resolve by name (case-insensitive)', () => {
164
+ const router = createTestRouter();
165
+ const agent = router.resolveAgent('Beth');
166
+ assert.strictEqual(agent?.id, 'beth');
167
+ });
168
+ it('should return undefined for unknown agent', () => {
169
+ const router = createTestRouter();
170
+ const agent = router.resolveAgent('nonexistent');
171
+ assert.strictEqual(agent, undefined);
172
+ });
173
+ it('should check agent existence', () => {
174
+ const router = createTestRouter();
175
+ assert.strictEqual(router.hasAgent('developer'), true);
176
+ assert.strictEqual(router.hasAgent('nonexistent'), false);
177
+ });
178
+ });
179
+ describe('Inferable agents', () => {
180
+ it('should return agents with infer: true', () => {
181
+ const router = createTestRouter();
182
+ const inferable = router.getInferableAgents();
183
+ assert.ok(inferable.length > 0);
184
+ for (const agent of inferable) {
185
+ assert.strictEqual(agent.frontmatter.infer, true);
186
+ }
187
+ });
188
+ it('should not include non-inferable agents', () => {
189
+ const agents = [
190
+ createAgent('beth', 'Beth', true),
191
+ createAgent('helper', 'Helper', false),
192
+ createAgent('developer', 'developer', true),
193
+ ];
194
+ const router = createTestRouter(agents);
195
+ const inferable = router.getInferableAgents();
196
+ assert.strictEqual(inferable.length, 2);
197
+ const ids = inferable.map((a) => a.id);
198
+ assert.ok(!ids.includes('helper'));
199
+ });
200
+ });
201
+ describe('Default agent', () => {
202
+ it('should return the configured default agent', () => {
203
+ const router = createTestRouter(undefined, undefined, 'beth');
204
+ const agent = router.getDefaultAgent();
205
+ assert.strictEqual(agent.id, 'beth');
206
+ });
207
+ it('should fallback to first agent if default not found', () => {
208
+ const agents = [createAgent('dev', 'Developer')];
209
+ const router = createTestRouter(agents, [], 'nonexistent');
210
+ const agent = router.getDefaultAgent();
211
+ assert.strictEqual(agent.id, 'dev');
212
+ });
213
+ });
214
+ });
215
+ //# sourceMappingURL=router.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.test.js","sourceRoot":"","sources":["../../src/core/router.test.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,6 +5,15 @@
5
5
  */
6
6
  export * from './core/agents/index.js';
7
7
  export * from './core/skills/index.js';
8
+ export { Orchestrator } from './core/orchestrator.js';
9
+ export type { OrchestratorConfig, TurnResult, ToolCallRecord, SubagentResult, OrchestratorObserver, } from './core/orchestrator.js';
10
+ export { ConversationContext } from './core/context.js';
11
+ export type { ConversationContextOptions, ConversationSummary, } from './core/context.js';
12
+ export { AgentRouter } from './core/router.js';
13
+ export type { RouteResult, RouteReason } from './core/router.js';
14
+ export { HandoffManager } from './core/handoffs.js';
15
+ export type { HandoffRequest, HandoffResult, HandoffRecord, HandoffMode, } from './core/handoffs.js';
8
16
  export * from './lib/index.js';
9
17
  export * from './cli/commands/index.js';
18
+ export * from './tools/index.js';
10
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,wBAAwB,CAAC;AAGvC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,wBAAwB,CAAC;AAGvC,cAAc,wBAAwB,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EACV,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EACV,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAG5B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,yBAAyB,CAAC;AAGxC,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -7,8 +7,15 @@
7
7
  export * from './core/agents/index.js';
8
8
  // Core exports - Skills
9
9
  export * from './core/skills/index.js';
10
+ // Core exports - Orchestration
11
+ export { Orchestrator } from './core/orchestrator.js';
12
+ export { ConversationContext } from './core/context.js';
13
+ export { AgentRouter } from './core/router.js';
14
+ export { HandoffManager } from './core/handoffs.js';
10
15
  // Library utilities
11
16
  export * from './lib/index.js';
12
17
  // CLI commands
13
18
  export * from './cli/commands/index.js';
19
+ // Tool abstraction layer
20
+ export * from './tools/index.js';
14
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAwB;AACxB,cAAc,wBAAwB,CAAC;AAEvC,wBAAwB;AACxB,cAAc,wBAAwB,CAAC;AAEvC,oBAAoB;AACpB,cAAc,gBAAgB,CAAC;AAE/B,eAAe;AACf,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAwB;AACxB,cAAc,wBAAwB,CAAC;AAEvC,wBAAwB;AACxB,cAAc,wBAAwB,CAAC;AAEvC,+BAA+B;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAQtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAKxD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQpD,oBAAoB;AACpB,cAAc,gBAAgB,CAAC;AAE/B,eAAe;AACf,cAAc,yBAAyB,CAAC;AAExC,yBAAyB;AACzB,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Beads Tool
3
+ *
4
+ * Wraps the `bd` CLI for issue tracking via the beads system.
5
+ * Supports creating, closing, listing, and inspecting issues
6
+ * and their dependency trees.
7
+ *
8
+ * @see https://github.com/steveyegge/beads
9
+ */
10
+ import { execFile as nodeExecFile } from 'node:child_process';
11
+ import type { Tool } from '../interface.js';
12
+ /** Type for the execFile callback-style function, used for dependency injection in tests */
13
+ type ExecFileFn = typeof nodeExecFile;
14
+ /**
15
+ * Create a beads tool instance.
16
+ *
17
+ * Accepts an optional `execFn` for dependency injection in tests.
18
+ * When omitted, uses `node:child_process.execFile`.
19
+ *
20
+ * @param execFn - Optional execFile function for testing
21
+ * @returns A Tool implementation for beads
22
+ */
23
+ export declare function createBeadsTool(execFn?: ExecFileFn): Tool;
24
+ /** Default beads tool instance using real execFile */
25
+ export declare const beadsTool: Tool;
26
+ export {};
27
+ //# sourceMappingURL=beads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beads.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/beads.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,4FAA4F;AAC5F,KAAK,UAAU,GAAG,OAAO,YAAY,CAAC;AAsGtC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CA2EzD;AAED,sDAAsD;AACtD,eAAO,MAAM,SAAS,EAAE,IAAwB,CAAC"}