UNPKG

llm-commit

Version:

Turns diffs into concise, readable git commit messages

103 lines 4.61 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { config } from 'dotenv'; config(); import { writeFile } from 'fs/promises'; import process from 'node:process'; import { program } from 'commander'; import pc from 'picocolors'; import clipboard from 'clipboardy'; import { oraPromise } from 'ora'; // todo make us not have to write file extension import { DEFAULT_TOKENS, defaultProvider, providerData } from './constants.js'; import { genCommitMessage } from './genMessage.js'; export const run = () => __awaiter(void 0, void 0, void 0, function* () { try { program .description(`${pc.greenBright('LLM Commit')} - Turn diffs into somewhat accurate commit messages`) .option('-p, --provider <provider>', 'LLM provider') .option('-m, --model-id <id>', 'model id') .option('-t, --max-tokens <tokens>', 'max tokens') .option('-o, --out-path <path>', 'write path for full LLM output') .option('-u, --unstaged', 'Use unstaged changes (omits --cached in git diff)') .option('-c, --copy', 'copies output to clipboard') .option('-r, --reason-tokens <reasonTokens>', 'enable reasoning/thinking for eligible models') .option('-s, --silent', 'do not print output') .action(commanderActionEndpoint); yield program.parseAsync(process.argv); } catch (error) { console.error(error); } }); const commanderActionEndpoint = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (options = {}) { yield runCli(process.cwd(), options); }); export const runCli = (cwd_1, _a) => __awaiter(void 0, [cwd_1, _a], void 0, function* (cwd, { modelId, maxTokens, outPath, reasonTokens, silent, unstaged, provider, copy }) { if (!provider) { console.log(`Defaulting to ${defaultProvider}...`); provider = defaultProvider; } const useProviderKey = convertProviderInput(provider); if (!(useProviderKey in providerData)) { throw new Error(`provider "${provider}" not recognized`); } const { defaultModelId, sdkProvider } = providerData[useProviderKey]; const useModelId = modelId || defaultModelId; const model = sdkProvider(useModelId); console.log('Running ' + useModelId); try { const llmResult = yield oraPromise(genCommitMessage({ model, maxTokens: maxTokens || DEFAULT_TOKENS, reasonTokens, diffOptions: { cached: !unstaged } })); if (!llmResult.text) { throw new Error('No commit message generated'); } if (copy) { clipboard.write(llmResult.text); // if this were browser we'd want to catch err in case we don't have permission } if (!silent) { console.log('\n' + llmResult.text); } if (outPath) { try { yield writeFile(outPath, JSON.stringify(llmResult), 'utf8'); } catch (writeError) { // We don't want to fail the entire operation if just the output file fails console.error(`Warning: Failed to write output to ${outPath}: ${writeError.message}`); } } } catch (err) { // seems like ai-sdk already handles any retryable errors, just error includes a lot of the request and res which seems unnecessary if ('data' in err && 'error' in err.data) { console.error(err.data.error.type + '\n' + err.data.error.message); } else { console.error(err); } process.exit(1); } }); // tries to find close matches/shorthands const convertProviderInput = (rawInput) => { const normalized = rawInput.toLowerCase().trim(); for (const provider in providerData) { if (providerData[provider].names.includes(normalized)) { return provider; } } return null; }; //# sourceMappingURL=cli.js.map