specweave 0.4.0 → 0.4.1

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 (62) hide show
  1. package/CLAUDE.md +501 -28
  2. package/README.md +99 -57
  3. package/bin/specweave.js +16 -0
  4. package/dist/adapters/adapter-base.d.ts +21 -0
  5. package/dist/adapters/adapter-base.d.ts.map +1 -1
  6. package/dist/adapters/adapter-base.js +28 -0
  7. package/dist/adapters/adapter-base.js.map +1 -1
  8. package/dist/adapters/adapter-interface.d.ts +41 -0
  9. package/dist/adapters/adapter-interface.d.ts.map +1 -1
  10. package/dist/adapters/claude/adapter.d.ts +36 -0
  11. package/dist/adapters/claude/adapter.d.ts.map +1 -1
  12. package/dist/adapters/claude/adapter.js +135 -0
  13. package/dist/adapters/claude/adapter.js.map +1 -1
  14. package/dist/adapters/copilot/adapter.d.ts +25 -0
  15. package/dist/adapters/copilot/adapter.d.ts.map +1 -1
  16. package/dist/adapters/copilot/adapter.js +112 -0
  17. package/dist/adapters/copilot/adapter.js.map +1 -1
  18. package/dist/adapters/cursor/adapter.d.ts +36 -0
  19. package/dist/adapters/cursor/adapter.d.ts.map +1 -1
  20. package/dist/adapters/cursor/adapter.js +140 -0
  21. package/dist/adapters/cursor/adapter.js.map +1 -1
  22. package/dist/adapters/generic/adapter.d.ts +25 -0
  23. package/dist/adapters/generic/adapter.d.ts.map +1 -1
  24. package/dist/adapters/generic/adapter.js +111 -0
  25. package/dist/adapters/generic/adapter.js.map +1 -1
  26. package/dist/cli/commands/init.d.ts.map +1 -1
  27. package/dist/cli/commands/init.js +48 -1
  28. package/dist/cli/commands/init.js.map +1 -1
  29. package/dist/cli/commands/plugin.d.ts +37 -0
  30. package/dist/cli/commands/plugin.d.ts.map +1 -0
  31. package/dist/cli/commands/plugin.js +296 -0
  32. package/dist/cli/commands/plugin.js.map +1 -0
  33. package/dist/core/plugin-detector.d.ts +96 -0
  34. package/dist/core/plugin-detector.d.ts.map +1 -0
  35. package/dist/core/plugin-detector.js +349 -0
  36. package/dist/core/plugin-detector.js.map +1 -0
  37. package/dist/core/plugin-loader.d.ts +111 -0
  38. package/dist/core/plugin-loader.d.ts.map +1 -0
  39. package/dist/core/plugin-loader.js +319 -0
  40. package/dist/core/plugin-loader.js.map +1 -0
  41. package/dist/core/plugin-manager.d.ts +144 -0
  42. package/dist/core/plugin-manager.d.ts.map +1 -0
  43. package/dist/core/plugin-manager.js +393 -0
  44. package/dist/core/plugin-manager.js.map +1 -0
  45. package/dist/core/schemas/plugin-manifest.schema.json +253 -0
  46. package/dist/core/types/plugin.d.ts +252 -0
  47. package/dist/core/types/plugin.d.ts.map +1 -0
  48. package/dist/core/types/plugin.js +48 -0
  49. package/dist/core/types/plugin.js.map +1 -0
  50. package/dist/integrations/jira/jira-mapper.d.ts +2 -2
  51. package/dist/integrations/jira/jira-mapper.js +2 -2
  52. package/package.json +13 -9
  53. package/src/adapters/adapter-base.ts +33 -0
  54. package/src/adapters/adapter-interface.ts +46 -0
  55. package/src/adapters/claude/adapter.ts +164 -0
  56. package/src/adapters/copilot/adapter.ts +138 -0
  57. package/src/adapters/cursor/adapter.ts +170 -0
  58. package/src/adapters/generic/adapter.ts +137 -0
  59. package/src/commands/specweave.increment.md +48 -4
  60. package/src/hooks/post-increment-plugin-detect.sh +142 -0
  61. package/src/hooks/post-task-completion.sh +53 -11
  62. package/src/hooks/pre-task-plugin-detect.sh +96 -0
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Plugin Loader
3
+ *
4
+ * Reads plugin directories, validates manifests, and loads skills/agents/commands.
5
+ * Provides plugin discovery and integrity checking.
6
+ *
7
+ * @module core/plugin-loader
8
+ * @version 0.4.0
9
+ */
10
+ import * as path from 'path';
11
+ import * as fs from 'fs-extra';
12
+ import Ajv from 'ajv';
13
+ import { ManifestValidationError, PluginNotFoundError } from './types/plugin.js';
14
+ // Import JSON schema for validation
15
+ import pluginManifestSchema from './schemas/plugin-manifest.schema.json';
16
+ /**
17
+ * PluginLoader - Loads and validates plugins from filesystem
18
+ */
19
+ export class PluginLoader {
20
+ constructor() {
21
+ // Initialize JSON schema validator
22
+ this.ajv = new Ajv({ allErrors: true });
23
+ this.validateManifestSchema = this.ajv.compile(pluginManifestSchema);
24
+ }
25
+ /**
26
+ * Load a plugin from directory
27
+ *
28
+ * @param pluginPath - Absolute path to plugin directory
29
+ * @returns Loaded plugin with all components
30
+ * @throws PluginNotFoundError if directory doesn't exist
31
+ * @throws ManifestValidationError if manifest is invalid
32
+ */
33
+ async loadFromDirectory(pluginPath) {
34
+ // Verify directory exists
35
+ if (!(await fs.pathExists(pluginPath))) {
36
+ throw new PluginNotFoundError(path.basename(pluginPath));
37
+ }
38
+ // Load and validate manifest
39
+ const manifest = await this.loadManifest(pluginPath);
40
+ // Load components
41
+ const [skills, agents, commands] = await Promise.all([
42
+ this.loadSkills(pluginPath, manifest.provides.skills),
43
+ this.loadAgents(pluginPath, manifest.provides.agents),
44
+ this.loadCommands(pluginPath, manifest.provides.commands)
45
+ ]);
46
+ return {
47
+ manifest,
48
+ path: pluginPath,
49
+ skills,
50
+ agents,
51
+ commands
52
+ };
53
+ }
54
+ /**
55
+ * Load plugin manifest from .claude-plugin/manifest.json
56
+ *
57
+ * @param pluginPath - Path to plugin directory
58
+ * @returns Validated plugin manifest
59
+ * @throws ManifestValidationError if manifest is invalid
60
+ */
61
+ async loadManifest(pluginPath) {
62
+ const manifestPath = path.join(pluginPath, '.claude-plugin', 'manifest.json');
63
+ // Check if manifest exists
64
+ if (!(await fs.pathExists(manifestPath))) {
65
+ throw new ManifestValidationError(`Manifest not found at ${manifestPath}`, path.basename(pluginPath));
66
+ }
67
+ // Read and parse manifest
68
+ let content;
69
+ try {
70
+ content = await fs.readJSON(manifestPath);
71
+ }
72
+ catch (error) {
73
+ throw new ManifestValidationError(`Invalid JSON in manifest: ${error.message}`, path.basename(pluginPath));
74
+ }
75
+ // Validate against schema
76
+ const validation = this.validateManifest(content);
77
+ if (!validation.valid) {
78
+ throw new ManifestValidationError(`Manifest validation failed:\n${validation.errors.join('\n')}`, path.basename(pluginPath));
79
+ }
80
+ return content;
81
+ }
82
+ /**
83
+ * Validate manifest against JSON schema
84
+ *
85
+ * @param manifest - Manifest object to validate
86
+ * @returns Validation result with errors/warnings
87
+ */
88
+ validateManifest(manifest) {
89
+ const valid = this.validateManifestSchema(manifest);
90
+ const errors = [];
91
+ const warnings = [];
92
+ if (!valid && this.validateManifestSchema.errors) {
93
+ for (const error of this.validateManifestSchema.errors) {
94
+ errors.push(`${error.instancePath} ${error.message}`);
95
+ }
96
+ }
97
+ // Additional semantic validation
98
+ if (manifest.provides) {
99
+ // Warn if no skills, agents, or commands provided
100
+ if (manifest.provides.skills.length === 0 &&
101
+ manifest.provides.agents.length === 0 &&
102
+ manifest.provides.commands.length === 0) {
103
+ warnings.push('Plugin provides no skills, agents, or commands');
104
+ }
105
+ }
106
+ return { valid, errors, warnings };
107
+ }
108
+ /**
109
+ * Load skills from plugin
110
+ *
111
+ * @param pluginPath - Path to plugin directory
112
+ * @param skillNames - Skill names from manifest
113
+ * @returns Array of loaded skills
114
+ */
115
+ async loadSkills(pluginPath, skillNames) {
116
+ const skills = [];
117
+ const skillsDir = path.join(pluginPath, 'skills');
118
+ for (const skillName of skillNames) {
119
+ const skillPath = path.join(skillsDir, skillName);
120
+ const skillMdPath = path.join(skillPath, 'SKILL.md');
121
+ if (await fs.pathExists(skillMdPath)) {
122
+ const content = await fs.readFile(skillMdPath, 'utf-8');
123
+ const description = this.extractDescription(content);
124
+ // Load test cases if they exist
125
+ const testCases = await this.loadTestCases(skillPath);
126
+ skills.push({
127
+ name: skillName,
128
+ path: skillPath,
129
+ description,
130
+ testCases
131
+ });
132
+ }
133
+ else {
134
+ console.warn(`Skill ${skillName} not found at ${skillMdPath}`);
135
+ }
136
+ }
137
+ return skills;
138
+ }
139
+ /**
140
+ * Load agents from plugin
141
+ *
142
+ * @param pluginPath - Path to plugin directory
143
+ * @param agentNames - Agent names from manifest
144
+ * @returns Array of loaded agents
145
+ */
146
+ async loadAgents(pluginPath, agentNames) {
147
+ const agents = [];
148
+ const agentsDir = path.join(pluginPath, 'agents');
149
+ for (const agentName of agentNames) {
150
+ const agentPath = path.join(agentsDir, agentName);
151
+ const agentMdPath = path.join(agentPath, 'AGENT.md');
152
+ if (await fs.pathExists(agentMdPath)) {
153
+ const content = await fs.readFile(agentMdPath, 'utf-8');
154
+ const systemPrompt = content; // Full content is the system prompt
155
+ const capabilities = this.extractCapabilities(content);
156
+ agents.push({
157
+ name: agentName,
158
+ path: agentPath,
159
+ systemPrompt,
160
+ capabilities
161
+ });
162
+ }
163
+ else {
164
+ console.warn(`Agent ${agentName} not found at ${agentMdPath}`);
165
+ }
166
+ }
167
+ return agents;
168
+ }
169
+ /**
170
+ * Load commands from plugin
171
+ *
172
+ * @param pluginPath - Path to plugin directory
173
+ * @param commandNames - Command names from manifest
174
+ * @returns Array of loaded commands
175
+ */
176
+ async loadCommands(pluginPath, commandNames) {
177
+ const commands = [];
178
+ const commandsDir = path.join(pluginPath, 'commands');
179
+ for (const commandName of commandNames) {
180
+ // Convert specweave.github.sync → github-sync.md
181
+ const fileName = commandName.replace('specweave.', '').replace(/\./g, '-') + '.md';
182
+ const commandPath = path.join(commandsDir, fileName);
183
+ if (await fs.pathExists(commandPath)) {
184
+ const content = await fs.readFile(commandPath, 'utf-8');
185
+ const description = this.extractDescription(content);
186
+ commands.push({
187
+ name: commandName,
188
+ path: commandPath,
189
+ description,
190
+ prompt: content
191
+ });
192
+ }
193
+ else {
194
+ console.warn(`Command ${commandName} not found at ${commandPath}`);
195
+ }
196
+ }
197
+ return commands;
198
+ }
199
+ /**
200
+ * Load test cases from skill directory
201
+ *
202
+ * @param skillPath - Path to skill directory
203
+ * @returns Array of test cases
204
+ */
205
+ async loadTestCases(skillPath) {
206
+ const testCases = [];
207
+ const testCasesDir = path.join(skillPath, 'test-cases');
208
+ if (!(await fs.pathExists(testCasesDir))) {
209
+ return testCases;
210
+ }
211
+ const files = await fs.readdir(testCasesDir);
212
+ for (const file of files) {
213
+ if (file.endsWith('.yaml') || file.endsWith('.yml')) {
214
+ const testCasePath = path.join(testCasesDir, file);
215
+ // TODO: Parse YAML test case
216
+ // For now, just record the path
217
+ testCases.push({
218
+ id: file.replace(/\.(yaml|yml)$/, ''),
219
+ description: `Test case from ${file}`,
220
+ input: '',
221
+ expected: '',
222
+ path: testCasePath
223
+ });
224
+ }
225
+ }
226
+ return testCases;
227
+ }
228
+ /**
229
+ * Extract description from SKILL.md or AGENT.md frontmatter
230
+ *
231
+ * @param content - File content
232
+ * @returns Extracted description
233
+ */
234
+ extractDescription(content) {
235
+ // Extract from YAML frontmatter
236
+ const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---/);
237
+ if (frontmatterMatch) {
238
+ const descMatch = frontmatterMatch[1].match(/description:\s*(.+)/);
239
+ if (descMatch) {
240
+ return descMatch[1].trim();
241
+ }
242
+ }
243
+ // Fallback: first non-empty line after frontmatter
244
+ const lines = content.split('\n');
245
+ for (const line of lines) {
246
+ const trimmed = line.trim();
247
+ if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('-')) {
248
+ return trimmed.substring(0, 200); // Max 200 chars
249
+ }
250
+ }
251
+ return 'No description available';
252
+ }
253
+ /**
254
+ * Extract capabilities from agent content
255
+ *
256
+ * @param content - Agent file content
257
+ * @returns Array of capability strings
258
+ */
259
+ extractCapabilities(content) {
260
+ const capabilities = [];
261
+ // Look for "Capabilities" or "Can do" section
262
+ const capabilitiesMatch = content.match(/##\s*Capabilities\s*\n([\s\S]+?)(?=\n##|$)/i);
263
+ if (capabilitiesMatch) {
264
+ const lines = capabilitiesMatch[1].split('\n');
265
+ for (const line of lines) {
266
+ const trimmed = line.trim();
267
+ if (trimmed.startsWith('-') || trimmed.startsWith('*')) {
268
+ capabilities.push(trimmed.substring(1).trim());
269
+ }
270
+ }
271
+ }
272
+ return capabilities;
273
+ }
274
+ /**
275
+ * Verify plugin integrity
276
+ *
277
+ * Checks that all declared skills/agents/commands exist
278
+ *
279
+ * @param plugin - Plugin to verify
280
+ * @returns True if plugin is intact
281
+ */
282
+ async verifyPlugin(plugin) {
283
+ const { manifest, skills, agents, commands } = plugin;
284
+ // Check skills
285
+ if (skills.length !== manifest.provides.skills.length) {
286
+ console.warn(`Plugin ${manifest.name}: Expected ${manifest.provides.skills.length} skills, found ${skills.length}`);
287
+ return false;
288
+ }
289
+ // Check agents
290
+ if (agents.length !== manifest.provides.agents.length) {
291
+ console.warn(`Plugin ${manifest.name}: Expected ${manifest.provides.agents.length} agents, found ${agents.length}`);
292
+ return false;
293
+ }
294
+ // Check commands
295
+ if (commands.length !== manifest.provides.commands.length) {
296
+ console.warn(`Plugin ${manifest.name}: Expected ${manifest.provides.commands.length} commands, found ${commands.length}`);
297
+ return false;
298
+ }
299
+ return true;
300
+ }
301
+ /**
302
+ * Get plugin metadata (lightweight, without loading full plugin)
303
+ *
304
+ * @param pluginPath - Path to plugin directory
305
+ * @returns Plugin metadata
306
+ */
307
+ async getMetadata(pluginPath) {
308
+ const manifest = await this.loadManifest(pluginPath);
309
+ return {
310
+ name: manifest.name,
311
+ version: manifest.version,
312
+ description: manifest.description,
313
+ skillCount: manifest.provides.skills.length,
314
+ agentCount: manifest.provides.agents.length,
315
+ commandCount: manifest.provides.commands.length
316
+ };
317
+ }
318
+ }
319
+ //# sourceMappingURL=plugin-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/core/plugin-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Plugin Manager
3
+ *
4
+ * Central orchestrator for plugin lifecycle management.
5
+ * Handles loading/unloading, dependency resolution, configuration management.
6
+ *
7
+ * @module core/plugin-manager
8
+ * @version 0.4.0
9
+ */
10
+ import type { Plugin, PluginInfo, PluginLoadOptions, PluginUnloadOptions } from './types/plugin.js';
11
+ import type { IAdapter } from '../adapters/adapter-interface.js';
12
+ /**
13
+ * PluginManager - Manages plugin lifecycle and configuration
14
+ */
15
+ export declare class PluginManager {
16
+ private projectPath;
17
+ private loader;
18
+ private configPath;
19
+ private pluginsDir;
20
+ private loadedPlugins;
21
+ /**
22
+ * Create a new PluginManager
23
+ *
24
+ * @param projectPath - Path to project root
25
+ * @param pluginsDir - Path to plugins directory (default: src/plugins)
26
+ */
27
+ constructor(projectPath?: string, pluginsDir?: string);
28
+ /**
29
+ * Load (enable) a plugin
30
+ *
31
+ * 1. Load plugin from src/plugins/
32
+ * 2. Check dependencies
33
+ * 3. Install via adapter
34
+ * 4. Update config
35
+ *
36
+ * @param name - Plugin name (e.g., "github", "kubernetes")
37
+ * @param adapter - Adapter to use for installation
38
+ * @param options - Load options
39
+ */
40
+ loadPlugin(name: string, adapter: IAdapter, options?: PluginLoadOptions): Promise<void>;
41
+ /**
42
+ * Unload (disable) a plugin
43
+ *
44
+ * @param name - Plugin name
45
+ * @param adapter - Adapter to use for uninstallation
46
+ * @param options - Unload options
47
+ */
48
+ unloadPlugin(name: string, adapter: IAdapter, options?: PluginUnloadOptions): Promise<void>;
49
+ /**
50
+ * Get all available plugins (scan src/plugins/)
51
+ *
52
+ * @returns Array of plugin info
53
+ */
54
+ getAvailablePlugins(): Promise<PluginInfo[]>;
55
+ /**
56
+ * Get enabled plugins from config
57
+ *
58
+ * @returns Array of enabled plugin names
59
+ */
60
+ getEnabledPlugins(): Promise<string[]>;
61
+ /**
62
+ * Check if a plugin is enabled
63
+ *
64
+ * @param name - Plugin name
65
+ * @returns True if enabled
66
+ */
67
+ isPluginEnabled(name: string): Promise<boolean>;
68
+ /**
69
+ * Update plugin configuration
70
+ *
71
+ * @param name - Plugin name
72
+ * @param action - 'enable' or 'disable'
73
+ */
74
+ private updateConfig;
75
+ /**
76
+ * Load plugin configuration from .specweave/config.yaml
77
+ *
78
+ * @returns Plugin configuration
79
+ */
80
+ private loadConfig;
81
+ /**
82
+ * Save plugin configuration to .specweave/config.yaml
83
+ *
84
+ * @param pluginConfig - Plugin configuration to save
85
+ */
86
+ private saveConfig;
87
+ /**
88
+ * Check plugin dependencies
89
+ *
90
+ * Ensures all required plugins are loaded
91
+ *
92
+ * @param plugin - Plugin to check
93
+ * @throws PluginDependencyError if dependencies are not met
94
+ */
95
+ checkDependencies(plugin: Plugin): Promise<void>;
96
+ /**
97
+ * Resolve dependency graph for a plugin
98
+ *
99
+ * Returns all plugins that need to be loaded (including transitive deps)
100
+ *
101
+ * @param plugin - Plugin to resolve
102
+ * @returns Array of plugins in load order
103
+ */
104
+ resolveDependencies(plugin: Plugin): Promise<Plugin[]>;
105
+ /**
106
+ * Get plugins that depend on a given plugin
107
+ *
108
+ * @param name - Plugin name
109
+ * @returns Array of dependent plugin names
110
+ */
111
+ private getDependents;
112
+ /**
113
+ * Validate plugin configuration
114
+ *
115
+ * Checks for circular dependencies, missing plugins, etc.
116
+ *
117
+ * @returns Validation result
118
+ */
119
+ validateConfig(): Promise<{
120
+ valid: boolean;
121
+ errors: string[];
122
+ }>;
123
+ /**
124
+ * Get plugin by name
125
+ *
126
+ * @param name - Plugin name
127
+ * @returns Loaded plugin
128
+ * @throws PluginNotFoundError if plugin is not loaded
129
+ */
130
+ getPlugin(name: string): Plugin;
131
+ /**
132
+ * Get all loaded plugins
133
+ *
134
+ * @returns Map of loaded plugins
135
+ */
136
+ getLoadedPlugins(): Map<string, Plugin>;
137
+ /**
138
+ * Clear loaded plugins cache
139
+ *
140
+ * Useful for testing or forcing reload
141
+ */
142
+ clearCache(): void;
143
+ }
144
+ //# sourceMappingURL=plugin-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/core/plugin-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EAEV,iBAAiB,EACjB,mBAAmB,EAEpB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAEjE;;GAEG;AACH,qBAAa,aAAa;IAatB,OAAO,CAAC,WAAW;IAZrB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAsB;IAE3C;;;;;OAKG;gBAEO,WAAW,GAAE,MAAsB,EAC3C,UAAU,CAAC,EAAE,MAAM;IAQrB;;;;;;;;;;;OAWG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,QAAQ,EACjB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAmDhB;;;;;;OAMG;IACG,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,QAAQ,EACjB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC;IAkChB;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAwClD;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAK5C;;;;;OAKG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrD;;;;;OAKG;YACW,YAAY;IAc1B;;;;OAIG;YACW,UAAU;IA4BxB;;;;OAIG;YACW,UAAU;IAgBxB;;;;;;;OAOG;IACG,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBtD;;;;;;;OAOG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA4B5D;;;;;OAKG;YACW,aAAa;IAgB3B;;;;;;OAMG;IACG,cAAc,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAuDrE;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQ/B;;;;OAIG;IACH,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIvC;;;;OAIG;IACH,UAAU,IAAI,IAAI;CAGnB"}