@7n/llm-lib 2.13.0 → 2.13.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/CHANGELOG.md +14 -0
- package/lib/acp.mjs +6 -5
- package/lib/agent-skill.mjs +4 -3
- package/lib/batch.mjs +2 -2
- package/lib/docs/acp.md +6 -7
- package/lib/docs/agent-skill.md +15 -17
- package/lib/docs/batch.md +28 -16
- package/lib/docs/local-cloud.md +15 -12
- package/lib/docs/local-providers.md +21 -11
- package/lib/docs/model-tiers.md +13 -21
- package/lib/docs/one-shot.md +21 -16
- package/lib/local-cloud.mjs +3 -3
- package/lib/model-tiers.mjs +27 -16
- package/lib/one-shot.mjs +3 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.13.2] - 2026-07-29
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Уніфіковано вибір моделей через `resolveModel`: явні local/cloud selectors
|
|
8
|
+
використовують спільну Rust-драбину, а one-shot і agent runners вимагають
|
|
9
|
+
tier або explicit model policy.
|
|
10
|
+
|
|
11
|
+
## [2.13.1] - 2026-07-29
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- local-providers.test: герметизація від ambient N_OMLX_*/N_LITELLM_* env (тест «без env» падав на машинах зі справжнім N_LITELLM_API_KEY)
|
|
16
|
+
|
|
3
17
|
## [2.13.0] - 2026-07-29
|
|
4
18
|
|
|
5
19
|
### Changed
|
package/lib/acp.mjs
CHANGED
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
* watchdog-поведінкою на мертвий/незапущений дочірній процес.
|
|
11
11
|
*
|
|
12
12
|
* `claude` тут немає — Rust-крейт моделює лише `cursor`/`codex`/`pi`
|
|
13
|
-
* (`AcpAgentKind`);
|
|
14
|
-
* JS-шимом у `@7n/rules` (`npm/scripts/lib/acp-runner.mjs`).
|
|
13
|
+
* (`AcpAgentKind`); `claude` тут навмисно не підтримується.
|
|
15
14
|
*/
|
|
16
15
|
import { loadNative } from './internal/native.mjs'
|
|
17
16
|
|
|
@@ -20,17 +19,19 @@ import { loadNative } from './internal/native.mjs'
|
|
|
20
19
|
* рішення И) — опційний абстрактний тир (`min`/`avg`/`max`): якщо заданий,
|
|
21
20
|
* Rust сам резолвить tier→env/args/post-session-config з пресету агента
|
|
22
21
|
* (`one_shot_acp_with_tier`) — жодного JS-хелпера "пресет→env" тут немає.
|
|
23
|
-
* Без `tier`
|
|
22
|
+
* Без `tier` виклик заборонений, крім явного `mode:'interactive'` для персонального CLI-конфіга.
|
|
24
23
|
* @param {'cursor' | 'codex' | 'pi'} kind провайдер
|
|
25
24
|
* @param {string} prompt промпт
|
|
26
25
|
* @param {string} cwd робочий каталог сесії агента (каталог проєкту-викликача)
|
|
27
26
|
* @param {{
|
|
28
|
-
* tier?: 'min' | 'avg' | 'max',
|
|
27
|
+
* tier?: 'min' | 'avg' | 'max', mode?: 'interactive',
|
|
29
28
|
* native?: { oneShotAcp: (kind: string, prompt: string, cwd: string, tier?: string) => Promise<string> }
|
|
30
29
|
* }} [options] тир + інжект `native` для тестів (той самий 4-й аргумент, що й раніше — сумісність зі старим `{ native }`-викликом збережена)
|
|
31
30
|
* @returns {Promise<string>} повний текст відповіді до кінця ходу
|
|
32
31
|
*/
|
|
33
|
-
export function runAcpAgent(kind, prompt, cwd, { tier, native } = {}) {
|
|
32
|
+
export function runAcpAgent(kind, prompt, cwd, { tier, mode, native } = {}) {
|
|
33
|
+
if (!tier && mode !== 'interactive') throw new TypeError('runAcpAgent: передай tier або явно mode:"interactive"')
|
|
34
|
+
if (tier && mode) throw new TypeError('runAcpAgent: tier і mode взаємовиключні')
|
|
34
35
|
const nativeImpl = native ?? loadNative()
|
|
35
36
|
return nativeImpl.oneShotAcp(kind, prompt, cwd, tier)
|
|
36
37
|
}
|
package/lib/agent-skill.mjs
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Виконує один скіл як pi-агента: готовий промпт-рядок → `session.prompt`.
|
|
7
7
|
* Повний user-trust набір вбудованих tools (`read/grep/find/edit/write/ls/bash`), БЕЗ
|
|
8
8
|
* write-guard — скіл є явною user-invocation (паритет із `claude -p`, який теж без
|
|
9
|
-
* обмежень). Модель
|
|
9
|
+
* обмежень). Модель задається явним тиром або `modelSpec`, без escalation-сходів fix-engine.
|
|
10
10
|
* Runaway-backstop: turn-ceiling + per-call timeout. Асистентський текст стрімиться
|
|
11
11
|
* у stdout (паритет із `claude -p`). Телеметрія `kind:"skill"` у глобальний trace.
|
|
12
12
|
*
|
|
@@ -80,7 +80,7 @@ async function defaultCreateSession({ registry, model, cwd, thinkingLevel, maxTo
|
|
|
80
80
|
export async function runAgentSkill(prompt, opts = {}) {
|
|
81
81
|
const {
|
|
82
82
|
skillId = 'skill',
|
|
83
|
-
tier
|
|
83
|
+
tier,
|
|
84
84
|
modelSpec,
|
|
85
85
|
cwd = process.cwd(),
|
|
86
86
|
thinkingLevel,
|
|
@@ -122,7 +122,8 @@ export async function runAgentSkill(prompt, opts = {}) {
|
|
|
122
122
|
let model
|
|
123
123
|
try {
|
|
124
124
|
registry = deps.registry ?? (await getReg())
|
|
125
|
-
|
|
125
|
+
if (!modelSpec && !tier) return fail('model selection: передай tier або явний modelSpec', null)
|
|
126
|
+
spec = modelSpec || resolveModel(tier)
|
|
126
127
|
model = spec ? resolveModelSpec(registry, spec) : null
|
|
127
128
|
if (spec && !model) return fail(`модель не знайдена: ${spec}`, spec)
|
|
128
129
|
} catch (error) {
|
package/lib/batch.mjs
CHANGED
|
@@ -29,8 +29,8 @@ import { loadNative } from './internal/native.mjs'
|
|
|
29
29
|
/**
|
|
30
30
|
* Batch-виклик Типу 2b. `modelSpecOrTier` — той самий контракт, що й у
|
|
31
31
|
* [`oneShotLocalCloud`] з `local-cloud.mjs`: явний `"provider/model-id"`
|
|
32
|
-
*
|
|
33
|
-
* @param {string} modelSpecOrTier `"provider/model-id"
|
|
32
|
+
* абстрактний тир (`min`/`avg`/`max`) або явний env-selector.
|
|
33
|
+
* @param {string} modelSpecOrTier `"provider/model-id"`, tier або env-selector
|
|
34
34
|
* @param {BatchItem[]} items вхідні items (`customId` — унікальний у межах виклику)
|
|
35
35
|
* @param {{
|
|
36
36
|
* localProviders?: Record<string, { baseUrl: string, apiKey?: string | null }>,
|
package/lib/docs/acp.md
CHANGED
|
@@ -3,9 +3,9 @@ type: JS Module
|
|
|
3
3
|
title: acp.mjs
|
|
4
4
|
resource: llm-lib/lib/acp.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
model:
|
|
8
|
-
tier:
|
|
6
|
+
crc: 022452f4
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
tier: cloud-min
|
|
9
9
|
score: 80
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -22,8 +22,7 @@ ACP JSON-RPC/`ClientSideConnection` тут; уся протокольна лог
|
|
|
22
22
|
watchdog-поведінкою на мертвий/незапущений дочірній процес.
|
|
23
23
|
|
|
24
24
|
`claude` тут немає — Rust-крейт моделює лише `cursor`/`codex`/`pi`
|
|
25
|
-
(`AcpAgentKind`);
|
|
26
|
-
JS-шимом у `@7n/rules` (`npm/scripts/lib/acp-runner.mjs`).
|
|
25
|
+
(`AcpAgentKind`); `claude` тут навмисно не підтримується.
|
|
27
26
|
|
|
28
27
|
## Публічний API
|
|
29
28
|
|
|
@@ -31,11 +30,11 @@ JS-шимом у `@7n/rules` (`npm/scripts/lib/acp-runner.mjs`).
|
|
|
31
30
|
рішення И) — опційний абстрактний тир (`min`/`avg`/`max`): якщо заданий,
|
|
32
31
|
Rust сам резолвить tier→env/args/post-session-config з пресету агента
|
|
33
32
|
(`one_shot_acp_with_tier`) — жодного JS-хелпера "пресет→env" тут немає.
|
|
34
|
-
Без `tier`
|
|
33
|
+
Без `tier` виклик заборонений, крім явного `mode:'interactive'` для персонального CLI-конфіга.
|
|
35
34
|
|
|
36
35
|
## Сценарії використання
|
|
37
36
|
|
|
38
|
-
- `llm-lib/tests/acp.test.mjs` (runAcpAgent; getAcpPresets (smoke через реально збудований napi-аддон)) — делегує kind/prompt/cwd у native.oneShotAcp і віддає його результат; без
|
|
37
|
+
- `llm-lib/tests/acp.test.mjs` (runAcpAgent; getAcpPresets (smoke через реально збудований napi-аддон)) — interactive mode делегує kind/prompt/cwd у native.oneShotAcp і віддає його результат; без tier або interactive mode — fail-closed; tier прокидається в native.oneShotAcp четвертим аргументом; kind
|
|
39
38
|
|
|
40
39
|
## Гарантії поведінки
|
|
41
40
|
|
package/lib/docs/agent-skill.md
CHANGED
|
@@ -3,33 +3,31 @@ type: JS Module
|
|
|
3
3
|
title: agent-skill.mjs
|
|
4
4
|
resource: llm-lib/lib/agent-skill.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 7c86fb8b
|
|
7
7
|
model: openai-codex/gpt-5.4-mini
|
|
8
8
|
tier: cloud-min
|
|
9
9
|
score: 100
|
|
10
|
-
issues: judge:
|
|
10
|
+
issues: judge-refine:kept-original,judge:inaccurate:0.99
|
|
11
11
|
judgeModel: openai-codex/gpt-5.4-mini
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## Огляд
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Файл запускає один агентський skill-run і передає виконання в існуючу сесію, щоб пов’язати його з обраним tier або modelSpec та зберегти трасування контексту. Це потрібно, щоб виклик або завершився успішно, або повернув діагностовану помилку; частина fail-safe гілок обробляється локально, а інші помилки можуть поширюватися назовні.
|
|
17
17
|
|
|
18
18
|
## Поведінка
|
|
19
19
|
|
|
20
|
-
1. Приймає готовий prompt для одного skill
|
|
21
|
-
2.
|
|
22
|
-
3.
|
|
23
|
-
4.
|
|
24
|
-
5.
|
|
25
|
-
6.
|
|
26
|
-
7.
|
|
27
|
-
8.
|
|
28
|
-
9.
|
|
29
|
-
10.
|
|
30
|
-
11.
|
|
31
|
-
12. Передає результат у chain і trace, а також зберігає capture для подальшого аналізу прогону.
|
|
32
|
-
13. Повертає ознаку успіху, telemetry і текст помилки; успіх можливий лише коли немає помилки й не спрацював backstop.
|
|
20
|
+
1. Приймає готовий prompt для одного skill-run і фіксує контекст виконання: skill, tier, modelSpec, cwd, thinkingLevel, timeout, maxTokens, caller та chain.
|
|
21
|
+
2. Перемикає ланцюжок на наступний крок, якщо chain передано, і готує контрольну позначку для трасування запиту.
|
|
22
|
+
3. Перевіряє, чи задано спосіб вибору моделі: або tier, або явний modelSpec. Якщо ні — завершує невдачею без запуску сесії.
|
|
23
|
+
4. Визначає цільову модель і перевіряє, чи вона доступна в registry. Якщо модель не знайдена або registry недоступний — завершує невдачею з діагностикою.
|
|
24
|
+
5. Створює агентську сесію з повним набором вбудованих tools і без write-guard; для локальних моделей може підключити chain-кореляцію, для інших — ні.
|
|
25
|
+
6. Підписується на події сесії, щоб рахувати turns і tool-виклики, стрімити текст відповіді у stdout та зберегти підсумкове usage з фінального повідомлення.
|
|
26
|
+
7. Запускає виконання prompt із пер-call timeout і runaway-backstop на turns. Якщо ліміт turns перевищено або спрацьовує timeout, сесію зупиняє.
|
|
27
|
+
8. Якщо під час запуску виникає memory-guard rejection для локального model-сервера, повертає failure-поведінку з друком prompt і помилкою замість structured result.
|
|
28
|
+
9. Після завершення формує підсумок виконання: фактичну модель, кількість turns, кількість tool-викликів, факт спрацювання backstop і тривалість.
|
|
29
|
+
10. Оновлює chain і trace, а також зберігає capture-дані для подальшого аналізу: prompt, output, usage, error і кореляційні поля.
|
|
30
|
+
11. Повертає успіх лише тоді, коли немає помилки і не спрацював backstop; інакше повертає невдачу з telemetry, де це можливо.
|
|
33
31
|
|
|
34
32
|
## Публічний API
|
|
35
33
|
|
|
@@ -37,7 +35,7 @@ docgen:
|
|
|
37
35
|
|
|
38
36
|
## Сценарії використання
|
|
39
37
|
|
|
40
|
-
- `llm-lib/tests/agent-skill.test.mjs` (runAgentSkill) — happy-path: ok, телеметрія, стрім тексту, trace kind:; createSession отримує тиру → thinkingLevel і cwd; maxTokens прокидається у createSession (0 = без стелі); з chain: step/note/chain-поля у trace; хмарна модель → chain:null у сесію; modelSpec
|
|
38
|
+
- `llm-lib/tests/agent-skill.test.mjs` (runAgentSkill) — happy-path: ok, телеметрія, стрім тексту, trace kind:; createSession отримує тиру → thinkingLevel і cwd; maxTokens прокидається у createSession (0 = без стелі); з chain: step/note/chain-поля у trace; хмарна модель → chain:null у сесію; явний modelSpec зберігається у telemetry; ще 5
|
|
41
39
|
|
|
42
40
|
## Гарантії поведінки
|
|
43
41
|
|
package/lib/docs/batch.md
CHANGED
|
@@ -3,31 +3,43 @@ type: JS Module
|
|
|
3
3
|
title: batch.mjs
|
|
4
4
|
resource: llm-lib/lib/batch.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
model: openai-codex/gpt-5.
|
|
8
|
-
tier: cloud-
|
|
9
|
-
score:
|
|
6
|
+
crc: ce0ba158
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
tier: cloud-min
|
|
9
|
+
score: 100
|
|
10
10
|
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## Огляд
|
|
14
14
|
|
|
15
|
-
Тип 2b (OpenAI-сумісний API, batch) —
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
Тип 2b (OpenAI-сумісний API, batch) — `submitBatch` обирає між клієнтською
|
|
16
|
+
емуляцією (v1, чанкований конкурентний прогін через Тип 2a
|
|
17
|
+
`llm_lib::local_cloud`) і справжнім `/v1/batches` litellm batch-adapter-а
|
|
18
|
+
(спека `docs/specs/2026-07-27-batch-local-avg-real-batches.md`), під тим
|
|
19
|
+
самим інтерфейсом `submit → progress → results` для обох. Вибір —
|
|
20
|
+
`backend` (дефолт `'auto'`: реальний Batch API лише коли резолвлений
|
|
21
|
+
провайдер `litellm` і кешована мережева проба адаптера пройшла; локальний
|
|
22
|
+
omlx завжди йде емуляцією).
|
|
20
23
|
|
|
21
|
-
Тонкий JS-клієнт до Rust-крейта `llm_lib::batch`
|
|
22
|
-
in-process (`llm-lib/crates/llm-lib-napi`) — жодного
|
|
23
|
-
тут (анти-приклад, якого це узагальнює:
|
|
24
|
-
переклади проти omlx вручну, з
|
|
24
|
+
Тонкий JS-клієнт до Rust-крейта `llm_lib::batch`/`llm_lib::remote_batch`
|
|
25
|
+
через napi FFI in-process (`llm-lib/crates/llm-lib-napi`) — жодного
|
|
26
|
+
власного чанкінгу чи HTTP тут (анти-приклад, якого це узагальнює:
|
|
27
|
+
`mlmail/use-summary.js` чанкує переклади проти omlx вручну, з
|
|
28
|
+
вистражданими лімітами).
|
|
29
|
+
|
|
30
|
+
## Поведінка
|
|
31
|
+
|
|
32
|
+
submitBatch працює з набором batch-елементів як з одним запитом: для кожного елемента зберігається зв’язок між `customId` і відповіддю, а порядок результатів відповідає порядку вхідних `items`.
|
|
33
|
+
|
|
34
|
+
Якщо для елемента є помилка, у результаті повертається запис з `error` замість `ok`; для одного елемента заповнюється рівно одне з цих полів. Це дає змогу обробляти частково успішні batch-и без втрати прив’язки до конкретного `customId`.
|
|
35
|
+
|
|
36
|
+
Передані `system`, `localProviders`, `backend`, `chunkSize`, `concurrency`, `pollIntervalMs` і `pollTimeoutMs` впливають на поведінку batch-виклику, а `onProgress` дозволяє отримувати проміжний стан виконання.
|
|
25
37
|
|
|
26
38
|
## Публічний API
|
|
27
39
|
|
|
28
|
-
- submitBatch —
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
- submitBatch — Batch-виклик Типу 2b. `modelSpecOrTier` — той самий контракт, що й у
|
|
41
|
+
[`oneShotLocalCloud`] з `local-cloud.mjs`: явний `"provider/model-id"`
|
|
42
|
+
абстрактний тир (`min`/`avg`/`max`) або явний env-selector.
|
|
31
43
|
|
|
32
44
|
## Сценарії використання
|
|
33
45
|
|
package/lib/docs/local-cloud.md
CHANGED
|
@@ -3,32 +3,35 @@ type: JS Module
|
|
|
3
3
|
title: local-cloud.mjs
|
|
4
4
|
resource: llm-lib/lib/local-cloud.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: cedae6fe
|
|
7
7
|
model: openai-codex/gpt-5.5
|
|
8
8
|
tier: cloud-avg
|
|
9
|
-
score:
|
|
9
|
+
score: 80
|
|
10
10
|
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## Огляд
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Тип 2a (OpenAI-сумісний API, sync) для Node — прямий HTTP до OpenAI-compatible
|
|
16
|
+
ендпоінта (`chat/completions`): локальні провайдери (напр. omlx) і хмарні
|
|
17
|
+
(стандартна автентифікація провайдера) — без агентського циклу.
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
3. Передає текст користувача, optional system-повідомлення та конфігурацію локальних провайдерів до in-process Rust-клієнта через napi FFI.
|
|
22
|
-
4. Делегує HTTP-взаємодію з OpenAI-compatible ендпоінтом Rust-реалізації, щоб у JS-шарі не виникало окремого клієнта й розрізненого читання `settings.json`.
|
|
23
|
-
5. Повертає текст відповіді моделі як результат одного синхронного за сценарієм запиту.
|
|
19
|
+
Тонкий JS-клієнт до Rust-крейта `llm_lib::local_cloud` через napi FFI
|
|
20
|
+
in-process (`llm-lib/crates/llm-lib-napi`) — жодного власного HTTP-клієнта
|
|
21
|
+
тут (анти-приклад, якого це уникає: `mlmail` читає `~/.omlx/settings.json`
|
|
22
|
+
і б'є в ендпоінт напряму замість спільної точки, задача T5/рішення Н).
|
|
24
23
|
|
|
25
24
|
## Публічний API
|
|
26
25
|
|
|
27
|
-
- oneShotLocalCloud — Один chat-виклик Типу 2a. `modelSpecOrTier` —
|
|
28
|
-
|
|
26
|
+
- oneShotLocalCloud — Один chat-виклик Типу 2a. `modelSpecOrTier` — явний `"provider/model-id"`,
|
|
27
|
+
абстрактний tier або `N_LOCAL_*_MODEL`/`N_CLOUD_*_MODEL` selector
|
|
29
28
|
через ту саму [`llm_lib::resolve_model`], що й `resolveModel` з
|
|
30
29
|
`model-tiers.mjs`.
|
|
31
30
|
|
|
31
|
+
## Сценарії використання
|
|
32
|
+
|
|
33
|
+
- `llm-lib/tests/local-cloud.test.mjs` (oneShotLocalCloud) — делегує modelSpecOrTier/prompt у native.oneShotLocalCloud і віддає його результат; явний; localProviders і system прокидаються в options; без опцій (лише modelSpecOrTier/prompt) — localProviders/system undefined
|
|
34
|
+
|
|
32
35
|
## Гарантії поведінки
|
|
33
36
|
|
|
34
37
|
- Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
|
|
@@ -3,26 +3,36 @@ type: JS Module
|
|
|
3
3
|
title: local-providers.mjs
|
|
4
4
|
resource: llm-lib/lib/local-providers.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
model: openai-codex/gpt-5.
|
|
8
|
-
tier: cloud-
|
|
6
|
+
crc: cd7b4cfa
|
|
7
|
+
model: openai-codex/gpt-5.5
|
|
8
|
+
tier: cloud-avg
|
|
9
9
|
score: 100
|
|
10
10
|
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## Огляд
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`omlx` і `litellm` завжди присутні в мапі одночасно, а фактичний виклик іде рівно в один клієнт за `provider`-префіксом у model-spec. Якщо spec не вказує на певний префікс, відповідний запис у мапі не отримує запиту.
|
|
15
|
+
Файл надає стандартну мапу local-провайдерів для `llm_lib::local_cloud` у формі `{ prefix: { baseUrl, apiKey } }`, щоб JS-частина могла передати Rust-крейту готові endpoints для `oneShotLocalCloud` і `submitBatch`. `defaultLocalProviders` завжди описує `omlx` і `litellm` одночасно, а фактичний мережевий запит отримує лише провайдер, чий префікс вибрано в model-spec, наприклад `N_LOCAL_MIN_MODEL`.
|
|
18
16
|
|
|
19
17
|
## Поведінка
|
|
20
18
|
|
|
21
|
-
1. `defaultLocalProviders` формує
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
1. `defaultLocalProviders` формує стандартний набір local-провайдерів для `llm_lib::local_cloud`, щоб JS-частина передавала Rust-крейту готову мапу endpoint-ів у спільному форматі.
|
|
20
|
+
|
|
21
|
+
2. До мапи завжди входять `omlx` і `litellm`; наявність обох записів не означає одночасне використання обох провайдерів.
|
|
22
|
+
|
|
23
|
+
3. Активним стає лише провайдер, чий префікс вибрано в model-spec, тому запит спрямовується до одного відповідного клієнта.
|
|
24
|
+
|
|
25
|
+
4. Для `omlx` використовується локальна адреса за замовчуванням `http://127.0.0.1:8000/v1/`, щоб підтримати локальний LLM-сервер без обов’язкової конфігурації.
|
|
26
|
+
|
|
27
|
+
5. Для `litellm` використовується віддалена адреса за замовчуванням `https://llm.7n.ai/v1/`, щоб мати готовий fallback-провайдер для централізованого LLM endpoint-а.
|
|
28
|
+
|
|
29
|
+
6. Значення адрес і ключів доступу можуть надходити з оточення, щоб одна й та сама логіка працювала в локальному, CI та production-середовищах без зміни коду.
|
|
30
|
+
|
|
31
|
+
7. Файл лише збирає конфігурацію провайдерів і не виконує власних операцій запису.
|
|
32
|
+
|
|
33
|
+
## Сценарії використання
|
|
34
|
+
|
|
35
|
+
- `llm-lib/tests/local-providers.test.mjs` (defaultLocalProviders) — без env — дефолтні baseUrl для omlx і litellm, apiKey null; обидва провайдери завжди присутні одночасно (жоден не вимикається іншим); N_OMLX_BASE_URL/N_OMLX_API_KEY перекривають дефолт omlx; N_LITELLM_BASE_URL/N_LITELLM_API_KEY перекривають дефолт litellm
|
|
26
36
|
|
|
27
37
|
## Гарантії поведінки
|
|
28
38
|
|
package/lib/docs/model-tiers.md
CHANGED
|
@@ -3,27 +3,21 @@ type: JS Module
|
|
|
3
3
|
title: model-tiers.mjs
|
|
4
4
|
resource: llm-lib/lib/model-tiers.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
model:
|
|
8
|
-
tier:
|
|
6
|
+
crc: 1953f7a9
|
|
7
|
+
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
+
tier: local-min-retry
|
|
9
9
|
score: 100
|
|
10
|
-
issues: judge
|
|
10
|
+
issues: judge:error
|
|
11
11
|
judgeModel: openai-codex/gpt-5.4-mini
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## Огляд
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Файл відповідає за визначення та вибір моделі для виконання завдань. Він інтерпретує граничні значення, такі як `LOCAL_MIN`, `LOCAL_AVG`, `LOCAL_MAX` для локальних моделей та `CLOUD_MIN`, `CLOUD_AVG`, `CLOUD_MAX` для хмарних моделей. На основі цих значень відбувається пошук відповідної моделі через функцію `resolveModel`. Після вибору моделі, відповідно до її типу, визначається відповідний рівень обробки за допомогою `thinkingLevelForTier`.
|
|
17
17
|
|
|
18
18
|
## Поведінка
|
|
19
19
|
|
|
20
|
-
LOCAL_MIN
|
|
21
|
-
|
|
22
|
-
thinkingLevelForTier переводить rung-tier у дискретний рівень thinking, щоб downstream-логіка могла узгоджено трактувати силу моделі без повторного аналізу spec. local-min і local-min-retry зводяться до найнижчого рівня, cloud-min, cloud-avg і cloud-max піднімають рівень відповідно до потужності хмарного вибору.
|
|
23
|
-
|
|
24
|
-
parseModelId і formatModelSpec утворюють парний обмін між рядковим model spec та об’єктом моделі: перший розбирає канонічний рядок на provider та id, другий збирає фактично резолвлену модель назад у той самий формат. Якщо spec або модель неповні, результатом є null, щоб не маскувати malformed або відсутній стан.
|
|
25
|
-
|
|
26
|
-
isLocalModel використовує ту саму політику, що й resolveModel: спочатку звіряє явні локальні тири, а потім визначає локальність за provider із model spec. Це дає спільне правило для агрегатів local/cloud і для рішень, де потрібно відрізнити локальний шлях від хмарного без дублювання логіки в consumers.
|
|
20
|
+
Значення `LOCAL_MIN`, `LOCAL_AVG`, `LOCAL_MAX`, `CLOUD_MIN`, `CLOUD_AVG`, `CLOUD_MAX` визначаються через змінні середовища, використовуючи префікси, які можуть бути налаштовані для вказівки на конкретні моделі. Ці значення слугують стартовими точками для визначення моделі та її рівні у ланцюжку. Коли викликається `resolveModel` з певною стартовою сходинкою, ця сходинка використовується для каскадного пошуку моделі, починаючи з локальних мінімальних та переходячи до хмарних, якщо необхідна модель не знайдена локально. Результат `resolveModel` повертає ідентифікатор моделі у форматі `"provider/model-id"`. Цей ідентифікатор може бути перетворений на пару `provider` та `id` за допомогою `parseModelId` або знову відформатований назад у `"provider/model-id"` за допомогою `formatModelSpec`, що корисно при отриманні дефолтної моделі від системи. `isLocalModel` приймає специфікатор моделі та визначає, чи належить вона до локальних моделей, спираючись на визначені стартові тири або на налаштування провайдерів у змінній середовища. Якщо ідентифікатор моделі відомий, `thinkingLevelForTier` визначає відповідний рівень складності (від `low` до `xhigh`) на основі того, який із визначених тирів був обраний.
|
|
27
21
|
|
|
28
22
|
## Публічний API
|
|
29
23
|
|
|
@@ -33,14 +27,12 @@ isLocalModel використовує ту саму політику, що й re
|
|
|
33
27
|
- CLOUD_MIN — Мінімальний хмарний (потрібен ключ у pi auth). Напр.: openai/gpt-5.4-mini
|
|
34
28
|
- CLOUD_AVG — Середній хмарний. Напр.: openai/gpt-5.4
|
|
35
29
|
- CLOUD_MAX — Максимальний хмарний. Напр.: openai/gpt-5.5
|
|
36
|
-
- resolveModel —
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Тир валідується тут (не в Rust) — щоб зберегти контракт `TypeError` для
|
|
43
|
-
невідомого тиру без потреби мапити помилку з napi-боку.
|
|
30
|
+
- resolveModel — Універсально резолвить модель від явної env-сходинки:
|
|
31
|
+
- LOCAL_MIN → LOCAL_AVG → LOCAL_MAX → CLOUD_MIN → CLOUD_AVG → CLOUD_MAX;
|
|
32
|
+
- LOCAL_AVG → LOCAL_MAX → CLOUD_AVG → CLOUD_MAX;
|
|
33
|
+
- LOCAL_MAX → CLOUD_MAX;
|
|
34
|
+
- cloud-старти проходять лише відповідну й сильніші cloud-сходинки.
|
|
35
|
+
`min`/`avg`/`max` лишаються alias-ами відповідних `N_LOCAL_*_MODEL`.
|
|
44
36
|
- thinkingLevelForTier — `thinkingLevel` за rung-тиром fix-драбини: слабка локальна — `low`,
|
|
45
37
|
cloud-min — `medium`, cloud-avg — `high`, cloud-max (experiment-only tier,
|
|
46
38
|
не в production ladder) — `xhigh`.
|
|
@@ -60,7 +52,7 @@ model-spec, не за наявністю запису в мапі. Викори
|
|
|
60
52
|
|
|
61
53
|
## Сценарії використання
|
|
62
54
|
|
|
63
|
-
- `llm-lib/tests/model-tiers.test.mjs` (isLocalModel; parseModelId) — omlx-провайдер — локальний (дефолт N_LLM_LOCAL_PROVIDERS); litellm-провайдер — теж локальний за дефолтом (перемикач omlx/litellm через тир-env); порожній/malformed spec — не локальний; кастомний список провайдерів через env (ізольований re-import); звичайна пара; ще
|
|
55
|
+
- `llm-lib/tests/model-tiers.test.mjs` (isLocalModel; parseModelId) — omlx-провайдер — локальний (дефолт N_LLM_LOCAL_PROVIDERS); litellm-провайдер — теж локальний за дефолтом (перемикач omlx/litellm через тир-env); порожній/malformed spec — не локальний; кастомний список провайдерів через env (ізольований re-import); звичайна пара; ще 9
|
|
64
56
|
|
|
65
57
|
## Гарантії поведінки
|
|
66
58
|
|
package/lib/docs/one-shot.md
CHANGED
|
@@ -3,32 +3,37 @@ type: JS Module
|
|
|
3
3
|
title: one-shot.mjs
|
|
4
4
|
resource: llm-lib/lib/one-shot.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
model:
|
|
6
|
+
crc: 38adb9ce
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
tier: cloud-min
|
|
9
|
+
score: 100
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
8
11
|
---
|
|
9
12
|
|
|
10
13
|
## Огляд
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
`runOneShot` виконує одноразовий запит до вибраної моделі чи tier без agent-циклу і використовується як точка входу для сценаріїв, де потрібна одна відповідь без подальшої взаємодії. У файлі є локальні fail-safe гілки для окремих збоїв.
|
|
13
16
|
|
|
14
17
|
## Поведінка
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
7. У разі успіху, функція повертає згенерований текст, інформацію про використання моделі, статус помилки та метадані моделі, використовуючи інформацію, зібрану під час взаємодії з сесією.
|
|
19
|
+
1. Приймає набір повідомлень, зводить їх в один запит і рахує його відбиток для подальшого трасування.
|
|
20
|
+
2. Визначає модель виконання: або за явним spec, або за tier; якщо вибір не задано, повертає контрольовану помилку без запуску запиту.
|
|
21
|
+
3. Перевіряє, чи існує запитана модель; якщо ні — завершує виклик керованою помилкою.
|
|
22
|
+
4. Ініціює одноразову сесію без інструментів, щоб отримати plain completion без agent-циклу.
|
|
23
|
+
5. Відправляє запит із лімітом часу; якщо під час виконання виникає memory-guard відмова локального model-сервера, пробиває її назовні як fail-fast сценарій.
|
|
24
|
+
6. Акумулює текст відповіді та службову інформацію про завершення; якщо відповідь обрізана стелею, це фіксується у stop reason для рішення колером.
|
|
25
|
+
7. Після завершення повертає очищений текст відповіді, usage, помилку за потреби, фактичну модель, stop reason і caller.
|
|
26
|
+
8. Додатково пише trace і capture для спостережуваності, але не гарантує обробку всіх зовнішніх помилок.
|
|
25
27
|
|
|
26
28
|
## Публічний API
|
|
27
29
|
|
|
28
|
-
- runOneShot —
|
|
29
|
-
|
|
30
|
+
- runOneShot — Виконує bounded one-shot LLM-виклик.
|
|
31
|
+
|
|
32
|
+
## Сценарії використання
|
|
33
|
+
|
|
34
|
+
- `llm-lib/tests/one-shot.test.mjs` (runOneShot) — happy path: збирає текст + usage; усі messages (system+user) зливаються в один prompt; без replaceInstructions; модель не знайдена → error, сесія не створюється; prompt кидає → error; timeout → error; ще 13
|
|
30
35
|
|
|
31
36
|
## Гарантії поведінки
|
|
32
37
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
38
|
+
- Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
|
|
39
|
+
- Містить локальні fail-safe гілки.
|
package/lib/local-cloud.mjs
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
import { loadNative } from './internal/native.mjs'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Один chat-виклик Типу 2a. `modelSpecOrTier` —
|
|
15
|
-
*
|
|
14
|
+
* Один chat-виклик Типу 2a. `modelSpecOrTier` — явний `"provider/model-id"`,
|
|
15
|
+
* абстрактний tier або `N_LOCAL_*_MODEL`/`N_CLOUD_*_MODEL` selector
|
|
16
16
|
* через ту саму [`llm_lib::resolve_model`], що й `resolveModel` з
|
|
17
17
|
* `model-tiers.mjs`.
|
|
18
|
-
* @param {string} modelSpecOrTier `"provider/model-id"
|
|
18
|
+
* @param {string} modelSpecOrTier `"provider/model-id"`, tier або env-selector
|
|
19
19
|
* @param {string} prompt user-репліка
|
|
20
20
|
* @param {{
|
|
21
21
|
* localProviders?: Record<string, { baseUrl: string, apiKey?: string | null }>,
|
package/lib/model-tiers.mjs
CHANGED
|
@@ -34,29 +34,40 @@ export const CLOUD_AVG = env.N_CLOUD_AVG_MODEL ?? ''
|
|
|
34
34
|
/** Максимальний хмарний. Напр.: openai/gpt-5.5 */
|
|
35
35
|
export const CLOUD_MAX = env.N_CLOUD_MAX_MODEL ?? ''
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
const
|
|
37
|
+
/** Абстрактний tier → явна стартова env-сходинка. */
|
|
38
|
+
const TIER_START = {
|
|
39
|
+
min: 'N_LOCAL_MIN_MODEL',
|
|
40
|
+
avg: 'N_LOCAL_AVG_MODEL',
|
|
41
|
+
max: 'N_LOCAL_MAX_MODEL'
|
|
42
|
+
}
|
|
43
|
+
const MODEL_ENV_KEYS = new Set([
|
|
44
|
+
'N_LOCAL_MIN_MODEL',
|
|
45
|
+
'N_LOCAL_AVG_MODEL',
|
|
46
|
+
'N_LOCAL_MAX_MODEL',
|
|
47
|
+
'N_CLOUD_MIN_MODEL',
|
|
48
|
+
'N_CLOUD_AVG_MODEL',
|
|
49
|
+
'N_CLOUD_MAX_MODEL'
|
|
50
|
+
])
|
|
39
51
|
|
|
40
52
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* @param {'min'|'avg'|'max'} tier тир
|
|
50
|
-
* @param {{ native?: { resolveModel: (tier: string) => string | null } }} [deps] інжект `native` для тестів
|
|
53
|
+
* Універсально резолвить модель від явної env-сходинки:
|
|
54
|
+
* - LOCAL_MIN → LOCAL_AVG → LOCAL_MAX → CLOUD_MIN → CLOUD_AVG → CLOUD_MAX;
|
|
55
|
+
* - LOCAL_AVG → LOCAL_MAX → CLOUD_AVG → CLOUD_MAX;
|
|
56
|
+
* - LOCAL_MAX → CLOUD_MAX;
|
|
57
|
+
* - cloud-старти проходять лише відповідну й сильніші cloud-сходинки.
|
|
58
|
+
* `min`/`avg`/`max` лишаються alias-ами відповідних `N_LOCAL_*_MODEL`.
|
|
59
|
+
* @param {'min'|'avg'|'max'|'N_LOCAL_MIN_MODEL'|'N_LOCAL_AVG_MODEL'|'N_LOCAL_MAX_MODEL'|'N_CLOUD_MIN_MODEL'|'N_CLOUD_AVG_MODEL'|'N_CLOUD_MAX_MODEL'} requested стартова сходинка
|
|
60
|
+
* @param {{ native?: { resolveModel: (start: string) => string | null } }} [deps] інжект `native` для тестів
|
|
51
61
|
* @returns {string} `"provider/model-id"` або `''` (дефолт провайдера substrate)
|
|
52
62
|
* @throws {TypeError} якщо tier невідомий
|
|
53
63
|
*/
|
|
54
|
-
export function resolveModel(
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
export function resolveModel(requested, deps = {}) {
|
|
65
|
+
const start = TIER_START[requested] ?? requested
|
|
66
|
+
if (!MODEL_ENV_KEYS.has(start)) {
|
|
67
|
+
throw new TypeError(`resolveModel: unknown model selector ${JSON.stringify(requested)}.`)
|
|
57
68
|
}
|
|
58
69
|
const native = deps.native ?? loadNative()
|
|
59
|
-
return native.resolveModel(
|
|
70
|
+
return native.resolveModel(start) ?? ''
|
|
60
71
|
}
|
|
61
72
|
|
|
62
73
|
// ── Escalation-rung → thinkingLevel ──────────────────────────────────────────
|
package/lib/one-shot.mjs
CHANGED
|
@@ -81,7 +81,7 @@ async function defaultCreateSession({ registry, model, cwd, thinkingLevel, maxTo
|
|
|
81
81
|
*/
|
|
82
82
|
export async function runOneShot({
|
|
83
83
|
messages,
|
|
84
|
-
modelTier
|
|
84
|
+
modelTier,
|
|
85
85
|
modelSpec,
|
|
86
86
|
thinkingLevel,
|
|
87
87
|
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
@@ -122,7 +122,8 @@ export async function runOneShot({
|
|
|
122
122
|
let model
|
|
123
123
|
try {
|
|
124
124
|
registry = deps.registry ?? (await getReg())
|
|
125
|
-
|
|
125
|
+
if (!modelSpec && !modelTier) return fail('model selection: передай modelTier або явний modelSpec', null)
|
|
126
|
+
spec = modelSpec || resolveModel(modelTier)
|
|
126
127
|
model = spec ? resolveModelSpec(registry, spec) : null
|
|
127
128
|
if (spec && !model) return fail(`модель не знайдена: ${spec}`, spec)
|
|
128
129
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7n/llm-lib",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.2",
|
|
4
4
|
"description": "Тонкий шар роботи з LLM (локальні omlx + хмарні провайдери) поверх pi: model tiers, one-shot, agentic-раннери, write-guard, trace, telemetry, prompt-budget",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nitra",
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"optionalDependencies": {
|
|
59
|
-
"@7n/llm-lib-darwin-arm64": "2.
|
|
60
|
-
"@7n/llm-lib-linux-x64": "2.
|
|
59
|
+
"@7n/llm-lib-darwin-arm64": "2.13.2",
|
|
60
|
+
"@7n/llm-lib-linux-x64": "2.13.2"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"@earendil-works/pi-ai": "~0.80.10",
|