agentaudit 3.13.9 → 3.13.11
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/cli.mjs +55 -23
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -2876,27 +2876,36 @@ async function safeJsonParse(res, llmConfig) {
|
|
|
2876
2876
|
}
|
|
2877
2877
|
|
|
2878
2878
|
function getMaxOutputTokens(model) {
|
|
2879
|
-
// Known max_completion_tokens from provider docs
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
'claude-
|
|
2884
|
-
'claude-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2879
|
+
// Known max_completion_tokens from provider docs (2026-02)
|
|
2880
|
+
// Array (not object) to guarantee match order — specific keys before generic ones
|
|
2881
|
+
const limits = [
|
|
2882
|
+
// Anthropic (specific versions first, then generic)
|
|
2883
|
+
['claude-haiku-4-5', 8192], ['claude-3-haiku', 4096], ['claude-3-5-haiku', 8192],
|
|
2884
|
+
['claude-sonnet-4-6', 64000], ['claude-sonnet-4-5', 16384], ['claude-3-5-sonnet', 8192], ['claude-sonnet-4', 16384],
|
|
2885
|
+
['claude-opus-4-6', 32768], ['claude-opus-4', 32768],
|
|
2886
|
+
// Google Gemini
|
|
2887
|
+
['gemini-3', 65536], ['gemini-2.5', 65536], ['gemini-2.0', 65536],
|
|
2888
|
+
// Qwen (OpenRouter)
|
|
2889
|
+
['qwen3.5', 65536], ['qwen3', 32768], ['qwen2.5', 32768],
|
|
2889
2890
|
// xAI
|
|
2890
|
-
'grok-4'
|
|
2891
|
+
['grok-4', 32768], ['grok-3', 16384],
|
|
2891
2892
|
// OpenAI
|
|
2892
|
-
'gpt-4.1'
|
|
2893
|
-
|
|
2894
|
-
|
|
2893
|
+
['gpt-4.1', 32768], ['gpt-4o', 16384], ['gpt-4-turbo', 4096], ['o3', 100000], ['o4-mini', 100000],
|
|
2894
|
+
// DeepSeek (8K standard mode — thinking mode allows 64K but we use standard)
|
|
2895
|
+
['deepseek', 8192],
|
|
2896
|
+
// Mistral
|
|
2897
|
+
['mistral-large', 32768], ['mistral-medium', 32768], ['mistral-small', 32768],
|
|
2898
|
+
// Meta Llama (served by Groq 32K, Together, Fireworks, Cerebras)
|
|
2899
|
+
['llama-3.3', 32768], ['llama-v3p3', 32768], ['llama-3.1', 32768], ['llama-v3p1', 32768],
|
|
2900
|
+
['llama-4', 32768], ['llama-3', 16384],
|
|
2901
|
+
// Zhipu / z.ai
|
|
2902
|
+
['glm-4', 16384], ['glm-3', 8192],
|
|
2903
|
+
];
|
|
2895
2904
|
const m = (model || '').toLowerCase();
|
|
2896
|
-
for (const [key, val] of
|
|
2905
|
+
for (const [key, val] of limits) {
|
|
2897
2906
|
if (m.includes(key)) return val;
|
|
2898
2907
|
}
|
|
2899
|
-
return
|
|
2908
|
+
return 8192; // conservative fallback — safe for all providers
|
|
2900
2909
|
}
|
|
2901
2910
|
|
|
2902
2911
|
async function callLlm(llmConfig, systemPrompt, userMessage) {
|
|
@@ -2904,6 +2913,11 @@ async function callLlm(llmConfig, systemPrompt, userMessage) {
|
|
|
2904
2913
|
if (!apiKey) return { error: `Missing API key: ${llmConfig.key}` };
|
|
2905
2914
|
const start = Date.now();
|
|
2906
2915
|
|
|
2916
|
+
// --timeout flag (seconds), default 180s (3 min)
|
|
2917
|
+
const timeoutArgIdx = process.argv.indexOf('--timeout');
|
|
2918
|
+
const timeoutSec = timeoutArgIdx !== -1 ? Math.max(30, Math.min(600, parseInt(process.argv[timeoutArgIdx + 1], 10) || 180)) : 180;
|
|
2919
|
+
const timeoutMs = timeoutSec * 1000;
|
|
2920
|
+
|
|
2907
2921
|
// Context window warning
|
|
2908
2922
|
const ctxCheck = checkContextLimit(llmConfig.model, systemPrompt, userMessage);
|
|
2909
2923
|
if (ctxCheck) {
|
|
@@ -2913,6 +2927,17 @@ async function callLlm(llmConfig, systemPrompt, userMessage) {
|
|
|
2913
2927
|
}
|
|
2914
2928
|
}
|
|
2915
2929
|
|
|
2930
|
+
// Live timer — updates every second while waiting for LLM
|
|
2931
|
+
let liveTimer = null;
|
|
2932
|
+
if (process.stdout.isTTY && !quietMode) {
|
|
2933
|
+
liveTimer = setInterval(() => {
|
|
2934
|
+
const secs = Math.round((Date.now() - start) / 1000);
|
|
2935
|
+
const remaining = timeoutSec - secs;
|
|
2936
|
+
const timerColor = remaining <= 30 ? c.yellow : c.dim;
|
|
2937
|
+
process.stdout.write(`\r ${stepProgress(4, 4)} Running LLM analysis ${c.dim}(${llmConfig.name})${c.reset} ${timerColor}${secs}s/${timeoutSec}s${c.reset} `);
|
|
2938
|
+
}, 1000);
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2916
2941
|
let _text = '';
|
|
2917
2942
|
try {
|
|
2918
2943
|
let data;
|
|
@@ -2921,7 +2946,7 @@ async function callLlm(llmConfig, systemPrompt, userMessage) {
|
|
|
2921
2946
|
method: 'POST',
|
|
2922
2947
|
headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'content-type': 'application/json' },
|
|
2923
2948
|
body: JSON.stringify({ model: llmConfig.model, max_tokens: getMaxOutputTokens(llmConfig.model), system: systemPrompt, messages: [{ role: 'user', content: userMessage }] }),
|
|
2924
|
-
signal: AbortSignal.timeout(
|
|
2949
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
2925
2950
|
});
|
|
2926
2951
|
data = await safeJsonParse(res, llmConfig);
|
|
2927
2952
|
if (data.error) {
|
|
@@ -2954,7 +2979,7 @@ async function callLlm(llmConfig, systemPrompt, userMessage) {
|
|
|
2954
2979
|
contents: [{ role: 'user', parts: [{ text: userMessage }] }],
|
|
2955
2980
|
generationConfig: { maxOutputTokens: getMaxOutputTokens(llmConfig.model), responseMimeType: 'application/json', thinkingConfig: { thinkingBudget: 8192 } },
|
|
2956
2981
|
}),
|
|
2957
|
-
signal: AbortSignal.timeout(
|
|
2982
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
2958
2983
|
});
|
|
2959
2984
|
data = await safeJsonParse(res, llmConfig);
|
|
2960
2985
|
if (data.error) {
|
|
@@ -2982,7 +3007,7 @@ async function callLlm(llmConfig, systemPrompt, userMessage) {
|
|
|
2982
3007
|
method: 'POST',
|
|
2983
3008
|
headers,
|
|
2984
3009
|
body: JSON.stringify({ model: llmConfig.model, max_tokens: getMaxOutputTokens(llmConfig.model), messages: [{ role: 'system', content: systemPrompt }, { role: 'user', content: userMessage }] }),
|
|
2985
|
-
signal: AbortSignal.timeout(
|
|
3010
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
2986
3011
|
});
|
|
2987
3012
|
data = await safeJsonParse(res, llmConfig);
|
|
2988
3013
|
if (data.error) {
|
|
@@ -3008,9 +3033,11 @@ async function callLlm(llmConfig, systemPrompt, userMessage) {
|
|
|
3008
3033
|
}
|
|
3009
3034
|
} catch (err) {
|
|
3010
3035
|
const dur = Date.now() - start;
|
|
3011
|
-
if (err.name === 'TimeoutError' || err.message?.includes('timeout')) return { error:
|
|
3036
|
+
if (err.name === 'TimeoutError' || err.message?.includes('timeout')) return { error: `Request timed out (${timeoutSec}s)`, hint: `Increase timeout: --timeout ${timeoutSec * 2}`, duration: dur };
|
|
3012
3037
|
if (err.code === 'ENOTFOUND' || err.code === 'ECONNREFUSED' || err.message?.includes('fetch failed')) return { error: `Network error: could not reach ${llmConfig.provider}`, hint: 'Check your internet connection', duration: dur };
|
|
3013
3038
|
return { error: err.message, duration: dur };
|
|
3039
|
+
} finally {
|
|
3040
|
+
if (liveTimer) clearInterval(liveTimer);
|
|
3014
3041
|
}
|
|
3015
3042
|
}
|
|
3016
3043
|
|
|
@@ -3818,14 +3845,16 @@ async function auditRepo(url) {
|
|
|
3818
3845
|
|
|
3819
3846
|
const llmResult = await callLlm(activeLlm, systemPrompt, userMessage);
|
|
3820
3847
|
|
|
3848
|
+
// Clear live timer line and print final status
|
|
3849
|
+
if (process.stdout.isTTY) process.stdout.write('\r\x1b[K');
|
|
3821
3850
|
if (llmResult.error) {
|
|
3822
|
-
console.log(` ${c.red}failed${c.reset}`);
|
|
3851
|
+
console.log(` ${stepProgress(4, 4)} Running LLM analysis ${c.dim}(${modelLabel})${c.reset} ${c.red}failed${c.reset} ${c.dim}(${elapsed(start)})${c.reset}`);
|
|
3823
3852
|
console.log(` ${c.red}${llmResult.error}${c.reset}`);
|
|
3824
3853
|
if (llmResult.hint) console.log(` ${c.dim}${llmResult.hint}${c.reset}`);
|
|
3825
3854
|
return null;
|
|
3826
3855
|
}
|
|
3827
3856
|
|
|
3828
|
-
console.log(` ${c.green}done${c.reset} ${c.dim}(${elapsed(start)})${c.reset}`);
|
|
3857
|
+
console.log(` ${stepProgress(4, 4)} Running LLM analysis ${c.dim}(${modelLabel})${c.reset} ${c.green}done${c.reset} ${c.dim}(${elapsed(start)})${c.reset}`);
|
|
3829
3858
|
|
|
3830
3859
|
if (llmResult.truncated) {
|
|
3831
3860
|
console.log();
|
|
@@ -5234,11 +5263,13 @@ async function main() {
|
|
|
5234
5263
|
// Strip global flags from args (including --model <value>, --format <value>)
|
|
5235
5264
|
const globalFlags = new Set(['--json', '--quiet', '-q', '--no-color', '--no-upload', '--remote']);
|
|
5236
5265
|
let args = rawArgs.filter(a => !globalFlags.has(a));
|
|
5237
|
-
// Remove --model <value
|
|
5266
|
+
// Remove --model <value>, --models <value>, --timeout <value> pairs
|
|
5238
5267
|
const modelIdx = args.indexOf('--model');
|
|
5239
5268
|
if (modelIdx !== -1) args.splice(modelIdx, 2);
|
|
5240
5269
|
const modelsIdx = args.indexOf('--models');
|
|
5241
5270
|
if (modelsIdx !== -1) args.splice(modelsIdx, 2);
|
|
5271
|
+
const timeoutIdx = args.indexOf('--timeout');
|
|
5272
|
+
if (timeoutIdx !== -1) args.splice(timeoutIdx, 2);
|
|
5242
5273
|
// Remove --format <value> pair
|
|
5243
5274
|
const formatIdx = args.indexOf('--format');
|
|
5244
5275
|
const formatFlag = formatIdx !== -1 ? args.splice(formatIdx, 2)[1] : null;
|
|
@@ -5314,6 +5345,7 @@ async function main() {
|
|
|
5314
5345
|
` <name> — specific model as verifier (e.g. sonnet)`,
|
|
5315
5346
|
` --no-verify Disable verification (even if default)`,
|
|
5316
5347
|
` --remote Use agentaudit.dev server (no LLM key needed, 3/day free)`,
|
|
5348
|
+
` --timeout <sec> LLM request timeout in seconds (default: 180, max: 600)`,
|
|
5317
5349
|
` --model <name> Override LLM model for this run`,
|
|
5318
5350
|
` --models <a,b,c> Multi-model audit (parallel calls, consensus comparison)`,
|
|
5319
5351
|
` --no-upload Skip uploading report to registry`,
|