legacyver 3.0.0 → 3.1.0

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.
Files changed (73) hide show
  1. package/bin/legacyver.js +6 -8
  2. package/legacyver-docs/OrderController.md +79 -79
  3. package/legacyver-docs/SUMMARY.md +2 -2
  4. package/legacyver-docs/bin/legacyver.md +107 -0
  5. package/legacyver-docs/index.md +15 -15
  6. package/legacyver-docs/src/api/auth.md +47 -0
  7. package/legacyver-docs/src/cache/hash.md +24 -0
  8. package/legacyver-docs/src/cache/index.md +112 -0
  9. package/legacyver-docs/src/cli/commands/analyze.md +58 -0
  10. package/legacyver-docs/src/cli/commands/cache.md +21 -0
  11. package/legacyver-docs/src/cli/commands/init.md +42 -0
  12. package/legacyver-docs/src/cli/commands/login.md +70 -0
  13. package/legacyver-docs/src/cli/commands/logout.md +26 -0
  14. package/legacyver-docs/src/cli/commands/providers.md +23 -0
  15. package/legacyver-docs/src/cli/commands/push.md +48 -0
  16. package/legacyver-docs/src/cli/commands/version.md +26 -0
  17. package/legacyver-docs/src/cli/ui.md +112 -0
  18. package/legacyver-docs/src/crawler/filters.md +54 -0
  19. package/legacyver-docs/src/crawler/index.md +54 -0
  20. package/legacyver-docs/src/crawler/manifest.md +22 -0
  21. package/legacyver-docs/src/crawler/walk.md +29 -0
  22. package/legacyver-docs/src/db/config.md +13 -0
  23. package/legacyver-docs/src/db/index.md +86 -0
  24. package/legacyver-docs/src/llm/chunker.md +28 -0
  25. package/legacyver-docs/src/llm/cost-estimator.md +62 -0
  26. package/legacyver-docs/src/llm/free-model.md +40 -0
  27. package/legacyver-docs/src/llm/index.md +29 -0
  28. package/legacyver-docs/src/llm/prompts.md +150 -0
  29. package/legacyver-docs/src/llm/providers/gemini.md +51 -0
  30. package/legacyver-docs/src/llm/providers/groq.md +76 -0
  31. package/legacyver-docs/src/llm/providers/kimi.md +48 -0
  32. package/legacyver-docs/src/llm/providers/ollama.md +50 -0
  33. package/legacyver-docs/src/llm/providers/openrouter.md +55 -0
  34. package/legacyver-docs/src/llm/queue.md +41 -0
  35. package/legacyver-docs/src/llm/re-prompter.md +33 -0
  36. package/legacyver-docs/src/llm/validator.md +34 -0
  37. package/legacyver-docs/src/parser/ast/generic.md +34 -0
  38. package/legacyver-docs/src/parser/ast/go.md +59 -0
  39. package/legacyver-docs/src/parser/ast/java.md +58 -0
  40. package/legacyver-docs/src/parser/ast/javascript.md +71 -0
  41. package/legacyver-docs/src/parser/ast/laravel/blade.md +45 -0
  42. package/legacyver-docs/src/parser/ast/laravel/classifier.md +29 -0
  43. package/legacyver-docs/src/parser/ast/laravel/controller.md +57 -0
  44. package/legacyver-docs/src/parser/ast/laravel/index.md +27 -0
  45. package/legacyver-docs/src/parser/ast/laravel/model.md +34 -0
  46. package/legacyver-docs/src/parser/ast/laravel/provider.md +31 -0
  47. package/legacyver-docs/src/parser/ast/laravel/routes.md +31 -0
  48. package/legacyver-docs/src/parser/ast/php.md +127 -0
  49. package/legacyver-docs/src/parser/ast/python.md +62 -0
  50. package/legacyver-docs/src/parser/ast/typescript.md +22 -0
  51. package/legacyver-docs/src/parser/body-extractor.md +34 -0
  52. package/legacyver-docs/src/parser/call-graph.md +45 -0
  53. package/legacyver-docs/src/parser/complexity-scorer.md +25 -0
  54. package/legacyver-docs/src/parser/index.md +59 -0
  55. package/legacyver-docs/src/parser/pattern-detector.md +28 -0
  56. package/legacyver-docs/src/parser/pkg-builder.md +34 -0
  57. package/legacyver-docs/src/renderer/html.md +36 -0
  58. package/legacyver-docs/src/renderer/index.md +26 -0
  59. package/legacyver-docs/src/renderer/json.md +25 -0
  60. package/legacyver-docs/src/renderer/markdown.md +77 -0
  61. package/legacyver-docs/src/utils/config.md +62 -0
  62. package/legacyver-docs/src/utils/errors.md +53 -0
  63. package/legacyver-docs/src/utils/logger.md +48 -0
  64. package/package.json +50 -51
  65. package/src/cli/commands/analyze.js +5 -5
  66. package/src/cli/commands/init.js +4 -4
  67. package/src/cli/commands/providers.js +3 -3
  68. package/src/llm/cost-estimator.js +2 -2
  69. package/src/llm/free-model.js +2 -2
  70. package/src/llm/index.js +2 -2
  71. package/src/llm/providers/openrouter.js +5 -2
  72. package/src/llm/validator.js +41 -2
  73. package/src/utils/config.js +1 -1
@@ -144,12 +144,12 @@ module.exports = async function analyzeCommand(target, flags) {
144
144
  provider = createProvider(config);
145
145
  } catch (e) {
146
146
  if (e.code === 'NO_API_KEY') {
147
- const providerName = (config.provider || 'groq').toLowerCase();
147
+ const providerName = (config.provider || 'openrouter').toLowerCase();
148
148
  const isGroq = providerName === 'groq';
149
149
  const isGemini = providerName === 'gemini';
150
150
  const isKimi = providerName === 'kimi';
151
151
  const isOpenRouter = providerName === 'openrouter';
152
- const label = isKimi ? 'Kimi (Moonshot)' : isGemini ? 'Google Gemini' : isOpenRouter ? 'OpenRouter' : 'Groq';
152
+ const label = isKimi ? 'Kimi (Moonshot)' : isGemini ? 'Google Gemini' : isGroq ? 'Groq' : 'OpenRouter';
153
153
  console.error(pc.red(`\n No API key found for ${label}.\n`));
154
154
  console.error(' To fix, choose one of:\n');
155
155
  if (isKimi) {
@@ -171,12 +171,12 @@ module.exports = async function analyzeCommand(target, flags) {
171
171
  console.error(' export OPENROUTER_API_KEY=your_key_here\n');
172
172
  console.error(' Get a free OpenRouter key at: https://openrouter.ai/keys\n');
173
173
  } else {
174
- // Default: Groq
174
+ // Default: OpenRouter
175
175
  console.error(pc.cyan(' 1. Run the setup wizard:'));
176
176
  console.error(' legacyver init\n');
177
177
  console.error(pc.cyan(' 2. Set an environment variable:'));
178
- console.error(' export GROQ_API_KEY=your_key_here\n');
179
- console.error(' Get a free Groq key at: https://console.groq.com/keys\n');
178
+ console.error(' export OPENROUTER_API_KEY=your_key_here\n');
179
+ console.error(' Get a free OpenRouter key at: https://openrouter.ai/keys\n');
180
180
  console.error(pc.cyan(' 3. Use Google Gemini instead (free, 15 req/min):'));
181
181
  console.error(' legacyver analyze --provider gemini\n');
182
182
  console.error(pc.cyan(' 4. Use Kimi (Moonshot) instead (free credits):'));
@@ -24,8 +24,8 @@ module.exports = async function initCommand() {
24
24
  }
25
25
  }
26
26
 
27
- const providerRaw = await ask(rl, `LLM provider [groq/gemini/kimi/openrouter/ollama] (default: groq): `);
28
- const providerChoice = providerRaw.trim() || 'groq';
27
+ const providerRaw = await ask(rl, `LLM provider [openrouter/groq/gemini/kimi/ollama] (default: openrouter): `);
28
+ const providerChoice = providerRaw.trim() || 'openrouter';
29
29
  const isOllama = providerChoice === 'ollama';
30
30
  const isGroq = providerChoice === 'groq';
31
31
  const isGemini = providerChoice === 'gemini';
@@ -39,7 +39,7 @@ module.exports = async function initCommand() {
39
39
  ? 'gemini-2.0-flash'
40
40
  : isKimi
41
41
  ? 'moonshot-v1-8k'
42
- : 'meta-llama/llama-3.3-70b-instruct:free';
42
+ : 'meta-llama/llama-3.1-8b-instruct'; // default: openrouter
43
43
 
44
44
  let apiKey = '';
45
45
  if (!isOllama) {
@@ -83,6 +83,6 @@ module.exports = async function initCommand() {
83
83
  ? 'legacyver analyze --provider gemini'
84
84
  : isKimi
85
85
  ? 'legacyver analyze --provider kimi'
86
- : 'legacyver analyze';
86
+ : 'legacyver analyze'; // openrouter is the default, no flag needed
87
87
  console.log(pc.cyan(`\nRun \`${exampleCmd}\` to generate documentation.`));
88
88
  };
@@ -4,7 +4,7 @@ const pc = require('picocolors');
4
4
  const logger = require('../../utils/logger');
5
5
 
6
6
  const RECOMMENDED_MODELS = [
7
- { id: 'meta-llama/llama-3.3-70b-instruct:free', context: '128k', inputCost: 0, outputCost: 0, free: true },
7
+ { id: 'meta-llama/llama-3.1-8b-instruct', context: '16k', inputCost: 0.02, outputCost: 0.05, free: false },
8
8
  { id: 'anthropic/claude-haiku-3-5', context: '200k', inputCost: 0.80, outputCost: 4.00, free: false },
9
9
  { id: 'anthropic/claude-sonnet-4-5', context: '200k', inputCost: 3.00, outputCost: 15.00, free: false },
10
10
  { id: 'openai/gpt-4o-mini', context: '128k', inputCost: 0.15, outputCost: 0.60, free: false },
@@ -30,7 +30,7 @@ module.exports = async function providersCommand() {
30
30
 
31
31
  console.log(pc.bold('Legacyver — Supported LLM Providers\n'));
32
32
 
33
- console.log(pc.bold('Groq') + pc.green(' [DEFAULT]') + ' (https://groq.com)');
33
+ console.log(pc.bold('Groq') + ' (https://groq.com)');
34
34
  console.log(' Fastest free LLM inference. 30 req/min, 14,400 req/day. Set GROQ_API_KEY env variable.');
35
35
  console.log(' Status: ' + (process.env.GROQ_API_KEY ? pc.green('API key detected') : pc.yellow('No API key found')));
36
36
  console.log(' Get a free key at: https://console.groq.com/keys');
@@ -45,7 +45,7 @@ module.exports = async function providersCommand() {
45
45
  console.log(' Status: ' + (process.env.MOONSHOT_API_KEY ? pc.green('API key detected') : pc.yellow('No API key found')));
46
46
  console.log(' Get a key at: https://platform.moonshot.cn/console/api-keys');
47
47
  console.log('');
48
- console.log(pc.bold('OpenRouter') + ' (https://openrouter.ai)');
48
+ console.log(pc.bold('OpenRouter') + pc.green(' [DEFAULT]') + ' (https://openrouter.ai)');
49
49
  console.log(' Unified gateway to 200+ models (Claude, GPT-4o, Llama, etc). Set OPENROUTER_API_KEY env variable.');
50
50
  console.log(' Status: ' + (process.env.OPENROUTER_API_KEY ? pc.green('API key detected') : pc.yellow('No API key found')));
51
51
  console.log(' Get a key at: https://openrouter.ai/keys');
@@ -25,7 +25,7 @@ let modelPricingCachedAt = 0;
25
25
  const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
26
26
 
27
27
  const FALLBACK_PRICING = {
28
- 'meta-llama/llama-3.3-70b-instruct:free': { input: 0, output: 0 },
28
+ 'meta-llama/llama-3.1-8b-instruct': { input: 0.02 / 1e6, output: 0.05 / 1e6 },
29
29
  'anthropic/claude-haiku-3-5': { input: 0.8 / 1e6, output: 4.0 / 1e6 },
30
30
  'anthropic/claude-sonnet-4-5': { input: 3.0 / 1e6, output: 15.0 / 1e6 },
31
31
  'openai/gpt-4o-mini': { input: 0.15 / 1e6, output: 0.6 / 1e6 },
@@ -64,7 +64,7 @@ async function fetchModelPricing() {
64
64
  * @returns {Promise<{totalInputTokens, totalOutputTokens, estimatedCostUSD, modelId}>}
65
65
  */
66
66
  async function estimateCost(chunks, config) {
67
- const modelId = config.model || 'meta-llama/llama-3.3-70b-instruct:free';
67
+ const modelId = config.model || 'meta-llama/llama-3.1-8b-instruct';
68
68
  const pricing = await fetchModelPricing();
69
69
  const modelPricing = pricing[modelId] || { input: 0, output: 0 };
70
70
 
@@ -9,7 +9,7 @@ const pc = require('picocolors');
9
9
  * @returns {Object} mutated config
10
10
  */
11
11
  function applyFreeModelPolicy(config) {
12
- const provider = (config.provider || 'groq').toLowerCase();
12
+ const provider = (config.provider || 'openrouter').toLowerCase();
13
13
 
14
14
  // Ollama, Groq, Gemini, and Kimi are always free — skip openrouter-specific logic
15
15
  if (provider === 'ollama' || provider === 'groq' || provider === 'gemini' || provider === 'kimi') {
@@ -45,7 +45,7 @@ function applyFreeModelPolicy(config) {
45
45
  return config;
46
46
  }
47
47
 
48
- const model = config.model || 'meta-llama/llama-3.3-70b-instruct:free';
48
+ const model = config.model || 'meta-llama/llama-3.1-8b-instruct:free';
49
49
  if (!model.endsWith(':free')) {
50
50
  config.isFreeModel = false;
51
51
  return config;
package/src/llm/index.js CHANGED
@@ -12,9 +12,10 @@ const { KimiProvider } = require('./providers/kimi');
12
12
  * @returns {OpenRouterProvider|OllamaProvider|GroqProvider|GeminiProvider|KimiProvider}
13
13
  */
14
14
  function createProvider(config) {
15
- const provider = (config.provider || 'groq').toLowerCase();
15
+ const provider = (config.provider || 'openrouter').toLowerCase();
16
16
  switch (provider) {
17
17
  case 'openrouter':
18
+ default:
18
19
  return new OpenRouterProvider(config);
19
20
  case 'ollama':
20
21
  return new OllamaProvider(config);
@@ -23,7 +24,6 @@ function createProvider(config) {
23
24
  case 'kimi':
24
25
  return new KimiProvider(config);
25
26
  case 'groq':
26
- default:
27
27
  return new GroqProvider(config);
28
28
  }
29
29
  }
@@ -3,11 +3,14 @@
3
3
  const { NoApiKeyError, RateLimitError } = require('../../utils/errors');
4
4
  const logger = require('../../utils/logger');
5
5
 
6
- const DEFAULT_MODEL = 'meta-llama/llama-3.3-70b-instruct:free';
6
+ const DEFAULT_MODEL = 'meta-llama/llama-3.1-8b-instruct';
7
+ // Built-in shared key — lets users run legacyver out of the box without setup.
8
+ // Users can override with their own OPENROUTER_API_KEY env var for higher rate limits.
9
+ const BUILT_IN_KEY = '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';
7
10
 
8
11
  class OpenRouterProvider {
9
12
  constructor(config) {
10
- this.apiKey = process.env.OPENROUTER_API_KEY || config.apiKey;
13
+ this.apiKey = process.env.OPENROUTER_API_KEY || config.apiKey || BUILT_IN_KEY;
11
14
  if (!this.apiKey) {
12
15
  throw new NoApiKeyError('openrouter');
13
16
  }
@@ -40,9 +40,48 @@ function validateFragment(fragment, fileFacts) {
40
40
  for (const exp of (fileFacts.exports || [])) knownIdentifiers.add(exp);
41
41
 
42
42
  // Common words to skip (not identifiers)
43
- const stopWords = new Set(['The', 'This', 'File', 'Function', 'Functions', 'Class', 'Method', 'Returns', 'Return', 'Parameter', 'Parameters', 'Param', 'Import', 'Export', 'Overview', 'Usage', 'Example', 'Dependencies', 'Dependency', 'Async', 'Static', 'Public', 'Private', 'Protected', 'Boolean', 'String', 'Number', 'Object', 'Array', 'Void', 'Null', 'Undefined', 'True', 'False', 'Error', 'Promise', 'Request', 'Response', 'Node', 'JavaScript', 'TypeScript', 'PHP', 'Python', 'Laravel', 'Express', 'Route', 'Controller', 'Model', 'Service', 'Repository', 'Middleware', 'Provider', 'Summary', 'None', 'Name', 'Description', 'Value', 'Type', 'Map', 'Set', 'Date', 'Creates', 'Create', 'Retrieves', 'Retrieve', 'Updates', 'Update', 'Deletes', 'Delete', 'Validates', 'Validate', 'Destroys', 'Destroy', 'Returns', 'Return', 'Gets', 'Get', 'Sets', 'Set', 'Checks', 'Check', 'Handles', 'Handle', 'Builds', 'Build', 'Loads', 'Load', 'Saves', 'Save', 'Sends', 'Send', 'Reads', 'Read', 'Writes', 'Write', 'Parses', 'Parse', 'Formats', 'Format', 'Converts', 'Convert', 'Generates', 'Generate', 'Initializes', 'Initialize', 'Registers', 'Register', 'Removes', 'Remove', 'Adds', 'Add', 'Lists', 'List', 'Fetches', 'Fetch', 'Renders', 'Render', 'Runs', 'Run', 'Starts', 'Start', 'Stops', 'Stop', 'Optional', 'Required', 'Default', 'Properties', 'Methods', 'Fields', 'Attributes', 'Throws', 'Emits', 'For', 'With', 'From', 'Into', 'Upon', 'When', 'After', 'Before', 'During', 'John', 'Jane', 'Doe', 'Example', 'New', 'Old', 'Current', 'Previous', 'Next', 'First', 'Last', 'All', 'Each', 'Every', 'Any', 'Given', 'Note', 'See', 'Also', 'More', 'Less', 'Here', 'There', 'Where', 'How', 'What', 'Which', 'Such', 'Like', 'Used', 'Uses', 'Using']);
43
+ const stopWords = new Set([
44
+ // General English prose words
45
+ 'The', 'This', 'File', 'Function', 'Functions', 'Class', 'Method', 'Returns', 'Return',
46
+ 'Parameter', 'Parameters', 'Param', 'Import', 'Export', 'Overview', 'Usage', 'Example',
47
+ 'Dependencies', 'Dependency', 'Async', 'Static', 'Public', 'Private', 'Protected',
48
+ 'Boolean', 'String', 'Number', 'Object', 'Array', 'Void', 'Null', 'Undefined',
49
+ 'True', 'False', 'Error', 'Promise', 'Request', 'Response',
50
+ 'Node', 'JavaScript', 'TypeScript', 'PHP', 'Python',
51
+ 'Laravel', 'Express', 'Route', 'Controller', 'Model', 'Service', 'Repository',
52
+ 'Middleware', 'Provider', 'Summary', 'None', 'Name', 'Description', 'Value', 'Type',
53
+ 'Map', 'Set', 'Date',
54
+ 'Creates', 'Create', 'Retrieves', 'Retrieve', 'Updates', 'Update', 'Deletes', 'Delete',
55
+ 'Validates', 'Validate', 'Destroys', 'Destroy', 'Gets', 'Get', 'Sets', 'Checks', 'Check',
56
+ 'Handles', 'Handle', 'Builds', 'Build', 'Loads', 'Load', 'Saves', 'Save',
57
+ 'Sends', 'Send', 'Reads', 'Read', 'Writes', 'Write', 'Parses', 'Parse',
58
+ 'Formats', 'Format', 'Converts', 'Convert', 'Generates', 'Generate',
59
+ 'Initializes', 'Initialize', 'Registers', 'Register', 'Removes', 'Remove',
60
+ 'Adds', 'Add', 'Lists', 'List', 'Fetches', 'Fetch', 'Renders', 'Render',
61
+ 'Runs', 'Run', 'Starts', 'Start', 'Stops', 'Stop', 'Computes', 'Compute',
62
+ 'Optional', 'Required', 'Default', 'Properties', 'Methods', 'Fields', 'Attributes',
63
+ 'Throws', 'Emits', 'For', 'With', 'From', 'Into', 'Upon', 'When', 'After', 'Before',
64
+ 'During', 'John', 'Jane', 'Doe', 'New', 'Old', 'Current', 'Previous', 'Next',
65
+ 'First', 'Last', 'All', 'Each', 'Every', 'Any', 'Given', 'Note', 'See', 'Also',
66
+ 'More', 'Less', 'Here', 'There', 'Where', 'How', 'What', 'Which', 'Such', 'Like',
67
+ 'Used', 'Uses', 'Using', 'Analyzing', 'Confirmed', 'Interactive', 'Manually',
68
+ 'Asynchronously', 'Concurrently', 'Automatically', 'Internally',
69
+ // Common technical acronyms / uppercase terms safe to appear in prose docs
70
+ 'SHA', 'MD', 'AES', 'RSA', 'CLI', 'API', 'LLM', 'AST', 'PKG', 'JSON', 'XML',
71
+ 'CSV', 'HTML', 'CSS', 'URL', 'URI', 'UUID', 'JWT', 'ISO', 'UTC', 'ENV',
72
+ 'SDK', 'SPA', 'SSR', 'CDN', 'AWS', 'GCP', 'SQL', 'ORM', 'MVC', 'MVP',
73
+ 'HTTP', 'HTTPS', 'REST', 'RPC', 'TCP', 'UDP', 'DNS', 'SSL', 'TLS',
74
+ 'CPU', 'RAM', 'GPU', 'EOF', 'EOL', 'CRLF', 'NaN', 'Inf',
75
+ // Common doc section words
76
+ 'Docs', 'Markdown', 'Readme', 'Changelog', 'License', 'Contributing',
77
+ // Words from description prose commonly flagged incorrectly
78
+ 'Only', 'Skip', 'Output', 'Input', 'Done', 'Log', 'Path', 'Hash',
79
+ 'Concurrent', 'Manage', 'Analyze', 'Compute', 'Concurrent',
80
+ ]);
44
81
 
45
- const capitalizedIdentifiers = outputText.match(/\b([A-Z][a-zA-Z]{2,})\b/g) || [];
82
+ // Only flag compound PascalCase identifiers (e.g. MyClass, buildPKG),
83
+ // NOT plain Title-case prose words or uppercase acronyms.
84
+ const capitalizedIdentifiers = outputText.match(/\b([A-Z][a-z]+(?:[A-Z][a-zA-Z0-9]*)+)\b/g) || [];
46
85
  for (const identifier of capitalizedIdentifiers) {
47
86
  if (stopWords.has(identifier)) continue;
48
87
  if (!knownIdentifiers.has(identifier)) {
@@ -59,7 +59,7 @@ function loadConfig(cliFlags = {}) {
59
59
  }
60
60
 
61
61
  const defaults = {
62
- provider: 'groq',
62
+ provider: 'openrouter',
63
63
  model: undefined,
64
64
  format: 'markdown',
65
65
  out: './legacyver-docs',