legacyver 2.1.0 → 2.1.2
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/.agent/skills/openspec-apply-change/SKILL.md +156 -0
- package/.agent/skills/openspec-archive-change/SKILL.md +114 -0
- package/.agent/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.agent/skills/openspec-continue-change/SKILL.md +118 -0
- package/.agent/skills/openspec-explore/SKILL.md +290 -0
- package/.agent/skills/openspec-ff-change/SKILL.md +101 -0
- package/.agent/skills/openspec-new-change/SKILL.md +74 -0
- package/.agent/skills/openspec-onboard/SKILL.md +529 -0
- package/.agent/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.agent/skills/openspec-verify-change/SKILL.md +168 -0
- package/.agent/workflows/opsx-apply.md +149 -0
- package/.agent/workflows/opsx-archive.md +154 -0
- package/.agent/workflows/opsx-bulk-archive.md +239 -0
- package/.agent/workflows/opsx-continue.md +111 -0
- package/.agent/workflows/opsx-explore.md +171 -0
- package/.agent/workflows/opsx-ff.md +91 -0
- package/.agent/workflows/opsx-new.md +66 -0
- package/.agent/workflows/opsx-onboard.md +522 -0
- package/.agent/workflows/opsx-sync.md +131 -0
- package/.agent/workflows/opsx-verify.md +161 -0
- package/.github/prompts/opsx-apply.prompt.md +149 -0
- package/.github/prompts/opsx-archive.prompt.md +154 -0
- package/.github/prompts/opsx-bulk-archive.prompt.md +239 -0
- package/.github/prompts/opsx-continue.prompt.md +111 -0
- package/.github/prompts/opsx-explore.prompt.md +171 -0
- package/.github/prompts/opsx-ff.prompt.md +91 -0
- package/.github/prompts/opsx-new.prompt.md +66 -0
- package/.github/prompts/opsx-onboard.prompt.md +522 -0
- package/.github/prompts/opsx-sync.prompt.md +131 -0
- package/.github/prompts/opsx-verify.prompt.md +161 -0
- package/.github/skills/openspec-apply-change/SKILL.md +156 -0
- package/.github/skills/openspec-archive-change/SKILL.md +114 -0
- package/.github/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.github/skills/openspec-continue-change/SKILL.md +118 -0
- package/.github/skills/openspec-explore/SKILL.md +290 -0
- package/.github/skills/openspec-ff-change/SKILL.md +101 -0
- package/.github/skills/openspec-new-change/SKILL.md +74 -0
- package/.github/skills/openspec-onboard/SKILL.md +529 -0
- package/.github/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.github/skills/openspec-verify-change/SKILL.md +168 -0
- package/.legacyverignore.example +43 -0
- package/.legacyverrc +7 -0
- package/.opencode/command/opsx-apply.md +149 -0
- package/.opencode/command/opsx-archive.md +154 -0
- package/.opencode/command/opsx-bulk-archive.md +239 -0
- package/.opencode/command/opsx-continue.md +111 -0
- package/.opencode/command/opsx-explore.md +171 -0
- package/.opencode/command/opsx-ff.md +91 -0
- package/.opencode/command/opsx-new.md +66 -0
- package/.opencode/command/opsx-onboard.md +522 -0
- package/.opencode/command/opsx-sync.md +131 -0
- package/.opencode/command/opsx-verify.md +161 -0
- package/.opencode/skills/openspec-apply-change/SKILL.md +156 -0
- package/.opencode/skills/openspec-archive-change/SKILL.md +114 -0
- package/.opencode/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.opencode/skills/openspec-continue-change/SKILL.md +118 -0
- package/.opencode/skills/openspec-explore/SKILL.md +290 -0
- package/.opencode/skills/openspec-ff-change/SKILL.md +101 -0
- package/.opencode/skills/openspec-new-change/SKILL.md +74 -0
- package/.opencode/skills/openspec-onboard/SKILL.md +529 -0
- package/.opencode/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.opencode/skills/openspec-verify-change/SKILL.md +168 -0
- package/LICENSE +1 -1
- package/README.md +128 -83
- package/bin/legacyver.js +48 -25
- package/legacyver-docs/SUMMARY.md +3 -0
- package/legacyver-docs/components.md +57 -0
- package/legacyver-docs/index.md +15 -0
- package/nul +2 -0
- package/package.json +23 -25
- package/src/cache/hash.js +9 -10
- package/src/cache/index.js +43 -65
- package/src/cli/commands/analyze.js +212 -190
- package/src/cli/commands/cache.js +15 -35
- package/src/cli/commands/init.js +63 -107
- package/src/cli/commands/providers.js +56 -81
- package/src/cli/commands/version.js +7 -10
- package/src/cli/ui.js +58 -77
- package/src/crawler/filters.js +41 -40
- package/src/crawler/index.js +52 -36
- package/src/crawler/manifest.js +31 -43
- package/src/crawler/walk.js +32 -38
- package/src/llm/chunker.js +34 -56
- package/src/llm/cost-estimator.js +68 -51
- package/src/llm/free-model.js +67 -0
- package/src/llm/index.js +22 -43
- package/src/llm/prompts.js +45 -33
- package/src/llm/providers/gemini.js +94 -0
- package/src/llm/providers/groq.js +55 -40
- package/src/llm/providers/ollama.js +38 -65
- package/src/llm/providers/openrouter.js +67 -0
- package/src/llm/queue.js +59 -88
- package/src/llm/re-prompter.js +41 -0
- package/src/llm/validator.js +72 -0
- package/src/parser/ast/generic.js +45 -222
- package/src/parser/ast/go.js +86 -205
- package/src/parser/ast/java.js +76 -146
- package/src/parser/ast/javascript.js +173 -241
- package/src/parser/ast/laravel/blade.js +56 -0
- package/src/parser/ast/laravel/classifier.js +30 -0
- package/src/parser/ast/laravel/controller.js +35 -0
- package/src/parser/ast/laravel/index.js +54 -0
- package/src/parser/ast/laravel/model.js +41 -0
- package/src/parser/ast/laravel/provider.js +28 -0
- package/src/parser/ast/laravel/routes.js +45 -0
- package/src/parser/ast/php.js +129 -0
- package/src/parser/ast/python.js +76 -199
- package/src/parser/ast/typescript.js +10 -244
- package/src/parser/body-extractor.js +40 -0
- package/src/parser/call-graph.js +50 -67
- package/src/parser/complexity-scorer.js +59 -0
- package/src/parser/index.js +61 -86
- package/src/parser/pattern-detector.js +71 -0
- package/src/parser/pkg-builder.js +36 -83
- package/src/renderer/html.js +63 -135
- package/src/renderer/index.js +23 -35
- package/src/renderer/json.js +17 -35
- package/src/renderer/markdown.js +83 -117
- package/src/utils/config.js +52 -53
- package/src/utils/errors.js +26 -41
- package/src/utils/logger.js +32 -53
- package/src/cli/flags.js +0 -87
- package/src/llm/providers/anthropic.js +0 -57
- package/src/llm/providers/google.js +0 -65
- package/src/llm/providers/openai.js +0 -52
- package/src/parser/ast/tree-sitter-init.js +0 -80
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Anthropic LLM provider adapter.
|
|
3
|
-
* Uses @anthropic-ai/sdk.
|
|
4
|
-
* Default model: claude-haiku-3-5.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import Anthropic from '@anthropic-ai/sdk';
|
|
8
|
-
import { NoApiKeyError, RateLimitError } from '../../utils/errors.js';
|
|
9
|
-
|
|
10
|
-
export class AnthropicProvider {
|
|
11
|
-
constructor(config = {}) {
|
|
12
|
-
this.name = 'anthropic';
|
|
13
|
-
this.model = config.model || 'claude-3-5-haiku-latest';
|
|
14
|
-
|
|
15
|
-
const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
16
|
-
if (!apiKey) {
|
|
17
|
-
throw new NoApiKeyError('anthropic');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
this.client = new Anthropic({ apiKey });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Send a completion request.
|
|
25
|
-
* @param {object} request - { systemPrompt, userMessage }
|
|
26
|
-
* @returns {Promise<{ content: string, tokensUsed: { input: number, output: number } }>}
|
|
27
|
-
*/
|
|
28
|
-
async complete(request) {
|
|
29
|
-
try {
|
|
30
|
-
const response = await this.client.messages.create({
|
|
31
|
-
model: this.model,
|
|
32
|
-
max_tokens: 4096,
|
|
33
|
-
system: request.systemPrompt,
|
|
34
|
-
messages: [
|
|
35
|
-
{ role: 'user', content: request.userMessage },
|
|
36
|
-
],
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
content: response.content[0].text,
|
|
41
|
-
tokensUsed: {
|
|
42
|
-
input: response.usage.input_tokens,
|
|
43
|
-
output: response.usage.output_tokens,
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
} catch (err) {
|
|
47
|
-
if (err.status === 429) {
|
|
48
|
-
throw new RateLimitError('anthropic', err.headers?.['retry-after'] * 1000);
|
|
49
|
-
}
|
|
50
|
-
throw err;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
estimateCost(inputTokens, outputTokens) {
|
|
55
|
-
return (inputTokens * 0.00025 + outputTokens * 0.00125) / 1000;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Google AI LLM provider adapter.
|
|
3
|
-
* Uses @google/generative-ai SDK.
|
|
4
|
-
* Default model: gemini-1.5-flash.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { GoogleGenerativeAI } from '@google/generative-ai';
|
|
8
|
-
import { NoApiKeyError, RateLimitError } from '../../utils/errors.js';
|
|
9
|
-
|
|
10
|
-
export class GoogleProvider {
|
|
11
|
-
constructor(config = {}) {
|
|
12
|
-
this.name = 'google';
|
|
13
|
-
this.model = config.model || 'gemini-1.5-flash';
|
|
14
|
-
|
|
15
|
-
const apiKey = config.apiKey || process.env.GOOGLE_API_KEY;
|
|
16
|
-
if (!apiKey) {
|
|
17
|
-
throw new NoApiKeyError('google');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
this.genAI = new GoogleGenerativeAI(apiKey);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async complete(request) {
|
|
24
|
-
try {
|
|
25
|
-
const model = this.genAI.getGenerativeModel({ model: this.model });
|
|
26
|
-
|
|
27
|
-
const result = await model.generateContent({
|
|
28
|
-
contents: [
|
|
29
|
-
{
|
|
30
|
-
role: 'user',
|
|
31
|
-
parts: [
|
|
32
|
-
{ text: request.systemPrompt + '\n\n' + request.userMessage },
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
generationConfig: {
|
|
37
|
-
maxOutputTokens: 4096,
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const response = result.response;
|
|
42
|
-
const text = response.text();
|
|
43
|
-
|
|
44
|
-
// Google doesn't always return exact token counts
|
|
45
|
-
const usageMetadata = response.usageMetadata || {};
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
content: text,
|
|
49
|
-
tokensUsed: {
|
|
50
|
-
input: usageMetadata.promptTokenCount || 0,
|
|
51
|
-
output: usageMetadata.candidatesTokenCount || 0,
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
} catch (err) {
|
|
55
|
-
if (err.status === 429 || err.message?.includes('RESOURCE_EXHAUSTED')) {
|
|
56
|
-
throw new RateLimitError('google');
|
|
57
|
-
}
|
|
58
|
-
throw err;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
estimateCost(inputTokens, outputTokens) {
|
|
63
|
-
return (inputTokens * 0.000075 + outputTokens * 0.0003) / 1000;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenAI LLM provider adapter.
|
|
3
|
-
* Uses openai SDK.
|
|
4
|
-
* Default model: gpt-4o-mini.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import OpenAI from 'openai';
|
|
8
|
-
import { NoApiKeyError, RateLimitError } from '../../utils/errors.js';
|
|
9
|
-
|
|
10
|
-
export class OpenAIProvider {
|
|
11
|
-
constructor(config = {}) {
|
|
12
|
-
this.name = 'openai';
|
|
13
|
-
this.model = config.model || 'gpt-4o-mini';
|
|
14
|
-
|
|
15
|
-
const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
|
|
16
|
-
if (!apiKey) {
|
|
17
|
-
throw new NoApiKeyError('openai');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
this.client = new OpenAI({ apiKey });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async complete(request) {
|
|
24
|
-
try {
|
|
25
|
-
const response = await this.client.chat.completions.create({
|
|
26
|
-
model: this.model,
|
|
27
|
-
max_tokens: 4096,
|
|
28
|
-
messages: [
|
|
29
|
-
{ role: 'system', content: request.systemPrompt },
|
|
30
|
-
{ role: 'user', content: request.userMessage },
|
|
31
|
-
],
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
content: response.choices[0].message.content,
|
|
36
|
-
tokensUsed: {
|
|
37
|
-
input: response.usage.prompt_tokens,
|
|
38
|
-
output: response.usage.completion_tokens,
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
} catch (err) {
|
|
42
|
-
if (err.status === 429) {
|
|
43
|
-
throw new RateLimitError('openai');
|
|
44
|
-
}
|
|
45
|
-
throw err;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
estimateCost(inputTokens, outputTokens) {
|
|
50
|
-
return (inputTokens * 0.00015 + outputTokens * 0.0006) / 1000;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tree-sitter initialization helper.
|
|
3
|
-
* Handles WASM loading for web-tree-sitter.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { createRequire } from 'node:module';
|
|
7
|
-
import { existsSync } from 'node:fs';
|
|
8
|
-
import { join, dirname } from 'node:path';
|
|
9
|
-
import { fileURLToPath } from 'node:url';
|
|
10
|
-
|
|
11
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
|
|
13
|
-
let Parser = null;
|
|
14
|
-
let initialized = false;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Initialize web-tree-sitter. Must be called once before using any parsers.
|
|
18
|
-
*/
|
|
19
|
-
export async function initTreeSitter() {
|
|
20
|
-
if (initialized) return Parser;
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const TreeSitter = (await import('web-tree-sitter')).default;
|
|
24
|
-
await TreeSitter.init();
|
|
25
|
-
Parser = TreeSitter;
|
|
26
|
-
initialized = true;
|
|
27
|
-
return Parser;
|
|
28
|
-
} catch (err) {
|
|
29
|
-
// Tree-sitter not available
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Load a language grammar WASM file.
|
|
36
|
-
* Looks for .wasm files in common locations.
|
|
37
|
-
* @param {string} languageName - e.g., 'javascript', 'typescript', 'python'
|
|
38
|
-
* @returns {Promise<object|null>} Language object or null
|
|
39
|
-
*/
|
|
40
|
-
export async function loadLanguage(languageName) {
|
|
41
|
-
if (!Parser) return null;
|
|
42
|
-
|
|
43
|
-
const wasmName = `tree-sitter-${languageName}.wasm`;
|
|
44
|
-
|
|
45
|
-
// Search paths for WASM files
|
|
46
|
-
const searchPaths = [
|
|
47
|
-
join(__dirname, '..', '..', '..', 'grammars', wasmName),
|
|
48
|
-
join(__dirname, '..', '..', '..', 'node_modules', `tree-sitter-${languageName}`, wasmName),
|
|
49
|
-
join(__dirname, '..', '..', '..', 'node_modules', 'web-tree-sitter', wasmName),
|
|
50
|
-
join(process.cwd(), 'grammars', wasmName),
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
for (const wasmPath of searchPaths) {
|
|
54
|
-
if (existsSync(wasmPath)) {
|
|
55
|
-
try {
|
|
56
|
-
const language = await Parser.Language.load(wasmPath);
|
|
57
|
-
return language;
|
|
58
|
-
} catch {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Create a parser instance with the given language.
|
|
69
|
-
* @param {object} language - Language object from loadLanguage
|
|
70
|
-
* @returns {object|null} Parser instance
|
|
71
|
-
*/
|
|
72
|
-
export function createParser(language) {
|
|
73
|
-
if (!Parser || !language) return null;
|
|
74
|
-
|
|
75
|
-
const parser = new Parser();
|
|
76
|
-
parser.setLanguage(language);
|
|
77
|
-
return parser;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export { Parser };
|