genai-lite 0.8.3 → 0.9.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.
- package/LICENSE +21 -21
- package/README.md +210 -207
- package/dist/config/llm-presets.json +24 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +6 -1
- package/dist/llm/LLMService.d.ts +30 -1
- package/dist/llm/LLMService.js +42 -4
- package/dist/llm/clients/AnthropicClientAdapter.d.ts +2 -2
- package/dist/llm/clients/AnthropicClientAdapter.js +17 -3
- package/dist/llm/clients/GeminiClientAdapter.d.ts +2 -2
- package/dist/llm/clients/GeminiClientAdapter.js +14 -3
- package/dist/llm/clients/LlamaCppClientAdapter.d.ts +4 -4
- package/dist/llm/clients/LlamaCppClientAdapter.js +118 -15
- package/dist/llm/clients/MistralClientAdapter.d.ts +2 -2
- package/dist/llm/clients/MistralClientAdapter.js +15 -4
- package/dist/llm/clients/MockClientAdapter.d.ts +2 -2
- package/dist/llm/clients/MockClientAdapter.js +36 -19
- package/dist/llm/clients/OpenAIClientAdapter.d.ts +2 -2
- package/dist/llm/clients/OpenAIClientAdapter.js +26 -3
- package/dist/llm/clients/OpenRouterClientAdapter.d.ts +2 -2
- package/dist/llm/clients/OpenRouterClientAdapter.js +81 -10
- package/dist/llm/clients/types.d.ts +18 -1
- package/dist/llm/clients/types.js +4 -0
- package/dist/llm/config.d.ts +9 -2
- package/dist/llm/config.js +697 -33
- package/dist/llm/services/ModelResolver.d.ts +6 -0
- package/dist/llm/services/ModelResolver.js +57 -17
- package/dist/llm/services/SettingsManager.d.ts +1 -1
- package/dist/llm/services/SettingsManager.js +92 -4
- package/dist/llm/types.d.ts +127 -0
- package/dist/prompting/index.d.ts +1 -1
- package/dist/prompting/index.js +2 -1
- package/dist/prompting/parser.d.ts +23 -0
- package/dist/prompting/parser.js +33 -0
- package/dist/shared/adapters/errorUtils.d.ts +15 -0
- package/dist/shared/adapters/errorUtils.js +69 -1
- package/dist/shared/adapters/logprobsUtils.d.ts +13 -0
- package/dist/shared/adapters/logprobsUtils.js +33 -0
- package/dist/shared/services/withRetry.d.ts +50 -0
- package/dist/shared/services/withRetry.js +78 -0
- package/package.json +59 -59
- package/src/config/image-presets.json +212 -212
- package/src/config/llm-presets.json +623 -599
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI Summary: Shared mapper for OpenAI-shaped chat-completions logprobs payloads.
|
|
3
|
+
// Used by the OpenAI, OpenRouter and llama.cpp adapters (identical wire shape).
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.mapOpenAIChatLogprobs = mapOpenAIChatLogprobs;
|
|
6
|
+
/**
|
|
7
|
+
* Maps an OpenAI-shaped chat-completions logprobs payload
|
|
8
|
+
* (`choice.logprobs.content[].{token, logprob, top_logprobs[]}`) to the
|
|
9
|
+
* library's normalized {@link TokenLogprob} array.
|
|
10
|
+
*
|
|
11
|
+
* llama-server's chat endpoint produces the same shape, so this mapper is
|
|
12
|
+
* shared across the OpenAI-SDK-based adapters.
|
|
13
|
+
*
|
|
14
|
+
* @param logprobs - The raw `choice.logprobs` object from the provider response
|
|
15
|
+
* @returns Normalized token logprobs, or undefined when absent/empty
|
|
16
|
+
*/
|
|
17
|
+
function mapOpenAIChatLogprobs(logprobs) {
|
|
18
|
+
const content = logprobs?.content;
|
|
19
|
+
if (!Array.isArray(content) || content.length === 0) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
return content.map((entry) => ({
|
|
23
|
+
token: entry.token,
|
|
24
|
+
logprob: entry.logprob,
|
|
25
|
+
...(Array.isArray(entry.top_logprobs) &&
|
|
26
|
+
entry.top_logprobs.length > 0 && {
|
|
27
|
+
topLogprobs: entry.top_logprobs.map((alt) => ({
|
|
28
|
+
token: alt.token,
|
|
29
|
+
logprob: alt.logprob,
|
|
30
|
+
})),
|
|
31
|
+
}),
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Logger } from "../../logging/types";
|
|
2
|
+
/**
|
|
3
|
+
* Retry policy configuration.
|
|
4
|
+
*/
|
|
5
|
+
export interface RetryPolicy {
|
|
6
|
+
/** Maximum number of retries after the initial attempt (default 2 → up to 3 attempts) */
|
|
7
|
+
maxRetries: number;
|
|
8
|
+
/** Base delay before the first retry, in ms (default 500) */
|
|
9
|
+
initialDelayMs: number;
|
|
10
|
+
/** Upper bound for any single delay, in ms (default 10000) */
|
|
11
|
+
maxDelayMs: number;
|
|
12
|
+
/** Exponential growth factor per attempt (default 2) */
|
|
13
|
+
backoffFactor: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const DEFAULT_RETRY_POLICY: RetryPolicy;
|
|
16
|
+
/**
|
|
17
|
+
* Verdict returned by the caller's shouldRetry callback.
|
|
18
|
+
*/
|
|
19
|
+
export interface RetryVerdict {
|
|
20
|
+
/** Whether the operation should be retried */
|
|
21
|
+
retry: boolean;
|
|
22
|
+
/** Provider-suggested wait (e.g. from a Retry-After header); used when larger than the computed backoff */
|
|
23
|
+
retryAfterMs?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface WithRetryOptions extends Partial<RetryPolicy> {
|
|
26
|
+
/** Abort signal — no further retries (or waits) once aborted */
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
/** Logger for retry warnings */
|
|
29
|
+
logger?: Logger;
|
|
30
|
+
/** Label used in log messages (e.g. "openai/gpt-4.1") */
|
|
31
|
+
label?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Runs an async operation with retries and exponential backoff.
|
|
35
|
+
*
|
|
36
|
+
* Unlike typical retry helpers, this operates on RETURNED values rather than
|
|
37
|
+
* exceptions: the caller's `shouldRetry` inspects each result (genai-lite
|
|
38
|
+
* adapters return failure responses instead of throwing) and decides whether
|
|
39
|
+
* to retry. The last result is always returned — never thrown.
|
|
40
|
+
*
|
|
41
|
+
* Delay per retry: `min(maxDelayMs, initialDelayMs * backoffFactor^attempt)`
|
|
42
|
+
* with ±20% jitter; a provider-supplied `retryAfterMs` is honored when larger
|
|
43
|
+
* (still capped at `maxDelayMs`).
|
|
44
|
+
*
|
|
45
|
+
* @param operation - The operation to run; receives the 0-based attempt index
|
|
46
|
+
* @param shouldRetry - Inspects a result and decides whether to retry
|
|
47
|
+
* @param options - Policy overrides, abort signal, logger
|
|
48
|
+
* @returns The final result (successful, non-retryable, or last exhausted attempt)
|
|
49
|
+
*/
|
|
50
|
+
export declare function withRetry<T>(operation: (attempt: number) => Promise<T>, shouldRetry: (result: T) => RetryVerdict, options?: WithRetryOptions): Promise<T>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI Summary: Generic retry helper with exponential backoff and jitter.
|
|
3
|
+
// Works on RETURNED values (genai-lite adapters never throw), honors Retry-After
|
|
4
|
+
// hints and AbortSignals. Used by LLMService's unified retry layer.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DEFAULT_RETRY_POLICY = void 0;
|
|
7
|
+
exports.withRetry = withRetry;
|
|
8
|
+
exports.DEFAULT_RETRY_POLICY = {
|
|
9
|
+
maxRetries: 2,
|
|
10
|
+
initialDelayMs: 500,
|
|
11
|
+
maxDelayMs: 10000,
|
|
12
|
+
backoffFactor: 2,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Runs an async operation with retries and exponential backoff.
|
|
16
|
+
*
|
|
17
|
+
* Unlike typical retry helpers, this operates on RETURNED values rather than
|
|
18
|
+
* exceptions: the caller's `shouldRetry` inspects each result (genai-lite
|
|
19
|
+
* adapters return failure responses instead of throwing) and decides whether
|
|
20
|
+
* to retry. The last result is always returned — never thrown.
|
|
21
|
+
*
|
|
22
|
+
* Delay per retry: `min(maxDelayMs, initialDelayMs * backoffFactor^attempt)`
|
|
23
|
+
* with ±20% jitter; a provider-supplied `retryAfterMs` is honored when larger
|
|
24
|
+
* (still capped at `maxDelayMs`).
|
|
25
|
+
*
|
|
26
|
+
* @param operation - The operation to run; receives the 0-based attempt index
|
|
27
|
+
* @param shouldRetry - Inspects a result and decides whether to retry
|
|
28
|
+
* @param options - Policy overrides, abort signal, logger
|
|
29
|
+
* @returns The final result (successful, non-retryable, or last exhausted attempt)
|
|
30
|
+
*/
|
|
31
|
+
async function withRetry(operation, shouldRetry, options) {
|
|
32
|
+
const policy = {
|
|
33
|
+
maxRetries: options?.maxRetries ?? exports.DEFAULT_RETRY_POLICY.maxRetries,
|
|
34
|
+
initialDelayMs: options?.initialDelayMs ?? exports.DEFAULT_RETRY_POLICY.initialDelayMs,
|
|
35
|
+
maxDelayMs: options?.maxDelayMs ?? exports.DEFAULT_RETRY_POLICY.maxDelayMs,
|
|
36
|
+
backoffFactor: options?.backoffFactor ?? exports.DEFAULT_RETRY_POLICY.backoffFactor,
|
|
37
|
+
};
|
|
38
|
+
let result = await operation(0);
|
|
39
|
+
for (let attempt = 0; attempt < policy.maxRetries; attempt++) {
|
|
40
|
+
const verdict = shouldRetry(result);
|
|
41
|
+
if (!verdict.retry || options?.signal?.aborted) {
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
// Exponential backoff with ±20% jitter; honor Retry-After when larger
|
|
45
|
+
const baseDelay = Math.min(policy.maxDelayMs, policy.initialDelayMs * Math.pow(policy.backoffFactor, attempt));
|
|
46
|
+
const jittered = baseDelay * (0.8 + Math.random() * 0.4);
|
|
47
|
+
const delayMs = Math.min(policy.maxDelayMs, Math.max(jittered, verdict.retryAfterMs ?? 0));
|
|
48
|
+
options?.logger?.warn(`Retrying${options.label ? ` ${options.label}` : ''} after failure ` +
|
|
49
|
+
`(attempt ${attempt + 2}/${policy.maxRetries + 1}, waiting ${Math.round(delayMs)}ms)`);
|
|
50
|
+
const aborted = await sleepUnlessAborted(delayMs, options?.signal);
|
|
51
|
+
if (aborted) {
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
result = await operation(attempt + 1);
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Sleeps for the given duration unless the signal aborts first.
|
|
60
|
+
*
|
|
61
|
+
* @returns true when the wait was cut short by an abort
|
|
62
|
+
*/
|
|
63
|
+
function sleepUnlessAborted(ms, signal) {
|
|
64
|
+
if (signal?.aborted) {
|
|
65
|
+
return Promise.resolve(true);
|
|
66
|
+
}
|
|
67
|
+
return new Promise((resolve) => {
|
|
68
|
+
const onAbort = () => {
|
|
69
|
+
clearTimeout(timer);
|
|
70
|
+
resolve(true);
|
|
71
|
+
};
|
|
72
|
+
const timer = setTimeout(() => {
|
|
73
|
+
signal?.removeEventListener('abort', onAbort);
|
|
74
|
+
resolve(false);
|
|
75
|
+
}, ms);
|
|
76
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
77
|
+
});
|
|
78
|
+
}
|
package/package.json
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "genai-lite",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A lightweight, portable toolkit for interacting with various Generative AI APIs.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/index.js",
|
|
10
|
-
"require": "./dist/index.js",
|
|
11
|
-
"types": "./dist/index.d.ts"
|
|
12
|
-
},
|
|
13
|
-
"./prompting": {
|
|
14
|
-
"import": "./dist/prompting/index.js",
|
|
15
|
-
"require": "./dist/prompting/index.js",
|
|
16
|
-
"types": "./dist/prompting/index.d.ts"
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"author": "Luigi Acerbi <luigi.acerbi@gmail.com>",
|
|
20
|
-
"license": "MIT",
|
|
21
|
-
"funding": {
|
|
22
|
-
"type": "github",
|
|
23
|
-
"url": "https://github.com/sponsors/lacerbi"
|
|
24
|
-
},
|
|
25
|
-
"repository": {
|
|
26
|
-
"type": "git",
|
|
27
|
-
"url": "git+https://github.com/lacerbi/genai-lite.git"
|
|
28
|
-
},
|
|
29
|
-
"bugs": {
|
|
30
|
-
"url": "https://github.com/lacerbi/genai-lite/issues"
|
|
31
|
-
},
|
|
32
|
-
"homepage": "https://github.com/lacerbi/genai-lite#readme",
|
|
33
|
-
"files": [
|
|
34
|
-
"dist",
|
|
35
|
-
"src/config/llm-presets.json",
|
|
36
|
-
"src/config/image-presets.json"
|
|
37
|
-
],
|
|
38
|
-
"scripts": {
|
|
39
|
-
"build": "tsc",
|
|
40
|
-
"test": "jest --coverage",
|
|
41
|
-
"test:watch": "jest --watch",
|
|
42
|
-
"test:e2e": "npm run build && jest --config jest.e2e.config.js",
|
|
43
|
-
"test:e2e:reasoning": "npm run build && jest --config jest.e2e.config.js reasoning.e2e.test.ts"
|
|
44
|
-
},
|
|
45
|
-
"dependencies": {
|
|
46
|
-
"@anthropic-ai/sdk": "^0.71.2",
|
|
47
|
-
"@google/genai": "^1.0.1",
|
|
48
|
-
"@mistralai/mistralai": "^1.11.0",
|
|
49
|
-
"js-tiktoken": "^1.0.20",
|
|
50
|
-
"openai": "^6.7.0"
|
|
51
|
-
},
|
|
52
|
-
"devDependencies": {
|
|
53
|
-
"@types/jest": ">=30.0.0",
|
|
54
|
-
"@types/node": ">=20.11.24",
|
|
55
|
-
"jest": ">=30.0.4",
|
|
56
|
-
"ts-jest": ">=29.4.0",
|
|
57
|
-
"typescript": ">=5.3.3"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "genai-lite",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "A lightweight, portable toolkit for interacting with various Generative AI APIs.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./prompting": {
|
|
14
|
+
"import": "./dist/prompting/index.js",
|
|
15
|
+
"require": "./dist/prompting/index.js",
|
|
16
|
+
"types": "./dist/prompting/index.d.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"author": "Luigi Acerbi <luigi.acerbi@gmail.com>",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"funding": {
|
|
22
|
+
"type": "github",
|
|
23
|
+
"url": "https://github.com/sponsors/lacerbi"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/lacerbi/genai-lite.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/lacerbi/genai-lite/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/lacerbi/genai-lite#readme",
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"src/config/llm-presets.json",
|
|
36
|
+
"src/config/image-presets.json"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc",
|
|
40
|
+
"test": "jest --coverage",
|
|
41
|
+
"test:watch": "jest --watch",
|
|
42
|
+
"test:e2e": "npm run build && jest --config jest.e2e.config.js",
|
|
43
|
+
"test:e2e:reasoning": "npm run build && jest --config jest.e2e.config.js reasoning.e2e.test.ts"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
47
|
+
"@google/genai": "^1.0.1",
|
|
48
|
+
"@mistralai/mistralai": "^1.11.0",
|
|
49
|
+
"js-tiktoken": "^1.0.20",
|
|
50
|
+
"openai": "^6.7.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/jest": ">=30.0.0",
|
|
54
|
+
"@types/node": ">=20.11.24",
|
|
55
|
+
"jest": ">=30.0.4",
|
|
56
|
+
"ts-jest": ">=29.4.0",
|
|
57
|
+
"typescript": ">=5.3.3"
|
|
58
|
+
}
|
|
59
|
+
}
|