{"version":3,"sources":["/home/mkabumattar/withrawi/rawi/dist/chunk-65B2KITR.cjs","../src/cli/commands/ask.command.ts"],"names":["readStdin","resolve","data","chunk","createAskCommand","askCommand","Command","chalk","DEFAULT_PROFILE","query","options","dbManager","stdinContent","fileContent","forceFileType","fileTypeKey","SupportedFileType"],"mappings":"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","file":"/home/mkabumattar/withrawi/rawi/dist/chunk-65B2KITR.cjs","sourcesContent":[null,"import chalk from 'chalk';\nimport {Command} from 'commander';\nimport {getCredentials, isConfigured} from '../../core/configs/utils.js';\nimport {DatabaseManager} from '../../core/database/manager.js';\nimport {SupportedFileType} from '../../core/file-readers/interfaces/types.js';\nimport {FileReaderManager} from '../../core/file-readers/managers/file-reader.manager.js';\nimport {processQuery} from '../../core/providers/utils.js';\nimport {DEFAULT_PROFILE} from '../../core/shared/constants.js';\nimport {spinnerManager} from '../../core/shared/spinner.js';\nimport {applyActTemplate} from '../../core/templates/utils.js';\n\nconst readStdin = (): Promise<string> => {\n  return new Promise((resolve) => {\n    let data = '';\n\n    if (process.stdin.isTTY) {\n      resolve('');\n      return;\n    }\n\n    process.stdin.setEncoding('utf8');\n\n    process.stdin.on('data', (chunk) => {\n      data += chunk;\n    });\n\n    process.stdin.on('end', () => {\n      resolve(data.trim());\n    });\n  });\n};\n\nexport const createAskCommand = (): Command => {\n  const askCommand = new Command('ask');\n\n  askCommand\n    .description(\n      [\n        chalk.bold('Ask AI a question and get a response.'),\n        '',\n        chalk.gray('Supports piped input from stdin and file processing.'),\n        chalk.gray('Use --act <template> for expert prompt templates.'),\n        chalk.gray('See all templates with \"rawi act --list\".'),\n      ].join('\\n'),\n    )\n    .argument(\n      '[query]',\n      chalk.white(\n        'The question or prompt to send to the AI (can be combined with piped input or file content)',\n      ),\n    )\n    .option(\n      '-p, --profile <profile>',\n      chalk.white('Profile to use for AI configuration'),\n      DEFAULT_PROFILE,\n    )\n    .option(\n      '-s, --session <sessionId>',\n      chalk.white('Continue an existing chat session'),\n    )\n    .option('-n, --new-session', chalk.white('Start a new chat session'))\n    .option(\n      '--act <template>',\n      chalk.white('Use an act template (e.g., ethereum-developer)'),\n    )\n    .option(\n      '-f, --file <path>',\n      chalk.white(\n        'Process content from a file (PDF, DOCX, PPTX, XLSX, ODT, ODP, ODS, TXT, etc.)',\n      ),\n    )\n    .option(\n      '-F, --files <paths...>',\n      chalk.white('Process content from multiple files'),\n    )\n    .option(\n      '-b, --batch <patterns...>',\n      chalk.white(\n        'Process files matching glob patterns (e.g., \"src/**/*.js\" \"docs/*.md\")',\n      ),\n    )\n    .option(\n      '--parallel',\n      chalk.white('Process multiple files in parallel (faster for many files)'),\n    )\n    .option(\n      '--max-concurrency <number>',\n      chalk.white(\n        'Maximum number of files to process concurrently (default: 5)',\n      ),\n      '5',\n    )\n    .option(\n      '--continue-on-error',\n      chalk.white('Continue processing other files if one fails'),\n    )\n    .option(\n      '--file-type <type>',\n      chalk.white(\n        'Override automatic file type detection (pdf, docx, pptx, xlsx, odt, odp, ods, txt, etc.)',\n      ),\n    )\n    .option(\n      '--verbose',\n      chalk.white('Show detailed status and debug information'),\n    )\n    .addHelpText(\n      'after',\n      [\n        chalk.bold.cyan('\\nExamples:'),\n        chalk.gray(\n          '  rawi ask \"What is this document about?\" --file report.pdf',\n        ),\n        chalk.gray('  rawi ask \"Analyze this data\" --file data.xlsx'),\n        chalk.gray('  rawi ask \"Review this code\" --file src/app.js'),\n        chalk.gray(\n          '  rawi ask \"Summarize\" --file document.docx --act technical-writer',\n        ),\n        chalk.gray(\n          '  echo \"Additional context\" | rawi ask \"Analyze\" --file data.json',\n        ),\n        '',\n        chalk.bold.cyan('Batch Processing:'),\n        chalk.gray(\n          '  rawi ask \"Review these files\" --files file1.js file2.py file3.md',\n        ),\n        chalk.gray(\n          '  rawi ask \"Analyze source code\" --batch \"src/**/*.{js,ts}\"',\n        ),\n        chalk.gray(\n          '  rawi ask \"Review docs\" --batch \"docs/**/*.md\" --parallel',\n        ),\n        chalk.gray(\n          '  rawi ask \"Check configs\" --batch \"**/*.{json,yml,yaml}\" --continue-on-error',\n        ),\n        '',\n        chalk.bold.cyan('See also:'),\n        chalk.gray('  rawi act --list'),\n        chalk.gray('  rawi provider --list'),\n        chalk.gray('  rawi configure --show'),\n        chalk.gray('  rawi ask --help'),\n      ].join('\\n'),\n    )\n    .action(async (query: string, options: any) => {\n      let dbManager: DatabaseManager | null = null;\n\n      try {\n        const stdinContent = await readStdin();\n        let fileContent = '';\n\n        if (options.file || options.files || options.batch) {\n          if (options.verbose) {\n            console.log(chalk.dim('📄 Processing files...'));\n          }\n\n          try {\n            let forceFileType: SupportedFileType | undefined;\n            if (options.fileType) {\n              const fileTypeKey = options.fileType.toUpperCase();\n              if (fileTypeKey in SupportedFileType) {\n                forceFileType =\n                  SupportedFileType[\n                    fileTypeKey as keyof typeof SupportedFileType\n                  ];\n              } else {\n                console.error(\n                  chalk.red(`❌ Unsupported file type: ${options.fileType}`),\n                );\n                console.log(\n                  chalk.yellow(\n                    'Supported types: pdf, docx, pptx, xlsx, odt, odp, ods, txt, js, jsx, ts, tsx, py, java, cpp, c, go, rs, rb, kt, swift, dart, scala, php, json, md, yml, yaml, xml, html, css, sql, sh, bash, env, ini, conf, toml, log, and more',\n                  ),\n                );\n                process.exit(1);\n              }\n            }\n\n            const fileReaderManager = new FileReaderManager({\n              verbose: options.verbose,\n              forceFileType,\n            });\n\n            let result: any;\n            let totalFiles = 0;\n\n            if (options.file) {\n              result = await fileReaderManager.readFile(options.file);\n              if (result.success && result.content) {\n                fileContent = result.content.text;\n                totalFiles = 1;\n              } else {\n                console.error(\n                  chalk.red(`❌ Failed to process file: ${result.error}`),\n                );\n                process.exit(1);\n              }\n            } else {\n              const maxConcurrency =\n                Number.parseInt(options.maxConcurrency) || 5;\n              const batchOptions = {\n                parallel: options.parallel,\n                maxConcurrency,\n                continueOnError: options.continueOnError,\n                fileType: options.fileType,\n                onProgress: options.verbose\n                  ? (processed: number, total: number, currentFile: string) => {\n                      console.log(\n                        chalk.dim(\n                          `📝 [${processed}/${total}] Processing: ${currentFile}`,\n                        ),\n                      );\n                    }\n                  : undefined,\n              };\n\n              let summary: any;\n              if (options.files) {\n                summary = await fileReaderManager.processMultipleFiles(\n                  options.files,\n                  batchOptions,\n                );\n              } else if (options.batch) {\n                summary = await fileReaderManager.processGlobPatterns(\n                  options.batch,\n                  batchOptions,\n                );\n              }\n\n              if (summary) {\n                const contentParts: string[] = [];\n                let successCount = 0;\n\n                for (const fileResult of summary.results) {\n                  if (fileResult.result.success && fileResult.result.content) {\n                    contentParts.push(\n                      `=== ${fileResult.filePath} ===\\n${fileResult.result.content.text}\\n`,\n                    );\n                    successCount++;\n                  }\n                }\n\n                fileContent = contentParts.join('\\n');\n                totalFiles = summary.totalFiles;\n\n                if (options.verbose) {\n                  console.log(\n                    chalk.dim(\n                      `✅ Successfully processed ${successCount}/${summary.totalFiles} files`,\n                    ),\n                  );\n                  console.log(\n                    chalk.dim(\n                      `⏱️  Total time: ${(summary.totalProcessingTime / 1000).toFixed(2)}s`,\n                    ),\n                  );\n                  console.log(\n                    chalk.dim(\n                      `📊 Total content length: ${fileContent.length} characters`,\n                    ),\n                  );\n\n                  if (summary.failedFiles > 0) {\n                    console.log(\n                      chalk.yellow(\n                        `⚠️  ${summary.failedFiles} files failed to process:`,\n                      ),\n                    );\n                    for (const error of summary.errors) {\n                      console.log(\n                        chalk.yellow(`   • ${error.filePath}: ${error.error}`),\n                      );\n                    }\n                  }\n                }\n\n                if (successCount === 0) {\n                  console.error(\n                    chalk.red('❌ No files were processed successfully'),\n                  );\n                  process.exit(1);\n                }\n              }\n            }\n\n            if (options.verbose && totalFiles === 1) {\n              console.log(chalk.dim('✅ Successfully processed file'));\n              console.log(\n                chalk.dim(\n                  `📊 Content length: ${fileContent.length} characters`,\n                ),\n              );\n            }\n          } catch (error) {\n            const errorMessage =\n              error instanceof Error ? error.message : 'Unknown error occurred';\n            console.error(\n              chalk.red(`❌ Error processing file: ${errorMessage}`),\n            );\n            process.exit(1);\n          }\n        }\n\n        let finalQuery: string;\n        const contentParts = [query, stdinContent, fileContent].filter(Boolean);\n\n        if (contentParts.length === 0) {\n          askCommand.help();\n          return;\n        }\n\n        finalQuery = contentParts.join('\\n\\n');\n\n        if (options.act) {\n          try {\n            finalQuery = applyActTemplate(options.act, finalQuery);\n            if (options.verbose) {\n              console.log(chalk.dim(`🎭 Using act template: ${options.act}`));\n            }\n          } catch (error) {\n            const errorMessage =\n              error instanceof Error ? error.message : 'Unknown error occurred';\n            if (options.verbose) {\n              console.error(chalk.red(`❌ ${errorMessage}`));\n              console.log(\n                chalk.yellow(\n                  '💡 Use \"rawi act --list\" to see available templates.',\n                ),\n              );\n            }\n            return;\n          }\n        }\n\n        const profile = options.profile || DEFAULT_PROFILE;\n\n        if (!isConfigured(profile)) {\n          if (options.verbose) {\n            console.error(\n              chalk.red(\n                `❌ Profile '${profile}' does not exist or is not properly configured.`,\n              ),\n            );\n            console.error(\n              chalk.yellow(\n                `Run 'rawi configure -p ${profile}' to set up this profile.`,\n              ),\n            );\n          }\n          process.exit(1);\n        }\n\n        dbManager = new DatabaseManager();\n\n        let sessionId: string;\n        if (options.newSession) {\n          sessionId = await dbManager.createSession(profile);\n          if (options.verbose) {\n            console.log(chalk.dim(`🆕 Started new session: ${sessionId}`));\n          }\n        } else if (options.session) {\n          sessionId = options.session;\n          const session = await dbManager.getSession(sessionId);\n          if (!session) {\n            if (options.verbose) {\n              console.error(chalk.red(`❌ Session '${sessionId}' not found.`));\n            }\n            process.exit(1);\n          }\n          if (session.profile !== profile) {\n            if (options.verbose) {\n              console.error(\n                chalk.red(\n                  `❌ Session '${sessionId}' belongs to profile '${session.profile}', not '${profile}'.`,\n                ),\n              );\n            }\n            process.exit(1);\n          }\n          if (options.verbose) {\n            console.log(chalk.dim(`🔄 Continuing session: ${sessionId}`));\n          }\n        } else {\n          sessionId = await dbManager.getCurrentSession(profile);\n          if (options.verbose) {\n            console.log(chalk.dim(`📝 Using current session: ${sessionId}`));\n          }\n        }\n\n        if (options.verbose) {\n          console.log(`Using profile: ${profile}`);\n          console.log(\n            `Processing query: ${finalQuery.length > 100 ? `${finalQuery.substring(0, 100)}...` : finalQuery}`,\n          );\n        }\n\n        if (options.verbose) {\n          spinnerManager.start('validation', 'Validating configuration...');\n        }\n\n        const credentials = getCredentials(profile);\n\n        if (!credentials) {\n          if (options.verbose) {\n            spinnerManager.fail(\n              'validation',\n              'Configuration validation failed',\n            );\n            console.error(\n              chalk.red(\n                `❌ Unable to load credentials for profile '${profile}'.`,\n              ),\n            );\n          }\n          process.exit(1);\n        }\n\n        if (options.verbose) {\n          spinnerManager.succeed(\n            'validation',\n            'Configuration validated successfully',\n          );\n        }\n\n        await dbManager.addMessage(\n          sessionId,\n          'user',\n          finalQuery,\n          credentials.provider,\n          credentials.model,\n          credentials.temperature,\n          credentials.maxTokens,\n        );\n\n        if (options.verbose) {\n          spinnerManager.start(\n            'generation',\n            `Streaming response using ${credentials.provider} (${credentials.model})...`,\n            {color: 'cyan'},\n          );\n        }\n\n        console.log(`${chalk.cyan('Result:')}`);\n\n        let response: string;\n        let hasStartedStreaming = false;\n\n        try {\n          response = await processQuery(credentials, finalQuery, {\n            streaming: true,\n            onChunk: (chunk: string) => {\n              if (!hasStartedStreaming) {\n                if (options.verbose) {\n                  spinnerManager.succeed(\n                    'generation',\n                    'Starting to stream response...',\n                  );\n                }\n                hasStartedStreaming = true;\n              }\n              process.stdout.write(chunk);\n            },\n            onComplete: () => {\n              console.log();\n              if (options.verbose) {\n                console.log(chalk.dim('✅ Streaming completed'));\n              }\n            },\n            onError: (error: Error) => {\n              if (options.verbose) {\n                spinnerManager.fail(\n                  'generation',\n                  'Failed to generate response',\n                );\n                console.error(chalk.red(`❌ ${error.message}`));\n              }\n            },\n          });\n\n          await dbManager.addMessage(\n            sessionId,\n            'assistant',\n            response,\n            credentials.provider,\n            credentials.model,\n            credentials.temperature,\n            credentials.maxTokens,\n          );\n\n          if (options.verbose) {\n            spinnerManager.succeed(\n              'generation',\n              'Response streamed successfully!',\n            );\n          }\n        } catch (error) {\n          if (options.verbose) {\n            spinnerManager.fail('generation', 'Failed to generate response');\n            console.error(\n              chalk.red(\n                `❌ ${error instanceof Error ? error.message : String(error)}`,\n              ),\n            );\n          }\n          response = `Unable to generate response using ${credentials.provider} (${credentials.model}). Error: ${error instanceof Error ? error.message : String(error)}`;\n\n          await dbManager.addMessage(\n            sessionId,\n            'assistant',\n            response,\n            credentials.provider,\n            credentials.model,\n            credentials.temperature,\n            credentials.maxTokens,\n            {error: true},\n          );\n        }\n\n        if (options.verbose) {\n          const session = await dbManager.getSession(sessionId);\n          if (session) {\n            console.log(\n              chalk.dim(\n                `\\n💬 Session: ${sessionId} (${session.messageCount} messages)`,\n              ),\n            );\n          }\n        }\n      } catch (error) {\n        if (options.verbose) {\n          console.error('Error processing query:', error);\n        }\n        process.exit(1);\n      } finally {\n        if (dbManager) {\n          dbManager.close();\n        }\n      }\n    });\n\n  return askCommand;\n};\n"]}