@defai.digital/agent-domain 13.0.3

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 (77) hide show
  1. package/LICENSE +214 -0
  2. package/dist/enhanced-executor.d.ts +170 -0
  3. package/dist/enhanced-executor.d.ts.map +1 -0
  4. package/dist/enhanced-executor.js +1072 -0
  5. package/dist/enhanced-executor.js.map +1 -0
  6. package/dist/executor.d.ts +120 -0
  7. package/dist/executor.d.ts.map +1 -0
  8. package/dist/executor.js +929 -0
  9. package/dist/executor.js.map +1 -0
  10. package/dist/index.d.ts +25 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +34 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/loader.d.ts +50 -0
  15. package/dist/loader.d.ts.map +1 -0
  16. package/dist/loader.js +160 -0
  17. package/dist/loader.js.map +1 -0
  18. package/dist/persistent-registry.d.ts +105 -0
  19. package/dist/persistent-registry.d.ts.map +1 -0
  20. package/dist/persistent-registry.js +183 -0
  21. package/dist/persistent-registry.js.map +1 -0
  22. package/dist/production-factories.d.ts +70 -0
  23. package/dist/production-factories.d.ts.map +1 -0
  24. package/dist/production-factories.js +434 -0
  25. package/dist/production-factories.js.map +1 -0
  26. package/dist/prompt-executor.d.ts +119 -0
  27. package/dist/prompt-executor.d.ts.map +1 -0
  28. package/dist/prompt-executor.js +211 -0
  29. package/dist/prompt-executor.js.map +1 -0
  30. package/dist/registry.d.ts +57 -0
  31. package/dist/registry.d.ts.map +1 -0
  32. package/dist/registry.js +123 -0
  33. package/dist/registry.js.map +1 -0
  34. package/dist/selection-service.d.ts +74 -0
  35. package/dist/selection-service.d.ts.map +1 -0
  36. package/dist/selection-service.js +322 -0
  37. package/dist/selection-service.js.map +1 -0
  38. package/dist/selector.d.ts +51 -0
  39. package/dist/selector.d.ts.map +1 -0
  40. package/dist/selector.js +249 -0
  41. package/dist/selector.js.map +1 -0
  42. package/dist/stub-checkpoint.d.ts +23 -0
  43. package/dist/stub-checkpoint.d.ts.map +1 -0
  44. package/dist/stub-checkpoint.js +137 -0
  45. package/dist/stub-checkpoint.js.map +1 -0
  46. package/dist/stub-delegation-tracker.d.ts +25 -0
  47. package/dist/stub-delegation-tracker.d.ts.map +1 -0
  48. package/dist/stub-delegation-tracker.js +118 -0
  49. package/dist/stub-delegation-tracker.js.map +1 -0
  50. package/dist/stub-parallel-executor.d.ts +19 -0
  51. package/dist/stub-parallel-executor.d.ts.map +1 -0
  52. package/dist/stub-parallel-executor.js +176 -0
  53. package/dist/stub-parallel-executor.js.map +1 -0
  54. package/dist/types.d.ts +614 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +15 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/workflow-templates.d.ts +117 -0
  59. package/dist/workflow-templates.d.ts.map +1 -0
  60. package/dist/workflow-templates.js +342 -0
  61. package/dist/workflow-templates.js.map +1 -0
  62. package/package.json +51 -0
  63. package/src/enhanced-executor.ts +1395 -0
  64. package/src/executor.ts +1153 -0
  65. package/src/index.ts +172 -0
  66. package/src/loader.ts +191 -0
  67. package/src/persistent-registry.ts +235 -0
  68. package/src/production-factories.ts +613 -0
  69. package/src/prompt-executor.ts +310 -0
  70. package/src/registry.ts +167 -0
  71. package/src/selection-service.ts +411 -0
  72. package/src/selector.ts +299 -0
  73. package/src/stub-checkpoint.ts +187 -0
  74. package/src/stub-delegation-tracker.ts +161 -0
  75. package/src/stub-parallel-executor.ts +224 -0
  76. package/src/types.ts +784 -0
  77. package/src/workflow-templates.ts +393 -0
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Agent Selection Service
3
+ *
4
+ * Domain service for agent recommendation and capability discovery.
5
+ * Implements contract-defined invariants for agent selection.
6
+ *
7
+ * Invariants:
8
+ * - INV-AGT-SEL-001: Selection is deterministic (same input = same output)
9
+ * - INV-AGT-SEL-002: Confidence scores must be between 0 and 1
10
+ * - INV-AGT-SEL-003: Results must be sorted by confidence descending
11
+ * - INV-AGT-SEL-004: Always returns at least one result (fallback to 'standard')
12
+ * - INV-AGT-SEL-005: exampleTasks boost confidence when matched
13
+ * - INV-AGT-SEL-006: notForTasks reduce confidence when matched
14
+ */
15
+ // ============================================================================
16
+ // Constants
17
+ // ============================================================================
18
+ /**
19
+ * Default agent ID when no match is found (INV-AGT-SEL-004)
20
+ */
21
+ const FALLBACK_AGENT_ID = 'standard';
22
+ /**
23
+ * Default confidence for fallback agent (INV-AGT-SEL-004)
24
+ */
25
+ const FALLBACK_CONFIDENCE = 0.5;
26
+ /**
27
+ * Minimum confidence threshold for selection
28
+ */
29
+ const MIN_CONFIDENCE_THRESHOLD = 0.1;
30
+ /**
31
+ * Scoring weights (INV-AGT-SEL-005, INV-AGT-SEL-006)
32
+ */
33
+ const SCORE_WEIGHTS = {
34
+ EXACT_EXAMPLE_MATCH: 0.6, // INV-AGT-SEL-005: Exact match adds +0.6
35
+ SUBSTRING_EXAMPLE_MATCH: 0.4, // INV-AGT-SEL-005: Substring match adds +0.4
36
+ NOT_FOR_TASK_PENALTY: -0.5, // INV-AGT-SEL-006: NotForTask subtracts -0.5
37
+ PRIMARY_INTENT: 0.3,
38
+ KEYWORD: 0.15,
39
+ ANTI_KEYWORD: -0.2,
40
+ NEGATIVE_INTENT: -0.3,
41
+ CAPABILITY: 0.1,
42
+ REQUIRED_CAPABILITY_FULL: 0.25,
43
+ EXPERTISE: 0.15,
44
+ ROLE: 0.1,
45
+ DESCRIPTION_WORD: 0.05,
46
+ TEAM: 0.1,
47
+ REDIRECT: -0.5,
48
+ };
49
+ // ============================================================================
50
+ // Agent Selection Service Implementation
51
+ // ============================================================================
52
+ /**
53
+ * Agent Selection Service
54
+ *
55
+ * Implements deterministic agent selection based on task matching.
56
+ */
57
+ export class AgentSelectionService {
58
+ registry;
59
+ constructor(registry) {
60
+ this.registry = registry;
61
+ }
62
+ /**
63
+ * Recommend the best agent for a task
64
+ *
65
+ * Implements:
66
+ * - INV-AGT-SEL-001: Deterministic selection
67
+ * - INV-AGT-SEL-002: Confidence range [0,1]
68
+ * - INV-AGT-SEL-003: Sorted by confidence descending
69
+ * - INV-AGT-SEL-004: Fallback to 'standard'
70
+ */
71
+ async recommend(request) {
72
+ // Get all enabled agents, optionally filtered by team
73
+ const filter = request.team !== undefined
74
+ ? { team: request.team, enabled: true }
75
+ : { enabled: true };
76
+ const agents = await this.registry.list(filter);
77
+ // Filter out excluded agents
78
+ const filteredAgents = request.excludeAgents
79
+ ? agents.filter((a) => !request.excludeAgents.includes(a.agentId))
80
+ : agents;
81
+ // Score each agent (INV-AGT-SEL-001: deterministic)
82
+ const scored = filteredAgents
83
+ .map((agent) => this.scoreAgent(agent, request.task, request.requiredCapabilities))
84
+ .filter((result) => result.confidence >= MIN_CONFIDENCE_THRESHOLD);
85
+ // INV-AGT-SEL-003: Sort by confidence descending, then by agentId for tie-breaking
86
+ scored.sort((a, b) => {
87
+ const confidenceDiff = b.confidence - a.confidence;
88
+ if (confidenceDiff !== 0)
89
+ return confidenceDiff;
90
+ return a.agentId.localeCompare(b.agentId); // Deterministic tie-breaking
91
+ });
92
+ // INV-AGT-SEL-004: Always return at least one result
93
+ if (scored.length === 0) {
94
+ return {
95
+ recommended: FALLBACK_AGENT_ID,
96
+ confidence: FALLBACK_CONFIDENCE,
97
+ reason: 'No specific agent matched, using default generalist agent',
98
+ alternatives: [],
99
+ };
100
+ }
101
+ // Get top N results based on maxResults
102
+ const topResults = scored.slice(0, request.maxResults);
103
+ const best = topResults[0];
104
+ return {
105
+ recommended: best.agentId,
106
+ confidence: best.confidence,
107
+ reason: best.reason,
108
+ alternatives: topResults.slice(1).map((s) => ({
109
+ agentId: s.agentId,
110
+ confidence: s.confidence,
111
+ reason: s.reason,
112
+ })),
113
+ };
114
+ }
115
+ /**
116
+ * Get all agent capabilities
117
+ */
118
+ async getCapabilities(request) {
119
+ // Get agents based on request filters
120
+ const filter = request.includeDisabled ? {} : { enabled: true };
121
+ let agents = await this.registry.list(filter);
122
+ // Filter by category if specified
123
+ if (request.category) {
124
+ agents = agents.filter((a) => a.selectionMetadata?.agentCategory === request.category);
125
+ }
126
+ // Build capability mappings
127
+ const allCapabilities = new Set();
128
+ const agentsByCapability = {};
129
+ const capabilitiesByAgent = {};
130
+ const categoriesByAgent = {};
131
+ for (const agent of agents) {
132
+ const caps = agent.capabilities ?? [];
133
+ capabilitiesByAgent[agent.agentId] = caps;
134
+ // Track category
135
+ if (agent.selectionMetadata?.agentCategory) {
136
+ categoriesByAgent[agent.agentId] = agent.selectionMetadata.agentCategory;
137
+ }
138
+ // Build reverse mapping
139
+ for (const cap of caps) {
140
+ allCapabilities.add(cap);
141
+ if (!agentsByCapability[cap]) {
142
+ agentsByCapability[cap] = [];
143
+ }
144
+ agentsByCapability[cap].push(agent.agentId);
145
+ }
146
+ }
147
+ return {
148
+ capabilities: Array.from(allCapabilities).sort(),
149
+ agentsByCapability,
150
+ capabilitiesByAgent,
151
+ categoriesByAgent: Object.keys(categoriesByAgent).length > 0 ? categoriesByAgent : undefined,
152
+ };
153
+ }
154
+ /**
155
+ * Score an agent for a task
156
+ *
157
+ * Implements:
158
+ * - INV-AGT-SEL-002: Confidence clamped to [0,1]
159
+ * - INV-AGT-SEL-005: exampleTasks boost
160
+ * - INV-AGT-SEL-006: notForTasks penalty
161
+ */
162
+ scoreAgent(agent, task, requiredCapabilities) {
163
+ const taskLower = task.toLowerCase();
164
+ const taskNormalized = this.normalizeText(taskLower);
165
+ const taskWords = this.extractWords(taskLower);
166
+ let score = 0;
167
+ const matchDetails = [];
168
+ // INV-AGT-SEL-005: Score based on exampleTasks (highest priority)
169
+ const exampleTasks = agent.selectionMetadata?.exampleTasks ?? [];
170
+ for (const example of exampleTasks) {
171
+ const exampleNormalized = this.normalizeText(example.toLowerCase());
172
+ if (taskNormalized === exampleNormalized) {
173
+ score += SCORE_WEIGHTS.EXACT_EXAMPLE_MATCH;
174
+ matchDetails.push(`exact example match: "${example}"`);
175
+ break;
176
+ }
177
+ else if (taskLower.includes(example.toLowerCase()) ||
178
+ example.toLowerCase().includes(taskLower)) {
179
+ score += SCORE_WEIGHTS.SUBSTRING_EXAMPLE_MATCH;
180
+ matchDetails.push(`example match: "${example}"`);
181
+ break;
182
+ }
183
+ }
184
+ // INV-AGT-SEL-006: Negative score for notForTasks
185
+ const notForTasks = agent.selectionMetadata?.notForTasks ?? [];
186
+ for (const notFor of notForTasks) {
187
+ if (taskLower.includes(notFor.toLowerCase()) ||
188
+ notFor.toLowerCase().includes(taskLower)) {
189
+ score += SCORE_WEIGHTS.NOT_FOR_TASK_PENALTY;
190
+ matchDetails.push(`not-for match: "${notFor}"`);
191
+ break;
192
+ }
193
+ }
194
+ // Score based on primary intents
195
+ const primaryIntents = agent.selectionMetadata?.primaryIntents ?? [];
196
+ for (const intent of primaryIntents) {
197
+ if (taskLower.includes(intent.toLowerCase())) {
198
+ score += SCORE_WEIGHTS.PRIMARY_INTENT;
199
+ matchDetails.push(`primary intent: ${intent}`);
200
+ }
201
+ }
202
+ // Score based on keywords
203
+ const keywords = agent.selectionMetadata?.keywords ?? [];
204
+ for (const keyword of keywords) {
205
+ if (taskLower.includes(keyword.toLowerCase())) {
206
+ score += SCORE_WEIGHTS.KEYWORD;
207
+ matchDetails.push(`keyword: ${keyword}`);
208
+ }
209
+ }
210
+ // Negative score for anti-keywords
211
+ const antiKeywords = agent.selectionMetadata?.antiKeywords ?? [];
212
+ for (const antiKeyword of antiKeywords) {
213
+ if (taskLower.includes(antiKeyword.toLowerCase())) {
214
+ score += SCORE_WEIGHTS.ANTI_KEYWORD;
215
+ matchDetails.push(`anti-keyword: ${antiKeyword}`);
216
+ }
217
+ }
218
+ // Score based on negative intents
219
+ const negativeIntents = agent.selectionMetadata?.negativeIntents ?? [];
220
+ for (const intent of negativeIntents) {
221
+ if (taskLower.includes(intent.toLowerCase())) {
222
+ score += SCORE_WEIGHTS.NEGATIVE_INTENT;
223
+ matchDetails.push(`negative intent: ${intent}`);
224
+ }
225
+ }
226
+ // Score based on capabilities
227
+ const capabilities = agent.capabilities ?? [];
228
+ for (const cap of capabilities) {
229
+ if (taskWords.some((w) => cap.toLowerCase().includes(w))) {
230
+ score += SCORE_WEIGHTS.CAPABILITY;
231
+ matchDetails.push(`capability: ${cap}`);
232
+ }
233
+ }
234
+ // Score based on required capabilities
235
+ if (requiredCapabilities && requiredCapabilities.length > 0) {
236
+ const matches = requiredCapabilities.filter((req) => capabilities.some((cap) => cap.toLowerCase().includes(req.toLowerCase())));
237
+ if (matches.length === requiredCapabilities.length) {
238
+ score += SCORE_WEIGHTS.REQUIRED_CAPABILITY_FULL;
239
+ matchDetails.push('all required capabilities');
240
+ }
241
+ else if (matches.length > 0) {
242
+ const partial = SCORE_WEIGHTS.CAPABILITY * (matches.length / requiredCapabilities.length);
243
+ score += partial;
244
+ matchDetails.push(`${matches.length}/${requiredCapabilities.length} required capabilities`);
245
+ }
246
+ }
247
+ // Score based on expertise
248
+ const expertise = agent.expertise ?? [];
249
+ for (const exp of expertise) {
250
+ if (taskWords.some((w) => exp.toLowerCase().includes(w))) {
251
+ score += SCORE_WEIGHTS.EXPERTISE;
252
+ matchDetails.push(`expertise: ${exp}`);
253
+ }
254
+ }
255
+ // Score based on role match
256
+ if (agent.role) {
257
+ const roleWords = this.extractWords(agent.role.toLowerCase());
258
+ const roleMatches = roleWords.filter((r) => taskWords.includes(r));
259
+ if (roleMatches.length > 0) {
260
+ score += SCORE_WEIGHTS.ROLE;
261
+ matchDetails.push(`role: ${agent.role}`);
262
+ }
263
+ }
264
+ // Score based on description match
265
+ if (agent.description) {
266
+ const descWords = this.extractWords(agent.description.toLowerCase());
267
+ const descMatches = descWords.filter((d) => taskWords.includes(d)).length;
268
+ if (descMatches > 2) {
269
+ score += SCORE_WEIGHTS.DESCRIPTION_WORD * Math.min(descMatches, 5);
270
+ matchDetails.push(`description: ${descMatches} words`);
271
+ }
272
+ }
273
+ // Check redirect rules (suggests this agent is NOT right)
274
+ const redirectRules = agent.selectionMetadata?.redirectWhen ?? [];
275
+ for (const rule of redirectRules) {
276
+ if (taskLower.includes(rule.phrase.toLowerCase())) {
277
+ score += SCORE_WEIGHTS.REDIRECT;
278
+ matchDetails.push(`redirect to: ${rule.suggest}`);
279
+ }
280
+ }
281
+ // INV-AGT-SEL-002: Clamp confidence to [0,1]
282
+ const confidence = Math.max(0, Math.min(1, score));
283
+ // Build reason from match details
284
+ const reason = matchDetails.length > 0
285
+ ? matchDetails.slice(0, 3).join('; ')
286
+ : 'no specific match';
287
+ return {
288
+ agentId: agent.agentId,
289
+ confidence,
290
+ reason,
291
+ matchDetails,
292
+ };
293
+ }
294
+ /**
295
+ * Normalize text for comparison
296
+ */
297
+ normalizeText(text) {
298
+ return text
299
+ .replace(/[^\w\s]/g, ' ')
300
+ .replace(/\s+/g, ' ')
301
+ .trim();
302
+ }
303
+ /**
304
+ * Extract meaningful words from text
305
+ */
306
+ extractWords(text) {
307
+ return text
308
+ .split(/[\s\-_,./]+/)
309
+ .filter((w) => w.length > 2)
310
+ .map((w) => w.toLowerCase());
311
+ }
312
+ }
313
+ // ============================================================================
314
+ // Factory Function
315
+ // ============================================================================
316
+ /**
317
+ * Creates an agent selection service
318
+ */
319
+ export function createAgentSelectionService(registry) {
320
+ return new AgentSelectionService(registry);
321
+ }
322
+ //# sourceMappingURL=selection-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection-service.js","sourceRoot":"","sources":["../src/selection-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Agent Selector
3
+ *
4
+ * Selects the best agent for a given task based on keywords,
5
+ * capabilities, context, and example tasks.
6
+ *
7
+ * Invariants:
8
+ * - INV-AGT-SEL-001: Selection is deterministic (same input = same output)
9
+ * - INV-AGT-SEL-002: Confidence scores must be between 0 and 1
10
+ * - INV-AGT-SEL-003: Results must be sorted by confidence descending
11
+ * - INV-AGT-SEL-004: Always returns at least one result (fallback to 'standard')
12
+ * - INV-AGT-SEL-005: exampleTasks boost confidence when matched
13
+ * - INV-AGT-SEL-006: notForTasks reduce confidence when matched
14
+ */
15
+ import type { AgentRegistry, AgentSelector, AgentSelectionResult, AgentSelectionContext } from './types.js';
16
+ /**
17
+ * Keyword-based agent selector implementation
18
+ */
19
+ export declare class KeywordAgentSelector implements AgentSelector {
20
+ private readonly registry;
21
+ constructor(registry: AgentRegistry);
22
+ /**
23
+ * Select the best agent for a task
24
+ */
25
+ select(task: string, context?: AgentSelectionContext): Promise<AgentSelectionResult>;
26
+ /**
27
+ * Get all agents that match a task
28
+ */
29
+ match(task: string, context?: AgentSelectionContext): Promise<AgentSelectionResult[]>;
30
+ /**
31
+ * Score an agent for a task
32
+ *
33
+ * Implements invariants:
34
+ * - INV-AGT-SEL-005: exampleTasks boost confidence when matched
35
+ * - INV-AGT-SEL-006: notForTasks reduce confidence when matched
36
+ */
37
+ private scoreAgent;
38
+ /**
39
+ * Normalize text for comparison (remove punctuation, extra spaces)
40
+ */
41
+ private normalizeText;
42
+ /**
43
+ * Extract words from text
44
+ */
45
+ private extractWords;
46
+ }
47
+ /**
48
+ * Creates a keyword-based agent selector
49
+ */
50
+ export declare function createAgentSelector(registry: AgentRegistry): AgentSelector;
51
+ //# sourceMappingURL=selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../src/selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAoBpB;;GAEG;AACH,qBAAa,oBAAqB,YAAW,aAAa;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,aAAa;IAEpD;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC;IAuBhC;;OAEG;IACG,KAAK,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAsBlC;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IA6JlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAE1E"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Agent Selector
3
+ *
4
+ * Selects the best agent for a given task based on keywords,
5
+ * capabilities, context, and example tasks.
6
+ *
7
+ * Invariants:
8
+ * - INV-AGT-SEL-001: Selection is deterministic (same input = same output)
9
+ * - INV-AGT-SEL-002: Confidence scores must be between 0 and 1
10
+ * - INV-AGT-SEL-003: Results must be sorted by confidence descending
11
+ * - INV-AGT-SEL-004: Always returns at least one result (fallback to 'standard')
12
+ * - INV-AGT-SEL-005: exampleTasks boost confidence when matched
13
+ * - INV-AGT-SEL-006: notForTasks reduce confidence when matched
14
+ */
15
+ // ============================================================================
16
+ // Constants
17
+ // ============================================================================
18
+ /**
19
+ * Default agent ID when no match is found
20
+ */
21
+ const DEFAULT_AGENT_ID = 'standard';
22
+ /**
23
+ * Minimum confidence threshold for selection
24
+ */
25
+ const MIN_CONFIDENCE_THRESHOLD = 0.1;
26
+ // ============================================================================
27
+ // Keyword-Based Agent Selector
28
+ // ============================================================================
29
+ /**
30
+ * Keyword-based agent selector implementation
31
+ */
32
+ export class KeywordAgentSelector {
33
+ registry;
34
+ constructor(registry) {
35
+ this.registry = registry;
36
+ }
37
+ /**
38
+ * Select the best agent for a task
39
+ */
40
+ async select(task, context) {
41
+ const matches = await this.match(task, context);
42
+ if (matches.length === 0) {
43
+ // Return default agent
44
+ return {
45
+ agentId: DEFAULT_AGENT_ID,
46
+ confidence: 0.5,
47
+ reason: 'No specific agent matched, using default',
48
+ alternatives: [],
49
+ };
50
+ }
51
+ const best = matches[0];
52
+ return {
53
+ ...best,
54
+ alternatives: matches.slice(1).map((m) => ({
55
+ agentId: m.agentId,
56
+ confidence: m.confidence,
57
+ })),
58
+ };
59
+ }
60
+ /**
61
+ * Get all agents that match a task
62
+ */
63
+ async match(task, context) {
64
+ const filter = context?.team !== undefined
65
+ ? { team: context.team, enabled: true }
66
+ : { enabled: true };
67
+ const agents = await this.registry.list(filter);
68
+ // Filter by excluded agents
69
+ const filtered = context?.excludeAgents
70
+ ? agents.filter((a) => !context.excludeAgents.includes(a.agentId))
71
+ : agents;
72
+ // Score each agent
73
+ const scored = filtered
74
+ .map((agent) => this.scoreAgent(agent, task, context))
75
+ .filter((result) => result.confidence >= MIN_CONFIDENCE_THRESHOLD);
76
+ // INV-AGT-SEL-003: Sort by confidence descending
77
+ scored.sort((a, b) => b.confidence - a.confidence);
78
+ return scored;
79
+ }
80
+ /**
81
+ * Score an agent for a task
82
+ *
83
+ * Implements invariants:
84
+ * - INV-AGT-SEL-005: exampleTasks boost confidence when matched
85
+ * - INV-AGT-SEL-006: notForTasks reduce confidence when matched
86
+ */
87
+ scoreAgent(agent, task, context) {
88
+ const taskLower = task.toLowerCase();
89
+ const taskNormalized = this.normalizeText(taskLower);
90
+ const taskWords = this.extractWords(taskLower);
91
+ let score = 0;
92
+ const reasons = [];
93
+ // INV-AGT-SEL-005: Score based on exampleTasks (highest priority)
94
+ const exampleTasks = agent.selectionMetadata?.exampleTasks ?? [];
95
+ for (const example of exampleTasks) {
96
+ const exampleNormalized = this.normalizeText(example.toLowerCase());
97
+ if (taskNormalized === exampleNormalized) {
98
+ // Exact match (normalized) adds +0.6
99
+ score += 0.6;
100
+ reasons.push(`exact example match: "${example}"`);
101
+ break; // Only count best match
102
+ }
103
+ else if (taskLower.includes(example.toLowerCase()) || example.toLowerCase().includes(taskLower)) {
104
+ // Substring match adds +0.4
105
+ score += 0.4;
106
+ reasons.push(`example match: "${example}"`);
107
+ break; // Only count best match
108
+ }
109
+ }
110
+ // INV-AGT-SEL-006: Negative score for notForTasks
111
+ const notForTasks = agent.selectionMetadata?.notForTasks ?? [];
112
+ for (const notFor of notForTasks) {
113
+ if (taskLower.includes(notFor.toLowerCase()) || notFor.toLowerCase().includes(taskLower)) {
114
+ // NotForTask match subtracts -0.5
115
+ score -= 0.5;
116
+ reasons.push(`not-for match: "${notFor}"`);
117
+ break; // Only count first match
118
+ }
119
+ }
120
+ // Score based on primary intents
121
+ const primaryIntents = agent.selectionMetadata?.primaryIntents ?? [];
122
+ for (const intent of primaryIntents) {
123
+ if (taskLower.includes(intent.toLowerCase())) {
124
+ score += 0.3;
125
+ reasons.push(`primary intent match: ${intent}`);
126
+ }
127
+ }
128
+ // Score based on keywords
129
+ const keywords = agent.selectionMetadata?.keywords ?? [];
130
+ for (const keyword of keywords) {
131
+ if (taskLower.includes(keyword.toLowerCase())) {
132
+ score += 0.15;
133
+ reasons.push(`keyword match: ${keyword}`);
134
+ }
135
+ }
136
+ // Negative score for anti-keywords
137
+ const antiKeywords = agent.selectionMetadata?.antiKeywords ?? [];
138
+ for (const antiKeyword of antiKeywords) {
139
+ if (taskLower.includes(antiKeyword.toLowerCase())) {
140
+ score -= 0.2;
141
+ reasons.push(`anti-keyword match: ${antiKeyword}`);
142
+ }
143
+ }
144
+ // Score based on negative intents
145
+ const negativeIntents = agent.selectionMetadata?.negativeIntents ?? [];
146
+ for (const intent of negativeIntents) {
147
+ if (taskLower.includes(intent.toLowerCase())) {
148
+ score -= 0.3;
149
+ reasons.push(`negative intent match: ${intent}`);
150
+ }
151
+ }
152
+ // Score based on capabilities
153
+ const capabilities = agent.capabilities ?? [];
154
+ for (const cap of capabilities) {
155
+ if (taskWords.some((w) => cap.toLowerCase().includes(w))) {
156
+ score += 0.1;
157
+ reasons.push(`capability match: ${cap}`);
158
+ }
159
+ }
160
+ // Score based on required capabilities in context
161
+ if (context?.requiredCapabilities) {
162
+ const matches = context.requiredCapabilities.filter((req) => capabilities.some((cap) => cap.toLowerCase().includes(req.toLowerCase())));
163
+ if (matches.length === context.requiredCapabilities.length) {
164
+ score += 0.25;
165
+ reasons.push('all required capabilities match');
166
+ }
167
+ else if (matches.length > 0) {
168
+ score += 0.1 * (matches.length / context.requiredCapabilities.length);
169
+ reasons.push(`${matches.length}/${context.requiredCapabilities.length} required capabilities`);
170
+ }
171
+ }
172
+ // Score based on expertise
173
+ const expertise = agent.expertise ?? [];
174
+ for (const exp of expertise) {
175
+ if (taskWords.some((w) => exp.toLowerCase().includes(w))) {
176
+ score += 0.15;
177
+ reasons.push(`expertise match: ${exp}`);
178
+ }
179
+ }
180
+ // Score based on role match
181
+ if (agent.role) {
182
+ const roleWords = this.extractWords(agent.role.toLowerCase());
183
+ const roleMatches = roleWords.filter((r) => taskWords.includes(r));
184
+ if (roleMatches.length > 0) {
185
+ score += 0.1;
186
+ reasons.push(`role match: ${agent.role}`);
187
+ }
188
+ }
189
+ // Score based on description match
190
+ if (agent.description) {
191
+ const descWords = this.extractWords(agent.description.toLowerCase());
192
+ const descMatches = descWords.filter((d) => taskWords.includes(d)).length;
193
+ if (descMatches > 2) {
194
+ score += 0.05 * Math.min(descMatches, 5);
195
+ reasons.push(`description match: ${descMatches} words`);
196
+ }
197
+ }
198
+ // Team bonus
199
+ if (context?.team && agent.team === context.team) {
200
+ score += 0.1;
201
+ reasons.push(`team match: ${agent.team}`);
202
+ }
203
+ // Check redirect rules
204
+ const redirectRules = agent.selectionMetadata?.redirectWhen ?? [];
205
+ for (const rule of redirectRules) {
206
+ if (taskLower.includes(rule.phrase.toLowerCase())) {
207
+ // This agent suggests redirecting to another
208
+ score -= 0.5;
209
+ reasons.push(`redirect suggested to: ${rule.suggest}`);
210
+ }
211
+ }
212
+ // INV-AGT-SEL-002: Clamp confidence between 0 and 1
213
+ const confidence = Math.max(0, Math.min(1, score));
214
+ return {
215
+ agentId: agent.agentId,
216
+ confidence,
217
+ reason: reasons.length > 0 ? reasons.join('; ') : 'no specific match',
218
+ alternatives: [],
219
+ };
220
+ }
221
+ /**
222
+ * Normalize text for comparison (remove punctuation, extra spaces)
223
+ */
224
+ normalizeText(text) {
225
+ return text
226
+ .replace(/[^\w\s]/g, ' ')
227
+ .replace(/\s+/g, ' ')
228
+ .trim();
229
+ }
230
+ /**
231
+ * Extract words from text
232
+ */
233
+ extractWords(text) {
234
+ return text
235
+ .split(/[\s\-_,./]+/)
236
+ .filter((w) => w.length > 2)
237
+ .map((w) => w.toLowerCase());
238
+ }
239
+ }
240
+ // ============================================================================
241
+ // Factory Function
242
+ // ============================================================================
243
+ /**
244
+ * Creates a keyword-based agent selector
245
+ */
246
+ export function createAgentSelector(registry) {
247
+ return new KeywordAgentSelector(registry);
248
+ }
249
+ //# sourceMappingURL=selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.js","sourceRoot":"","sources":["../src/selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E;;GAEG;AACH,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAEpC;;GAEG;AACH,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC,+EAA+E;AAC/E,+BAA+B;AAC/B,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,QAAuB;QAAvB,aAAQ,GAAR,QAAQ,CAAe;IAAG,CAAC;IAExD;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,IAAY,EACZ,OAA+B;QAE/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEhD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,uBAAuB;YACvB,OAAO;gBACL,OAAO,EAAE,gBAAgB;gBACzB,UAAU,EAAE,GAAG;gBACf,MAAM,EAAE,0CAA0C;gBAClD,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QACzB,OAAO;YACL,GAAG,IAAI;YACP,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzC,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,UAAU,EAAE,CAAC,CAAC,UAAU;aACzB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK,CACT,IAAY,EACZ,OAA+B;QAE/B,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,KAAK,SAAS;YACxC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAa,EAAE;YAChD,CAAC,CAAC,EAAE,OAAO,EAAE,IAAa,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhD,4BAA4B;QAC5B,MAAM,QAAQ,GAAG,OAAO,EAAE,aAAa;YACrC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,aAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACnE,CAAC,CAAC,MAAM,CAAC;QAEX,mBAAmB;QACnB,MAAM,MAAM,GAAG,QAAQ;aACpB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;aACrD,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,IAAI,wBAAwB,CAAC,CAAC;QAErE,iDAAiD;QACjD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;QAEnD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IACK,UAAU,CAChB,KAAmB,EACnB,IAAY,EACZ,OAA+B;QAE/B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAE/C,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,kEAAkE;QAClE,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,EAAE,YAAY,IAAI,EAAE,CAAC;QACjE,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;YACnC,MAAM,iBAAiB,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;YACpE,IAAI,cAAc,KAAK,iBAAiB,EAAE,CAAC;gBACzC,qCAAqC;gBACrC,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,yBAAyB,OAAO,GAAG,CAAC,CAAC;gBAClD,MAAM,CAAC,wBAAwB;YACjC,CAAC;iBAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClG,4BAA4B;gBAC5B,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,mBAAmB,OAAO,GAAG,CAAC,CAAC;gBAC5C,MAAM,CAAC,wBAAwB;YACjC,CAAC;QACH,CAAC;QAED,kDAAkD;QAClD,MAAM,WAAW,GAAG,KAAK,CAAC,iBAAiB,EAAE,WAAW,IAAI,EAAE,CAAC;QAC/D,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBACzF,kCAAkC;gBAClC,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,mBAAmB,MAAM,GAAG,CAAC,CAAC;gBAC3C,MAAM,CAAC,yBAAyB;YAClC,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,EAAE,cAAc,IAAI,EAAE,CAAC;QACrE,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;YACpC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAC7C,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,yBAAyB,MAAM,EAAE,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,MAAM,QAAQ,GAAG,KAAK,CAAC,iBAAiB,EAAE,QAAQ,IAAI,EAAE,CAAC;QACzD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAC9C,KAAK,IAAI,IAAI,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,mCAAmC;QACnC,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,EAAE,YAAY,IAAI,EAAE,CAAC;QACjE,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAClD,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,uBAAuB,WAAW,EAAE,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,MAAM,eAAe,GAAG,KAAK,CAAC,iBAAiB,EAAE,eAAe,IAAI,EAAE,CAAC;QACvE,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;YACrC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAC7C,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;QAC9C,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,kDAAkD;QAClD,IAAI,OAAO,EAAE,oBAAoB,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAC1D,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CACxB,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAC9C,CACF,CAAC;YACF,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC;gBAC3D,KAAK,IAAI,IAAI,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;YAClD,CAAC;iBAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,KAAK,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;gBACtE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,oBAAoB,CAAC,MAAM,wBAAwB,CAAC,CAAC;YACjG,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,KAAK,IAAI,IAAI,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,4BAA4B;QAC5B,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAC9D,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YACnE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,mCAAmC;QACnC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;YACrE,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAC1E,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBACpB,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,sBAAsB,WAAW,QAAQ,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QAED,aAAa;QACb,IAAI,OAAO,EAAE,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC;YACjD,KAAK,IAAI,GAAG,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,uBAAuB;QACvB,MAAM,aAAa,GAAG,KAAK,CAAC,iBAAiB,EAAE,YAAY,IAAI,EAAE,CAAC;QAClE,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAClD,6CAA6C;gBAC7C,KAAK,IAAI,GAAG,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAEnD,OAAO;YACL,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU;YACV,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,mBAAmB;YACrE,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,IAAY;QAChC,OAAO,IAAI;aACR,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;aACxB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;aACpB,IAAI,EAAE,CAAC;IACZ,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,IAAY;QAC/B,OAAO,IAAI;aACR,KAAK,CAAC,aAAa,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;aAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACjC,CAAC;CACF;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAuB;IACzD,OAAO,IAAI,oBAAoB,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC"}