test: update tests
This commit is contained in:
+197
-110
@@ -128,6 +128,24 @@ async function confirmCommit(message, isLocalHeuristic) {
|
||||
});
|
||||
}
|
||||
|
||||
function askQuestion(promptText) {
|
||||
const readline = require('readline');
|
||||
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
return new Promise(resolve => {
|
||||
rl.question(promptText, answer => {
|
||||
rl.close();
|
||||
resolve(answer.trim());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function confirmPrompt(message, defaultYes = true) {
|
||||
const suffix = defaultYes ? '[Y/n]' : '[y/N]';
|
||||
const answer = (await askQuestion(`${message} ${suffix}: `)).toLowerCase();
|
||||
if (answer === '') return defaultYes;
|
||||
return answer === 'y' || answer === 'yes';
|
||||
}
|
||||
|
||||
async function resolveCommit(input) {
|
||||
if (/^\d+$/.test(input)) {
|
||||
const { all } = await safeLog();
|
||||
@@ -145,6 +163,25 @@ async function hasChanges() {
|
||||
return status.files.length > 0;
|
||||
}
|
||||
|
||||
// Returns staged diff string, auto-staging as needed, or null when nothing to commit.
|
||||
async function getStagedDiff(opts) {
|
||||
if (!(await hasChanges()) && !opts.all) return null;
|
||||
|
||||
if (opts.all) {
|
||||
Progress.info('Staging all changes...');
|
||||
await git.add('.');
|
||||
}
|
||||
|
||||
let diff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!diff.trim()) {
|
||||
Progress.info('No staged changes found; staging all changes...');
|
||||
await git.add('.');
|
||||
diff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
}
|
||||
|
||||
return diff.trim() ? diff : null;
|
||||
}
|
||||
|
||||
program
|
||||
.name('gims')
|
||||
.alias('g')
|
||||
@@ -528,27 +565,12 @@ program.command('local').alias('l')
|
||||
const opts = getOpts();
|
||||
|
||||
try {
|
||||
if (!(await hasChanges()) && !opts.all) {
|
||||
const rawDiff = await getStagedDiff(opts);
|
||||
if (!rawDiff) {
|
||||
Progress.warning('No changes to commit');
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.all) {
|
||||
Progress.info('Staging all changes...');
|
||||
await git.add('.');
|
||||
}
|
||||
|
||||
let rawDiff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!rawDiff.trim()) {
|
||||
Progress.info('No staged changes found; staging all changes...');
|
||||
await git.add('.');
|
||||
rawDiff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!rawDiff.trim()) {
|
||||
Progress.warning('No changes to commit');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.progressIndicators) Progress.start('🤖 Generating commit message');
|
||||
const result = await generateCommitMessage(rawDiff, opts);
|
||||
if (opts.progressIndicators) Progress.stop('');
|
||||
@@ -590,27 +612,12 @@ program.command('online').alias('o')
|
||||
const opts = getOpts();
|
||||
|
||||
try {
|
||||
if (!(await hasChanges()) && !opts.all) {
|
||||
const rawDiff = await getStagedDiff(opts);
|
||||
if (!rawDiff) {
|
||||
Progress.warning('No changes to commit');
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.all) {
|
||||
Progress.info('Staging all changes...');
|
||||
await git.add('.');
|
||||
}
|
||||
|
||||
let rawDiff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!rawDiff.trim()) {
|
||||
Progress.info('No staged changes found; staging all changes...');
|
||||
await git.add('.');
|
||||
rawDiff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!rawDiff.trim()) {
|
||||
Progress.warning('No changes to commit');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.progressIndicators) Progress.start('🤖 Generating commit message');
|
||||
const result = await generateCommitMessage(rawDiff, opts);
|
||||
if (opts.progressIndicators) Progress.stop('');
|
||||
@@ -675,22 +682,12 @@ program.command('commit <message...>').alias('m')
|
||||
const msg = (messageParts || []).join(' ').trim();
|
||||
if (!msg) { console.log('Provide a commit message.'); return; }
|
||||
|
||||
if (!(await hasChanges()) && !opts.all) {
|
||||
console.log('No changes to commit.');
|
||||
const rawDiff = await getStagedDiff(opts);
|
||||
if (!rawDiff) {
|
||||
Progress.warning('No changes to commit');
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.all) await git.add('.');
|
||||
|
||||
let rawDiff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!rawDiff.trim()) {
|
||||
// Auto-stage all changes by default when nothing is staged
|
||||
console.log(color.yellow('No staged changes found; staging all changes (git add .).'));
|
||||
await git.add('.');
|
||||
rawDiff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!rawDiff.trim()) { console.log('No changes to commit.'); return; }
|
||||
}
|
||||
|
||||
if (opts.dryRun) {
|
||||
console.log(color.yellow('[dry-run] Would commit with custom message:'));
|
||||
console.log(msg);
|
||||
@@ -722,16 +719,114 @@ program.command('pull')
|
||||
|
||||
program.command('push')
|
||||
.description('Push commits to remote')
|
||||
.action(async () => {
|
||||
.option('--tags', 'Push all tags to remote')
|
||||
.action(async (cmdOptions) => {
|
||||
await ensureRepo();
|
||||
try {
|
||||
Progress.info('Pushing to remote...');
|
||||
await git.push();
|
||||
Progress.success('Pushed to remote');
|
||||
if (cmdOptions.tags) {
|
||||
Progress.info('Pushing tags to remote...');
|
||||
await git.push(['--tags']);
|
||||
Progress.success('Tags pushed to remote');
|
||||
} else {
|
||||
Progress.info('Pushing to remote...');
|
||||
await git.push();
|
||||
Progress.success('Pushed to remote');
|
||||
}
|
||||
}
|
||||
catch (e) { handleError('Push error', e); }
|
||||
});
|
||||
|
||||
program.command('mirror [url]')
|
||||
.alias('mr')
|
||||
.description('Manage extra push destinations for origin (g push fans out to all of them)')
|
||||
.action(async (url) => {
|
||||
await ensureRepo();
|
||||
try {
|
||||
const remotes = await git.getRemotes(true);
|
||||
const origin = remotes.find(r => r.name === 'origin');
|
||||
if (!origin) {
|
||||
Progress.warning("No 'origin' remote configured");
|
||||
return;
|
||||
}
|
||||
|
||||
const primary = origin.refs.fetch;
|
||||
const pushUrls = (await git.raw(['config', '--get-all', 'remote.origin.pushurl']).catch(() => ''))
|
||||
.split('\n').map(s => s.trim()).filter(Boolean);
|
||||
const mirrors = pushUrls.filter(u => u !== primary);
|
||||
|
||||
if (url) {
|
||||
if (primary === url || pushUrls.includes(url)) {
|
||||
Progress.warning('That URL is already registered for origin');
|
||||
return;
|
||||
}
|
||||
|
||||
Progress.info(`Verifying ${url}...`);
|
||||
try {
|
||||
await git.listRemote([url]);
|
||||
} catch {
|
||||
const proceed = await confirmPrompt(`Could not reach "${url}". Add it anyway?`, false);
|
||||
if (!proceed) { Progress.info('Cancelled'); return; }
|
||||
}
|
||||
|
||||
// Make the primary an explicit pushurl first so it isn't lost once we add others
|
||||
if (pushUrls.length === 0) {
|
||||
await git.raw(['remote', 'set-url', '--push', 'origin', primary]);
|
||||
}
|
||||
await git.raw(['remote', 'set-url', '--add', '--push', 'origin', url]);
|
||||
Progress.success(`Added mirror: ${url}`);
|
||||
Progress.info(`'g push' now pushes to ${mirrors.length + 2} destination(s)`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(color.bold('\nPush destinations for origin:'));
|
||||
console.log(` ${color.green('●')} ${primary} ${color.dim('(primary)')}`);
|
||||
if (mirrors.length === 0) {
|
||||
console.log(color.dim('\nNo mirrors configured.'));
|
||||
console.log(color.dim(`Add one with: ${color.cyan('g mirror <url>')}`));
|
||||
return;
|
||||
}
|
||||
mirrors.forEach(m => console.log(` ${color.cyan('○')} ${m} ${color.dim('(mirror)')}`));
|
||||
|
||||
// Single readline session for the whole remove flow — separate
|
||||
// interfaces on the same stdin can drop input on later prompts.
|
||||
const readline = require('readline');
|
||||
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
const ask = (q) => new Promise(resolve => rl.question(q, a => resolve(a.trim())));
|
||||
const confirm = async (message, defaultYes) => {
|
||||
const suffix = defaultYes ? '[Y/n]' : '[y/N]';
|
||||
const answer = (await ask(`${message} ${suffix}: `)).toLowerCase();
|
||||
if (answer === '') return defaultYes;
|
||||
return answer === 'y' || answer === 'yes';
|
||||
};
|
||||
|
||||
try {
|
||||
const wantsRemove = await confirm('\nRemove a mirror?', false);
|
||||
if (!wantsRemove) return;
|
||||
|
||||
let target = mirrors[0];
|
||||
if (mirrors.length > 1) {
|
||||
const answer = await ask(`Which mirror? [1-${mirrors.length}]: `);
|
||||
const idx = parseInt(answer) - 1;
|
||||
if (isNaN(idx) || idx < 0 || idx >= mirrors.length) {
|
||||
Progress.warning('Invalid selection, cancelled');
|
||||
return;
|
||||
}
|
||||
target = mirrors[idx];
|
||||
}
|
||||
|
||||
const confirmDelete = await confirm(`Remove "${target}"?`, false);
|
||||
if (!confirmDelete) { Progress.info('Cancelled'); return; }
|
||||
|
||||
await git.raw(['remote', 'set-url', '--delete', '--push', 'origin', target]);
|
||||
Progress.success(`Removed mirror: ${target}`);
|
||||
} finally {
|
||||
rl.close();
|
||||
}
|
||||
} catch (e) {
|
||||
handleError('Mirror error', e);
|
||||
}
|
||||
});
|
||||
|
||||
program.command('sync')
|
||||
.description('Smart sync: pull + rebase/merge')
|
||||
.option('--rebase', 'Use rebase instead of merge')
|
||||
@@ -826,11 +921,12 @@ program.command('stash')
|
||||
|
||||
Progress.start('🤖 Generating stash description');
|
||||
const diff = await git.diff();
|
||||
const description = await aiProvider.generateCommitMessage(diff, {
|
||||
const descResult = await aiProvider.generateCommitMessage(diff, {
|
||||
conventional: false,
|
||||
body: false
|
||||
});
|
||||
Progress.stop('');
|
||||
const description = descResult.message || descResult;
|
||||
|
||||
await git.stash(['push', '-m', `WIP: ${description}`]);
|
||||
Progress.success(`Stashed changes: "${description}"`);
|
||||
@@ -923,28 +1019,28 @@ program.command('amend').alias('a')
|
||||
}
|
||||
});
|
||||
|
||||
async function printCommitLog(limit) {
|
||||
const log = await git.log({ maxCount: limit });
|
||||
const commits = [...log.all].reverse();
|
||||
if (commits.length === 0) {
|
||||
Progress.info('No commits found');
|
||||
return;
|
||||
}
|
||||
commits.forEach((c, i) => {
|
||||
console.log(`${color.cyan((i + 1).toString())}. ${color.yellow(c.hash.slice(0, 7))} ${c.message}`);
|
||||
});
|
||||
if (log.all.length >= limit) {
|
||||
console.log(color.dim(`\n... showing last ${limit} commits (use --limit to see more)`));
|
||||
}
|
||||
}
|
||||
|
||||
program.command('list').alias('ls')
|
||||
.description('Short numbered git log (oldest → newest)')
|
||||
.option('--limit <n>', 'Limit number of commits', '20')
|
||||
.action(async (cmdOptions) => {
|
||||
await ensureRepo();
|
||||
try {
|
||||
const limit = parseInt(cmdOptions.limit) || 20;
|
||||
const log = await git.log({ maxCount: limit });
|
||||
const commits = [...log.all].reverse();
|
||||
|
||||
if (commits.length === 0) {
|
||||
Progress.info('No commits found');
|
||||
return;
|
||||
}
|
||||
|
||||
commits.forEach((c, i) => {
|
||||
console.log(`${color.cyan((i + 1).toString())}. ${color.yellow(c.hash.slice(0, 7))} ${c.message}`);
|
||||
});
|
||||
|
||||
if (log.all.length >= limit) {
|
||||
console.log(color.dim(`\n... showing last ${limit} commits (use --limit to see more)`));
|
||||
}
|
||||
await printCommitLog(parseInt(cmdOptions.limit) || 20);
|
||||
} catch (e) {
|
||||
handleError('List error', e);
|
||||
}
|
||||
@@ -984,22 +1080,7 @@ program.command('history').alias('h')
|
||||
.action(async (cmdOptions) => {
|
||||
await ensureRepo();
|
||||
try {
|
||||
const limit = parseInt(cmdOptions.limit) || 20;
|
||||
const log = await git.log({ maxCount: limit });
|
||||
const commits = [...log.all].reverse();
|
||||
|
||||
if (commits.length === 0) {
|
||||
Progress.info('No commits found');
|
||||
return;
|
||||
}
|
||||
|
||||
commits.forEach((c, i) => {
|
||||
console.log(`${color.cyan((i + 1).toString())}. ${color.yellow(c.hash.slice(0, 7))} ${c.message}`);
|
||||
});
|
||||
|
||||
if (log.all.length >= limit) {
|
||||
console.log(color.dim(`\n... showing last ${limit} commits (use --limit to see more)`));
|
||||
}
|
||||
await printCommitLog(parseInt(cmdOptions.limit) || 20);
|
||||
} catch (e) {
|
||||
handleError('History error', e);
|
||||
}
|
||||
@@ -1743,14 +1824,16 @@ program.command('fix').alias('f')
|
||||
|
||||
if (behind > 0) {
|
||||
try {
|
||||
const behindLog = await git.log({ from: branch, to: remoteBranch, maxCount: 5 });
|
||||
// symmetric: false → "branch..remoteBranch" (commits on remote only, not "branch...remoteBranch" which mixes both directions)
|
||||
const behindLog = await git.log({ from: branch, to: remoteBranch, symmetric: false, maxCount: 5 });
|
||||
aiContext += `Incoming commits (latest 5):\n${behindLog.all.map(c => `- ${c.message}`).join('\n')}\n\n`;
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
if (ahead > 0) {
|
||||
try {
|
||||
const aheadLog = await git.log({ from: remoteBranch, to: branch, maxCount: 5 });
|
||||
// symmetric: false → "remoteBranch..branch" (commits on local only)
|
||||
const aheadLog = await git.log({ from: remoteBranch, to: branch, symmetric: false, maxCount: 5 });
|
||||
aiContext += `My outgoing commits (latest 5):\n${aheadLog.all.map(c => `- ${c.message}`).join('\n')}\n`;
|
||||
} catch (e) { }
|
||||
}
|
||||
@@ -1766,36 +1849,40 @@ program.command('fix').alias('f')
|
||||
Recommended Command: <command>
|
||||
`;
|
||||
|
||||
// Use preferred provider or auto-resolve
|
||||
const provider = aiProvider.resolveProvider(opts.provider);
|
||||
if (provider === 'none') {
|
||||
const heuristicRec = () => {
|
||||
if (ahead > 0 && behind === 0) return 'Push (g push)';
|
||||
if (behind > 0 && ahead === 0) return 'Pull (g pull)';
|
||||
return 'Rebase (g fix --rebase)';
|
||||
};
|
||||
|
||||
// Try each available provider in priority order, with full fallback chain
|
||||
const providerChain = aiProvider.buildProviderChain(opts.provider || 'auto')
|
||||
.filter(p => p !== 'local');
|
||||
|
||||
if (providerChain.length === 0) {
|
||||
Progress.stop('');
|
||||
console.log(color.yellow('No AI provider configured. Falling back to simple heuristics.'));
|
||||
// ... heuristic fallback ...
|
||||
let rec = '';
|
||||
if (ahead > 0 && behind === 0) rec = 'Push (g push)';
|
||||
else if (behind > 0 && ahead === 0) rec = 'Pull (g pull)';
|
||||
else rec = 'Rebase (g fix --rebase)';
|
||||
console.log(`Recommendation: ${rec}`);
|
||||
console.log(`Recommendation: ${heuristicRec()}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await aiProvider.generateWithProvider(provider, prompt, { temperature: 0.3 }); // Use generic provider method
|
||||
|
||||
Progress.stop('');
|
||||
console.log(`\n${color.bold('🤖 AI Analysis:')}`);
|
||||
console.log(response.trim());
|
||||
} catch (e) {
|
||||
Progress.stop('');
|
||||
console.log(color.yellow('AI Analysis failed, falling back to heuristics.'));
|
||||
// ... heuristic fallback code ...
|
||||
let rec = '';
|
||||
if (ahead > 0 && behind === 0) rec = 'Push (g push)';
|
||||
else if (behind > 0 && ahead === 0) rec = 'Pull (g pull)';
|
||||
else rec = 'Rebase (g fix --rebase)';
|
||||
console.log(`Recommendation: ${rec}`);
|
||||
let response = null;
|
||||
for (const p of providerChain) {
|
||||
try {
|
||||
response = await aiProvider.generateWithProvider(p, prompt, { temperature: 0.3 });
|
||||
break;
|
||||
} catch { continue; }
|
||||
}
|
||||
|
||||
Progress.stop('');
|
||||
if (!response) {
|
||||
console.log(color.yellow('AI providers unavailable. Falling back to heuristics.'));
|
||||
console.log(`Recommendation: ${heuristicRec()}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`\n${color.bold('🤖 AI Analysis:')}`);
|
||||
console.log(response.trim());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+49
-38
@@ -1,3 +1,5 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { OpenAI } = require('openai');
|
||||
const { GoogleGenAI } = require('@google/genai');
|
||||
const { Progress } = require('../utils/progress');
|
||||
@@ -9,31 +11,17 @@ const { color } = require('../utils/colors');
|
||||
class AIProviderManager {
|
||||
constructor(config = {}) {
|
||||
this.config = config;
|
||||
this.cache = new Map();
|
||||
this.maxCacheSize = 100;
|
||||
}
|
||||
|
||||
resolveProvider(preference = 'auto') {
|
||||
if (preference === 'none') return 'none';
|
||||
|
||||
// Check if preferred provider's key is available
|
||||
if (preference === 'openai' && process.env.OPENAI_API_KEY) return 'openai';
|
||||
if (preference === 'gemini' && process.env.GEMINI_API_KEY) return 'gemini';
|
||||
if (preference === 'groq' && process.env.GROQ_API_KEY) return 'groq';
|
||||
|
||||
// Fallback: try any available provider (priority: Gemini → OpenAI → Groq)
|
||||
if (process.env.GEMINI_API_KEY) return 'gemini';
|
||||
if (process.env.OPENAI_API_KEY) return 'openai';
|
||||
if (process.env.GROQ_API_KEY) return 'groq';
|
||||
|
||||
return 'none';
|
||||
this.cacheFile = path.join(
|
||||
process.env.HOME || process.env.USERPROFILE || process.cwd(),
|
||||
'.gims', 'cache.json'
|
||||
);
|
||||
}
|
||||
|
||||
getDefaultModel(provider) {
|
||||
const defaults = {
|
||||
'gemini': 'gemini-3-flash-preview', // Latest Gemini model
|
||||
'openai': 'gpt-5.2-2025-12-11', // Latest GPT model
|
||||
'groq': 'groq/compound' // Latest Groq model
|
||||
'gemini': 'gemini-2.0-flash',
|
||||
'openai': 'gpt-4o-mini',
|
||||
'groq': 'llama-3.3-70b-versatile'
|
||||
};
|
||||
return defaults[provider] || '';
|
||||
}
|
||||
@@ -46,26 +34,36 @@ class AIProviderManager {
|
||||
|
||||
getFromCache(cacheKey) {
|
||||
if (!this.config.cacheEnabled) return null;
|
||||
return this.cache.get(cacheKey);
|
||||
try {
|
||||
if (!fs.existsSync(this.cacheFile)) return null;
|
||||
const data = JSON.parse(fs.readFileSync(this.cacheFile, 'utf8'));
|
||||
return data[cacheKey] || null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
setCache(cacheKey, result, usedLocal = false) {
|
||||
if (!this.config.cacheEnabled) return;
|
||||
|
||||
if (this.cache.size >= this.maxCacheSize) {
|
||||
const firstKey = this.cache.keys().next().value;
|
||||
this.cache.delete(firstKey);
|
||||
}
|
||||
|
||||
this.cache.set(cacheKey, {
|
||||
result,
|
||||
usedLocal,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
try {
|
||||
const dir = path.dirname(this.cacheFile);
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
let data = {};
|
||||
if (fs.existsSync(this.cacheFile)) {
|
||||
try { data = JSON.parse(fs.readFileSync(this.cacheFile, 'utf8')); } catch {}
|
||||
}
|
||||
const keys = Object.keys(data);
|
||||
if (keys.length >= 100) {
|
||||
const oldest = keys.sort((a, b) => (data[a].timestamp || 0) - (data[b].timestamp || 0));
|
||||
oldest.slice(0, keys.length - 99).forEach(k => delete data[k]);
|
||||
}
|
||||
data[cacheKey] = { result, usedLocal, timestamp: Date.now() };
|
||||
fs.writeFileSync(this.cacheFile, JSON.stringify(data));
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async generateWithProvider(provider, prompt, options = {}) {
|
||||
const { model = '', temperature = 0.3, maxTokens = 200 } = options;
|
||||
const { model = '' } = options;
|
||||
|
||||
try {
|
||||
switch (provider) {
|
||||
@@ -79,7 +77,14 @@ class AIProviderManager {
|
||||
throw new Error(`Unknown provider: ${provider}`);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`${provider} generation failed: ${error.message}`);
|
||||
const msg = error.message || '';
|
||||
if (msg.includes('429') || /rate.?limit/i.test(msg)) {
|
||||
throw new Error(`${provider} rate limit hit — try again in a moment`);
|
||||
}
|
||||
if (msg.includes('401') || /invalid.api.key|api_key/i.test(msg)) {
|
||||
throw new Error(`${provider} API key invalid — run: g setup --api-key ${provider}`);
|
||||
}
|
||||
throw new Error(`${provider} generation failed: ${msg}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,8 +140,14 @@ class AIProviderManager {
|
||||
verbose = false
|
||||
} = options;
|
||||
|
||||
// Truncate oversized diffs before sending to AI
|
||||
const maxDiffSize = this.config.maxDiffSize || 100000;
|
||||
const truncatedDiff = diff.length > maxDiffSize
|
||||
? diff.substring(0, maxDiffSize) + '\n... (diff truncated for AI)'
|
||||
: diff;
|
||||
|
||||
// Check cache first
|
||||
const cacheKey = this.getCacheKey(diff, { conventional, body });
|
||||
const cacheKey = this.getCacheKey(truncatedDiff, { conventional, body });
|
||||
const cached = this.getFromCache(cacheKey);
|
||||
if (cached && Date.now() - cached.timestamp < 3600000) { // 1 hour cache
|
||||
if (verbose) Progress.info('Using cached result');
|
||||
@@ -148,12 +159,12 @@ class AIProviderManager {
|
||||
for (const provider of providerChain) {
|
||||
try {
|
||||
if (provider === 'local') {
|
||||
const result = await this.generateLocalHeuristic(diff, options);
|
||||
const result = await this.generateLocalHeuristic(truncatedDiff, options);
|
||||
this.setCache(cacheKey, result, true);
|
||||
return { message: result, usedLocal: true };
|
||||
}
|
||||
|
||||
const prompt = this.buildPrompt(diff, { conventional, body });
|
||||
const prompt = this.buildPrompt(truncatedDiff, { conventional, body });
|
||||
const result = await this.generateWithProvider(provider, prompt, options);
|
||||
const cleaned = this.cleanCommitMessage(result, { body });
|
||||
|
||||
|
||||
@@ -164,14 +164,14 @@ class ConfigManager {
|
||||
console.log(` ${color.cyan('g setup --api-key openai')} # High quality`);
|
||||
console.log(` ${color.cyan('g setup --api-key groq')} # Ultra fast`);
|
||||
console.log('\nOr set environment variables manually:');
|
||||
console.log(' - OPENAI_API_KEY (gpt-5)');
|
||||
console.log(' - GEMINI_API_KEY (gemini-2.5-flash)');
|
||||
console.log(' - GROQ_API_KEY (groq/compound)');
|
||||
console.log(' - OPENAI_API_KEY (gpt-4o-mini)');
|
||||
console.log(' - GEMINI_API_KEY (gemini-2.0-flash)');
|
||||
console.log(' - GROQ_API_KEY (llama-3.3-70b-versatile)');
|
||||
} else {
|
||||
console.log('Available providers with default models:');
|
||||
if (hasGemini) console.log(` ${color.green('✓')} Google Gemini (gemini-2.5-flash)`);
|
||||
if (hasOpenAI) console.log(` ${color.green('✓')} OpenAI (gpt-5)`);
|
||||
if (hasGroq) console.log(` ${color.green('✓')} Groq (groq/compound)`);
|
||||
if (hasGemini) console.log(` ${color.green('✓')} Google Gemini (gemini-2.0-flash)`);
|
||||
if (hasOpenAI) console.log(` ${color.green('✓')} OpenAI (gpt-4o-mini)`);
|
||||
if (hasGroq) console.log(` ${color.green('✓')} Groq (llama-3.3-70b-versatile)`);
|
||||
}
|
||||
|
||||
const provider = await question(`\nPreferred provider (auto/openai/gemini/groq/none) [auto]: `) || 'auto';
|
||||
|
||||
Generated
+161
-189
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "gims",
|
||||
"version": "0.8.5",
|
||||
"version": "0.9.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gims",
|
||||
"version": "0.8.5",
|
||||
"version": "0.9.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -49,9 +49,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@hono/node-server": {
|
||||
"version": "1.19.9",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
|
||||
"integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==",
|
||||
"version": "1.19.14",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz",
|
||||
"integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.14.1"
|
||||
@@ -76,9 +76,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@modelcontextprotocol/sdk": {
|
||||
"version": "1.25.3",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz",
|
||||
"integrity": "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==",
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
|
||||
"integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.19.9",
|
||||
@@ -89,14 +89,15 @@
|
||||
"cross-spawn": "^7.0.5",
|
||||
"eventsource": "^3.0.2",
|
||||
"eventsource-parser": "^3.0.0",
|
||||
"express": "^5.0.1",
|
||||
"express-rate-limit": "^7.5.0",
|
||||
"jose": "^6.1.1",
|
||||
"express": "^5.2.1",
|
||||
"express-rate-limit": "^8.2.1",
|
||||
"hono": "^4.11.4",
|
||||
"jose": "^6.1.3",
|
||||
"json-schema-typed": "^8.0.2",
|
||||
"pkce-challenge": "^5.0.0",
|
||||
"raw-body": "^3.0.0",
|
||||
"zod": "^3.25 || ^4.0",
|
||||
"zod-to-json-schema": "^3.25.0"
|
||||
"zod-to-json-schema": "^3.25.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -114,23 +115,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@simple-git/args-pathspec": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@simple-git/args-pathspec/-/args-pathspec-1.0.3.tgz",
|
||||
"integrity": "sha512-ngJMaHlsWDTfjyq9F3VIQ8b7NXbBLq5j9i5bJ6XLYtD6qlDXT7fdKY2KscWWUF8t18xx052Y/PUO1K1TRc9yKA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@simple-git/argv-parser": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@simple-git/argv-parser/-/argv-parser-1.1.1.tgz",
|
||||
"integrity": "sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@simple-git/args-pathspec": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.19.111",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.111.tgz",
|
||||
"integrity": "sha512-90sGdgA+QLJr1F9X79tQuEut0gEYIfkX9pydI4XGRgvFo9g2JWswefI+WUSUHPYVBHYSEfTEqBxA5hQvAZB3Mw==",
|
||||
"version": "18.19.130",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
|
||||
"integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-fetch": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||
"integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
|
||||
"version": "2.6.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
|
||||
"integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"form-data": "^4.0.0"
|
||||
"form-data": "^4.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/abort-controller": {
|
||||
@@ -158,35 +174,10 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts/node_modules/mime-db": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts/node_modules/mime-types": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
|
||||
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "^1.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
|
||||
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
@@ -205,9 +196,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.20.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
||||
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -284,9 +275,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bignumber.js": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz",
|
||||
"integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==",
|
||||
"version": "9.3.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
|
||||
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
@@ -399,9 +390,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
|
||||
"integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
|
||||
"integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -561,9 +552,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
|
||||
"integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
@@ -624,9 +615,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eventsource-parser": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
|
||||
"integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.0.tgz",
|
||||
"integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -699,10 +690,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express-rate-limit": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz",
|
||||
"integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==",
|
||||
"version": "8.5.2",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz",
|
||||
"integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ip-address": "^10.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
@@ -713,31 +707,6 @@
|
||||
"express": ">= 4.11"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/mime-db": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/mime-types": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
|
||||
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "^1.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
@@ -751,9 +720,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-uri": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
|
||||
"integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -788,9 +757,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
@@ -809,6 +778,27 @@
|
||||
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/form-data/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/formdata-node": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
|
||||
@@ -1007,9 +997,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
|
||||
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
@@ -1019,11 +1009,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/hono": {
|
||||
"version": "4.11.7",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
|
||||
"integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
|
||||
"version": "4.12.24",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.24.tgz",
|
||||
"integrity": "sha512-I36D1s+HgQc55KbhEr4iybfxv/9o1zdpw+XEM6dJa91LqQD0HCoSGdxpRJCZE+aavs87j4V3Ls2OJzq8C/U4iw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
}
|
||||
@@ -1101,6 +1090,15 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
|
||||
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
@@ -1162,9 +1160,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/jose": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
|
||||
"integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==",
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz",
|
||||
"integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
@@ -1203,12 +1201,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jws": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
|
||||
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
|
||||
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jwa": "^2.0.0",
|
||||
"jwa": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
@@ -1249,24 +1247,28 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
|
||||
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
"mime-db": "^1.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-fn": {
|
||||
@@ -1451,9 +1453,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
|
||||
"integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
|
||||
"integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -1483,9 +1485,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"version": "6.15.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
|
||||
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
@@ -1598,31 +1600,6 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/mime-db": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/mime-types": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
|
||||
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "^1.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
|
||||
@@ -1689,13 +1666,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel-list": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
|
||||
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
|
||||
"integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"object-inspect": "^1.13.3"
|
||||
"object-inspect": "^1.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -1748,13 +1725,15 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/simple-git": {
|
||||
"version": "3.28.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.28.0.tgz",
|
||||
"integrity": "sha512-Rs/vQRwsn1ILH1oBUy8NucJlXmnnLeLCfcvbSehkPzbv3wwoFWIdtfd6Ndo6ZPhlPsCZ60CPI4rxurnwAa+a2w==",
|
||||
"version": "3.36.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.36.0.tgz",
|
||||
"integrity": "sha512-cGQjLjK8bxJw4QuYT7gxHw3/IouVESbhahSsHrX97MzCL1gu2u7oy38W6L2ZIGECEfIBG4BabsWDPjBxJENv9Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@kwsites/file-exists": "^1.1.1",
|
||||
"@kwsites/promise-deferred": "^1.1.1",
|
||||
"@simple-git/args-pathspec": "^1.0.3",
|
||||
"@simple-git/argv-parser": "^1.1.0",
|
||||
"debug": "^4.4.0"
|
||||
},
|
||||
"funding": {
|
||||
@@ -1796,36 +1775,28 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
|
||||
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
|
||||
"integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"content-type": "^1.0.5",
|
||||
"content-type": "^2.0.0",
|
||||
"media-typer": "^1.1.0",
|
||||
"mime-types": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is/node_modules/mime-db": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is/node_modules/mime-types": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
|
||||
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "^1.54.0"
|
||||
"node": ">= 18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is/node_modules/content-type": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
|
||||
"integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@@ -1853,6 +1824,7 @@
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
@@ -1918,9 +1890,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
|
||||
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
||||
"version": "8.21.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
|
||||
"integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -1939,21 +1911,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.25.64",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.64.tgz",
|
||||
"integrity": "sha512-hbP9FpSZf7pkS7hRVUrOjhwKJNyampPgtXKc3AN6DsWtoHsg2Sb4SQaS4Tcay380zSwd2VPo9G9180emBACp5g==",
|
||||
"version": "3.25.76",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/zod-to-json-schema": {
|
||||
"version": "3.25.1",
|
||||
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
|
||||
"integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==",
|
||||
"version": "3.25.2",
|
||||
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz",
|
||||
"integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25 || ^4"
|
||||
"zod": "^3.25.28 || ^4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gims",
|
||||
"version": "0.9.1",
|
||||
"version": "0.9.2",
|
||||
"description": "Git Made Simple – AI‑powered git helper with smart insights, stats & code review",
|
||||
"author": "S41R4J",
|
||||
"license": "MIT",
|
||||
|
||||
Reference in New Issue
Block a user