legacyver 2.1.2 → 2.1.3
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/legacyver-docs/SUMMARY.md +3 -1
- package/legacyver-docs/components.md +44 -46
- package/legacyver-docs/config.md +30 -0
- package/legacyver-docs/errors.md +74 -0
- package/legacyver-docs/index.md +7 -5
- package/legacyver-docs/logger.md +83 -0
- package/package.json +1 -1
- package/src/llm/prompts.js +96 -38
- package/src/llm/providers/gemini.js +1 -1
- package/src/llm/providers/groq.js +1 -1
- package/src/llm/providers/openrouter.js +1 -1
|
@@ -1,57 +1,55 @@
|
|
|
1
1
|
## Overview
|
|
2
|
-
|
|
2
|
+
The provided code is a collection of React components and a utility function written in TypeScript. It contains two React components, `Button` and `UserCard`, and a function `formatCurrency` for formatting currency.
|
|
3
3
|
|
|
4
4
|
## Functions
|
|
5
|
-
|
|
6
|
-
### formatCurrency
|
|
7
|
-
|
|
8
|
-
#### Description
|
|
9
|
-
Formats a given amount as a string in a specified currency.
|
|
10
|
-
|
|
11
|
-
#### Params Table
|
|
12
|
-
|
|
13
|
-
| Name | Type |
|
|
14
|
-
| --- | --- |
|
|
15
|
-
| `amount` | `number` |
|
|
16
|
-
| `currency` | `string`, defaults to `'USD'` |
|
|
17
|
-
|
|
18
|
-
#### Return Value
|
|
19
|
-
A formatted string representing the currency amount.
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
export function formatCurrency(amount: number, currency: string = 'USD'): string {
|
|
23
|
-
return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount);
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Dependencies
|
|
28
|
-
|
|
29
|
-
* `react`
|
|
30
|
-
* `intl`
|
|
31
|
-
|
|
32
|
-
## Overview
|
|
33
|
-
This file appears to contain UI components, with buttons and cards used for user representation.
|
|
34
|
-
|
|
35
|
-
## Functions
|
|
36
|
-
|
|
37
5
|
### Button
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
| Param | Type | Required |
|
|
6
|
+
The `Button` component is a React functional component that takes in several props and returns a `button` element.
|
|
7
|
+
#### Parameters
|
|
8
|
+
| Name | Type | Description |
|
|
42
9
|
| --- | --- | --- |
|
|
43
|
-
|
|
|
10
|
+
| label | string | The text to be displayed on the button |
|
|
11
|
+
| onClick | () => void | The function to be called when the button is clicked |
|
|
12
|
+
| disabled | boolean | Whether the button is disabled (optional) |
|
|
13
|
+
| variant | 'primary' | 'secondary' | 'danger' | The style variant of the button (optional) |
|
|
44
14
|
#### Return Value
|
|
45
|
-
|
|
15
|
+
The `Button` component returns a `button` element with the specified props.
|
|
46
16
|
|
|
47
17
|
### UserCard
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
| Param | Type | Required |
|
|
18
|
+
The `UserCard` component is a React functional component that takes in several props and returns a user card.
|
|
19
|
+
#### Parameters
|
|
20
|
+
| Name | Type | Description |
|
|
52
21
|
| --- | --- | --- |
|
|
53
|
-
|
|
|
22
|
+
| userId | number | The ID of the user |
|
|
23
|
+
| onClose | () => void | The function to be called when the close button is clicked |
|
|
24
|
+
#### Return Value
|
|
25
|
+
The `UserCard` component returns a `div` element containing the user's information, or a loading message if the data is not available.
|
|
26
|
+
|
|
27
|
+
### formatCurrency
|
|
28
|
+
The `formatCurrency` function formats a given amount as a currency string.
|
|
29
|
+
#### Parameters
|
|
30
|
+
| Name | Type | Description |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| amount | number | The amount to be formatted |
|
|
33
|
+
| currency | string | The currency of the amount (optional, defaults to 'USD') |
|
|
34
|
+
#### Return Value
|
|
35
|
+
The `formatCurrency` function returns a string representing the formatted currency.
|
|
54
36
|
|
|
55
37
|
## Dependencies
|
|
56
|
-
*
|
|
57
|
-
*
|
|
38
|
+
* React
|
|
39
|
+
* Intl.NumberFormat (for currency formatting)
|
|
40
|
+
|
|
41
|
+
## Usage Example
|
|
42
|
+
No clear usage pattern is visible in the provided code. However, the components and function can be used as follows:
|
|
43
|
+
```tsx
|
|
44
|
+
import { Button, UserCard, formatCurrency } from './components';
|
|
45
|
+
|
|
46
|
+
const Example = () => {
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
<Button label="Click me" onClick={() => console.log('Button clicked')} />
|
|
50
|
+
<UserCard userId={1} onClose={() => console.log('User card closed')} />
|
|
51
|
+
<p>Formatted currency: {formatCurrency(1000, 'USD')}</p>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
This is a JavaScript module that exports a single function `loadConfig`, which loads configuration from a file and merges with CLI flags.
|
|
3
|
+
|
|
4
|
+
## Functions
|
|
5
|
+
### `loadConfig`
|
|
6
|
+
|
|
7
|
+
#### Description:
|
|
8
|
+
Load configuration from file and merge with CLI flags.
|
|
9
|
+
CLI flags always win over file config.
|
|
10
|
+
|
|
11
|
+
#### Params Table:
|
|
12
|
+
|
|
13
|
+
| Name | Type |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| `cliFlags` | Object |
|
|
16
|
+
|
|
17
|
+
#### Return Value:
|
|
18
|
+
Object
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
function loadConfig(cliFlags = {}) {
|
|
22
|
+
// ...
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Dependencies
|
|
27
|
+
* `cosmiconfig: cosmiconfigSync`
|
|
28
|
+
|
|
29
|
+
## Usage Example
|
|
30
|
+
No clear pattern is visible in the code to demonstrate usage.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
This file exports five custom error classes for use in a Legacyver application.
|
|
3
|
+
|
|
4
|
+
## Functions
|
|
5
|
+
|
|
6
|
+
### `LegacyverError`
|
|
7
|
+
#### Description
|
|
8
|
+
A base class for all custom errors in Legacyver.
|
|
9
|
+
#### Parameters
|
|
10
|
+
| Name | Type | Default Value |
|
|
11
|
+
| --- | --- | --- |
|
|
12
|
+
| message | string | |
|
|
13
|
+
| code | string | 'LEGACYVER_ERROR' |
|
|
14
|
+
|
|
15
|
+
#### Return Value
|
|
16
|
+
None.
|
|
17
|
+
|
|
18
|
+
### `NoApiKeyError`
|
|
19
|
+
#### Description
|
|
20
|
+
Raised when no API key is found for a provider.
|
|
21
|
+
#### Parameters
|
|
22
|
+
| Name | Type | Required | Default Value |
|
|
23
|
+
| --- | --- | --- | --- |
|
|
24
|
+
| provider | string | | |
|
|
25
|
+
|
|
26
|
+
#### Return Value
|
|
27
|
+
None.
|
|
28
|
+
|
|
29
|
+
#### Detected Patterns:
|
|
30
|
+
- The error message includes a suggestion to set the `OPENROUTER_API_KEY` environment variable or run `legacyver init`.
|
|
31
|
+
- The error message includes a link to obtain an API key at https://openrouter.ai/keys.
|
|
32
|
+
|
|
33
|
+
### `RateLimitError`
|
|
34
|
+
#### Description
|
|
35
|
+
Raised when the rate limit is exceeded for a provider.
|
|
36
|
+
#### Parameters
|
|
37
|
+
| Name | Type | Required | Default Value |
|
|
38
|
+
| --- | --- | --- | --- |
|
|
39
|
+
| provider | string | | |
|
|
40
|
+
| retryAfter | number | | 1000 |
|
|
41
|
+
|
|
42
|
+
#### Return Value
|
|
43
|
+
None.
|
|
44
|
+
|
|
45
|
+
#### Detected Patterns:
|
|
46
|
+
- The error message includes a suggestion to retry.
|
|
47
|
+
- The error message indicates the amount of time that must pass before retrying (1000ms by default).
|
|
48
|
+
|
|
49
|
+
### `ParseError`
|
|
50
|
+
#### Description
|
|
51
|
+
Raised when there is an issue parsing a file.
|
|
52
|
+
#### Parameters
|
|
53
|
+
| Name | Type | Required | Default Value |
|
|
54
|
+
| --- | --- | --- | --- |
|
|
55
|
+
| filePath | string | | |
|
|
56
|
+
| originalError | Error | | |
|
|
57
|
+
|
|
58
|
+
#### Return Value
|
|
59
|
+
None.
|
|
60
|
+
|
|
61
|
+
### `RenderError`
|
|
62
|
+
#### Description
|
|
63
|
+
Raised when there is an issue rendering a format.
|
|
64
|
+
#### Parameters
|
|
65
|
+
| Name | Type | Required | Default Value |
|
|
66
|
+
| --- | --- | --- | --- |
|
|
67
|
+
| format | string | | |
|
|
68
|
+
| originalError | Error | | |
|
|
69
|
+
|
|
70
|
+
#### Return Value
|
|
71
|
+
None.
|
|
72
|
+
|
|
73
|
+
## Dependencies
|
|
74
|
+
* `Error`
|
package/legacyver-docs/index.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# utils — Documentation
|
|
2
2
|
|
|
3
|
-
**Primary language:**
|
|
4
|
-
**Total files:**
|
|
5
|
-
**Analyzed at:** 2026-02-
|
|
3
|
+
**Primary language:** javascript
|
|
4
|
+
**Total files:** 3
|
|
5
|
+
**Analyzed at:** 2026-02-21T08:58:31.525Z
|
|
6
6
|
|
|
7
7
|
## Files
|
|
8
8
|
|
|
9
|
-
- [
|
|
9
|
+
- [errors.js](errors.md)
|
|
10
|
+
- [config.js](config.md)
|
|
11
|
+
- [logger.js](logger.md)
|
|
10
12
|
|
|
11
13
|
## Dependency Graph
|
|
12
14
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
This module provides a logging system with configurable log levels and colorful output.
|
|
3
|
+
|
|
4
|
+
## Functions
|
|
5
|
+
|
|
6
|
+
### `setLevel(level)`
|
|
7
|
+
#### Params | Description
|
|
8
|
+
----------|-------------
|
|
9
|
+
`level` | The desired log level
|
|
10
|
+
|
|
11
|
+
#### Returns
|
|
12
|
+
None
|
|
13
|
+
|
|
14
|
+
Sets the current log level to the specified `level`.
|
|
15
|
+
|
|
16
|
+
### `setCI(val)`
|
|
17
|
+
#### Params | Description
|
|
18
|
+
----------|-------------
|
|
19
|
+
`val` | A boolean indicating whether CI mode is enabled
|
|
20
|
+
|
|
21
|
+
#### Returns
|
|
22
|
+
None
|
|
23
|
+
|
|
24
|
+
Toggles the CI mode on or off.
|
|
25
|
+
|
|
26
|
+
### `shouldLog(level)`
|
|
27
|
+
#### Params | Description
|
|
28
|
+
----------|-------------
|
|
29
|
+
`level` | The log level to check for
|
|
30
|
+
|
|
31
|
+
#### Returns
|
|
32
|
+
Boolean
|
|
33
|
+
Determines whether the current log level allows logging at the specified `level`.
|
|
34
|
+
|
|
35
|
+
### `debug(...args)`
|
|
36
|
+
#### Params | Description
|
|
37
|
+
----------|-------------
|
|
38
|
+
`...args` | Variable number of arguments to be logged as debug output
|
|
39
|
+
|
|
40
|
+
#### Returns
|
|
41
|
+
None
|
|
42
|
+
Logs the provided `args` to the console with a gray '[debug]' prefix if the current log level allows it.
|
|
43
|
+
|
|
44
|
+
### `info(...args)`
|
|
45
|
+
#### Params | Description
|
|
46
|
+
----------|-------------
|
|
47
|
+
`...args` | Variable number of arguments to be logged as info output
|
|
48
|
+
|
|
49
|
+
#### Returns
|
|
50
|
+
None
|
|
51
|
+
Logs the provided `args` to the console with a cyan '[info]' prefix if the current log level allows it.
|
|
52
|
+
|
|
53
|
+
### `warn(...args)`
|
|
54
|
+
#### Params | Description
|
|
55
|
+
----------|-------------
|
|
56
|
+
`...args` | Variable number of arguments to be logged as warn output
|
|
57
|
+
|
|
58
|
+
#### Returns
|
|
59
|
+
None
|
|
60
|
+
Logs the provided `args` to the console with a yellow '[warn]' prefix if the current log level allows it.
|
|
61
|
+
|
|
62
|
+
### `error(...args)`
|
|
63
|
+
#### Params | Description
|
|
64
|
+
----------|-------------
|
|
65
|
+
`...args` | Variable number of arguments to be logged as error output
|
|
66
|
+
|
|
67
|
+
#### Returns
|
|
68
|
+
None
|
|
69
|
+
Logs the provided `args` to the console with a red '[error]' prefix if the current log level allows it.
|
|
70
|
+
|
|
71
|
+
## Dependencies
|
|
72
|
+
* picocolors (`pc`)
|
|
73
|
+
|
|
74
|
+
## Usage Example
|
|
75
|
+
```javascript
|
|
76
|
+
const logger = require('./logger');
|
|
77
|
+
|
|
78
|
+
logger.debug('This is a debug message');
|
|
79
|
+
logger.info('This is an info message');
|
|
80
|
+
logger.warn('This is a warn message');
|
|
81
|
+
logger.error('This is an error message');
|
|
82
|
+
```
|
|
83
|
+
Note: This example demonstrates the usage of the `debug`, `info`, `warn`, and `error` functions, which are exported from the logger module.
|
package/package.json
CHANGED
package/src/llm/prompts.js
CHANGED
|
@@ -1,34 +1,98 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const SYSTEM_PROMPT = `You are a technical documentation writer.
|
|
4
|
-
1. Extracted structural facts about a source file (JSON)
|
|
5
|
-
2. The raw source code of that file
|
|
6
|
-
|
|
7
|
-
Your job is to write clear, accurate Markdown documentation based ONLY on what is present in the code.
|
|
3
|
+
const SYSTEM_PROMPT = `You are a technical documentation writer. Given a file's structure and source code, write accurate Markdown documentation based ONLY on what is present.
|
|
8
4
|
|
|
9
5
|
Rules:
|
|
10
|
-
- Do NOT infer behavior not
|
|
11
|
-
- Do NOT
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- Do not mention any function, class, parameter, or behavior that does not appear in the FileFacts JSON or bodySnippet above
|
|
15
|
-
- For each function with complexityClass "moderate" or "complex", explain the logic described in the bodySnippet in plain language
|
|
16
|
-
- For each function with detectedPatterns[] non-empty, explicitly describe what that pattern does in context
|
|
17
|
-
|
|
18
|
-
Temperature: use 0.1 — factual output only.
|
|
6
|
+
- Do NOT infer behavior not shown in the code
|
|
7
|
+
- Do NOT fabricate descriptions
|
|
8
|
+
- For complex functions, explain the logic from the bodySnippet
|
|
9
|
+
- For functions with detectedPatterns, describe what each pattern does
|
|
19
10
|
|
|
20
|
-
Output format
|
|
11
|
+
Output format:
|
|
21
12
|
## Overview
|
|
22
|
-
[1-2 sentences
|
|
13
|
+
[1-2 sentences]
|
|
23
14
|
|
|
24
15
|
## Functions
|
|
25
|
-
[
|
|
16
|
+
[### per function: description, params table, return value]
|
|
26
17
|
|
|
27
18
|
## Dependencies
|
|
28
|
-
[Bullet list of imports
|
|
19
|
+
[Bullet list of imports]
|
|
29
20
|
|
|
30
21
|
## Usage Example
|
|
31
|
-
[Only
|
|
22
|
+
[Only if a clear pattern is visible in the code]`;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Strip null/undefined values and empty arrays from an object (shallow).
|
|
26
|
+
*/
|
|
27
|
+
function stripEmpty(obj) {
|
|
28
|
+
const result = {};
|
|
29
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
30
|
+
if (v === null || v === undefined) continue;
|
|
31
|
+
if (Array.isArray(v) && v.length === 0) continue;
|
|
32
|
+
result[k] = v;
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Build a slim version of FileFacts for the prompt — remove noise, keep signal.
|
|
39
|
+
*/
|
|
40
|
+
function slimFacts(fileFacts) {
|
|
41
|
+
const slim = {
|
|
42
|
+
file: fileFacts.relativePath,
|
|
43
|
+
lang: fileFacts.language,
|
|
44
|
+
lines: fileFacts.linesOfCode,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Functions — only include useful fields
|
|
48
|
+
if (fileFacts.functions && fileFacts.functions.length > 0) {
|
|
49
|
+
slim.functions = fileFacts.functions.map(fn => {
|
|
50
|
+
const entry = { name: fn.name };
|
|
51
|
+
if (fn.params && fn.params.length > 0) {
|
|
52
|
+
entry.params = fn.params.map(p => p.type ? `${p.name}:${p.type}` : p.name);
|
|
53
|
+
}
|
|
54
|
+
if (fn.returnType) entry.returns = fn.returnType;
|
|
55
|
+
if (fn.isExported) entry.exported = true;
|
|
56
|
+
if (fn.isAsync) entry.async = true;
|
|
57
|
+
if (fn.complexityClass && fn.complexityClass !== 'simple') {
|
|
58
|
+
entry.complexity = fn.complexityClass;
|
|
59
|
+
}
|
|
60
|
+
if (fn.detectedPatterns && fn.detectedPatterns.length > 0) {
|
|
61
|
+
entry.patterns = fn.detectedPatterns;
|
|
62
|
+
}
|
|
63
|
+
if (fn.bodySnippet) entry.body = fn.bodySnippet;
|
|
64
|
+
if (fn.calls && fn.calls.length > 0) entry.calls = fn.calls;
|
|
65
|
+
return entry;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Classes
|
|
70
|
+
if (fileFacts.classes && fileFacts.classes.length > 0) {
|
|
71
|
+
slim.classes = fileFacts.classes.map(c => {
|
|
72
|
+
const entry = { name: c.name };
|
|
73
|
+
if (c.superClass) entry.extends = c.superClass;
|
|
74
|
+
if (c.methods && c.methods.length > 0) entry.methods = c.methods.map(m => m.name || m);
|
|
75
|
+
return entry;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Imports — compact
|
|
80
|
+
if (fileFacts.imports && fileFacts.imports.length > 0) {
|
|
81
|
+
slim.imports = fileFacts.imports.map(i => {
|
|
82
|
+
if (i.specifiers && i.specifiers.length > 0) {
|
|
83
|
+
return `${i.module}: ${i.specifiers.join(', ')}`;
|
|
84
|
+
}
|
|
85
|
+
return i.module;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Exports
|
|
90
|
+
if (fileFacts.exports && fileFacts.exports.length > 0) {
|
|
91
|
+
slim.exports = fileFacts.exports;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return slim;
|
|
95
|
+
}
|
|
32
96
|
|
|
33
97
|
/**
|
|
34
98
|
* Build the user message for a single file.
|
|
@@ -37,28 +101,22 @@ Output format (strict Markdown):
|
|
|
37
101
|
* @returns {string}
|
|
38
102
|
*/
|
|
39
103
|
function buildUserMessage(fileFacts, rawSource) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (fn.detectedPatterns && fn.detectedPatterns.length > 0) {
|
|
49
|
-
entry._patternHint = `This function uses patterns: ${fn.detectedPatterns.join(', ')}. Describe what each does in context.`;
|
|
50
|
-
}
|
|
51
|
-
return entry;
|
|
52
|
-
}),
|
|
53
|
-
};
|
|
104
|
+
const slim = slimFacts(fileFacts);
|
|
105
|
+
|
|
106
|
+
// Truncate source to ~150 lines to keep prompt small
|
|
107
|
+
const lines = rawSource.split('\n');
|
|
108
|
+
let source = rawSource;
|
|
109
|
+
if (lines.length > 150) {
|
|
110
|
+
source = lines.slice(0, 150).join('\n') + '\n// ... truncated';
|
|
111
|
+
}
|
|
54
112
|
|
|
55
|
-
return `
|
|
56
|
-
${JSON.stringify(
|
|
113
|
+
return `STRUCTURE:
|
|
114
|
+
${JSON.stringify(slim)}
|
|
57
115
|
|
|
58
|
-
|
|
59
|
-
${
|
|
116
|
+
CODE:
|
|
117
|
+
${source}
|
|
60
118
|
|
|
61
|
-
Generate documentation
|
|
119
|
+
Generate documentation following the system instructions.`;
|
|
62
120
|
}
|
|
63
121
|
|
|
64
122
|
module.exports = { SYSTEM_PROMPT, buildUserMessage };
|
|
@@ -7,7 +7,7 @@ const DEFAULT_MODEL = 'gemini-2.0-flash';
|
|
|
7
7
|
|
|
8
8
|
class GeminiProvider {
|
|
9
9
|
constructor(config) {
|
|
10
|
-
this.apiKey =
|
|
10
|
+
this.apiKey = process.env.GEMINI_API_KEY || config.geminiApiKey;
|
|
11
11
|
if (!this.apiKey) throw new NoApiKeyError('gemini');
|
|
12
12
|
this.model = config.model || DEFAULT_MODEL;
|
|
13
13
|
this.name = 'gemini';
|
|
@@ -7,7 +7,7 @@ const DEFAULT_MODEL = 'llama-3.3-70b-versatile';
|
|
|
7
7
|
|
|
8
8
|
class GroqProvider {
|
|
9
9
|
constructor(config) {
|
|
10
|
-
this.apiKey =
|
|
10
|
+
this.apiKey = process.env.GROQ_API_KEY || config.groqApiKey;
|
|
11
11
|
if (!this.apiKey) throw new NoApiKeyError('groq');
|
|
12
12
|
this.model = config.model || DEFAULT_MODEL;
|
|
13
13
|
this.name = 'groq';
|
|
@@ -7,7 +7,7 @@ const DEFAULT_MODEL = 'meta-llama/llama-3.3-70b-instruct:free';
|
|
|
7
7
|
|
|
8
8
|
class OpenRouterProvider {
|
|
9
9
|
constructor(config) {
|
|
10
|
-
this.apiKey =
|
|
10
|
+
this.apiKey = process.env.OPENROUTER_API_KEY || config.apiKey;
|
|
11
11
|
if (!this.apiKey) {
|
|
12
12
|
throw new NoApiKeyError('openrouter');
|
|
13
13
|
}
|