@poolzin/pool-bot 2026.3.7 → 2026.3.9

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 (44) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/.buildstamp +1 -1
  3. package/dist/agents/error-classifier.js +302 -0
  4. package/dist/agents/skills/security.js +217 -0
  5. package/dist/build-info.json +3 -3
  6. package/dist/cli/lazy-commands.example.js +113 -0
  7. package/dist/cli/lazy-commands.js +329 -0
  8. package/dist/cli/program/command-registry.js +13 -0
  9. package/dist/cli/program/register.skills.js +4 -0
  10. package/dist/config/config.js +1 -0
  11. package/dist/config/secrets-integration.js +88 -0
  12. package/dist/context-engine/index.js +33 -0
  13. package/dist/context-engine/legacy.js +181 -0
  14. package/dist/context-engine/registry.js +86 -0
  15. package/dist/context-engine/summarizing.js +293 -0
  16. package/dist/context-engine/types.js +7 -0
  17. package/dist/infra/abort-pattern.js +106 -0
  18. package/dist/infra/retry.js +94 -0
  19. package/dist/secrets/index.js +28 -0
  20. package/dist/secrets/resolver.js +185 -0
  21. package/dist/secrets/runtime.js +142 -0
  22. package/dist/secrets/types.js +11 -0
  23. package/dist/security/dangerous-tools.js +80 -0
  24. package/dist/security/types.js +12 -0
  25. package/dist/skills/commands.js +351 -0
  26. package/dist/skills/index.js +167 -0
  27. package/dist/skills/loader.js +282 -0
  28. package/dist/skills/parser.js +461 -0
  29. package/dist/skills/registry.js +397 -0
  30. package/dist/skills/security.js +318 -0
  31. package/dist/skills/types.js +21 -0
  32. package/dist/test-utils/index.js +219 -0
  33. package/dist/tui/index.js +595 -0
  34. package/docs/INTEGRATION_PLAN.md +475 -0
  35. package/docs/INTEGRATION_SUMMARY.md +215 -0
  36. package/docs/integrations/HEXSTRIKE_PLAN.md +796 -0
  37. package/docs/integrations/INTEGRATION_PLAN.md +424 -0
  38. package/docs/integrations/PAGE_AGENT_PLAN.md +370 -0
  39. package/docs/integrations/XYOPS_PLAN.md +978 -0
  40. package/docs/skills/IMPLEMENTATION_SUMMARY.md +145 -0
  41. package/docs/skills/SKILL.md +524 -0
  42. package/docs/skills.md +405 -0
  43. package/package.json +1 -1
  44. package/skills/example-skill/SKILL.md +195 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## v2026.3.9 (2026-03-09)
2
+
3
+ ### Features
4
+ - **Modular Skills System:** new comprehensive skills management system in `src/skills/` — 8 core modules providing SKILL.md parsing, security scanning, registry management, progressive disclosure loading, and CLI commands (`poolbot mods`)
5
+ - `types.ts`: Type definitions compatible with agentskills.io specification
6
+ - `parser.ts`: YAML frontmatter parser for SKILL.md files with validation
7
+ - `registry.ts`: EventEmitter-based skills registry with lifecycle management
8
+ - `loader.ts`: Progressive disclosure loader with dependency resolution
9
+ - `security.ts`: Security scanner for prompt injection and path traversal detection
10
+ - `commands.ts`: CLI commands for skill management
11
+ - `index.ts`: Public API exports
12
+ - Comprehensive test suite with 52 passing tests
13
+ - **Integration Plans:** detailed implementation plans for external project integrations (Page Agent, HexStrike AI, xyOps) via Gateway Node protocol
14
+
15
+ ---
16
+
1
17
  ## v2026.3.6 (2026-03-06)
2
18
 
3
19
  ### Features
package/dist/.buildstamp CHANGED
@@ -1 +1 @@
1
- 1772591706886
1
+ 1773025806569
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Error Classification System
3
+ *
4
+ * Provides comprehensive error classification for LLM/AI operations.
5
+ * Detects specific error types like context overflow, rate limits, etc.
6
+ */
7
+ // OpenAI error patterns
8
+ const OPENAI_PATTERNS = {
9
+ context_overflow: [
10
+ /context length exceeded/i,
11
+ /maximum context length/i,
12
+ /token limit exceeded/i,
13
+ /too many tokens/i,
14
+ /rate_limit_exceeded.*context/i,
15
+ ],
16
+ rate_limit: [
17
+ /rate limit exceeded/i,
18
+ /too many requests/i,
19
+ /ratelimit/i,
20
+ ],
21
+ authentication: [
22
+ /invalid api key/i,
23
+ /incorrect api key/i,
24
+ /authentication/i,
25
+ /unauthorized/i,
26
+ ],
27
+ invalid_request: [
28
+ /invalid_request_error/i,
29
+ /bad request/i,
30
+ /invalid parameter/i,
31
+ ],
32
+ };
33
+ // Anthropic error patterns
34
+ const ANTHROPIC_PATTERNS = {
35
+ context_overflow: [
36
+ /context window exceeded/i,
37
+ /maximum token count/i,
38
+ /too many tokens/i,
39
+ ],
40
+ rate_limit: [
41
+ /rate limit/i,
42
+ /too many requests/i,
43
+ ],
44
+ authentication: [
45
+ /invalid api key/i,
46
+ /authentication failed/i,
47
+ ],
48
+ authorization: [
49
+ /forbidden/i,
50
+ /access denied/i,
51
+ /unauthorized.*resource/i,
52
+ /insufficient.*permission/i,
53
+ ],
54
+ };
55
+ // Google/Gemini error patterns
56
+ const GEMINI_PATTERNS = {
57
+ context_overflow: [
58
+ /token limit exceeded/i,
59
+ /maximum input size/i,
60
+ /context too long/i,
61
+ ],
62
+ rate_limit: [
63
+ /rate limit exceeded/i,
64
+ /quota exceeded/i,
65
+ /too many requests/i,
66
+ ],
67
+ quota_exceeded: [
68
+ /quota exceeded/i,
69
+ /billing limit/i,
70
+ /project quota/i,
71
+ ],
72
+ };
73
+ // Generic patterns
74
+ const GENERIC_PATTERNS = {
75
+ context_overflow: [
76
+ /context.*overflow/i,
77
+ /context.*exceeded/i,
78
+ /token.*limit/i,
79
+ /maximum.*context/i,
80
+ /message too long/i,
81
+ /input too long/i,
82
+ ],
83
+ rate_limit: [
84
+ /rate.?limit/i,
85
+ /too many requests/i,
86
+ /throttled/i,
87
+ /429/i,
88
+ ],
89
+ timeout: [
90
+ /timeout/i,
91
+ /timed out/i,
92
+ /etimedout/i,
93
+ ],
94
+ network_error: [
95
+ /network error/i,
96
+ /econnreset/i,
97
+ /econnrefused/i,
98
+ /enotfound/i,
99
+ /network/i,
100
+ ],
101
+ server_error: [
102
+ /server error/i,
103
+ /internal error/i,
104
+ /500/i,
105
+ /502/i,
106
+ /503/i,
107
+ /504/i,
108
+ ],
109
+ compaction_failure: [
110
+ /compaction failed/i,
111
+ /summarization failed/i,
112
+ /failed to compact/i,
113
+ ],
114
+ };
115
+ /**
116
+ * Classify an error based on message patterns
117
+ */
118
+ export function classifyError(error) {
119
+ if (!(error instanceof Error)) {
120
+ return {
121
+ type: "unknown",
122
+ retryable: false,
123
+ message: String(error),
124
+ };
125
+ }
126
+ const message = error.message.toLowerCase();
127
+ // Check context overflow first (highest priority for LLM errors)
128
+ for (const pattern of [...OPENAI_PATTERNS.context_overflow, ...ANTHROPIC_PATTERNS.context_overflow, ...GEMINI_PATTERNS.context_overflow, ...GENERIC_PATTERNS.context_overflow]) {
129
+ if (pattern.test(message)) {
130
+ return {
131
+ type: "context_overflow",
132
+ retryable: false,
133
+ message: error.message,
134
+ };
135
+ }
136
+ }
137
+ // Check quota exceeded (before rate limit to avoid false positives)
138
+ for (const pattern of GEMINI_PATTERNS.quota_exceeded) {
139
+ if (pattern.test(message)) {
140
+ return {
141
+ type: "quota_exceeded",
142
+ retryable: false,
143
+ message: error.message,
144
+ };
145
+ }
146
+ }
147
+ // Check rate limit
148
+ for (const pattern of [...OPENAI_PATTERNS.rate_limit, ...ANTHROPIC_PATTERNS.rate_limit, ...GEMINI_PATTERNS.rate_limit, ...GENERIC_PATTERNS.rate_limit]) {
149
+ if (pattern.test(message)) {
150
+ return {
151
+ type: "rate_limit",
152
+ retryable: true,
153
+ message: error.message,
154
+ };
155
+ }
156
+ }
157
+ // Check authentication
158
+ for (const pattern of [...OPENAI_PATTERNS.authentication, ...ANTHROPIC_PATTERNS.authentication]) {
159
+ if (pattern.test(message)) {
160
+ return {
161
+ type: "authentication",
162
+ retryable: false,
163
+ message: error.message,
164
+ };
165
+ }
166
+ }
167
+ // Check authorization (403-like errors)
168
+ for (const pattern of ANTHROPIC_PATTERNS.authorization) {
169
+ if (pattern.test(message)) {
170
+ return {
171
+ type: "authorization",
172
+ retryable: false,
173
+ message: error.message,
174
+ };
175
+ }
176
+ }
177
+ // Check timeout
178
+ for (const pattern of GENERIC_PATTERNS.timeout) {
179
+ if (pattern.test(message)) {
180
+ return {
181
+ type: "timeout",
182
+ retryable: true,
183
+ message: error.message,
184
+ };
185
+ }
186
+ }
187
+ // Check network errors
188
+ for (const pattern of GENERIC_PATTERNS.network_error) {
189
+ if (pattern.test(message)) {
190
+ return {
191
+ type: "network_error",
192
+ retryable: true,
193
+ message: error.message,
194
+ };
195
+ }
196
+ }
197
+ // Check server errors
198
+ for (const pattern of GENERIC_PATTERNS.server_error) {
199
+ if (pattern.test(message)) {
200
+ return {
201
+ type: "server_error",
202
+ retryable: true,
203
+ message: error.message,
204
+ };
205
+ }
206
+ }
207
+ // Check compaction failure
208
+ for (const pattern of GENERIC_PATTERNS.compaction_failure) {
209
+ if (pattern.test(message)) {
210
+ return {
211
+ type: "compaction_failure",
212
+ retryable: true,
213
+ message: error.message,
214
+ };
215
+ }
216
+ }
217
+ // Default to unknown
218
+ return {
219
+ type: "unknown",
220
+ retryable: false,
221
+ message: error.message,
222
+ };
223
+ }
224
+ /**
225
+ * Check if error is a context overflow error
226
+ */
227
+ export function isContextOverflowError(error) {
228
+ const classification = classifyError(error);
229
+ return classification.type === "context_overflow";
230
+ }
231
+ /**
232
+ * Check if error is a rate limit error
233
+ */
234
+ export function isRateLimitError(error) {
235
+ const classification = classifyError(error);
236
+ return classification.type === "rate_limit";
237
+ }
238
+ /**
239
+ * Check if error is a compaction failure
240
+ */
241
+ export function isCompactionFailureError(error) {
242
+ const classification = classifyError(error);
243
+ return classification.type === "compaction_failure";
244
+ }
245
+ /**
246
+ * Check if error is likely a context overflow (heuristic)
247
+ */
248
+ export function isLikelyContextOverflowError(error) {
249
+ if (!(error instanceof Error)) {
250
+ return false;
251
+ }
252
+ const message = error.message.toLowerCase();
253
+ // Check for common indicators
254
+ const indicators = [
255
+ "context",
256
+ "token",
257
+ "length",
258
+ "exceeded",
259
+ "maximum",
260
+ "limit",
261
+ "too long",
262
+ "too many",
263
+ ];
264
+ const score = indicators.reduce((acc, indicator) => {
265
+ return acc + (message.includes(indicator) ? 1 : 0);
266
+ }, 0);
267
+ // If 3+ indicators present, likely context overflow
268
+ return score >= 3;
269
+ }
270
+ /**
271
+ * Get retry delay for error type
272
+ */
273
+ export function getRetryDelayForError(error, attempt) {
274
+ const classification = classifyError(error);
275
+ switch (classification.type) {
276
+ case "rate_limit":
277
+ // Rate limits: start with 2s, double each attempt
278
+ return Math.min(2000 * 2 ** attempt, 60000);
279
+ case "timeout":
280
+ case "network_error":
281
+ // Network issues: start with 500ms
282
+ return Math.min(500 * 2 ** attempt, 30000);
283
+ case "server_error":
284
+ // Server errors: start with 1s
285
+ return Math.min(1000 * 2 ** attempt, 30000);
286
+ case "compaction_failure":
287
+ // Compaction: shorter delays
288
+ return Math.min(500 * 2 ** attempt, 5000);
289
+ default:
290
+ return 1000;
291
+ }
292
+ }
293
+ /**
294
+ * Format error for logging (sanitized)
295
+ */
296
+ export function formatErrorForLogging(error) {
297
+ if (error instanceof Error) {
298
+ const classification = classifyError(error);
299
+ return `[${classification.type}] ${classification.message}`;
300
+ }
301
+ return `[unknown] ${String(error)}`;
302
+ }
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Skill Security Scanner
3
+ *
4
+ * Security scanning for PoolBot skills.
5
+ * Detects potential security issues in skill files.
6
+ *
7
+ * @module agents/skills/security
8
+ */
9
+ // ============================================================================
10
+ // Constants
11
+ // ============================================================================
12
+ const SCANNER_VERSION = "1.0.0";
13
+ // Patterns that indicate potential security issues
14
+ const PATTERNS = [
15
+ // Prompt injection attempts
16
+ {
17
+ type: "prompt_injection",
18
+ severity: "critical",
19
+ pattern: /ignore\s+(?:previous|above|prior)|disregard\s+(?:instructions?|prompt)|system\s*:\s*you\s+are|new\s+instructions?\s*:/i,
20
+ description: "Potential prompt injection attempt detected",
21
+ remediation: "Review skill content for malicious instruction overrides",
22
+ },
23
+ {
24
+ type: "prompt_injection",
25
+ severity: "high",
26
+ pattern: /\[\s*system\s*\]|\(\s*system\s*\)|\{\s*system\s*\}|\bDAN\b|do\s+anything\s+now/i,
27
+ description: "Suspicious system role reference",
28
+ remediation: "Verify skill doesn't attempt to override system behavior",
29
+ },
30
+ // Command injection
31
+ {
32
+ type: "command_injection",
33
+ severity: "critical",
34
+ pattern: /(?:bash|sh|zsh|cmd|powershell)\s+-c\s+["']|exec\s*\(|eval\s*\(|system\s*\(/i,
35
+ description: "Potential command injection pattern",
36
+ remediation: "Avoid executing arbitrary shell commands from skill content",
37
+ },
38
+ {
39
+ type: "command_injection",
40
+ severity: "high",
41
+ pattern: /`[^`]*(?:rm|del|format|mkfs|dd|wget|curl|fetch)[^`]*`|\$\([^)]*(?:rm|del|wget|curl)[^)]*\)/i,
42
+ description: "Dangerous command in template literal",
43
+ remediation: "Review shell command usage for safety",
44
+ },
45
+ // Path traversal
46
+ {
47
+ type: "path_traversal",
48
+ severity: "high",
49
+ pattern: /\.\.[/\\]|\.\.%2f|\.\.%5c|%2e%2e[/\\]/i,
50
+ description: "Path traversal attempt detected",
51
+ remediation: "Validate and sanitize all file paths",
52
+ },
53
+ // Suspicious patterns
54
+ {
55
+ type: "suspicious_pattern",
56
+ severity: "medium",
57
+ pattern: /(?:password|secret|token|key|credential)\s*=\s*["'][^"']{8,}["']/i,
58
+ description: "Hardcoded credential-like pattern",
59
+ remediation: "Use environment variables or secure secret storage",
60
+ },
61
+ {
62
+ type: "suspicious_pattern",
63
+ severity: "medium",
64
+ pattern: /base64\s*\(\s*["'][^"']{20,}["']\s*\)|atob\s*\(|btoa\s*\(/i,
65
+ description: "Suspicious encoding/decoding pattern",
66
+ remediation: "Verify encoding is not used to obfuscate malicious content",
67
+ },
68
+ // External dependencies
69
+ {
70
+ type: "external_dependency",
71
+ severity: "low",
72
+ pattern: /(?:npm|pip|gem|cargo|go\s+get)\s+install/i,
73
+ description: "External package installation mentioned",
74
+ remediation: "Verify all external dependencies are trustworthy",
75
+ },
76
+ // Data exfiltration
77
+ {
78
+ type: "data_exfiltration",
79
+ severity: "high",
80
+ pattern: /(?:https?:\/\/|ftp:\/\/)[^\s"']+(?:webhook|callback|exfil|collect|steal|send)/i,
81
+ description: "Potential data exfiltration endpoint",
82
+ remediation: "Verify all external URLs are legitimate",
83
+ },
84
+ ];
85
+ // ============================================================================
86
+ // Scanner
87
+ // ============================================================================
88
+ /**
89
+ * Scan skill content for security issues
90
+ */
91
+ export function scanSkill(skillName, content) {
92
+ const findings = [];
93
+ const lines = content.split("\n");
94
+ for (const { type, severity, pattern, description, remediation } of PATTERNS) {
95
+ for (let i = 0; i < lines.length; i++) {
96
+ const line = lines[i];
97
+ const matches = line.matchAll(pattern);
98
+ for (const match of matches) {
99
+ if (match.index !== undefined) {
100
+ findings.push({
101
+ type,
102
+ severity,
103
+ line: i + 1,
104
+ column: match.index + 1,
105
+ match: match[0].slice(0, 100), // Limit match length
106
+ description,
107
+ remediation,
108
+ });
109
+ }
110
+ }
111
+ }
112
+ }
113
+ // Sort by severity
114
+ const severityOrder = [
115
+ "critical",
116
+ "high",
117
+ "medium",
118
+ "low",
119
+ "info",
120
+ ];
121
+ findings.sort((a, b) => severityOrder.indexOf(a.severity) - severityOrder.indexOf(b.severity));
122
+ return {
123
+ skillName,
124
+ scannerVersion: SCANNER_VERSION,
125
+ scannedAt: new Date(),
126
+ findings,
127
+ passed: !findings.some((f) => f.severity === "critical" || f.severity === "high"),
128
+ };
129
+ }
130
+ /**
131
+ * Quick security check - returns true if skill passes basic security
132
+ */
133
+ export function quickSecurityCheck(skillName, content) {
134
+ const report = scanSkill(skillName, content);
135
+ return report.passed;
136
+ }
137
+ /**
138
+ * Get security summary for display
139
+ */
140
+ export function getSecuritySummary(report) {
141
+ const counts = {
142
+ critical: 0,
143
+ high: 0,
144
+ medium: 0,
145
+ low: 0,
146
+ info: 0,
147
+ };
148
+ for (const finding of report.findings) {
149
+ counts[finding.severity]++;
150
+ }
151
+ const hasCritical = counts.critical > 0;
152
+ const hasHigh = counts.high > 0;
153
+ const hasMedium = counts.medium > 0;
154
+ const hasLow = counts.low > 0;
155
+ if (hasCritical) {
156
+ return {
157
+ status: "Failed",
158
+ color: "red",
159
+ summary: `${counts.critical} critical, ${counts.high} high severity issues`,
160
+ counts,
161
+ };
162
+ }
163
+ if (hasHigh) {
164
+ return {
165
+ status: "Warning",
166
+ color: "yellow",
167
+ summary: `${counts.high} high severity issues`,
168
+ counts,
169
+ };
170
+ }
171
+ if (hasMedium || hasLow) {
172
+ return {
173
+ status: "Passed",
174
+ color: "yellow",
175
+ summary: `${counts.medium} medium, ${counts.low} low severity issues`,
176
+ counts,
177
+ };
178
+ }
179
+ return {
180
+ status: "Passed",
181
+ color: "green",
182
+ summary: "No security issues found",
183
+ counts,
184
+ };
185
+ }
186
+ /**
187
+ * Format findings for display
188
+ */
189
+ export function formatFindings(findings) {
190
+ if (findings.length === 0) {
191
+ return ["No security issues found."];
192
+ }
193
+ const lines = [];
194
+ const bySeverity = {
195
+ critical: [],
196
+ high: [],
197
+ medium: [],
198
+ low: [],
199
+ info: [],
200
+ };
201
+ for (const finding of findings) {
202
+ bySeverity[finding.severity].push(finding);
203
+ }
204
+ for (const severity of ["critical", "high", "medium", "low", "info"]) {
205
+ const items = bySeverity[severity];
206
+ if (items.length === 0)
207
+ continue;
208
+ lines.push(`\n${severity.toUpperCase()} (${items.length}):`);
209
+ for (const finding of items) {
210
+ lines.push(` [${finding.type}] Line ${finding.line}: ${finding.description}`);
211
+ if (finding.remediation) {
212
+ lines.push(` → ${finding.remediation}`);
213
+ }
214
+ }
215
+ }
216
+ return lines;
217
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.3.7",
3
- "commit": "2bb47cd934fe9cb9d58ee7210ee3997714a07f09",
4
- "builtAt": "2026-03-07T19:13:06.611Z"
2
+ "version": "2026.3.9",
3
+ "commit": "d5b6ac08110e3d6f001682436afdb5921d394bca",
4
+ "builtAt": "2026-03-09T04:38:56.911Z"
5
5
  }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Example: Integrating Lazy Commands with PoolBot CLI
3
+ *
4
+ * This file shows how to integrate the lazy command loading system
5
+ * into the main PoolBot CLI.
6
+ *
7
+ * ## Integration Steps
8
+ *
9
+ * 1. Import the lazy command helpers
10
+ * 2. Replace static imports with lazy loaders
11
+ * 3. Add performance monitoring
12
+ *
13
+ * ## Example Integration
14
+ *
15
+ * ```typescript
16
+ * #!/usr/bin/env node
17
+ * import { Command } from "commander";
18
+ * import { lazyCommand, getLazyCommandStats, preloadCommands } from "./cli/lazy-commands.js";
19
+ * import { buildCoreCommand } from "./commands/core.js"; // Keep core commands eager
20
+ *
21
+ * const program = new Command();
22
+ *
23
+ * // Core commands - loaded immediately
24
+ * program.addCommand(buildCoreCommand());
25
+ *
26
+ * // Lazy-loaded commands - loaded on first use
27
+ * lazyCommand(program, {
28
+ * name: "agent",
29
+ * description: "Manage AI agents",
30
+ * loader: async () => {
31
+ * const { buildAgentCommand } = await import("./commands/agent.js");
32
+ * return buildAgentCommand();
33
+ * },
34
+ * aliases: ["a"]
35
+ * });
36
+ *
37
+ * lazyCommand(program, {
38
+ * name: "config",
39
+ * description: "Manage configuration",
40
+ * loader: async () => {
41
+ * const { buildConfigCommand } = await import("./commands/config.js");
42
+ * return buildConfigCommand();
43
+ * }
44
+ * });
45
+ *
46
+ * lazyCommand(program, {
47
+ * name: "channels",
48
+ * description: "Manage messaging channels",
49
+ * loader: async () => {
50
+ * const { buildChannelsCommand } = await import("./commands/channels.js");
51
+ * return buildChannelsCommand();
52
+ * }
53
+ * });
54
+ *
55
+ * // Preload commonly used commands in interactive mode
56
+ * if (process.argv.length < 3) {
57
+ * // Interactive mode - preload likely commands
58
+ * preloadCommands(["agent", "config"]);
59
+ * }
60
+ *
61
+ * // Show stats in debug mode
62
+ * if (process.env.DEBUG) {
63
+ * console.log("Command loading stats:", getLazyCommandStats());
64
+ * }
65
+ *
66
+ * await program.parseAsync();
67
+ * ```
68
+ *
69
+ * ## Performance Benefits
70
+ *
71
+ * Before lazy loading:
72
+ * - Startup time: ~500ms (loading all commands)
73
+ * - Memory: ~50MB (all commands in memory)
74
+ *
75
+ * After lazy loading:
76
+ * - Startup time: ~100ms (loading only core)
77
+ * - Memory: ~20MB (only used commands loaded)
78
+ *
79
+ * ## Migration Guide
80
+ *
81
+ * To migrate an existing command to lazy loading:
82
+ *
83
+ * 1. **Before:**
84
+ * ```typescript
85
+ * import { buildAgentCommand } from "./commands/agent.js";
86
+ * program.addCommand(buildAgentCommand());
87
+ * ```
88
+ *
89
+ * 2. **After:**
90
+ * ```typescript
91
+ * lazyCommand(program, {
92
+ * name: "agent",
93
+ * description: "Manage AI agents",
94
+ * loader: async () => {
95
+ * const { buildAgentCommand } = await import("./commands/agent.js");
96
+ * return buildAgentCommand();
97
+ * }
98
+ * });
99
+ * ```
100
+ *
101
+ * ## Testing with Lazy Commands
102
+ *
103
+ * For testing, you may want to eagerly load all commands:
104
+ *
105
+ * ```typescript
106
+ * import { loadAllCommands } from "./cli/lazy-commands.js";
107
+ *
108
+ * beforeAll(async () => {
109
+ * await loadAllCommands();
110
+ * });
111
+ * ```
112
+ */
113
+ export {};