cast-code 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/git/services/commit-generator.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { execSync } from 'child_process';\nimport { HumanMessage, SystemMessage } from '@langchain/core/messages';\nimport { MultiLlmService } from '../../../common/services/multi-llm.service';\nimport { MonorepoDetectorService } from './monorepo-detector.service';\nimport { GitDiffInfo, SplitCommit, CommitGroup, MonorepoInfo } from '../types/git.types';\n\n@Injectable()\nexport class CommitGeneratorService {\n constructor(\n private readonly multiLlmService: MultiLlmService,\n private readonly monorepoDetector: MonorepoDetectorService,\n ) {}\n\n getDiffInfo(): GitDiffInfo | null {\n try {\n const cwd = process.cwd();\n const staged = execSync('git diff --cached', { cwd, encoding: 'utf-8' });\n const unstaged = execSync('git diff', { cwd, encoding: 'utf-8' });\n const stats = execSync('git diff --stat', { cwd, encoding: 'utf-8' });\n const untrackedRaw = execSync('git ls-files --others --exclude-standard', { cwd, encoding: 'utf-8' });\n const untrackedFiles = untrackedRaw.trim() ? untrackedRaw.trim().split('\\n').filter(f => f.trim()) : [];\n\n return {\n staged,\n unstaged,\n stagedFiles: this.extractFiles(staged),\n unstagedFiles: this.extractFiles(unstaged),\n untrackedFiles,\n stats,\n };\n } catch {\n return null;\n }\n }\n\n hasChanges(): boolean {\n try {\n const output = execSync('git status --porcelain', { cwd: process.cwd(), encoding: 'utf-8' });\n return output.trim().length > 0;\n } catch {\n return false;\n }\n }\n\n async generateCommitMessage(): Promise<string | null> {\n const diffInfo = this.getDiffInfo();\n if (!diffInfo) return null;\n\n const monorepoInfo = this.monorepoDetector.detectMonorepo(process.cwd());\n const allFiles = [...diffInfo.stagedFiles, ...diffInfo.unstagedFiles, ...diffInfo.untrackedFiles];\n const scope = this.monorepoDetector.determineScope(allFiles, monorepoInfo);\n\n const llm = this.multiLlmService.createModel('cheap');\n const prompt = this.buildCommitPrompt(diffInfo, scope);\n\n const response = await llm.invoke([\n new SystemMessage(this.getCommitSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const message = this.extractContent(response.content);\n return this.cleanCommitMessage(message);\n }\n\n async splitCommits(): Promise<SplitCommit[] | null> {\n const diffInfo = this.getDiffInfo();\n if (!diffInfo) return null;\n\n const monorepoInfo = this.monorepoDetector.detectMonorepo(process.cwd());\n const allFiles = [...diffInfo.stagedFiles, ...diffInfo.unstagedFiles, ...diffInfo.untrackedFiles];\n\n const llm = this.multiLlmService.createModel('cheap');\n const splitPrompt = this.buildSplitPrompt(diffInfo, allFiles);\n\n const splitResponse = await llm.invoke([\n new SystemMessage(this.getSplitSystemPrompt()),\n new HumanMessage(splitPrompt),\n ]);\n\n const splitContent = this.extractContent(splitResponse.content);\n const commitGroups = this.parseCommitGroups(splitContent);\n\n if (!commitGroups?.length) return null;\n\n const validGroups = commitGroups.filter((group) => Array.isArray(group.files) && group.files.length > 0);\n if (validGroups.length === 0) return null;\n\n for (const group of validGroups) {\n if (!group.scope) {\n group.scope = this.monorepoDetector.determineScope(group.files, monorepoInfo);\n }\n }\n\n const splitCommits: SplitCommit[] = [];\n for (const group of validGroups) {\n const message = await this.generateMessageForGroup(group, diffInfo);\n splitCommits.push({ ...group, message });\n }\n\n return splitCommits;\n }\n\n executeCommit(message: string, autoStage = true): boolean {\n try {\n const cwd = process.cwd();\n if (autoStage) {\n execSync('git add -A', { cwd });\n }\n execSync('git commit -F -', { cwd, input: `${message}\\n`, encoding: 'utf-8' });\n return true;\n } catch {\n return false;\n }\n }\n\n executePush(): { success: boolean; error?: string } {\n try {\n const cwd = process.cwd();\n const branch = execSync('git branch --show-current', { cwd, encoding: 'utf-8' }).trim();\n execSync(`git push origin ${branch}`, { cwd, encoding: 'utf-8' });\n return { success: true };\n } catch (error: any) {\n const message = error.message || 'Push failed';\n if (message.includes('rejected') || message.includes('diverged')) {\n return { success: false, error: 'Push rejected. Run \"git pull --rebase\" first.' };\n }\n return { success: false, error: message };\n }\n }\n\n executeSplitCommits(commits: SplitCommit[]): { success: boolean; committed: number; error?: string; originalHead?: string } {\n const cwd = process.cwd();\n let committedCount = 0;\n let originalHead: string | undefined;\n\n try {\n originalHead = execSync('git rev-parse HEAD', { cwd, encoding: 'utf-8' }).trim();\n\n for (const commit of commits) {\n execSync('git reset', { cwd });\n\n for (const file of commit.files) {\n try {\n execSync(`git add \"${file}\"`, { cwd });\n } catch {}\n }\n\n const staged = execSync('git diff --cached --name-only', { cwd, encoding: 'utf-8' });\n if (!staged.trim()) continue;\n\n execSync('git commit -F -', { cwd, input: `${commit.message}\\n`, encoding: 'utf-8' });\n committedCount++;\n }\n\n return { success: true, committed: committedCount };\n } catch (error: any) {\n return {\n success: false,\n committed: committedCount,\n error: error.message || 'Failed to execute commits',\n originalHead\n };\n }\n }\n\n async refineCommitMessage(\n currentMessage: string,\n userSuggestion: string,\n diffInfo: GitDiffInfo,\n ): Promise<string> {\n const llm = this.multiLlmService.createModel('cheap');\n\n const prompt = `Current commit message: ${currentMessage}\\n\\nUser suggestion: ${userSuggestion}\\n\\nDiff:\\n${diffInfo.staged.slice(0, 3000)}`;\n\n const response = await llm.invoke([\n new SystemMessage(this.getRefineSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const message = this.extractContent(response.content);\n return this.cleanCommitMessage(message);\n }\n\n private extractFiles(diff: string): string[] {\n const files = new Set<string>();\n const lines = diff.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('diff --git')) {\n const match = line.match(/diff --git a\\/(.+?) b\\/(.+?)$/);\n if (match) {\n files.add(match[2]);\n }\n }\n }\n\n return Array.from(files);\n }\n\n private extractContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0];\n if (typeof first === 'object' && first !== null && 'text' in first) {\n return String(first.text);\n }\n }\n return String(content);\n }\n\n private cleanCommitMessage(message: string): string {\n const lines = message.trim().split('\\n').map(l => l.trim()).filter(l => l.length > 0);\n const firstCommitLine = lines.find(l => l.includes(':')) || lines[0] || '';\n return firstCommitLine.replace(/^[\"']|[\"']$/g, '').trim();\n }\n\n private buildCommitPrompt(diffInfo: GitDiffInfo, scope?: string): string {\n const scopeHint = scope ? `\\n\\nThis is a monorepo. The changes are primarily in the \"${scope}\" module.` : '';\n\n let fullDiff = '';\n if (diffInfo.staged) {\n fullDiff += `=== Staged changes ===\\n${diffInfo.staged}\\n\\n`;\n }\n if (diffInfo.unstaged) {\n fullDiff += `=== Unstaged changes ===\\n${diffInfo.unstaged}\\n\\n`;\n }\n\n const untrackedHint = diffInfo.untrackedFiles.length > 0\n ? `\\nNew untracked files (will also be committed): ${diffInfo.untrackedFiles.join(', ')}\\n`\n : '';\n\n const maxLength = 10000;\n if (fullDiff.length > maxLength) {\n fullDiff = fullDiff.slice(0, maxLength) + '\\n\\n... (truncated)';\n }\n\n return `Generate a single conventional commit message for ALL of the following changes.${scopeHint}\\n\\nFiles changed:\\n${diffInfo.stats}${untrackedHint}\\n\\n${fullDiff}`;\n }\n\n private buildSplitPrompt(diffInfo: GitDiffInfo, files: string[]): string {\n let fullDiff = '';\n if (diffInfo.staged) {\n fullDiff += `=== Staged changes ===\\n${diffInfo.staged}\\n\\n`;\n }\n if (diffInfo.unstaged) {\n fullDiff += `=== Unstaged changes ===\\n${diffInfo.unstaged}\\n\\n`;\n }\n\n const allFiles = [...files, ...diffInfo.untrackedFiles.filter(f => !files.includes(f))];\n const untrackedHint = diffInfo.untrackedFiles.length > 0\n ? `\\nNew untracked files (must be included in commits): ${diffInfo.untrackedFiles.join(', ')}\\n`\n : '';\n\n const maxLength = 8000;\n if (fullDiff.length > maxLength) {\n fullDiff = fullDiff.slice(0, maxLength) + '\\n\\n... (truncated)';\n }\n\n return `Analyze all the files below and group them into logical commits. Include ALL files in the result.\\n\\nFiles: ${allFiles.join(', ')}${untrackedHint}\\n\\nStats:\\n${diffInfo.stats}\\n\\n${fullDiff}`;\n }\n\n private async generateMessageForGroup(group: CommitGroup, diffInfo: GitDiffInfo): Promise<string> {\n const llm = this.multiLlmService.createModel('cheap');\n\n const scopePart = group.scope ? `(${group.scope})` : '';\n\n const prompt = `Generate a conventional commit message (max 72 chars) for:\\n\\nType: ${group.type}${scopePart}\\nFiles: ${group.files.join(', ')}\\nDescription: ${group.description}\\n\\nIMPORTANT: Return ONLY the commit message in format: \"type(scope): description\" or \"type: description\"\\nThe message MUST be in English.`;\n\n const response = await llm.invoke([\n new SystemMessage(this.getCommitSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n let message = this.extractContent(response.content);\n message = this.cleanCommitMessage(message);\n\n if (!message.includes(':')) {\n const scope = group.scope ? `(${group.scope})` : '';\n message = `${group.type}${scope}: ${message}`;\n }\n\n return message;\n }\n\n private parseCommitGroups(content: string): CommitGroup[] | null {\n const jsonMatch = content.match(/```json\\s*([\\s\\S]*?)\\s*```/);\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[1]);\n if (parsed.commits && Array.isArray(parsed.commits)) {\n return parsed.commits;\n }\n } catch {}\n }\n\n try {\n const parsed = JSON.parse(content);\n if (parsed.commits && Array.isArray(parsed.commits)) {\n return parsed.commits;\n }\n } catch {}\n\n return null;\n }\n\n private getCommitSystemPrompt(): string {\n return `You are a Git commit message expert. Generate concise commit messages following Conventional Commits.\n\n**Available types:**\n- feat: new feature\n- fix: bug fix\n- docs: documentation\n- style: formatting (no logic change)\n- refactor: refactoring (no functionality change)\n- perf: performance improvement\n- test: tests\n- build: build/dependencies\n- ci: continuous integration\n- chore: general tasks\n- cleanup: code cleanup\n- remove: code removal\n\n**Format:**\n- With scope: <type>(<scope>): <description>\n- Without scope: <type>: <description>\n\n**Rules:**\n- Maximum 72 characters for the subject line\n- Description in English\n- No period at the end\n- Use imperative mood (\"add\" not \"added\")\n- Be specific but concise\n\nIf this is a monorepo and you can identify the module, include the scope.\n\nReturn ONLY the commit message, nothing else.`;\n }\n\n private getSplitSystemPrompt(): string {\n return `You are a Git commit organization expert. Analyze the changes and divide them into logical commits.\n\n**YOUR TASK:**\nGroup changes into logical commits based on:\n1. **Functional cohesion**: Changes that make sense together\n2. **Change type**: features, fixes, docs, refactorings separated\n3. **Related files**: Files that work together\n\n**RETURN FORMAT (JSON):**\nReturn ONLY valid JSON in this format:\n\\`\\`\\`json\n{\n \"commits\": [\n {\n \"type\": \"feat\",\n \"files\": [\"src/auth.ts\", \"src/models/user.ts\"],\n \"description\": \"add user authentication\"\n },\n {\n \"type\": \"docs\",\n \"files\": [\"README.md\"],\n \"description\": \"update documentation\"\n }\n ]\n}\n\\`\\`\\`\n\n**AVAILABLE TYPES:**\nfeat, fix, docs, style, refactor, perf, test, build, ci, chore\n\n**RULES:**\n- Each commit should have a clear purpose\n- Group functionally related files\n- Separate features from fixes from documentation\n- Maximum 5 files per commit (ideally fewer)\n- If diff is small (<3 files), can be 1 commit only\n- Description must ALWAYS be in English\n- Include ALL files in the result\n\n**IMPORTANT:** Return ONLY the JSON, no additional text.`;\n }\n\n private getRefineSystemPrompt(): string {\n return `You are refining a commit message based on user feedback.\n\n**Instructions:**\n- Keep the message concise (max 72 characters)\n- Follow Conventional Commits format\n- Incorporate the user's suggestion\n- Return ONLY the new commit message, without explanations\n- Message MUST be in English`;\n }\n}\n"],"names":["CommitGeneratorService","getDiffInfo","cwd","process","staged","execSync","encoding","unstaged","stats","untrackedRaw","untrackedFiles","trim","split","filter","f","stagedFiles","extractFiles","unstagedFiles","hasChanges","output","length","generateCommitMessage","diffInfo","monorepoInfo","monorepoDetector","detectMonorepo","allFiles","scope","determineScope","llm","multiLlmService","createModel","prompt","buildCommitPrompt","response","invoke","SystemMessage","getCommitSystemPrompt","HumanMessage","message","extractContent","content","cleanCommitMessage","splitCommits","splitPrompt","buildSplitPrompt","splitResponse","getSplitSystemPrompt","splitContent","commitGroups","parseCommitGroups","validGroups","group","Array","isArray","files","generateMessageForGroup","push","executeCommit","autoStage","input","executePush","branch","success","error","includes","executeSplitCommits","commits","committedCount","originalHead","commit","file","committed","refineCommitMessage","currentMessage","userSuggestion","slice","getRefineSystemPrompt","diff","Set","lines","line","startsWith","match","add","from","first","String","text","map","l","firstCommitLine","find","replace","scopeHint","fullDiff","untrackedHint","join","maxLength","scopePart","type","description","jsonMatch","parsed","JSON","parse"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/modules/git/services/commit-generator.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { readFileSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { HumanMessage, SystemMessage } from '@langchain/core/messages';\nimport { MultiLlmService } from '../../../common/services/multi-llm.service';\nimport { MonorepoDetectorService } from './monorepo-detector.service';\nimport { GitDiffInfo, SplitCommit, CommitGroup, ConventionalCommitType } from '../types/git.types';\n\nconst COMMIT_TYPES: ConventionalCommitType[] = [\n 'feat',\n 'fix',\n 'docs',\n 'style',\n 'refactor',\n 'perf',\n 'test',\n 'build',\n 'ci',\n 'chore',\n];\n\nconst COMMIT_TYPE_SET = new Set<string>(COMMIT_TYPES);\n\nconst COMMIT_TYPE_ALIASES: Record<string, ConventionalCommitType> = {\n feature: 'feat',\n features: 'feat',\n bug: 'fix',\n bugfix: 'fix',\n documentation: 'docs',\n docs: 'docs',\n test: 'test',\n tests: 'test',\n testing: 'test',\n performance: 'perf',\n optimize: 'perf',\n optimization: 'perf',\n dependency: 'build',\n dependencies: 'build',\n maintenance: 'chore',\n housekeeping: 'chore',\n cleanup: 'chore',\n remove: 'refactor',\n};\n\nconst LEADING_VERB_TRANSLATIONS: Record<string, string> = {\n add: 'adiciona',\n adds: 'adiciona',\n update: 'atualiza',\n updates: 'atualiza',\n upgrade: 'atualiza',\n upgrades: 'atualiza',\n fix: 'corrige',\n fixes: 'corrige',\n remove: 'remove',\n removes: 'remove',\n refactor: 'refatora',\n refactors: 'refatora',\n improve: 'melhora',\n improves: 'melhora',\n create: 'cria',\n creates: 'cria',\n implement: 'implementa',\n implements: 'implementa',\n rename: 'renomeia',\n renames: 'renomeia',\n};\n\n@Injectable()\nexport class CommitGeneratorService {\n constructor(\n private readonly multiLlmService: MultiLlmService,\n private readonly monorepoDetector: MonorepoDetectorService,\n ) {}\n\n getDiffInfo(): GitDiffInfo | null {\n try {\n const cwd = process.cwd();\n const staged = execSync('git diff --cached --unified=1 --no-ext-diff', { cwd, encoding: 'utf-8' });\n const unstaged = execSync('git diff --unified=1 --no-ext-diff', { cwd, encoding: 'utf-8' });\n const stagedStats = execSync('git diff --cached --stat', { cwd, encoding: 'utf-8' });\n const unstagedStats = execSync('git diff --stat', { cwd, encoding: 'utf-8' });\n const statusShort = execSync('git status --short', { cwd, encoding: 'utf-8' });\n const untrackedRaw = execSync('git ls-files --others --exclude-standard', { cwd, encoding: 'utf-8' });\n const untrackedFiles = untrackedRaw.trim() ? untrackedRaw.trim().split('\\n').filter(f => f.trim()) : [];\n\n return {\n staged,\n unstaged,\n stagedFiles: this.extractFiles(staged),\n unstagedFiles: this.extractFiles(unstaged),\n untrackedFiles,\n stats: this.buildStatsSummary(stagedStats, unstagedStats, statusShort, untrackedFiles),\n };\n } catch {\n return null;\n }\n }\n\n hasChanges(): boolean {\n try {\n const output = execSync('git status --porcelain', { cwd: process.cwd(), encoding: 'utf-8' });\n return output.trim().length > 0;\n } catch {\n return false;\n }\n }\n\n async generateCommitMessage(): Promise<string | null> {\n const diffInfo = this.getDiffInfo();\n if (!diffInfo) return null;\n\n const monorepoInfo = this.monorepoDetector.detectMonorepo(process.cwd());\n const allFiles = [...diffInfo.stagedFiles, ...diffInfo.unstagedFiles, ...diffInfo.untrackedFiles];\n const scope = this.monorepoDetector.determineScope(allFiles, monorepoInfo);\n\n const llm = this.multiLlmService.createModel('cheap');\n const prompt = this.buildCommitPrompt(diffInfo, scope);\n\n const response = await llm.invoke([\n new SystemMessage(this.getCommitSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const message = this.extractContent(response.content);\n return this.normalizeCommitMessage(message, 'chore', scope);\n }\n\n async splitCommits(): Promise<SplitCommit[] | null> {\n const diffInfo = this.getDiffInfo();\n if (!diffInfo) return null;\n\n const monorepoInfo = this.monorepoDetector.detectMonorepo(process.cwd());\n const allFiles = [...diffInfo.stagedFiles, ...diffInfo.unstagedFiles, ...diffInfo.untrackedFiles];\n\n const llm = this.multiLlmService.createModel('cheap');\n const splitPrompt = this.buildSplitPrompt(diffInfo, allFiles);\n\n const splitResponse = await llm.invoke([\n new SystemMessage(this.getSplitSystemPrompt()),\n new HumanMessage(splitPrompt),\n ]);\n\n const splitContent = this.extractContent(splitResponse.content);\n const commitGroups = this.parseCommitGroups(splitContent);\n if (!commitGroups?.length) return null;\n\n const normalizedGroups = this.normalizeCommitGroups(commitGroups, allFiles);\n if (normalizedGroups.length === 0) return null;\n\n for (const group of normalizedGroups) {\n if (!group.scope) {\n group.scope = this.monorepoDetector.determineScope(group.files, monorepoInfo);\n }\n }\n\n const splitCommits: SplitCommit[] = [];\n for (const group of normalizedGroups) {\n const message = await this.generateMessageForGroup(group);\n splitCommits.push({ ...group, message });\n }\n\n return splitCommits;\n }\n\n executeCommit(message: string, autoStage = true): boolean {\n try {\n const cwd = process.cwd();\n if (autoStage) {\n execSync('git add -A', { cwd });\n }\n execSync('git commit -F -', { cwd, input: `${message}\\n`, encoding: 'utf-8' });\n return true;\n } catch {\n return false;\n }\n }\n\n executePush(): { success: boolean; error?: string } {\n try {\n const cwd = process.cwd();\n const branch = execSync('git branch --show-current', { cwd, encoding: 'utf-8' }).trim();\n execSync(`git push origin ${branch}`, { cwd, encoding: 'utf-8' });\n return { success: true };\n } catch (error: any) {\n const message = error.message || 'Push failed';\n if (message.includes('rejected') || message.includes('diverged')) {\n return { success: false, error: 'Push rejected. Run \"git pull --rebase\" first.' };\n }\n return { success: false, error: message };\n }\n }\n\n executeSplitCommits(commits: SplitCommit[]): { success: boolean; committed: number; error?: string; originalHead?: string } {\n const cwd = process.cwd();\n let committedCount = 0;\n let originalHead: string | undefined;\n\n try {\n originalHead = execSync('git rev-parse HEAD', { cwd, encoding: 'utf-8' }).trim();\n\n for (const commit of commits) {\n execSync('git reset', { cwd });\n\n for (const file of this.normalizeFiles(commit.files)) {\n try {\n execSync(`git add -- ${this.escapeShellArg(file)}`, { cwd });\n } catch {}\n }\n\n const staged = execSync('git diff --cached --name-only', { cwd, encoding: 'utf-8' });\n if (!staged.trim()) continue;\n\n execSync('git commit -F -', { cwd, input: `${commit.message}\\n`, encoding: 'utf-8' });\n committedCount++;\n }\n\n return { success: true, committed: committedCount };\n } catch (error: any) {\n return {\n success: false,\n committed: committedCount,\n error: error.message || 'Failed to execute commits',\n originalHead\n };\n }\n }\n\n async refineCommitMessage(\n currentMessage: string,\n userSuggestion: string,\n diffInfo: GitDiffInfo,\n ): Promise<string> {\n const llm = this.multiLlmService.createModel('cheap');\n const context = this.buildDiffContext(diffInfo, {\n maxLength: 6000,\n maxCharsPerFile: 1200,\n maxUntrackedFiles: 3,\n maxUntrackedLines: 40,\n });\n const currentMetadata = this.extractTypeAndScope(currentMessage);\n\n const prompt = `Mensagem atual: ${currentMessage}\n\nSugestão do usuário: ${userSuggestion}\n\nContexto do diff:\n${context}`;\n\n const response = await llm.invoke([\n new SystemMessage(this.getRefineSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const message = this.extractContent(response.content);\n return this.normalizeCommitMessage(\n message,\n currentMetadata.type ?? 'chore',\n currentMetadata.scope,\n 'atualiza código',\n currentMetadata.breaking ?? false,\n );\n }\n\n private extractFiles(diff: string): string[] {\n const files = new Set<string>();\n const lines = diff.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('diff --git')) {\n const match = line.match(/diff --git a\\/(.+?) b\\/(.+?)$/);\n if (match) {\n files.add(match[2]);\n }\n }\n }\n\n return Array.from(files);\n }\n\n private extractContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0];\n if (typeof first === 'object' && first !== null && 'text' in first) {\n return String(first.text);\n }\n }\n return String(content);\n }\n\n private buildCommitPrompt(diffInfo: GitDiffInfo, scope?: string): string {\n const scopeHint = scope\n ? `Escopo provável do monorepo: \"${scope}\".`\n : 'Escopo do monorepo não identificado automaticamente.';\n const fullDiff = this.buildDiffContext(diffInfo, {\n maxLength: 12000,\n maxCharsPerFile: 1800,\n maxUntrackedFiles: 4,\n maxUntrackedLines: 60,\n });\n\n return `Analise TODO o contexto de mudanças e gere UMA mensagem de commit no padrão Conventional Commits.\n\n${scopeHint}\n\nRegras obrigatórias:\n- Formato: \"type(scope): descrição\", \"type: descrição\" ou com breaking \"type(scope)!: descrição\"\n- Tipos permitidos: ${COMMIT_TYPES.join(', ')}\n- Descrição em português (pt-BR), objetiva, no imperativo e sem ponto final\n- Máximo de 72 caracteres no assunto completo\n- A mensagem deve refletir a intenção principal do conjunto total de mudanças\n- Se for breaking change, inclua \"!\" após o type/scope\n- Considere staged, unstaged e arquivos novos\n\nContexto do diff:\n${fullDiff}`;\n }\n\n private buildSplitPrompt(diffInfo: GitDiffInfo, files: string[]): string {\n const allFiles = this.normalizeFiles([...files, ...diffInfo.untrackedFiles]);\n const fullDiff = this.buildDiffContext(diffInfo, {\n maxLength: 15000,\n maxCharsPerFile: 1600,\n maxUntrackedFiles: 6,\n maxUntrackedLines: 80,\n });\n\n return `Analise o diff completo e divida em commits lógicos no padrão Conventional Commits.\n\nRegras obrigatórias:\n- Cada arquivo da lista deve aparecer exatamente uma vez no resultado\n- Inclua TODOS os arquivos listados\n- Separe mudanças por coesão funcional (feature, fix, docs, refactor etc.)\n- Evite misturar objetivos diferentes no mesmo commit\n- Tipos permitidos: ${COMMIT_TYPES.join(', ')}\n- Descrição em português (pt-BR), no imperativo e sem ponto final\n\nArquivos esperados:\n${allFiles.join(', ') || '(nenhum arquivo detectado)'}\n\nContexto do diff:\n${fullDiff}`;\n }\n\n private async generateMessageForGroup(group: CommitGroup): Promise<string> {\n const llm = this.multiLlmService.createModel('cheap');\n const scopePart = group.scope ? `(${group.scope})` : '';\n const prompt = `Gere uma mensagem Conventional Commit (máximo 72 caracteres) para este grupo:\n\nTipo: ${group.type}${scopePart}\nArquivos: ${group.files.join(', ')}\nResumo: ${group.description}\n\nRetorne APENAS uma linha no formato:\n\"type(scope): descrição\", \"type: descrição\" ou \"type(scope)!: descrição\"\n\nDescrição obrigatoriamente em português (pt-BR).`;\n\n const response = await llm.invoke([\n new SystemMessage(this.getCommitSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const message = this.extractContent(response.content);\n return this.normalizeCommitMessage(message, group.type, group.scope, group.description);\n }\n\n private parseCommitGroups(content: string): CommitGroup[] | null {\n const jsonMatch = content.match(/```json\\s*([\\s\\S]*?)\\s*```/);\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[1]);\n if (parsed.commits && Array.isArray(parsed.commits)) {\n return parsed.commits;\n }\n } catch {}\n }\n\n try {\n const parsed = JSON.parse(content);\n if (parsed.commits && Array.isArray(parsed.commits)) {\n return parsed.commits;\n }\n } catch {}\n\n return null;\n }\n\n private getCommitSystemPrompt(): string {\n return `Você é especialista em mensagens de commit no padrão Conventional Commits.\n\nTipos permitidos:\n${COMMIT_TYPES.join(', ')}\n\nFormato obrigatório:\n- Com escopo: <type>(<scope>): <descrição>\n- Sem escopo: <type>: <descrição>\n- Breaking change no assunto: <type>(<scope>)!: <descrição> (ou <type>!: <descrição>)\n\nRegras:\n- Assunto completo com no máximo 72 caracteres\n- Descrição em português (pt-BR)\n- Verbo no imperativo\n- Sem ponto final\n- Seja específico e evite mensagens genéricas\n- Use escopo quando ele estiver claro\n- Tipos feat e fix devem ser usados de forma semântica (feature e correção)\n\nRetorne SOMENTE a linha do commit, sem explicações.`;\n }\n\n private getSplitSystemPrompt(): string {\n return `Você é especialista em organizar diffs em commits lógicos.\n\nTarefa:\n- Agrupar mudanças por coesão funcional\n- Separar corretamente feature, fix, docs, refactor etc.\n- Garantir que todos os arquivos apareçam exatamente uma vez\n\nFormato de resposta:\nRetorne SOMENTE JSON válido:\n\\`\\`\\`json\n{\n \"commits\": [\n {\n \"type\": \"feat\",\n \"files\": [\"src/chatbot/service.ts\"],\n \"description\": \"adiciona service de chatbot\"\n },\n {\n \"type\": \"docs\",\n \"files\": [\"README.md\"],\n \"description\": \"atualiza documentação de uso\"\n }\n ]\n}\n\\`\\`\\`\n\nRegras:\n- Tipos permitidos: ${COMMIT_TYPES.join(', ')}\n- Cada commit com propósito claro\n- Descrição em português (pt-BR), no imperativo, sem ponto final\n- Máximo recomendado de 5 arquivos por commit\n- Pode retornar 1 commit apenas se o diff for pequeno e coeso\n\nRetorne SOMENTE o JSON, sem texto adicional.`;\n }\n\n private getRefineSystemPrompt(): string {\n return `Você está refinando uma mensagem de commit a partir do feedback do usuário.\n\nInstruções:\n- Respeite Conventional Commits\n- Mantenha no máximo 72 caracteres\n- Mensagem em português (pt-BR), no imperativo e sem ponto final\n- Incorpore a sugestão do usuário sem perder precisão técnica\n\nRetorne SOMENTE a nova linha de commit.`;\n }\n\n private normalizeCommitGroups(commitGroups: CommitGroup[], files: string[]): CommitGroup[] {\n const expectedFiles = new Set(this.normalizeFiles(files));\n const usedFiles = new Set<string>();\n const normalizedGroups: CommitGroup[] = [];\n\n for (const group of commitGroups) {\n const filesFromGroup = this.normalizeFiles(Array.isArray(group.files) ? group.files : [])\n .filter((file) => expectedFiles.has(file))\n .filter((file) => {\n if (usedFiles.has(file)) {\n return false;\n }\n usedFiles.add(file);\n return true;\n });\n\n if (filesFromGroup.length === 0) continue;\n\n normalizedGroups.push({\n type: this.normalizeCommitType(group.type, this.inferTypeFromFiles(filesFromGroup)),\n files: filesFromGroup,\n description: this.normalizeDescription(group.description, 'organiza mudanças relacionadas'),\n scope: this.normalizeScope(group.scope),\n });\n }\n\n const missingFiles = this.normalizeFiles(files).filter((file) => !usedFiles.has(file));\n if (missingFiles.length > 0) {\n normalizedGroups.push({\n type: this.inferTypeFromFiles(missingFiles),\n files: missingFiles,\n description: 'organiza arquivos restantes do diff',\n });\n }\n\n return normalizedGroups;\n }\n\n private normalizeCommitMessage(\n rawMessage: string,\n fallbackType: ConventionalCommitType,\n fallbackScope?: string,\n fallbackDescription = 'atualiza código',\n fallbackBreaking = false,\n ): string {\n const candidateLine = this.extractCandidateCommitLine(rawMessage);\n const match = candidateLine.match(/^([a-zA-Z-]+)(?:\\(([^)]+)\\))?(!)?:\\s*(.+)$/);\n\n const type = this.normalizeCommitType(match?.[1], fallbackType);\n const scope = this.normalizeScope(match?.[2] ?? fallbackScope);\n const breaking = Boolean(match?.[3]) || fallbackBreaking;\n const rawDescription = match?.[4] ?? candidateLine;\n const description = this.normalizeDescription(rawDescription, fallbackDescription);\n\n const breakingFlag = breaking ? '!' : '';\n const prefix = scope\n ? `${type}(${scope})${breakingFlag}: `\n : `${type}${breakingFlag}: `;\n const maxDescriptionLength = Math.max(12, 72 - prefix.length);\n const truncatedDescription = this.truncateText(description, maxDescriptionLength);\n\n return `${prefix}${truncatedDescription}`;\n }\n\n private extractTypeAndScope(message: string): {\n type?: ConventionalCommitType;\n scope?: string;\n breaking?: boolean;\n } {\n const candidateLine = this.extractCandidateCommitLine(message);\n const match = candidateLine.match(/^([a-zA-Z-]+)(?:\\(([^)]+)\\))?(!)?:\\s*.+$/);\n if (!match) return {};\n\n return {\n type: this.normalizeCommitType(match[1], 'chore'),\n scope: this.normalizeScope(match[2]),\n breaking: Boolean(match[3]),\n };\n }\n\n private extractCandidateCommitLine(rawMessage: string): string {\n const withoutCodeBlock = rawMessage.replace(/```(?:[\\w-]+)?/g, '');\n const lines = withoutCodeBlock\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => line.replace(/^[-*]\\s+/, ''));\n\n if (lines.length === 0) return '';\n\n const conventionalLine = lines.find((line) => /^[a-zA-Z-]+(?:\\([^)]+\\))?!?:\\s+/.test(line));\n if (conventionalLine) {\n return conventionalLine.replace(/^[\"'`]|[\"'`]$/g, '').trim();\n }\n\n const prefixedLine = lines.find((line) => /^commit\\s*:/i.test(line));\n if (prefixedLine) {\n return prefixedLine.replace(/^commit\\s*:/i, '').replace(/^[\"'`]|[\"'`]$/g, '').trim();\n }\n\n return lines[0].replace(/^[\"'`]|[\"'`]$/g, '').trim();\n }\n\n private normalizeCommitType(\n type: string | undefined,\n fallbackType: ConventionalCommitType,\n ): ConventionalCommitType {\n const normalized = (type || '')\n .toLowerCase()\n .trim()\n .replace(/[^a-z]/g, '');\n\n if (!normalized) return fallbackType;\n if (COMMIT_TYPE_SET.has(normalized)) return normalized as ConventionalCommitType;\n if (COMMIT_TYPE_ALIASES[normalized]) return COMMIT_TYPE_ALIASES[normalized];\n\n return fallbackType;\n }\n\n private normalizeScope(scope?: string): string | undefined {\n if (!scope) return undefined;\n\n const normalized = scope\n .trim()\n .replace(/^[\"'`]|[\"'`]$/g, '')\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9/_-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n\n return normalized || undefined;\n }\n\n private normalizeDescription(description: string, fallback: string): string {\n let normalized = description\n .replace(/^[\"'`]|[\"'`]$/g, '')\n .replace(/^([a-zA-Z-]+)(?:\\([^)]+\\))?!?:\\s*/, '')\n .replace(/\\s+/g, ' ')\n .trim();\n\n normalized = normalized.replace(/[.;:!?]+$/, '').trim();\n if (!normalized) normalized = fallback;\n\n normalized = this.translateLeadingVerb(normalized);\n\n if (/^[A-ZÀ-Ý]/.test(normalized)) {\n normalized = normalized.charAt(0).toLowerCase() + normalized.slice(1);\n }\n\n return normalized;\n }\n\n private translateLeadingVerb(description: string): string {\n const match = description.match(/^([a-zA-Z]+)(\\b.*)$/);\n if (!match) return description;\n\n const translated = LEADING_VERB_TRANSLATIONS[match[1].toLowerCase()];\n if (!translated) return description;\n\n return `${translated}${match[2]}`;\n }\n\n private truncateText(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n\n const truncated = text.slice(0, maxLength).trimEnd();\n const lastSpace = truncated.lastIndexOf(' ');\n if (lastSpace > maxLength * 0.6) {\n return truncated.slice(0, lastSpace).trimEnd();\n }\n\n return truncated;\n }\n\n private normalizeFiles(files: string[]): string[] {\n const unique = new Set<string>();\n\n for (const file of files) {\n if (typeof file !== 'string') continue;\n const normalized = file.trim().replace(/^[\"']|[\"']$/g, '');\n if (!normalized) continue;\n unique.add(normalized);\n }\n\n return Array.from(unique);\n }\n\n private buildStatsSummary(\n stagedStats: string,\n unstagedStats: string,\n statusShort: string,\n untrackedFiles: string[],\n ): string {\n const sections: string[] = [];\n\n if (statusShort.trim()) {\n sections.push(`Git status (--short):\\n${statusShort.trim()}`);\n }\n if (stagedStats.trim()) {\n sections.push(`Diff staged (--cached --stat):\\n${stagedStats.trim()}`);\n }\n if (unstagedStats.trim()) {\n sections.push(`Diff unstaged (--stat):\\n${unstagedStats.trim()}`);\n }\n if (untrackedFiles.length > 0) {\n sections.push(`Arquivos novos (${untrackedFiles.length}): ${untrackedFiles.join(', ')}`);\n }\n\n return sections.join('\\n\\n');\n }\n\n private buildDiffContext(\n diffInfo: GitDiffInfo,\n options: {\n maxLength: number;\n maxCharsPerFile: number;\n maxUntrackedFiles: number;\n maxUntrackedLines: number;\n },\n ): string {\n const sections: string[] = [];\n\n if (diffInfo.stats.trim()) {\n sections.push(`Resumo:\\n${diffInfo.stats.trim()}`);\n }\n\n sections.push(this.buildFilesSummary(diffInfo));\n\n const stagedByFile = this.limitDiffByFile(diffInfo.staged, options.maxCharsPerFile);\n if (stagedByFile) {\n sections.push(`=== STAGED ===\\n${stagedByFile}`);\n }\n\n const unstagedByFile = this.limitDiffByFile(diffInfo.unstaged, options.maxCharsPerFile);\n if (unstagedByFile) {\n sections.push(`=== UNSTAGED ===\\n${unstagedByFile}`);\n }\n\n const untrackedPreview = this.buildUntrackedPreview(\n diffInfo.untrackedFiles,\n options.maxUntrackedFiles,\n options.maxUntrackedLines,\n );\n if (untrackedPreview) {\n sections.push(`=== PREVIEW ARQUIVOS NOVOS ===\\n${untrackedPreview}`);\n }\n\n let combined = sections.filter(Boolean).join('\\n\\n');\n if (combined.length > options.maxLength) {\n combined = `${combined.slice(0, options.maxLength).trimEnd()}\\n\\n... (contexto truncado)`;\n }\n\n return combined;\n }\n\n private buildFilesSummary(diffInfo: GitDiffInfo): string {\n const lines: string[] = [];\n\n const stagedFiles = this.normalizeFiles(diffInfo.stagedFiles);\n const unstagedFiles = this.normalizeFiles(diffInfo.unstagedFiles);\n const untrackedFiles = this.normalizeFiles(diffInfo.untrackedFiles);\n\n if (stagedFiles.length > 0) {\n lines.push(`Staged (${stagedFiles.length}): ${this.summarizeFileList(stagedFiles)}`);\n }\n if (unstagedFiles.length > 0) {\n lines.push(`Unstaged (${unstagedFiles.length}): ${this.summarizeFileList(unstagedFiles)}`);\n }\n if (untrackedFiles.length > 0) {\n lines.push(`Novos (${untrackedFiles.length}): ${this.summarizeFileList(untrackedFiles)}`);\n }\n\n if (lines.length === 0) {\n return 'Arquivos afetados: nenhum arquivo identificado';\n }\n\n return `Arquivos afetados:\\n${lines.join('\\n')}`;\n }\n\n private summarizeFileList(files: string[], limit = 20): string {\n if (files.length <= limit) {\n return files.join(', ');\n }\n\n const remaining = files.length - limit;\n return `${files.slice(0, limit).join(', ')}, ... (+${remaining})`;\n }\n\n private limitDiffByFile(diff: string, maxCharsPerFile: number): string {\n if (!diff.trim()) return '';\n\n const sections = this.splitDiffByFile(diff);\n if (sections.length === 0) return '';\n\n const limitedSections = sections.map((section) => {\n if (section.length <= maxCharsPerFile) return section.trimEnd();\n return `${section.slice(0, maxCharsPerFile).trimEnd()}\\n... (diff deste arquivo truncado)`;\n });\n\n return limitedSections.join('\\n\\n');\n }\n\n private splitDiffByFile(diff: string): string[] {\n const rawSections = diff\n .split(/^diff --git /m)\n .map((section) => section.trim())\n .filter((section) => section.length > 0);\n\n return rawSections.map((section) => `diff --git ${section}`);\n }\n\n private buildUntrackedPreview(files: string[], maxFiles: number, maxLines: number): string {\n const selectedFiles = this.normalizeFiles(files).slice(0, maxFiles);\n const sections: string[] = [];\n\n for (const file of selectedFiles) {\n const preview = this.readTextFilePreview(file, maxLines);\n if (!preview) continue;\n sections.push(`--- ${file} ---\\n${preview}`);\n }\n\n if (files.length > maxFiles) {\n sections.push(`... ${files.length - maxFiles} arquivo(s) novo(s) omitido(s)`);\n }\n\n return sections.join('\\n\\n');\n }\n\n private readTextFilePreview(file: string, maxLines: number): string {\n try {\n const content = readFileSync(file, 'utf-8');\n if (content.includes('\\u0000')) {\n return '[arquivo binário omitido]';\n }\n\n if (!content.length) {\n return '[arquivo vazio]';\n }\n\n const lines = content.split('\\n');\n const preview = lines.slice(0, maxLines).join('\\n');\n const clippedPreview = preview.length > 2500 ? `${preview.slice(0, 2500)}\\n...` : preview;\n\n if (lines.length > maxLines && !clippedPreview.endsWith('\\n...')) {\n return `${clippedPreview}\\n...`;\n }\n\n return clippedPreview;\n } catch {\n return '';\n }\n }\n\n private inferTypeFromFiles(files: string[]): ConventionalCommitType {\n if (files.length === 0) return 'chore';\n\n const onlyDocs = files.every((file) =>\n /^docs\\//i.test(file)\n || /(^|\\/)README\\.md$/i.test(file)\n || /(^|\\/)CHANGELOG\\.md$/i.test(file)\n || /\\.(md|mdx|txt)$/i.test(file),\n );\n if (onlyDocs) return 'docs';\n\n const onlyTests = files.every((file) =>\n /(^|\\/)__tests__\\//.test(file)\n || /\\.(spec|test)\\.[cm]?[jt]sx?$/.test(file),\n );\n if (onlyTests) return 'test';\n\n const onlyInfra = files.every((file) =>\n /(^|\\/)package(-lock)?\\.json$/.test(file)\n || /(^|\\/)(pnpm-lock\\.yaml|yarn\\.lock)$/i.test(file)\n || /(^|\\/)Dockerfile/i.test(file)\n || /(^|\\/)docker-compose\\.ya?ml$/i.test(file)\n || /(^|\\/)\\.github\\/workflows\\//.test(file),\n );\n if (onlyInfra) return 'build';\n\n return 'chore';\n }\n\n private escapeShellArg(value: string): string {\n return `'${value.replace(/'/g, '\\'\\\\\\'\\'')}'`;\n }\n}\n"],"names":["CommitGeneratorService","COMMIT_TYPES","COMMIT_TYPE_SET","Set","COMMIT_TYPE_ALIASES","feature","features","bug","bugfix","documentation","docs","test","tests","testing","performance","optimize","optimization","dependency","dependencies","maintenance","housekeeping","cleanup","remove","LEADING_VERB_TRANSLATIONS","add","adds","update","updates","upgrade","upgrades","fix","fixes","removes","refactor","refactors","improve","improves","create","creates","implement","implements","rename","renames","getDiffInfo","cwd","process","staged","execSync","encoding","unstaged","stagedStats","unstagedStats","statusShort","untrackedRaw","untrackedFiles","trim","split","filter","f","stagedFiles","extractFiles","unstagedFiles","stats","buildStatsSummary","hasChanges","output","length","generateCommitMessage","diffInfo","monorepoInfo","monorepoDetector","detectMonorepo","allFiles","scope","determineScope","llm","multiLlmService","createModel","prompt","buildCommitPrompt","response","invoke","SystemMessage","getCommitSystemPrompt","HumanMessage","message","extractContent","content","normalizeCommitMessage","splitCommits","splitPrompt","buildSplitPrompt","splitResponse","getSplitSystemPrompt","splitContent","commitGroups","parseCommitGroups","normalizedGroups","normalizeCommitGroups","group","files","generateMessageForGroup","push","executeCommit","autoStage","input","executePush","branch","success","error","includes","executeSplitCommits","commits","committedCount","originalHead","commit","file","normalizeFiles","escapeShellArg","committed","refineCommitMessage","currentMessage","userSuggestion","context","buildDiffContext","maxLength","maxCharsPerFile","maxUntrackedFiles","maxUntrackedLines","currentMetadata","extractTypeAndScope","getRefineSystemPrompt","type","breaking","diff","lines","line","startsWith","match","Array","from","isArray","first","String","text","scopeHint","fullDiff","join","scopePart","description","jsonMatch","parsed","JSON","parse","expectedFiles","usedFiles","filesFromGroup","has","normalizeCommitType","inferTypeFromFiles","normalizeDescription","normalizeScope","missingFiles","rawMessage","fallbackType","fallbackScope","fallbackDescription","fallbackBreaking","candidateLine","extractCandidateCommitLine","Boolean","rawDescription","breakingFlag","prefix","maxDescriptionLength","Math","max","truncatedDescription","truncateText","withoutCodeBlock","replace","map","conventionalLine","find","prefixedLine","normalized","toLowerCase","undefined","fallback","translateLeadingVerb","charAt","slice","translated","truncated","trimEnd","lastSpace","lastIndexOf","unique","sections","options","buildFilesSummary","stagedByFile","limitDiffByFile","unstagedByFile","untrackedPreview","buildUntrackedPreview","combined","summarizeFileList","limit","remaining","splitDiffByFile","limitedSections","section","rawSections","maxFiles","maxLines","selectedFiles","preview","readTextFilePreview","readFileSync","clippedPreview","endsWith","onlyDocs","every","onlyTests","onlyInfra","value"],"mappings":"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"}
@@ -31,8 +31,13 @@ let PlanModeService = class PlanModeService {
31
31
  if (this.inPlanMode) {
32
32
  throw new Error('Already in plan mode');
33
33
  }
34
+ if (this.taskService.getExecutionContext()) {
35
+ throw new Error('Cannot enter plan mode while executing an approved plan');
36
+ }
34
37
  this.inPlanMode = true;
35
38
  this.planContext.clear();
39
+ this.planContext.set('title', title);
40
+ this.planContext.set('description', description);
36
41
  console.log('');
37
42
  console.log('━'.repeat(60));
38
43
  this.promptService.info('📋 Entering PLAN MODE');
@@ -48,33 +53,36 @@ let PlanModeService = class PlanModeService {
48
53
  if (!this.inPlanMode) {
49
54
  throw new Error('Not in plan mode');
50
55
  }
51
- console.log('');
52
- console.log(''.repeat(60));
53
- this.promptService.info('📋 Saindo do MODO PLANEJAMENTO - Apresentando Plano');
54
- console.log(''.repeat(60));
55
- console.log('');
56
- const planTitle = this.planContext.get('title') || 'Plano de Execução';
57
- const planDescription = this.planContext.get('description') || '';
58
- const plan = this.taskService.createPlan(planTitle, planDescription, tasks);
59
- this.currentPlan = plan;
60
- const result = await this.taskService.approvePlan(plan.id);
61
- if (result.approved) {
62
- // Configurar contexto de execução
63
- this.taskService.setExecutionContext({
64
- planId: plan.id,
56
+ try {
57
+ console.log('');
58
+ console.log(''.repeat(60));
59
+ this.promptService.info('📋 Saindo do MODO PLANEJAMENTO - Apresentando Plano');
60
+ console.log(''.repeat(60));
61
+ console.log('');
62
+ const planTitle = this.planContext.get('title') || 'Plano de Execução';
63
+ const planDescription = this.planContext.get('description') || '';
64
+ const plan = this.taskService.createPlan(planTitle, planDescription, tasks);
65
+ this.currentPlan = plan;
66
+ const result = await this.taskService.approvePlan(plan.id);
67
+ if (result.approved) {
68
+ // Configurar contexto de execução
69
+ this.taskService.setExecutionContext({
70
+ planId: plan.id,
71
+ autoApprove: result.autoApprove,
72
+ currentTaskIndex: 0,
73
+ startedAt: Date.now()
74
+ });
75
+ // Executar plano usando PlanExecutorService
76
+ await this.planExecutor.executePlan(plan.id, result.autoApprove);
77
+ }
78
+ return {
79
+ approved: result.approved,
65
80
  autoApprove: result.autoApprove,
66
- currentTaskIndex: 0,
67
- startedAt: Date.now()
68
- });
69
- // Executar plano usando PlanExecutorService
70
- await this.planExecutor.executePlan(plan.id, result.autoApprove);
81
+ modification: result.modificationRequested
82
+ };
83
+ } finally{
84
+ this.inPlanMode = false;
71
85
  }
72
- this.inPlanMode = false;
73
- return {
74
- approved: result.approved,
75
- autoApprove: result.autoApprove,
76
- modification: result.modificationRequested
77
- };
78
86
  }
79
87
  isInPlanMode() {
80
88
  return this.inPlanMode;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/tasks/services/plan-mode.service.ts"],"sourcesContent":["import { Injectable, forwardRef, Inject } from '@nestjs/common';\nimport { TaskManagementService } from './task-management.service';\nimport { PlanExecutorService } from './plan-executor.service';\nimport { PromptService } from '../../permissions/services/prompt.service';\nimport { CreateTaskOptions, TaskPlan } from '../types/task.types';\n\n@Injectable()\nexport class PlanModeService {\n private inPlanMode = false;\n private currentPlan: TaskPlan | null = null;\n private planContext: Map<string, any> = new Map();\n\n constructor(\n private taskService: TaskManagementService,\n @Inject(forwardRef(() => PlanExecutorService))\n private planExecutor: PlanExecutorService,\n private promptService: PromptService,\n ) {}\n\n async enterPlanMode(title: string, description: string): Promise<void> {\n if (this.inPlanMode) {\n throw new Error('Already in plan mode');\n }\n\n this.inPlanMode = true;\n this.planContext.clear();\n\n console.log('');\n console.log('━'.repeat(60));\n this.promptService.info('📋 Entering PLAN MODE');\n console.log('━'.repeat(60));\n console.log('');\n console.log(`Planning: ${title}`);\n console.log(description);\n console.log('');\n this.promptService.info('I will ask you some questions and create an execution plan.');\n console.log('');\n }\n\n async exitPlanMode(tasks: CreateTaskOptions[]): Promise<{ approved: boolean; autoApprove: boolean; modification?: string }> {\n if (!this.inPlanMode) {\n throw new Error('Not in plan mode');\n }\n\n console.log('');\n console.log('━'.repeat(60));\n this.promptService.info('📋 Saindo do MODO PLANEJAMENTO - Apresentando Plano');\n console.log('━'.repeat(60));\n console.log('');\n\n const planTitle = this.planContext.get('title') || 'Plano de Execução';\n const planDescription = this.planContext.get('description') || '';\n\n const plan = this.taskService.createPlan(planTitle, planDescription, tasks);\n this.currentPlan = plan;\n\n const result = await this.taskService.approvePlan(plan.id);\n\n if (result.approved) {\n // Configurar contexto de execução\n this.taskService.setExecutionContext({\n planId: plan.id,\n autoApprove: result.autoApprove,\n currentTaskIndex: 0,\n startedAt: Date.now(),\n });\n\n // Executar plano usando PlanExecutorService\n await this.planExecutor.executePlan(plan.id, result.autoApprove);\n }\n\n this.inPlanMode = false;\n\n return {\n approved: result.approved,\n autoApprove: result.autoApprove,\n modification: result.modificationRequested,\n };\n }\n\n isInPlanMode(): boolean {\n return this.inPlanMode;\n }\n\n setPlanContext(key: string, value: any): void {\n this.planContext.set(key, value);\n }\n\n getPlanContext(key: string): any {\n return this.planContext.get(key);\n }\n\n cancelPlanMode(): void {\n if (!this.inPlanMode) return;\n\n this.promptService.warn('Plan mode cancelled');\n this.inPlanMode = false;\n this.currentPlan = null;\n this.planContext.clear();\n }\n\n getCurrentPlan(): TaskPlan | null {\n return this.currentPlan;\n }\n}\n"],"names":["PlanModeService","enterPlanMode","title","description","inPlanMode","Error","planContext","clear","console","log","repeat","promptService","info","exitPlanMode","tasks","planTitle","get","planDescription","plan","taskService","createPlan","currentPlan","result","approvePlan","id","approved","setExecutionContext","planId","autoApprove","currentTaskIndex","startedAt","Date","now","planExecutor","executePlan","modification","modificationRequested","isInPlanMode","setPlanContext","key","value","set","getPlanContext","cancelPlanMode","warn","getCurrentPlan","Map","PlanExecutorService"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/modules/tasks/services/plan-mode.service.ts"],"sourcesContent":["import { Injectable, forwardRef, Inject } from '@nestjs/common';\nimport { TaskManagementService } from './task-management.service';\nimport { PlanExecutorService } from './plan-executor.service';\nimport { PromptService } from '../../permissions/services/prompt.service';\nimport { CreateTaskOptions, TaskPlan } from '../types/task.types';\n\n@Injectable()\nexport class PlanModeService {\n private inPlanMode = false;\n private currentPlan: TaskPlan | null = null;\n private planContext: Map<string, any> = new Map();\n\n constructor(\n private taskService: TaskManagementService,\n @Inject(forwardRef(() => PlanExecutorService))\n private planExecutor: PlanExecutorService,\n private promptService: PromptService,\n ) {}\n\n async enterPlanMode(title: string, description: string): Promise<void> {\n if (this.inPlanMode) {\n throw new Error('Already in plan mode');\n }\n\n if (this.taskService.getExecutionContext()) {\n throw new Error('Cannot enter plan mode while executing an approved plan');\n }\n\n this.inPlanMode = true;\n this.planContext.clear();\n this.planContext.set('title', title);\n this.planContext.set('description', description);\n\n console.log('');\n console.log('━'.repeat(60));\n this.promptService.info('📋 Entering PLAN MODE');\n console.log('━'.repeat(60));\n console.log('');\n console.log(`Planning: ${title}`);\n console.log(description);\n console.log('');\n this.promptService.info('I will ask you some questions and create an execution plan.');\n console.log('');\n }\n\n async exitPlanMode(tasks: CreateTaskOptions[]): Promise<{ approved: boolean; autoApprove: boolean; modification?: string }> {\n if (!this.inPlanMode) {\n throw new Error('Not in plan mode');\n }\n\n try {\n console.log('');\n console.log('━'.repeat(60));\n this.promptService.info('📋 Saindo do MODO PLANEJAMENTO - Apresentando Plano');\n console.log('━'.repeat(60));\n console.log('');\n\n const planTitle = this.planContext.get('title') || 'Plano de Execução';\n const planDescription = this.planContext.get('description') || '';\n\n const plan = this.taskService.createPlan(planTitle, planDescription, tasks);\n this.currentPlan = plan;\n\n const result = await this.taskService.approvePlan(plan.id);\n\n if (result.approved) {\n // Configurar contexto de execução\n this.taskService.setExecutionContext({\n planId: plan.id,\n autoApprove: result.autoApprove,\n currentTaskIndex: 0,\n startedAt: Date.now(),\n });\n\n // Executar plano usando PlanExecutorService\n await this.planExecutor.executePlan(plan.id, result.autoApprove);\n }\n\n return {\n approved: result.approved,\n autoApprove: result.autoApprove,\n modification: result.modificationRequested,\n };\n } finally {\n this.inPlanMode = false;\n }\n }\n\n isInPlanMode(): boolean {\n return this.inPlanMode;\n }\n\n setPlanContext(key: string, value: any): void {\n this.planContext.set(key, value);\n }\n\n getPlanContext(key: string): any {\n return this.planContext.get(key);\n }\n\n cancelPlanMode(): void {\n if (!this.inPlanMode) return;\n\n this.promptService.warn('Plan mode cancelled');\n this.inPlanMode = false;\n this.currentPlan = null;\n this.planContext.clear();\n }\n\n getCurrentPlan(): TaskPlan | null {\n return this.currentPlan;\n }\n}\n"],"names":["PlanModeService","enterPlanMode","title","description","inPlanMode","Error","taskService","getExecutionContext","planContext","clear","set","console","log","repeat","promptService","info","exitPlanMode","tasks","planTitle","get","planDescription","plan","createPlan","currentPlan","result","approvePlan","id","approved","setExecutionContext","planId","autoApprove","currentTaskIndex","startedAt","Date","now","planExecutor","executePlan","modification","modificationRequested","isInPlanMode","setPlanContext","key","value","getPlanContext","cancelPlanMode","warn","getCurrentPlan","Map","PlanExecutorService"],"mappings":"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"}
@@ -221,7 +221,7 @@ let TaskToolsService = class TaskToolsService {
221
221
  createExitPlanModeTool() {
222
222
  return (0, _tools.tool)(async ({ tasks })=>{
223
223
  try {
224
- const approved = await this.planModeService.exitPlanMode(tasks.map((t)=>({
224
+ const approval = await this.planModeService.exitPlanMode(tasks.map((t)=>({
225
225
  subject: t.subject,
226
226
  description: t.description,
227
227
  activeForm: t.activeForm,
@@ -229,8 +229,8 @@ let TaskToolsService = class TaskToolsService {
229
229
  })));
230
230
  return JSON.stringify({
231
231
  success: true,
232
- approved,
233
- message: approved ? 'Plan approved! You can now execute the tasks.' : 'Plan was not approved. Ask the user what they want to change.'
232
+ approved: approval,
233
+ message: approval.approved ? 'Plan approved! You can now execute the tasks.' : 'Plan was not approved. Ask the user what they want to change.'
234
234
  });
235
235
  } catch (error) {
236
236
  return JSON.stringify({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/tasks/services/task-tools.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { tool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { TaskManagementService } from './task-management.service';\nimport { PlanModeService } from './plan-mode.service';\nimport { TaskStatus } from '../types/task.types';\nimport { PromptService } from '../../permissions/services/prompt.service';\n\n@Injectable()\nexport class TaskToolsService {\n constructor(\n private taskService: TaskManagementService,\n private planModeService: PlanModeService,\n private promptService: PromptService,\n ) {}\n\n getTools() {\n return [\n this.createTaskCreateTool(),\n this.createTaskUpdateTool(),\n this.createTaskListTool(),\n this.createTaskGetTool(),\n this.createAskUserQuestionTool(),\n this.createEnterPlanModeTool(),\n this.createExitPlanModeTool(),\n ];\n }\n\n private createTaskCreateTool() {\n return tool(\n async ({ subject, description, activeForm, dependencies, metadata }) => {\n const task = this.taskService.createTask({\n subject,\n description,\n activeForm,\n dependencies: dependencies || [],\n metadata: metadata || {},\n });\n\n return JSON.stringify({\n success: true,\n taskId: task.id,\n task: {\n id: task.id,\n subject: task.subject,\n status: task.status,\n },\n });\n },\n {\n name: 'task_create',\n description:\n 'Create a new task. Use this when breaking down complex work into trackable subtasks. The task will be shown to the user for approval.',\n schema: z.object({\n subject: z.string().describe('Brief task title (e.g., \"Implement login endpoint\")'),\n description: z\n .string()\n .describe('Detailed description of what needs to be done and why'),\n activeForm: z\n .string()\n .optional()\n .describe(\n 'Present continuous form shown when in_progress (e.g., \"Implementing login\")',\n ),\n dependencies: z\n .array(z.string())\n .optional()\n .describe('Array of task IDs that must complete before this one'),\n metadata: z.record(z.any()).optional().describe('Additional metadata'),\n }),\n },\n );\n }\n\n private createTaskUpdateTool() {\n return tool(\n async ({ taskId, status, subject, description, activeForm, addDependencies, metadata }) => {\n const task = this.taskService.updateTask(taskId, {\n status: status as TaskStatus,\n subject,\n description,\n activeForm,\n addDependencies,\n metadata,\n });\n\n if (!task) {\n return JSON.stringify({ success: false, error: 'Task not found' });\n }\n\n return JSON.stringify({\n success: true,\n task: {\n id: task.id,\n subject: task.subject,\n status: task.status,\n },\n });\n },\n {\n name: 'task_update',\n description:\n 'Update an existing task. Use to change status, modify details, or add dependencies.',\n schema: z.object({\n taskId: z.string().describe('ID of the task to update'),\n status: z\n .enum(['pending', 'in_progress', 'completed', 'failed', 'blocked', 'cancelled'])\n .optional()\n .describe('New status for the task'),\n subject: z.string().optional().describe('New subject'),\n description: z.string().optional().describe('New description'),\n activeForm: z.string().optional().describe('New active form'),\n addDependencies: z\n .array(z.string())\n .optional()\n .describe('Task IDs to add as dependencies'),\n metadata: z.record(z.any()).optional().describe('Metadata to merge'),\n }),\n },\n );\n }\n\n private createTaskListTool() {\n return tool(\n async () => {\n const tasks = this.taskService.listTasks();\n const pending = this.taskService.listPendingTasks();\n\n return JSON.stringify({\n total: tasks.length,\n pending: pending.length,\n tasks: tasks.map((t) => ({\n id: t.id,\n subject: t.subject,\n status: t.status,\n dependencies: t.dependencies,\n blocks: t.blocks,\n })),\n });\n },\n {\n name: 'task_list',\n description: 'List all tasks with their current status. Shows which tasks are ready to execute.',\n schema: z.object({}),\n },\n );\n }\n\n private createTaskGetTool() {\n return tool(\n async ({ taskId }) => {\n const task = this.taskService.getTask(taskId);\n\n if (!task) {\n return JSON.stringify({ success: false, error: 'Task not found' });\n }\n\n return JSON.stringify({\n success: true,\n task,\n });\n },\n {\n name: 'task_get',\n description: 'Get full details of a specific task including description and metadata.',\n schema: z.object({\n taskId: z.string().describe('ID of the task to retrieve'),\n }),\n },\n );\n }\n\n private createAskUserQuestionTool() {\n return tool(\n async ({ question, type, choices }) => {\n console.log('');\n\n if (type === 'confirm') {\n const answer = await this.promptService.confirm(question);\n return JSON.stringify({ answer });\n }\n\n if (type === 'choice' && choices) {\n const choiceObjects = choices.map((c, i) => ({\n key: String(i),\n label: c,\n }));\n\n const selectedKey = await this.promptService.choice(question, choiceObjects);\n const selectedIndex = parseInt(selectedKey);\n return JSON.stringify({ answer: choices[selectedIndex] });\n }\n\n if (type === 'text') {\n const answer = await this.promptService.question(question);\n return JSON.stringify({ answer });\n }\n\n return JSON.stringify({ error: 'Invalid question type' });\n },\n {\n name: 'ask_user_question',\n description:\n 'Ask the user a question interactively. Use this when you need clarification, preferences, or decisions from the user before proceeding. This is better than guessing!',\n schema: z.object({\n question: z.string().describe('The question to ask the user'),\n type: z\n .enum(['confirm', 'choice', 'text'])\n .describe('Type of question: confirm (yes/no), choice (multiple options), or text (free form)'),\n choices: z\n .array(z.string())\n .optional()\n .describe('Array of choices for type=choice'),\n }),\n },\n );\n }\n\n private createEnterPlanModeTool() {\n return tool(\n async ({ title, description }) => {\n try {\n await this.planModeService.enterPlanMode(title, description);\n return JSON.stringify({\n success: true,\n message: 'Entered plan mode. Explore the codebase, design your approach, then use exit_plan_mode to present the plan for approval.',\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: (error as Error).message,\n });\n }\n },\n {\n name: 'enter_plan_mode',\n description:\n 'Enter planning mode for complex tasks. In plan mode, you should explore the codebase using read_file, glob, and grep to understand the architecture, then create a detailed plan. Use exit_plan_mode when ready to present the plan for user approval.',\n schema: z.object({\n title: z.string().describe('Title of the plan (e.g., \"Implement user authentication\")'),\n description: z\n .string()\n .describe('Brief description of what will be planned'),\n }),\n },\n );\n }\n\n private createExitPlanModeTool() {\n return tool(\n async ({ tasks }) => {\n try {\n const approved = await this.planModeService.exitPlanMode(\n tasks.map((t) => ({\n subject: t.subject,\n description: t.description,\n activeForm: t.activeForm,\n dependencies: t.dependencies,\n })),\n );\n\n return JSON.stringify({\n success: true,\n approved,\n message: approved\n ? 'Plan approved! You can now execute the tasks.'\n : 'Plan was not approved. Ask the user what they want to change.',\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: (error as Error).message,\n });\n }\n },\n {\n name: 'exit_plan_mode',\n description:\n 'Exit planning mode and present the plan for user approval. The user will see all tasks and can approve, modify, or cancel the plan.',\n schema: z.object({\n tasks: z\n .array(\n z.object({\n subject: z.string().describe('Task title'),\n description: z.string().describe('What this task does'),\n activeForm: z.string().optional().describe('Present continuous form'),\n dependencies: z\n .array(z.string())\n .optional()\n .describe('Task IDs this depends on'),\n }),\n )\n .describe('Array of tasks that make up the plan'),\n }),\n },\n );\n }\n}\n"],"names":["TaskToolsService","getTools","createTaskCreateTool","createTaskUpdateTool","createTaskListTool","createTaskGetTool","createAskUserQuestionTool","createEnterPlanModeTool","createExitPlanModeTool","tool","subject","description","activeForm","dependencies","metadata","task","taskService","createTask","JSON","stringify","success","taskId","id","status","name","schema","z","object","string","describe","optional","array","record","any","addDependencies","updateTask","error","enum","tasks","listTasks","pending","listPendingTasks","total","length","map","t","blocks","getTask","question","type","choices","console","log","answer","promptService","confirm","choiceObjects","c","i","key","String","label","selectedKey","choice","selectedIndex","parseInt","title","planModeService","enterPlanMode","message","approved","exitPlanMode"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/modules/tasks/services/task-tools.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { tool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { TaskManagementService } from './task-management.service';\nimport { PlanModeService } from './plan-mode.service';\nimport { TaskStatus } from '../types/task.types';\nimport { PromptService } from '../../permissions/services/prompt.service';\n\n@Injectable()\nexport class TaskToolsService {\n constructor(\n private taskService: TaskManagementService,\n private planModeService: PlanModeService,\n private promptService: PromptService,\n ) {}\n\n getTools() {\n return [\n this.createTaskCreateTool(),\n this.createTaskUpdateTool(),\n this.createTaskListTool(),\n this.createTaskGetTool(),\n this.createAskUserQuestionTool(),\n this.createEnterPlanModeTool(),\n this.createExitPlanModeTool(),\n ];\n }\n\n private createTaskCreateTool() {\n return tool(\n async ({ subject, description, activeForm, dependencies, metadata }) => {\n const task = this.taskService.createTask({\n subject,\n description,\n activeForm,\n dependencies: dependencies || [],\n metadata: metadata || {},\n });\n\n return JSON.stringify({\n success: true,\n taskId: task.id,\n task: {\n id: task.id,\n subject: task.subject,\n status: task.status,\n },\n });\n },\n {\n name: 'task_create',\n description:\n 'Create a new task. Use this when breaking down complex work into trackable subtasks. The task will be shown to the user for approval.',\n schema: z.object({\n subject: z.string().describe('Brief task title (e.g., \"Implement login endpoint\")'),\n description: z\n .string()\n .describe('Detailed description of what needs to be done and why'),\n activeForm: z\n .string()\n .optional()\n .describe(\n 'Present continuous form shown when in_progress (e.g., \"Implementing login\")',\n ),\n dependencies: z\n .array(z.string())\n .optional()\n .describe('Array of task IDs that must complete before this one'),\n metadata: z.record(z.any()).optional().describe('Additional metadata'),\n }),\n },\n );\n }\n\n private createTaskUpdateTool() {\n return tool(\n async ({ taskId, status, subject, description, activeForm, addDependencies, metadata }) => {\n const task = this.taskService.updateTask(taskId, {\n status: status as TaskStatus,\n subject,\n description,\n activeForm,\n addDependencies,\n metadata,\n });\n\n if (!task) {\n return JSON.stringify({ success: false, error: 'Task not found' });\n }\n\n return JSON.stringify({\n success: true,\n task: {\n id: task.id,\n subject: task.subject,\n status: task.status,\n },\n });\n },\n {\n name: 'task_update',\n description:\n 'Update an existing task. Use to change status, modify details, or add dependencies.',\n schema: z.object({\n taskId: z.string().describe('ID of the task to update'),\n status: z\n .enum(['pending', 'in_progress', 'completed', 'failed', 'blocked', 'cancelled'])\n .optional()\n .describe('New status for the task'),\n subject: z.string().optional().describe('New subject'),\n description: z.string().optional().describe('New description'),\n activeForm: z.string().optional().describe('New active form'),\n addDependencies: z\n .array(z.string())\n .optional()\n .describe('Task IDs to add as dependencies'),\n metadata: z.record(z.any()).optional().describe('Metadata to merge'),\n }),\n },\n );\n }\n\n private createTaskListTool() {\n return tool(\n async () => {\n const tasks = this.taskService.listTasks();\n const pending = this.taskService.listPendingTasks();\n\n return JSON.stringify({\n total: tasks.length,\n pending: pending.length,\n tasks: tasks.map((t) => ({\n id: t.id,\n subject: t.subject,\n status: t.status,\n dependencies: t.dependencies,\n blocks: t.blocks,\n })),\n });\n },\n {\n name: 'task_list',\n description: 'List all tasks with their current status. Shows which tasks are ready to execute.',\n schema: z.object({}),\n },\n );\n }\n\n private createTaskGetTool() {\n return tool(\n async ({ taskId }) => {\n const task = this.taskService.getTask(taskId);\n\n if (!task) {\n return JSON.stringify({ success: false, error: 'Task not found' });\n }\n\n return JSON.stringify({\n success: true,\n task,\n });\n },\n {\n name: 'task_get',\n description: 'Get full details of a specific task including description and metadata.',\n schema: z.object({\n taskId: z.string().describe('ID of the task to retrieve'),\n }),\n },\n );\n }\n\n private createAskUserQuestionTool() {\n return tool(\n async ({ question, type, choices }) => {\n console.log('');\n\n if (type === 'confirm') {\n const answer = await this.promptService.confirm(question);\n return JSON.stringify({ answer });\n }\n\n if (type === 'choice' && choices) {\n const choiceObjects = choices.map((c, i) => ({\n key: String(i),\n label: c,\n }));\n\n const selectedKey = await this.promptService.choice(question, choiceObjects);\n const selectedIndex = parseInt(selectedKey);\n return JSON.stringify({ answer: choices[selectedIndex] });\n }\n\n if (type === 'text') {\n const answer = await this.promptService.question(question);\n return JSON.stringify({ answer });\n }\n\n return JSON.stringify({ error: 'Invalid question type' });\n },\n {\n name: 'ask_user_question',\n description:\n 'Ask the user a question interactively. Use this when you need clarification, preferences, or decisions from the user before proceeding. This is better than guessing!',\n schema: z.object({\n question: z.string().describe('The question to ask the user'),\n type: z\n .enum(['confirm', 'choice', 'text'])\n .describe('Type of question: confirm (yes/no), choice (multiple options), or text (free form)'),\n choices: z\n .array(z.string())\n .optional()\n .describe('Array of choices for type=choice'),\n }),\n },\n );\n }\n\n private createEnterPlanModeTool() {\n return tool(\n async ({ title, description }) => {\n try {\n await this.planModeService.enterPlanMode(title, description);\n return JSON.stringify({\n success: true,\n message: 'Entered plan mode. Explore the codebase, design your approach, then use exit_plan_mode to present the plan for approval.',\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: (error as Error).message,\n });\n }\n },\n {\n name: 'enter_plan_mode',\n description:\n 'Enter planning mode for complex tasks. In plan mode, you should explore the codebase using read_file, glob, and grep to understand the architecture, then create a detailed plan. Use exit_plan_mode when ready to present the plan for user approval.',\n schema: z.object({\n title: z.string().describe('Title of the plan (e.g., \"Implement user authentication\")'),\n description: z\n .string()\n .describe('Brief description of what will be planned'),\n }),\n },\n );\n }\n\n private createExitPlanModeTool() {\n return tool(\n async ({ tasks }) => {\n try {\n const approval = await this.planModeService.exitPlanMode(\n tasks.map((t) => ({\n subject: t.subject,\n description: t.description,\n activeForm: t.activeForm,\n dependencies: t.dependencies,\n })),\n );\n\n return JSON.stringify({\n success: true,\n approved: approval,\n message: approval.approved\n ? 'Plan approved! You can now execute the tasks.'\n : 'Plan was not approved. Ask the user what they want to change.',\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: (error as Error).message,\n });\n }\n },\n {\n name: 'exit_plan_mode',\n description:\n 'Exit planning mode and present the plan for user approval. The user will see all tasks and can approve, modify, or cancel the plan.',\n schema: z.object({\n tasks: z\n .array(\n z.object({\n subject: z.string().describe('Task title'),\n description: z.string().describe('What this task does'),\n activeForm: z.string().optional().describe('Present continuous form'),\n dependencies: z\n .array(z.string())\n .optional()\n .describe('Task IDs this depends on'),\n }),\n )\n .describe('Array of tasks that make up the plan'),\n }),\n },\n );\n }\n}\n"],"names":["TaskToolsService","getTools","createTaskCreateTool","createTaskUpdateTool","createTaskListTool","createTaskGetTool","createAskUserQuestionTool","createEnterPlanModeTool","createExitPlanModeTool","tool","subject","description","activeForm","dependencies","metadata","task","taskService","createTask","JSON","stringify","success","taskId","id","status","name","schema","z","object","string","describe","optional","array","record","any","addDependencies","updateTask","error","enum","tasks","listTasks","pending","listPendingTasks","total","length","map","t","blocks","getTask","question","type","choices","console","log","answer","promptService","confirm","choiceObjects","c","i","key","String","label","selectedKey","choice","selectedIndex","parseInt","title","planModeService","enterPlanMode","message","approval","exitPlanMode","approved"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cast-code",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Multi-agent CLI system powered by DeepAgents",
5
5
  "main": "dist/main.js",
6
6
  "bin": {