agentaudit 3.9.21 → 3.9.22
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 +116 -6
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -1631,7 +1631,7 @@ async function auditRepo(url) {
|
|
|
1631
1631
|
|
|
1632
1632
|
// ── Check command ───────────────────────────────────────
|
|
1633
1633
|
|
|
1634
|
-
async function checkPackage(name) {
|
|
1634
|
+
async function checkPackage(name, { autoAudit = false } = {}) {
|
|
1635
1635
|
if (!jsonMode) {
|
|
1636
1636
|
console.log(`${icons.info} Looking up ${c.bold}${name}${c.reset} in registry...`);
|
|
1637
1637
|
console.log();
|
|
@@ -1640,8 +1640,8 @@ async function checkPackage(name) {
|
|
|
1640
1640
|
const data = await checkRegistry(name);
|
|
1641
1641
|
if (!data) {
|
|
1642
1642
|
if (!jsonMode) {
|
|
1643
|
-
//
|
|
1644
|
-
if (name.includes('github.com') || name.includes('://')) {
|
|
1643
|
+
// Auto-audit: only when called from 'check' command AND input looks like a URL
|
|
1644
|
+
if (autoAudit && (name.includes('github.com') || name.includes('://'))) {
|
|
1645
1645
|
console.log(` ${c.yellow}Not found in registry.${c.reset}`);
|
|
1646
1646
|
console.log(` ${c.dim}Starting audit for ${name}...${c.reset}`);
|
|
1647
1647
|
console.log();
|
|
@@ -1650,7 +1650,8 @@ async function checkPackage(name) {
|
|
|
1650
1650
|
console.log(` ${c.yellow}✖ Not found${c.reset} — "${name}" hasn't been audited yet.`);
|
|
1651
1651
|
console.log();
|
|
1652
1652
|
console.log(` ${c.dim}Next steps:${c.reset}`);
|
|
1653
|
-
console.log(` ${c.cyan}agentaudit
|
|
1653
|
+
console.log(` ${c.cyan}agentaudit check <repo-url>${c.reset} ${c.dim}Auto-lookup + audit if not found${c.reset}`);
|
|
1654
|
+
console.log(` ${c.cyan}agentaudit audit <repo-url>${c.reset} ${c.dim}Deep LLM audit${c.reset}`);
|
|
1654
1655
|
console.log(` ${c.cyan}agentaudit scan <repo-url>${c.reset} ${c.dim}Quick static check (no API key)${c.reset}`);
|
|
1655
1656
|
}
|
|
1656
1657
|
return null;
|
|
@@ -1774,6 +1775,7 @@ async function main() {
|
|
|
1774
1775
|
console.log(` ${c.bold}SETUP${c.reset}`);
|
|
1775
1776
|
console.log(` ${c.cyan}status${c.reset} Check providers & API keys`);
|
|
1776
1777
|
console.log(` ${c.cyan}setup${c.reset} Register & configure`);
|
|
1778
|
+
console.log(` ${c.cyan}models${c.reset} List available LLM models`);
|
|
1777
1779
|
console.log(` ${c.cyan}config set${c.reset} <key> <value> Set default provider/options`);
|
|
1778
1780
|
console.log();
|
|
1779
1781
|
console.log(` ${c.bold}OPTIONS${c.reset}`);
|
|
@@ -1910,6 +1912,113 @@ async function main() {
|
|
|
1910
1912
|
return;
|
|
1911
1913
|
}
|
|
1912
1914
|
|
|
1915
|
+
if (command === 'models') {
|
|
1916
|
+
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
1917
|
+
const openaiKey = process.env.OPENAI_API_KEY;
|
|
1918
|
+
const openrouterKey = process.env.OPENROUTER_API_KEY;
|
|
1919
|
+
|
|
1920
|
+
console.log(` ${c.bold}Available models by provider:${c.reset}`);
|
|
1921
|
+
console.log();
|
|
1922
|
+
|
|
1923
|
+
// Static lists for Anthropic (no list API)
|
|
1924
|
+
console.log(` ${c.bold}Anthropic${c.reset}${anthropicKey ? ` ${c.green}(configured)${c.reset}` : ` ${c.dim}(not configured)${c.reset}`}`);
|
|
1925
|
+
console.log(` ${c.dim}claude-sonnet-4-20250514${c.reset} ${c.dim}(default)${c.reset}`);
|
|
1926
|
+
console.log(` ${c.dim}claude-opus-4-20250514${c.reset}`);
|
|
1927
|
+
console.log(` ${c.dim}claude-haiku-3-20250514${c.reset}`);
|
|
1928
|
+
console.log();
|
|
1929
|
+
|
|
1930
|
+
// Static list for OpenAI
|
|
1931
|
+
console.log(` ${c.bold}OpenAI${c.reset}${openaiKey ? ` ${c.green}(configured)${c.reset}` : ` ${c.dim}(not configured)${c.reset}`}`);
|
|
1932
|
+
console.log(` ${c.dim}gpt-4o${c.reset} ${c.dim}(default)${c.reset}`);
|
|
1933
|
+
console.log(` ${c.dim}gpt-4o-mini${c.reset}`);
|
|
1934
|
+
console.log(` ${c.dim}gpt-4.1${c.reset}`);
|
|
1935
|
+
console.log(` ${c.dim}gpt-4.1-mini${c.reset}`);
|
|
1936
|
+
console.log(` ${c.dim}o3${c.reset}`);
|
|
1937
|
+
console.log(` ${c.dim}o4-mini${c.reset}`);
|
|
1938
|
+
console.log();
|
|
1939
|
+
|
|
1940
|
+
// OpenRouter — fetch from API
|
|
1941
|
+
console.log(` ${c.bold}OpenRouter${c.reset}${openrouterKey ? ` ${c.green}(configured)${c.reset}` : ` ${c.dim}(not configured)${c.reset}`}`);
|
|
1942
|
+
if (openrouterKey || targets.includes('--all')) {
|
|
1943
|
+
process.stdout.write(` ${c.dim}Fetching models...${c.reset}`);
|
|
1944
|
+
try {
|
|
1945
|
+
const res = await fetch('https://openrouter.ai/api/v1/models', {
|
|
1946
|
+
headers: openrouterKey ? { 'Authorization': `Bearer ${openrouterKey}` } : {},
|
|
1947
|
+
signal: AbortSignal.timeout(10_000),
|
|
1948
|
+
});
|
|
1949
|
+
const data = await res.json();
|
|
1950
|
+
const models = (data.data || [])
|
|
1951
|
+
.filter(m => m.id && !m.id.includes(':free') && !m.id.includes('/extended'))
|
|
1952
|
+
.sort((a, b) => (a.id || '').localeCompare(b.id || ''));
|
|
1953
|
+
|
|
1954
|
+
// Group by provider prefix
|
|
1955
|
+
const groups = {};
|
|
1956
|
+
for (const m of models) {
|
|
1957
|
+
const [prefix] = m.id.split('/');
|
|
1958
|
+
if (!groups[prefix]) groups[prefix] = [];
|
|
1959
|
+
groups[prefix].push(m);
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
// Show popular ones first
|
|
1963
|
+
const popular = ['anthropic', 'openai', 'google', 'meta-llama', 'mistralai', 'deepseek'];
|
|
1964
|
+
const shown = new Set();
|
|
1965
|
+
process.stdout.write(`\r ${c.green}${models.length} models available${c.reset} \n`);
|
|
1966
|
+
console.log();
|
|
1967
|
+
|
|
1968
|
+
for (const prefix of popular) {
|
|
1969
|
+
if (!groups[prefix]) continue;
|
|
1970
|
+
shown.add(prefix);
|
|
1971
|
+
console.log(` ${c.bold}${prefix}${c.reset}`);
|
|
1972
|
+
for (const m of groups[prefix].slice(0, 5)) {
|
|
1973
|
+
console.log(` ${c.dim}${m.id}${c.reset}`);
|
|
1974
|
+
}
|
|
1975
|
+
if (groups[prefix].length > 5) {
|
|
1976
|
+
console.log(` ${c.dim}... and ${groups[prefix].length - 5} more${c.reset}`);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
const otherCount = Object.keys(groups).filter(k => !shown.has(k)).length;
|
|
1981
|
+
if (otherCount > 0) {
|
|
1982
|
+
console.log();
|
|
1983
|
+
console.log(` ${c.dim}+ ${otherCount} more providers. Use --model=<provider/model>${c.reset}`);
|
|
1984
|
+
console.log(` ${c.dim}Full list: https://openrouter.ai/models${c.reset}`);
|
|
1985
|
+
}
|
|
1986
|
+
} catch (e) {
|
|
1987
|
+
process.stdout.write(`\r ${c.red}Failed to fetch: ${e.message}${c.reset} \n`);
|
|
1988
|
+
}
|
|
1989
|
+
} else {
|
|
1990
|
+
console.log(` ${c.dim}anthropic/claude-sonnet-4${c.reset} ${c.dim}(default)${c.reset}`);
|
|
1991
|
+
console.log(` ${c.dim}Set OPENROUTER_API_KEY to see all ${c.bold}200+${c.reset}${c.dim} models${c.reset}`);
|
|
1992
|
+
console.log(` ${c.dim}Or browse: https://openrouter.ai/models${c.reset}`);
|
|
1993
|
+
}
|
|
1994
|
+
console.log();
|
|
1995
|
+
|
|
1996
|
+
// Ollama
|
|
1997
|
+
const ollamaModel = process.env.OLLAMA_MODEL;
|
|
1998
|
+
const ollamaHost = process.env.OLLAMA_HOST || 'http://localhost:11434';
|
|
1999
|
+
console.log(` ${c.bold}Ollama${c.reset}${ollamaModel ? ` ${c.green}(configured: ${ollamaModel})${c.reset}` : ` ${c.dim}(not configured)${c.reset}`}`);
|
|
2000
|
+
if (ollamaModel || process.env.OLLAMA_HOST) {
|
|
2001
|
+
try {
|
|
2002
|
+
const res = await fetch(`${ollamaHost}/api/tags`, { signal: AbortSignal.timeout(5_000) });
|
|
2003
|
+
const data = await res.json();
|
|
2004
|
+
for (const m of (data.models || []).slice(0, 10)) {
|
|
2005
|
+
console.log(` ${c.dim}${m.name}${c.reset}`);
|
|
2006
|
+
}
|
|
2007
|
+
} catch {
|
|
2008
|
+
console.log(` ${c.dim}(Ollama not running at ${ollamaHost})${c.reset}`);
|
|
2009
|
+
}
|
|
2010
|
+
} else {
|
|
2011
|
+
console.log(` ${c.dim}Set OLLAMA_MODEL to use local models${c.reset}`);
|
|
2012
|
+
}
|
|
2013
|
+
console.log();
|
|
2014
|
+
|
|
2015
|
+
console.log(` ${c.bold}Set model:${c.reset}`);
|
|
2016
|
+
console.log(` ${c.cyan}agentaudit config set model <name>${c.reset}`);
|
|
2017
|
+
console.log(` ${c.cyan}agentaudit audit <url> --model <name>${c.reset}`);
|
|
2018
|
+
console.log(` ${c.dim}Or env: AGENTAUDIT_MODEL=<name>${c.reset}`);
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
2021
|
+
|
|
1913
2022
|
if (command === 'config') {
|
|
1914
2023
|
const subCmd = targets[0];
|
|
1915
2024
|
if (subCmd === 'set' && targets[1] === 'provider' && targets[2]) {
|
|
@@ -1961,8 +2070,9 @@ async function main() {
|
|
|
1961
2070
|
return;
|
|
1962
2071
|
}
|
|
1963
2072
|
const results = [];
|
|
2073
|
+
const allowAutoAudit = command === 'check'; // only 'check' auto-audits, 'lookup' never does
|
|
1964
2074
|
for (const t of names) {
|
|
1965
|
-
const data = await checkPackage(t);
|
|
2075
|
+
const data = await checkPackage(t, { autoAudit: allowAutoAudit });
|
|
1966
2076
|
results.push(data);
|
|
1967
2077
|
}
|
|
1968
2078
|
if (jsonMode) {
|
|
@@ -2033,7 +2143,7 @@ async function main() {
|
|
|
2033
2143
|
}
|
|
2034
2144
|
|
|
2035
2145
|
// Typo correction via Levenshtein distance
|
|
2036
|
-
const knownCommands = ['discover', 'scan', 'audit', 'check', 'lookup', 'status', 'setup', 'config'];
|
|
2146
|
+
const knownCommands = ['discover', 'scan', 'audit', 'check', 'lookup', 'status', 'setup', 'config', 'models'];
|
|
2037
2147
|
const suggestion = knownCommands
|
|
2038
2148
|
.map(cmd => ({ cmd, dist: levenshtein(command, cmd) }))
|
|
2039
2149
|
.filter(x => x.dist <= 3)
|