@lenadweb/aicmt 0.1.1
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 +21 -0
- package/README.md +123 -0
- package/dist/bin/aicmt.js +870 -0
- package/dist/bin/aicmt.js.map +1 -0
- package/dist/cli.js +876 -0
- package/dist/cli.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli.ts","../../src/commands/commit.ts","../../src/config.ts","../../src/constants.ts","../../src/git.ts","../../src/utils.ts","../../src/openrouter.ts","../../src/commands/init.ts","../../src/bin/aicmt.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { runCommit } from './commands/commit';\nimport { runInit } from './commands/init';\n\nexport async function run(argv: string[] = process.argv): Promise<void> {\n const program = new Command();\n\n program\n .name('aicmt')\n .description('AI-assisted git commits via OpenRouter')\n .version('0.1.0');\n\n program\n .command('init')\n .description('Initialize aicmt in this repository')\n .option('-c, --config <path>', 'Path to global config file')\n .action(async (options: { config?: string }) => {\n await runInit({ cwd: process.cwd(), configPath: options.config });\n });\n\n program\n .command('commit', { isDefault: true })\n .description('Generate and create a commit for staged changes')\n .option('-c, --config <path>', 'Path to global config file')\n .option('--dry-run', 'Show the chosen message without committing', false)\n .option('-v, --verbose', 'Show AI request and response logs', false)\n .option('-y, --yes', 'Skip prompts: stage all, pick first message', false)\n .action(\n async (options: {\n config?: string;\n dryRun?: boolean;\n verbose?: boolean;\n yes?: boolean;\n }) => {\n await runCommit({\n cwd: process.cwd(),\n configPath: options.config,\n dryRun: Boolean(options.dryRun),\n verbose: Boolean(options.verbose),\n yes: Boolean(options.yes),\n });\n },\n );\n\n await program.parseAsync(argv);\n}\n","import prompts from 'prompts';\nimport { loadGlobalConfig, resolveConfigPath, resolveProjectConfig } from '../config';\nimport {\n commitWithMessage,\n getRepoRoot,\n getStagedDiff,\n getStatus,\n isGitRepo,\n stageAll,\n} from '../git';\nimport { generateCommitMessages, OpenRouterDebugInfo } from '../openrouter';\n\nconst promptOptions = {\n onCancel: () => {\n throw new Error('Cancelled');\n },\n};\n\nexport interface CommitOptions {\n cwd: string;\n configPath?: string;\n dryRun?: boolean;\n verbose?: boolean;\n yes?: boolean;\n}\n\nexport async function runCommit({\n cwd,\n configPath,\n dryRun = false,\n verbose = false,\n yes = false,\n}: CommitOptions): Promise<void> {\n const isRepo = await isGitRepo(cwd);\n if (!isRepo) {\n throw new Error('Not a git repository. Run inside a git project.');\n }\n\n const repoRoot = await getRepoRoot(cwd);\n const resolvedConfigPath = resolveConfigPath(repoRoot, configPath);\n const globalConfig = await loadGlobalConfig(resolvedConfigPath);\n const config = resolveProjectConfig(globalConfig, repoRoot);\n\n let status = await getStatus(repoRoot);\n if (status.staged.length === 0 && status.unstaged.length === 0) {\n throw new Error('No changes to commit.');\n }\n\n if (status.unstaged.length > 0) {\n if (yes) {\n await stageAll(repoRoot);\n } else {\n const { stage } = await prompts(\n {\n type: 'confirm',\n name: 'stage',\n message: 'Unstaged changes detected. Stage all changes?',\n initial: true,\n },\n promptOptions,\n );\n\n if (!stage) {\n throw new Error('Aborted: commit requires all changes to be staged.');\n }\n\n await stageAll(repoRoot);\n }\n status = await getStatus(repoRoot);\n }\n\n if (status.staged.length === 0) {\n throw new Error('No staged changes to commit.');\n }\n\n const diff = await getStagedDiff(repoRoot);\n\n const debugInfo: {\n request?: OpenRouterDebugInfo;\n response?: OpenRouterDebugInfo;\n } = {};\n\n const messages = await generateCommitMessages({\n apiKey: config.openrouterApiKey,\n model: config.model,\n instructions: config.instructions,\n diff,\n temperature: config.temperature,\n maxTokens: config.maxTokens,\n onDebug: (info) => {\n if (info.stage === 'request') {\n debugInfo.request = info;\n } else {\n debugInfo.response = info;\n }\n },\n });\n\n if (verbose) {\n if (debugInfo.request) {\n console.log('[aicmt] AI request payload:');\n console.log(JSON.stringify(debugInfo.request.payload, null, 2));\n console.log('[aicmt] AI request prompt:');\n console.log(debugInfo.request.prompt);\n }\n\n if (debugInfo.response) {\n const status = debugInfo.response.status ?? 'unknown';\n console.log(`[aicmt] AI response (status ${status}):`);\n console.log(debugInfo.response.responseText ?? '');\n }\n }\n\n let finalMessage = messages[0] ?? '';\n\n if (!yes) {\n const choicePrompt = await prompts(\n {\n type: 'select',\n name: 'selection',\n message: 'Choose a commit message',\n choices: [\n ...messages.map((message, index) => ({\n title: message,\n value: message,\n description: `Option ${index + 1}`,\n })),\n { title: 'Custom message', value: '__custom', description: 'Write your own' },\n { title: 'Abort', value: '__abort', description: 'Cancel commit' },\n ],\n },\n promptOptions,\n );\n\n if (!choicePrompt.selection || choicePrompt.selection === '__abort') {\n console.log('Commit cancelled.');\n return;\n }\n\n finalMessage = String(choicePrompt.selection);\n\n if (choicePrompt.selection === '__custom') {\n const { customMessage } = await prompts(\n {\n type: 'text',\n name: 'customMessage',\n message: 'Enter commit message',\n validate: (value: string) =>\n value.trim().length > 0 ? true : 'Commit message is required.',\n },\n promptOptions,\n );\n\n finalMessage = String(customMessage || '').trim();\n }\n }\n\n if (!finalMessage) {\n throw new Error('Commit message is empty.');\n }\n\n if (!yes) {\n const { confirm } = await prompts(\n {\n type: 'confirm',\n name: 'confirm',\n message: `Commit with message:\\n${finalMessage}\\nProceed?`,\n initial: true,\n },\n promptOptions,\n );\n\n if (!confirm) {\n console.log('Commit cancelled.');\n return;\n }\n }\n\n if (dryRun) {\n console.log(`[dry-run] ${finalMessage}`);\n return;\n }\n\n await commitWithMessage(repoRoot, finalMessage);\n console.log(`Commit created: ${finalMessage}`);\n}\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { z } from 'zod';\nimport {\n CONFIG_DIR_NAME,\n CONFIG_FILENAME,\n DEFAULT_MAX_TOKENS,\n DEFAULT_TEMPERATURE,\n MAX_OUTPUT_TOKENS,\n MIN_OUTPUT_TOKENS,\n} from './constants';\n\nconst sharedConfigSchema = z\n .object({\n openrouterApiKey: z.string().min(1).optional(),\n model: z.string().min(1).optional(),\n format: z.string().min(1).optional(),\n instructions: z.string().min(1).optional(),\n temperature: z.number().min(0).max(2).optional(),\n maxTokens: z.number().int().positive().optional(),\n })\n .strict();\n\nconst projectConfigSchema = sharedConfigSchema;\n\nexport const globalConfigSchema = sharedConfigSchema\n .extend({\n projects: z.record(projectConfigSchema).default({}),\n })\n .strict();\n\nexport type ProjectConfig = z.infer<typeof projectConfigSchema>;\nexport type GlobalConfig = z.infer<typeof globalConfigSchema>;\nexport type GlobalDefaults = Omit<GlobalConfig, 'projects'>;\n\nexport interface ResolvedConfig {\n openrouterApiKey: string;\n model: string;\n format: string;\n instructions: string;\n temperature: number;\n maxTokens: number;\n}\n\nexport interface LoadConfigOptions {\n allowMissing?: boolean;\n}\n\nexport function getDefaultConfigPath(): string {\n const base = process.env.XDG_CONFIG_HOME?.trim();\n const configDir = base\n ? path.join(base, CONFIG_DIR_NAME)\n : path.join(os.homedir(), '.config', CONFIG_DIR_NAME);\n return path.join(configDir, CONFIG_FILENAME);\n}\n\nexport function resolveConfigPath(repoRoot: string, providedPath?: string): string {\n if (providedPath) {\n return path.isAbsolute(providedPath)\n ? providedPath\n : path.resolve(repoRoot, providedPath);\n }\n\n return getDefaultConfigPath();\n}\n\nfunction clampMaxTokens(value: number): number {\n if (value < MIN_OUTPUT_TOKENS) {\n return MIN_OUTPUT_TOKENS;\n }\n\n if (value > MAX_OUTPUT_TOKENS) {\n return MAX_OUTPUT_TOKENS;\n }\n\n return value;\n}\n\nfunction applyDefaults(config: {\n openrouterApiKey: string;\n model: string;\n format: string;\n instructions: string;\n temperature?: number;\n maxTokens?: number;\n}): ResolvedConfig {\n return {\n openrouterApiKey: config.openrouterApiKey,\n model: config.model,\n format: config.format,\n instructions: config.instructions,\n temperature:\n typeof config.temperature === 'number'\n ? config.temperature\n : DEFAULT_TEMPERATURE,\n maxTokens:\n typeof config.maxTokens === 'number'\n ? clampMaxTokens(config.maxTokens)\n : DEFAULT_MAX_TOKENS,\n };\n}\n\nexport function resolveProjectConfig(\n globalConfig: GlobalConfig,\n repoRoot: string,\n): ResolvedConfig {\n const { projects = {}, ...defaults } = globalConfig;\n const projectConfig = projects[repoRoot] ?? {};\n const merged = { ...defaults, ...projectConfig };\n\n const missing: string[] = [];\n if (!merged.openrouterApiKey) {\n missing.push('openrouterApiKey');\n }\n if (!merged.model) {\n missing.push('model');\n }\n if (!merged.format) {\n missing.push('format');\n }\n if (!merged.instructions) {\n missing.push('instructions');\n }\n\n if (missing.length > 0) {\n throw new Error(\n `Missing ${missing.join(', ')} in config. Run aicmt init to set defaults.`,\n );\n }\n\n return applyDefaults({\n openrouterApiKey: merged.openrouterApiKey,\n model: merged.model,\n format: merged.format,\n instructions: merged.instructions,\n temperature: merged.temperature,\n maxTokens: merged.maxTokens,\n });\n}\n\nexport async function loadGlobalConfig(\n configPath: string,\n options: LoadConfigOptions = {},\n): Promise<GlobalConfig> {\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf8');\n } catch (error) {\n if (options.allowMissing) {\n return globalConfigSchema.parse({});\n }\n throw new Error(`Global config not found at ${configPath}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new Error(`Invalid JSON in config: ${configPath}`);\n }\n\n const result = globalConfigSchema.safeParse(parsed);\n if (!result.success) {\n const message = result.error.issues\n .map((issue) => issue.message)\n .join('; ');\n throw new Error(`Invalid config: ${message}`);\n }\n\n return result.data;\n}\n\nexport async function saveGlobalConfig(\n configPath: string,\n config: GlobalConfig,\n): Promise<void> {\n const result = globalConfigSchema.safeParse(config);\n if (!result.success) {\n const message = result.error.issues\n .map((issue) => issue.message)\n .join('; ');\n throw new Error(`Refusing to write invalid config: ${message}`);\n }\n\n await fs.mkdir(path.dirname(configPath), { recursive: true });\n const json = `${JSON.stringify(result.data, null, 2)}\\n`;\n await fs.writeFile(configPath, json, 'utf8');\n}\n","export const CONFIG_DIR_NAME = 'aicmt';\nexport const CONFIG_FILENAME = 'config.json';\nexport const DEFAULT_MODEL = 'openai/gpt-4o-mini';\nexport const DEFAULT_TEMPERATURE = 0.2;\nexport const DEFAULT_MAX_TOKENS = 120;\nexport const MIN_OUTPUT_TOKENS = 32;\nexport const MAX_OUTPUT_TOKENS = 512;\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { runCommand } from './utils';\n\nexport interface GitStatus {\n staged: string[];\n unstaged: string[];\n}\n\nasync function runGit(args: string[], cwd: string): Promise<{ stdout: string; stderr: string }> {\n try {\n return await runCommand('git', args, { cwd });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Git command failed';\n const stderr = (error as { stderr?: string } | undefined)?.stderr ?? '';\n const detail = stderr.trim() || message;\n throw new Error(detail);\n }\n}\n\nexport async function getRepoRoot(cwd: string): Promise<string> {\n const result = await runGit(['rev-parse', '--show-toplevel'], cwd);\n return result.stdout.trim();\n}\n\nexport async function isGitRepo(cwd: string): Promise<boolean> {\n try {\n const result = await runGit(['rev-parse', '--is-inside-work-tree'], cwd);\n return result.stdout.trim() === 'true';\n } catch (error) {\n return false;\n }\n}\n\nfunction extractPath(rawPath: string): string {\n const trimmed = rawPath.trim();\n const arrowIndex = trimmed.indexOf('->');\n if (arrowIndex === -1) {\n return trimmed;\n }\n\n return trimmed.slice(arrowIndex + 2).trim();\n}\n\nfunction parseStatus(output: string): GitStatus {\n const staged = new Set<string>();\n const unstaged = new Set<string>();\n\n output\n .split('\\n')\n .map((line) => line.trimEnd())\n .filter(Boolean)\n .forEach((line) => {\n if (line.startsWith('??')) {\n const filePath = extractPath(line.slice(2));\n unstaged.add(filePath);\n return;\n }\n\n const indexStatus = line[0];\n const worktreeStatus = line[1];\n const filePath = extractPath(line.slice(2));\n\n if (indexStatus && indexStatus !== ' ') {\n staged.add(filePath);\n }\n\n if (worktreeStatus && worktreeStatus !== ' ') {\n unstaged.add(filePath);\n }\n });\n\n return {\n staged: Array.from(staged),\n unstaged: Array.from(unstaged),\n };\n}\n\nexport async function getStatus(repoRoot: string): Promise<GitStatus> {\n const result = await runGit(['status', '--porcelain=v1'], repoRoot);\n return parseStatus(result.stdout);\n}\n\nexport async function stageAll(repoRoot: string): Promise<void> {\n await runGit(['add', '-A'], repoRoot);\n}\n\nexport async function getStagedDiff(repoRoot: string): Promise<string> {\n const result = await runGit(['diff', '--cached'], repoRoot);\n return result.stdout;\n}\n\nexport async function commitWithMessage(repoRoot: string, message: string): Promise<void> {\n if (!message.includes('\\n')) {\n await runGit(['commit', '-m', message], repoRoot);\n return;\n }\n\n const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aicmt-'));\n const tempPath = path.join(tempDir, 'commit-message.txt');\n await fs.writeFile(tempPath, message, 'utf8');\n try {\n await runGit(['commit', '-F', tempPath], repoRoot);\n } finally {\n try {\n await fs.unlink(tempPath);\n } catch (error) {\n // Ignore cleanup errors.\n }\n }\n}\n","import { execFile } from 'node:child_process';\nimport type { ExecFileOptions } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport async function runCommand(\n command: string,\n args: string[],\n options: ExecFileOptions = {},\n): Promise<{ stdout: string; stderr: string }> {\n const result = await execFileAsync(command, args, {\n ...options,\n encoding: 'utf8',\n maxBuffer: 10 * 1024 * 1024,\n });\n\n const stdout = typeof result.stdout === 'string' ? result.stdout : '';\n const stderr = typeof result.stderr === 'string' ? result.stderr : '';\n\n return {\n stdout: stdout.trimEnd(),\n stderr: stderr.trimEnd(),\n };\n}\n","import { fetch } from 'undici';\n\ninterface OpenRouterResponse {\n choices?: Array<{\n message?: {\n content?: string;\n };\n }>;\n}\n\nconst LARGE_NEW_FILE_LINE_LIMIT = 400;\nconst LARGE_NEW_FILE_HEAD_LINES = 120;\nconst LARGE_NEW_FILE_TAIL_LINES = 60;\n\nfunction stripCodeFences(text: string): string {\n const trimmed = text.trim();\n if (!trimmed.startsWith('```')) {\n return trimmed;\n }\n\n return trimmed.replace(/^```[a-zA-Z]*\\n?/, '').replace(/```$/, '').trim();\n}\n\nfunction parseJsonArray(text: string): string[] | null {\n const cleaned = stripCodeFences(text);\n try {\n const parsed = JSON.parse(cleaned);\n if (!Array.isArray(parsed)) {\n return null;\n }\n\n const strings = parsed\n .map((entry) => (typeof entry === 'string' ? entry.trim() : ''))\n .filter(Boolean);\n\n return strings.length ? strings : null;\n } catch (error) {\n return null;\n }\n}\n\nfunction parseLines(text: string): string[] {\n return text\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => line.replace(/^[-*\\d.\\)\\s]+/, '').trim())\n .filter(Boolean);\n}\n\nfunction splitDiffBlocks(diff: string): string[][] {\n const lines = diff.split('\\n');\n const blocks: string[][] = [];\n let current: string[] = [];\n\n for (const line of lines) {\n if (line.startsWith('diff --git ')) {\n if (current.length > 0) {\n blocks.push(current);\n }\n current = [line];\n continue;\n }\n\n current.push(line);\n }\n\n if (current.length > 0) {\n blocks.push(current);\n }\n\n return blocks;\n}\n\nfunction isNewFileBlock(block: string[]): boolean {\n return (\n block.some((line) => line.startsWith('new file mode')) ||\n block.some((line) => line.startsWith('index 0000000..'))\n );\n}\n\nfunction compressLargeNewFiles(diff: string): string {\n if (!diff.trim()) {\n return diff;\n }\n\n const blocks = splitDiffBlocks(diff);\n const compressed = blocks.map((block) => {\n if (!isNewFileBlock(block)) {\n return block;\n }\n\n const hunkStart = block.findIndex((line) => line.startsWith('@@'));\n if (hunkStart === -1) {\n return block;\n }\n\n const header = block.slice(0, hunkStart + 1);\n const content = block.slice(hunkStart + 1);\n const addedLineCount = content.filter(\n (line) => line.startsWith('+') && !line.startsWith('+++'),\n ).length;\n\n if (addedLineCount <= LARGE_NEW_FILE_LINE_LIMIT) {\n return block;\n }\n\n const head = content.slice(0, LARGE_NEW_FILE_HEAD_LINES);\n const tail = content.slice(-LARGE_NEW_FILE_TAIL_LINES);\n\n if (head.length + tail.length >= content.length) {\n return block;\n }\n\n const omitted = content.length - head.length - tail.length;\n const marker = `+... [truncated ${omitted} lines from large new file] ...`;\n\n return [...header, ...head, marker, ...tail];\n });\n\n return compressed.flat().join('\\n');\n}\n\nfunction normalizeMessages(messages: string[]): string[] {\n const unique: string[] = [];\n for (const message of messages) {\n if (!unique.includes(message)) {\n unique.push(message);\n }\n }\n\n if (unique.length < 3) {\n throw new Error('OpenRouter returned fewer than 3 messages');\n }\n\n return unique.slice(0, 3);\n}\n\nexport interface GenerateCommitMessagesInput {\n apiKey: string;\n model: string;\n instructions: string;\n diff: string;\n temperature: number;\n maxTokens: number;\n onDebug?: (info: OpenRouterDebugInfo) => void;\n}\n\nexport interface OpenRouterDebugInfo {\n stage: 'request' | 'response';\n prompt: string;\n payload: Record<string, unknown>;\n responseText?: string;\n status?: number;\n}\n\nexport async function generateCommitMessages({\n apiKey,\n model,\n instructions,\n diff,\n temperature,\n maxTokens,\n onDebug,\n}: GenerateCommitMessagesInput): Promise<string[]> {\n const trimmedDiff = diff.trim();\n const diffText = trimmedDiff\n ? compressLargeNewFiles(trimmedDiff)\n : '[No diff available]';\n\n const systemContent = [\n 'You generate git commit messages for staged changes.',\n 'Return ONLY a JSON array of exactly 3 strings.',\n 'Each string must be a commit message that matches the instructions.',\n 'Each option must summarize the full set of changes in this diff as a single commit.',\n 'Do not include any extra commentary or markdown.',\n '',\n 'Instructions:',\n instructions,\n ].join('\\n');\n const prompt = diffText;\n\n const payload: Record<string, unknown> = {\n model,\n messages: [\n {\n role: 'system',\n content: systemContent,\n },\n { role: 'user', content: prompt },\n ],\n };\n\n if (typeof temperature === 'number') {\n payload.temperature = temperature;\n }\n\n if (typeof maxTokens === 'number') {\n payload.max_tokens = maxTokens;\n }\n\n onDebug?.({ stage: 'request', prompt, payload });\n\n const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'HTTP-Referer': 'https://aicmt.local',\n 'X-Title': 'aicmt',\n },\n body: JSON.stringify(payload),\n });\n\n const responseText = await response.text();\n onDebug?.({\n stage: 'response',\n prompt,\n payload,\n responseText,\n status: response.status,\n });\n\n if (!response.ok) {\n throw new Error(`OpenRouter error: ${response.status} ${responseText}`);\n }\n\n let data: OpenRouterResponse;\n try {\n data = JSON.parse(responseText) as OpenRouterResponse;\n } catch (error) {\n throw new Error('OpenRouter returned invalid JSON');\n }\n const content = data.choices?.[0]?.message?.content ?? '';\n\n if (!content) {\n throw new Error('OpenRouter returned empty content');\n }\n\n const jsonMessages = parseJsonArray(content);\n if (jsonMessages) {\n return normalizeMessages(jsonMessages);\n }\n\n const lineMessages = parseLines(content);\n return normalizeMessages(lineMessages);\n}\n","import prompts from 'prompts';\nimport {\n DEFAULT_MAX_TOKENS,\n DEFAULT_MODEL,\n DEFAULT_TEMPERATURE,\n MAX_OUTPUT_TOKENS,\n MIN_OUTPUT_TOKENS,\n} from '../constants';\nimport {\n GlobalConfig,\n ProjectConfig,\n loadGlobalConfig,\n resolveConfigPath,\n saveGlobalConfig,\n} from '../config';\nimport { getRepoRoot, isGitRepo } from '../git';\n\ninterface FormatChoice {\n value: string;\n title: string;\n description: string;\n instructions?: string;\n}\n\nconst formatChoices: FormatChoice[] = [\n {\n value: 'conventional-scope',\n title: 'Conventional Commits (type(scope): subject)',\n description: 'Best for structured history with scopes.',\n instructions: [\n 'Use Conventional Commits: type(scope): subject.',\n 'Allowed types: feat, fix, docs, style, refactor, perf, test, chore, ci, build.',\n 'Subject <= 72 chars, imperative mood, no trailing period.',\n ].join('\\n'),\n },\n {\n value: 'conventional',\n title: 'Conventional Commits (type: subject)',\n description: 'Structured without scopes.',\n instructions: [\n 'Use Conventional Commits: type: subject.',\n 'Allowed types: feat, fix, docs, style, refactor, perf, test, chore, ci, build.',\n 'Subject <= 72 chars, imperative mood, no trailing period.',\n ].join('\\n'),\n },\n {\n value: 'short',\n title: 'Short imperative summary',\n description: 'Simple single-line format.',\n instructions: [\n 'Single-line summary, imperative mood, <= 72 chars, no trailing period.',\n ].join('\\n'),\n },\n {\n value: 'detailed',\n title: 'Detailed subject + body',\n description: 'Subject line plus body details.',\n instructions: [\n 'Subject <= 72 chars, imperative mood, no trailing period.',\n 'Blank line.',\n 'Body with bullet list of key changes (wrap at 100 chars).',\n ].join('\\n'),\n },\n {\n value: 'custom',\n title: 'Custom format',\n description: 'Provide your own instructions.',\n },\n];\n\nconst promptOptions = {\n onCancel: () => {\n throw new Error('Cancelled');\n },\n};\n\nexport interface InitOptions {\n cwd: string;\n configPath?: string;\n}\n\nfunction hasGlobalDefaults(config: GlobalConfig): boolean {\n return Boolean(\n config.model ||\n config.format ||\n config.instructions ||\n typeof config.temperature === 'number' ||\n typeof config.maxTokens === 'number',\n );\n}\n\nexport async function runInit({ cwd, configPath }: InitOptions): Promise<void> {\n const isRepo = await isGitRepo(cwd);\n if (!isRepo) {\n throw new Error('Not a git repository. Run inside a git project.');\n }\n\n const repoRoot = await getRepoRoot(cwd);\n const resolvedConfigPath = resolveConfigPath(repoRoot, configPath);\n\n const existingConfig = await loadGlobalConfig(resolvedConfigPath, {\n allowMissing: true,\n });\n\n const { format } = await prompts(\n {\n type: 'select',\n name: 'format',\n message: 'Choose commit message format',\n choices: formatChoices.map((choice) => ({\n title: choice.title,\n value: choice.value,\n description: choice.description,\n })),\n initial: 0,\n },\n promptOptions,\n );\n\n const selected = formatChoices.find((choice) => choice.value === format);\n if (!selected) {\n throw new Error('Invalid format selection.');\n }\n\n let baseInstructions = selected.instructions ?? '';\n if (selected.value === 'custom') {\n const { customInstructions } = await prompts(\n {\n type: 'text',\n name: 'customInstructions',\n message: 'Describe the commit message format',\n validate: (value: string) =>\n value.trim().length > 0 ? true : 'Please enter instructions.',\n },\n promptOptions,\n );\n baseInstructions = String(customInstructions || '').trim();\n }\n\n const { extraInstructions } = await prompts(\n {\n type: 'text',\n name: 'extraInstructions',\n message: 'Additional instructions (optional)',\n initial: '',\n },\n promptOptions,\n );\n\n const extra = String(extraInstructions || '').trim();\n const instructions = extra ? `${baseInstructions}\\n${extra}` : baseInstructions;\n\n const { model } = await prompts(\n {\n type: 'text',\n name: 'model',\n message: 'OpenRouter model',\n initial: DEFAULT_MODEL,\n validate: (value: string) =>\n value.trim().length > 0 ? true : 'Model is required.',\n },\n promptOptions,\n );\n\n const { temperature } = await prompts(\n {\n type: 'number',\n name: 'temperature',\n message: 'Temperature (0-2)',\n initial: DEFAULT_TEMPERATURE,\n min: 0,\n max: 2,\n float: true,\n },\n promptOptions,\n );\n\n const { maxTokens } = await prompts(\n {\n type: 'number',\n name: 'maxTokens',\n message: `Max tokens (${MIN_OUTPUT_TOKENS}-${MAX_OUTPUT_TOKENS})`,\n initial: DEFAULT_MAX_TOKENS,\n min: MIN_OUTPUT_TOKENS,\n max: MAX_OUTPUT_TOKENS,\n },\n promptOptions,\n );\n\n const { scope } = await prompts(\n {\n type: 'select',\n name: 'scope',\n message: 'Apply settings to',\n choices: [\n {\n title: 'All projects (global defaults)',\n value: 'global',\n description: 'Used when a repo has no override',\n },\n {\n title: 'This repo only (override)',\n value: 'project',\n description: 'Use custom settings for this repository',\n },\n ],\n initial: 0,\n },\n promptOptions,\n );\n\n const targetScope = scope === 'project' ? 'project' : 'global';\n\n if (targetScope === 'global' && hasGlobalDefaults(existingConfig)) {\n const { overwrite } = await prompts(\n {\n type: 'confirm',\n name: 'overwrite',\n message: 'Global defaults already exist. Overwrite?',\n initial: false,\n },\n promptOptions,\n );\n\n if (!overwrite) {\n console.log('Init cancelled.');\n return;\n }\n }\n\n if (targetScope === 'project' && existingConfig.projects?.[repoRoot]) {\n const { overwrite } = await prompts(\n {\n type: 'confirm',\n name: 'overwrite',\n message: 'Config already exists for this repo. Overwrite?',\n initial: false,\n },\n promptOptions,\n );\n\n if (!overwrite) {\n console.log('Init cancelled.');\n return;\n }\n }\n\n let globalApiKey = existingConfig.openrouterApiKey ?? '';\n if (globalApiKey) {\n const { reuseKey } = await prompts(\n {\n type: 'confirm',\n name: 'reuseKey',\n message: 'Use existing global OpenRouter API key?',\n initial: true,\n },\n promptOptions,\n );\n\n if (!reuseKey) {\n const { apiKey } = await prompts(\n {\n type: 'password',\n name: 'apiKey',\n message: 'OpenRouter API key',\n validate: (value: string) =>\n value.trim().length > 0 ? true : 'API key is required.',\n },\n promptOptions,\n );\n globalApiKey = String(apiKey || '').trim();\n }\n } else {\n const { apiKey } = await prompts(\n {\n type: 'password',\n name: 'apiKey',\n message: 'OpenRouter API key',\n validate: (value: string) =>\n value.trim().length > 0 ? true : 'API key is required.',\n },\n promptOptions,\n );\n globalApiKey = String(apiKey || '').trim();\n }\n\n const projectConfig: ProjectConfig = {\n model: String(model || DEFAULT_MODEL).trim(),\n format: String(format || 'custom'),\n instructions: instructions.trim(),\n temperature:\n typeof temperature === 'number' && !Number.isNaN(temperature)\n ? temperature\n : DEFAULT_TEMPERATURE,\n maxTokens:\n typeof maxTokens === 'number' && !Number.isNaN(maxTokens)\n ? Math.round(maxTokens)\n : DEFAULT_MAX_TOKENS,\n };\n\n const updatedConfig: GlobalConfig = {\n ...existingConfig,\n projects: {\n ...(existingConfig.projects ?? {}),\n },\n };\n\n updatedConfig.openrouterApiKey = globalApiKey;\n\n if (targetScope === 'global') {\n updatedConfig.model = projectConfig.model;\n updatedConfig.format = projectConfig.format;\n updatedConfig.instructions = projectConfig.instructions;\n updatedConfig.temperature = projectConfig.temperature;\n updatedConfig.maxTokens = projectConfig.maxTokens;\n } else {\n updatedConfig.projects[repoRoot] = projectConfig;\n }\n\n await saveGlobalConfig(resolvedConfigPath, updatedConfig);\n\n console.log(`Config saved to ${resolvedConfigPath}`);\n if (targetScope === 'global') {\n console.log('Applied as global defaults for all projects.');\n } else {\n console.log(`Applied as override for ${repoRoot}.`);\n }\n}\n","#!/usr/bin/env node\n\nimport { run } from '../cli';\n\nrun().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${message}`);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["path","os","fs","import_promises","import_node_os","import_node_path","filePath","fs","path","os","prompts","status","import_prompts","promptOptions","prompts"]}
|