@7n/llm-lib 2.9.9 → 2.10.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.10.1] - 2026-07-27
4
+
5
+ ### Fixed
6
+
7
+ - Smoke-тест `resolveModel` через живий napi-аддон стабільний під `bun run --bun vitest`: каскад ганяється в дочірньому процесі з env при spawn, бо Bun не передає записи `process.env` у нативний environ (Rust `env::var` бачив ambient-значення замість `vi.stubEnv`)
8
+
9
+ ## [2.10.0] - 2026-07-27
10
+
11
+ ### Added
12
+
13
+ - llm-lib: додано litellm як другий local-provider (перемикач omlx/litellm через `N_LOCAL_*_MODEL`, `defaultLocalProviders()` з `N_OMLX_*`/`N_LITELLM_*` env)
14
+
3
15
  ## [2.9.9] - 2026-07-27
4
16
 
5
17
  ### Fixed
package/lib/docs/index.md CHANGED
@@ -16,6 +16,7 @@ resource: llm-lib/lib/
16
16
  | [chains-report.mjs](chains-report.md) | JS Module |
17
17
  | [harness.mjs](harness.md) | JS Module |
18
18
  | [local-cloud.mjs](local-cloud.md) | JS Module |
19
+ | [local-providers.mjs](local-providers.md) | JS Module |
19
20
  | [model-tiers.mjs](model-tiers.md) | JS Module |
20
21
  | [one-shot.mjs](one-shot.md) | JS Module |
21
22
  | [prompt-budget.mjs](prompt-budget.md) | JS Module |
@@ -0,0 +1,29 @@
1
+ ---
2
+ type: JS Module
3
+ title: local-providers.mjs
4
+ resource: llm-lib/lib/local-providers.mjs
5
+ docgen:
6
+ crc: 6513b04f
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 100
10
+ judgeModel: openai-codex/gpt-5.4-mini
11
+ ---
12
+
13
+ ## Огляд
14
+
15
+ Дефолтна мапа local-провайдерів для `llm_lib::local_cloud` у форматі `{ prefix: { baseUrl, apiKey } }`, яку споживають `oneShotLocalCloud` і `submitBatch`.
16
+
17
+ `omlx` і `litellm` завжди присутні в мапі одночасно, а фактичний виклик іде рівно в один клієнт за `provider`-префіксом у model-spec. Якщо spec не вказує на певний префікс, відповідний запис у мапі не отримує запиту.
18
+
19
+ ## Поведінка
20
+
21
+ 1. `defaultLocalProviders` формує єдиний дефолтний набір local-провайдерів для `llm_lib::local_cloud`, щоб обидва зареєстровані напрямки — `omlx` і `litellm` — були доступні одночасно в очікуваному `{ prefix: { baseUrl, apiKey } }` форматі для `oneShotLocalCloud` і `submitBatch`.
22
+ 2. Для `omlx` функція бере `baseUrl` з `N_OMLX_BASE_URL`, а якщо його немає — підставляє `http://127.0.0.1:8000/v1/`; `apiKey` бере з `N_OMLX_API_KEY`, інакше лишає порожнім значенням.
23
+ 3. Для `litellm` функція бере `baseUrl` з `N_LITELLM_BASE_URL`, а якщо його немає — підставляє `https://llm.7n.ai/v1/`; `apiKey` бере з `N_LITELLM_API_KEY`, інакше лишає порожнім значенням.
24
+ 4. Функція не вирішує, який провайдер “активний” сама по собі: вибір фактично визначається тим, який provider-префікс вказаний у model-spec на кшталт `N_LOCAL_MIN_MODEL`.
25
+ 5. Коли model-spec вказує на один префікс, `LocalCloud::one_shot_with_spec` звертається рівно до відповідного клієнта; другий запис у мапі залишається запасним і не отримує запитів, доки жоден spec на нього не посилається.
26
+
27
+ ## Гарантії поведінки
28
+
29
+ - Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
@@ -3,9 +3,9 @@ type: JS Module
3
3
  title: model-tiers.mjs
4
4
  resource: llm-lib/lib/model-tiers.mjs
5
5
  docgen:
6
- crc: 13970c1f
7
- model: openai-codex/gpt-5.5
8
- tier: cloud-avg
6
+ crc: 05c5eb6a
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
9
  score: 100
10
10
  issues: judge-refine:kept-original,judge:inaccurate:0.97
11
11
  judgeModel: openai-codex/gpt-5.4-mini
@@ -13,21 +13,17 @@ docgen:
13
13
 
14
14
  ## Огляд
15
15
 
16
- Модуль централізує вибір і нормалізацію LLM-моделей для local та cloud tier значень. Він дає спільну точку для розбору і форматування model spec, визначення локальності моделі та зіставлення tier із рівнем thinking.
16
+ `LOCAL_MIN`, `LOCAL_AVG`, `LOCAL_MAX`, `CLOUD_MIN`, `CLOUD_AVG` і `CLOUD_MAX` задають спільні варіанти модельного рівня для локального та хмарного сценаріїв, щоб споживачі використовували однакові значення для вибору режиму роботи. `parseModelId` і `formatModelSpec` узгоджують подання модельного ідентифікатора між внутрішнім представленням і зовнішнім форматом, а `resolveModel` повертає уже погоджений варіант для подальшого використання. `thinkingLevelForTier` фіксує відповідність між tier і рівнем thinking, а `isLocalModel` дає змогу відрізнити локальні моделі від інших без дублювання цієї перевірки в різних місцях.
17
17
 
18
18
  ## Поведінка
19
19
 
20
- Модуль задає спільну env-політику вибору моделей через LOCAL_MIN, LOCAL_AVG, LOCAL_MAX, CLOUD_MIN, CLOUD_AVG і CLOUD_MAX. Ці значення є вхідним станом для подальшого резолву та класифікації: порожнє значення означає, що відповідний tier не заданий явно.
20
+ LOCAL_MIN, LOCAL_AVG, LOCAL_MAX, CLOUD_MIN, CLOUD_AVG і CLOUD_MAX беруть значення з environment на старті модуля та задають єдину політику вибору моделі для локального й хмарного шарів. Ці значення далі слугують опорою для resolveModel, який повертає вже фактично обраний model spec у форматі provider/model-id або порожній рядок, якщо дефолт провайдера лишився substrate-рівню. Невідомий tier відсіюється на цьому рівні як помилка контракту.
21
21
 
22
- resolveModel приймає абстрактний tier і повертає фактичний model spec у форматі pi. Вибір делегується нативному шару, щоб JavaScript-споживачі отримували той самий каскад, що й Rust-частина. Якщо каскад не знаходить явної моделі, результатом стає порожній рядок, який залишає вибір дефолтної моделі нижчому шару.
22
+ thinkingLevelForTier переводить rung-tier у дискретний рівень thinking, щоб downstream-логіка могла узгоджено трактувати силу моделі без повторного аналізу spec. local-min і local-min-retry зводяться до найнижчого рівня, cloud-min, cloud-avg і cloud-max піднімають рівень відповідно до потужності хмарного вибору.
23
23
 
24
- parseModelId і formatModelSpec підтримують єдиний формат обміну між конфігурацією, результатами resolveModel і pi-моделями. parseModelId відкидає некоректні або неповні model spec, а formatModelSpec перетворює фактично вибрану pi-модель назад у той самий текстовий формат для подальшого порівняння чи логування.
24
+ parseModelId і formatModelSpec утворюють парний обмін між рядковим model spec та об’єктом моделі: перший розбирає канонічний рядок на provider та id, другий збирає фактично резолвлену модель назад у той самий формат. Якщо spec або модель неповні, результатом є null, щоб не маскувати malformed або відсутній стан.
25
25
 
26
- isLocalModel використовує спільні LOCAL_* значення та список локальних провайдерів з оточення, щоб визначити, чи фактично вибрана або явно задана модель є локальною. Для цього результат resolveModel або formatModelSpec може бути переданий у isLocalModel після нормалізації через спільний формат.
27
-
28
- thinkingLevelForTier працює з rung-рівнями escalation-ланцюжка й повертає дискретний рівень thinking для виконання запиту. Це рішення незалежне від env-конфігурації моделей, але використовується поруч із resolveModel у потоках, де одночасно обираються модельний tier і інтенсивність міркування.
29
-
30
- Файл не виконує власних операцій запису у ФС чи БД; результати передаються назовні як значення для споживачів LLM-шару. Імпортовані модулі не аналізувались.
26
+ isLocalModel використовує ту саму політику, що й resolveModel: спочатку звіряє явні локальні тири, а потім визначає локальність за provider із model spec. Це дає спільне правило для агрегатів local/cloud і для рішень, де потрібно відрізнити локальний шлях від хмарного без дублювання логіки в consumers.
31
27
 
32
28
  ## Публічний API
33
29
 
@@ -55,9 +51,17 @@ cloud-min — `medium`, cloud-avg — `high`, cloud-max (experiment-only tier,
55
51
  pi-моделі (`session.model`), коли consumer лишив `modelSpec` порожнім і pi
56
52
  сам вибрав дефолт (локальний чи хмарний).
57
53
  - isLocalModel — Чи model-spec вказує на локальну модель: збіг з одним із LOCAL_* тирів
58
- АБО провайдер з `N_LLM_LOCAL_PROVIDERS` (дефолт `omlx`). Використовується
54
+ АБО провайдер з `N_LLM_LOCAL_PROVIDERS` (дефолт `omlx,litellm`). Обидва
55
+ провайдери можуть бути зареєстровані в `localProviders`-конфізі одночасно
56
+ (див. `local-providers.mjs`) — "активний" завжди рівно один, бо
57
+ `LocalCloud` викликає клієнта за провайдер-префіксом фактичного
58
+ model-spec, не за наявністю запису в мапі. Використовується
59
59
  для local/cloud-агрегатів ланцюжків і рішення про chain-заголовки.
60
60
 
61
+ ## Сценарії використання
62
+
63
+ - `llm-lib/tests/model-tiers.test.mjs` (isLocalModel; parseModelId) — omlx-провайдер — локальний (дефолт N_LLM_LOCAL_PROVIDERS); litellm-провайдер — теж локальний за дефолтом (перемикач omlx/litellm через тир-env); порожній/malformed spec — не локальний; кастомний список провайдерів через env (ізольований re-import); звичайна пара; ще 8
64
+
61
65
  ## Гарантії поведінки
62
66
 
63
67
  - Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Дефолтна мапа local-провайдерів для Rust-крейта `llm_lib::local_cloud`
3
+ * (той самий `{ prefix: { baseUrl, apiKey } }` конфіг, що приймає
4
+ * `oneShotLocalCloud`/`submitBatch`). Обидва зареєстровані провайдери
5
+ * (`omlx`, `litellm`) завжди присутні в мапі одночасно — "активність"
6
+ * визначається лише тим, чий provider-префікс реально стоїть у
7
+ * model-spec (`N_LOCAL_MIN_MODEL` тощо): `LocalCloud::one_shot_with_spec`
8
+ * б'є рівно в один клієнт за префіксом spec, тож другий запис у мапі
9
+ * ніколи не отримує запиту, поки на нього не вказує жоден spec.
10
+ */
11
+ import { env } from 'node:process'
12
+
13
+ /**
14
+ * @returns {{
15
+ * omlx: { baseUrl: string, apiKey: string|null },
16
+ * litellm: { baseUrl: string, apiKey: string|null }
17
+ * }} дефолтна мапа локальних провайдерів (override окремих полів — через
18
+ * `N_OMLX_BASE_URL`/`N_OMLX_API_KEY`/`N_LITELLM_BASE_URL`/`N_LITELLM_API_KEY`)
19
+ */
20
+ export function defaultLocalProviders() {
21
+ return {
22
+ omlx: {
23
+ baseUrl: env.N_OMLX_BASE_URL ?? 'http://127.0.0.1:8000/v1/',
24
+ apiKey: env.N_OMLX_API_KEY ?? null
25
+ },
26
+ litellm: {
27
+ baseUrl: env.N_LITELLM_BASE_URL ?? 'https://llm.7n.ai/v1/',
28
+ apiKey: env.N_LITELLM_API_KEY ?? null
29
+ }
30
+ }
31
+ }
@@ -107,7 +107,7 @@ export function formatModelSpec(model) {
107
107
 
108
108
  /** Провайдери, що вважаються локальними. Override: `N_LLM_LOCAL_PROVIDERS` (кома-список). */
109
109
  const LOCAL_PROVIDERS = new Set(
110
- (env.N_LLM_LOCAL_PROVIDERS ?? 'omlx')
110
+ (env.N_LLM_LOCAL_PROVIDERS ?? 'omlx,litellm')
111
111
  .split(',')
112
112
  .map(p => p.trim())
113
113
  .filter(Boolean)
@@ -115,7 +115,11 @@ const LOCAL_PROVIDERS = new Set(
115
115
 
116
116
  /**
117
117
  * Чи model-spec вказує на локальну модель: збіг з одним із LOCAL_* тирів
118
- * АБО провайдер з `N_LLM_LOCAL_PROVIDERS` (дефолт `omlx`). Використовується
118
+ * АБО провайдер з `N_LLM_LOCAL_PROVIDERS` (дефолт `omlx,litellm`). Обидва
119
+ * провайдери можуть бути зареєстровані в `localProviders`-конфізі одночасно
120
+ * (див. `local-providers.mjs`) — "активний" завжди рівно один, бо
121
+ * `LocalCloud` викликає клієнта за провайдер-префіксом фактичного
122
+ * model-spec, не за наявністю запису в мапі. Використовується
119
123
  * для local/cloud-агрегатів ланцюжків і рішення про chain-заголовки.
120
124
  * @param {string} spec `"provider/model-id"`
121
125
  * @returns {boolean} true — локальна модель
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/llm-lib",
3
- "version": "2.9.9",
3
+ "version": "2.10.1",
4
4
  "description": "Тонкий шар роботи з LLM (локальні omlx + хмарні провайдери) поверх pi: model tiers, one-shot, agentic-раннери, write-guard, trace, telemetry, prompt-budget",
5
5
  "keywords": [
6
6
  "nitra",
@@ -36,6 +36,7 @@
36
36
  "./anchored-edit": "./lib/anchored-edit.mjs",
37
37
  "./web-tools": "./lib/web-tools.mjs",
38
38
  "./model-tiers": "./lib/model-tiers.mjs",
39
+ "./local-providers": "./lib/local-providers.mjs",
39
40
  "./acp": "./lib/acp.mjs",
40
41
  "./local-cloud": "./lib/local-cloud.mjs",
41
42
  "./batch": "./lib/batch.mjs",