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.
Files changed (43) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +210 -207
  3. package/dist/config/llm-presets.json +24 -0
  4. package/dist/index.d.ts +4 -2
  5. package/dist/index.js +6 -1
  6. package/dist/llm/LLMService.d.ts +30 -1
  7. package/dist/llm/LLMService.js +42 -4
  8. package/dist/llm/clients/AnthropicClientAdapter.d.ts +2 -2
  9. package/dist/llm/clients/AnthropicClientAdapter.js +17 -3
  10. package/dist/llm/clients/GeminiClientAdapter.d.ts +2 -2
  11. package/dist/llm/clients/GeminiClientAdapter.js +14 -3
  12. package/dist/llm/clients/LlamaCppClientAdapter.d.ts +4 -4
  13. package/dist/llm/clients/LlamaCppClientAdapter.js +118 -15
  14. package/dist/llm/clients/MistralClientAdapter.d.ts +2 -2
  15. package/dist/llm/clients/MistralClientAdapter.js +15 -4
  16. package/dist/llm/clients/MockClientAdapter.d.ts +2 -2
  17. package/dist/llm/clients/MockClientAdapter.js +36 -19
  18. package/dist/llm/clients/OpenAIClientAdapter.d.ts +2 -2
  19. package/dist/llm/clients/OpenAIClientAdapter.js +26 -3
  20. package/dist/llm/clients/OpenRouterClientAdapter.d.ts +2 -2
  21. package/dist/llm/clients/OpenRouterClientAdapter.js +81 -10
  22. package/dist/llm/clients/types.d.ts +18 -1
  23. package/dist/llm/clients/types.js +4 -0
  24. package/dist/llm/config.d.ts +9 -2
  25. package/dist/llm/config.js +697 -33
  26. package/dist/llm/services/ModelResolver.d.ts +6 -0
  27. package/dist/llm/services/ModelResolver.js +57 -17
  28. package/dist/llm/services/SettingsManager.d.ts +1 -1
  29. package/dist/llm/services/SettingsManager.js +92 -4
  30. package/dist/llm/types.d.ts +127 -0
  31. package/dist/prompting/index.d.ts +1 -1
  32. package/dist/prompting/index.js +2 -1
  33. package/dist/prompting/parser.d.ts +23 -0
  34. package/dist/prompting/parser.js +33 -0
  35. package/dist/shared/adapters/errorUtils.d.ts +15 -0
  36. package/dist/shared/adapters/errorUtils.js +69 -1
  37. package/dist/shared/adapters/logprobsUtils.d.ts +13 -0
  38. package/dist/shared/adapters/logprobsUtils.js +33 -0
  39. package/dist/shared/services/withRetry.d.ts +50 -0
  40. package/dist/shared/services/withRetry.js +78 -0
  41. package/package.json +59 -59
  42. package/src/config/image-presets.json +212 -212
  43. 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.8.3",
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
+ }