@eldrforge/ai-service 0.1.15 → 0.1.17
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.
- package/LICENSE +1 -1
- package/README.md +7 -7
- package/dist/index.js +291 -72
- package/dist/index.js.map +1 -1
- package/dist/src/tools/commit-tools.d.ts.map +1 -1
- package/examples/README.md +3 -3
- package/package.json +4 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/logger.ts","../src/ai.ts","../src/interactive.ts","../src/prompts/templates.ts","../src/prompts/commit.ts","../src/prompts/release.ts","../src/prompts/review.ts","../src/agentic/executor.ts","../src/tools/registry.ts","../src/tools/commit-tools.ts","../src/agentic/commit.ts","../src/tools/release-tools.ts","../src/agentic/release.ts","../src/tools/publish-tools.ts","../src/agentic/publish.ts","../src/observability/conversation-logger.ts","../src/observability/reflection.ts","../src/observability/metrics.ts"],"sourcesContent":["/**\n * Optional logger support\n * If winston is available as a peer dependency, use it\n * Otherwise, provide a no-op logger\n */\n\nimport type { Logger } from './types';\n\nlet logger: Logger | undefined;\n\n/**\n * Set a custom logger instance\n */\nexport function setLogger(customLogger: Logger): void {\n logger = customLogger;\n}\n\n/**\n * Create a no-op logger that does nothing\n */\nexport function createNoOpLogger(): Logger {\n return {\n info: () => {},\n error: () => {},\n warn: () => {},\n debug: () => {},\n };\n}\n\n/**\n * Attempt to load winston logger\n * @returns winston logger if available, otherwise null\n */\nexport function tryLoadWinston(): Logger | null {\n try {\n // Dynamic import to avoid hard dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const winston = require('winston');\n if (winston && winston.createLogger) {\n return winston.createLogger({\n level: 'info',\n format: winston.format.simple(),\n transports: [new winston.transports.Console()],\n });\n }\n } catch {\n // Winston not available\n }\n return null;\n}\n\n/**\n * Get the current logger or a no-op logger\n */\nexport function getLogger(): Logger {\n if (logger) {\n return logger;\n }\n\n // Try to load winston if available\n const winstonLogger = tryLoadWinston();\n if (winstonLogger) {\n logger = winstonLogger;\n return winstonLogger;\n }\n\n // Return no-op logger\n return createNoOpLogger();\n}\n","import { OpenAI } from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources';\nimport { safeJsonParse } from '@eldrforge/git-tools';\nimport fs from 'fs';\nimport { getLogger } from './logger';\nimport type { AIConfig, Transcription, StorageAdapter, Logger } from './types';\n\nexport interface OpenAIOptions {\n responseFormat?: any;\n model?: string;\n debug?: boolean;\n debugFile?: string;\n debugRequestFile?: string;\n debugResponseFile?: string;\n maxTokens?: number;\n openaiReasoning?: 'low' | 'medium' | 'high';\n openaiMaxOutputTokens?: number;\n storage?: StorageAdapter;\n logger?: Logger;\n tools?: any[]; // OpenAI tool definitions\n toolChoice?: 'auto' | 'none' | 'required' | { type: 'function'; function: { name: string } };\n}\n\nexport interface TranscriptionOptions {\n model?: string;\n debug?: boolean;\n debugFile?: string;\n debugRequestFile?: string;\n debugResponseFile?: string;\n outputDirectory?: string;\n storage?: StorageAdapter;\n logger?: Logger;\n onArchive?: (audioPath: string, transcriptionText: string) => Promise<void>;\n}\n\n/**\n * Get the appropriate model to use based on command-specific configuration\n * Command-specific model overrides the global model setting\n */\nexport function getModelForCommand(config: AIConfig, commandName: string): string {\n let commandModel: string | undefined;\n\n switch (commandName) {\n case 'commit':\n case 'audio-commit':\n commandModel = config.commands?.commit?.model;\n break;\n case 'release':\n commandModel = config.commands?.release?.model;\n break;\n case 'review':\n case 'audio-review':\n commandModel = config.commands?.review?.model;\n break;\n default:\n // For other commands, just use global model\n break;\n }\n\n // Return command-specific model if available, otherwise global model\n return commandModel || config.model || 'gpt-4o-mini';\n}\n\n/**\n * Get the appropriate OpenAI reasoning level based on command-specific configuration\n * Command-specific reasoning overrides the global reasoning setting\n */\nexport function getOpenAIReasoningForCommand(config: AIConfig, commandName: string): 'low' | 'medium' | 'high' {\n let commandReasoning: 'low' | 'medium' | 'high' | undefined;\n\n switch (commandName) {\n case 'commit':\n case 'audio-commit':\n commandReasoning = config.commands?.commit?.reasoning;\n break;\n case 'release':\n commandReasoning = config.commands?.release?.reasoning;\n break;\n case 'review':\n case 'audio-review':\n commandReasoning = config.commands?.review?.reasoning;\n break;\n default:\n // For other commands, just use global reasoning\n break;\n }\n\n // Return command-specific reasoning if available, otherwise global reasoning\n return commandReasoning || config.reasoning || 'low';\n}\n\nexport class OpenAIError extends Error {\n constructor(message: string, public readonly isTokenLimitError: boolean = false) {\n super(message);\n this.name = 'OpenAIError';\n }\n}\n\n// Check if an error is a token limit exceeded error\nexport function isTokenLimitError(error: any): boolean {\n if (!error?.message) return false;\n\n const message = error.message.toLowerCase();\n return message.includes('maximum context length') ||\n message.includes('context_length_exceeded') ||\n message.includes('token limit') ||\n message.includes('too many tokens') ||\n message.includes('reduce the length');\n}\n\n// Check if an error is a rate limit error\nexport function isRateLimitError(error: any): boolean {\n if (!error?.message && !error?.code && !error?.status) return false;\n\n // Check for OpenAI specific rate limit indicators\n if (error.status === 429 || error.code === 'rate_limit_exceeded') {\n return true;\n }\n\n // Only check message if it exists\n if (error.message) {\n const message = error.message.toLowerCase();\n return message.includes('rate limit exceeded') ||\n message.includes('too many requests') ||\n message.includes('quota exceeded') ||\n (message.includes('rate') && message.includes('limit'));\n }\n\n return false;\n}\n\n/**\n * Create OpenAI completion with optional debug and retry support\n */\nexport async function createCompletion(\n messages: ChatCompletionMessageParam[],\n options: OpenAIOptions = { model: \"gpt-4o-mini\" }\n): Promise<string | any> {\n const logger = options.logger || getLogger();\n let openai: OpenAI | null = null;\n\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n // Create the client which we'll close in the finally block.\n const timeoutMs = parseInt(process.env.OPENAI_TIMEOUT_MS || '300000', 10); // Default to 5 minutes\n if (isNaN(timeoutMs) || timeoutMs <= 0) {\n throw new OpenAIError('Invalid OPENAI_TIMEOUT_MS value - must be a positive number');\n }\n openai = new OpenAI({\n apiKey: apiKey,\n timeout: timeoutMs,\n });\n\n const modelToUse = options.model || \"gpt-4o-mini\";\n\n // Calculate request size\n const requestSize = JSON.stringify(messages).length;\n const requestSizeKB = (requestSize / 1024).toFixed(2);\n\n // Log model, reasoning level, and request size\n const reasoningInfo = options.openaiReasoning ? ` | Reasoning: ${options.openaiReasoning}` : '';\n logger.info('🤖 Making request to OpenAI');\n logger.info(' Model: %s%s', modelToUse, reasoningInfo);\n logger.info(' Request size: %s KB (%s bytes)', requestSizeKB, requestSize.toLocaleString());\n\n logger.debug('Sending prompt to OpenAI: %j', messages);\n\n // Use openaiMaxOutputTokens if specified (highest priority), otherwise fall back to maxTokens, or default to 10000\n const maxCompletionTokens = options.openaiMaxOutputTokens ?? options.maxTokens ?? 10000;\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile) && options.storage) {\n const requestData = {\n model: modelToUse,\n messages,\n max_completion_tokens: maxCompletionTokens,\n response_format: options.responseFormat,\n reasoning_effort: options.openaiReasoning,\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(requestData, null, 2));\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n // Prepare the API call options\n const apiOptions: any = {\n model: modelToUse,\n messages,\n max_completion_tokens: maxCompletionTokens,\n response_format: options.responseFormat,\n };\n\n // Add tools if provided\n if (options.tools && options.tools.length > 0) {\n apiOptions.tools = options.tools;\n apiOptions.tool_choice = options.toolChoice || 'auto';\n }\n\n // Add reasoning parameter if specified and model supports it\n if (options.openaiReasoning && (modelToUse.includes('gpt-5') || modelToUse.includes('o3'))) {\n apiOptions.reasoning_effort = options.openaiReasoning;\n }\n\n // Add timeout wrapper to the OpenAI API call\n const startTime = Date.now();\n const completionPromise = openai.chat.completions.create(apiOptions);\n\n // Create timeout promise with proper cleanup to prevent memory leaks\n let timeoutId: NodeJS.Timeout | null = null;\n const timeoutPromise = new Promise<never>((_, reject) => {\n const timeoutMs = parseInt(process.env.OPENAI_TIMEOUT_MS || '300000', 10); // Default to 5 minutes\n const validTimeout = isNaN(timeoutMs) || timeoutMs <= 0 ? 300000 : timeoutMs;\n timeoutId = setTimeout(() => reject(new OpenAIError(`OpenAI API call timed out after ${validTimeout/1000} seconds`)), validTimeout);\n });\n\n // Add progress indicator that updates every 5 seconds\n let progressIntervalId: NodeJS.Timeout | null = null;\n progressIntervalId = setInterval(() => {\n const elapsed = Math.round((Date.now() - startTime) / 1000);\n logger.info(' ⏳ Waiting for response... %ds', elapsed);\n }, 5000);\n\n let completion;\n try {\n completion = await Promise.race([completionPromise, timeoutPromise]);\n } finally {\n // Clear the timeout to prevent memory leaks\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n // Clear the progress interval\n if (progressIntervalId !== null) {\n clearInterval(progressIntervalId);\n }\n }\n\n const elapsedTime = Date.now() - startTime;\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile) && options.storage) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(completion, null, 2));\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const message = completion.choices[0]?.message;\n if (!message) {\n throw new OpenAIError('No response message received from OpenAI');\n }\n\n // If tools are being used, return the full message object (includes tool_calls)\n if (options.tools && options.tools.length > 0) {\n // Log elapsed time\n const elapsedTimeFormatted = elapsedTime >= 1000\n ? `${(elapsedTime / 1000).toFixed(1)}s`\n : `${elapsedTime}ms`;\n logger.info(' Time: %s', elapsedTimeFormatted);\n\n // Log token usage if available\n if (completion.usage) {\n logger.info(' Token usage: %s prompt + %s completion = %s total',\n completion.usage.prompt_tokens?.toLocaleString() || '?',\n completion.usage.completion_tokens?.toLocaleString() || '?',\n completion.usage.total_tokens?.toLocaleString() || '?'\n );\n }\n\n return message; // Return full message object for tool handling\n }\n\n // For non-tool calls, return content as string\n const response = message.content?.trim();\n if (!response) {\n throw new OpenAIError('No response content received from OpenAI');\n }\n\n // Calculate and log response size\n const responseSize = response.length;\n const responseSizeKB = (responseSize / 1024).toFixed(2);\n logger.info(' Response size: %s KB (%s bytes)', responseSizeKB, responseSize.toLocaleString());\n\n // Log elapsed time\n const elapsedTimeFormatted = elapsedTime >= 1000\n ? `${(elapsedTime / 1000).toFixed(1)}s`\n : `${elapsedTime}ms`;\n logger.info(' Time: %s', elapsedTimeFormatted);\n\n // Log token usage if available\n if (completion.usage) {\n logger.info(' Token usage: %s prompt + %s completion = %s total',\n completion.usage.prompt_tokens?.toLocaleString() || '?',\n completion.usage.completion_tokens?.toLocaleString() || '?',\n completion.usage.total_tokens?.toLocaleString() || '?'\n );\n }\n\n logger.debug('Received response from OpenAI: %s...', response.substring(0, 30));\n if (options.responseFormat) {\n return safeJsonParse(response, 'OpenAI API response');\n } else {\n return response;\n }\n\n } catch (error: any) {\n logger.error('Error calling OpenAI API: %s %s', error.message, error.stack);\n const isTokenError = isTokenLimitError(error);\n throw new OpenAIError(`Failed to create completion: ${error.message}`, isTokenError);\n } finally {\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n\n/**\n * Create completion with automatic retry on token limit errors\n */\nexport async function createCompletionWithRetry(\n messages: ChatCompletionMessageParam[],\n options: OpenAIOptions = { model: \"gpt-4o-mini\" },\n retryCallback?: (attempt: number) => Promise<ChatCompletionMessageParam[]>\n): Promise<string | any> {\n const logger = options.logger || getLogger();\n const maxRetries = 3;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n const messagesToSend = attempt === 1 ? messages : (retryCallback ? await retryCallback(attempt) : messages);\n return await createCompletion(messagesToSend, options);\n } catch (error: any) {\n if (error instanceof OpenAIError && error.isTokenLimitError && attempt < maxRetries && retryCallback) {\n logger.warn('Token limit exceeded on attempt %d/%d, retrying with reduced content...', attempt, maxRetries);\n // Add exponential backoff for token limit errors\n const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1), 10000);\n await new Promise(resolve => setTimeout(resolve, backoffMs));\n continue;\n } else if (isRateLimitError(error) && attempt < maxRetries) {\n // Handle rate limiting with exponential backoff\n const backoffMs = Math.min(2000 * Math.pow(2, attempt - 1), 15000); // More reasonable backoff: 2s, 4s, 8s, max 15s\n logger.warn(`Rate limit hit on attempt ${attempt}/${maxRetries}, waiting ${backoffMs}ms before retry...`);\n await new Promise(resolve => setTimeout(resolve, backoffMs));\n continue;\n }\n throw error;\n }\n }\n\n // This should never be reached, but TypeScript requires it\n throw new OpenAIError('Max retries exceeded');\n}\n\n/**\n * Transcribe audio file using OpenAI Whisper API\n */\nexport async function transcribeAudio(\n filePath: string,\n options: TranscriptionOptions = { model: \"whisper-1\" }\n): Promise<Transcription> {\n const logger = options.logger || getLogger();\n let openai: OpenAI | null = null;\n let audioStream: fs.ReadStream | null = null;\n let streamClosed = false;\n\n // Helper function to safely close the stream\n const closeAudioStream = () => {\n if (audioStream && !streamClosed) {\n try {\n // Only call destroy if it exists and the stream isn't already destroyed\n if (typeof audioStream.destroy === 'function' && !audioStream.destroyed) {\n audioStream.destroy();\n }\n streamClosed = true;\n logger.debug('Audio stream closed successfully');\n } catch (streamErr) {\n logger.debug('Failed to destroy audio read stream: %s', (streamErr as Error).message);\n streamClosed = true; // Mark as closed even if destroy failed\n }\n }\n };\n\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n openai = new OpenAI({\n apiKey: apiKey,\n });\n\n logger.debug('Transcribing audio file: %s', filePath);\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile) && options.storage) {\n const requestData = {\n model: options.model || \"whisper-1\",\n file: filePath, // Can't serialize the stream, so just save the file path\n response_format: \"json\",\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(requestData, null, 2));\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n audioStream = fs.createReadStream(filePath);\n\n // Set up error handler for the stream to ensure cleanup on stream errors\n // Only add handler if the stream has the 'on' method (real streams)\n if (audioStream && typeof audioStream.on === 'function') {\n audioStream.on('error', (streamError) => {\n logger.error('Audio stream error: %s', streamError.message);\n closeAudioStream();\n });\n }\n\n let transcription;\n try {\n transcription = await openai.audio.transcriptions.create({\n model: options.model || \"whisper-1\",\n file: audioStream,\n response_format: \"json\",\n });\n // Close the stream immediately after successful API call to prevent race conditions\n closeAudioStream();\n } catch (apiError) {\n // Close the stream immediately if the API call fails\n closeAudioStream();\n throw apiError;\n }\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile) && options.storage) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(transcription, null, 2));\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const response = transcription;\n if (!response) {\n throw new OpenAIError('No transcription received from OpenAI');\n }\n\n logger.debug('Received transcription from OpenAI: %s', response);\n\n // Archive the audio file and transcription if callback provided\n if (options.onArchive) {\n try {\n await options.onArchive(filePath, response.text);\n } catch (archiveError: any) {\n // Don't fail the transcription if archiving fails, just log the error\n logger.warn('Failed to archive audio file: %s', archiveError.message);\n }\n }\n\n return response;\n\n } catch (error: any) {\n logger.error('Error transcribing audio file: %s %s', error.message, error.stack);\n throw new OpenAIError(`Failed to transcribe audio: ${error.message}`);\n } finally {\n // Ensure the audio stream is properly closed to release file handles\n closeAudioStream();\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n\n","#!/usr/bin/env node\nimport { getLogger } from './logger';\nimport type { Logger, Choice, InteractiveOptions } from './types';\nimport { spawnSync } from 'child_process';\nimport * as path from 'path';\nimport * as os from 'os';\nimport * as fs from 'fs/promises';\n\n/**\n * Get user choice interactively from terminal input\n * @param prompt The prompt message to display\n * @param choices Array of available choices\n * @param options Additional options for customizing behavior\n * @returns Promise resolving to the selected choice key\n */\nexport async function getUserChoice(\n prompt: string,\n choices: Choice[],\n options: InteractiveOptions = {}\n): Promise<string> {\n const logger = options.logger || getLogger();\n\n logger.info(prompt);\n choices.forEach(choice => {\n logger.info(` [${choice.key}] ${choice.label}`);\n });\n logger.info('');\n\n // Check if stdin is a TTY (terminal) or piped\n if (!process.stdin.isTTY) {\n logger.error('⚠️ STDIN is piped but interactive mode is enabled');\n logger.error(' Interactive prompts cannot be used when input is piped');\n logger.error(' Solutions:');\n logger.error(' • Use terminal input instead of piping');\n\n // Add any additional suggestions\n if (options.nonTtyErrorSuggestions) {\n options.nonTtyErrorSuggestions.forEach(suggestion => {\n logger.error(` • ${suggestion}`);\n });\n }\n\n return 's'; // Default to skip\n }\n\n return new Promise((resolve, reject) => {\n let isResolved = false;\n let dataHandler: ((key: Buffer) => void) | null = null;\n let errorHandler: ((error: Error) => void) | null = null;\n\n const cleanup = () => {\n if (dataHandler) {\n process.stdin.removeListener('data', dataHandler);\n }\n if (errorHandler) {\n process.stdin.removeListener('error', errorHandler);\n }\n\n try {\n if (process.stdin.setRawMode) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n // Detach stdin again now that we're done\n if (typeof process.stdin.unref === 'function') {\n process.stdin.unref();\n }\n } catch {\n // Ignore cleanup errors\n }\n };\n\n const safeResolve = (value: string) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n resolve(value);\n }\n };\n\n const safeReject = (error: Error) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n reject(error);\n }\n };\n\n try {\n // Ensure stdin is referenced so the process doesn't exit while waiting for input\n if (typeof process.stdin.ref === 'function') {\n process.stdin.ref();\n }\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n dataHandler = (key: Buffer) => {\n try {\n const keyStr = key.toString().toLowerCase();\n const choice = choices.find(c => c.key === keyStr);\n if (choice) {\n logger.info(`Selected: ${choice.label}\\n`);\n safeResolve(choice.key);\n }\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Unknown error processing input'));\n }\n };\n\n errorHandler = (error: Error) => {\n safeReject(error);\n };\n\n process.stdin.on('data', dataHandler);\n process.stdin.on('error', errorHandler);\n\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Failed to setup input handlers'));\n }\n });\n}\n\n/**\n * Secure temporary file handle that prevents TOCTOU vulnerabilities\n */\nexport class SecureTempFile {\n private fd: fs.FileHandle | null = null;\n private filePath: string;\n private isCleanedUp = false;\n private logger: Logger;\n\n private constructor(filePath: string, fd: fs.FileHandle, logger?: Logger) {\n this.filePath = filePath;\n this.fd = fd;\n this.logger = logger || getLogger();\n }\n\n /**\n * Create a secure temporary file with proper permissions and atomic operations\n * @param prefix Prefix for the temporary filename\n * @param extension File extension (e.g., '.txt', '.md')\n * @param logger Optional logger instance\n * @returns Promise resolving to SecureTempFile instance\n */\n static async create(prefix: string = 'ai-service', extension: string = '.txt', logger?: Logger): Promise<SecureTempFile> {\n const tmpDir = os.tmpdir();\n const log = logger || getLogger();\n\n // Ensure temp directory exists and is writable (skip check in test environments)\n if (!process.env.VITEST) {\n try {\n await fs.access(tmpDir, fs.constants.W_OK);\n } catch (error: any) {\n // Try to create the directory if it doesn't exist\n try {\n await fs.mkdir(tmpDir, { recursive: true, mode: 0o700 });\n } catch (mkdirError: any) {\n throw new Error(`Temp directory not writable: ${tmpDir} - ${error.message}. Failed to create: ${mkdirError.message}`);\n }\n }\n }\n\n const tmpFilePath = path.join(tmpDir, `${prefix}_${Date.now()}_${Math.random().toString(36).substring(7)}${extension}`);\n\n // Create file with exclusive access and restrictive permissions (owner read/write only)\n // Using 'wx' flag ensures exclusive creation (fails if file exists)\n let fd: fs.FileHandle;\n try {\n fd = await fs.open(tmpFilePath, 'wx', 0o600);\n } catch (error: any) {\n if (error.code === 'EEXIST') {\n // Highly unlikely with timestamp + random suffix, but handle it\n throw new Error(`Temporary file already exists: ${tmpFilePath}`);\n }\n throw new Error(`Failed to create temporary file: ${error.message}`);\n }\n\n return new SecureTempFile(tmpFilePath, fd, log);\n }\n\n /**\n * Get the file path (use with caution in external commands)\n */\n get path(): string {\n if (this.isCleanedUp) {\n throw new Error('Temp file has been cleaned up');\n }\n return this.filePath;\n }\n\n /**\n * Write content to the temporary file\n */\n async writeContent(content: string): Promise<void> {\n if (!this.fd || this.isCleanedUp) {\n throw new Error('Temp file is not available for writing');\n }\n await this.fd.writeFile(content, 'utf8');\n }\n\n /**\n * Read content from the temporary file\n */\n async readContent(): Promise<string> {\n if (!this.fd || this.isCleanedUp) {\n throw new Error('Temp file is not available for reading');\n }\n const content = await this.fd.readFile('utf8');\n return content;\n }\n\n /**\n * Close the file handle\n */\n async close(): Promise<void> {\n if (this.fd && !this.isCleanedUp) {\n await this.fd.close();\n this.fd = null;\n }\n }\n\n /**\n * Securely cleanup the temporary file - prevents TOCTOU by using file descriptor\n */\n async cleanup(): Promise<void> {\n if (this.isCleanedUp) {\n return; // Already cleaned up\n }\n\n try {\n // Close file descriptor first if still open\n if (this.fd) {\n await this.fd.close();\n this.fd = null;\n }\n\n // Now safely remove the file\n // Use fs.unlink which is safer than checking existence first\n await fs.unlink(this.filePath);\n } catch (error: any) {\n // Only ignore ENOENT (file not found) errors\n if (error.code !== 'ENOENT') {\n this.logger.warn(`Failed to cleanup temp file ${this.filePath}: ${error.message}`);\n // Don't throw here to avoid masking main operations\n }\n } finally {\n this.isCleanedUp = true;\n }\n }\n}\n\n/**\n * Create a secure temporary file for editing with proper permissions\n * @param prefix Prefix for the temporary filename\n * @param extension File extension (e.g., '.txt', '.md')\n * @param logger Optional logger instance\n * @returns Promise resolving to the temporary file path\n * @deprecated Use SecureTempFile.create() for better security\n */\nexport async function createSecureTempFile(prefix: string = 'ai-service', extension: string = '.txt', logger?: Logger): Promise<string> {\n const secureTempFile = await SecureTempFile.create(prefix, extension, logger);\n await secureTempFile.close();\n return secureTempFile.path;\n}\n\n/**\n * Clean up a temporary file\n * @param filePath Path to the temporary file to clean up\n * @param logger Optional logger instance\n * @deprecated Use SecureTempFile.cleanup() for better security\n */\nexport async function cleanupTempFile(filePath: string, logger?: Logger): Promise<void> {\n const log = logger || getLogger();\n try {\n await fs.unlink(filePath);\n } catch (error: any) {\n // Only ignore ENOENT (file not found) errors\n if (error.code !== 'ENOENT') {\n log.warn(`Failed to cleanup temp file ${filePath}: ${error.message}`);\n }\n }\n}\n\nexport interface EditorResult {\n content: string;\n wasEdited: boolean;\n}\n\n/**\n * Open content in user's editor for editing\n * @param content Initial content to edit\n * @param templateLines Additional template lines to include (will be filtered out)\n * @param fileExtension File extension for syntax highlighting\n * @param editor Editor command to use (defaults to EDITOR/VISUAL env var or 'vi')\n * @param logger Optional logger instance\n * @returns Promise resolving to the edited content\n */\nexport async function editContentInEditor(\n content: string,\n templateLines: string[] = [],\n fileExtension: string = '.txt',\n editor?: string,\n logger?: Logger\n): Promise<EditorResult> {\n const log = logger || getLogger();\n const editorCmd = editor || process.env.EDITOR || process.env.VISUAL || 'vi';\n\n const secureTempFile = await SecureTempFile.create('ai-service_edit', fileExtension, log);\n try {\n // Build template content\n const templateContent = [\n ...templateLines,\n ...(templateLines.length > 0 ? [''] : []), // Add separator if we have template lines\n content,\n '',\n ].join('\\n');\n\n await secureTempFile.writeContent(templateContent);\n await secureTempFile.close(); // Close before external editor access\n\n log.info(`📝 Opening ${editorCmd} to edit content...`);\n\n // Open the editor synchronously\n const result = spawnSync(editorCmd, [secureTempFile.path], { stdio: 'inherit' });\n\n if (result.error) {\n throw new Error(`Failed to launch editor '${editorCmd}': ${result.error.message}`);\n }\n\n // Read the file back in, stripping comment lines\n const fileContent = (await fs.readFile(secureTempFile.path, 'utf8'))\n .split('\\n')\n .filter(line => !line.trim().startsWith('#'))\n .join('\\n')\n .trim();\n\n if (!fileContent) {\n throw new Error('Content is empty after editing');\n }\n\n log.info('✅ Content updated successfully');\n\n return {\n content: fileContent,\n wasEdited: fileContent !== content.trim()\n };\n\n } finally {\n // Always clean up the temp file securely\n await secureTempFile.cleanup();\n }\n}\n\n/**\n * Standard choices for interactive feedback loops\n */\nexport const STANDARD_CHOICES = {\n CONFIRM: { key: 'c', label: 'Confirm and proceed' },\n EDIT: { key: 'e', label: 'Edit in editor' },\n SKIP: { key: 's', label: 'Skip and abort' },\n IMPROVE: { key: 'i', label: 'Improve with LLM feedback' }\n} as const;\n\n/**\n * Get text input from the user\n * @param prompt The prompt message to display\n * @param options Additional options for customizing behavior\n * @returns Promise resolving to the user's text input\n */\nexport async function getUserTextInput(\n prompt: string,\n options: InteractiveOptions = {}\n): Promise<string> {\n const logger = options.logger || getLogger();\n\n // Check if stdin is a TTY (terminal) or piped\n if (!process.stdin.isTTY) {\n logger.error('⚠️ STDIN is piped but interactive text input is required');\n logger.error(' Interactive text input cannot be used when input is piped');\n logger.error(' Solutions:');\n logger.error(' • Use terminal input instead of piping');\n\n // Add any additional suggestions\n if (options.nonTtyErrorSuggestions) {\n options.nonTtyErrorSuggestions.forEach(suggestion => {\n logger.error(` • ${suggestion}`);\n });\n }\n\n throw new Error('Interactive text input requires a terminal');\n }\n\n logger.info(prompt);\n logger.info('(Press Enter when done, or type Ctrl+C to cancel)');\n logger.info('');\n\n return new Promise((resolve, reject) => {\n let inputBuffer = '';\n let isResolved = false;\n let dataHandler: ((chunk: string) => void) | null = null;\n let errorHandler: ((error: Error) => void) | null = null;\n\n const cleanup = () => {\n if (dataHandler) {\n process.stdin.removeListener('data', dataHandler);\n }\n if (errorHandler) {\n process.stdin.removeListener('error', errorHandler);\n }\n\n try {\n process.stdin.pause();\n // Detach stdin again now that we're done\n if (typeof process.stdin.unref === 'function') {\n process.stdin.unref();\n }\n } catch {\n // Ignore cleanup errors\n }\n };\n\n const safeResolve = (value: string) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n resolve(value);\n }\n };\n\n const safeReject = (error: Error) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n reject(error);\n }\n };\n\n try {\n // Ensure stdin is referenced so the process doesn't exit while waiting for input\n if (typeof process.stdin.ref === 'function') {\n process.stdin.ref();\n }\n\n process.stdin.setEncoding('utf8');\n process.stdin.resume();\n\n dataHandler = (chunk: string) => {\n try {\n inputBuffer += chunk;\n\n // Check if user pressed Enter (newline character)\n if (inputBuffer.includes('\\n')) {\n const userInput = inputBuffer.replace(/\\n$/, '').trim();\n\n if (userInput === '') {\n logger.warn('Empty input received. Please provide feedback text.');\n safeReject(new Error('Empty input received'));\n } else {\n logger.info(`✅ Received feedback: \"${userInput}\"\\n`);\n safeResolve(userInput);\n }\n }\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Unknown error processing input'));\n }\n };\n\n errorHandler = (error: Error) => {\n safeReject(error);\n };\n\n process.stdin.on('data', dataHandler);\n process.stdin.on('error', errorHandler);\n\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Failed to setup input handlers'));\n }\n });\n}\n\n/**\n * Get LLM improvement feedback from the user using the editor\n * @param contentType Type of content being improved (e.g., 'commit message', 'release notes')\n * @param currentContent The current content to be improved\n * @param editor Optional editor command\n * @param logger Optional logger instance\n * @returns Promise resolving to the user's feedback text\n */\nexport async function getLLMFeedbackInEditor(\n contentType: string,\n currentContent: string,\n editor?: string,\n logger?: Logger\n): Promise<string> {\n const templateLines = [\n '# Provide Your Instructions and Guidance for a Revision Here',\n '#',\n '# Type your guidance above this line. Be specific about what you want changed,',\n '# added, or improved. You can also edit the original content below directly',\n '# to provide examples or show desired changes.',\n '#',\n '# Lines starting with \"#\" will be ignored.',\n '',\n '### YOUR FEEDBACK AND GUIDANCE:',\n '',\n '# (Type your improvement instructions here)',\n '',\n `### ORIGINAL ${contentType.toUpperCase()}:`,\n ''\n ];\n\n const result = await editContentInEditor(\n currentContent,\n templateLines,\n '.md',\n editor,\n logger\n );\n\n // Extract just the feedback section (everything before the original content)\n const lines = result.content.split('\\n');\n const originalSectionIndex = lines.findIndex(line =>\n line.trim().toLowerCase().startsWith('### original')\n );\n\n let feedback: string;\n if (originalSectionIndex >= 0) {\n // Take everything before the \"### ORIGINAL\" section\n feedback = lines.slice(0, originalSectionIndex).join('\\n').trim();\n } else {\n // If no original section found, take everything\n feedback = result.content.trim();\n }\n\n // Remove the feedback header if it exists\n feedback = feedback.replace(/^### YOUR FEEDBACK AND GUIDANCE:\\s*/i, '').trim();\n\n if (!feedback) {\n throw new Error('No feedback provided. Please provide improvement instructions.');\n }\n\n return feedback;\n}\n\n/**\n * Check if interactive mode is available (TTY check)\n * @param errorMessage Custom error message to throw if TTY not available\n * @param logger Optional logger instance\n * @throws Error if not in TTY environment\n */\nexport function requireTTY(errorMessage: string = 'Interactive mode requires a terminal. Use --dry-run instead.', logger?: Logger): void {\n const log = logger || getLogger();\n if (!process.stdin.isTTY) {\n log.error('❌ Interactive mode requires a terminal (TTY)');\n log.error(' Solutions:');\n log.error(' • Run without piping input');\n log.error(' • Use --dry-run to see the generated content');\n throw new Error(errorMessage);\n }\n}\n\n","/**\n * RiotPrompt Template Registry\n *\n * This module registers reusable prompt templates that can be used\n * across different prompt builders. Templates define common patterns\n * for personas, instructions, and structure.\n */\n\nimport { registerTemplates, type TemplateConfig } from '@riotprompt/riotprompt';\n\n/**\n * Initialize and register all prompt templates.\n * This should be called once during application initialization.\n */\nexport const initializeTemplates = (): void => {\n const templates: Record<string, TemplateConfig> = {\n // Commit message generation template\n 'commit': {\n persona: { path: 'personas/you.md' },\n instructions: [{ path: 'instructions/commit.md' }]\n },\n\n // Release notes generation template\n 'release': {\n persona: { path: 'personas/releaser.md' },\n instructions: [{ path: 'instructions/release.md' }]\n },\n\n // Code review template\n 'review': {\n persona: { path: 'personas/you.md' },\n instructions: [{ path: 'instructions/review.md' }]\n }\n };\n\n registerTemplates(templates);\n};\n\n/**\n * Template names for type-safe template references\n */\nexport const TemplateNames = {\n COMMIT: 'commit',\n RELEASE: 'release',\n REVIEW: 'review'\n} as const;\n\nexport type TemplateName = typeof TemplateNames[keyof typeof TemplateNames];\n\n","import { Prompt, cook, type ContentItem } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { TemplateNames } from './templates';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Types for the commit prompt\nexport type CommitContent = {\n diffContent: string;\n userDirection?: string;\n isFileContent?: boolean; // Flag to indicate if diffContent is actually file content\n githubIssuesContext?: string; // GitHub issues related to current version/milestone\n};\n\nexport type CommitContext = {\n logContext?: string;\n context?: string;\n directories?: string[];\n};\n\nexport type CommitConfig = {\n overridePaths?: string[];\n overrides?: boolean;\n}\n\n/**\n * Build a commit prompt using RiotPrompt Recipes.\n *\n * This prompt is configured to generate multiline commit messages by default,\n * with separate lines/bullet points for different groups of changes rather\n * than squeezing everything into single lines.\n *\n * @param config The configuration for overrides\n * @param content Mandatory content inputs (e.g. diff)\n * @param ctx Optional contextual inputs configured by the user\n */\nexport const createCommitPrompt = async (\n { overridePaths: _overridePaths, overrides: _overrides }: CommitConfig,\n { diffContent, userDirection, isFileContent, githubIssuesContext }: CommitContent,\n { logContext, context, directories }: CommitContext = {}\n): Promise<Prompt> => {\n const basePath = __dirname;\n\n // Build content items for the prompt\n const contentItems: ContentItem[] = [];\n const contextItems: ContentItem[] = [];\n\n // Developer Note: Direction is injected first as the highest-priority prompt input\n // This ensures user guidance takes precedence over other context sources like\n // GitHub issues or commit history.\n if (userDirection) {\n contentItems.push({ content: userDirection, title: 'User Direction' });\n }\n if (diffContent) {\n const contentTitle = isFileContent ? 'Project Files' : 'Diff';\n contentItems.push({ content: diffContent, title: contentTitle });\n }\n if (githubIssuesContext) {\n contentItems.push({ content: githubIssuesContext, title: 'Recent GitHub Issues' });\n }\n\n // IMPORTANT: Log context provides background but can contaminate output if too large.\n // LLMs tend to pattern-match against recent commits instead of describing the actual diff.\n // Keep messageLimit low (3-5) to minimize contamination.\n if (logContext) {\n contextItems.push({ content: logContext, title: 'Log Context' });\n }\n if (context) {\n contextItems.push({ content: context, title: 'User Context' });\n }\n if (directories && directories.length > 0) {\n contextItems.push({ directories, title: 'Directories' });\n }\n\n // Use declarative cook() API with registered template\n return cook({\n basePath,\n template: TemplateNames.COMMIT,\n overridePaths: _overridePaths ?? [],\n overrides: _overrides ?? true,\n content: contentItems,\n context: contextItems\n });\n};\n\n","import { Prompt, cook, type ContentItem } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { TemplateNames } from './templates';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Types for the release prompt\nexport type ReleaseConfig = {\n overridePaths?: string[];\n overrides?: boolean;\n}\n\nexport type ReleaseContent = {\n releaseFocus?: string;\n logContent: string;\n diffContent: string;\n milestoneIssues?: string;\n};\n\nexport type ReleaseContext = {\n context?: string;\n directories?: string[];\n};\n\nexport type ReleasePromptResult = {\n prompt: Prompt;\n maxTokens: number;\n isLargeRelease: boolean;\n};\n\n/**\n * Analyzes release content to determine if it's a large release\n * and calculates appropriate token limits\n */\nconst analyzeReleaseSize = (logContent: string, diffContent?: string, milestoneIssues?: string): { isLarge: boolean; maxTokens: number } => {\n const logLines = logContent.split('\\n').length;\n const diffLines = diffContent ? diffContent.split('\\n').length : 0;\n const milestoneLines = milestoneIssues ? milestoneIssues.split('\\n').length : 0;\n const totalContentLength = logContent.length + (diffContent?.length || 0) + (milestoneIssues?.length || 0);\n\n // Consider it a large release if:\n // - More than 20 commits (log lines typically ~3-5 per commit)\n // - More than 500 diff lines\n // - Milestone issues present (indicates significant work)\n // - Total content length > 50KB\n const isLarge = logLines > 60 || diffLines > 500 || milestoneLines > 50 || totalContentLength > 50000;\n\n if (isLarge) {\n // For large releases, significantly increase token limit\n return { isLarge: true, maxTokens: 25000 };\n } else {\n // Standard token limit for normal releases\n return { isLarge: false, maxTokens: 10000 };\n }\n};\n\n/**\n * Build a release prompt using RiotPrompt Recipes.\n */\nexport const createReleasePrompt = async (\n { overrides: _overrides, overridePaths: _overridePaths }: ReleaseConfig,\n { releaseFocus, logContent, diffContent, milestoneIssues }: ReleaseContent,\n { context, directories }: ReleaseContext = {}\n): Promise<ReleasePromptResult> => {\n const basePath = __dirname;\n\n // Analyze release size to determine token requirements\n const { isLarge: isLargeRelease, maxTokens } = analyzeReleaseSize(logContent, diffContent, milestoneIssues);\n\n // Build content items for the prompt\n const contentItems: ContentItem[] = [];\n const contextItems: ContentItem[] = [];\n\n if (diffContent) {\n contentItems.push({ content: diffContent, title: 'Diff' });\n }\n if (logContent) {\n contentItems.push({ content: logContent, title: 'Log Context' });\n }\n if (milestoneIssues) {\n contentItems.push({ content: milestoneIssues, title: 'Resolved Issues from Milestone' });\n }\n if (releaseFocus) {\n contentItems.push({ content: releaseFocus, title: 'Release Focus' });\n }\n\n // Add release size context to help guide the AI\n if (isLargeRelease) {\n contextItems.push({\n content: `This appears to be a LARGE RELEASE with significant changes. Please provide comprehensive, detailed release notes that thoroughly document all major changes, improvements, and fixes. Don't summarize - dive deep into the details.`,\n title: 'Release Size Context'\n });\n }\n\n if (context) {\n contextItems.push({ content: context, title: 'User Context' });\n }\n if (directories && directories.length > 0) {\n contextItems.push({ directories, title: 'Directories' });\n }\n\n // Use declarative cook() API with registered template\n const prompt = await cook({\n basePath,\n template: TemplateNames.RELEASE,\n overridePaths: _overridePaths ?? [],\n overrides: _overrides ?? true,\n content: contentItems,\n context: contextItems\n });\n\n return {\n prompt,\n maxTokens,\n isLargeRelease\n };\n};\n\n","import { Prompt, cook, type ContentItem } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { TemplateNames } from './templates';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport type ReviewConfig = {\n overridePaths?: string[];\n overrides?: boolean;\n}\n\nexport type ReviewContent = {\n notes: string;\n};\n\nexport type ReviewContext = {\n logContext?: string;\n diffContext?: string;\n releaseNotesContext?: string;\n issuesContext?: string;\n context?: string;\n directories?: string[];\n};\n\n/**\n * Build a review prompt using RiotPrompt Recipes.\n */\nexport const createReviewPrompt = async (\n { overridePaths: _overridePaths, overrides: _overrides }: ReviewConfig,\n { notes }: ReviewContent,\n { logContext, diffContext, releaseNotesContext, issuesContext, context, directories }: ReviewContext = {}\n): Promise<Prompt> => {\n const basePath = __dirname;\n\n // Build content items for the prompt\n const contentItems: ContentItem[] = [];\n const contextItems: ContentItem[] = [];\n\n if (notes) {\n contentItems.push({ content: notes, title: 'Review Notes' });\n }\n\n if (logContext) {\n contextItems.push({ content: logContext, title: 'Log Context' });\n }\n if (diffContext) {\n contextItems.push({ content: diffContext, title: 'Diff Context' });\n }\n if (releaseNotesContext) {\n contextItems.push({ content: releaseNotesContext, title: 'Release Notes Context' });\n }\n if (issuesContext) {\n contextItems.push({ content: issuesContext, title: 'Issues Context' });\n }\n if (context) {\n contextItems.push({ content: context, title: 'User Context' });\n }\n if (directories && directories.length > 0) {\n contextItems.push({ directories, title: 'Directories' });\n }\n\n // Use declarative cook() API with registered template\n return cook({\n basePath,\n template: TemplateNames.REVIEW,\n overridePaths: _overridePaths ?? [],\n overrides: _overrides ?? true,\n content: contentItems,\n context: contextItems\n });\n};\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { createCompletionWithRetry } from '../ai';\nimport type { ToolRegistry } from '../tools/registry';\nimport type { ToolResult } from '../tools/types';\nimport { ConversationBuilder, type Model } from '@riotprompt/riotprompt';\n\nexport interface AgenticConfig {\n messages: ChatCompletionMessageParam[];\n tools: ToolRegistry;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n debugRequestFile?: string;\n debugResponseFile?: string;\n storage?: any;\n logger?: any;\n openaiReasoning?: 'low' | 'medium' | 'high';\n // Token budget configuration\n tokenBudget?: {\n max: number;\n reserveForResponse?: number;\n strategy?: 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n onBudgetExceeded?: 'compress' | 'error' | 'warn' | 'truncate';\n };\n}\n\nexport interface ToolExecutionMetric {\n name: string;\n success: boolean;\n duration: number;\n error?: string;\n iteration: number;\n timestamp: string;\n}\n\nexport interface AgenticResult {\n finalMessage: string;\n iterations: number;\n toolCallsExecuted: number;\n conversationHistory: ChatCompletionMessageParam[];\n toolMetrics: ToolExecutionMetric[];\n}\n\n/**\n * Execute an agentic loop where the LLM can call tools to gather information\n */\nexport class AgenticExecutor {\n private logger?: any;\n private toolMetrics: ToolExecutionMetric[] = [];\n\n constructor(logger?: any) {\n this.logger = logger;\n }\n\n /**\n * Run the agentic loop with ConversationBuilder\n */\n async run(config: AgenticConfig): Promise<AgenticResult> {\n const {\n messages: initialMessages,\n tools,\n model = 'gpt-4o',\n maxIterations = 10,\n debug = false,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning = false,\n tokenBudget,\n } = config;\n\n // Create ConversationBuilder for better state management\n const conversation = ConversationBuilder.create({ model: model as Model }, logger);\n\n // Add initial messages to conversation\n for (const msg of initialMessages) {\n if (msg.role === 'system') {\n conversation.addSystemMessage(msg.content as string);\n } else if (msg.role === 'user') {\n conversation.addUserMessage(msg.content as string);\n }\n }\n\n // Configure token budget if provided\n if (tokenBudget) {\n this.log('Configuring token budget', tokenBudget);\n conversation.withTokenBudget({\n max: tokenBudget.max,\n reserveForResponse: tokenBudget.reserveForResponse || 4000,\n strategy: tokenBudget.strategy || 'fifo',\n onBudgetExceeded: tokenBudget.onBudgetExceeded || 'compress'\n });\n }\n\n let iterations = 0;\n let toolCallsExecuted = 0;\n\n this.log('Starting agentic loop with ConversationBuilder', { maxIterations, toolCount: tools.count() });\n\n while (iterations < maxIterations) {\n iterations++;\n this.log(`Iteration ${iterations}/${maxIterations}`);\n\n // Get current messages from conversation\n const messages = conversation.toMessages();\n\n // Call LLM with tools available\n const response = await createCompletionWithRetry(\n messages as ChatCompletionMessageParam[],\n {\n model,\n openaiReasoning: openaiReasoning || undefined,\n debug,\n debugRequestFile: debugRequestFile ? `${debugRequestFile}-iter${iterations}` : undefined,\n debugResponseFile: debugResponseFile ? `${debugResponseFile}-iter${iterations}` : undefined,\n storage,\n logger,\n tools: tools.toOpenAIFormat(),\n }\n );\n\n // When tools are enabled, response is the full message object\n const message = typeof response === 'string' ? { role: 'assistant', content: response } : response;\n\n // Check if there are tool calls in the response\n const toolCalls = message.tool_calls || [];\n\n if (toolCalls.length === 0) {\n // No tool calls, agent is done\n const finalContent = message.content || '';\n this.log('Agent completed without tool calls', { iterations, toolCallsExecuted });\n conversation.addAssistantMessage(finalContent);\n\n return {\n finalMessage: finalContent,\n iterations,\n toolCallsExecuted,\n conversationHistory: conversation.toMessages() as ChatCompletionMessageParam[],\n toolMetrics: this.toolMetrics,\n };\n }\n\n // Add assistant message with tool calls to conversation\n conversation.addAssistantWithToolCalls(message.content || null, toolCalls as any);\n\n // Execute tool calls\n this.log(`Executing ${toolCalls.length} tool call(s)`);\n\n for (const toolCall of toolCalls) {\n const startTime = Date.now();\n const toolName = toolCall.function.name;\n\n try {\n this.log(`Executing tool: ${toolName}`, toolCall.function.arguments);\n\n // Log to info level so user can see tool execution in real-time\n if (this.logger?.info) {\n this.logger.info(`🔧 Running tool: ${toolName}`);\n }\n\n // Parse arguments with error handling\n let args: any;\n try {\n args = JSON.parse(toolCall.function.arguments);\n } catch (parseError: any) {\n throw new Error(`Failed to parse tool arguments: ${parseError.message}`);\n }\n\n // Execute the tool\n const result = await tools.execute(toolName, args);\n\n const duration = Date.now() - startTime;\n\n // Add tool result to conversation using ConversationBuilder\n const formattedResult = this.formatToolResult({ id: toolCall.id, name: toolName, result });\n conversation.addToolResult(toolCall.id, formattedResult, toolName);\n\n toolCallsExecuted++;\n\n // Track successful execution\n this.toolMetrics.push({\n name: toolName,\n success: true,\n duration,\n iteration: iterations,\n timestamp: new Date().toISOString(),\n });\n\n this.log(`Tool ${toolName} succeeded in ${duration}ms`);\n\n if (this.logger?.info) {\n this.logger.info(`✅ Tool ${toolName} completed (${duration}ms)`);\n }\n } catch (error: any) {\n const duration = Date.now() - startTime;\n const errorMessage = error.message || String(error);\n\n this.log(`Tool ${toolName} failed: ${errorMessage}`);\n\n // Track failed execution\n this.toolMetrics.push({\n name: toolName,\n success: false,\n duration,\n error: errorMessage,\n iteration: iterations,\n timestamp: new Date().toISOString(),\n });\n\n if (this.logger?.warn) {\n this.logger.warn(`❌ Tool ${toolName} failed: ${errorMessage}`);\n }\n\n // Add error result to conversation using ConversationBuilder\n conversation.addToolResult(toolCall.id, `Tool execution failed: ${errorMessage}`, toolName);\n }\n }\n\n this.log(`Completed tool execution`, { toolCallsExecuted });\n }\n\n // Max iterations reached\n this.log('Max iterations reached, forcing completion', { iterations, toolCallsExecuted });\n\n // Make one final call without tools to get a synthesized response\n conversation.addUserMessage('Please provide your final analysis based on your investigation. Do not request any more tools.');\n\n const finalMessages = conversation.toMessages();\n const finalResponse = await createCompletionWithRetry(\n finalMessages as ChatCompletionMessageParam[],\n {\n model,\n openaiReasoning: openaiReasoning || undefined,\n debug,\n storage,\n logger,\n }\n );\n\n conversation.addAssistantMessage(finalResponse);\n\n return {\n finalMessage: finalResponse,\n iterations,\n toolCallsExecuted,\n conversationHistory: conversation.toMessages() as ChatCompletionMessageParam[],\n toolMetrics: this.toolMetrics,\n };\n }\n\n /**\n * Format tool result for inclusion in conversation\n */\n private formatToolResult(result: ToolResult): string {\n if (typeof result.result === 'string') {\n return result.result;\n }\n return JSON.stringify(result.result, null, 2);\n }\n\n /**\n * Log a message if logger is available\n */\n private log(message: string, data?: any): void {\n if (this.logger?.debug) {\n if (data) {\n this.logger.debug(`[AgenticExecutor] ${message}`, data);\n } else {\n this.logger.debug(`[AgenticExecutor] ${message}`);\n }\n }\n }\n}\n\n/**\n * Create and run an agentic executor\n */\nexport async function runAgentic(config: AgenticConfig): Promise<AgenticResult> {\n const executor = new AgenticExecutor(config.logger);\n return await executor.run(config);\n}\n\n","import type { Tool, OpenAITool, ToolContext } from './types';\n\n/**\n * Registry for managing tools available to agentic LLM interactions\n */\nexport class ToolRegistry {\n private tools: Map<string, Tool> = new Map();\n private context?: ToolContext;\n\n constructor(context?: ToolContext) {\n this.context = context;\n }\n\n /**\n * Register a tool in the registry\n */\n register(tool: Tool): void {\n if (this.tools.has(tool.name)) {\n throw new Error(`Tool with name \"${tool.name}\" is already registered`);\n }\n this.tools.set(tool.name, tool);\n }\n\n /**\n * Register multiple tools at once\n */\n registerAll(tools: Tool[]): void {\n for (const tool of tools) {\n this.register(tool);\n }\n }\n\n /**\n * Get a tool by name\n */\n get(name: string): Tool | undefined {\n return this.tools.get(name);\n }\n\n /**\n * Get all registered tools\n */\n getAll(): Tool[] {\n return Array.from(this.tools.values());\n }\n\n /**\n * Check if a tool exists\n */\n has(name: string): boolean {\n return this.tools.has(name);\n }\n\n /**\n * Execute a tool by name with given parameters\n */\n async execute(name: string, params: any): Promise<any> {\n const tool = this.tools.get(name);\n if (!tool) {\n throw new Error(`Tool \"${name}\" not found in registry`);\n }\n\n try {\n return await tool.execute(params, this.context);\n } catch (error: any) {\n throw new Error(`Tool \"${name}\" execution failed: ${error.message}`);\n }\n }\n\n /**\n * Convert tools to OpenAI function calling format\n */\n toOpenAIFormat(): OpenAITool[] {\n return this.getAll().map(tool => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n },\n }));\n }\n\n /**\n * Get tool definitions (without execute functions) for serialization\n */\n getDefinitions(): Array<{ name: string; description: string; parameters: any }> {\n return this.getAll().map(tool => ({\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n }));\n }\n\n /**\n * Clear all registered tools\n */\n clear(): void {\n this.tools.clear();\n }\n\n /**\n * Get count of registered tools\n */\n count(): number {\n return this.tools.size;\n }\n}\n\n/**\n * Create a new tool registry with optional context\n */\nexport function createToolRegistry(context?: ToolContext): ToolRegistry {\n return new ToolRegistry(context);\n}\n\n","import type { Tool, ToolContext } from './types';\nimport { run } from '@eldrforge/git-tools';\nimport * as path from 'path';\n\n/**\n * Create tools for commit message generation\n */\nexport function createCommitTools(): Tool[] {\n return [\n createGetFileHistoryTool(),\n createGetFileContentTool(),\n createSearchCodebaseTool(),\n createGetRelatedTestsTool(),\n createGetFileDependenciesTool(),\n createAnalyzeDiffSectionTool(),\n createGetRecentCommitsTool(),\n createGroupFilesByConcernTool(),\n ];\n}\n\n/**\n * Get git commit history for specific files\n */\nfunction createGetFileHistoryTool(): Tool {\n return {\n name: 'get_file_history',\n description: 'Get git commit history for one or more files to understand their evolution and past changes',\n category: 'Understanding',\n cost: 'cheap',\n examples: [\n {\n scenario: 'Check if file has recent refactoring',\n params: { filePaths: ['src/auth.ts'], limit: 5 },\n expectedResult: 'List of recent commits affecting auth.ts'\n },\n {\n scenario: 'Understand evolution of multiple related files',\n params: { filePaths: ['src/user.ts', 'src/auth.ts'], limit: 10, format: 'detailed' },\n expectedResult: 'Detailed commit history for both files'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Array of file paths to get history for',\n items: { type: 'string', description: 'File path' },\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 10)',\n default: 10,\n },\n format: {\n type: 'string',\n description: 'Output format: \"summary\" for brief or \"detailed\" for full messages',\n enum: ['summary', 'detailed'],\n default: 'summary',\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; limit?: number; format?: 'summary' | 'detailed' }, context?: ToolContext) => {\n const { filePaths, limit = 10, format = 'summary' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Use proper shell quoting to avoid issues with parentheses in format strings\n const formatArg = format === 'detailed' ? '--format=\"%H%n%an (%ae)%n%ad%n%s%n%n%b%n---\"' : '--format=\"%h - %s (%an, %ar)\"';\n const fileArgs = filePaths.join(' ');\n const command = `git log ${formatArg} -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No history found for specified files';\n } catch (error: any) {\n throw new Error(`Failed to get file history: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get the full current content of a file\n */\nfunction createGetFileContentTool(): Tool {\n return {\n name: 'get_file_content',\n description: 'Get the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).',\n category: 'Understanding',\n cost: 'moderate',\n examples: [\n {\n scenario: 'See full class definition for modified method',\n params: { filePath: 'src/services/auth.ts', includeLineNumbers: true },\n expectedResult: 'Complete file content with line numbers'\n },\n {\n scenario: 'Check imports and structure',\n params: { filePath: 'src/utils/helpers.ts' },\n expectedResult: 'Full file content showing imports and exports'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'Path to the file',\n },\n includeLineNumbers: {\n type: 'boolean',\n description: 'Include line numbers in output (default: false)',\n default: false,\n },\n },\n required: ['filePath'],\n },\n execute: async (params: { filePath: string; includeLineNumbers?: boolean }, context?: ToolContext) => {\n const { filePath, includeLineNumbers = false } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n\n if (includeLineNumbers) {\n const lines = content.split('\\n');\n return lines.map((line: string, idx: number) => `${idx + 1}: ${line}`).join('\\n');\n }\n\n return content;\n } catch (error: any) {\n // Handle file not found gracefully - common for deleted files in diffs\n if (error.code === 'ENOENT' || error.message?.includes('ENOENT')) {\n return `File not found: ${filePath}\\n\\nThis file may have been deleted in this release or does not exist in the current working tree. Check the diff to see if this file was removed.`;\n }\n throw new Error(`Failed to read file: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Search for code patterns or identifiers across the codebase\n */\nfunction createSearchCodebaseTool(): Tool {\n return {\n name: 'search_codebase',\n description: 'Search for code patterns, function names, or text across the codebase using git grep',\n category: 'Analysis',\n cost: 'moderate',\n examples: [\n {\n scenario: 'Find all uses of a renamed function',\n params: { query: 'oldFunctionName', fileTypes: ['ts', 'tsx'] },\n expectedResult: 'List of files and lines containing the function'\n },\n {\n scenario: 'Check if pattern exists elsewhere',\n params: { query: 'pattern.*string', contextLines: 3 },\n expectedResult: 'Matching lines with surrounding context'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search pattern (can be plain text or regex)',\n },\n fileTypes: {\n type: 'array',\n description: 'Limit search to specific file extensions (e.g., [\"ts\", \"js\"])',\n items: { type: 'string', description: 'File extension' },\n },\n contextLines: {\n type: 'number',\n description: 'Number of context lines to show around matches (default: 2)',\n default: 2,\n },\n },\n required: ['query'],\n },\n execute: async (params: { query: string; fileTypes?: string[]; contextLines?: number }, context?: ToolContext) => {\n const { query, fileTypes, contextLines = 2 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Build command with proper git grep syntax: pattern comes BEFORE pathspec\n let command = `git grep -n -C ${contextLines} \"${query}\"`;\n\n if (fileTypes && fileTypes.length > 0) {\n // Add glob patterns for each file type with proper quoting\n const patterns = fileTypes.map(ext => `'*.${ext}'`).join(' ');\n command += ` -- ${patterns}`;\n }\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No matches found';\n } catch (error: any) {\n // git grep returns exit code 1 when no matches found\n if (error.message.includes('exit code 1') || error.stderr?.includes('did not match any file')) {\n return 'No matches found';\n }\n throw new Error(`Search failed: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Find test files related to changed production files\n */\nfunction createGetRelatedTestsTool(): Tool {\n return {\n name: 'get_related_tests',\n description: 'Find test files related to production files to understand what the code is supposed to do',\n category: 'Understanding',\n cost: 'cheap',\n examples: [{ scenario: 'Find tests for modified service', params: { filePaths: ['src/services/auth.ts'] }, expectedResult: 'List of related test files' }],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Production file paths',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n const relatedTests: string[] = [];\n\n for (const filePath of filePaths) {\n // Common test patterns\n const patterns = [\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.test.$1'),\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.spec.$1'),\n filePath.replace('/src/', '/tests/').replace('/lib/', '/tests/'),\n path.join('tests', filePath),\n path.join('test', filePath),\n ];\n\n for (const pattern of patterns) {\n try {\n await storage.readFile(pattern, 'utf-8');\n relatedTests.push(pattern);\n } catch {\n // File doesn't exist, continue\n }\n }\n }\n\n if (relatedTests.length === 0) {\n return 'No related test files found';\n }\n\n return `Found related test files:\\n${relatedTests.join('\\n')}`;\n },\n };\n}\n\n/**\n * Understand what files import/depend on changed files\n */\nfunction createGetFileDependenciesTool(): Tool {\n return {\n name: 'get_file_dependencies',\n description: 'Find which files import or depend on the changed files to assess change impact',\n category: 'Analysis',\n cost: 'moderate',\n examples: [{ scenario: 'Check impact of util function change', params: { filePaths: ['src/utils/format.ts'] }, expectedResult: 'Files that import format.ts' }],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to analyze dependencies for',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const results: string[] = [];\n\n for (const filePath of filePaths) {\n // Extract filename without extension for searching imports\n const fileName = path.basename(filePath, path.extname(filePath));\n\n // Search for imports of this file\n const searchPatterns = [\n `from.*['\"].*${fileName}`,\n `import.*['\"].*${fileName}`,\n `require\\\\(['\"].*${fileName}`,\n ];\n\n for (const pattern of searchPatterns) {\n try {\n const command = `git grep -l \"${pattern}\"`;\n const output = await run(command, { cwd: workingDir });\n if (output.stdout) {\n results.push(`Files importing ${filePath}:\\n${output.stdout}`);\n break; // Found matches, no need to try other patterns\n }\n } catch {\n // No matches or error, continue\n }\n }\n }\n\n return results.length > 0\n ? results.join('\\n\\n')\n : 'No files found that import the specified files';\n },\n };\n}\n\n/**\n * Get detailed analysis of specific lines in a diff\n */\nfunction createAnalyzeDiffSectionTool(): Tool {\n return {\n name: 'analyze_diff_section',\n description: 'Get expanded context around specific lines in a file to better understand changes',\n category: 'Understanding',\n cost: 'cheap',\n examples: [{ scenario: 'See context around confusing change', params: { filePath: 'src/auth.ts', startLine: 45, endLine: 52, contextLines: 15 }, expectedResult: 'Expanded code section with context' }],\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'File containing the section to analyze',\n },\n startLine: {\n type: 'number',\n description: 'Starting line number',\n },\n endLine: {\n type: 'number',\n description: 'Ending line number',\n },\n contextLines: {\n type: 'number',\n description: 'Number of additional context lines to show before and after (default: 10)',\n default: 10,\n },\n },\n required: ['filePath', 'startLine', 'endLine'],\n },\n execute: async (params: { filePath: string; startLine: number; endLine: number; contextLines?: number }, context?: ToolContext) => {\n const { filePath, startLine, endLine, contextLines = 10 } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n const actualStart = Math.max(0, startLine - contextLines - 1);\n const actualEnd = Math.min(lines.length, endLine + contextLines);\n\n const section = lines.slice(actualStart, actualEnd)\n .map((line: string, idx: number) => `${actualStart + idx + 1}: ${line}`)\n .join('\\n');\n\n return `Lines ${actualStart + 1}-${actualEnd} from ${filePath}:\\n\\n${section}`;\n } catch (error: any) {\n throw new Error(`Failed to analyze diff section: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get recent commits that touched the same files\n */\nfunction createGetRecentCommitsTool(): Tool {\n return {\n name: 'get_recent_commits',\n description: 'Get recent commits that modified the same files to understand recent work in this area',\n category: 'Understanding',\n cost: 'cheap',\n examples: [{ scenario: 'Check for duplicate commit messages', params: { filePaths: ['src/auth.ts'], since: '1 week ago', limit: 5 }, expectedResult: 'Recent commits to auth.ts' }],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to check for recent commits',\n items: { type: 'string', description: 'File path' },\n },\n since: {\n type: 'string',\n description: 'Time period to look back (e.g., \"1 week ago\", \"2 days ago\")',\n default: '1 week ago',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 5)',\n default: 5,\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; since?: string; limit?: number }, context?: ToolContext) => {\n const { filePaths, since = '1 week ago', limit = 5 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const fileArgs = filePaths.join(' ');\n const command = `git log --format=\"%h - %s (%an, %ar)\" --since=\"${since}\" -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || `No commits found in the specified time period (${since})`;\n } catch (error: any) {\n throw new Error(`Failed to get recent commits: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Analyze changed files and suggest logical groupings\n */\nfunction createGroupFilesByConcernTool(): Tool {\n return {\n name: 'group_files_by_concern',\n description: 'Analyze changed files and suggest logical groupings that might represent separate commits',\n category: 'Organization',\n cost: 'cheap',\n examples: [\n {\n scenario: 'Check if multiple unrelated changes should be split',\n params: { filePaths: ['src/auth.ts', 'README.md', 'tests/auth.test.ts', 'package.json'] },\n expectedResult: 'Files grouped by concern with split suggestions'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'All changed files to analyze',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }) => {\n const { filePaths } = params;\n\n // Group files by directory and type\n const groups: Record<string, string[]> = {};\n\n for (const filePath of filePaths) {\n const dir = path.dirname(filePath);\n const ext = path.extname(filePath);\n const basename = path.basename(filePath, ext);\n\n // Determine category\n let category = 'other';\n\n if (basename.includes('.test') || basename.includes('.spec') || dir.includes('test')) {\n category = 'tests';\n } else if (filePath.includes('package.json') || filePath.includes('package-lock.json')) {\n category = 'dependencies';\n } else if (ext === '.md' || basename === 'README') {\n category = 'documentation';\n } else if (dir.includes('src') || dir.includes('lib')) {\n // Group by module/subdirectory\n category = `source:${dir.split('/').slice(0, 3).join('/')}`;\n }\n\n if (!groups[category]) {\n groups[category] = [];\n }\n groups[category].push(filePath);\n }\n\n // Format the groupings\n const output = Object.entries(groups)\n .map(([category, files]) => {\n return `${category} (${files.length} files):\\n${files.map(f => ` - ${f}`).join('\\n')}`;\n })\n .join('\\n\\n');\n\n const groupCount = Object.keys(groups).length;\n const suggestion = groupCount > 1\n ? `\\n\\nSuggestion: These ${groupCount} groups might be better as separate commits if they represent different concerns.`\n : '\\n\\nSuggestion: All files appear to be related and should be in a single commit.';\n\n return output + suggestion;\n },\n };\n}\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { runAgentic, type AgenticConfig, type ToolExecutionMetric } from './executor';\nimport { createToolRegistry } from '../tools/registry';\nimport { createCommitTools } from '../tools/commit-tools';\nimport type { StorageAdapter, Logger } from '../types';\nimport { generateToolGuidance } from '@riotprompt/riotprompt';\n\nexport interface AgenticCommitConfig {\n changedFiles: string[];\n diffContent: string;\n userDirection?: string;\n logContext?: string;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n debugRequestFile?: string;\n debugResponseFile?: string;\n storage?: StorageAdapter;\n logger?: Logger;\n openaiReasoning?: 'low' | 'medium' | 'high';\n tokenBudget?: {\n max: number;\n reserveForResponse?: number;\n strategy?: 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n onBudgetExceeded?: 'compress' | 'error' | 'warn' | 'truncate';\n };\n}\n\nexport interface AgenticCommitResult {\n commitMessage: string;\n iterations: number;\n toolCallsExecuted: number;\n suggestedSplits: Array<{\n files: string[];\n message: string;\n rationale: string;\n }>;\n conversationHistory: ChatCompletionMessageParam[];\n toolMetrics: ToolExecutionMetric[];\n}\n\n/**\n * Run agentic commit message generation\n */\nexport async function runAgenticCommit(config: AgenticCommitConfig): Promise<AgenticCommitResult> {\n const {\n changedFiles,\n diffContent,\n userDirection,\n logContext,\n model = 'gpt-4o',\n maxIterations = 10,\n debug = false,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget,\n } = config;\n\n // Create tool registry with context\n const toolRegistry = createToolRegistry({\n workingDirectory: process.cwd(),\n storage,\n logger,\n });\n\n // Register commit-specific tools\n const tools = createCommitTools();\n toolRegistry.registerAll(tools);\n\n // Generate automatic tool guidance from riotprompt\n const toolGuidance = generateToolGuidance(tools, {\n strategy: 'adaptive',\n includeExamples: true,\n explainWhenToUse: true,\n includeCategories: true,\n });\n\n // Build initial system prompt with tool guidance\n const systemPrompt = buildSystemPrompt(toolGuidance);\n\n // Build initial user message\n const userMessage = buildUserMessage(changedFiles, diffContent, userDirection, logContext);\n\n // Prepare messages for agentic loop\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n // Run agentic loop with optional token budget\n const agenticConfig: AgenticConfig = {\n messages,\n tools: toolRegistry,\n model,\n maxIterations,\n debug,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget: tokenBudget || {\n max: 150000,\n reserveForResponse: 4000,\n strategy: 'fifo',\n onBudgetExceeded: 'compress'\n },\n };\n\n const result = await runAgentic(agenticConfig);\n\n // Parse the final message to extract commit message and suggested splits\n const parsed = parseAgenticResult(result.finalMessage);\n\n return {\n commitMessage: parsed.commitMessage,\n iterations: result.iterations,\n toolCallsExecuted: result.toolCallsExecuted,\n suggestedSplits: parsed.suggestedSplits,\n conversationHistory: result.conversationHistory,\n toolMetrics: result.toolMetrics,\n };\n}\n\n/**\n * Build the system prompt for agentic commit generation\n */\nfunction buildSystemPrompt(toolGuidance: string): string {\n return `You are an expert software engineer tasked with generating meaningful commit messages.\n\n${toolGuidance}\n\n## Investigation Strategy\n\nFor simple changes (1-3 files, obvious purpose):\n- Use 1-2 tools: get_recent_commits to avoid duplicates, get_related_tests if logic changed\n\nFor moderate changes (4-10 files, clear theme):\n- Use 2-4 tools: group_files_by_concern, get_file_content for key files, get_recent_commits, get_related_tests\n\nFor complex changes (10+ files, or unclear purpose):\n- Use 4-6 tools: group_files_by_concern, get_file_history, get_file_content for key files, get_file_dependencies, get_related_tests, search_codebase\n\nAlways use tools to understand context - don't rely only on the diff.\n\n## Guidelines\n- Follow conventional commit format when appropriate (feat:, fix:, refactor:, docs:, test:, chore:)\n- Consider suggesting split commits for unrelated changes\n- Output only the commit message and/or splits - no conversational remarks\n- NEVER include phrases like \"If you want\" or \"Let me know\" or offer follow-up actions\n\nOutput format:\nWhen you're ready to provide the final commit message, format it as:\n\nCOMMIT_MESSAGE:\n[Your generated commit message here]\n\nIf you recommend splitting into multiple commits, also include:\n\nSUGGESTED_SPLITS:\nSplit 1:\nFiles: [list of files]\nRationale: [why these belong together]\nMessage: [commit message for this split]\n\nSplit 2:\n...\n\nIf changes should remain as one commit, do not include SUGGESTED_SPLITS section.`;\n}\n\n/**\n * Build the initial user message\n */\nfunction buildUserMessage(\n changedFiles: string[],\n diffContent: string,\n userDirection?: string,\n logContext?: string\n): string {\n let message = `I have staged changes that need a commit message.\n\nChanged files (${changedFiles.length}):\n${changedFiles.map(f => ` - ${f}`).join('\\n')}\n\nDiff:\n${diffContent}`;\n\n if (userDirection) {\n message += `\\n\\nUser direction: ${userDirection}`;\n }\n\n if (logContext) {\n message += `\\n\\nRecent commit history for context:\n${logContext}`;\n }\n\n message += `\\n\\nPlease investigate these changes and generate an appropriate commit message.\nUse the available tools to gather additional context as needed.\nIf these changes should be split into multiple commits, suggest the groupings.`;\n\n return message;\n}\n\n/**\n * Parse the agentic result to extract commit message and splits\n */\nfunction parseAgenticResult(finalMessage: string): {\n commitMessage: string;\n suggestedSplits: Array<{ files: string[]; message: string; rationale: string }>;\n} {\n // Look for COMMIT_MESSAGE: marker\n const commitMatch = finalMessage.match(/COMMIT_MESSAGE:\\s*\\n([\\s\\S]*?)(?=\\n\\nSUGGESTED_SPLITS:|$)/);\n const commitMessage = commitMatch ? commitMatch[1].trim() : finalMessage.trim();\n\n // Look for SUGGESTED_SPLITS: section\n const suggestedSplits: Array<{ files: string[]; message: string; rationale: string }> = [];\n const splitsMatch = finalMessage.match(/SUGGESTED_SPLITS:\\s*\\n([\\s\\S]*)/);\n\n if (splitsMatch) {\n const splitsText = splitsMatch[1];\n // Parse each split\n const splitRegex = /Split \\d+:\\s*\\nFiles: ([\\s\\S]*?)\\nRationale: ([\\s\\S]*?)\\nMessage: ([\\s\\S]*?)(?=\\n\\nSplit \\d+:|$)/g;\n let match;\n\n while ((match = splitRegex.exec(splitsText)) !== null) {\n const filesText = match[1].trim();\n const files = filesText\n .split('\\n')\n .map(line => line.trim().replace(/^[-*]\\s*/, ''))\n .filter(line => line.length > 0);\n\n suggestedSplits.push({\n files,\n rationale: match[2].trim(),\n message: match[3].trim(),\n });\n }\n }\n\n return { commitMessage, suggestedSplits };\n}\n\n","import type { Tool, ToolContext } from './types';\nimport { run } from '@eldrforge/git-tools';\nimport * as path from 'path';\n\n/**\n * Create tools for release notes generation\n */\nexport function createReleaseTools(): Tool[] {\n return [\n createGetFileHistoryTool(),\n createGetFileContentTool(),\n createSearchCodebaseTool(),\n createGetRelatedTestsTool(),\n createGetFileDependenciesTool(),\n createAnalyzeDiffSectionTool(),\n createGetRecentCommitsTool(),\n createGroupFilesByConcernTool(),\n createGetTagHistoryTool(),\n createComparePreviousReleaseTool(),\n createGetReleaseStatsTool(),\n createGetBreakingChangesTool(),\n createAnalyzeCommitPatternsTool(),\n ];\n}\n\n/**\n * Get git commit history for specific files\n */\nfunction createGetFileHistoryTool(): Tool {\n return {\n name: 'get_file_history',\n description: 'Get git commit history for one or more files to understand their evolution and past changes',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Array of file paths to get history for',\n items: { type: 'string', description: 'File path' },\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 10)',\n default: 10,\n },\n format: {\n type: 'string',\n description: 'Output format: \"summary\" for brief or \"detailed\" for full messages',\n enum: ['summary', 'detailed'],\n default: 'summary',\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; limit?: number; format?: 'summary' | 'detailed' }, context?: ToolContext) => {\n const { filePaths, limit = 10, format = 'summary' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Use proper shell quoting to avoid issues with parentheses in format strings\n const formatArg = format === 'detailed' ? '--format=\"%H%n%an (%ae)%n%ad%n%s%n%n%b%n---\"' : '--format=\"%h - %s (%an, %ar)\"';\n const fileArgs = filePaths.join(' ');\n const command = `git log ${formatArg} -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No history found for specified files';\n } catch (error: any) {\n throw new Error(`Failed to get file history: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get the full current content of a file\n */\nfunction createGetFileContentTool(): Tool {\n return {\n name: 'get_file_content',\n description: 'Get the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'Path to the file',\n },\n includeLineNumbers: {\n type: 'boolean',\n description: 'Include line numbers in output (default: false)',\n default: false,\n },\n },\n required: ['filePath'],\n },\n execute: async (params: { filePath: string; includeLineNumbers?: boolean }, context?: ToolContext) => {\n const { filePath, includeLineNumbers = false } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n\n if (includeLineNumbers) {\n const lines = content.split('\\n');\n return lines.map((line: string, idx: number) => `${idx + 1}: ${line}`).join('\\n');\n }\n\n return content;\n } catch (error: any) {\n // Handle file not found gracefully - common for deleted files in diffs\n if (error.code === 'ENOENT' || error.message?.includes('ENOENT')) {\n return `File not found: ${filePath}\\n\\nThis file may have been deleted in this release or does not exist in the current working tree. Check the diff to see if this file was removed.`;\n }\n throw new Error(`Failed to read file: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Search for code patterns or identifiers across the codebase\n */\nfunction createSearchCodebaseTool(): Tool {\n return {\n name: 'search_codebase',\n description: 'Search for code patterns, function names, or text across the codebase using git grep',\n parameters: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search pattern (can be plain text or regex)',\n },\n fileTypes: {\n type: 'array',\n description: 'Limit search to specific file extensions (e.g., [\"ts\", \"js\"])',\n items: { type: 'string', description: 'File extension' },\n },\n contextLines: {\n type: 'number',\n description: 'Number of context lines to show around matches (default: 2)',\n default: 2,\n },\n },\n required: ['query'],\n },\n execute: async (params: { query: string; fileTypes?: string[]; contextLines?: number }, context?: ToolContext) => {\n const { query, fileTypes, contextLines = 2 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Build command with proper git grep syntax: pattern comes BEFORE pathspec\n let command = `git grep -n -C ${contextLines} \"${query}\"`;\n\n if (fileTypes && fileTypes.length > 0) {\n // Add glob patterns for each file type with proper quoting\n const patterns = fileTypes.map(ext => `'*.${ext}'`).join(' ');\n command += ` -- ${patterns}`;\n }\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No matches found';\n } catch (error: any) {\n // git grep returns exit code 1 when no matches found\n if (error.message.includes('exit code 1') || error.stderr?.includes('did not match any file')) {\n return 'No matches found';\n }\n throw new Error(`Search failed: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Find test files related to changed production files\n */\nfunction createGetRelatedTestsTool(): Tool {\n return {\n name: 'get_related_tests',\n description: 'Find test files related to production files to understand what the code is supposed to do',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Production file paths',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n const relatedTests: string[] = [];\n\n for (const filePath of filePaths) {\n // Common test patterns\n const patterns = [\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.test.$1'),\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.spec.$1'),\n filePath.replace('/src/', '/tests/').replace('/lib/', '/tests/'),\n path.join('tests', filePath),\n path.join('test', filePath),\n ];\n\n for (const pattern of patterns) {\n try {\n await storage.readFile(pattern, 'utf-8');\n relatedTests.push(pattern);\n } catch {\n // File doesn't exist, continue\n }\n }\n }\n\n if (relatedTests.length === 0) {\n return 'No related test files found';\n }\n\n return `Found related test files:\\n${relatedTests.join('\\n')}`;\n },\n };\n}\n\n/**\n * Understand what files import/depend on changed files\n */\nfunction createGetFileDependenciesTool(): Tool {\n return {\n name: 'get_file_dependencies',\n description: 'Find which files import or depend on the changed files to assess change impact',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to analyze dependencies for',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const results: string[] = [];\n\n for (const filePath of filePaths) {\n // Extract filename without extension for searching imports\n const fileName = path.basename(filePath, path.extname(filePath));\n\n // Search for imports of this file\n const searchPatterns = [\n `from.*['\"].*${fileName}`,\n `import.*['\"].*${fileName}`,\n `require\\\\(['\"].*${fileName}`,\n ];\n\n for (const pattern of searchPatterns) {\n try {\n const command = `git grep -l \"${pattern}\"`;\n const output = await run(command, { cwd: workingDir });\n if (output.stdout) {\n results.push(`Files importing ${filePath}:\\n${output.stdout}`);\n break; // Found matches, no need to try other patterns\n }\n } catch {\n // No matches or error, continue\n }\n }\n }\n\n return results.length > 0\n ? results.join('\\n\\n')\n : 'No files found that import the specified files';\n },\n };\n}\n\n/**\n * Get detailed analysis of specific lines in a diff\n */\nfunction createAnalyzeDiffSectionTool(): Tool {\n return {\n name: 'analyze_diff_section',\n description: 'Get expanded context around specific lines in a file to better understand changes',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'File containing the section to analyze',\n },\n startLine: {\n type: 'number',\n description: 'Starting line number',\n },\n endLine: {\n type: 'number',\n description: 'Ending line number',\n },\n contextLines: {\n type: 'number',\n description: 'Number of additional context lines to show before and after (default: 10)',\n default: 10,\n },\n },\n required: ['filePath', 'startLine', 'endLine'],\n },\n execute: async (params: { filePath: string; startLine: number; endLine: number; contextLines?: number }, context?: ToolContext) => {\n const { filePath, startLine, endLine, contextLines = 10 } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n const actualStart = Math.max(0, startLine - contextLines - 1);\n const actualEnd = Math.min(lines.length, endLine + contextLines);\n\n const section = lines.slice(actualStart, actualEnd)\n .map((line: string, idx: number) => `${actualStart + idx + 1}: ${line}`)\n .join('\\n');\n\n return `Lines ${actualStart + 1}-${actualEnd} from ${filePath}:\\n\\n${section}`;\n } catch (error: any) {\n throw new Error(`Failed to analyze diff section: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get recent commits that touched the same files\n */\nfunction createGetRecentCommitsTool(): Tool {\n return {\n name: 'get_recent_commits',\n description: 'Get recent commits that modified the same files to understand recent work in this area',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to check for recent commits',\n items: { type: 'string', description: 'File path' },\n },\n since: {\n type: 'string',\n description: 'Time period to look back (e.g., \"1 week ago\", \"2 days ago\")',\n default: '1 week ago',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 5)',\n default: 5,\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; since?: string; limit?: number }, context?: ToolContext) => {\n const { filePaths, since = '1 week ago', limit = 5 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const fileArgs = filePaths.join(' ');\n const command = `git log --format=\"%h - %s (%an, %ar)\" --since=\"${since}\" -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || `No commits found in the specified time period (${since})`;\n } catch (error: any) {\n throw new Error(`Failed to get recent commits: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Analyze changed files and suggest logical groupings\n */\nfunction createGroupFilesByConcernTool(): Tool {\n return {\n name: 'group_files_by_concern',\n description: 'Analyze changed files and suggest logical groupings that might represent separate concerns',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'All changed files to analyze',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }) => {\n const { filePaths } = params;\n\n // Group files by directory and type\n const groups: Record<string, string[]> = {};\n\n for (const filePath of filePaths) {\n const dir = path.dirname(filePath);\n const ext = path.extname(filePath);\n const basename = path.basename(filePath, ext);\n\n // Determine category\n let category = 'other';\n\n if (basename.includes('.test') || basename.includes('.spec') || dir.includes('test')) {\n category = 'tests';\n } else if (filePath.includes('package.json') || filePath.includes('package-lock.json')) {\n category = 'dependencies';\n } else if (ext === '.md' || basename === 'README') {\n category = 'documentation';\n } else if (dir.includes('src') || dir.includes('lib')) {\n // Group by module/subdirectory\n category = `source:${dir.split('/').slice(0, 3).join('/')}`;\n }\n\n if (!groups[category]) {\n groups[category] = [];\n }\n groups[category].push(filePath);\n }\n\n // Format the groupings\n const output = Object.entries(groups)\n .map(([category, files]) => {\n return `${category} (${files.length} files):\\n${files.map(f => ` - ${f}`).join('\\n')}`;\n })\n .join('\\n\\n');\n\n const groupCount = Object.keys(groups).length;\n const suggestion = groupCount > 1\n ? `\\n\\nSuggestion: These ${groupCount} groups represent different concerns in the release.`\n : '\\n\\nSuggestion: All files appear to be related to a single concern.';\n\n return output + suggestion;\n },\n };\n}\n\n/**\n * Get history of previous release tags\n */\nfunction createGetTagHistoryTool(): Tool {\n return {\n name: 'get_tag_history',\n description: 'Get the history of previous release tags to understand release patterns and versioning',\n category: 'Release Analysis',\n cost: 'cheap',\n examples: [{ scenario: 'Check recent version tags', params: { limit: 5, pattern: 'v*' }, expectedResult: 'List of recent version tags with dates' }],\n parameters: {\n type: 'object',\n properties: {\n limit: {\n type: 'number',\n description: 'Number of recent tags to retrieve (default: 10)',\n default: 10,\n },\n pattern: {\n type: 'string',\n description: 'Filter tags by pattern (e.g., \"v*\" for version tags)',\n },\n },\n },\n execute: async (params: { limit?: number; pattern?: string }, context?: ToolContext) => {\n const { limit = 10, pattern } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n let command = 'git tag --sort=-creatordate';\n if (pattern) {\n command += ` -l \"${pattern}\"`;\n }\n command += ` | head -n ${limit}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n if (!output.stdout) {\n return 'No tags found in repository';\n }\n\n // Get detailed info for each tag\n const tags = output.stdout.trim().split('\\n');\n const detailedInfo: string[] = [];\n\n for (const tag of tags) {\n try {\n const tagInfo = await run(`git show --quiet --format=\"%ci - %s\" ${tag}`, { cwd: workingDir });\n detailedInfo.push(`${tag}: ${tagInfo.stdout.trim()}`);\n } catch {\n detailedInfo.push(`${tag}: (no info available)`);\n }\n }\n\n return `Recent release tags:\\n${detailedInfo.join('\\n')}`;\n } catch (error: any) {\n throw new Error(`Failed to get tag history: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Compare this release with a previous release\n */\nfunction createComparePreviousReleaseTool(): Tool {\n return {\n name: 'compare_previous_release',\n description: 'Compare this release with a previous release to understand what changed between versions',\n category: 'Release Analysis',\n cost: 'moderate',\n examples: [{ scenario: 'Compare with last release', params: { previousTag: 'v1.0.0', currentRef: 'HEAD' }, expectedResult: 'Commit count and file change statistics' }],\n parameters: {\n type: 'object',\n properties: {\n previousTag: {\n type: 'string',\n description: 'Previous release tag to compare against',\n },\n currentRef: {\n type: 'string',\n description: 'Current reference (default: HEAD)',\n default: 'HEAD',\n },\n statsOnly: {\n type: 'boolean',\n description: 'Return only statistics, not full diff (default: true)',\n default: true,\n },\n },\n required: ['previousTag'],\n },\n execute: async (params: { previousTag: string; currentRef?: string; statsOnly?: boolean }, context?: ToolContext) => {\n const { previousTag, currentRef = 'HEAD', statsOnly = true } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get commit count\n const commitCountCmd = `git rev-list --count ${previousTag}..${currentRef}`;\n const commitCount = await run(commitCountCmd, { cwd: workingDir });\n\n // Get file change stats\n const statsCmd = `git diff --stat ${previousTag}..${currentRef}`;\n const stats = await run(statsCmd, { cwd: workingDir });\n\n let result = `Comparison between ${previousTag} and ${currentRef}:\\n\\n`;\n result += `Commits: ${commitCount.stdout.trim()}\\n\\n`;\n result += `File changes:\\n${stats.stdout}`;\n\n if (!statsOnly) {\n // Get short log of commits\n const logCmd = `git log --oneline ${previousTag}..${currentRef}`;\n const log = await run(logCmd, { cwd: workingDir });\n result += `\\n\\nCommit summary:\\n${log.stdout}`;\n }\n\n return result;\n } catch (error: any) {\n throw new Error(`Failed to compare releases: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get statistics about the release\n */\nfunction createGetReleaseStatsTool(): Tool {\n return {\n name: 'get_release_stats',\n description: 'Get comprehensive statistics about the release including contributors, file changes, and commit patterns',\n category: 'Release Analysis',\n cost: 'moderate',\n examples: [{ scenario: 'Get release overview', params: { fromRef: 'v1.0.0', toRef: 'HEAD' }, expectedResult: 'Contributors, file changes, and top modified files' }],\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting reference for the release range',\n },\n toRef: {\n type: 'string',\n description: 'Ending reference for the release range (default: HEAD)',\n default: 'HEAD',\n },\n },\n required: ['fromRef'],\n },\n execute: async (params: { fromRef: string; toRef?: string }, context?: ToolContext) => {\n const { fromRef, toRef = 'HEAD' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n const results: string[] = [];\n\n // Commit count\n const commitCount = await run(`git rev-list --count ${fromRef}..${toRef}`, { cwd: workingDir });\n results.push(`Total commits: ${commitCount.stdout.trim()}`);\n\n // Contributors\n const contributors = await run(\n `git shortlog -sn ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n results.push(`\\nContributors:\\n${contributors.stdout}`);\n\n // File change summary\n const fileStats = await run(\n `git diff --shortstat ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n results.push(`\\nFile changes: ${fileStats.stdout.trim()}`);\n\n // Most changed files\n const topFiles = await run(\n `git diff --stat ${fromRef}..${toRef} | sort -k2 -rn | head -n 10`,\n { cwd: workingDir }\n );\n results.push(`\\nTop 10 most changed files:\\n${topFiles.stdout}`);\n\n return results.join('\\n');\n } catch (error: any) {\n throw new Error(`Failed to get release stats: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Identify potential breaking changes\n */\nfunction createGetBreakingChangesTool(): Tool {\n return {\n name: 'get_breaking_changes',\n description: 'Search for potential breaking changes by looking for specific patterns in commits and diffs',\n category: 'Release Analysis',\n cost: 'expensive',\n examples: [{ scenario: 'Check for breaking changes', params: { fromRef: 'v1.0.0', toRef: 'HEAD' }, expectedResult: 'List of potential breaking changes found' }],\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting reference for the release range',\n },\n toRef: {\n type: 'string',\n description: 'Ending reference for the release range (default: HEAD)',\n default: 'HEAD',\n },\n },\n required: ['fromRef'],\n },\n execute: async (params: { fromRef: string; toRef?: string }, context?: ToolContext) => {\n const { fromRef, toRef = 'HEAD' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const results: string[] = [];\n\n try {\n // Search for BREAKING CHANGE in commit messages\n const breakingCommits = await run(\n `git log --grep=\"BREAKING CHANGE\" --oneline ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n if (breakingCommits.stdout) {\n results.push(`Commits with BREAKING CHANGE:\\n${breakingCommits.stdout}`);\n }\n\n // Search for removed exports\n const removedExports = await run(\n `git diff ${fromRef}..${toRef} | grep \"^-export\"`,\n { cwd: workingDir }\n );\n if (removedExports.stdout) {\n results.push(`\\nRemoved exports (potential breaking):\\n${removedExports.stdout}`);\n }\n\n // Search for changed function signatures\n const changedSignatures = await run(\n `git diff ${fromRef}..${toRef} | grep -E \"^[-+].*function|^[-+].*const.*=.*=>|^[-+].*interface|^[-+].*type.*=\"`,\n { cwd: workingDir }\n );\n if (changedSignatures.stdout) {\n results.push(`\\nChanged function/type signatures (review for breaking changes):\\n${changedSignatures.stdout.split('\\n').slice(0, 20).join('\\n')}`);\n }\n\n if (results.length === 0) {\n return 'No obvious breaking changes detected. Manual review recommended for API changes.';\n }\n\n return results.join('\\n\\n');\n } catch {\n // Some commands may fail if no matches found\n if (results.length > 0) {\n return results.join('\\n\\n');\n }\n return 'No obvious breaking changes detected. Manual review recommended for API changes.';\n }\n },\n };\n}\n\n/**\n * Analyze commit patterns to identify themes\n */\nfunction createAnalyzeCommitPatternsTool(): Tool {\n return {\n name: 'analyze_commit_patterns',\n description: 'Analyze commit messages to identify patterns and themes in the release',\n category: 'Release Analysis',\n cost: 'cheap',\n examples: [{ scenario: 'Find commit themes', params: { fromRef: 'v1.0.0', toRef: 'HEAD' }, expectedResult: 'Commit types and top keywords' }],\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting reference for the release range',\n },\n toRef: {\n type: 'string',\n description: 'Ending reference for the release range (default: HEAD)',\n default: 'HEAD',\n },\n },\n required: ['fromRef'],\n },\n execute: async (params: { fromRef: string; toRef?: string }, context?: ToolContext) => {\n const { fromRef, toRef = 'HEAD' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n const results: string[] = [];\n\n // Get all commit messages\n const commits = await run(\n `git log --format=\"%s\" ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n\n const messages = commits.stdout.trim().split('\\n');\n\n // Count conventional commit types\n const types: Record<string, number> = {};\n const keywords: Record<string, number> = {};\n\n for (const msg of messages) {\n // Check for conventional commit format\n const conventionalMatch = msg.match(/^(\\w+)(\\(.+?\\))?:/);\n if (conventionalMatch) {\n const type = conventionalMatch[1];\n types[type] = (types[type] || 0) + 1;\n }\n\n // Extract keywords (words longer than 4 chars)\n const words = msg.toLowerCase().match(/\\b\\w{5,}\\b/g) || [];\n for (const word of words) {\n keywords[word] = (keywords[word] || 0) + 1;\n }\n }\n\n // Format commit types\n if (Object.keys(types).length > 0) {\n results.push('Commit types:');\n const sortedTypes = Object.entries(types)\n .sort((a, b) => b[1] - a[1])\n .map(([type, count]) => ` ${type}: ${count}`)\n .join('\\n');\n results.push(sortedTypes);\n }\n\n // Format top keywords\n const topKeywords = Object.entries(keywords)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 15)\n .map(([word, count]) => ` ${word}: ${count}`)\n .join('\\n');\n\n if (topKeywords) {\n results.push('\\nTop keywords in commits:');\n results.push(topKeywords);\n }\n\n return results.join('\\n');\n } catch (error: any) {\n throw new Error(`Failed to analyze commit patterns: ${error.message}`);\n }\n },\n };\n}\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { runAgentic, type AgenticConfig, type ToolExecutionMetric } from './executor';\nimport { createToolRegistry } from '../tools/registry';\nimport { createReleaseTools } from '../tools/release-tools';\nimport type { StorageAdapter, Logger } from '../types';\nimport { generateToolGuidance } from '@riotprompt/riotprompt';\n\nexport interface AgenticReleaseConfig {\n fromRef: string;\n toRef: string;\n logContent: string;\n diffContent: string;\n milestoneIssues?: string;\n releaseFocus?: string;\n userContext?: string;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n debugRequestFile?: string;\n debugResponseFile?: string;\n storage?: StorageAdapter;\n logger?: Logger;\n openaiReasoning?: 'low' | 'medium' | 'high';\n tokenBudget?: {\n max: number;\n reserveForResponse?: number;\n strategy?: 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n onBudgetExceeded?: 'compress' | 'error' | 'warn' | 'truncate';\n };\n}\n\nexport interface AgenticReleaseResult {\n releaseNotes: {\n title: string;\n body: string;\n };\n iterations: number;\n toolCallsExecuted: number;\n conversationHistory: ChatCompletionMessageParam[];\n toolMetrics: ToolExecutionMetric[];\n}\n\n/**\n * Run agentic release notes generation\n */\nexport async function runAgenticRelease(config: AgenticReleaseConfig): Promise<AgenticReleaseResult> {\n const {\n fromRef,\n toRef,\n logContent,\n diffContent,\n milestoneIssues,\n releaseFocus,\n userContext,\n model = 'gpt-4o',\n maxIterations = 30,\n debug = false,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget,\n } = config;\n\n // Create tool registry with context\n const toolRegistry = createToolRegistry({\n workingDirectory: process.cwd(),\n storage,\n logger,\n });\n\n // Register release-specific tools\n const tools = createReleaseTools();\n toolRegistry.registerAll(tools);\n\n // Generate automatic tool guidance from riotprompt\n const toolGuidance = generateToolGuidance(tools, {\n strategy: 'adaptive',\n includeExamples: true,\n explainWhenToUse: true,\n includeCategories: true,\n });\n\n // Build initial system prompt with tool guidance\n const systemPrompt = buildSystemPrompt(toolGuidance);\n\n // Build initial user message\n const userMessage = buildUserMessage({\n fromRef,\n toRef,\n logContent,\n diffContent,\n milestoneIssues,\n releaseFocus,\n userContext,\n });\n\n // Prepare messages for agentic loop\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n // Run agentic loop with token budget (larger for release notes)\n const agenticConfig: AgenticConfig = {\n messages,\n tools: toolRegistry,\n model,\n maxIterations,\n debug,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget: tokenBudget || {\n max: 200000,\n reserveForResponse: 8000,\n strategy: 'fifo',\n onBudgetExceeded: 'compress'\n },\n };\n\n const result = await runAgentic(agenticConfig);\n\n // Parse the final message to extract release notes\n const parsed = parseAgenticResult(result.finalMessage);\n\n return {\n releaseNotes: parsed.releaseNotes,\n iterations: result.iterations,\n toolCallsExecuted: result.toolCallsExecuted,\n conversationHistory: result.conversationHistory,\n toolMetrics: result.toolMetrics,\n };\n}\n\n/**\n * Build the system prompt for agentic release notes generation\n */\nfunction buildSystemPrompt(toolGuidance: string): string {\n return `You are an expert software engineer and technical writer tasked with generating comprehensive, thoughtful release notes.\n\n${toolGuidance}\n- get_tag_history: Use early to understand release cadence. Good for: establishing context about project versioning patterns\n\n**Analyzing Current Changes:**\n- get_file_content: Use when diff alone isn't enough. Good for: understanding APIs, seeing full class/function context, checking imports\n- analyze_diff_section: Use to expand context around cryptic changes. Good for: seeing surrounding code, understanding integration points\n- get_file_dependencies: Use for refactors/moves. Good for: assessing impact scope, identifying what depends on changed code\n- search_codebase: Use to find usage patterns. Good for: checking if APIs are widely used, finding similar patterns elsewhere\n\n**Pattern Recognition:**\n- group_files_by_concern: Use when many files changed. Good for: organizing changes into logical themes, identifying what actually happened\n- analyze_commit_patterns: Use for many commits. Good for: detecting themes across commits, identifying if work is focused or scattered\n- get_release_stats: Use to quantify scope. Good for: getting concrete metrics on scale of changes\n\n**Risk Assessment:**\n- get_breaking_changes: Always use. Good for: identifying API changes, finding removals/signature changes that could break users\n- get_related_tests: Use for significant logic changes. Good for: understanding what behavior changed, verifying test coverage exists\n\n## Your Investigation Strategy\n\n1. **Start broad** (2-3 tools): get_tag_history, get_release_stats, analyze_commit_patterns\n2. **Identify themes** (1-2 tools): group_files_by_concern if many files, compare_previous_release for context\n3. **Deep dive** (3-5 tools): get_file_content for key changes, get_file_dependencies for refactors, analyze_diff_section for unclear changes\n4. **Verify understanding** (2-3 tools): get_related_tests for logic changes, search_codebase for impact\n5. **Check risks** (1 tool): get_breaking_changes always\n\nUse at least 6-8 tools per release to ensure comprehensive analysis. Each tool provides a different lens on the changes.\n\nOutput format:\nWhen you're ready to provide the final release notes, format them as JSON:\n\nRELEASE_NOTES:\n{\n \"title\": \"A concise, single-line title capturing the most significant changes\",\n \"body\": \"The detailed release notes in Markdown format, following best practices for structure, depth, and analysis\"\n}\n\nThe release notes should:\n- Demonstrate genuine understanding of the changes\n- Provide context and explain implications\n- Connect related changes to reveal patterns\n- Be substantial and analytical, not formulaic\n- Sound like they were written by a human who studied the changes\n- Be grounded in actual commits and issues (no hallucinations)\n- Be standalone documentation that can be published as-is\n- NEVER include conversational elements like \"If you want, I can also...\" or \"Let me know if...\"\n- NEVER offer follow-up actions, questions, or suggestions for additional work\n- End with substantive content, not conversational closing remarks`;\n}\n\n/**\n * Build the initial user message\n */\nfunction buildUserMessage(params: {\n fromRef: string;\n toRef: string;\n logContent: string;\n diffContent: string;\n milestoneIssues?: string;\n releaseFocus?: string;\n userContext?: string;\n}): string {\n const { fromRef, toRef, logContent, diffContent, milestoneIssues, releaseFocus, userContext } = params;\n\n let message = `I need comprehensive release notes for changes from ${fromRef} to ${toRef}.\n\n## Commit Log\n${logContent}\n\n## Diff Summary\n${diffContent}`;\n\n if (milestoneIssues) {\n message += `\\n\\n## Resolved Issues from Milestone\n${milestoneIssues}`;\n }\n\n if (releaseFocus) {\n message += `\\n\\n## Release Focus\n${releaseFocus}\n\nThis is the PRIMARY GUIDE for how to frame and structure the release notes. Use this to determine emphasis and narrative.`;\n }\n\n if (userContext) {\n message += `\\n\\n## Additional Context\n${userContext}`;\n }\n\n message += `\\n\\nPlease investigate these changes thoroughly and generate comprehensive release notes that:\n1. Demonstrate deep understanding of what changed and why\n2. Provide context about how changes relate to each other\n3. Explain implications for users and developers\n4. Connect this release to previous releases and project evolution\n5. Identify any breaking changes or significant architectural shifts\n6. Follow best practices for technical writing and release notes\n\nUse the available tools to gather additional context as needed. Take your time to understand the changes deeply before writing the release notes.`;\n\n return message;\n}\n\n/**\n * Parse the agentic result to extract release notes\n */\nfunction parseAgenticResult(finalMessage: string): {\n releaseNotes: { title: string; body: string };\n} {\n // Look for RELEASE_NOTES: marker with JSON\n const jsonMatch = finalMessage.match(/RELEASE_NOTES:\\s*\\n([\\s\\S]*)/);\n\n if (jsonMatch) {\n try {\n const jsonStr = jsonMatch[1].trim();\n // Try to parse the JSON with error handling\n let parsed: any;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n // Failed to parse JSON, will use fallback parsing below\n parsed = null;\n }\n\n if (parsed && parsed.title && parsed.body) {\n return {\n releaseNotes: {\n title: parsed.title,\n body: parsed.body,\n },\n };\n }\n } catch {\n // JSON parsing failed, fall through to fallback\n }\n }\n\n // Fallback: try to extract title and body from the message\n const lines = finalMessage.split('\\n');\n let title = '';\n let body = '';\n let inBody = false;\n\n for (const line of lines) {\n if (!title && line.trim() && !line.startsWith('#')) {\n title = line.trim();\n } else if (title && line.trim()) {\n inBody = true;\n }\n\n if (inBody) {\n body += line + '\\n';\n }\n }\n\n // If we still don't have good content, use the whole message\n if (!title || !body) {\n title = 'Release Notes';\n body = finalMessage;\n }\n\n return {\n releaseNotes: {\n title: title.trim(),\n body: body.trim(),\n },\n };\n}\n\n","import type { Tool, ToolContext } from './types';\nimport { run, isBranchInSyncWithRemote, safeSyncBranchWithRemote, localBranchExists } from '@eldrforge/git-tools';\n\n/**\n * Create tools for agentic publish workflows\n */\nexport function createPublishTools(): Tool[] {\n return [\n createCheckGitStatusTool(),\n createCheckBranchSyncTool(),\n createAnalyzeDivergenceTool(),\n createGetCommitLogTool(),\n createGetBranchInfoTool(),\n createSyncBranchTool(),\n createGetDiffStatsTool(),\n createCheckConflictsTool(),\n createResetBranchTool(),\n ];\n}\n\n/**\n * Check git repository status\n */\nfunction createCheckGitStatusTool(): Tool {\n return {\n name: 'check_git_status',\n description: 'Check the current git repository status, including uncommitted changes, current branch, and repository state',\n parameters: {\n type: 'object',\n properties: {\n showUntracked: {\n type: 'boolean',\n description: 'Include untracked files in output (default: false)',\n default: false,\n },\n },\n required: [],\n },\n execute: async (params: { showUntracked?: boolean }, context?: ToolContext) => {\n const { showUntracked = false } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get current branch\n const branchResult = await run('git branch --show-current', { cwd: workingDir });\n const currentBranch = branchResult.stdout.trim();\n\n // Get status\n const statusCmd = showUntracked ? 'git status --porcelain' : 'git status --porcelain --untracked-files=no';\n const statusResult = await run(statusCmd, { cwd: workingDir });\n const hasChanges = statusResult.stdout.trim().length > 0;\n\n // Get HEAD commit\n const headResult = await run('git rev-parse --short HEAD', { cwd: workingDir });\n const headSha = headResult.stdout.trim();\n\n return {\n currentBranch,\n headSha,\n hasUncommittedChanges: hasChanges,\n statusOutput: statusResult.stdout,\n };\n } catch (error: any) {\n throw new Error(`Failed to check git status: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Check if a branch is synchronized with remote\n */\nfunction createCheckBranchSyncTool(): Tool {\n return {\n name: 'check_branch_sync',\n description: 'Check if a local branch is synchronized with its remote counterpart. Returns sync status, local/remote SHAs, and whether the branch exists locally.',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to check',\n },\n },\n required: ['branchName'],\n },\n execute: async (params: { branchName: string }, _context?: ToolContext) => {\n const { branchName } = params;\n\n try {\n // Check if branch exists locally\n const exists = await localBranchExists(branchName);\n\n if (!exists) {\n return {\n exists: false,\n message: `Branch '${branchName}' does not exist locally`,\n };\n }\n\n // Check sync status\n const syncStatus = await isBranchInSyncWithRemote(branchName);\n\n return {\n exists: true,\n branchName,\n inSync: syncStatus.inSync,\n localSha: syncStatus.localSha,\n remoteSha: syncStatus.remoteSha,\n error: syncStatus.error,\n isDiverged: syncStatus.localSha !== syncStatus.remoteSha,\n };\n } catch (error: any) {\n throw new Error(`Failed to check branch sync: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Analyze how two branches have diverged\n */\nfunction createAnalyzeDivergenceTool(): Tool {\n return {\n name: 'analyze_divergence',\n description: 'Analyze how two branches have diverged by showing commits unique to each branch',\n parameters: {\n type: 'object',\n properties: {\n sourceBranch: {\n type: 'string',\n description: 'The source/local branch name',\n },\n targetBranch: {\n type: 'string',\n description: 'The target/remote branch to compare against (e.g., \"origin/main\")',\n },\n maxCommits: {\n type: 'number',\n description: 'Maximum number of commits to show for each branch (default: 10)',\n default: 10,\n },\n },\n required: ['sourceBranch', 'targetBranch'],\n },\n execute: async (params: { sourceBranch: string; targetBranch: string; maxCommits?: number }, context?: ToolContext) => {\n const { sourceBranch, targetBranch, maxCommits = 10 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get commits in source but not in target\n const sourceOnlyResult = await run(\n `git log ${targetBranch}..${sourceBranch} --oneline -n ${maxCommits}`,\n { cwd: workingDir }\n );\n\n // Get commits in target but not in source\n const targetOnlyResult = await run(\n `git log ${sourceBranch}..${targetBranch} --oneline -n ${maxCommits}`,\n { cwd: workingDir }\n );\n\n // Get merge base\n const mergeBaseResult = await run(\n `git merge-base ${sourceBranch} ${targetBranch}`,\n { cwd: workingDir }\n );\n\n return {\n sourceBranch,\n targetBranch,\n mergeBase: mergeBaseResult.stdout.trim(),\n commitsInSourceOnly: sourceOnlyResult.stdout.trim() || 'None',\n commitsInTargetOnly: targetOnlyResult.stdout.trim() || 'None',\n isDiverged: sourceOnlyResult.stdout.trim().length > 0 && targetOnlyResult.stdout.trim().length > 0,\n canFastForward: sourceOnlyResult.stdout.trim().length === 0, // Target is ahead, can fast-forward\n };\n } catch (error: any) {\n throw new Error(`Failed to analyze divergence: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get commit log for a branch or range\n */\nfunction createGetCommitLogTool(): Tool {\n return {\n name: 'get_commit_log',\n description: 'Get git commit log for a branch or commit range with detailed information',\n parameters: {\n type: 'object',\n properties: {\n ref: {\n type: 'string',\n description: 'Git ref (branch name, commit range like \"main..working\", or single commit)',\n },\n maxCommits: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 20)',\n default: 20,\n },\n format: {\n type: 'string',\n description: 'Format: \"oneline\" for brief, \"full\" for detailed with message body',\n enum: ['oneline', 'full'],\n default: 'oneline',\n },\n },\n required: ['ref'],\n },\n execute: async (params: { ref: string; maxCommits?: number; format?: 'oneline' | 'full' }, context?: ToolContext) => {\n const { ref, maxCommits = 20, format = 'oneline' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n const formatStr = format === 'full'\n ? '%H%n%an <%ae>%n%ad%n%s%n%n%b%n---'\n : '%h - %s (%an, %ar)';\n\n const result = await run(\n `git log \"${ref}\" --format=\"${formatStr}\" -n ${maxCommits}`,\n { cwd: workingDir }\n );\n\n return result.stdout || 'No commits found';\n } catch (error: any) {\n throw new Error(`Failed to get commit log: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get detailed information about a branch\n */\nfunction createGetBranchInfoTool(): Tool {\n return {\n name: 'get_branch_info',\n description: 'Get detailed information about a branch including its tracking info, last commit, and whether it exists remotely',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to inspect',\n },\n },\n required: ['branchName'],\n },\n execute: async (params: { branchName: string }, context?: ToolContext) => {\n const { branchName } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Check if branch exists locally\n const localExists = await localBranchExists(branchName);\n\n if (!localExists) {\n // Check if it exists remotely\n try {\n const remoteCheckResult = await run(`git ls-remote --heads origin ${branchName}`, { cwd: workingDir });\n const remoteExists = remoteCheckResult.stdout.trim().length > 0;\n\n return {\n branchName,\n existsLocally: false,\n existsRemotely: remoteExists,\n message: remoteExists\n ? `Branch exists remotely but not locally`\n : `Branch does not exist locally or remotely`,\n };\n } catch {\n return {\n branchName,\n existsLocally: false,\n existsRemotely: false,\n };\n }\n }\n\n // Get branch tracking info\n let trackingBranch = null;\n try {\n const trackingResult = await run(`git rev-parse --abbrev-ref ${branchName}@{upstream}`, { cwd: workingDir });\n trackingBranch = trackingResult.stdout.trim();\n } catch {\n // No upstream configured\n }\n\n // Get last commit info\n const lastCommitResult = await run(\n `git log ${branchName} -1 --format=\"%H|%h|%s|%an|%ar\"`,\n { cwd: workingDir }\n );\n const [fullSha, shortSha, subject, author, relativeDate] = lastCommitResult.stdout.trim().split('|');\n\n // Get commit count\n const countResult = await run(`git rev-list --count ${branchName}`, { cwd: workingDir });\n const commitCount = parseInt(countResult.stdout.trim(), 10);\n if (isNaN(commitCount)) {\n throw new Error(`Invalid commit count returned from git: ${countResult.stdout}`);\n }\n\n return {\n branchName,\n existsLocally: true,\n trackingBranch,\n lastCommit: {\n fullSha,\n shortSha,\n subject,\n author,\n relativeDate,\n },\n commitCount,\n };\n } catch (error: any) {\n throw new Error(`Failed to get branch info: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Attempt to sync a branch with remote\n */\nfunction createSyncBranchTool(): Tool {\n return {\n name: 'sync_branch',\n description: 'Attempt to synchronize a local branch with its remote counterpart. Returns success status and details about what happened.',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to sync',\n },\n },\n required: ['branchName'],\n },\n execute: async (params: { branchName: string }, _context?: ToolContext) => {\n const { branchName } = params;\n\n try {\n const syncResult = await safeSyncBranchWithRemote(branchName);\n\n return {\n branchName,\n success: syncResult.success,\n conflictResolutionRequired: syncResult.conflictResolutionRequired,\n error: syncResult.error,\n message: syncResult.success\n ? `Successfully synchronized ${branchName} with remote`\n : syncResult.conflictResolutionRequired\n ? `Sync failed due to merge conflicts in ${branchName}`\n : `Sync failed: ${syncResult.error}`,\n };\n } catch (error: any) {\n throw new Error(`Failed to sync branch: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get diff statistics between two refs\n */\nfunction createGetDiffStatsTool(): Tool {\n return {\n name: 'get_diff_stats',\n description: 'Get statistics about differences between two git refs (branches, commits, etc.)',\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting ref (e.g., \"main\", \"origin/main\")',\n },\n toRef: {\n type: 'string',\n description: 'Ending ref (e.g., \"working\", \"HEAD\")',\n },\n includeFileList: {\n type: 'boolean',\n description: 'Include list of changed files (default: true)',\n default: true,\n },\n },\n required: ['fromRef', 'toRef'],\n },\n execute: async (params: { fromRef: string; toRef: string; includeFileList?: boolean }, context?: ToolContext) => {\n const { fromRef, toRef, includeFileList = true } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get diff stats\n const statsResult = await run(`git diff --shortstat ${fromRef}..${toRef}`, { cwd: workingDir });\n\n let fileList = null;\n if (includeFileList) {\n const fileListResult = await run(`git diff --name-status ${fromRef}..${toRef}`, { cwd: workingDir });\n fileList = fileListResult.stdout;\n }\n\n return {\n fromRef,\n toRef,\n stats: statsResult.stdout.trim() || 'No differences',\n fileList,\n };\n } catch (error: any) {\n throw new Error(`Failed to get diff stats: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Check for merge conflicts\n */\nfunction createCheckConflictsTool(): Tool {\n return {\n name: 'check_conflicts',\n description: 'Check if merging one branch into another would result in conflicts (without actually performing the merge)',\n parameters: {\n type: 'object',\n properties: {\n sourceBranch: {\n type: 'string',\n description: 'Branch to merge from',\n },\n targetBranch: {\n type: 'string',\n description: 'Branch to merge into',\n },\n },\n required: ['sourceBranch', 'targetBranch'],\n },\n execute: async (params: { sourceBranch: string; targetBranch: string }, context?: ToolContext) => {\n const { sourceBranch, targetBranch } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Use git merge-tree to check for conflicts without actually merging\n const mergeBaseResult = await run(\n `git merge-base ${targetBranch} ${sourceBranch}`,\n { cwd: workingDir }\n );\n const mergeBase = mergeBaseResult.stdout.trim();\n\n // Check if merge would create conflicts\n const mergeTreeResult = await run(\n `git merge-tree ${mergeBase} ${targetBranch} ${sourceBranch}`,\n { cwd: workingDir }\n );\n\n // Look for conflict markers in the output\n const hasConflicts = mergeTreeResult.stdout.includes('<<<<<<<') ||\n mergeTreeResult.stdout.includes('>>>>>>>') ||\n mergeTreeResult.stdout.includes('=======');\n\n // Extract conflicting files if any\n const conflicts = hasConflicts\n ? mergeTreeResult.stdout.match(/\\+\\+\\+ b\\/([^\\n]+)/g)?.map(m => m.replace(/\\+\\+\\+ b\\//, ''))\n : [];\n\n return {\n sourceBranch,\n targetBranch,\n mergeBase,\n hasConflicts,\n conflictingFiles: conflicts || [],\n message: hasConflicts\n ? `Merging ${sourceBranch} into ${targetBranch} would create conflicts`\n : `Merging ${sourceBranch} into ${targetBranch} should succeed without conflicts`,\n };\n } catch (error: any) {\n throw new Error(`Failed to check conflicts: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Reset a branch to match another ref\n */\nfunction createResetBranchTool(): Tool {\n return {\n name: 'reset_branch',\n description: 'Reset a branch to match another ref (e.g., reset local main to origin/main). USE WITH CAUTION - this is a destructive operation.',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to reset',\n },\n targetRef: {\n type: 'string',\n description: 'Ref to reset to (e.g., \"origin/main\")',\n },\n resetType: {\n type: 'string',\n description: 'Type of reset: \"hard\" (discard changes), \"soft\" (keep changes staged), \"mixed\" (keep changes unstaged)',\n enum: ['hard', 'soft', 'mixed'],\n default: 'hard',\n },\n },\n required: ['branchName', 'targetRef'],\n },\n execute: async (params: { branchName: string; targetRef: string; resetType?: 'hard' | 'soft' | 'mixed' }, context?: ToolContext) => {\n const { branchName, targetRef, resetType = 'hard' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // First, checkout the branch\n await run(`git checkout ${branchName}`, { cwd: workingDir });\n\n // Then reset it to the target ref\n await run(`git reset --${resetType} ${targetRef}`, { cwd: workingDir });\n\n // Get the new HEAD\n const headResult = await run('git rev-parse --short HEAD', { cwd: workingDir });\n const newHead = headResult.stdout.trim();\n\n return {\n branchName,\n targetRef,\n resetType,\n newHead,\n message: `Successfully reset ${branchName} to ${targetRef} (${resetType})`,\n };\n } catch (error: any) {\n throw new Error(`Failed to reset branch: ${error.message}`);\n }\n },\n };\n}\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { AgenticExecutor } from './executor';\nimport { createToolRegistry } from '../tools/registry';\nimport { createPublishTools } from '../tools/publish-tools';\nimport type { ToolContext } from '../tools/types';\n\nexport interface AgenticPublishConfig {\n targetBranch: string;\n sourceBranch: string;\n issue: 'branch_sync' | 'uncommitted_changes' | 'merge_conflicts' | 'unknown';\n issueDetails?: string;\n workingDirectory?: string;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n storage?: any;\n logger?: any;\n dryRun?: boolean;\n}\n\nexport interface AgenticPublishResult {\n success: boolean;\n message: string;\n actionsTaken: string[];\n iterations: number;\n toolCallsExecuted: number;\n requiresManualIntervention: boolean;\n manualSteps?: string[];\n}\n\n/**\n * Run agentic publish recovery\n */\nexport async function runAgenticPublish(config: AgenticPublishConfig): Promise<AgenticPublishResult> {\n const {\n targetBranch,\n sourceBranch,\n issue,\n issueDetails,\n workingDirectory = process.cwd(),\n model = 'gpt-4o',\n maxIterations = 10,\n debug = false,\n storage,\n logger,\n dryRun = false,\n } = config;\n\n // Create tool context\n const toolContext: ToolContext = {\n workingDirectory,\n storage,\n logger,\n };\n\n // Create tool registry with publish tools\n const tools = createToolRegistry(toolContext);\n tools.registerAll(createPublishTools());\n\n // Build the system prompt\n const systemPrompt = buildSystemPrompt(issue, dryRun);\n\n // Build the user prompt with specific issue details\n const userPrompt = buildUserPrompt({\n issue,\n targetBranch,\n sourceBranch,\n issueDetails,\n });\n\n // Prepare messages\n const messages: ChatCompletionMessageParam[] = [\n {\n role: 'system',\n content: systemPrompt,\n },\n {\n role: 'user',\n content: userPrompt,\n },\n ];\n\n // Run the agentic executor\n const executor = new AgenticExecutor(logger);\n const result = await executor.run({\n messages,\n tools,\n model,\n maxIterations,\n debug,\n storage,\n logger,\n });\n\n // Parse the final message to extract actions and recommendations\n const analysis = parseAgentResponse(result.finalMessage);\n\n return {\n success: analysis.success,\n message: result.finalMessage,\n actionsTaken: analysis.actionsTaken,\n iterations: result.iterations,\n toolCallsExecuted: result.toolCallsExecuted,\n requiresManualIntervention: analysis.requiresManualIntervention,\n manualSteps: analysis.manualSteps,\n };\n}\n\n/**\n * Build system prompt for agentic publish\n */\nfunction buildSystemPrompt(issue: string, dryRun: boolean): string {\n const modeNote = dryRun\n ? '\\n\\nIMPORTANT: This is a DRY RUN. Do not use tools that make destructive changes (like reset_branch or sync_branch). Only use diagnostic tools to analyze the issue and provide recommendations.'\n : '';\n\n return `You are an expert Git operations assistant helping to diagnose and fix issues that prevent publishing a software package.\n\nYour role is to:\n1. Use the available tools to investigate the problem\n2. Analyze the root cause of the issue\n3. ${dryRun ? 'Recommend' : 'Attempt to fix'} the issue using best practices\n4. Provide clear explanations of what you found and ${dryRun ? 'would do' : 'did'}\n\nAvailable tools allow you to:\n- Check git status and branch information\n- Analyze divergence between branches\n- View commit logs and diff statistics\n- Check for potential merge conflicts\n${dryRun ? '' : '- Sync branches with remote\\n- Reset branches to match remote refs'}\n\nGuidelines:\n- Always diagnose before taking action\n- Prefer safe, non-destructive operations when possible\n- If a situation requires manual intervention, clearly state why and provide steps\n- Be thorough in your analysis\n- Consider the impact of each action on the repository state\n\nCurrent issue type: ${issue}${modeNote}`;\n}\n\n/**\n * Build user prompt with specific issue details\n */\nfunction buildUserPrompt(params: {\n issue: string;\n targetBranch: string;\n sourceBranch: string;\n issueDetails?: string;\n}): string {\n const { issue, targetBranch, sourceBranch, issueDetails } = params;\n\n const issueDescriptions = {\n branch_sync: `The target branch '${targetBranch}' is not synchronized with its remote counterpart. This prevents the publish workflow from proceeding safely.`,\n uncommitted_changes: `There are uncommitted changes in the working directory on branch '${sourceBranch}'. The publish workflow requires a clean working directory.`,\n merge_conflicts: `There are merge conflicts between '${sourceBranch}' and '${targetBranch}' that need to be resolved before publishing.`,\n unknown: `An unknown issue is preventing the publish workflow from proceeding.`,\n };\n\n const basePrompt = `I'm trying to run a publish workflow that will:\n1. Create a release from source branch '${sourceBranch}'\n2. Merge it into target branch '${targetBranch}'\n3. Publish the package\n\nHowever, I'm encountering an issue:\n\n${issueDescriptions[issue as keyof typeof issueDescriptions] || issueDescriptions.unknown}`;\n\n const detailsSection = issueDetails\n ? `\\n\\nAdditional details:\\n${issueDetails}`\n : '';\n\n return `${basePrompt}${detailsSection}\n\nPlease investigate this issue and ${process.env.DRY_RUN ? 'recommend how to fix it' : 'attempt to fix it if possible'}. Use the available tools to:\n\n1. Diagnose the exact problem\n2. Understand what caused it (e.g., what commits are causing divergence)\n3. ${process.env.DRY_RUN ? 'Recommend a solution' : 'Attempt to resolve it safely'}\n4. Explain what ${process.env.DRY_RUN ? 'should be' : 'was'} done and why\n\nIf the issue requires manual intervention, please explain why and provide clear steps.`;\n}\n\n/**\n * Parse agent response to extract structured information\n */\nfunction parseAgentResponse(message: string): {\n success: boolean;\n actionsTaken: string[];\n requiresManualIntervention: boolean;\n manualSteps: string[];\n} {\n // Look for indicators of success/failure\n const successIndicators = [\n 'successfully',\n 'resolved',\n 'fixed',\n 'synced',\n 'safe to proceed',\n 'ready to publish',\n ];\n\n const manualInterventionIndicators = [\n 'requires manual',\n 'manual intervention',\n 'cannot automatically',\n 'you will need to',\n 'please manually',\n ];\n\n const messageLower = message.toLowerCase();\n const hasSuccessIndicator = successIndicators.some(indicator => messageLower.includes(indicator));\n const hasManualIndicator = manualInterventionIndicators.some(indicator => messageLower.includes(indicator));\n\n // Extract actions taken (look for past tense verbs and tool usage patterns)\n const actionsTaken: string[] = [];\n const actionPatterns = [\n /(?:I |We )?(checked|analyzed|found|discovered|synced|reset|merged|fetched|pulled|compared|investigated)\\s+([^.\\n]+)/gi,\n /(?:Successfully|Successfully)\\s+([^.\\n]+)/gi,\n ];\n\n for (const pattern of actionPatterns) {\n const matches = message.matchAll(pattern);\n for (const match of matches) {\n actionsTaken.push(match[0].trim());\n }\n }\n\n // Extract manual steps (look for numbered lists or bullet points)\n const manualSteps: string[] = [];\n const stepPatterns = [\n /(?:Step \\d+:|^\\d+\\.)\\s*(.+)$/gim,\n /^[-*]\\s+(.+)$/gim,\n ];\n\n if (hasManualIndicator) {\n // Only extract steps if manual intervention is needed\n for (const pattern of stepPatterns) {\n const matches = message.matchAll(pattern);\n for (const match of matches) {\n const step = match[1]?.trim();\n if (step && step.length > 10) { // Filter out very short matches\n manualSteps.push(step);\n }\n }\n }\n }\n\n return {\n success: hasSuccessIndicator && !hasManualIndicator,\n actionsTaken: [...new Set(actionsTaken)], // Remove duplicates\n requiresManualIntervention: hasManualIndicator,\n manualSteps: [...new Set(manualSteps)], // Remove duplicates\n };\n}\n\n/**\n * Create a friendly summary of the agentic publish result\n */\nexport function formatAgenticPublishResult(result: AgenticPublishResult): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push('═══════════════════════════════════════════════════════════');\n lines.push(' AGENTIC PUBLISH RECOVERY REPORT');\n lines.push('═══════════════════════════════════════════════════════════');\n lines.push('');\n\n if (result.success) {\n lines.push('✅ Status: RESOLVED');\n } else if (result.requiresManualIntervention) {\n lines.push('⚠️ Status: MANUAL INTERVENTION REQUIRED');\n } else {\n lines.push('❌ Status: UNRESOLVED');\n }\n\n lines.push('');\n lines.push(`Iterations: ${result.iterations}`);\n lines.push(`Tools executed: ${result.toolCallsExecuted}`);\n lines.push('');\n\n if (result.actionsTaken.length > 0) {\n lines.push('Actions taken:');\n for (const action of result.actionsTaken) {\n lines.push(` • ${action}`);\n }\n lines.push('');\n }\n\n if (result.requiresManualIntervention && result.manualSteps && result.manualSteps.length > 0) {\n lines.push('Manual steps required:');\n for (let i = 0; i < result.manualSteps.length; i++) {\n lines.push(` ${i + 1}. ${result.manualSteps[i]}`);\n }\n lines.push('');\n }\n\n lines.push('Detailed analysis:');\n lines.push('───────────────────────────────────────────────────────────');\n lines.push(result.message);\n lines.push('───────────────────────────────────────────────────────────');\n lines.push('');\n\n if (result.success) {\n lines.push('You can now retry the publish command.');\n } else if (result.requiresManualIntervention) {\n lines.push('Please complete the manual steps above, then retry the publish command.');\n } else {\n lines.push('The issue could not be resolved automatically. Please review the analysis above.');\n }\n\n lines.push('');\n\n return lines.join('\\n');\n}\n\n","/**\n * Conversation logging for debugging and analysis\n *\n * Provides simple wrappers for logging agentic conversations\n * to disk for later analysis.\n */\n\nimport { ConversationLogger, type LogConfig } from '@riotprompt/riotprompt';\nimport type { Logger, StorageAdapter } from '../types';\nimport path from 'path';\n\nexport interface ConversationLoggerConfig {\n outputDir: string;\n format?: 'json' | 'markdown';\n includeMetadata?: boolean;\n storage?: StorageAdapter;\n logger?: Logger;\n}\n\n/**\n * Create a conversation logger instance\n *\n * @example\n * ```typescript\n * const logger = createConversationLogger({\n * outputDir: 'output/conversations',\n * storage,\n * logger\n * });\n *\n * // Log conversation\n * await logger.save(conversationId, messages, metadata);\n * ```\n */\nexport function createConversationLogger(config: ConversationLoggerConfig) {\n const {\n outputDir,\n format = 'json',\n storage,\n logger\n } = config;\n\n return {\n /**\n * Save a conversation to disk\n */\n async save(\n conversationId: string,\n messages: any[],\n metadata?: Record<string, any>\n ): Promise<string> {\n try {\n if (!storage) {\n throw new Error('Storage adapter required');\n }\n\n const conversation = {\n id: conversationId,\n timestamp: new Date().toISOString(),\n messages,\n metadata: metadata || {}\n };\n\n const filename = `${conversationId}.${format}`;\n const filepath = path.join(outputDir, filename);\n\n const content = format === 'json'\n ? JSON.stringify(conversation, null, 2)\n : formatConversationAsMarkdown(conversation);\n\n await storage.writeOutput(filename, content);\n\n if (logger) {\n logger.debug(`Logged conversation ${conversationId} to ${filepath}`);\n }\n\n return filepath;\n } catch (error: any) {\n if (logger) {\n logger.warn(`Failed to log conversation ${conversationId}: ${error.message}`);\n }\n throw error;\n }\n },\n\n /**\n * Load a conversation from disk\n */\n async load(conversationId: string) {\n try {\n if (!storage) {\n throw new Error('Storage adapter required');\n }\n\n const filename = `${conversationId}.${format}`;\n const content = await storage.readFile(path.join(outputDir, filename), 'utf-8');\n\n let conversation: any;\n if (format === 'json') {\n try {\n conversation = JSON.parse(content);\n } catch (parseError: any) {\n throw new Error(`Failed to parse conversation JSON: ${parseError.message}`);\n }\n } else {\n conversation = content;\n }\n\n if (logger) {\n logger.info(`Loaded conversation ${conversationId}`);\n }\n\n return conversation;\n } catch (error: any) {\n if (logger) {\n logger.warn(`Failed to load conversation ${conversationId}: ${error.message}`);\n }\n throw error;\n }\n },\n\n /**\n * Get conversation summary\n */\n async getSummary(conversationId: string) {\n try {\n const conversation = await this.load(conversationId);\n\n return {\n id: conversation.id,\n timestamp: conversation.timestamp,\n messageCount: conversation.messages?.length || 0,\n metadata: conversation.metadata\n };\n } catch (error: any) {\n if (logger) {\n logger.warn(`Failed to get summary for ${conversationId}: ${error.message}`);\n }\n throw error;\n }\n },\n\n /**\n * Create riotprompt ConversationLogger instance for advanced usage\n */\n createRiotLogger(): ConversationLogger {\n const logConfig: LogConfig = {\n enabled: true,\n outputPath: outputDir,\n format: format as 'json' | 'markdown' | 'jsonl',\n includeMetadata: true\n };\n\n return new ConversationLogger(logConfig, logger);\n }\n };\n}\n\n/**\n * Format conversation as markdown\n */\nfunction formatConversationAsMarkdown(conversation: any): string {\n const lines: string[] = [];\n\n lines.push(`# Conversation: ${conversation.id}`);\n lines.push('');\n lines.push(`**Timestamp:** ${conversation.timestamp}`);\n\n if (conversation.metadata) {\n lines.push('');\n lines.push('## Metadata');\n lines.push('```json');\n lines.push(JSON.stringify(conversation.metadata, null, 2));\n lines.push('```');\n }\n\n lines.push('');\n lines.push('## Messages');\n lines.push('');\n\n for (let i = 0; i < conversation.messages.length; i++) {\n const msg = conversation.messages[i];\n lines.push(`### Message ${i + 1}: ${msg.role}`);\n lines.push('');\n lines.push(msg.content || '(no content)');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Helper to generate conversation ID\n */\nexport function generateConversationId(command: string): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('.')[0];\n return `${command}-${timestamp}`;\n}\n\nexport type ConversationLoggerInstance = ReturnType<typeof createConversationLogger>;\n","/**\n * Self-reflection report generation\n *\n * Provides enhanced reflection reports for agentic workflows.\n * Uses our custom implementation optimized for commit and release workflows.\n */\n\nimport type { Logger, StorageAdapter } from '../types';\nimport type { ToolExecutionMetric } from '../agentic/executor';\n\nexport interface ReflectionOptions {\n iterations: number;\n toolCallsExecuted: number;\n maxIterations: number;\n toolMetrics: ToolExecutionMetric[];\n conversationHistory?: any[];\n commitMessage?: string;\n suggestedSplits?: any[];\n releaseNotes?: any;\n logger?: Logger;\n}\n\n/**\n * Generate a comprehensive self-reflection report\n *\n * @example\n * ```typescript\n * const report = await generateReflectionReport({\n * iterations: result.iterations,\n * toolCallsExecuted: result.toolCallsExecuted,\n * maxIterations: 10,\n * toolMetrics: result.toolMetrics,\n * commitMessage: result.commitMessage,\n * logger\n * });\n *\n * await saveReflectionReport(report, 'output/reflection.md', storage);\n * ```\n */\nexport async function generateReflectionReport(options: ReflectionOptions): Promise<string> {\n const {\n iterations,\n toolCallsExecuted,\n maxIterations,\n toolMetrics,\n conversationHistory,\n commitMessage,\n suggestedSplits,\n releaseNotes,\n logger\n } = options;\n\n const sections: string[] = [];\n\n // Header\n sections.push('# Agentic Workflow - Self-Reflection Report');\n sections.push('');\n sections.push(`Generated: ${new Date().toISOString()}`);\n sections.push('');\n\n // Execution Summary\n sections.push('## Execution Summary');\n sections.push('');\n sections.push(`- **Iterations**: ${iterations}${iterations >= maxIterations ? ' (max reached)' : ''}`);\n sections.push(`- **Tool Calls**: ${toolCallsExecuted}`);\n sections.push(`- **Unique Tools**: ${new Set(toolMetrics.map(m => m.name)).size}`);\n sections.push('');\n\n // Calculate tool statistics\n const toolStats = calculateToolStats(toolMetrics);\n\n // Tool Effectiveness\n sections.push('## Tool Effectiveness Analysis');\n sections.push('');\n\n if (toolStats.size === 0) {\n sections.push('*No tools were executed during this run.*');\n } else {\n sections.push('| Tool | Calls | Success | Failures | Success Rate | Avg Duration |');\n sections.push('|------|-------|---------|----------|--------------|--------------|');\n\n for (const [toolName, stats] of Array.from(toolStats.entries()).sort((a, b) => b[1].total - a[1].total)) {\n const successRate = stats.total > 0 ? ((stats.success / stats.total) * 100).toFixed(1) : '0.0';\n const avgDuration = stats.total > 0 ? (stats.totalDuration / stats.total).toFixed(0) : '0';\n sections.push(`| ${toolName} | ${stats.total} | ${stats.success} | ${stats.failures} | ${successRate}% | ${avgDuration}ms |`);\n }\n }\n sections.push('');\n\n // Performance Insights\n if (toolStats.size > 0) {\n sections.push('### Tool Performance Insights');\n sections.push('');\n\n const failedTools = Array.from(toolStats.entries()).filter(([_, stats]) => stats.failures > 0);\n if (failedTools.length > 0) {\n sections.push('**Tools with Failures:**');\n for (const [toolName, stats] of failedTools) {\n const failureRate = stats.total > 0 ? ((stats.failures / stats.total) * 100).toFixed(1) : '0.0';\n sections.push(`- ${toolName}: ${stats.failures}/${stats.total} failures (${failureRate}%)`);\n }\n sections.push('');\n }\n\n const slowTools = Array.from(toolStats.entries())\n .filter(([_, stats]) => stats.total > 0 && (stats.totalDuration / stats.total) > 1000)\n .sort((a, b) => {\n const avgA = a[1].total > 0 ? a[1].totalDuration / a[1].total : 0;\n const avgB = b[1].total > 0 ? b[1].totalDuration / b[1].total : 0;\n return avgB - avgA;\n });\n\n if (slowTools.length > 0) {\n sections.push('**Slow Tools (>1s average):**');\n for (const [toolName, stats] of slowTools) {\n const avgDuration = stats.total > 0 ? (stats.totalDuration / stats.total / 1000).toFixed(2) : '0.00';\n sections.push(`- ${toolName}: ${avgDuration}s average`);\n }\n sections.push('');\n }\n\n sections.push('**Most Frequently Used:**');\n const topTools = Array.from(toolStats.entries()).slice(0, 3);\n for (const [toolName, stats] of topTools) {\n sections.push(`- ${toolName}: ${stats.total} calls`);\n }\n sections.push('');\n }\n\n // Recommendations\n sections.push('## Recommendations for Improvement');\n sections.push('');\n\n const recommendations = generateRecommendations(options, toolStats);\n if (recommendations.length === 0) {\n sections.push('*No specific recommendations at this time. Execution appears optimal.*');\n } else {\n for (const rec of recommendations) {\n sections.push(rec);\n }\n }\n sections.push('');\n\n // Execution Timeline\n sections.push('## Detailed Execution Timeline');\n sections.push('');\n\n if (toolMetrics.length === 0) {\n sections.push('*No tool execution timeline available.*');\n } else {\n sections.push('| Time | Iteration | Tool | Result | Duration |');\n sections.push('|------|-----------|------|--------|----------|');\n\n for (const metric of toolMetrics) {\n const time = new Date(metric.timestamp).toLocaleTimeString();\n const result = metric.success ? '✅ Success' : `❌ ${metric.error || 'Failed'}`;\n sections.push(`| ${time} | ${metric.iteration} | ${metric.name} | ${result} | ${metric.duration}ms |`);\n }\n sections.push('');\n }\n\n // Conversation History\n if (conversationHistory && conversationHistory.length > 0) {\n sections.push('## Conversation History');\n sections.push('');\n sections.push('<details>');\n sections.push('<summary>Click to expand full agentic interaction</summary>');\n sections.push('');\n sections.push('```json');\n sections.push(JSON.stringify(conversationHistory, null, 2));\n sections.push('```');\n sections.push('');\n sections.push('</details>');\n sections.push('');\n }\n\n // Generated Output\n if (commitMessage) {\n sections.push('## Generated Commit Message');\n sections.push('');\n sections.push('```');\n sections.push(commitMessage);\n sections.push('```');\n sections.push('');\n\n if (suggestedSplits && suggestedSplits.length > 1) {\n sections.push('## Suggested Commit Splits');\n sections.push('');\n for (let i = 0; i < suggestedSplits.length; i++) {\n const split = suggestedSplits[i];\n sections.push(`### Split ${i + 1}`);\n sections.push('');\n sections.push(`**Files**: ${split.files.join(', ')}`);\n sections.push('');\n sections.push(`**Rationale**: ${split.rationale}`);\n sections.push('');\n sections.push(`**Message**:`);\n sections.push('```');\n sections.push(split.message);\n sections.push('```');\n sections.push('');\n }\n }\n }\n\n if (releaseNotes) {\n sections.push('## Generated Release Notes');\n sections.push('');\n sections.push('### Title');\n sections.push('```');\n sections.push(releaseNotes.title);\n sections.push('```');\n sections.push('');\n sections.push('### Body');\n sections.push('```markdown');\n sections.push(releaseNotes.body);\n sections.push('```');\n sections.push('');\n }\n\n if (logger) {\n logger.debug(`Generated reflection report with ${toolStats.size} unique tools`);\n }\n\n return sections.join('\\n');\n}\n\n/**\n * Calculate tool statistics\n */\nfunction calculateToolStats(toolMetrics: ToolExecutionMetric[]): Map<string, { total: number; success: number; failures: number; totalDuration: number }> {\n const stats = new Map();\n\n for (const metric of toolMetrics) {\n if (!stats.has(metric.name)) {\n stats.set(metric.name, { total: 0, success: 0, failures: 0, totalDuration: 0 });\n }\n const toolStat = stats.get(metric.name);\n toolStat.total++;\n toolStat.totalDuration += metric.duration;\n if (metric.success) {\n toolStat.success++;\n } else {\n toolStat.failures++;\n }\n }\n\n return stats;\n}\n\n/**\n * Generate recommendations based on metrics\n */\nfunction generateRecommendations(\n options: ReflectionOptions,\n toolStats: Map<string, { total: number; success: number; failures: number; totalDuration: number }>\n): string[] {\n const recommendations: string[] = [];\n\n // Check for tool failures\n const toolsWithFailures = Array.from(toolStats.entries()).filter(([_, stats]) => stats.failures > 0);\n if (toolsWithFailures.length > 0) {\n recommendations.push('- **Tool Failures**: Investigate and fix tools that are failing. This may indicate issues with error handling or tool implementation.');\n }\n\n // Check for slow tools\n const slowTools = Array.from(toolStats.entries())\n .filter(([_, stats]) => stats.total > 0 && (stats.totalDuration / stats.total) > 1000);\n if (slowTools.length > 0) {\n recommendations.push('- **Performance**: Consider optimizing slow tools or caching results to improve execution speed.');\n }\n\n // Check for max iterations reached\n if (options.iterations >= options.maxIterations) {\n recommendations.push('- **Max Iterations Reached**: The agent reached maximum iterations. Consider increasing the limit or improving tool efficiency to allow the agent to complete naturally.');\n }\n\n // Check for underutilized tools\n const underutilizedTools = Array.from(toolStats.entries()).filter(([_, stats]) => stats.total === 1);\n if (underutilizedTools.length > 3) {\n recommendations.push('- **Underutilized Tools**: Many tools were called only once. Consider whether all tools are necessary or if the agent needs better guidance on when to use them.');\n }\n\n // Check tool diversity\n const uniqueTools = toolStats.size;\n if (uniqueTools === 1 && options.toolCallsExecuted > 3) {\n recommendations.push('- **Low Tool Diversity**: Only one tool was used despite multiple calls. Consider if the agent needs better guidance to use a variety of tools.');\n }\n\n return recommendations;\n}\n\n/**\n * Save reflection report to file\n */\nexport async function saveReflectionReport(\n report: string,\n outputPath: string,\n storage?: StorageAdapter\n): Promise<void> {\n if (!storage) {\n throw new Error('Storage adapter required to save report');\n }\n\n // Extract filename from path\n const filename = outputPath.split('/').pop() || 'reflection.md';\n await storage.writeOutput(filename, report);\n}\n","/**\n * Metrics collection for agentic workflows\n *\n * Provides integration with riotprompt's MetricsCollector while\n * maintaining compatibility with existing tool metrics.\n */\n\nimport { MetricsCollector, type AgenticExecutionMetrics } from '@riotprompt/riotprompt';\nimport type { Logger } from '../types';\n\nexport interface ToolExecutionMetric {\n name: string;\n timestamp: number;\n duration: number;\n success: boolean;\n iteration: number;\n error?: string;\n}\n\nexport interface MetricsConfig {\n logger?: Logger;\n}\n\n/**\n * Create a metrics collector for agentic workflows\n *\n * This wraps riotprompt's MetricsCollector and provides compatibility\n * with existing tool metrics format.\n */\nexport function createMetricsCollector(config: MetricsConfig = {}) {\n const { logger } = config;\n const collector = new MetricsCollector(logger);\n const toolMetrics: ToolExecutionMetric[] = [];\n\n return {\n /**\n * Record a tool execution\n */\n recordToolExecution(metric: ToolExecutionMetric) {\n toolMetrics.push(metric);\n\n // Also record in riotprompt's collector\n collector.recordToolCall(\n metric.name,\n metric.iteration,\n metric.duration,\n metric.success,\n metric.error\n );\n\n if (logger) {\n const status = metric.success ? 'success' : 'failed';\n logger.debug(`Tool ${metric.name} ${status} in ${metric.duration}ms`);\n }\n },\n\n /**\n * Record an iteration\n */\n recordIteration() {\n collector.incrementIteration();\n\n if (logger) {\n logger.debug(`Iteration incremented`);\n }\n },\n\n /**\n * Get tool metrics in legacy format (for backward compatibility)\n */\n getToolMetrics(): ToolExecutionMetric[] {\n return [...toolMetrics];\n },\n\n /**\n * Generate execution metrics report\n */\n generateReport(): AgenticExecutionMetrics {\n return collector.getMetrics([]);\n },\n\n /**\n * Get summary statistics\n */\n getSummary() {\n const report = collector.getMetrics([]);\n return {\n totalIterations: report.iterations,\n totalToolCalls: report.toolCallsExecuted,\n totalDuration: report.totalDuration,\n toolMetrics: report.toolMetrics,\n toolStats: report.toolStats\n };\n },\n\n /**\n * Reset all metrics\n */\n reset() {\n toolMetrics.length = 0;\n // Note: MetricsCollector doesn't have reset, create new instance if needed\n }\n };\n}\n\nexport type MetricsCollectorInstance = ReturnType<typeof createMetricsCollector>;\n\n"],"names":["isTokenLimitError","logger","timeoutMs","elapsedTimeFormatted","fs","__filename","__dirname","path","createGetFileHistoryTool","createGetFileContentTool","createSearchCodebaseTool","createGetRelatedTestsTool","createGetFileDependenciesTool","createAnalyzeDiffSectionTool","createGetRecentCommitsTool","createGroupFilesByConcernTool","buildSystemPrompt","buildUserMessage","parseAgenticResult"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/logger.ts","../src/ai.ts","../src/interactive.ts","../src/prompts/templates.ts","../src/prompts/commit.ts","../src/prompts/release.ts","../src/prompts/review.ts","../src/agentic/executor.ts","../src/tools/registry.ts","../src/tools/commit-tools.ts","../src/agentic/commit.ts","../src/tools/release-tools.ts","../src/agentic/release.ts","../src/tools/publish-tools.ts","../src/agentic/publish.ts","../src/observability/conversation-logger.ts","../src/observability/reflection.ts","../src/observability/metrics.ts"],"sourcesContent":["/**\n * Optional logger support\n * If winston is available as a peer dependency, use it\n * Otherwise, provide a no-op logger\n */\n\nimport type { Logger } from './types';\n\nlet logger: Logger | undefined;\n\n/**\n * Set a custom logger instance\n */\nexport function setLogger(customLogger: Logger): void {\n logger = customLogger;\n}\n\n/**\n * Create a no-op logger that does nothing\n */\nexport function createNoOpLogger(): Logger {\n return {\n info: () => {},\n error: () => {},\n warn: () => {},\n debug: () => {},\n };\n}\n\n/**\n * Attempt to load winston logger\n * @returns winston logger if available, otherwise null\n */\nexport function tryLoadWinston(): Logger | null {\n try {\n // Dynamic import to avoid hard dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const winston = require('winston');\n if (winston && winston.createLogger) {\n return winston.createLogger({\n level: 'info',\n format: winston.format.simple(),\n transports: [new winston.transports.Console()],\n });\n }\n } catch {\n // Winston not available\n }\n return null;\n}\n\n/**\n * Get the current logger or a no-op logger\n */\nexport function getLogger(): Logger {\n if (logger) {\n return logger;\n }\n\n // Try to load winston if available\n const winstonLogger = tryLoadWinston();\n if (winstonLogger) {\n logger = winstonLogger;\n return winstonLogger;\n }\n\n // Return no-op logger\n return createNoOpLogger();\n}\n","import { OpenAI } from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources';\nimport { safeJsonParse } from '@eldrforge/git-tools';\nimport fs from 'fs';\nimport { getLogger } from './logger';\nimport type { AIConfig, Transcription, StorageAdapter, Logger } from './types';\n\nexport interface OpenAIOptions {\n responseFormat?: any;\n model?: string;\n debug?: boolean;\n debugFile?: string;\n debugRequestFile?: string;\n debugResponseFile?: string;\n maxTokens?: number;\n openaiReasoning?: 'low' | 'medium' | 'high';\n openaiMaxOutputTokens?: number;\n storage?: StorageAdapter;\n logger?: Logger;\n tools?: any[]; // OpenAI tool definitions\n toolChoice?: 'auto' | 'none' | 'required' | { type: 'function'; function: { name: string } };\n}\n\nexport interface TranscriptionOptions {\n model?: string;\n debug?: boolean;\n debugFile?: string;\n debugRequestFile?: string;\n debugResponseFile?: string;\n outputDirectory?: string;\n storage?: StorageAdapter;\n logger?: Logger;\n onArchive?: (audioPath: string, transcriptionText: string) => Promise<void>;\n}\n\n/**\n * Get the appropriate model to use based on command-specific configuration\n * Command-specific model overrides the global model setting\n */\nexport function getModelForCommand(config: AIConfig, commandName: string): string {\n let commandModel: string | undefined;\n\n switch (commandName) {\n case 'commit':\n case 'audio-commit':\n commandModel = config.commands?.commit?.model;\n break;\n case 'release':\n commandModel = config.commands?.release?.model;\n break;\n case 'review':\n case 'audio-review':\n commandModel = config.commands?.review?.model;\n break;\n default:\n // For other commands, just use global model\n break;\n }\n\n // Return command-specific model if available, otherwise global model\n return commandModel || config.model || 'gpt-4o-mini';\n}\n\n/**\n * Get the appropriate OpenAI reasoning level based on command-specific configuration\n * Command-specific reasoning overrides the global reasoning setting\n */\nexport function getOpenAIReasoningForCommand(config: AIConfig, commandName: string): 'low' | 'medium' | 'high' {\n let commandReasoning: 'low' | 'medium' | 'high' | undefined;\n\n switch (commandName) {\n case 'commit':\n case 'audio-commit':\n commandReasoning = config.commands?.commit?.reasoning;\n break;\n case 'release':\n commandReasoning = config.commands?.release?.reasoning;\n break;\n case 'review':\n case 'audio-review':\n commandReasoning = config.commands?.review?.reasoning;\n break;\n default:\n // For other commands, just use global reasoning\n break;\n }\n\n // Return command-specific reasoning if available, otherwise global reasoning\n return commandReasoning || config.reasoning || 'low';\n}\n\nexport class OpenAIError extends Error {\n constructor(message: string, public readonly isTokenLimitError: boolean = false) {\n super(message);\n this.name = 'OpenAIError';\n }\n}\n\n// Check if an error is a token limit exceeded error\nexport function isTokenLimitError(error: any): boolean {\n if (!error?.message) return false;\n\n const message = error.message.toLowerCase();\n return message.includes('maximum context length') ||\n message.includes('context_length_exceeded') ||\n message.includes('token limit') ||\n message.includes('too many tokens') ||\n message.includes('reduce the length');\n}\n\n// Check if an error is a rate limit error\nexport function isRateLimitError(error: any): boolean {\n if (!error?.message && !error?.code && !error?.status) return false;\n\n // Check for OpenAI specific rate limit indicators\n if (error.status === 429 || error.code === 'rate_limit_exceeded') {\n return true;\n }\n\n // Only check message if it exists\n if (error.message) {\n const message = error.message.toLowerCase();\n return message.includes('rate limit exceeded') ||\n message.includes('too many requests') ||\n message.includes('quota exceeded') ||\n (message.includes('rate') && message.includes('limit'));\n }\n\n return false;\n}\n\n/**\n * Create OpenAI completion with optional debug and retry support\n */\nexport async function createCompletion(\n messages: ChatCompletionMessageParam[],\n options: OpenAIOptions = { model: \"gpt-4o-mini\" }\n): Promise<string | any> {\n const logger = options.logger || getLogger();\n let openai: OpenAI | null = null;\n\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n // Create the client which we'll close in the finally block.\n const timeoutMs = parseInt(process.env.OPENAI_TIMEOUT_MS || '300000', 10); // Default to 5 minutes\n if (isNaN(timeoutMs) || timeoutMs <= 0) {\n throw new OpenAIError('Invalid OPENAI_TIMEOUT_MS value - must be a positive number');\n }\n openai = new OpenAI({\n apiKey: apiKey,\n timeout: timeoutMs,\n });\n\n const modelToUse = options.model || \"gpt-4o-mini\";\n\n // Calculate request size\n const requestSize = JSON.stringify(messages).length;\n const requestSizeKB = (requestSize / 1024).toFixed(2);\n\n // Log model, reasoning level, and request size\n const reasoningInfo = options.openaiReasoning ? ` | Reasoning: ${options.openaiReasoning}` : '';\n logger.info('🤖 Making request to OpenAI');\n logger.info(' Model: %s%s', modelToUse, reasoningInfo);\n logger.info(' Request size: %s KB (%s bytes)', requestSizeKB, requestSize.toLocaleString());\n\n logger.debug('Sending prompt to OpenAI: %j', messages);\n\n // Use openaiMaxOutputTokens if specified (highest priority), otherwise fall back to maxTokens, or default to 10000\n const maxCompletionTokens = options.openaiMaxOutputTokens ?? options.maxTokens ?? 10000;\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile) && options.storage) {\n const requestData = {\n model: modelToUse,\n messages,\n max_completion_tokens: maxCompletionTokens,\n response_format: options.responseFormat,\n reasoning_effort: options.openaiReasoning,\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(requestData, null, 2));\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n // Prepare the API call options\n const apiOptions: any = {\n model: modelToUse,\n messages,\n max_completion_tokens: maxCompletionTokens,\n response_format: options.responseFormat,\n };\n\n // Add tools if provided\n if (options.tools && options.tools.length > 0) {\n apiOptions.tools = options.tools;\n apiOptions.tool_choice = options.toolChoice || 'auto';\n }\n\n // Add reasoning parameter if specified and model supports it\n if (options.openaiReasoning && (modelToUse.includes('gpt-5') || modelToUse.includes('o3'))) {\n apiOptions.reasoning_effort = options.openaiReasoning;\n }\n\n // Add timeout wrapper to the OpenAI API call\n const startTime = Date.now();\n const completionPromise = openai.chat.completions.create(apiOptions);\n\n // Create timeout promise with proper cleanup to prevent memory leaks\n let timeoutId: NodeJS.Timeout | null = null;\n const timeoutPromise = new Promise<never>((_, reject) => {\n const timeoutMs = parseInt(process.env.OPENAI_TIMEOUT_MS || '300000', 10); // Default to 5 minutes\n const validTimeout = isNaN(timeoutMs) || timeoutMs <= 0 ? 300000 : timeoutMs;\n timeoutId = setTimeout(() => reject(new OpenAIError(`OpenAI API call timed out after ${validTimeout/1000} seconds`)), validTimeout);\n });\n\n // Add progress indicator that updates every 5 seconds\n let progressIntervalId: NodeJS.Timeout | null = null;\n progressIntervalId = setInterval(() => {\n const elapsed = Math.round((Date.now() - startTime) / 1000);\n logger.info(' ⏳ Waiting for response... %ds', elapsed);\n }, 5000);\n\n let completion;\n try {\n completion = await Promise.race([completionPromise, timeoutPromise]);\n } finally {\n // Clear the timeout to prevent memory leaks\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n // Clear the progress interval\n if (progressIntervalId !== null) {\n clearInterval(progressIntervalId);\n }\n }\n\n const elapsedTime = Date.now() - startTime;\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile) && options.storage) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(completion, null, 2));\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const message = completion.choices[0]?.message;\n if (!message) {\n throw new OpenAIError('No response message received from OpenAI');\n }\n\n // If tools are being used, return the full message object (includes tool_calls)\n if (options.tools && options.tools.length > 0) {\n // Log elapsed time\n const elapsedTimeFormatted = elapsedTime >= 1000\n ? `${(elapsedTime / 1000).toFixed(1)}s`\n : `${elapsedTime}ms`;\n logger.info(' Time: %s', elapsedTimeFormatted);\n\n // Log token usage if available\n if (completion.usage) {\n logger.info(' Token usage: %s prompt + %s completion = %s total',\n completion.usage.prompt_tokens?.toLocaleString() || '?',\n completion.usage.completion_tokens?.toLocaleString() || '?',\n completion.usage.total_tokens?.toLocaleString() || '?'\n );\n }\n\n return message; // Return full message object for tool handling\n }\n\n // For non-tool calls, return content as string\n const response = message.content?.trim();\n if (!response) {\n throw new OpenAIError('No response content received from OpenAI');\n }\n\n // Calculate and log response size\n const responseSize = response.length;\n const responseSizeKB = (responseSize / 1024).toFixed(2);\n logger.info(' Response size: %s KB (%s bytes)', responseSizeKB, responseSize.toLocaleString());\n\n // Log elapsed time\n const elapsedTimeFormatted = elapsedTime >= 1000\n ? `${(elapsedTime / 1000).toFixed(1)}s`\n : `${elapsedTime}ms`;\n logger.info(' Time: %s', elapsedTimeFormatted);\n\n // Log token usage if available\n if (completion.usage) {\n logger.info(' Token usage: %s prompt + %s completion = %s total',\n completion.usage.prompt_tokens?.toLocaleString() || '?',\n completion.usage.completion_tokens?.toLocaleString() || '?',\n completion.usage.total_tokens?.toLocaleString() || '?'\n );\n }\n\n logger.debug('Received response from OpenAI: %s...', response.substring(0, 30));\n if (options.responseFormat) {\n return safeJsonParse(response, 'OpenAI API response');\n } else {\n return response;\n }\n\n } catch (error: any) {\n logger.error('Error calling OpenAI API: %s %s', error.message, error.stack);\n const isTokenError = isTokenLimitError(error);\n throw new OpenAIError(`Failed to create completion: ${error.message}`, isTokenError);\n } finally {\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n\n/**\n * Create completion with automatic retry on token limit errors\n */\nexport async function createCompletionWithRetry(\n messages: ChatCompletionMessageParam[],\n options: OpenAIOptions = { model: \"gpt-4o-mini\" },\n retryCallback?: (attempt: number) => Promise<ChatCompletionMessageParam[]>\n): Promise<string | any> {\n const logger = options.logger || getLogger();\n const maxRetries = 3;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n const messagesToSend = attempt === 1 ? messages : (retryCallback ? await retryCallback(attempt) : messages);\n return await createCompletion(messagesToSend, options);\n } catch (error: any) {\n if (error instanceof OpenAIError && error.isTokenLimitError && attempt < maxRetries && retryCallback) {\n logger.warn('Token limit exceeded on attempt %d/%d, retrying with reduced content...', attempt, maxRetries);\n // Add exponential backoff for token limit errors\n const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1), 10000);\n await new Promise(resolve => setTimeout(resolve, backoffMs));\n continue;\n } else if (isRateLimitError(error) && attempt < maxRetries) {\n // Handle rate limiting with exponential backoff\n const backoffMs = Math.min(2000 * Math.pow(2, attempt - 1), 15000); // More reasonable backoff: 2s, 4s, 8s, max 15s\n logger.warn(`Rate limit hit on attempt ${attempt}/${maxRetries}, waiting ${backoffMs}ms before retry...`);\n await new Promise(resolve => setTimeout(resolve, backoffMs));\n continue;\n }\n throw error;\n }\n }\n\n // This should never be reached, but TypeScript requires it\n throw new OpenAIError('Max retries exceeded');\n}\n\n/**\n * Transcribe audio file using OpenAI Whisper API\n */\nexport async function transcribeAudio(\n filePath: string,\n options: TranscriptionOptions = { model: \"whisper-1\" }\n): Promise<Transcription> {\n const logger = options.logger || getLogger();\n let openai: OpenAI | null = null;\n let audioStream: fs.ReadStream | null = null;\n let streamClosed = false;\n\n // Helper function to safely close the stream\n const closeAudioStream = () => {\n if (audioStream && !streamClosed) {\n try {\n // Only call destroy if it exists and the stream isn't already destroyed\n if (typeof audioStream.destroy === 'function' && !audioStream.destroyed) {\n audioStream.destroy();\n }\n streamClosed = true;\n logger.debug('Audio stream closed successfully');\n } catch (streamErr) {\n logger.debug('Failed to destroy audio read stream: %s', (streamErr as Error).message);\n streamClosed = true; // Mark as closed even if destroy failed\n }\n }\n };\n\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n openai = new OpenAI({\n apiKey: apiKey,\n });\n\n logger.debug('Transcribing audio file: %s', filePath);\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile) && options.storage) {\n const requestData = {\n model: options.model || \"whisper-1\",\n file: filePath, // Can't serialize the stream, so just save the file path\n response_format: \"json\",\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(requestData, null, 2));\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n audioStream = fs.createReadStream(filePath);\n\n // Set up error handler for the stream to ensure cleanup on stream errors\n // Only add handler if the stream has the 'on' method (real streams)\n if (audioStream && typeof audioStream.on === 'function') {\n audioStream.on('error', (streamError) => {\n logger.error('Audio stream error: %s', streamError.message);\n closeAudioStream();\n });\n }\n\n let transcription;\n try {\n transcription = await openai.audio.transcriptions.create({\n model: options.model || \"whisper-1\",\n file: audioStream,\n response_format: \"json\",\n });\n // Close the stream immediately after successful API call to prevent race conditions\n closeAudioStream();\n } catch (apiError) {\n // Close the stream immediately if the API call fails\n closeAudioStream();\n throw apiError;\n }\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile) && options.storage) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await options.storage.writeTemp(debugFile!, JSON.stringify(transcription, null, 2));\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const response = transcription;\n if (!response) {\n throw new OpenAIError('No transcription received from OpenAI');\n }\n\n logger.debug('Received transcription from OpenAI: %s', response);\n\n // Archive the audio file and transcription if callback provided\n if (options.onArchive) {\n try {\n await options.onArchive(filePath, response.text);\n } catch (archiveError: any) {\n // Don't fail the transcription if archiving fails, just log the error\n logger.warn('Failed to archive audio file: %s', archiveError.message);\n }\n }\n\n return response;\n\n } catch (error: any) {\n logger.error('Error transcribing audio file: %s %s', error.message, error.stack);\n throw new OpenAIError(`Failed to transcribe audio: ${error.message}`);\n } finally {\n // Ensure the audio stream is properly closed to release file handles\n closeAudioStream();\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n\n","#!/usr/bin/env node\nimport { getLogger } from './logger';\nimport type { Logger, Choice, InteractiveOptions } from './types';\nimport { spawnSync } from 'child_process';\nimport * as path from 'path';\nimport * as os from 'os';\nimport * as fs from 'fs/promises';\n\n/**\n * Get user choice interactively from terminal input\n * @param prompt The prompt message to display\n * @param choices Array of available choices\n * @param options Additional options for customizing behavior\n * @returns Promise resolving to the selected choice key\n */\nexport async function getUserChoice(\n prompt: string,\n choices: Choice[],\n options: InteractiveOptions = {}\n): Promise<string> {\n const logger = options.logger || getLogger();\n\n logger.info(prompt);\n choices.forEach(choice => {\n logger.info(` [${choice.key}] ${choice.label}`);\n });\n logger.info('');\n\n // Check if stdin is a TTY (terminal) or piped\n if (!process.stdin.isTTY) {\n logger.error('⚠️ STDIN is piped but interactive mode is enabled');\n logger.error(' Interactive prompts cannot be used when input is piped');\n logger.error(' Solutions:');\n logger.error(' • Use terminal input instead of piping');\n\n // Add any additional suggestions\n if (options.nonTtyErrorSuggestions) {\n options.nonTtyErrorSuggestions.forEach(suggestion => {\n logger.error(` • ${suggestion}`);\n });\n }\n\n return 's'; // Default to skip\n }\n\n return new Promise((resolve, reject) => {\n let isResolved = false;\n let dataHandler: ((key: Buffer) => void) | null = null;\n let errorHandler: ((error: Error) => void) | null = null;\n\n const cleanup = () => {\n if (dataHandler) {\n process.stdin.removeListener('data', dataHandler);\n }\n if (errorHandler) {\n process.stdin.removeListener('error', errorHandler);\n }\n\n try {\n if (process.stdin.setRawMode) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n // Detach stdin again now that we're done\n if (typeof process.stdin.unref === 'function') {\n process.stdin.unref();\n }\n } catch {\n // Ignore cleanup errors\n }\n };\n\n const safeResolve = (value: string) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n resolve(value);\n }\n };\n\n const safeReject = (error: Error) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n reject(error);\n }\n };\n\n try {\n // Ensure stdin is referenced so the process doesn't exit while waiting for input\n if (typeof process.stdin.ref === 'function') {\n process.stdin.ref();\n }\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n dataHandler = (key: Buffer) => {\n try {\n const keyStr = key.toString().toLowerCase();\n const choice = choices.find(c => c.key === keyStr);\n if (choice) {\n logger.info(`Selected: ${choice.label}\\n`);\n safeResolve(choice.key);\n }\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Unknown error processing input'));\n }\n };\n\n errorHandler = (error: Error) => {\n safeReject(error);\n };\n\n process.stdin.on('data', dataHandler);\n process.stdin.on('error', errorHandler);\n\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Failed to setup input handlers'));\n }\n });\n}\n\n/**\n * Secure temporary file handle that prevents TOCTOU vulnerabilities\n */\nexport class SecureTempFile {\n private fd: fs.FileHandle | null = null;\n private filePath: string;\n private isCleanedUp = false;\n private logger: Logger;\n\n private constructor(filePath: string, fd: fs.FileHandle, logger?: Logger) {\n this.filePath = filePath;\n this.fd = fd;\n this.logger = logger || getLogger();\n }\n\n /**\n * Create a secure temporary file with proper permissions and atomic operations\n * @param prefix Prefix for the temporary filename\n * @param extension File extension (e.g., '.txt', '.md')\n * @param logger Optional logger instance\n * @returns Promise resolving to SecureTempFile instance\n */\n static async create(prefix: string = 'ai-service', extension: string = '.txt', logger?: Logger): Promise<SecureTempFile> {\n const tmpDir = os.tmpdir();\n const log = logger || getLogger();\n\n // Ensure temp directory exists and is writable (skip check in test environments)\n if (!process.env.VITEST) {\n try {\n await fs.access(tmpDir, fs.constants.W_OK);\n } catch (error: any) {\n // Try to create the directory if it doesn't exist\n try {\n await fs.mkdir(tmpDir, { recursive: true, mode: 0o700 });\n } catch (mkdirError: any) {\n throw new Error(`Temp directory not writable: ${tmpDir} - ${error.message}. Failed to create: ${mkdirError.message}`);\n }\n }\n }\n\n const tmpFilePath = path.join(tmpDir, `${prefix}_${Date.now()}_${Math.random().toString(36).substring(7)}${extension}`);\n\n // Create file with exclusive access and restrictive permissions (owner read/write only)\n // Using 'wx' flag ensures exclusive creation (fails if file exists)\n let fd: fs.FileHandle;\n try {\n fd = await fs.open(tmpFilePath, 'wx', 0o600);\n } catch (error: any) {\n if (error.code === 'EEXIST') {\n // Highly unlikely with timestamp + random suffix, but handle it\n throw new Error(`Temporary file already exists: ${tmpFilePath}`);\n }\n throw new Error(`Failed to create temporary file: ${error.message}`);\n }\n\n return new SecureTempFile(tmpFilePath, fd, log);\n }\n\n /**\n * Get the file path (use with caution in external commands)\n */\n get path(): string {\n if (this.isCleanedUp) {\n throw new Error('Temp file has been cleaned up');\n }\n return this.filePath;\n }\n\n /**\n * Write content to the temporary file\n */\n async writeContent(content: string): Promise<void> {\n if (!this.fd || this.isCleanedUp) {\n throw new Error('Temp file is not available for writing');\n }\n await this.fd.writeFile(content, 'utf8');\n }\n\n /**\n * Read content from the temporary file\n */\n async readContent(): Promise<string> {\n if (!this.fd || this.isCleanedUp) {\n throw new Error('Temp file is not available for reading');\n }\n const content = await this.fd.readFile('utf8');\n return content;\n }\n\n /**\n * Close the file handle\n */\n async close(): Promise<void> {\n if (this.fd && !this.isCleanedUp) {\n await this.fd.close();\n this.fd = null;\n }\n }\n\n /**\n * Securely cleanup the temporary file - prevents TOCTOU by using file descriptor\n */\n async cleanup(): Promise<void> {\n if (this.isCleanedUp) {\n return; // Already cleaned up\n }\n\n try {\n // Close file descriptor first if still open\n if (this.fd) {\n await this.fd.close();\n this.fd = null;\n }\n\n // Now safely remove the file\n // Use fs.unlink which is safer than checking existence first\n await fs.unlink(this.filePath);\n } catch (error: any) {\n // Only ignore ENOENT (file not found) errors\n if (error.code !== 'ENOENT') {\n this.logger.warn(`Failed to cleanup temp file ${this.filePath}: ${error.message}`);\n // Don't throw here to avoid masking main operations\n }\n } finally {\n this.isCleanedUp = true;\n }\n }\n}\n\n/**\n * Create a secure temporary file for editing with proper permissions\n * @param prefix Prefix for the temporary filename\n * @param extension File extension (e.g., '.txt', '.md')\n * @param logger Optional logger instance\n * @returns Promise resolving to the temporary file path\n * @deprecated Use SecureTempFile.create() for better security\n */\nexport async function createSecureTempFile(prefix: string = 'ai-service', extension: string = '.txt', logger?: Logger): Promise<string> {\n const secureTempFile = await SecureTempFile.create(prefix, extension, logger);\n await secureTempFile.close();\n return secureTempFile.path;\n}\n\n/**\n * Clean up a temporary file\n * @param filePath Path to the temporary file to clean up\n * @param logger Optional logger instance\n * @deprecated Use SecureTempFile.cleanup() for better security\n */\nexport async function cleanupTempFile(filePath: string, logger?: Logger): Promise<void> {\n const log = logger || getLogger();\n try {\n await fs.unlink(filePath);\n } catch (error: any) {\n // Only ignore ENOENT (file not found) errors\n if (error.code !== 'ENOENT') {\n log.warn(`Failed to cleanup temp file ${filePath}: ${error.message}`);\n }\n }\n}\n\nexport interface EditorResult {\n content: string;\n wasEdited: boolean;\n}\n\n/**\n * Open content in user's editor for editing\n * @param content Initial content to edit\n * @param templateLines Additional template lines to include (will be filtered out)\n * @param fileExtension File extension for syntax highlighting\n * @param editor Editor command to use (defaults to EDITOR/VISUAL env var or 'vi')\n * @param logger Optional logger instance\n * @returns Promise resolving to the edited content\n */\nexport async function editContentInEditor(\n content: string,\n templateLines: string[] = [],\n fileExtension: string = '.txt',\n editor?: string,\n logger?: Logger\n): Promise<EditorResult> {\n const log = logger || getLogger();\n const editorCmd = editor || process.env.EDITOR || process.env.VISUAL || 'vi';\n\n const secureTempFile = await SecureTempFile.create('ai-service_edit', fileExtension, log);\n try {\n // Build template content\n const templateContent = [\n ...templateLines,\n ...(templateLines.length > 0 ? [''] : []), // Add separator if we have template lines\n content,\n '',\n ].join('\\n');\n\n await secureTempFile.writeContent(templateContent);\n await secureTempFile.close(); // Close before external editor access\n\n log.info(`📝 Opening ${editorCmd} to edit content...`);\n\n // Open the editor synchronously\n const result = spawnSync(editorCmd, [secureTempFile.path], { stdio: 'inherit' });\n\n if (result.error) {\n throw new Error(`Failed to launch editor '${editorCmd}': ${result.error.message}`);\n }\n\n // Read the file back in, stripping comment lines\n const fileContent = (await fs.readFile(secureTempFile.path, 'utf8'))\n .split('\\n')\n .filter(line => !line.trim().startsWith('#'))\n .join('\\n')\n .trim();\n\n if (!fileContent) {\n throw new Error('Content is empty after editing');\n }\n\n log.info('✅ Content updated successfully');\n\n return {\n content: fileContent,\n wasEdited: fileContent !== content.trim()\n };\n\n } finally {\n // Always clean up the temp file securely\n await secureTempFile.cleanup();\n }\n}\n\n/**\n * Standard choices for interactive feedback loops\n */\nexport const STANDARD_CHOICES = {\n CONFIRM: { key: 'c', label: 'Confirm and proceed' },\n EDIT: { key: 'e', label: 'Edit in editor' },\n SKIP: { key: 's', label: 'Skip and abort' },\n IMPROVE: { key: 'i', label: 'Improve with LLM feedback' }\n} as const;\n\n/**\n * Get text input from the user\n * @param prompt The prompt message to display\n * @param options Additional options for customizing behavior\n * @returns Promise resolving to the user's text input\n */\nexport async function getUserTextInput(\n prompt: string,\n options: InteractiveOptions = {}\n): Promise<string> {\n const logger = options.logger || getLogger();\n\n // Check if stdin is a TTY (terminal) or piped\n if (!process.stdin.isTTY) {\n logger.error('⚠️ STDIN is piped but interactive text input is required');\n logger.error(' Interactive text input cannot be used when input is piped');\n logger.error(' Solutions:');\n logger.error(' • Use terminal input instead of piping');\n\n // Add any additional suggestions\n if (options.nonTtyErrorSuggestions) {\n options.nonTtyErrorSuggestions.forEach(suggestion => {\n logger.error(` • ${suggestion}`);\n });\n }\n\n throw new Error('Interactive text input requires a terminal');\n }\n\n logger.info(prompt);\n logger.info('(Press Enter when done, or type Ctrl+C to cancel)');\n logger.info('');\n\n return new Promise((resolve, reject) => {\n let inputBuffer = '';\n let isResolved = false;\n let dataHandler: ((chunk: string) => void) | null = null;\n let errorHandler: ((error: Error) => void) | null = null;\n\n const cleanup = () => {\n if (dataHandler) {\n process.stdin.removeListener('data', dataHandler);\n }\n if (errorHandler) {\n process.stdin.removeListener('error', errorHandler);\n }\n\n try {\n process.stdin.pause();\n // Detach stdin again now that we're done\n if (typeof process.stdin.unref === 'function') {\n process.stdin.unref();\n }\n } catch {\n // Ignore cleanup errors\n }\n };\n\n const safeResolve = (value: string) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n resolve(value);\n }\n };\n\n const safeReject = (error: Error) => {\n if (!isResolved) {\n isResolved = true;\n cleanup();\n reject(error);\n }\n };\n\n try {\n // Ensure stdin is referenced so the process doesn't exit while waiting for input\n if (typeof process.stdin.ref === 'function') {\n process.stdin.ref();\n }\n\n process.stdin.setEncoding('utf8');\n process.stdin.resume();\n\n dataHandler = (chunk: string) => {\n try {\n inputBuffer += chunk;\n\n // Check if user pressed Enter (newline character)\n if (inputBuffer.includes('\\n')) {\n const userInput = inputBuffer.replace(/\\n$/, '').trim();\n\n if (userInput === '') {\n logger.warn('Empty input received. Please provide feedback text.');\n safeReject(new Error('Empty input received'));\n } else {\n logger.info(`✅ Received feedback: \"${userInput}\"\\n`);\n safeResolve(userInput);\n }\n }\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Unknown error processing input'));\n }\n };\n\n errorHandler = (error: Error) => {\n safeReject(error);\n };\n\n process.stdin.on('data', dataHandler);\n process.stdin.on('error', errorHandler);\n\n } catch (error) {\n safeReject(error instanceof Error ? error : new Error('Failed to setup input handlers'));\n }\n });\n}\n\n/**\n * Get LLM improvement feedback from the user using the editor\n * @param contentType Type of content being improved (e.g., 'commit message', 'release notes')\n * @param currentContent The current content to be improved\n * @param editor Optional editor command\n * @param logger Optional logger instance\n * @returns Promise resolving to the user's feedback text\n */\nexport async function getLLMFeedbackInEditor(\n contentType: string,\n currentContent: string,\n editor?: string,\n logger?: Logger\n): Promise<string> {\n const templateLines = [\n '# Provide Your Instructions and Guidance for a Revision Here',\n '#',\n '# Type your guidance above this line. Be specific about what you want changed,',\n '# added, or improved. You can also edit the original content below directly',\n '# to provide examples or show desired changes.',\n '#',\n '# Lines starting with \"#\" will be ignored.',\n '',\n '### YOUR FEEDBACK AND GUIDANCE:',\n '',\n '# (Type your improvement instructions here)',\n '',\n `### ORIGINAL ${contentType.toUpperCase()}:`,\n ''\n ];\n\n const result = await editContentInEditor(\n currentContent,\n templateLines,\n '.md',\n editor,\n logger\n );\n\n // Extract just the feedback section (everything before the original content)\n const lines = result.content.split('\\n');\n const originalSectionIndex = lines.findIndex(line =>\n line.trim().toLowerCase().startsWith('### original')\n );\n\n let feedback: string;\n if (originalSectionIndex >= 0) {\n // Take everything before the \"### ORIGINAL\" section\n feedback = lines.slice(0, originalSectionIndex).join('\\n').trim();\n } else {\n // If no original section found, take everything\n feedback = result.content.trim();\n }\n\n // Remove the feedback header if it exists\n feedback = feedback.replace(/^### YOUR FEEDBACK AND GUIDANCE:\\s*/i, '').trim();\n\n if (!feedback) {\n throw new Error('No feedback provided. Please provide improvement instructions.');\n }\n\n return feedback;\n}\n\n/**\n * Check if interactive mode is available (TTY check)\n * @param errorMessage Custom error message to throw if TTY not available\n * @param logger Optional logger instance\n * @throws Error if not in TTY environment\n */\nexport function requireTTY(errorMessage: string = 'Interactive mode requires a terminal. Use --dry-run instead.', logger?: Logger): void {\n const log = logger || getLogger();\n if (!process.stdin.isTTY) {\n log.error('❌ Interactive mode requires a terminal (TTY)');\n log.error(' Solutions:');\n log.error(' • Run without piping input');\n log.error(' • Use --dry-run to see the generated content');\n throw new Error(errorMessage);\n }\n}\n\n","/**\n * RiotPrompt Template Registry\n *\n * This module registers reusable prompt templates that can be used\n * across different prompt builders. Templates define common patterns\n * for personas, instructions, and structure.\n */\n\nimport { registerTemplates, type TemplateConfig } from '@riotprompt/riotprompt';\n\n/**\n * Initialize and register all prompt templates.\n * This should be called once during application initialization.\n */\nexport const initializeTemplates = (): void => {\n const templates: Record<string, TemplateConfig> = {\n // Commit message generation template\n 'commit': {\n persona: { path: 'personas/you.md' },\n instructions: [{ path: 'instructions/commit.md' }]\n },\n\n // Release notes generation template\n 'release': {\n persona: { path: 'personas/releaser.md' },\n instructions: [{ path: 'instructions/release.md' }]\n },\n\n // Code review template\n 'review': {\n persona: { path: 'personas/you.md' },\n instructions: [{ path: 'instructions/review.md' }]\n }\n };\n\n registerTemplates(templates);\n};\n\n/**\n * Template names for type-safe template references\n */\nexport const TemplateNames = {\n COMMIT: 'commit',\n RELEASE: 'release',\n REVIEW: 'review'\n} as const;\n\nexport type TemplateName = typeof TemplateNames[keyof typeof TemplateNames];\n\n","import { Prompt, cook, type ContentItem } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { TemplateNames } from './templates';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Types for the commit prompt\nexport type CommitContent = {\n diffContent: string;\n userDirection?: string;\n isFileContent?: boolean; // Flag to indicate if diffContent is actually file content\n githubIssuesContext?: string; // GitHub issues related to current version/milestone\n};\n\nexport type CommitContext = {\n logContext?: string;\n context?: string;\n directories?: string[];\n};\n\nexport type CommitConfig = {\n overridePaths?: string[];\n overrides?: boolean;\n}\n\n/**\n * Build a commit prompt using RiotPrompt Recipes.\n *\n * This prompt is configured to generate multiline commit messages by default,\n * with separate lines/bullet points for different groups of changes rather\n * than squeezing everything into single lines.\n *\n * @param config The configuration for overrides\n * @param content Mandatory content inputs (e.g. diff)\n * @param ctx Optional contextual inputs configured by the user\n */\nexport const createCommitPrompt = async (\n { overridePaths: _overridePaths, overrides: _overrides }: CommitConfig,\n { diffContent, userDirection, isFileContent, githubIssuesContext }: CommitContent,\n { logContext, context, directories }: CommitContext = {}\n): Promise<Prompt> => {\n const basePath = __dirname;\n\n // Build content items for the prompt\n const contentItems: ContentItem[] = [];\n const contextItems: ContentItem[] = [];\n\n // Developer Note: Direction is injected first as the highest-priority prompt input\n // This ensures user guidance takes precedence over other context sources like\n // GitHub issues or commit history.\n if (userDirection) {\n contentItems.push({ content: userDirection, title: 'User Direction' });\n }\n if (diffContent) {\n const contentTitle = isFileContent ? 'Project Files' : 'Diff';\n contentItems.push({ content: diffContent, title: contentTitle });\n }\n if (githubIssuesContext) {\n contentItems.push({ content: githubIssuesContext, title: 'Recent GitHub Issues' });\n }\n\n // IMPORTANT: Log context provides background but can contaminate output if too large.\n // LLMs tend to pattern-match against recent commits instead of describing the actual diff.\n // Keep messageLimit low (3-5) to minimize contamination.\n if (logContext) {\n contextItems.push({ content: logContext, title: 'Log Context' });\n }\n if (context) {\n contextItems.push({ content: context, title: 'User Context' });\n }\n if (directories && directories.length > 0) {\n contextItems.push({ directories, title: 'Directories' });\n }\n\n // Use declarative cook() API with registered template\n return cook({\n basePath,\n template: TemplateNames.COMMIT,\n overridePaths: _overridePaths ?? [],\n overrides: _overrides ?? true,\n content: contentItems,\n context: contextItems\n });\n};\n\n","import { Prompt, cook, type ContentItem } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { TemplateNames } from './templates';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Types for the release prompt\nexport type ReleaseConfig = {\n overridePaths?: string[];\n overrides?: boolean;\n}\n\nexport type ReleaseContent = {\n releaseFocus?: string;\n logContent: string;\n diffContent: string;\n milestoneIssues?: string;\n};\n\nexport type ReleaseContext = {\n context?: string;\n directories?: string[];\n};\n\nexport type ReleasePromptResult = {\n prompt: Prompt;\n maxTokens: number;\n isLargeRelease: boolean;\n};\n\n/**\n * Analyzes release content to determine if it's a large release\n * and calculates appropriate token limits\n */\nconst analyzeReleaseSize = (logContent: string, diffContent?: string, milestoneIssues?: string): { isLarge: boolean; maxTokens: number } => {\n const logLines = logContent.split('\\n').length;\n const diffLines = diffContent ? diffContent.split('\\n').length : 0;\n const milestoneLines = milestoneIssues ? milestoneIssues.split('\\n').length : 0;\n const totalContentLength = logContent.length + (diffContent?.length || 0) + (milestoneIssues?.length || 0);\n\n // Consider it a large release if:\n // - More than 20 commits (log lines typically ~3-5 per commit)\n // - More than 500 diff lines\n // - Milestone issues present (indicates significant work)\n // - Total content length > 50KB\n const isLarge = logLines > 60 || diffLines > 500 || milestoneLines > 50 || totalContentLength > 50000;\n\n if (isLarge) {\n // For large releases, significantly increase token limit\n return { isLarge: true, maxTokens: 25000 };\n } else {\n // Standard token limit for normal releases\n return { isLarge: false, maxTokens: 10000 };\n }\n};\n\n/**\n * Build a release prompt using RiotPrompt Recipes.\n */\nexport const createReleasePrompt = async (\n { overrides: _overrides, overridePaths: _overridePaths }: ReleaseConfig,\n { releaseFocus, logContent, diffContent, milestoneIssues }: ReleaseContent,\n { context, directories }: ReleaseContext = {}\n): Promise<ReleasePromptResult> => {\n const basePath = __dirname;\n\n // Analyze release size to determine token requirements\n const { isLarge: isLargeRelease, maxTokens } = analyzeReleaseSize(logContent, diffContent, milestoneIssues);\n\n // Build content items for the prompt\n const contentItems: ContentItem[] = [];\n const contextItems: ContentItem[] = [];\n\n if (diffContent) {\n contentItems.push({ content: diffContent, title: 'Diff' });\n }\n if (logContent) {\n contentItems.push({ content: logContent, title: 'Log Context' });\n }\n if (milestoneIssues) {\n contentItems.push({ content: milestoneIssues, title: 'Resolved Issues from Milestone' });\n }\n if (releaseFocus) {\n contentItems.push({ content: releaseFocus, title: 'Release Focus' });\n }\n\n // Add release size context to help guide the AI\n if (isLargeRelease) {\n contextItems.push({\n content: `This appears to be a LARGE RELEASE with significant changes. Please provide comprehensive, detailed release notes that thoroughly document all major changes, improvements, and fixes. Don't summarize - dive deep into the details.`,\n title: 'Release Size Context'\n });\n }\n\n if (context) {\n contextItems.push({ content: context, title: 'User Context' });\n }\n if (directories && directories.length > 0) {\n contextItems.push({ directories, title: 'Directories' });\n }\n\n // Use declarative cook() API with registered template\n const prompt = await cook({\n basePath,\n template: TemplateNames.RELEASE,\n overridePaths: _overridePaths ?? [],\n overrides: _overrides ?? true,\n content: contentItems,\n context: contextItems\n });\n\n return {\n prompt,\n maxTokens,\n isLargeRelease\n };\n};\n\n","import { Prompt, cook, type ContentItem } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { TemplateNames } from './templates';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport type ReviewConfig = {\n overridePaths?: string[];\n overrides?: boolean;\n}\n\nexport type ReviewContent = {\n notes: string;\n};\n\nexport type ReviewContext = {\n logContext?: string;\n diffContext?: string;\n releaseNotesContext?: string;\n issuesContext?: string;\n context?: string;\n directories?: string[];\n};\n\n/**\n * Build a review prompt using RiotPrompt Recipes.\n */\nexport const createReviewPrompt = async (\n { overridePaths: _overridePaths, overrides: _overrides }: ReviewConfig,\n { notes }: ReviewContent,\n { logContext, diffContext, releaseNotesContext, issuesContext, context, directories }: ReviewContext = {}\n): Promise<Prompt> => {\n const basePath = __dirname;\n\n // Build content items for the prompt\n const contentItems: ContentItem[] = [];\n const contextItems: ContentItem[] = [];\n\n if (notes) {\n contentItems.push({ content: notes, title: 'Review Notes' });\n }\n\n if (logContext) {\n contextItems.push({ content: logContext, title: 'Log Context' });\n }\n if (diffContext) {\n contextItems.push({ content: diffContext, title: 'Diff Context' });\n }\n if (releaseNotesContext) {\n contextItems.push({ content: releaseNotesContext, title: 'Release Notes Context' });\n }\n if (issuesContext) {\n contextItems.push({ content: issuesContext, title: 'Issues Context' });\n }\n if (context) {\n contextItems.push({ content: context, title: 'User Context' });\n }\n if (directories && directories.length > 0) {\n contextItems.push({ directories, title: 'Directories' });\n }\n\n // Use declarative cook() API with registered template\n return cook({\n basePath,\n template: TemplateNames.REVIEW,\n overridePaths: _overridePaths ?? [],\n overrides: _overrides ?? true,\n content: contentItems,\n context: contextItems\n });\n};\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { createCompletionWithRetry } from '../ai';\nimport type { ToolRegistry } from '../tools/registry';\nimport type { ToolResult } from '../tools/types';\nimport { ConversationBuilder, type Model } from '@riotprompt/riotprompt';\n\nexport interface AgenticConfig {\n messages: ChatCompletionMessageParam[];\n tools: ToolRegistry;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n debugRequestFile?: string;\n debugResponseFile?: string;\n storage?: any;\n logger?: any;\n openaiReasoning?: 'low' | 'medium' | 'high';\n // Token budget configuration\n tokenBudget?: {\n max: number;\n reserveForResponse?: number;\n strategy?: 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n onBudgetExceeded?: 'compress' | 'error' | 'warn' | 'truncate';\n };\n}\n\nexport interface ToolExecutionMetric {\n name: string;\n success: boolean;\n duration: number;\n error?: string;\n iteration: number;\n timestamp: string;\n}\n\nexport interface AgenticResult {\n finalMessage: string;\n iterations: number;\n toolCallsExecuted: number;\n conversationHistory: ChatCompletionMessageParam[];\n toolMetrics: ToolExecutionMetric[];\n}\n\n/**\n * Execute an agentic loop where the LLM can call tools to gather information\n */\nexport class AgenticExecutor {\n private logger?: any;\n private toolMetrics: ToolExecutionMetric[] = [];\n\n constructor(logger?: any) {\n this.logger = logger;\n }\n\n /**\n * Run the agentic loop with ConversationBuilder\n */\n async run(config: AgenticConfig): Promise<AgenticResult> {\n const {\n messages: initialMessages,\n tools,\n model = 'gpt-4o',\n maxIterations = 10,\n debug = false,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning = false,\n tokenBudget,\n } = config;\n\n // Create ConversationBuilder for better state management\n const conversation = ConversationBuilder.create({ model: model as Model }, logger);\n\n // Add initial messages to conversation\n for (const msg of initialMessages) {\n if (msg.role === 'system') {\n conversation.addSystemMessage(msg.content as string);\n } else if (msg.role === 'user') {\n conversation.addUserMessage(msg.content as string);\n }\n }\n\n // Configure token budget if provided\n if (tokenBudget) {\n this.log('Configuring token budget', tokenBudget);\n conversation.withTokenBudget({\n max: tokenBudget.max,\n reserveForResponse: tokenBudget.reserveForResponse || 4000,\n strategy: tokenBudget.strategy || 'fifo',\n onBudgetExceeded: tokenBudget.onBudgetExceeded || 'compress'\n });\n }\n\n let iterations = 0;\n let toolCallsExecuted = 0;\n\n this.log('Starting agentic loop with ConversationBuilder', { maxIterations, toolCount: tools.count() });\n\n while (iterations < maxIterations) {\n iterations++;\n this.log(`Iteration ${iterations}/${maxIterations}`);\n\n // Get current messages from conversation\n const messages = conversation.toMessages();\n\n // Call LLM with tools available\n const response = await createCompletionWithRetry(\n messages as ChatCompletionMessageParam[],\n {\n model,\n openaiReasoning: openaiReasoning || undefined,\n debug,\n debugRequestFile: debugRequestFile ? `${debugRequestFile}-iter${iterations}` : undefined,\n debugResponseFile: debugResponseFile ? `${debugResponseFile}-iter${iterations}` : undefined,\n storage,\n logger,\n tools: tools.toOpenAIFormat(),\n }\n );\n\n // When tools are enabled, response is the full message object\n const message = typeof response === 'string' ? { role: 'assistant', content: response } : response;\n\n // Check if there are tool calls in the response\n const toolCalls = message.tool_calls || [];\n\n if (toolCalls.length === 0) {\n // No tool calls, agent is done\n const finalContent = message.content || '';\n this.log('Agent completed without tool calls', { iterations, toolCallsExecuted });\n conversation.addAssistantMessage(finalContent);\n\n return {\n finalMessage: finalContent,\n iterations,\n toolCallsExecuted,\n conversationHistory: conversation.toMessages() as ChatCompletionMessageParam[],\n toolMetrics: this.toolMetrics,\n };\n }\n\n // Add assistant message with tool calls to conversation\n conversation.addAssistantWithToolCalls(message.content || null, toolCalls as any);\n\n // Execute tool calls\n this.log(`Executing ${toolCalls.length} tool call(s)`);\n\n for (const toolCall of toolCalls) {\n const startTime = Date.now();\n const toolName = toolCall.function.name;\n\n try {\n this.log(`Executing tool: ${toolName}`, toolCall.function.arguments);\n\n // Log to info level so user can see tool execution in real-time\n if (this.logger?.info) {\n this.logger.info(`🔧 Running tool: ${toolName}`);\n }\n\n // Parse arguments with error handling\n let args: any;\n try {\n args = JSON.parse(toolCall.function.arguments);\n } catch (parseError: any) {\n throw new Error(`Failed to parse tool arguments: ${parseError.message}`);\n }\n\n // Execute the tool\n const result = await tools.execute(toolName, args);\n\n const duration = Date.now() - startTime;\n\n // Add tool result to conversation using ConversationBuilder\n const formattedResult = this.formatToolResult({ id: toolCall.id, name: toolName, result });\n conversation.addToolResult(toolCall.id, formattedResult, toolName);\n\n toolCallsExecuted++;\n\n // Track successful execution\n this.toolMetrics.push({\n name: toolName,\n success: true,\n duration,\n iteration: iterations,\n timestamp: new Date().toISOString(),\n });\n\n this.log(`Tool ${toolName} succeeded in ${duration}ms`);\n\n if (this.logger?.info) {\n this.logger.info(`✅ Tool ${toolName} completed (${duration}ms)`);\n }\n } catch (error: any) {\n const duration = Date.now() - startTime;\n const errorMessage = error.message || String(error);\n\n this.log(`Tool ${toolName} failed: ${errorMessage}`);\n\n // Track failed execution\n this.toolMetrics.push({\n name: toolName,\n success: false,\n duration,\n error: errorMessage,\n iteration: iterations,\n timestamp: new Date().toISOString(),\n });\n\n if (this.logger?.warn) {\n this.logger.warn(`❌ Tool ${toolName} failed: ${errorMessage}`);\n }\n\n // Add error result to conversation using ConversationBuilder\n conversation.addToolResult(toolCall.id, `Tool execution failed: ${errorMessage}`, toolName);\n }\n }\n\n this.log(`Completed tool execution`, { toolCallsExecuted });\n }\n\n // Max iterations reached\n this.log('Max iterations reached, forcing completion', { iterations, toolCallsExecuted });\n\n // Make one final call without tools to get a synthesized response\n conversation.addUserMessage('Please provide your final analysis based on your investigation. Do not request any more tools.');\n\n const finalMessages = conversation.toMessages();\n const finalResponse = await createCompletionWithRetry(\n finalMessages as ChatCompletionMessageParam[],\n {\n model,\n openaiReasoning: openaiReasoning || undefined,\n debug,\n storage,\n logger,\n }\n );\n\n conversation.addAssistantMessage(finalResponse);\n\n return {\n finalMessage: finalResponse,\n iterations,\n toolCallsExecuted,\n conversationHistory: conversation.toMessages() as ChatCompletionMessageParam[],\n toolMetrics: this.toolMetrics,\n };\n }\n\n /**\n * Format tool result for inclusion in conversation\n */\n private formatToolResult(result: ToolResult): string {\n if (typeof result.result === 'string') {\n return result.result;\n }\n return JSON.stringify(result.result, null, 2);\n }\n\n /**\n * Log a message if logger is available\n */\n private log(message: string, data?: any): void {\n if (this.logger?.debug) {\n if (data) {\n this.logger.debug(`[AgenticExecutor] ${message}`, data);\n } else {\n this.logger.debug(`[AgenticExecutor] ${message}`);\n }\n }\n }\n}\n\n/**\n * Create and run an agentic executor\n */\nexport async function runAgentic(config: AgenticConfig): Promise<AgenticResult> {\n const executor = new AgenticExecutor(config.logger);\n return await executor.run(config);\n}\n\n","import type { Tool, OpenAITool, ToolContext } from './types';\n\n/**\n * Registry for managing tools available to agentic LLM interactions\n */\nexport class ToolRegistry {\n private tools: Map<string, Tool> = new Map();\n private context?: ToolContext;\n\n constructor(context?: ToolContext) {\n this.context = context;\n }\n\n /**\n * Register a tool in the registry\n */\n register(tool: Tool): void {\n if (this.tools.has(tool.name)) {\n throw new Error(`Tool with name \"${tool.name}\" is already registered`);\n }\n this.tools.set(tool.name, tool);\n }\n\n /**\n * Register multiple tools at once\n */\n registerAll(tools: Tool[]): void {\n for (const tool of tools) {\n this.register(tool);\n }\n }\n\n /**\n * Get a tool by name\n */\n get(name: string): Tool | undefined {\n return this.tools.get(name);\n }\n\n /**\n * Get all registered tools\n */\n getAll(): Tool[] {\n return Array.from(this.tools.values());\n }\n\n /**\n * Check if a tool exists\n */\n has(name: string): boolean {\n return this.tools.has(name);\n }\n\n /**\n * Execute a tool by name with given parameters\n */\n async execute(name: string, params: any): Promise<any> {\n const tool = this.tools.get(name);\n if (!tool) {\n throw new Error(`Tool \"${name}\" not found in registry`);\n }\n\n try {\n return await tool.execute(params, this.context);\n } catch (error: any) {\n throw new Error(`Tool \"${name}\" execution failed: ${error.message}`);\n }\n }\n\n /**\n * Convert tools to OpenAI function calling format\n */\n toOpenAIFormat(): OpenAITool[] {\n return this.getAll().map(tool => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n },\n }));\n }\n\n /**\n * Get tool definitions (without execute functions) for serialization\n */\n getDefinitions(): Array<{ name: string; description: string; parameters: any }> {\n return this.getAll().map(tool => ({\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n }));\n }\n\n /**\n * Clear all registered tools\n */\n clear(): void {\n this.tools.clear();\n }\n\n /**\n * Get count of registered tools\n */\n count(): number {\n return this.tools.size;\n }\n}\n\n/**\n * Create a new tool registry with optional context\n */\nexport function createToolRegistry(context?: ToolContext): ToolRegistry {\n return new ToolRegistry(context);\n}\n\n","import type { Tool, ToolContext } from './types';\nimport { run } from '@eldrforge/git-tools';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n/**\n * Create tools for commit message generation\n */\nexport function createCommitTools(): Tool[] {\n return [\n createGetFileHistoryTool(),\n createGetFileContentTool(),\n createSearchCodebaseTool(),\n createGetRelatedTestsTool(),\n createGetFileDependenciesTool(),\n createAnalyzeDiffSectionTool(),\n createGetRecentCommitsTool(),\n createGroupFilesByConcernTool(),\n createGetFileModificationTimesTool(),\n ];\n}\n\n/**\n * Get git commit history for specific files\n */\nfunction createGetFileHistoryTool(): Tool {\n return {\n name: 'get_file_history',\n description: 'Get git commit history for one or more files to understand their evolution and past changes',\n category: 'Understanding',\n cost: 'cheap',\n examples: [\n {\n scenario: 'Check if file has recent refactoring',\n params: { filePaths: ['src/auth.ts'], limit: 5 },\n expectedResult: 'List of recent commits affecting auth.ts'\n },\n {\n scenario: 'Understand evolution of multiple related files',\n params: { filePaths: ['src/user.ts', 'src/auth.ts'], limit: 10, format: 'detailed' },\n expectedResult: 'Detailed commit history for both files'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Array of file paths to get history for',\n items: { type: 'string', description: 'File path' },\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 10)',\n default: 10,\n },\n format: {\n type: 'string',\n description: 'Output format: \"summary\" for brief or \"detailed\" for full messages',\n enum: ['summary', 'detailed'],\n default: 'summary',\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; limit?: number; format?: 'summary' | 'detailed' }, context?: ToolContext) => {\n const { filePaths, limit = 10, format = 'summary' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Use proper shell quoting to avoid issues with parentheses in format strings\n const formatArg = format === 'detailed' ? '--format=\"%H%n%an (%ae)%n%ad%n%s%n%n%b%n---\"' : '--format=\"%h - %s (%an, %ar)\"';\n const fileArgs = filePaths.join(' ');\n const command = `git log ${formatArg} -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No history found for specified files';\n } catch (error: any) {\n throw new Error(`Failed to get file history: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get the full current content of a file\n */\nfunction createGetFileContentTool(): Tool {\n return {\n name: 'get_file_content',\n description: 'Get the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).',\n category: 'Understanding',\n cost: 'moderate',\n examples: [\n {\n scenario: 'See full class definition for modified method',\n params: { filePath: 'src/services/auth.ts', includeLineNumbers: true },\n expectedResult: 'Complete file content with line numbers'\n },\n {\n scenario: 'Check imports and structure',\n params: { filePath: 'src/utils/helpers.ts' },\n expectedResult: 'Full file content showing imports and exports'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'Path to the file',\n },\n includeLineNumbers: {\n type: 'boolean',\n description: 'Include line numbers in output (default: false)',\n default: false,\n },\n },\n required: ['filePath'],\n },\n execute: async (params: { filePath: string; includeLineNumbers?: boolean }, context?: ToolContext) => {\n const { filePath, includeLineNumbers = false } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n\n if (includeLineNumbers) {\n const lines = content.split('\\n');\n return lines.map((line: string, idx: number) => `${idx + 1}: ${line}`).join('\\n');\n }\n\n return content;\n } catch (error: any) {\n // Handle file not found gracefully - common for deleted files in diffs\n if (error.code === 'ENOENT' || error.message?.includes('ENOENT')) {\n return `File not found: ${filePath}\\n\\nThis file may have been deleted in this release or does not exist in the current working tree. Check the diff to see if this file was removed.`;\n }\n throw new Error(`Failed to read file: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Search for code patterns or identifiers across the codebase\n */\nfunction createSearchCodebaseTool(): Tool {\n return {\n name: 'search_codebase',\n description: 'Search for code patterns, function names, or text across the codebase using git grep',\n category: 'Analysis',\n cost: 'moderate',\n examples: [\n {\n scenario: 'Find all uses of a renamed function',\n params: { query: 'oldFunctionName', fileTypes: ['ts', 'tsx'] },\n expectedResult: 'List of files and lines containing the function'\n },\n {\n scenario: 'Check if pattern exists elsewhere',\n params: { query: 'pattern.*string', contextLines: 3 },\n expectedResult: 'Matching lines with surrounding context'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search pattern (can be plain text or regex)',\n },\n fileTypes: {\n type: 'array',\n description: 'Limit search to specific file extensions (e.g., [\"ts\", \"js\"])',\n items: { type: 'string', description: 'File extension' },\n },\n contextLines: {\n type: 'number',\n description: 'Number of context lines to show around matches (default: 2)',\n default: 2,\n },\n },\n required: ['query'],\n },\n execute: async (params: { query: string; fileTypes?: string[]; contextLines?: number }, context?: ToolContext) => {\n const { query, fileTypes, contextLines = 2 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Build command with proper git grep syntax: pattern comes BEFORE pathspec\n let command = `git grep -n -C ${contextLines} \"${query}\"`;\n\n if (fileTypes && fileTypes.length > 0) {\n // Add glob patterns for each file type with proper quoting\n const patterns = fileTypes.map(ext => `'*.${ext}'`).join(' ');\n command += ` -- ${patterns}`;\n }\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No matches found';\n } catch (error: any) {\n // git grep returns exit code 1 when no matches found\n if (error.message.includes('exit code 1') || error.stderr?.includes('did not match any file')) {\n return 'No matches found';\n }\n throw new Error(`Search failed: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Find test files related to changed production files\n */\nfunction createGetRelatedTestsTool(): Tool {\n return {\n name: 'get_related_tests',\n description: 'Find test files related to production files to understand what the code is supposed to do',\n category: 'Understanding',\n cost: 'cheap',\n examples: [{ scenario: 'Find tests for modified service', params: { filePaths: ['src/services/auth.ts'] }, expectedResult: 'List of related test files' }],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Production file paths',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n const relatedTests: string[] = [];\n\n for (const filePath of filePaths) {\n // Common test patterns\n const patterns = [\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.test.$1'),\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.spec.$1'),\n filePath.replace('/src/', '/tests/').replace('/lib/', '/tests/'),\n path.join('tests', filePath),\n path.join('test', filePath),\n ];\n\n for (const pattern of patterns) {\n try {\n await storage.readFile(pattern, 'utf-8');\n relatedTests.push(pattern);\n } catch {\n // File doesn't exist, continue\n }\n }\n }\n\n if (relatedTests.length === 0) {\n return 'No related test files found';\n }\n\n return `Found related test files:\\n${relatedTests.join('\\n')}`;\n },\n };\n}\n\n/**\n * Understand what files import/depend on changed files\n */\nfunction createGetFileDependenciesTool(): Tool {\n return {\n name: 'get_file_dependencies',\n description: 'Find which files import or depend on the changed files to assess change impact',\n category: 'Analysis',\n cost: 'moderate',\n examples: [{ scenario: 'Check impact of util function change', params: { filePaths: ['src/utils/format.ts'] }, expectedResult: 'Files that import format.ts' }],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to analyze dependencies for',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const results: string[] = [];\n\n for (const filePath of filePaths) {\n // Extract filename without extension for searching imports\n const fileName = path.basename(filePath, path.extname(filePath));\n\n // Search for imports of this file\n const searchPatterns = [\n `from.*['\"].*${fileName}`,\n `import.*['\"].*${fileName}`,\n `require\\\\(['\"].*${fileName}`,\n ];\n\n for (const pattern of searchPatterns) {\n try {\n const command = `git grep -l \"${pattern}\"`;\n const output = await run(command, { cwd: workingDir });\n if (output.stdout) {\n results.push(`Files importing ${filePath}:\\n${output.stdout}`);\n break; // Found matches, no need to try other patterns\n }\n } catch {\n // No matches or error, continue\n }\n }\n }\n\n return results.length > 0\n ? results.join('\\n\\n')\n : 'No files found that import the specified files';\n },\n };\n}\n\n/**\n * Get detailed analysis of specific lines in a diff\n */\nfunction createAnalyzeDiffSectionTool(): Tool {\n return {\n name: 'analyze_diff_section',\n description: 'Get expanded context around specific lines in a file to better understand changes',\n category: 'Understanding',\n cost: 'cheap',\n examples: [{ scenario: 'See context around confusing change', params: { filePath: 'src/auth.ts', startLine: 45, endLine: 52, contextLines: 15 }, expectedResult: 'Expanded code section with context' }],\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'File containing the section to analyze',\n },\n startLine: {\n type: 'number',\n description: 'Starting line number',\n },\n endLine: {\n type: 'number',\n description: 'Ending line number',\n },\n contextLines: {\n type: 'number',\n description: 'Number of additional context lines to show before and after (default: 10)',\n default: 10,\n },\n },\n required: ['filePath', 'startLine', 'endLine'],\n },\n execute: async (params: { filePath: string; startLine: number; endLine: number; contextLines?: number }, context?: ToolContext) => {\n const { filePath, startLine, endLine, contextLines = 10 } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n const actualStart = Math.max(0, startLine - contextLines - 1);\n const actualEnd = Math.min(lines.length, endLine + contextLines);\n\n const section = lines.slice(actualStart, actualEnd)\n .map((line: string, idx: number) => `${actualStart + idx + 1}: ${line}`)\n .join('\\n');\n\n return `Lines ${actualStart + 1}-${actualEnd} from ${filePath}:\\n\\n${section}`;\n } catch (error: any) {\n throw new Error(`Failed to analyze diff section: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get recent commits that touched the same files\n */\nfunction createGetRecentCommitsTool(): Tool {\n return {\n name: 'get_recent_commits',\n description: 'Get recent commits that modified the same files to understand recent work in this area',\n category: 'Understanding',\n cost: 'cheap',\n examples: [{ scenario: 'Check for duplicate commit messages', params: { filePaths: ['src/auth.ts'], since: '1 week ago', limit: 5 }, expectedResult: 'Recent commits to auth.ts' }],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to check for recent commits',\n items: { type: 'string', description: 'File path' },\n },\n since: {\n type: 'string',\n description: 'Time period to look back (e.g., \"1 week ago\", \"2 days ago\")',\n default: '1 week ago',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 5)',\n default: 5,\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; since?: string; limit?: number }, context?: ToolContext) => {\n const { filePaths, since = '1 week ago', limit = 5 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const fileArgs = filePaths.join(' ');\n const command = `git log --format=\"%h - %s (%an, %ar)\" --since=\"${since}\" -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || `No commits found in the specified time period (${since})`;\n } catch (error: any) {\n throw new Error(`Failed to get recent commits: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Analyze changed files and suggest logical groupings\n */\nfunction createGroupFilesByConcernTool(): Tool {\n return {\n name: 'group_files_by_concern',\n description: 'Analyze changed files and suggest logical groupings that might represent separate commits',\n category: 'Organization',\n cost: 'cheap',\n examples: [\n {\n scenario: 'Check if multiple unrelated changes should be split',\n params: { filePaths: ['src/auth.ts', 'README.md', 'tests/auth.test.ts', 'package.json'] },\n expectedResult: 'Files grouped by concern with split suggestions'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'All changed files to analyze',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }) => {\n const { filePaths } = params;\n\n // Group files by directory and type\n const groups: Record<string, string[]> = {};\n\n for (const filePath of filePaths) {\n const dir = path.dirname(filePath);\n const ext = path.extname(filePath);\n const basename = path.basename(filePath, ext);\n\n // Determine category\n let category = 'other';\n\n if (basename.includes('.test') || basename.includes('.spec') || dir.includes('test')) {\n category = 'tests';\n } else if (filePath.includes('package.json') || filePath.includes('package-lock.json')) {\n category = 'dependencies';\n } else if (ext === '.md' || basename === 'README') {\n category = 'documentation';\n } else if (dir.includes('src') || dir.includes('lib')) {\n // Group by module/subdirectory\n category = `source:${dir.split('/').slice(0, 3).join('/')}`;\n }\n\n if (!groups[category]) {\n groups[category] = [];\n }\n groups[category].push(filePath);\n }\n\n // Format the groupings\n const output = Object.entries(groups)\n .map(([category, files]) => {\n return `${category} (${files.length} files):\\n${files.map(f => ` - ${f}`).join('\\n')}`;\n })\n .join('\\n\\n');\n\n const groupCount = Object.keys(groups).length;\n const suggestion = groupCount > 1\n ? `\\n\\nSuggestion: These ${groupCount} groups might be better as separate commits if they represent different concerns.`\n : '\\n\\nSuggestion: All files appear to be related and should be in a single commit.';\n\n return output + suggestion;\n },\n };\n}\n\n/**\n * Get modification times for files to identify temporal clusters\n */\nfunction createGetFileModificationTimesTool(): Tool {\n return {\n name: 'get_file_modification_times',\n description: 'Get modification timestamps for changed files. Temporal proximity is one signal (among others) that can help identify related changes. Files modified close together MAY be part of the same logical change, but this is not guaranteed - always cross-reference with logical groupings.',\n category: 'Organization',\n cost: 'cheap',\n examples: [\n {\n scenario: 'Identify files modified together vs at different times',\n params: { filePaths: ['src/auth.ts', 'src/user.ts', 'README.md', 'tests/auth.test.ts'] },\n expectedResult: 'Files with timestamps grouped by temporal proximity'\n }\n ],\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'All changed files to analyze',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n interface FileTimeInfo {\n file: string;\n mtime: Date;\n mtimeMs: number;\n }\n\n const fileInfos: FileTimeInfo[] = [];\n const errors: string[] = [];\n\n for (const filePath of filePaths) {\n try {\n const fullPath = path.isAbsolute(filePath) ? filePath : path.join(workingDir, filePath);\n const stat = fs.statSync(fullPath);\n fileInfos.push({\n file: filePath,\n mtime: stat.mtime,\n mtimeMs: stat.mtimeMs,\n });\n } catch {\n // File might be deleted, try to get info from git\n errors.push(filePath);\n }\n }\n\n // Sort by modification time\n fileInfos.sort((a, b) => a.mtimeMs - b.mtimeMs);\n\n // Group files into temporal clusters (files within 10 minutes of each other)\n const CLUSTER_THRESHOLD_MS = 10 * 60 * 1000; // 10 minutes\n const clusters: FileTimeInfo[][] = [];\n let currentCluster: FileTimeInfo[] = [];\n\n for (const info of fileInfos) {\n if (currentCluster.length === 0) {\n currentCluster.push(info);\n } else {\n const lastFile = currentCluster[currentCluster.length - 1];\n if (info.mtimeMs - lastFile.mtimeMs <= CLUSTER_THRESHOLD_MS) {\n currentCluster.push(info);\n } else {\n clusters.push(currentCluster);\n currentCluster = [info];\n }\n }\n }\n if (currentCluster.length > 0) {\n clusters.push(currentCluster);\n }\n\n // Format output\n let output = `## File Modification Times (sorted oldest to newest)\\n\\n`;\n\n for (const info of fileInfos) {\n const timeStr = info.mtime.toISOString().replace('T', ' ').replace(/\\.\\d{3}Z$/, '');\n output += `${timeStr} ${info.file}\\n`;\n }\n\n if (errors.length > 0) {\n output += `\\n## Files not found (possibly deleted):\\n`;\n output += errors.map(f => ` - ${f}`).join('\\n');\n }\n\n // Add temporal cluster analysis\n output += `\\n\\n## Temporal Clusters (files modified within 10 minutes of each other)\\n\\n`;\n\n if (clusters.length === 1) {\n output += `All ${fileInfos.length} files were modified in a single work session.\\n`;\n } else {\n output += `Found ${clusters.length} distinct work sessions:\\n\\n`;\n\n clusters.forEach((cluster, idx) => {\n const startTime = cluster[0].mtime.toISOString().replace('T', ' ').replace(/\\.\\d{3}Z$/, '');\n const endTime = cluster[cluster.length - 1].mtime.toISOString().replace('T', ' ').replace(/\\.\\d{3}Z$/, '');\n const durationMs = cluster[cluster.length - 1].mtimeMs - cluster[0].mtimeMs;\n const durationMins = Math.round(durationMs / 60000);\n\n output += `### Session ${idx + 1} (${cluster.length} files, ${durationMins} min span)\\n`;\n output += `Time: ${startTime} to ${endTime}\\n`;\n output += `Files:\\n`;\n output += cluster.map(f => ` - ${f.file}`).join('\\n');\n output += '\\n\\n';\n });\n\n output += `\\n**Note**: These ${clusters.length} temporal clusters may indicate separate work sessions. Cross-reference with logical groupings to determine if they represent distinct changes worth splitting.`;\n }\n\n return output;\n },\n };\n}\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { runAgentic, type AgenticConfig, type ToolExecutionMetric } from './executor';\nimport { createToolRegistry } from '../tools/registry';\nimport { createCommitTools } from '../tools/commit-tools';\nimport type { StorageAdapter, Logger } from '../types';\nimport { generateToolGuidance } from '@riotprompt/riotprompt';\n\nexport interface AgenticCommitConfig {\n changedFiles: string[];\n diffContent: string;\n userDirection?: string;\n logContext?: string;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n debugRequestFile?: string;\n debugResponseFile?: string;\n storage?: StorageAdapter;\n logger?: Logger;\n openaiReasoning?: 'low' | 'medium' | 'high';\n tokenBudget?: {\n max: number;\n reserveForResponse?: number;\n strategy?: 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n onBudgetExceeded?: 'compress' | 'error' | 'warn' | 'truncate';\n };\n}\n\nexport interface AgenticCommitResult {\n commitMessage: string;\n iterations: number;\n toolCallsExecuted: number;\n suggestedSplits: Array<{\n files: string[];\n message: string;\n rationale: string;\n }>;\n conversationHistory: ChatCompletionMessageParam[];\n toolMetrics: ToolExecutionMetric[];\n}\n\n/**\n * Run agentic commit message generation\n */\nexport async function runAgenticCommit(config: AgenticCommitConfig): Promise<AgenticCommitResult> {\n const {\n changedFiles,\n diffContent,\n userDirection,\n logContext,\n model = 'gpt-4o',\n maxIterations = 10,\n debug = false,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget,\n } = config;\n\n // Create tool registry with context\n const toolRegistry = createToolRegistry({\n workingDirectory: process.cwd(),\n storage,\n logger,\n });\n\n // Register commit-specific tools\n const tools = createCommitTools();\n toolRegistry.registerAll(tools);\n\n // Generate automatic tool guidance from riotprompt\n const toolGuidance = generateToolGuidance(tools, {\n strategy: 'adaptive',\n includeExamples: true,\n explainWhenToUse: true,\n includeCategories: true,\n });\n\n // Build initial system prompt with tool guidance\n const systemPrompt = buildSystemPrompt(toolGuidance);\n\n // Build initial user message\n const userMessage = buildUserMessage(changedFiles, diffContent, userDirection, logContext);\n\n // Prepare messages for agentic loop\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n // Run agentic loop with optional token budget\n const agenticConfig: AgenticConfig = {\n messages,\n tools: toolRegistry,\n model,\n maxIterations,\n debug,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget: tokenBudget || {\n max: 150000,\n reserveForResponse: 4000,\n strategy: 'fifo',\n onBudgetExceeded: 'compress'\n },\n };\n\n const result = await runAgentic(agenticConfig);\n\n // Parse the final message to extract commit message and suggested splits\n const parsed = parseAgenticResult(result.finalMessage);\n\n return {\n commitMessage: parsed.commitMessage,\n iterations: result.iterations,\n toolCallsExecuted: result.toolCallsExecuted,\n suggestedSplits: parsed.suggestedSplits,\n conversationHistory: result.conversationHistory,\n toolMetrics: result.toolMetrics,\n };\n}\n\n/**\n * Build the system prompt for agentic commit generation\n */\nfunction buildSystemPrompt(toolGuidance: string): string {\n return `You are a professional software engineer writing commit messages for your team.\n\n${toolGuidance}\n\n## Your Task\n\nAnalyze the staged changes and determine the best way to commit them. Your primary goal is to create **meaningful, atomic commits** that each represent a single logical change.\n\n**CRITICAL**: When there are many changed files, especially after a long work session (multiple hours), you should almost always split them into multiple commits. A single commit with 10+ files usually indicates multiple distinct changes that should be separated.\n\nThink about:\n- What distinct features, fixes, or improvements are represented?\n- Are there natural groupings by functionality, module, or purpose?\n- When were files modified relative to each other?\n- What should reviewers focus on in each commit?\n\n## Investigation Strategy\n\nFor any non-trivial set of changes, gather multiple signals to understand how to group commits:\n\n1. **Check file modification times** using \\`get_file_modification_times\\`\n - This reveals *when* files were changed relative to each other\n - Files modified close together *may* be part of the same logical change\n - Large temporal gaps *can* indicate separate work sessions\n - Note: temporal proximity is one signal, not a guarantee of relatedness\n\n2. **Understand logical relationships** using \\`group_files_by_concern\\`\n - Groups by module, type (tests, docs, source), and directory structure\n - Reveals which files are functionally related regardless of when they were modified\n\n3. **Cross-reference both signals** to make informed decisions:\n - Files modified together AND logically related → strong candidate for same commit\n - Files modified apart BUT logically related → might still belong together\n - Files modified together BUT logically unrelated → consider splitting\n - Use your judgment - neither signal is definitive on its own\n\n4. **Investigate further** as needed:\n - get_file_content - see full context when diffs are unclear\n - get_file_history - understand how code evolved\n - get_file_dependencies - assess impact of changes\n - get_recent_commits - avoid duplicate messages\n - get_related_tests - understand behavior changes\n - search_codebase - find usage patterns\n\n## When to Split Commits\n\n**Prefer multiple commits when:**\n- Changes span multiple hours of work (check modification times!)\n- Different logical features or fixes are included\n- Test changes could be separated from production code changes\n- Documentation updates are unrelated to code changes\n- Refactoring is mixed with feature work\n- Configuration changes are mixed with implementation changes\n- Files in different modules/packages are changed for different reasons\n\n**Keep as one commit when:**\n- All changes are part of a single, cohesive feature\n- Files were modified together in a focused work session\n- Test changes directly test the production code changes\n- The changes tell a single coherent story\n\n**Default bias**: When in doubt about whether to split, **prefer splitting**. It's better to have too many focused commits than too few bloated ones. A good commit should be understandable and reviewable in isolation.\n\n## Important Context Guidelines\n\nIf additional context is provided (from context files or other sources), use your judgment:\n- If the context is relevant to these specific changes, incorporate it\n- If the context describes unrelated changes or other packages, ignore it\n- Don't force connections between unrelated information\n- Focus on accurately describing what actually changed\n\n## Writing Style\n\nWrite naturally and directly:\n- Use plain language, not corporate speak\n- Be specific and concrete\n- Avoid buzzwords and jargon\n- No emojis or excessive punctuation\n- No phrases like \"this commit\" or \"this PR\"\n- No meta-commentary about the commit itself\n\nFollow conventional commit format when appropriate (feat:, fix:, refactor:, docs:, test:, chore:), but prioritize clarity over formality.\n\n## Output Format\n\nWhen ready, format your response as:\n\nCOMMIT_MESSAGE:\n[Your commit message here - only for the FIRST group of changes if splitting]\n\nIf changes should be split into multiple commits (which is often the case with large changesets):\n\nSUGGESTED_SPLITS:\nSplit 1:\nFiles: [list of files]\nRationale: [why these belong together - mention temporal clustering and/or logical relationship]\nMessage: [commit message for this split]\n\nSplit 2:\nFiles: [list of files]\nRationale: [why these belong together]\nMessage: [commit message for this split]\n\nSplit 3:\n...\n\nOutput only the commit message and splits. No conversational remarks or follow-up offers.`;\n}\n\n/**\n * Build the initial user message\n */\nfunction buildUserMessage(\n changedFiles: string[],\n diffContent: string,\n userDirection?: string,\n logContext?: string\n): string {\n const fileCount = changedFiles.length;\n const manyFiles = fileCount >= 5;\n\n let message = `I have staged changes that need a commit message.\n\nChanged files (${fileCount}):\n${changedFiles.map(f => ` - ${f}`).join('\\n')}\n\nDiff:\n${diffContent}`;\n\n if (userDirection) {\n message += `\\n\\nUser direction: ${userDirection}`;\n }\n\n if (logContext) {\n message += `\\n\\nRecent commit history for context:\n${logContext}`;\n }\n\n message += `\\n\\n## Your Analysis Task\n\n${manyFiles ? `With ${fileCount} files changed, consider whether these represent multiple distinct changes that should be split into separate commits.\n\n` : ''}Gather signals to understand the changes:\n1. Use \\`get_file_modification_times\\` to see when files were modified relative to each other\n2. Use \\`group_files_by_concern\\` to understand how files relate by type/purpose\n3. Cross-reference both signals - temporal proximity and logical relatedness - to determine the best commit structure\n\nConsider:\n- What distinct features, fixes, or improvements are included?\n- Are files that were modified together also logically related?\n- Would separate commits make the history more understandable?\n\n${manyFiles ? 'With many files, consider whether multiple focused commits would be clearer than one large commit.' : 'If changes represent multiple logical concerns, suggest splits.'}\n\nIf context information is provided, use it only if relevant to these specific changes.\nDon't force connections that don't exist - focus on what actually changed.`;\n\n return message;\n}\n\n/**\n * Parse the agentic result to extract commit message and splits\n */\nfunction parseAgenticResult(finalMessage: string): {\n commitMessage: string;\n suggestedSplits: Array<{ files: string[]; message: string; rationale: string }>;\n} {\n // Look for COMMIT_MESSAGE: marker\n const commitMatch = finalMessage.match(/COMMIT_MESSAGE:\\s*\\n([\\s\\S]*?)(?=\\n\\nSUGGESTED_SPLITS:|$)/);\n const commitMessage = commitMatch ? commitMatch[1].trim() : finalMessage.trim();\n\n // Look for SUGGESTED_SPLITS: section\n const suggestedSplits: Array<{ files: string[]; message: string; rationale: string }> = [];\n const splitsMatch = finalMessage.match(/SUGGESTED_SPLITS:\\s*\\n([\\s\\S]*)/);\n\n if (splitsMatch) {\n const splitsText = splitsMatch[1];\n // Parse each split\n const splitRegex = /Split \\d+:\\s*\\nFiles: ([\\s\\S]*?)\\nRationale: ([\\s\\S]*?)\\nMessage: ([\\s\\S]*?)(?=\\n\\nSplit \\d+:|$)/g;\n let match;\n\n while ((match = splitRegex.exec(splitsText)) !== null) {\n const filesText = match[1].trim();\n const files = filesText\n .split('\\n')\n .map(line => line.trim().replace(/^[-*]\\s*/, ''))\n .filter(line => line.length > 0);\n\n suggestedSplits.push({\n files,\n rationale: match[2].trim(),\n message: match[3].trim(),\n });\n }\n }\n\n return { commitMessage, suggestedSplits };\n}\n\n","import type { Tool, ToolContext } from './types';\nimport { run } from '@eldrforge/git-tools';\nimport * as path from 'path';\n\n/**\n * Create tools for release notes generation\n */\nexport function createReleaseTools(): Tool[] {\n return [\n createGetFileHistoryTool(),\n createGetFileContentTool(),\n createSearchCodebaseTool(),\n createGetRelatedTestsTool(),\n createGetFileDependenciesTool(),\n createAnalyzeDiffSectionTool(),\n createGetRecentCommitsTool(),\n createGroupFilesByConcernTool(),\n createGetTagHistoryTool(),\n createComparePreviousReleaseTool(),\n createGetReleaseStatsTool(),\n createGetBreakingChangesTool(),\n createAnalyzeCommitPatternsTool(),\n ];\n}\n\n/**\n * Get git commit history for specific files\n */\nfunction createGetFileHistoryTool(): Tool {\n return {\n name: 'get_file_history',\n description: 'Get git commit history for one or more files to understand their evolution and past changes',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Array of file paths to get history for',\n items: { type: 'string', description: 'File path' },\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 10)',\n default: 10,\n },\n format: {\n type: 'string',\n description: 'Output format: \"summary\" for brief or \"detailed\" for full messages',\n enum: ['summary', 'detailed'],\n default: 'summary',\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; limit?: number; format?: 'summary' | 'detailed' }, context?: ToolContext) => {\n const { filePaths, limit = 10, format = 'summary' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Use proper shell quoting to avoid issues with parentheses in format strings\n const formatArg = format === 'detailed' ? '--format=\"%H%n%an (%ae)%n%ad%n%s%n%n%b%n---\"' : '--format=\"%h - %s (%an, %ar)\"';\n const fileArgs = filePaths.join(' ');\n const command = `git log ${formatArg} -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No history found for specified files';\n } catch (error: any) {\n throw new Error(`Failed to get file history: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get the full current content of a file\n */\nfunction createGetFileContentTool(): Tool {\n return {\n name: 'get_file_content',\n description: 'Get the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'Path to the file',\n },\n includeLineNumbers: {\n type: 'boolean',\n description: 'Include line numbers in output (default: false)',\n default: false,\n },\n },\n required: ['filePath'],\n },\n execute: async (params: { filePath: string; includeLineNumbers?: boolean }, context?: ToolContext) => {\n const { filePath, includeLineNumbers = false } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n\n if (includeLineNumbers) {\n const lines = content.split('\\n');\n return lines.map((line: string, idx: number) => `${idx + 1}: ${line}`).join('\\n');\n }\n\n return content;\n } catch (error: any) {\n // Handle file not found gracefully - common for deleted files in diffs\n if (error.code === 'ENOENT' || error.message?.includes('ENOENT')) {\n return `File not found: ${filePath}\\n\\nThis file may have been deleted in this release or does not exist in the current working tree. Check the diff to see if this file was removed.`;\n }\n throw new Error(`Failed to read file: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Search for code patterns or identifiers across the codebase\n */\nfunction createSearchCodebaseTool(): Tool {\n return {\n name: 'search_codebase',\n description: 'Search for code patterns, function names, or text across the codebase using git grep',\n parameters: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search pattern (can be plain text or regex)',\n },\n fileTypes: {\n type: 'array',\n description: 'Limit search to specific file extensions (e.g., [\"ts\", \"js\"])',\n items: { type: 'string', description: 'File extension' },\n },\n contextLines: {\n type: 'number',\n description: 'Number of context lines to show around matches (default: 2)',\n default: 2,\n },\n },\n required: ['query'],\n },\n execute: async (params: { query: string; fileTypes?: string[]; contextLines?: number }, context?: ToolContext) => {\n const { query, fileTypes, contextLines = 2 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n // Build command with proper git grep syntax: pattern comes BEFORE pathspec\n let command = `git grep -n -C ${contextLines} \"${query}\"`;\n\n if (fileTypes && fileTypes.length > 0) {\n // Add glob patterns for each file type with proper quoting\n const patterns = fileTypes.map(ext => `'*.${ext}'`).join(' ');\n command += ` -- ${patterns}`;\n }\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || 'No matches found';\n } catch (error: any) {\n // git grep returns exit code 1 when no matches found\n if (error.message.includes('exit code 1') || error.stderr?.includes('did not match any file')) {\n return 'No matches found';\n }\n throw new Error(`Search failed: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Find test files related to changed production files\n */\nfunction createGetRelatedTestsTool(): Tool {\n return {\n name: 'get_related_tests',\n description: 'Find test files related to production files to understand what the code is supposed to do',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Production file paths',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n const relatedTests: string[] = [];\n\n for (const filePath of filePaths) {\n // Common test patterns\n const patterns = [\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.test.$1'),\n filePath.replace(/\\.(ts|js|tsx|jsx)$/, '.spec.$1'),\n filePath.replace('/src/', '/tests/').replace('/lib/', '/tests/'),\n path.join('tests', filePath),\n path.join('test', filePath),\n ];\n\n for (const pattern of patterns) {\n try {\n await storage.readFile(pattern, 'utf-8');\n relatedTests.push(pattern);\n } catch {\n // File doesn't exist, continue\n }\n }\n }\n\n if (relatedTests.length === 0) {\n return 'No related test files found';\n }\n\n return `Found related test files:\\n${relatedTests.join('\\n')}`;\n },\n };\n}\n\n/**\n * Understand what files import/depend on changed files\n */\nfunction createGetFileDependenciesTool(): Tool {\n return {\n name: 'get_file_dependencies',\n description: 'Find which files import or depend on the changed files to assess change impact',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to analyze dependencies for',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }, context?: ToolContext) => {\n const { filePaths } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const results: string[] = [];\n\n for (const filePath of filePaths) {\n // Extract filename without extension for searching imports\n const fileName = path.basename(filePath, path.extname(filePath));\n\n // Search for imports of this file\n const searchPatterns = [\n `from.*['\"].*${fileName}`,\n `import.*['\"].*${fileName}`,\n `require\\\\(['\"].*${fileName}`,\n ];\n\n for (const pattern of searchPatterns) {\n try {\n const command = `git grep -l \"${pattern}\"`;\n const output = await run(command, { cwd: workingDir });\n if (output.stdout) {\n results.push(`Files importing ${filePath}:\\n${output.stdout}`);\n break; // Found matches, no need to try other patterns\n }\n } catch {\n // No matches or error, continue\n }\n }\n }\n\n return results.length > 0\n ? results.join('\\n\\n')\n : 'No files found that import the specified files';\n },\n };\n}\n\n/**\n * Get detailed analysis of specific lines in a diff\n */\nfunction createAnalyzeDiffSectionTool(): Tool {\n return {\n name: 'analyze_diff_section',\n description: 'Get expanded context around specific lines in a file to better understand changes',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'File containing the section to analyze',\n },\n startLine: {\n type: 'number',\n description: 'Starting line number',\n },\n endLine: {\n type: 'number',\n description: 'Ending line number',\n },\n contextLines: {\n type: 'number',\n description: 'Number of additional context lines to show before and after (default: 10)',\n default: 10,\n },\n },\n required: ['filePath', 'startLine', 'endLine'],\n },\n execute: async (params: { filePath: string; startLine: number; endLine: number; contextLines?: number }, context?: ToolContext) => {\n const { filePath, startLine, endLine, contextLines = 10 } = params;\n const storage = context?.storage;\n\n if (!storage) {\n throw new Error('Storage adapter not available in context');\n }\n\n try {\n const content = await storage.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n const actualStart = Math.max(0, startLine - contextLines - 1);\n const actualEnd = Math.min(lines.length, endLine + contextLines);\n\n const section = lines.slice(actualStart, actualEnd)\n .map((line: string, idx: number) => `${actualStart + idx + 1}: ${line}`)\n .join('\\n');\n\n return `Lines ${actualStart + 1}-${actualEnd} from ${filePath}:\\n\\n${section}`;\n } catch (error: any) {\n throw new Error(`Failed to analyze diff section: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get recent commits that touched the same files\n */\nfunction createGetRecentCommitsTool(): Tool {\n return {\n name: 'get_recent_commits',\n description: 'Get recent commits that modified the same files to understand recent work in this area',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'Files to check for recent commits',\n items: { type: 'string', description: 'File path' },\n },\n since: {\n type: 'string',\n description: 'Time period to look back (e.g., \"1 week ago\", \"2 days ago\")',\n default: '1 week ago',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 5)',\n default: 5,\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[]; since?: string; limit?: number }, context?: ToolContext) => {\n const { filePaths, since = '1 week ago', limit = 5 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const fileArgs = filePaths.join(' ');\n const command = `git log --format=\"%h - %s (%an, %ar)\" --since=\"${since}\" -n ${limit} -- ${fileArgs}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n return output.stdout || `No commits found in the specified time period (${since})`;\n } catch (error: any) {\n throw new Error(`Failed to get recent commits: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Analyze changed files and suggest logical groupings\n */\nfunction createGroupFilesByConcernTool(): Tool {\n return {\n name: 'group_files_by_concern',\n description: 'Analyze changed files and suggest logical groupings that might represent separate concerns',\n parameters: {\n type: 'object',\n properties: {\n filePaths: {\n type: 'array',\n description: 'All changed files to analyze',\n items: { type: 'string', description: 'File path' },\n },\n },\n required: ['filePaths'],\n },\n execute: async (params: { filePaths: string[] }) => {\n const { filePaths } = params;\n\n // Group files by directory and type\n const groups: Record<string, string[]> = {};\n\n for (const filePath of filePaths) {\n const dir = path.dirname(filePath);\n const ext = path.extname(filePath);\n const basename = path.basename(filePath, ext);\n\n // Determine category\n let category = 'other';\n\n if (basename.includes('.test') || basename.includes('.spec') || dir.includes('test')) {\n category = 'tests';\n } else if (filePath.includes('package.json') || filePath.includes('package-lock.json')) {\n category = 'dependencies';\n } else if (ext === '.md' || basename === 'README') {\n category = 'documentation';\n } else if (dir.includes('src') || dir.includes('lib')) {\n // Group by module/subdirectory\n category = `source:${dir.split('/').slice(0, 3).join('/')}`;\n }\n\n if (!groups[category]) {\n groups[category] = [];\n }\n groups[category].push(filePath);\n }\n\n // Format the groupings\n const output = Object.entries(groups)\n .map(([category, files]) => {\n return `${category} (${files.length} files):\\n${files.map(f => ` - ${f}`).join('\\n')}`;\n })\n .join('\\n\\n');\n\n const groupCount = Object.keys(groups).length;\n const suggestion = groupCount > 1\n ? `\\n\\nSuggestion: These ${groupCount} groups represent different concerns in the release.`\n : '\\n\\nSuggestion: All files appear to be related to a single concern.';\n\n return output + suggestion;\n },\n };\n}\n\n/**\n * Get history of previous release tags\n */\nfunction createGetTagHistoryTool(): Tool {\n return {\n name: 'get_tag_history',\n description: 'Get the history of previous release tags to understand release patterns and versioning',\n category: 'Release Analysis',\n cost: 'cheap',\n examples: [{ scenario: 'Check recent version tags', params: { limit: 5, pattern: 'v*' }, expectedResult: 'List of recent version tags with dates' }],\n parameters: {\n type: 'object',\n properties: {\n limit: {\n type: 'number',\n description: 'Number of recent tags to retrieve (default: 10)',\n default: 10,\n },\n pattern: {\n type: 'string',\n description: 'Filter tags by pattern (e.g., \"v*\" for version tags)',\n },\n },\n },\n execute: async (params: { limit?: number; pattern?: string }, context?: ToolContext) => {\n const { limit = 10, pattern } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n let command = 'git tag --sort=-creatordate';\n if (pattern) {\n command += ` -l \"${pattern}\"`;\n }\n command += ` | head -n ${limit}`;\n\n try {\n const output = await run(command, { cwd: workingDir });\n if (!output.stdout) {\n return 'No tags found in repository';\n }\n\n // Get detailed info for each tag\n const tags = output.stdout.trim().split('\\n');\n const detailedInfo: string[] = [];\n\n for (const tag of tags) {\n try {\n const tagInfo = await run(`git show --quiet --format=\"%ci - %s\" ${tag}`, { cwd: workingDir });\n detailedInfo.push(`${tag}: ${tagInfo.stdout.trim()}`);\n } catch {\n detailedInfo.push(`${tag}: (no info available)`);\n }\n }\n\n return `Recent release tags:\\n${detailedInfo.join('\\n')}`;\n } catch (error: any) {\n throw new Error(`Failed to get tag history: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Compare this release with a previous release\n */\nfunction createComparePreviousReleaseTool(): Tool {\n return {\n name: 'compare_previous_release',\n description: 'Compare this release with a previous release to understand what changed between versions',\n category: 'Release Analysis',\n cost: 'moderate',\n examples: [{ scenario: 'Compare with last release', params: { previousTag: 'v1.0.0', currentRef: 'HEAD' }, expectedResult: 'Commit count and file change statistics' }],\n parameters: {\n type: 'object',\n properties: {\n previousTag: {\n type: 'string',\n description: 'Previous release tag to compare against',\n },\n currentRef: {\n type: 'string',\n description: 'Current reference (default: HEAD)',\n default: 'HEAD',\n },\n statsOnly: {\n type: 'boolean',\n description: 'Return only statistics, not full diff (default: true)',\n default: true,\n },\n },\n required: ['previousTag'],\n },\n execute: async (params: { previousTag: string; currentRef?: string; statsOnly?: boolean }, context?: ToolContext) => {\n const { previousTag, currentRef = 'HEAD', statsOnly = true } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get commit count\n const commitCountCmd = `git rev-list --count ${previousTag}..${currentRef}`;\n const commitCount = await run(commitCountCmd, { cwd: workingDir });\n\n // Get file change stats\n const statsCmd = `git diff --stat ${previousTag}..${currentRef}`;\n const stats = await run(statsCmd, { cwd: workingDir });\n\n let result = `Comparison between ${previousTag} and ${currentRef}:\\n\\n`;\n result += `Commits: ${commitCount.stdout.trim()}\\n\\n`;\n result += `File changes:\\n${stats.stdout}`;\n\n if (!statsOnly) {\n // Get short log of commits\n const logCmd = `git log --oneline ${previousTag}..${currentRef}`;\n const log = await run(logCmd, { cwd: workingDir });\n result += `\\n\\nCommit summary:\\n${log.stdout}`;\n }\n\n return result;\n } catch (error: any) {\n throw new Error(`Failed to compare releases: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get statistics about the release\n */\nfunction createGetReleaseStatsTool(): Tool {\n return {\n name: 'get_release_stats',\n description: 'Get comprehensive statistics about the release including contributors, file changes, and commit patterns',\n category: 'Release Analysis',\n cost: 'moderate',\n examples: [{ scenario: 'Get release overview', params: { fromRef: 'v1.0.0', toRef: 'HEAD' }, expectedResult: 'Contributors, file changes, and top modified files' }],\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting reference for the release range',\n },\n toRef: {\n type: 'string',\n description: 'Ending reference for the release range (default: HEAD)',\n default: 'HEAD',\n },\n },\n required: ['fromRef'],\n },\n execute: async (params: { fromRef: string; toRef?: string }, context?: ToolContext) => {\n const { fromRef, toRef = 'HEAD' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n const results: string[] = [];\n\n // Commit count\n const commitCount = await run(`git rev-list --count ${fromRef}..${toRef}`, { cwd: workingDir });\n results.push(`Total commits: ${commitCount.stdout.trim()}`);\n\n // Contributors\n const contributors = await run(\n `git shortlog -sn ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n results.push(`\\nContributors:\\n${contributors.stdout}`);\n\n // File change summary\n const fileStats = await run(\n `git diff --shortstat ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n results.push(`\\nFile changes: ${fileStats.stdout.trim()}`);\n\n // Most changed files\n const topFiles = await run(\n `git diff --stat ${fromRef}..${toRef} | sort -k2 -rn | head -n 10`,\n { cwd: workingDir }\n );\n results.push(`\\nTop 10 most changed files:\\n${topFiles.stdout}`);\n\n return results.join('\\n');\n } catch (error: any) {\n throw new Error(`Failed to get release stats: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Identify potential breaking changes\n */\nfunction createGetBreakingChangesTool(): Tool {\n return {\n name: 'get_breaking_changes',\n description: 'Search for potential breaking changes by looking for specific patterns in commits and diffs',\n category: 'Release Analysis',\n cost: 'expensive',\n examples: [{ scenario: 'Check for breaking changes', params: { fromRef: 'v1.0.0', toRef: 'HEAD' }, expectedResult: 'List of potential breaking changes found' }],\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting reference for the release range',\n },\n toRef: {\n type: 'string',\n description: 'Ending reference for the release range (default: HEAD)',\n default: 'HEAD',\n },\n },\n required: ['fromRef'],\n },\n execute: async (params: { fromRef: string; toRef?: string }, context?: ToolContext) => {\n const { fromRef, toRef = 'HEAD' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n const results: string[] = [];\n\n try {\n // Search for BREAKING CHANGE in commit messages\n const breakingCommits = await run(\n `git log --grep=\"BREAKING CHANGE\" --oneline ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n if (breakingCommits.stdout) {\n results.push(`Commits with BREAKING CHANGE:\\n${breakingCommits.stdout}`);\n }\n\n // Search for removed exports\n const removedExports = await run(\n `git diff ${fromRef}..${toRef} | grep \"^-export\"`,\n { cwd: workingDir }\n );\n if (removedExports.stdout) {\n results.push(`\\nRemoved exports (potential breaking):\\n${removedExports.stdout}`);\n }\n\n // Search for changed function signatures\n const changedSignatures = await run(\n `git diff ${fromRef}..${toRef} | grep -E \"^[-+].*function|^[-+].*const.*=.*=>|^[-+].*interface|^[-+].*type.*=\"`,\n { cwd: workingDir }\n );\n if (changedSignatures.stdout) {\n results.push(`\\nChanged function/type signatures (review for breaking changes):\\n${changedSignatures.stdout.split('\\n').slice(0, 20).join('\\n')}`);\n }\n\n if (results.length === 0) {\n return 'No obvious breaking changes detected. Manual review recommended for API changes.';\n }\n\n return results.join('\\n\\n');\n } catch {\n // Some commands may fail if no matches found\n if (results.length > 0) {\n return results.join('\\n\\n');\n }\n return 'No obvious breaking changes detected. Manual review recommended for API changes.';\n }\n },\n };\n}\n\n/**\n * Analyze commit patterns to identify themes\n */\nfunction createAnalyzeCommitPatternsTool(): Tool {\n return {\n name: 'analyze_commit_patterns',\n description: 'Analyze commit messages to identify patterns and themes in the release',\n category: 'Release Analysis',\n cost: 'cheap',\n examples: [{ scenario: 'Find commit themes', params: { fromRef: 'v1.0.0', toRef: 'HEAD' }, expectedResult: 'Commit types and top keywords' }],\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting reference for the release range',\n },\n toRef: {\n type: 'string',\n description: 'Ending reference for the release range (default: HEAD)',\n default: 'HEAD',\n },\n },\n required: ['fromRef'],\n },\n execute: async (params: { fromRef: string; toRef?: string }, context?: ToolContext) => {\n const { fromRef, toRef = 'HEAD' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n const results: string[] = [];\n\n // Get all commit messages\n const commits = await run(\n `git log --format=\"%s\" ${fromRef}..${toRef}`,\n { cwd: workingDir }\n );\n\n const messages = commits.stdout.trim().split('\\n');\n\n // Count conventional commit types\n const types: Record<string, number> = {};\n const keywords: Record<string, number> = {};\n\n for (const msg of messages) {\n // Check for conventional commit format\n const conventionalMatch = msg.match(/^(\\w+)(\\(.+?\\))?:/);\n if (conventionalMatch) {\n const type = conventionalMatch[1];\n types[type] = (types[type] || 0) + 1;\n }\n\n // Extract keywords (words longer than 4 chars)\n const words = msg.toLowerCase().match(/\\b\\w{5,}\\b/g) || [];\n for (const word of words) {\n keywords[word] = (keywords[word] || 0) + 1;\n }\n }\n\n // Format commit types\n if (Object.keys(types).length > 0) {\n results.push('Commit types:');\n const sortedTypes = Object.entries(types)\n .sort((a, b) => b[1] - a[1])\n .map(([type, count]) => ` ${type}: ${count}`)\n .join('\\n');\n results.push(sortedTypes);\n }\n\n // Format top keywords\n const topKeywords = Object.entries(keywords)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 15)\n .map(([word, count]) => ` ${word}: ${count}`)\n .join('\\n');\n\n if (topKeywords) {\n results.push('\\nTop keywords in commits:');\n results.push(topKeywords);\n }\n\n return results.join('\\n');\n } catch (error: any) {\n throw new Error(`Failed to analyze commit patterns: ${error.message}`);\n }\n },\n };\n}\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { runAgentic, type AgenticConfig, type ToolExecutionMetric } from './executor';\nimport { createToolRegistry } from '../tools/registry';\nimport { createReleaseTools } from '../tools/release-tools';\nimport type { StorageAdapter, Logger } from '../types';\nimport { generateToolGuidance } from '@riotprompt/riotprompt';\n\nexport interface AgenticReleaseConfig {\n fromRef: string;\n toRef: string;\n logContent: string;\n diffContent: string;\n milestoneIssues?: string;\n releaseFocus?: string;\n userContext?: string;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n debugRequestFile?: string;\n debugResponseFile?: string;\n storage?: StorageAdapter;\n logger?: Logger;\n openaiReasoning?: 'low' | 'medium' | 'high';\n tokenBudget?: {\n max: number;\n reserveForResponse?: number;\n strategy?: 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n onBudgetExceeded?: 'compress' | 'error' | 'warn' | 'truncate';\n };\n}\n\nexport interface AgenticReleaseResult {\n releaseNotes: {\n title: string;\n body: string;\n };\n iterations: number;\n toolCallsExecuted: number;\n conversationHistory: ChatCompletionMessageParam[];\n toolMetrics: ToolExecutionMetric[];\n}\n\n/**\n * Run agentic release notes generation\n */\nexport async function runAgenticRelease(config: AgenticReleaseConfig): Promise<AgenticReleaseResult> {\n const {\n fromRef,\n toRef,\n logContent,\n diffContent,\n milestoneIssues,\n releaseFocus,\n userContext,\n model = 'gpt-4o',\n maxIterations = 30,\n debug = false,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget,\n } = config;\n\n // Create tool registry with context\n const toolRegistry = createToolRegistry({\n workingDirectory: process.cwd(),\n storage,\n logger,\n });\n\n // Register release-specific tools\n const tools = createReleaseTools();\n toolRegistry.registerAll(tools);\n\n // Generate automatic tool guidance from riotprompt\n const toolGuidance = generateToolGuidance(tools, {\n strategy: 'adaptive',\n includeExamples: true,\n explainWhenToUse: true,\n includeCategories: true,\n });\n\n // Build initial system prompt with tool guidance\n const systemPrompt = buildSystemPrompt(toolGuidance);\n\n // Build initial user message\n const userMessage = buildUserMessage({\n fromRef,\n toRef,\n logContent,\n diffContent,\n milestoneIssues,\n releaseFocus,\n userContext,\n });\n\n // Prepare messages for agentic loop\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n // Run agentic loop with token budget (larger for release notes)\n const agenticConfig: AgenticConfig = {\n messages,\n tools: toolRegistry,\n model,\n maxIterations,\n debug,\n debugRequestFile,\n debugResponseFile,\n storage,\n logger,\n openaiReasoning,\n tokenBudget: tokenBudget || {\n max: 200000,\n reserveForResponse: 8000,\n strategy: 'fifo',\n onBudgetExceeded: 'compress'\n },\n };\n\n const result = await runAgentic(agenticConfig);\n\n // Parse the final message to extract release notes\n const parsed = parseAgenticResult(result.finalMessage);\n\n return {\n releaseNotes: parsed.releaseNotes,\n iterations: result.iterations,\n toolCallsExecuted: result.toolCallsExecuted,\n conversationHistory: result.conversationHistory,\n toolMetrics: result.toolMetrics,\n };\n}\n\n/**\n * Build the system prompt for agentic release notes generation\n */\nfunction buildSystemPrompt(toolGuidance: string): string {\n return `You are a professional software engineer writing release notes for your team and users.\n\n${toolGuidance}\n\n## Your Task\n\nWrite release notes that clearly explain what's in this release and why it matters. Your notes should help users and developers understand what changed without needing to read every commit.\n\nFocus on:\n- What problems does this release solve?\n- What new capabilities does it add?\n- What's the impact on users and developers?\n- Are there breaking changes or important considerations?\n\nUse the available tools to investigate the changes. The more you understand, the better your notes will be.\n\n**Important**: If additional context is provided (from context files or other sources), use your judgment:\n- If the context is relevant to this specific package/release, incorporate it appropriately\n- If the context describes changes in other packages or unrelated work, ignore it\n- Don't fabricate connections between this package and unrelated context\n- Be honest about what changed - only mention what actually happened in this release\n- Context is supplemental information, not a requirement to include\n\n## Investigation Approach\n\nUse tools based on what you need to know:\n\n**Context:**\n- get_tag_history - understand release patterns\n- get_release_stats - quantify scope\n- compare_previous_release - see how this compares\n\n**Understanding:**\n- group_files_by_concern - identify themes\n- analyze_commit_patterns - detect patterns\n- get_file_content - see full context\n- analyze_diff_section - expand unclear changes\n- get_file_history - understand evolution\n\n**Impact:**\n- get_file_dependencies - assess reach\n- search_codebase - find usage patterns\n- get_related_tests - understand behavior changes\n- get_breaking_changes - identify breaking changes (always use)\n\n## Writing Style\n\nWrite naturally and directly:\n- Use plain language that users can understand\n- Be specific about what changed and why\n- Avoid marketing speak and buzzwords\n- No emojis or excessive punctuation\n- No phrases like \"we're excited to announce\"\n- No meta-commentary about the release itself\n- Focus on facts and implications, not enthusiasm\n\nStructure your notes logically:\n- Start with the most important changes\n- Group related changes together\n- Explain breaking changes clearly\n- Include practical examples when helpful\n\n## Output Format\n\nWhen ready, format your response as JSON:\n\nRELEASE_NOTES:\n{\n \"title\": \"Clear, factual title describing the main changes\",\n \"body\": \"Detailed release notes in Markdown format\"\n}\n\nOutput only the JSON. No conversational remarks or follow-up offers.`;\n}\n\n/**\n * Build the initial user message\n */\nfunction buildUserMessage(params: {\n fromRef: string;\n toRef: string;\n logContent: string;\n diffContent: string;\n milestoneIssues?: string;\n releaseFocus?: string;\n userContext?: string;\n}): string {\n const { fromRef, toRef, logContent, diffContent, milestoneIssues, releaseFocus, userContext } = params;\n\n let message = `I need comprehensive release notes for changes from ${fromRef} to ${toRef}.\n\n## Commit Log\n${logContent}\n\n## Diff Summary\n${diffContent}`;\n\n if (milestoneIssues) {\n message += `\\n\\n## Resolved Issues from Milestone\n${milestoneIssues}`;\n }\n\n if (releaseFocus) {\n message += `\\n\\n## Release Focus\n${releaseFocus}\n\nThis is the PRIMARY GUIDE for how to frame and structure the release notes. Use this to determine emphasis and narrative.`;\n }\n\n if (userContext) {\n message += `\\n\\n## Additional Context\n${userContext}`;\n }\n\n message += `\\n\\nAnalyze these changes and write clear release notes. Consider:\n- What's the main story of this release?\n- What problems does it solve?\n- What's the impact on users and developers?\n- Are there breaking changes?\n\nIf context information is provided, use it only if relevant to this specific package.\nDon't force connections that don't exist - if context describes changes in other packages\nor unrelated features, simply ignore it and focus on what actually changed in this release.\n\nInvestigate as needed to write accurate, helpful release notes.`;\n\n return message;\n}\n\n/**\n * Parse the agentic result to extract release notes\n */\nfunction parseAgenticResult(finalMessage: string): {\n releaseNotes: { title: string; body: string };\n} {\n // Look for RELEASE_NOTES: marker with JSON\n const jsonMatch = finalMessage.match(/RELEASE_NOTES:\\s*\\n([\\s\\S]*)/);\n\n if (jsonMatch) {\n try {\n const jsonStr = jsonMatch[1].trim();\n // Try to parse the JSON with error handling\n let parsed: any;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n // Failed to parse JSON, will use fallback parsing below\n parsed = null;\n }\n\n if (parsed && parsed.title && parsed.body) {\n return {\n releaseNotes: {\n title: parsed.title,\n body: parsed.body,\n },\n };\n }\n } catch {\n // JSON parsing failed, fall through to fallback\n }\n }\n\n // Fallback: try to extract title and body from the message\n const lines = finalMessage.split('\\n');\n let title = '';\n let body = '';\n let inBody = false;\n\n for (const line of lines) {\n if (!title && line.trim() && !line.startsWith('#')) {\n title = line.trim();\n } else if (title && line.trim()) {\n inBody = true;\n }\n\n if (inBody) {\n body += line + '\\n';\n }\n }\n\n // If we still don't have good content, use the whole message\n if (!title || !body) {\n title = 'Release Notes';\n body = finalMessage;\n }\n\n return {\n releaseNotes: {\n title: title.trim(),\n body: body.trim(),\n },\n };\n}\n\n","import type { Tool, ToolContext } from './types';\nimport { run, isBranchInSyncWithRemote, safeSyncBranchWithRemote, localBranchExists } from '@eldrforge/git-tools';\n\n/**\n * Create tools for agentic publish workflows\n */\nexport function createPublishTools(): Tool[] {\n return [\n createCheckGitStatusTool(),\n createCheckBranchSyncTool(),\n createAnalyzeDivergenceTool(),\n createGetCommitLogTool(),\n createGetBranchInfoTool(),\n createSyncBranchTool(),\n createGetDiffStatsTool(),\n createCheckConflictsTool(),\n createResetBranchTool(),\n ];\n}\n\n/**\n * Check git repository status\n */\nfunction createCheckGitStatusTool(): Tool {\n return {\n name: 'check_git_status',\n description: 'Check the current git repository status, including uncommitted changes, current branch, and repository state',\n parameters: {\n type: 'object',\n properties: {\n showUntracked: {\n type: 'boolean',\n description: 'Include untracked files in output (default: false)',\n default: false,\n },\n },\n required: [],\n },\n execute: async (params: { showUntracked?: boolean }, context?: ToolContext) => {\n const { showUntracked = false } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get current branch\n const branchResult = await run('git branch --show-current', { cwd: workingDir });\n const currentBranch = branchResult.stdout.trim();\n\n // Get status\n const statusCmd = showUntracked ? 'git status --porcelain' : 'git status --porcelain --untracked-files=no';\n const statusResult = await run(statusCmd, { cwd: workingDir });\n const hasChanges = statusResult.stdout.trim().length > 0;\n\n // Get HEAD commit\n const headResult = await run('git rev-parse --short HEAD', { cwd: workingDir });\n const headSha = headResult.stdout.trim();\n\n return {\n currentBranch,\n headSha,\n hasUncommittedChanges: hasChanges,\n statusOutput: statusResult.stdout,\n };\n } catch (error: any) {\n throw new Error(`Failed to check git status: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Check if a branch is synchronized with remote\n */\nfunction createCheckBranchSyncTool(): Tool {\n return {\n name: 'check_branch_sync',\n description: 'Check if a local branch is synchronized with its remote counterpart. Returns sync status, local/remote SHAs, and whether the branch exists locally.',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to check',\n },\n },\n required: ['branchName'],\n },\n execute: async (params: { branchName: string }, _context?: ToolContext) => {\n const { branchName } = params;\n\n try {\n // Check if branch exists locally\n const exists = await localBranchExists(branchName);\n\n if (!exists) {\n return {\n exists: false,\n message: `Branch '${branchName}' does not exist locally`,\n };\n }\n\n // Check sync status\n const syncStatus = await isBranchInSyncWithRemote(branchName);\n\n return {\n exists: true,\n branchName,\n inSync: syncStatus.inSync,\n localSha: syncStatus.localSha,\n remoteSha: syncStatus.remoteSha,\n error: syncStatus.error,\n isDiverged: syncStatus.localSha !== syncStatus.remoteSha,\n };\n } catch (error: any) {\n throw new Error(`Failed to check branch sync: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Analyze how two branches have diverged\n */\nfunction createAnalyzeDivergenceTool(): Tool {\n return {\n name: 'analyze_divergence',\n description: 'Analyze how two branches have diverged by showing commits unique to each branch',\n parameters: {\n type: 'object',\n properties: {\n sourceBranch: {\n type: 'string',\n description: 'The source/local branch name',\n },\n targetBranch: {\n type: 'string',\n description: 'The target/remote branch to compare against (e.g., \"origin/main\")',\n },\n maxCommits: {\n type: 'number',\n description: 'Maximum number of commits to show for each branch (default: 10)',\n default: 10,\n },\n },\n required: ['sourceBranch', 'targetBranch'],\n },\n execute: async (params: { sourceBranch: string; targetBranch: string; maxCommits?: number }, context?: ToolContext) => {\n const { sourceBranch, targetBranch, maxCommits = 10 } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get commits in source but not in target\n const sourceOnlyResult = await run(\n `git log ${targetBranch}..${sourceBranch} --oneline -n ${maxCommits}`,\n { cwd: workingDir }\n );\n\n // Get commits in target but not in source\n const targetOnlyResult = await run(\n `git log ${sourceBranch}..${targetBranch} --oneline -n ${maxCommits}`,\n { cwd: workingDir }\n );\n\n // Get merge base\n const mergeBaseResult = await run(\n `git merge-base ${sourceBranch} ${targetBranch}`,\n { cwd: workingDir }\n );\n\n return {\n sourceBranch,\n targetBranch,\n mergeBase: mergeBaseResult.stdout.trim(),\n commitsInSourceOnly: sourceOnlyResult.stdout.trim() || 'None',\n commitsInTargetOnly: targetOnlyResult.stdout.trim() || 'None',\n isDiverged: sourceOnlyResult.stdout.trim().length > 0 && targetOnlyResult.stdout.trim().length > 0,\n canFastForward: sourceOnlyResult.stdout.trim().length === 0, // Target is ahead, can fast-forward\n };\n } catch (error: any) {\n throw new Error(`Failed to analyze divergence: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get commit log for a branch or range\n */\nfunction createGetCommitLogTool(): Tool {\n return {\n name: 'get_commit_log',\n description: 'Get git commit log for a branch or commit range with detailed information',\n parameters: {\n type: 'object',\n properties: {\n ref: {\n type: 'string',\n description: 'Git ref (branch name, commit range like \"main..working\", or single commit)',\n },\n maxCommits: {\n type: 'number',\n description: 'Maximum number of commits to return (default: 20)',\n default: 20,\n },\n format: {\n type: 'string',\n description: 'Format: \"oneline\" for brief, \"full\" for detailed with message body',\n enum: ['oneline', 'full'],\n default: 'oneline',\n },\n },\n required: ['ref'],\n },\n execute: async (params: { ref: string; maxCommits?: number; format?: 'oneline' | 'full' }, context?: ToolContext) => {\n const { ref, maxCommits = 20, format = 'oneline' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n const formatStr = format === 'full'\n ? '%H%n%an <%ae>%n%ad%n%s%n%n%b%n---'\n : '%h - %s (%an, %ar)';\n\n const result = await run(\n `git log \"${ref}\" --format=\"${formatStr}\" -n ${maxCommits}`,\n { cwd: workingDir }\n );\n\n return result.stdout || 'No commits found';\n } catch (error: any) {\n throw new Error(`Failed to get commit log: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get detailed information about a branch\n */\nfunction createGetBranchInfoTool(): Tool {\n return {\n name: 'get_branch_info',\n description: 'Get detailed information about a branch including its tracking info, last commit, and whether it exists remotely',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to inspect',\n },\n },\n required: ['branchName'],\n },\n execute: async (params: { branchName: string }, context?: ToolContext) => {\n const { branchName } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Check if branch exists locally\n const localExists = await localBranchExists(branchName);\n\n if (!localExists) {\n // Check if it exists remotely\n try {\n const remoteCheckResult = await run(`git ls-remote --heads origin ${branchName}`, { cwd: workingDir });\n const remoteExists = remoteCheckResult.stdout.trim().length > 0;\n\n return {\n branchName,\n existsLocally: false,\n existsRemotely: remoteExists,\n message: remoteExists\n ? `Branch exists remotely but not locally`\n : `Branch does not exist locally or remotely`,\n };\n } catch {\n return {\n branchName,\n existsLocally: false,\n existsRemotely: false,\n };\n }\n }\n\n // Get branch tracking info\n let trackingBranch = null;\n try {\n const trackingResult = await run(`git rev-parse --abbrev-ref ${branchName}@{upstream}`, { cwd: workingDir });\n trackingBranch = trackingResult.stdout.trim();\n } catch {\n // No upstream configured\n }\n\n // Get last commit info\n const lastCommitResult = await run(\n `git log ${branchName} -1 --format=\"%H|%h|%s|%an|%ar\"`,\n { cwd: workingDir }\n );\n const [fullSha, shortSha, subject, author, relativeDate] = lastCommitResult.stdout.trim().split('|');\n\n // Get commit count\n const countResult = await run(`git rev-list --count ${branchName}`, { cwd: workingDir });\n const commitCount = parseInt(countResult.stdout.trim(), 10);\n if (isNaN(commitCount)) {\n throw new Error(`Invalid commit count returned from git: ${countResult.stdout}`);\n }\n\n return {\n branchName,\n existsLocally: true,\n trackingBranch,\n lastCommit: {\n fullSha,\n shortSha,\n subject,\n author,\n relativeDate,\n },\n commitCount,\n };\n } catch (error: any) {\n throw new Error(`Failed to get branch info: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Attempt to sync a branch with remote\n */\nfunction createSyncBranchTool(): Tool {\n return {\n name: 'sync_branch',\n description: 'Attempt to synchronize a local branch with its remote counterpart. Returns success status and details about what happened.',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to sync',\n },\n },\n required: ['branchName'],\n },\n execute: async (params: { branchName: string }, _context?: ToolContext) => {\n const { branchName } = params;\n\n try {\n const syncResult = await safeSyncBranchWithRemote(branchName);\n\n return {\n branchName,\n success: syncResult.success,\n conflictResolutionRequired: syncResult.conflictResolutionRequired,\n error: syncResult.error,\n message: syncResult.success\n ? `Successfully synchronized ${branchName} with remote`\n : syncResult.conflictResolutionRequired\n ? `Sync failed due to merge conflicts in ${branchName}`\n : `Sync failed: ${syncResult.error}`,\n };\n } catch (error: any) {\n throw new Error(`Failed to sync branch: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Get diff statistics between two refs\n */\nfunction createGetDiffStatsTool(): Tool {\n return {\n name: 'get_diff_stats',\n description: 'Get statistics about differences between two git refs (branches, commits, etc.)',\n parameters: {\n type: 'object',\n properties: {\n fromRef: {\n type: 'string',\n description: 'Starting ref (e.g., \"main\", \"origin/main\")',\n },\n toRef: {\n type: 'string',\n description: 'Ending ref (e.g., \"working\", \"HEAD\")',\n },\n includeFileList: {\n type: 'boolean',\n description: 'Include list of changed files (default: true)',\n default: true,\n },\n },\n required: ['fromRef', 'toRef'],\n },\n execute: async (params: { fromRef: string; toRef: string; includeFileList?: boolean }, context?: ToolContext) => {\n const { fromRef, toRef, includeFileList = true } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Get diff stats\n const statsResult = await run(`git diff --shortstat ${fromRef}..${toRef}`, { cwd: workingDir });\n\n let fileList = null;\n if (includeFileList) {\n const fileListResult = await run(`git diff --name-status ${fromRef}..${toRef}`, { cwd: workingDir });\n fileList = fileListResult.stdout;\n }\n\n return {\n fromRef,\n toRef,\n stats: statsResult.stdout.trim() || 'No differences',\n fileList,\n };\n } catch (error: any) {\n throw new Error(`Failed to get diff stats: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Check for merge conflicts\n */\nfunction createCheckConflictsTool(): Tool {\n return {\n name: 'check_conflicts',\n description: 'Check if merging one branch into another would result in conflicts (without actually performing the merge)',\n parameters: {\n type: 'object',\n properties: {\n sourceBranch: {\n type: 'string',\n description: 'Branch to merge from',\n },\n targetBranch: {\n type: 'string',\n description: 'Branch to merge into',\n },\n },\n required: ['sourceBranch', 'targetBranch'],\n },\n execute: async (params: { sourceBranch: string; targetBranch: string }, context?: ToolContext) => {\n const { sourceBranch, targetBranch } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // Use git merge-tree to check for conflicts without actually merging\n const mergeBaseResult = await run(\n `git merge-base ${targetBranch} ${sourceBranch}`,\n { cwd: workingDir }\n );\n const mergeBase = mergeBaseResult.stdout.trim();\n\n // Check if merge would create conflicts\n const mergeTreeResult = await run(\n `git merge-tree ${mergeBase} ${targetBranch} ${sourceBranch}`,\n { cwd: workingDir }\n );\n\n // Look for conflict markers in the output\n const hasConflicts = mergeTreeResult.stdout.includes('<<<<<<<') ||\n mergeTreeResult.stdout.includes('>>>>>>>') ||\n mergeTreeResult.stdout.includes('=======');\n\n // Extract conflicting files if any\n const conflicts = hasConflicts\n ? mergeTreeResult.stdout.match(/\\+\\+\\+ b\\/([^\\n]+)/g)?.map(m => m.replace(/\\+\\+\\+ b\\//, ''))\n : [];\n\n return {\n sourceBranch,\n targetBranch,\n mergeBase,\n hasConflicts,\n conflictingFiles: conflicts || [],\n message: hasConflicts\n ? `Merging ${sourceBranch} into ${targetBranch} would create conflicts`\n : `Merging ${sourceBranch} into ${targetBranch} should succeed without conflicts`,\n };\n } catch (error: any) {\n throw new Error(`Failed to check conflicts: ${error.message}`);\n }\n },\n };\n}\n\n/**\n * Reset a branch to match another ref\n */\nfunction createResetBranchTool(): Tool {\n return {\n name: 'reset_branch',\n description: 'Reset a branch to match another ref (e.g., reset local main to origin/main). USE WITH CAUTION - this is a destructive operation.',\n parameters: {\n type: 'object',\n properties: {\n branchName: {\n type: 'string',\n description: 'Name of the branch to reset',\n },\n targetRef: {\n type: 'string',\n description: 'Ref to reset to (e.g., \"origin/main\")',\n },\n resetType: {\n type: 'string',\n description: 'Type of reset: \"hard\" (discard changes), \"soft\" (keep changes staged), \"mixed\" (keep changes unstaged)',\n enum: ['hard', 'soft', 'mixed'],\n default: 'hard',\n },\n },\n required: ['branchName', 'targetRef'],\n },\n execute: async (params: { branchName: string; targetRef: string; resetType?: 'hard' | 'soft' | 'mixed' }, context?: ToolContext) => {\n const { branchName, targetRef, resetType = 'hard' } = params;\n const workingDir = context?.workingDirectory || process.cwd();\n\n try {\n // First, checkout the branch\n await run(`git checkout ${branchName}`, { cwd: workingDir });\n\n // Then reset it to the target ref\n await run(`git reset --${resetType} ${targetRef}`, { cwd: workingDir });\n\n // Get the new HEAD\n const headResult = await run('git rev-parse --short HEAD', { cwd: workingDir });\n const newHead = headResult.stdout.trim();\n\n return {\n branchName,\n targetRef,\n resetType,\n newHead,\n message: `Successfully reset ${branchName} to ${targetRef} (${resetType})`,\n };\n } catch (error: any) {\n throw new Error(`Failed to reset branch: ${error.message}`);\n }\n },\n };\n}\n\n","import type { ChatCompletionMessageParam } from 'openai/resources';\nimport { AgenticExecutor } from './executor';\nimport { createToolRegistry } from '../tools/registry';\nimport { createPublishTools } from '../tools/publish-tools';\nimport type { ToolContext } from '../tools/types';\n\nexport interface AgenticPublishConfig {\n targetBranch: string;\n sourceBranch: string;\n issue: 'branch_sync' | 'uncommitted_changes' | 'merge_conflicts' | 'unknown';\n issueDetails?: string;\n workingDirectory?: string;\n model?: string;\n maxIterations?: number;\n debug?: boolean;\n storage?: any;\n logger?: any;\n dryRun?: boolean;\n}\n\nexport interface AgenticPublishResult {\n success: boolean;\n message: string;\n actionsTaken: string[];\n iterations: number;\n toolCallsExecuted: number;\n requiresManualIntervention: boolean;\n manualSteps?: string[];\n}\n\n/**\n * Run agentic publish recovery\n */\nexport async function runAgenticPublish(config: AgenticPublishConfig): Promise<AgenticPublishResult> {\n const {\n targetBranch,\n sourceBranch,\n issue,\n issueDetails,\n workingDirectory = process.cwd(),\n model = 'gpt-4o',\n maxIterations = 10,\n debug = false,\n storage,\n logger,\n dryRun = false,\n } = config;\n\n // Create tool context\n const toolContext: ToolContext = {\n workingDirectory,\n storage,\n logger,\n };\n\n // Create tool registry with publish tools\n const tools = createToolRegistry(toolContext);\n tools.registerAll(createPublishTools());\n\n // Build the system prompt\n const systemPrompt = buildSystemPrompt(issue, dryRun);\n\n // Build the user prompt with specific issue details\n const userPrompt = buildUserPrompt({\n issue,\n targetBranch,\n sourceBranch,\n issueDetails,\n });\n\n // Prepare messages\n const messages: ChatCompletionMessageParam[] = [\n {\n role: 'system',\n content: systemPrompt,\n },\n {\n role: 'user',\n content: userPrompt,\n },\n ];\n\n // Run the agentic executor\n const executor = new AgenticExecutor(logger);\n const result = await executor.run({\n messages,\n tools,\n model,\n maxIterations,\n debug,\n storage,\n logger,\n });\n\n // Parse the final message to extract actions and recommendations\n const analysis = parseAgentResponse(result.finalMessage);\n\n return {\n success: analysis.success,\n message: result.finalMessage,\n actionsTaken: analysis.actionsTaken,\n iterations: result.iterations,\n toolCallsExecuted: result.toolCallsExecuted,\n requiresManualIntervention: analysis.requiresManualIntervention,\n manualSteps: analysis.manualSteps,\n };\n}\n\n/**\n * Build system prompt for agentic publish\n */\nfunction buildSystemPrompt(issue: string, dryRun: boolean): string {\n const modeNote = dryRun\n ? '\\n\\nIMPORTANT: This is a DRY RUN. Do not use tools that make destructive changes (like reset_branch or sync_branch). Only use diagnostic tools to analyze the issue and provide recommendations.'\n : '';\n\n return `You are an expert Git operations assistant helping to diagnose and fix issues that prevent publishing a software package.\n\nYour role is to:\n1. Use the available tools to investigate the problem\n2. Analyze the root cause of the issue\n3. ${dryRun ? 'Recommend' : 'Attempt to fix'} the issue using best practices\n4. Provide clear explanations of what you found and ${dryRun ? 'would do' : 'did'}\n\nAvailable tools allow you to:\n- Check git status and branch information\n- Analyze divergence between branches\n- View commit logs and diff statistics\n- Check for potential merge conflicts\n${dryRun ? '' : '- Sync branches with remote\\n- Reset branches to match remote refs'}\n\nGuidelines:\n- Always diagnose before taking action\n- Prefer safe, non-destructive operations when possible\n- If a situation requires manual intervention, clearly state why and provide steps\n- Be thorough in your analysis\n- Consider the impact of each action on the repository state\n\nCurrent issue type: ${issue}${modeNote}`;\n}\n\n/**\n * Build user prompt with specific issue details\n */\nfunction buildUserPrompt(params: {\n issue: string;\n targetBranch: string;\n sourceBranch: string;\n issueDetails?: string;\n}): string {\n const { issue, targetBranch, sourceBranch, issueDetails } = params;\n\n const issueDescriptions = {\n branch_sync: `The target branch '${targetBranch}' is not synchronized with its remote counterpart. This prevents the publish workflow from proceeding safely.`,\n uncommitted_changes: `There are uncommitted changes in the working directory on branch '${sourceBranch}'. The publish workflow requires a clean working directory.`,\n merge_conflicts: `There are merge conflicts between '${sourceBranch}' and '${targetBranch}' that need to be resolved before publishing.`,\n unknown: `An unknown issue is preventing the publish workflow from proceeding.`,\n };\n\n const basePrompt = `I'm trying to run a publish workflow that will:\n1. Create a release from source branch '${sourceBranch}'\n2. Merge it into target branch '${targetBranch}'\n3. Publish the package\n\nHowever, I'm encountering an issue:\n\n${issueDescriptions[issue as keyof typeof issueDescriptions] || issueDescriptions.unknown}`;\n\n const detailsSection = issueDetails\n ? `\\n\\nAdditional details:\\n${issueDetails}`\n : '';\n\n return `${basePrompt}${detailsSection}\n\nPlease investigate this issue and ${process.env.DRY_RUN ? 'recommend how to fix it' : 'attempt to fix it if possible'}. Use the available tools to:\n\n1. Diagnose the exact problem\n2. Understand what caused it (e.g., what commits are causing divergence)\n3. ${process.env.DRY_RUN ? 'Recommend a solution' : 'Attempt to resolve it safely'}\n4. Explain what ${process.env.DRY_RUN ? 'should be' : 'was'} done and why\n\nIf the issue requires manual intervention, please explain why and provide clear steps.`;\n}\n\n/**\n * Parse agent response to extract structured information\n */\nfunction parseAgentResponse(message: string): {\n success: boolean;\n actionsTaken: string[];\n requiresManualIntervention: boolean;\n manualSteps: string[];\n} {\n // Look for indicators of success/failure\n const successIndicators = [\n 'successfully',\n 'resolved',\n 'fixed',\n 'synced',\n 'safe to proceed',\n 'ready to publish',\n ];\n\n const manualInterventionIndicators = [\n 'requires manual',\n 'manual intervention',\n 'cannot automatically',\n 'you will need to',\n 'please manually',\n ];\n\n const messageLower = message.toLowerCase();\n const hasSuccessIndicator = successIndicators.some(indicator => messageLower.includes(indicator));\n const hasManualIndicator = manualInterventionIndicators.some(indicator => messageLower.includes(indicator));\n\n // Extract actions taken (look for past tense verbs and tool usage patterns)\n const actionsTaken: string[] = [];\n const actionPatterns = [\n /(?:I |We )?(checked|analyzed|found|discovered|synced|reset|merged|fetched|pulled|compared|investigated)\\s+([^.\\n]+)/gi,\n /(?:Successfully|Successfully)\\s+([^.\\n]+)/gi,\n ];\n\n for (const pattern of actionPatterns) {\n const matches = message.matchAll(pattern);\n for (const match of matches) {\n actionsTaken.push(match[0].trim());\n }\n }\n\n // Extract manual steps (look for numbered lists or bullet points)\n const manualSteps: string[] = [];\n const stepPatterns = [\n /(?:Step \\d+:|^\\d+\\.)\\s*(.+)$/gim,\n /^[-*]\\s+(.+)$/gim,\n ];\n\n if (hasManualIndicator) {\n // Only extract steps if manual intervention is needed\n for (const pattern of stepPatterns) {\n const matches = message.matchAll(pattern);\n for (const match of matches) {\n const step = match[1]?.trim();\n if (step && step.length > 10) { // Filter out very short matches\n manualSteps.push(step);\n }\n }\n }\n }\n\n return {\n success: hasSuccessIndicator && !hasManualIndicator,\n actionsTaken: [...new Set(actionsTaken)], // Remove duplicates\n requiresManualIntervention: hasManualIndicator,\n manualSteps: [...new Set(manualSteps)], // Remove duplicates\n };\n}\n\n/**\n * Create a friendly summary of the agentic publish result\n */\nexport function formatAgenticPublishResult(result: AgenticPublishResult): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push('═══════════════════════════════════════════════════════════');\n lines.push(' AGENTIC PUBLISH RECOVERY REPORT');\n lines.push('═══════════════════════════════════════════════════════════');\n lines.push('');\n\n if (result.success) {\n lines.push('✅ Status: RESOLVED');\n } else if (result.requiresManualIntervention) {\n lines.push('⚠️ Status: MANUAL INTERVENTION REQUIRED');\n } else {\n lines.push('❌ Status: UNRESOLVED');\n }\n\n lines.push('');\n lines.push(`Iterations: ${result.iterations}`);\n lines.push(`Tools executed: ${result.toolCallsExecuted}`);\n lines.push('');\n\n if (result.actionsTaken.length > 0) {\n lines.push('Actions taken:');\n for (const action of result.actionsTaken) {\n lines.push(` • ${action}`);\n }\n lines.push('');\n }\n\n if (result.requiresManualIntervention && result.manualSteps && result.manualSteps.length > 0) {\n lines.push('Manual steps required:');\n for (let i = 0; i < result.manualSteps.length; i++) {\n lines.push(` ${i + 1}. ${result.manualSteps[i]}`);\n }\n lines.push('');\n }\n\n lines.push('Detailed analysis:');\n lines.push('───────────────────────────────────────────────────────────');\n lines.push(result.message);\n lines.push('───────────────────────────────────────────────────────────');\n lines.push('');\n\n if (result.success) {\n lines.push('You can now retry the publish command.');\n } else if (result.requiresManualIntervention) {\n lines.push('Please complete the manual steps above, then retry the publish command.');\n } else {\n lines.push('The issue could not be resolved automatically. Please review the analysis above.');\n }\n\n lines.push('');\n\n return lines.join('\\n');\n}\n\n","/**\n * Conversation logging for debugging and analysis\n *\n * Provides simple wrappers for logging agentic conversations\n * to disk for later analysis.\n */\n\nimport { ConversationLogger, type LogConfig } from '@riotprompt/riotprompt';\nimport type { Logger, StorageAdapter } from '../types';\nimport path from 'path';\n\nexport interface ConversationLoggerConfig {\n outputDir: string;\n format?: 'json' | 'markdown';\n includeMetadata?: boolean;\n storage?: StorageAdapter;\n logger?: Logger;\n}\n\n/**\n * Create a conversation logger instance\n *\n * @example\n * ```typescript\n * const logger = createConversationLogger({\n * outputDir: 'output/conversations',\n * storage,\n * logger\n * });\n *\n * // Log conversation\n * await logger.save(conversationId, messages, metadata);\n * ```\n */\nexport function createConversationLogger(config: ConversationLoggerConfig) {\n const {\n outputDir,\n format = 'json',\n storage,\n logger\n } = config;\n\n return {\n /**\n * Save a conversation to disk\n */\n async save(\n conversationId: string,\n messages: any[],\n metadata?: Record<string, any>\n ): Promise<string> {\n try {\n if (!storage) {\n throw new Error('Storage adapter required');\n }\n\n const conversation = {\n id: conversationId,\n timestamp: new Date().toISOString(),\n messages,\n metadata: metadata || {}\n };\n\n const filename = `${conversationId}.${format}`;\n const filepath = path.join(outputDir, filename);\n\n const content = format === 'json'\n ? JSON.stringify(conversation, null, 2)\n : formatConversationAsMarkdown(conversation);\n\n await storage.writeOutput(filename, content);\n\n if (logger) {\n logger.debug(`Logged conversation ${conversationId} to ${filepath}`);\n }\n\n return filepath;\n } catch (error: any) {\n if (logger) {\n logger.warn(`Failed to log conversation ${conversationId}: ${error.message}`);\n }\n throw error;\n }\n },\n\n /**\n * Load a conversation from disk\n */\n async load(conversationId: string) {\n try {\n if (!storage) {\n throw new Error('Storage adapter required');\n }\n\n const filename = `${conversationId}.${format}`;\n const content = await storage.readFile(path.join(outputDir, filename), 'utf-8');\n\n let conversation: any;\n if (format === 'json') {\n try {\n conversation = JSON.parse(content);\n } catch (parseError: any) {\n throw new Error(`Failed to parse conversation JSON: ${parseError.message}`);\n }\n } else {\n conversation = content;\n }\n\n if (logger) {\n logger.info(`Loaded conversation ${conversationId}`);\n }\n\n return conversation;\n } catch (error: any) {\n if (logger) {\n logger.warn(`Failed to load conversation ${conversationId}: ${error.message}`);\n }\n throw error;\n }\n },\n\n /**\n * Get conversation summary\n */\n async getSummary(conversationId: string) {\n try {\n const conversation = await this.load(conversationId);\n\n return {\n id: conversation.id,\n timestamp: conversation.timestamp,\n messageCount: conversation.messages?.length || 0,\n metadata: conversation.metadata\n };\n } catch (error: any) {\n if (logger) {\n logger.warn(`Failed to get summary for ${conversationId}: ${error.message}`);\n }\n throw error;\n }\n },\n\n /**\n * Create riotprompt ConversationLogger instance for advanced usage\n */\n createRiotLogger(): ConversationLogger {\n const logConfig: LogConfig = {\n enabled: true,\n outputPath: outputDir,\n format: format as 'json' | 'markdown' | 'jsonl',\n includeMetadata: true\n };\n\n return new ConversationLogger(logConfig, logger);\n }\n };\n}\n\n/**\n * Format conversation as markdown\n */\nfunction formatConversationAsMarkdown(conversation: any): string {\n const lines: string[] = [];\n\n lines.push(`# Conversation: ${conversation.id}`);\n lines.push('');\n lines.push(`**Timestamp:** ${conversation.timestamp}`);\n\n if (conversation.metadata) {\n lines.push('');\n lines.push('## Metadata');\n lines.push('```json');\n lines.push(JSON.stringify(conversation.metadata, null, 2));\n lines.push('```');\n }\n\n lines.push('');\n lines.push('## Messages');\n lines.push('');\n\n for (let i = 0; i < conversation.messages.length; i++) {\n const msg = conversation.messages[i];\n lines.push(`### Message ${i + 1}: ${msg.role}`);\n lines.push('');\n lines.push(msg.content || '(no content)');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Helper to generate conversation ID\n */\nexport function generateConversationId(command: string): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('.')[0];\n return `${command}-${timestamp}`;\n}\n\nexport type ConversationLoggerInstance = ReturnType<typeof createConversationLogger>;\n","/**\n * Self-reflection report generation\n *\n * Provides enhanced reflection reports for agentic workflows.\n * Uses our custom implementation optimized for commit and release workflows.\n */\n\nimport type { Logger, StorageAdapter } from '../types';\nimport type { ToolExecutionMetric } from '../agentic/executor';\n\nexport interface ReflectionOptions {\n iterations: number;\n toolCallsExecuted: number;\n maxIterations: number;\n toolMetrics: ToolExecutionMetric[];\n conversationHistory?: any[];\n commitMessage?: string;\n suggestedSplits?: any[];\n releaseNotes?: any;\n logger?: Logger;\n}\n\n/**\n * Generate a comprehensive self-reflection report\n *\n * @example\n * ```typescript\n * const report = await generateReflectionReport({\n * iterations: result.iterations,\n * toolCallsExecuted: result.toolCallsExecuted,\n * maxIterations: 10,\n * toolMetrics: result.toolMetrics,\n * commitMessage: result.commitMessage,\n * logger\n * });\n *\n * await saveReflectionReport(report, 'output/reflection.md', storage);\n * ```\n */\nexport async function generateReflectionReport(options: ReflectionOptions): Promise<string> {\n const {\n iterations,\n toolCallsExecuted,\n maxIterations,\n toolMetrics,\n conversationHistory,\n commitMessage,\n suggestedSplits,\n releaseNotes,\n logger\n } = options;\n\n const sections: string[] = [];\n\n // Header\n sections.push('# Agentic Workflow - Self-Reflection Report');\n sections.push('');\n sections.push(`Generated: ${new Date().toISOString()}`);\n sections.push('');\n\n // Execution Summary\n sections.push('## Execution Summary');\n sections.push('');\n sections.push(`- **Iterations**: ${iterations}${iterations >= maxIterations ? ' (max reached)' : ''}`);\n sections.push(`- **Tool Calls**: ${toolCallsExecuted}`);\n sections.push(`- **Unique Tools**: ${new Set(toolMetrics.map(m => m.name)).size}`);\n sections.push('');\n\n // Calculate tool statistics\n const toolStats = calculateToolStats(toolMetrics);\n\n // Tool Effectiveness\n sections.push('## Tool Effectiveness Analysis');\n sections.push('');\n\n if (toolStats.size === 0) {\n sections.push('*No tools were executed during this run.*');\n } else {\n sections.push('| Tool | Calls | Success | Failures | Success Rate | Avg Duration |');\n sections.push('|------|-------|---------|----------|--------------|--------------|');\n\n for (const [toolName, stats] of Array.from(toolStats.entries()).sort((a, b) => b[1].total - a[1].total)) {\n const successRate = stats.total > 0 ? ((stats.success / stats.total) * 100).toFixed(1) : '0.0';\n const avgDuration = stats.total > 0 ? (stats.totalDuration / stats.total).toFixed(0) : '0';\n sections.push(`| ${toolName} | ${stats.total} | ${stats.success} | ${stats.failures} | ${successRate}% | ${avgDuration}ms |`);\n }\n }\n sections.push('');\n\n // Performance Insights\n if (toolStats.size > 0) {\n sections.push('### Tool Performance Insights');\n sections.push('');\n\n const failedTools = Array.from(toolStats.entries()).filter(([_, stats]) => stats.failures > 0);\n if (failedTools.length > 0) {\n sections.push('**Tools with Failures:**');\n for (const [toolName, stats] of failedTools) {\n const failureRate = stats.total > 0 ? ((stats.failures / stats.total) * 100).toFixed(1) : '0.0';\n sections.push(`- ${toolName}: ${stats.failures}/${stats.total} failures (${failureRate}%)`);\n }\n sections.push('');\n }\n\n const slowTools = Array.from(toolStats.entries())\n .filter(([_, stats]) => stats.total > 0 && (stats.totalDuration / stats.total) > 1000)\n .sort((a, b) => {\n const avgA = a[1].total > 0 ? a[1].totalDuration / a[1].total : 0;\n const avgB = b[1].total > 0 ? b[1].totalDuration / b[1].total : 0;\n return avgB - avgA;\n });\n\n if (slowTools.length > 0) {\n sections.push('**Slow Tools (>1s average):**');\n for (const [toolName, stats] of slowTools) {\n const avgDuration = stats.total > 0 ? (stats.totalDuration / stats.total / 1000).toFixed(2) : '0.00';\n sections.push(`- ${toolName}: ${avgDuration}s average`);\n }\n sections.push('');\n }\n\n sections.push('**Most Frequently Used:**');\n const topTools = Array.from(toolStats.entries()).slice(0, 3);\n for (const [toolName, stats] of topTools) {\n sections.push(`- ${toolName}: ${stats.total} calls`);\n }\n sections.push('');\n }\n\n // Recommendations\n sections.push('## Recommendations for Improvement');\n sections.push('');\n\n const recommendations = generateRecommendations(options, toolStats);\n if (recommendations.length === 0) {\n sections.push('*No specific recommendations at this time. Execution appears optimal.*');\n } else {\n for (const rec of recommendations) {\n sections.push(rec);\n }\n }\n sections.push('');\n\n // Execution Timeline\n sections.push('## Detailed Execution Timeline');\n sections.push('');\n\n if (toolMetrics.length === 0) {\n sections.push('*No tool execution timeline available.*');\n } else {\n sections.push('| Time | Iteration | Tool | Result | Duration |');\n sections.push('|------|-----------|------|--------|----------|');\n\n for (const metric of toolMetrics) {\n const time = new Date(metric.timestamp).toLocaleTimeString();\n const result = metric.success ? '✅ Success' : `❌ ${metric.error || 'Failed'}`;\n sections.push(`| ${time} | ${metric.iteration} | ${metric.name} | ${result} | ${metric.duration}ms |`);\n }\n sections.push('');\n }\n\n // Conversation History\n if (conversationHistory && conversationHistory.length > 0) {\n sections.push('## Conversation History');\n sections.push('');\n sections.push('<details>');\n sections.push('<summary>Click to expand full agentic interaction</summary>');\n sections.push('');\n sections.push('```json');\n sections.push(JSON.stringify(conversationHistory, null, 2));\n sections.push('```');\n sections.push('');\n sections.push('</details>');\n sections.push('');\n }\n\n // Generated Output\n if (commitMessage) {\n sections.push('## Generated Commit Message');\n sections.push('');\n sections.push('```');\n sections.push(commitMessage);\n sections.push('```');\n sections.push('');\n\n if (suggestedSplits && suggestedSplits.length > 1) {\n sections.push('## Suggested Commit Splits');\n sections.push('');\n for (let i = 0; i < suggestedSplits.length; i++) {\n const split = suggestedSplits[i];\n sections.push(`### Split ${i + 1}`);\n sections.push('');\n sections.push(`**Files**: ${split.files.join(', ')}`);\n sections.push('');\n sections.push(`**Rationale**: ${split.rationale}`);\n sections.push('');\n sections.push(`**Message**:`);\n sections.push('```');\n sections.push(split.message);\n sections.push('```');\n sections.push('');\n }\n }\n }\n\n if (releaseNotes) {\n sections.push('## Generated Release Notes');\n sections.push('');\n sections.push('### Title');\n sections.push('```');\n sections.push(releaseNotes.title);\n sections.push('```');\n sections.push('');\n sections.push('### Body');\n sections.push('```markdown');\n sections.push(releaseNotes.body);\n sections.push('```');\n sections.push('');\n }\n\n if (logger) {\n logger.debug(`Generated reflection report with ${toolStats.size} unique tools`);\n }\n\n return sections.join('\\n');\n}\n\n/**\n * Calculate tool statistics\n */\nfunction calculateToolStats(toolMetrics: ToolExecutionMetric[]): Map<string, { total: number; success: number; failures: number; totalDuration: number }> {\n const stats = new Map();\n\n for (const metric of toolMetrics) {\n if (!stats.has(metric.name)) {\n stats.set(metric.name, { total: 0, success: 0, failures: 0, totalDuration: 0 });\n }\n const toolStat = stats.get(metric.name);\n toolStat.total++;\n toolStat.totalDuration += metric.duration;\n if (metric.success) {\n toolStat.success++;\n } else {\n toolStat.failures++;\n }\n }\n\n return stats;\n}\n\n/**\n * Generate recommendations based on metrics\n */\nfunction generateRecommendations(\n options: ReflectionOptions,\n toolStats: Map<string, { total: number; success: number; failures: number; totalDuration: number }>\n): string[] {\n const recommendations: string[] = [];\n\n // Check for tool failures\n const toolsWithFailures = Array.from(toolStats.entries()).filter(([_, stats]) => stats.failures > 0);\n if (toolsWithFailures.length > 0) {\n recommendations.push('- **Tool Failures**: Investigate and fix tools that are failing. This may indicate issues with error handling or tool implementation.');\n }\n\n // Check for slow tools\n const slowTools = Array.from(toolStats.entries())\n .filter(([_, stats]) => stats.total > 0 && (stats.totalDuration / stats.total) > 1000);\n if (slowTools.length > 0) {\n recommendations.push('- **Performance**: Consider optimizing slow tools or caching results to improve execution speed.');\n }\n\n // Check for max iterations reached\n if (options.iterations >= options.maxIterations) {\n recommendations.push('- **Max Iterations Reached**: The agent reached maximum iterations. Consider increasing the limit or improving tool efficiency to allow the agent to complete naturally.');\n }\n\n // Check for underutilized tools\n const underutilizedTools = Array.from(toolStats.entries()).filter(([_, stats]) => stats.total === 1);\n if (underutilizedTools.length > 3) {\n recommendations.push('- **Underutilized Tools**: Many tools were called only once. Consider whether all tools are necessary or if the agent needs better guidance on when to use them.');\n }\n\n // Check tool diversity\n const uniqueTools = toolStats.size;\n if (uniqueTools === 1 && options.toolCallsExecuted > 3) {\n recommendations.push('- **Low Tool Diversity**: Only one tool was used despite multiple calls. Consider if the agent needs better guidance to use a variety of tools.');\n }\n\n return recommendations;\n}\n\n/**\n * Save reflection report to file\n */\nexport async function saveReflectionReport(\n report: string,\n outputPath: string,\n storage?: StorageAdapter\n): Promise<void> {\n if (!storage) {\n throw new Error('Storage adapter required to save report');\n }\n\n // Extract filename from path\n const filename = outputPath.split('/').pop() || 'reflection.md';\n await storage.writeOutput(filename, report);\n}\n","/**\n * Metrics collection for agentic workflows\n *\n * Provides integration with riotprompt's MetricsCollector while\n * maintaining compatibility with existing tool metrics.\n */\n\nimport { MetricsCollector, type AgenticExecutionMetrics } from '@riotprompt/riotprompt';\nimport type { Logger } from '../types';\n\nexport interface ToolExecutionMetric {\n name: string;\n timestamp: number;\n duration: number;\n success: boolean;\n iteration: number;\n error?: string;\n}\n\nexport interface MetricsConfig {\n logger?: Logger;\n}\n\n/**\n * Create a metrics collector for agentic workflows\n *\n * This wraps riotprompt's MetricsCollector and provides compatibility\n * with existing tool metrics format.\n */\nexport function createMetricsCollector(config: MetricsConfig = {}) {\n const { logger } = config;\n const collector = new MetricsCollector(logger);\n const toolMetrics: ToolExecutionMetric[] = [];\n\n return {\n /**\n * Record a tool execution\n */\n recordToolExecution(metric: ToolExecutionMetric) {\n toolMetrics.push(metric);\n\n // Also record in riotprompt's collector\n collector.recordToolCall(\n metric.name,\n metric.iteration,\n metric.duration,\n metric.success,\n metric.error\n );\n\n if (logger) {\n const status = metric.success ? 'success' : 'failed';\n logger.debug(`Tool ${metric.name} ${status} in ${metric.duration}ms`);\n }\n },\n\n /**\n * Record an iteration\n */\n recordIteration() {\n collector.incrementIteration();\n\n if (logger) {\n logger.debug(`Iteration incremented`);\n }\n },\n\n /**\n * Get tool metrics in legacy format (for backward compatibility)\n */\n getToolMetrics(): ToolExecutionMetric[] {\n return [...toolMetrics];\n },\n\n /**\n * Generate execution metrics report\n */\n generateReport(): AgenticExecutionMetrics {\n return collector.getMetrics([]);\n },\n\n /**\n * Get summary statistics\n */\n getSummary() {\n const report = collector.getMetrics([]);\n return {\n totalIterations: report.iterations,\n totalToolCalls: report.toolCallsExecuted,\n totalDuration: report.totalDuration,\n toolMetrics: report.toolMetrics,\n toolStats: report.toolStats\n };\n },\n\n /**\n * Reset all metrics\n */\n reset() {\n toolMetrics.length = 0;\n // Note: MetricsCollector doesn't have reset, create new instance if needed\n }\n };\n}\n\nexport type MetricsCollectorInstance = ReturnType<typeof createMetricsCollector>;\n\n"],"names":["isTokenLimitError","logger","timeoutMs","elapsedTimeFormatted","fs","__filename","__dirname","path","createGetFileHistoryTool","createGetFileContentTool","createSearchCodebaseTool","createGetRelatedTestsTool","createGetFileDependenciesTool","createAnalyzeDiffSectionTool","createGetRecentCommitsTool","createGroupFilesByConcernTool","buildSystemPrompt","buildUserMessage","parseAgenticResult"],"mappings":"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"}
|