@hyperdrive.bot/bmad-workflow 1.0.2

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1017 -0
  3. package/bin/dev +5 -0
  4. package/bin/dev.cmd +3 -0
  5. package/bin/dev.js +5 -0
  6. package/bin/run +5 -0
  7. package/bin/run.cmd +3 -0
  8. package/bin/run.js +5 -0
  9. package/dist/commands/config/show.d.ts +34 -0
  10. package/dist/commands/config/show.js +108 -0
  11. package/dist/commands/config/validate.d.ts +29 -0
  12. package/dist/commands/config/validate.js +131 -0
  13. package/dist/commands/decompose.d.ts +79 -0
  14. package/dist/commands/decompose.js +327 -0
  15. package/dist/commands/demo.d.ts +18 -0
  16. package/dist/commands/demo.js +107 -0
  17. package/dist/commands/epics/create.d.ts +123 -0
  18. package/dist/commands/epics/create.js +459 -0
  19. package/dist/commands/epics/list.d.ts +120 -0
  20. package/dist/commands/epics/list.js +280 -0
  21. package/dist/commands/hello/index.d.ts +12 -0
  22. package/dist/commands/hello/index.js +34 -0
  23. package/dist/commands/hello/world.d.ts +8 -0
  24. package/dist/commands/hello/world.js +24 -0
  25. package/dist/commands/prd/fix.d.ts +39 -0
  26. package/dist/commands/prd/fix.js +140 -0
  27. package/dist/commands/prd/validate.d.ts +112 -0
  28. package/dist/commands/prd/validate.js +302 -0
  29. package/dist/commands/stories/create.d.ts +95 -0
  30. package/dist/commands/stories/create.js +431 -0
  31. package/dist/commands/stories/develop.d.ts +91 -0
  32. package/dist/commands/stories/develop.js +460 -0
  33. package/dist/commands/stories/list.d.ts +84 -0
  34. package/dist/commands/stories/list.js +291 -0
  35. package/dist/commands/stories/move.d.ts +66 -0
  36. package/dist/commands/stories/move.js +273 -0
  37. package/dist/commands/stories/qa.d.ts +99 -0
  38. package/dist/commands/stories/qa.js +530 -0
  39. package/dist/commands/workflow.d.ts +97 -0
  40. package/dist/commands/workflow.js +390 -0
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.js +1 -0
  43. package/dist/models/agent-options.d.ts +50 -0
  44. package/dist/models/agent-options.js +1 -0
  45. package/dist/models/agent-result.d.ts +29 -0
  46. package/dist/models/agent-result.js +1 -0
  47. package/dist/models/index.d.ts +10 -0
  48. package/dist/models/index.js +10 -0
  49. package/dist/models/phase-result.d.ts +65 -0
  50. package/dist/models/phase-result.js +7 -0
  51. package/dist/models/provider.d.ts +28 -0
  52. package/dist/models/provider.js +18 -0
  53. package/dist/models/story.d.ts +154 -0
  54. package/dist/models/story.js +18 -0
  55. package/dist/models/workflow-config.d.ts +148 -0
  56. package/dist/models/workflow-config.js +1 -0
  57. package/dist/models/workflow-result.d.ts +164 -0
  58. package/dist/models/workflow-result.js +7 -0
  59. package/dist/services/agents/agent-runner-factory.d.ts +31 -0
  60. package/dist/services/agents/agent-runner-factory.js +44 -0
  61. package/dist/services/agents/agent-runner.d.ts +46 -0
  62. package/dist/services/agents/agent-runner.js +29 -0
  63. package/dist/services/agents/claude-agent-runner.d.ts +81 -0
  64. package/dist/services/agents/claude-agent-runner.js +332 -0
  65. package/dist/services/agents/gemini-agent-runner.d.ts +82 -0
  66. package/dist/services/agents/gemini-agent-runner.js +350 -0
  67. package/dist/services/agents/index.d.ts +7 -0
  68. package/dist/services/agents/index.js +7 -0
  69. package/dist/services/file-system/file-manager.d.ts +110 -0
  70. package/dist/services/file-system/file-manager.js +223 -0
  71. package/dist/services/file-system/glob-matcher.d.ts +75 -0
  72. package/dist/services/file-system/glob-matcher.js +126 -0
  73. package/dist/services/file-system/path-resolver.d.ts +183 -0
  74. package/dist/services/file-system/path-resolver.js +400 -0
  75. package/dist/services/logging/workflow-logger.d.ts +232 -0
  76. package/dist/services/logging/workflow-logger.js +552 -0
  77. package/dist/services/orchestration/batch-processor.d.ts +113 -0
  78. package/dist/services/orchestration/batch-processor.js +187 -0
  79. package/dist/services/orchestration/dependency-graph-executor.d.ts +60 -0
  80. package/dist/services/orchestration/dependency-graph-executor.js +447 -0
  81. package/dist/services/orchestration/index.d.ts +10 -0
  82. package/dist/services/orchestration/index.js +8 -0
  83. package/dist/services/orchestration/input-detector.d.ts +125 -0
  84. package/dist/services/orchestration/input-detector.js +381 -0
  85. package/dist/services/orchestration/story-queue.d.ts +94 -0
  86. package/dist/services/orchestration/story-queue.js +170 -0
  87. package/dist/services/orchestration/story-type-detector.d.ts +80 -0
  88. package/dist/services/orchestration/story-type-detector.js +258 -0
  89. package/dist/services/orchestration/task-decomposition-service.d.ts +67 -0
  90. package/dist/services/orchestration/task-decomposition-service.js +607 -0
  91. package/dist/services/orchestration/workflow-orchestrator.d.ts +659 -0
  92. package/dist/services/orchestration/workflow-orchestrator.js +2201 -0
  93. package/dist/services/parsers/epic-parser.d.ts +117 -0
  94. package/dist/services/parsers/epic-parser.js +264 -0
  95. package/dist/services/parsers/prd-fixer.d.ts +86 -0
  96. package/dist/services/parsers/prd-fixer.js +194 -0
  97. package/dist/services/parsers/prd-parser.d.ts +123 -0
  98. package/dist/services/parsers/prd-parser.js +286 -0
  99. package/dist/services/parsers/standalone-story-parser.d.ts +114 -0
  100. package/dist/services/parsers/standalone-story-parser.js +255 -0
  101. package/dist/services/parsers/story-parser-factory.d.ts +81 -0
  102. package/dist/services/parsers/story-parser-factory.js +108 -0
  103. package/dist/services/parsers/story-parser.d.ts +122 -0
  104. package/dist/services/parsers/story-parser.js +262 -0
  105. package/dist/services/scaffolding/decompose-session-scaffolder.d.ts +74 -0
  106. package/dist/services/scaffolding/decompose-session-scaffolder.js +315 -0
  107. package/dist/services/scaffolding/file-scaffolder.d.ts +94 -0
  108. package/dist/services/scaffolding/file-scaffolder.js +314 -0
  109. package/dist/services/validation/config-validator.d.ts +88 -0
  110. package/dist/services/validation/config-validator.js +167 -0
  111. package/dist/types/task-graph.d.ts +142 -0
  112. package/dist/types/task-graph.js +5 -0
  113. package/dist/utils/colors.d.ts +49 -0
  114. package/dist/utils/colors.js +50 -0
  115. package/dist/utils/error-formatter.d.ts +64 -0
  116. package/dist/utils/error-formatter.js +279 -0
  117. package/dist/utils/errors.d.ts +170 -0
  118. package/dist/utils/errors.js +233 -0
  119. package/dist/utils/formatters.d.ts +84 -0
  120. package/dist/utils/formatters.js +162 -0
  121. package/dist/utils/logger.d.ts +63 -0
  122. package/dist/utils/logger.js +78 -0
  123. package/dist/utils/progress.d.ts +104 -0
  124. package/dist/utils/progress.js +161 -0
  125. package/dist/utils/retry.d.ts +114 -0
  126. package/dist/utils/retry.js +160 -0
  127. package/dist/utils/shared-flags.d.ts +28 -0
  128. package/dist/utils/shared-flags.js +43 -0
  129. package/package.json +119 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * ClaudeAgentRunner Service
3
+ *
4
+ * Encapsulates Claude CLI process spawning with comprehensive error handling,
5
+ * logging, and timeout management for reliable AI agent execution.
6
+ */
7
+ import type pino from 'pino';
8
+ import type { AgentOptions, AgentResult } from '../../models/index.js';
9
+ import type { AIProvider } from '../../models/provider.js';
10
+ import type { AIProviderRunner } from './agent-runner.js';
11
+ /**
12
+ * ClaudeAgentRunner service for executing Claude AI agents
13
+ *
14
+ * Spawns Claude CLI processes to execute AI agents with specified prompts.
15
+ * Handles timeout, error collection, result formatting, and process cleanup.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const logger = createLogger({ namespace: 'agent-runner' })
20
+ * const runner = new ClaudeAgentRunner(logger)
21
+ * const result = await runner.runAgent({
22
+ * prompt: '@.bmad-core/agents/architect.md Create epic for user auth',
23
+ * agentType: 'architect',
24
+ * timeout: 300000
25
+ * })
26
+ * ```
27
+ */
28
+ export declare class ClaudeAgentRunner implements AIProviderRunner {
29
+ readonly provider: AIProvider;
30
+ private readonly config;
31
+ private readonly logger;
32
+ /**
33
+ * Create a new ClaudeAgentRunner instance
34
+ *
35
+ * @param logger - Logger instance for structured logging
36
+ */
37
+ constructor(logger: pino.Logger);
38
+ /**
39
+ * Get the count of active processes
40
+ * (Useful for testing and monitoring purposes)
41
+ *
42
+ * @returns Number of currently active child processes
43
+ */
44
+ getActiveProcessCount(): number;
45
+ /**
46
+ * Execute a Claude AI agent with the specified prompt and options
47
+ *
48
+ * This method spawns a Claude CLI process, captures output, handles errors,
49
+ * and enforces timeouts. It never throws exceptions - all errors are returned
50
+ * as typed AgentResult objects.
51
+ *
52
+ * @param prompt - The prompt to execute with the agent
53
+ * @param options - Agent execution options (without prompt)
54
+ * @returns AgentResult with success status, output, errors, and metadata
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const result = await runner.runAgent('@.bmad-core/agents/architect.md Create epic for user auth', {
59
+ * agentType: 'architect',
60
+ * timeout: 300000
61
+ * })
62
+ *
63
+ * if (result.success) {
64
+ * console.log('Output:', result.output)
65
+ * } else {
66
+ * console.error('Error:', result.errors)
67
+ * }
68
+ * ```
69
+ */
70
+ runAgent(prompt: string, options: Omit<AgentOptions, 'prompt'>): Promise<AgentResult>;
71
+ /**
72
+ * Build detailed error context for debugging process failures
73
+ * @private
74
+ */
75
+ private buildErrorContext;
76
+ /**
77
+ * Invoke onResponse callback and return result
78
+ * @private
79
+ */
80
+ private returnWithCallback;
81
+ }
@@ -0,0 +1,332 @@
1
+ /**
2
+ * ClaudeAgentRunner Service
3
+ *
4
+ * Encapsulates Claude CLI process spawning with comprehensive error handling,
5
+ * logging, and timeout management for reliable AI agent execution.
6
+ */
7
+ import { exec } from 'node:child_process';
8
+ import { mkdtemp, rm, writeFile } from 'node:fs/promises';
9
+ import { tmpdir } from 'node:os';
10
+ import { join } from 'node:path';
11
+ import { promisify } from 'node:util';
12
+ const execAsync = promisify(exec);
13
+ import { PROVIDER_CONFIGS } from '../../models/provider.js';
14
+ /**
15
+ * Track active child processes for cleanup on SIGINT
16
+ */
17
+ const activeProcesses = new Set();
18
+ /**
19
+ * Track if SIGINT handler has been registered
20
+ */
21
+ let sigintHandlerRegistered = false;
22
+ /**
23
+ * Register SIGINT handler for graceful process cleanup
24
+ */
25
+ const registerSigintHandler = (logger) => {
26
+ if (sigintHandlerRegistered)
27
+ return;
28
+ process.on('SIGINT', () => {
29
+ logger.info({
30
+ activeProcessCount: activeProcesses.size,
31
+ }, 'Received SIGINT, cleaning up active processes');
32
+ // Kill all active child processes
33
+ for (const childProcess of activeProcesses) {
34
+ try {
35
+ childProcess.kill('SIGTERM');
36
+ }
37
+ catch (error) {
38
+ logger.error({
39
+ error: error.message,
40
+ }, 'Error killing child process');
41
+ }
42
+ }
43
+ // Clear the set
44
+ activeProcesses.clear();
45
+ // Exit the main process
46
+ process.exit(130); // 130 = 128 + SIGINT signal number (2)
47
+ });
48
+ sigintHandlerRegistered = true;
49
+ };
50
+ /**
51
+ * ClaudeAgentRunner service for executing Claude AI agents
52
+ *
53
+ * Spawns Claude CLI processes to execute AI agents with specified prompts.
54
+ * Handles timeout, error collection, result formatting, and process cleanup.
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const logger = createLogger({ namespace: 'agent-runner' })
59
+ * const runner = new ClaudeAgentRunner(logger)
60
+ * const result = await runner.runAgent({
61
+ * prompt: '@.bmad-core/agents/architect.md Create epic for user auth',
62
+ * agentType: 'architect',
63
+ * timeout: 300000
64
+ * })
65
+ * ```
66
+ */
67
+ export class ClaudeAgentRunner {
68
+ provider = 'claude';
69
+ config = PROVIDER_CONFIGS.claude;
70
+ logger;
71
+ /**
72
+ * Create a new ClaudeAgentRunner instance
73
+ *
74
+ * @param logger - Logger instance for structured logging
75
+ */
76
+ constructor(logger) {
77
+ this.logger = logger;
78
+ registerSigintHandler(logger);
79
+ }
80
+ /**
81
+ * Get the count of active processes
82
+ * (Useful for testing and monitoring purposes)
83
+ *
84
+ * @returns Number of currently active child processes
85
+ */
86
+ getActiveProcessCount() {
87
+ return activeProcesses.size;
88
+ }
89
+ /**
90
+ * Execute a Claude AI agent with the specified prompt and options
91
+ *
92
+ * This method spawns a Claude CLI process, captures output, handles errors,
93
+ * and enforces timeouts. It never throws exceptions - all errors are returned
94
+ * as typed AgentResult objects.
95
+ *
96
+ * @param prompt - The prompt to execute with the agent
97
+ * @param options - Agent execution options (without prompt)
98
+ * @returns AgentResult with success status, output, errors, and metadata
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * const result = await runner.runAgent('@.bmad-core/agents/architect.md Create epic for user auth', {
103
+ * agentType: 'architect',
104
+ * timeout: 300000
105
+ * })
106
+ *
107
+ * if (result.success) {
108
+ * console.log('Output:', result.output)
109
+ * } else {
110
+ * console.error('Error:', result.errors)
111
+ * }
112
+ * ```
113
+ */
114
+ async runAgent(prompt, options) {
115
+ const startTime = Date.now();
116
+ const timeout = options.timeout ?? 1_800_000; // Default 30 minutes
117
+ // Input validation
118
+ if (!prompt || prompt.trim().length === 0) {
119
+ return this.returnWithCallback({
120
+ agentType: options.agentType,
121
+ duration: Date.now() - startTime,
122
+ errors: 'Prompt is required and cannot be empty',
123
+ exitCode: -1,
124
+ output: '',
125
+ success: false,
126
+ }, options.onResponse);
127
+ }
128
+ // Log execution start with metadata
129
+ this.logger.info({
130
+ agentType: options.agentType,
131
+ promptLength: prompt.length,
132
+ references: options.references?.length ?? 0,
133
+ timeout,
134
+ }, 'Executing Claude agent');
135
+ // Invoke onPrompt callback if provided
136
+ if (options.onPrompt) {
137
+ try {
138
+ // Create options object without callbacks for the callback
139
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
140
+ const { onPrompt, onResponse, ...callbackOptions } = options;
141
+ await onPrompt(prompt, callbackOptions);
142
+ }
143
+ catch (error) {
144
+ this.logger.warn({ error: error.message }, 'Error in onPrompt callback');
145
+ }
146
+ }
147
+ // For large prompts or prompts with special characters, use a temp file
148
+ // This avoids shell escaping issues
149
+ let tempDir = null;
150
+ let tempFile = null;
151
+ let stdoutData = '';
152
+ let stderrData = '';
153
+ try {
154
+ // Create temp directory and file
155
+ tempDir = await mkdtemp(join(tmpdir(), 'claude-prompt-'));
156
+ tempFile = join(tempDir, 'prompt.txt');
157
+ await writeFile(tempFile, prompt, 'utf8');
158
+ // Build command with temp file
159
+ const flags = this.config.flags.join(' ');
160
+ const command = `${this.config.command} ${flags} < "${tempFile}"`;
161
+ // Log the command being executed
162
+ this.logger.info({
163
+ promptLength: prompt.length,
164
+ tempFile,
165
+ }, 'Executing command with temp file');
166
+ // Use exec instead of spawn for better shell compatibility
167
+ const { stderr, stdout } = await execAsync(command, {
168
+ env: process.env,
169
+ maxBuffer: 10 * 1024 * 1024, // 10MB buffer
170
+ shell: process.env.SHELL || '/bin/bash',
171
+ timeout,
172
+ });
173
+ stdoutData = stdout;
174
+ stderrData = stderr;
175
+ const duration = Date.now() - startTime;
176
+ this.logger.info({
177
+ duration,
178
+ stderrLength: stderrData.length,
179
+ stdoutLength: stdoutData.length,
180
+ }, 'Claude CLI process completed successfully');
181
+ const result = {
182
+ agentType: options.agentType,
183
+ duration,
184
+ errors: stderrData,
185
+ exitCode: 0,
186
+ output: stdoutData,
187
+ success: true,
188
+ };
189
+ return this.returnWithCallback(result, options.onResponse);
190
+ }
191
+ catch (error) {
192
+ // Handle exec errors (includes timeout, non-zero exit, etc.)
193
+ const duration = Date.now() - startTime;
194
+ // Extract stdout/stderr from exec error if available
195
+ const execError = error;
196
+ if (execError.stdout)
197
+ stdoutData = execError.stdout;
198
+ if (execError.stderr)
199
+ stderrData = execError.stderr;
200
+ const exitCode = execError.code ?? -1;
201
+ const isTimeout = execError.killed === true && execError.signal === 'SIGTERM';
202
+ const wasKilled = execError.killed === true;
203
+ const signal = execError.signal ?? null;
204
+ // Build detailed error context for debugging
205
+ const errorContext = this.buildErrorContext({
206
+ cmd: execError.cmd,
207
+ duration,
208
+ exitCode,
209
+ isTimeout,
210
+ signal,
211
+ stderrData,
212
+ stdoutData,
213
+ wasKilled,
214
+ });
215
+ this.logger.error({
216
+ cmd: execError.cmd,
217
+ duration,
218
+ error: execError.message,
219
+ exitCode,
220
+ isTimeout,
221
+ signal,
222
+ stderrLength: stderrData.length,
223
+ stdoutLength: stdoutData.length,
224
+ wasKilled,
225
+ }, isTimeout ? 'Claude CLI process timeout' : 'Claude CLI process error');
226
+ return this.returnWithCallback({
227
+ agentType: options.agentType,
228
+ duration,
229
+ errors: errorContext,
230
+ exitCode: isTimeout ? 124 : exitCode,
231
+ output: stdoutData,
232
+ success: false,
233
+ }, options.onResponse);
234
+ }
235
+ finally {
236
+ // Clean up temp file and directory
237
+ if (tempDir) {
238
+ try {
239
+ await rm(tempDir, { force: true, recursive: true });
240
+ this.logger.debug({ tempDir }, 'Cleaned up temp directory');
241
+ }
242
+ catch (cleanupError) {
243
+ this.logger.warn({ error: cleanupError.message, tempDir }, 'Failed to clean up temp directory');
244
+ }
245
+ }
246
+ }
247
+ }
248
+ /**
249
+ * Build detailed error context for debugging process failures
250
+ * @private
251
+ */
252
+ buildErrorContext(info) {
253
+ const lines = [];
254
+ // Determine the type of failure
255
+ if (info.isTimeout) {
256
+ lines.push(`Process timeout after ${info.duration}ms`);
257
+ }
258
+ else if (info.wasKilled) {
259
+ lines.push('Process was killed externally');
260
+ // Explain common exit codes
261
+ switch (info.exitCode) {
262
+ case 130: {
263
+ lines.push('Exit code 130 = SIGINT (user interrupt, Ctrl+C)');
264
+ break;
265
+ }
266
+ case 137: {
267
+ lines.push('Exit code 137 = SIGKILL (process forcefully killed)', 'Possible causes:', ' - System OOM killer', ' - Exceeded memory limits', ' - Docker/container killed the process');
268
+ break;
269
+ }
270
+ case 143: {
271
+ lines.push('Exit code 143 = SIGTERM (process terminated)', 'Possible causes:', ' - System OOM killer terminated the process', ' - Another process sent SIGTERM', ' - Parent process cleanup', ' - Docker/container resource limits');
272
+ break;
273
+ }
274
+ // No default
275
+ }
276
+ if (info.signal) {
277
+ lines.push(`Signal received: ${info.signal}`);
278
+ }
279
+ else {
280
+ lines.push('No signal information available (signal: null)');
281
+ }
282
+ }
283
+ else {
284
+ lines.push(`Process exited with code ${info.exitCode}`);
285
+ }
286
+ // Add duration context
287
+ lines.push(`Duration: ${(info.duration / 1000).toFixed(2)}s`);
288
+ // Add output context
289
+ if (info.stdoutData.length > 0) {
290
+ lines.push(`Stdout (${info.stdoutData.length} chars):`);
291
+ // Truncate if too long, show last 500 chars which are often most relevant
292
+ const truncatedStdout = info.stdoutData.length > 500 ? `...[truncated]...\n${info.stdoutData.slice(-500)}` : info.stdoutData;
293
+ lines.push(truncatedStdout);
294
+ }
295
+ else {
296
+ lines.push('Stdout: (empty - no output captured)');
297
+ }
298
+ if (info.stderrData.length > 0) {
299
+ lines.push(`Stderr (${info.stderrData.length} chars):`);
300
+ const truncatedStderr = info.stderrData.length > 500 ? `...[truncated]...\n${info.stderrData.slice(-500)}` : info.stderrData;
301
+ lines.push(truncatedStderr);
302
+ }
303
+ else {
304
+ lines.push('Stderr: (empty - no error output)');
305
+ }
306
+ // Add command for reference (truncate if too long)
307
+ if (info.cmd) {
308
+ const truncatedCmd = info.cmd.length > 200 ? `${info.cmd.slice(0, 200)}...[truncated]` : info.cmd;
309
+ lines.push(`Command: ${truncatedCmd}`);
310
+ }
311
+ // Add troubleshooting suggestions for empty output
312
+ if (info.stdoutData.length === 0 && info.stderrData.length === 0) {
313
+ lines.push('', 'Troubleshooting (no output captured):', ' 1. Check system resources (memory, CPU)', ' 2. Verify Claude CLI is properly installed: `claude --version`', ' 3. Check for Claude API issues', ' 4. Review system logs: `dmesg | tail -50` (for OOM killer)', ' 5. Try running the command manually to see output');
314
+ }
315
+ return lines.join('\n');
316
+ }
317
+ /**
318
+ * Invoke onResponse callback and return result
319
+ * @private
320
+ */
321
+ async returnWithCallback(result, onResponse) {
322
+ if (onResponse) {
323
+ try {
324
+ await onResponse(result);
325
+ }
326
+ catch (error) {
327
+ this.logger.warn({ error: error.message }, 'Error in onResponse callback');
328
+ }
329
+ }
330
+ return result;
331
+ }
332
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * GeminiAgentRunner Service
3
+ *
4
+ * Encapsulates Gemini CLI process spawning with comprehensive error handling,
5
+ * logging, and timeout management for reliable AI agent execution.
6
+ *
7
+ * Key difference from Claude: Gemini CLI doesn't support @file references natively,
8
+ * so this runner preprocesses prompts to inline file content before execution.
9
+ */
10
+ import type pino from 'pino';
11
+ import type { AgentOptions, AgentResult } from '../../models/index.js';
12
+ import type { AIProvider } from '../../models/provider.js';
13
+ import type { AIProviderRunner } from './agent-runner.js';
14
+ /**
15
+ * GeminiAgentRunner service for executing Gemini AI agents
16
+ *
17
+ * Spawns Gemini CLI processes to execute AI agents with specified prompts.
18
+ * Preprocesses @file references to inline file content since Gemini CLI
19
+ * doesn't support native file references like Claude.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const logger = createLogger({ namespace: 'agent-runner' })
24
+ * const runner = new GeminiAgentRunner(logger)
25
+ * const result = await runner.runAgent({
26
+ * prompt: '@.bmad-core/agents/architect.md Create epic for user auth',
27
+ * agentType: 'architect',
28
+ * timeout: 300000
29
+ * })
30
+ * ```
31
+ */
32
+ export declare class GeminiAgentRunner implements AIProviderRunner {
33
+ readonly provider: AIProvider;
34
+ private readonly config;
35
+ private readonly logger;
36
+ /**
37
+ * Create a new GeminiAgentRunner instance
38
+ *
39
+ * @param logger - Logger instance for structured logging
40
+ */
41
+ constructor(logger: pino.Logger);
42
+ /**
43
+ * Get the count of active processes
44
+ * (Useful for testing and monitoring purposes)
45
+ *
46
+ * @returns Number of currently active child processes
47
+ */
48
+ getActiveProcessCount(): number;
49
+ /**
50
+ * Execute a Gemini AI agent with the specified prompt and options
51
+ *
52
+ * This method spawns a Gemini CLI process, captures output, handles errors,
53
+ * and enforces timeouts. It preprocesses @file references to inline content
54
+ * since Gemini CLI doesn't support native file references.
55
+ *
56
+ * @param prompt - The prompt to execute with the agent
57
+ * @param options - Agent execution options (without prompt)
58
+ * @returns AgentResult with success status, output, errors, and metadata
59
+ */
60
+ runAgent(prompt: string, options: Omit<AgentOptions, 'prompt'>): Promise<AgentResult>;
61
+ /**
62
+ * Build detailed error context for debugging process failures
63
+ * @private
64
+ */
65
+ private buildErrorContext;
66
+ /**
67
+ * Preprocess prompt to inline @file references
68
+ *
69
+ * Since Gemini CLI doesn't support @file syntax natively, this method
70
+ * finds all @file references and replaces them with the actual file content.
71
+ *
72
+ * @param prompt - The original prompt with @file references
73
+ * @param basePath - Base path for resolving relative file paths
74
+ * @returns Preprocessed prompt with inlined file content
75
+ */
76
+ private preprocessPrompt;
77
+ /**
78
+ * Invoke onResponse callback and return result
79
+ * @private
80
+ */
81
+ private returnWithCallback;
82
+ }