@7n/llm-lib 2.6.1 → 2.7.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/CHANGELOG.md +12 -0
- package/lib/acp.mjs +28 -0
- package/lib/docs/acp.md +31 -0
- package/lib/docs/index.md +4 -5
- package/lib/internal/docs/index.md +1 -0
- package/lib/internal/docs/native.md +30 -0
- package/lib/internal/native.mjs +125 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.7.0] - 2026-07-16
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `runAcpAgent`/`resolveModel`/`oneShotLocalCloud` (`@7n/llm-lib/acp`) — napi-міст до Rust-крейта `llm_cascade` (`llm-lib/crates/llm-cascade-napi`): ACP-виклик `cursor`/`codex`, каскад тирів і local/cloud chat-виклик в одному процесі, без повторної реалізації протоколу в JS
|
|
8
|
+
|
|
9
|
+
## [2.6.2] - 2026-07-14
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- llm-cascade: файлові доки (docs/*.md) для src і examples — 7 нових док за стилем doc-files
|
|
14
|
+
|
|
3
15
|
## [2.6.1] - 2026-07-13
|
|
4
16
|
|
|
5
17
|
### Changed
|
package/lib/acp.mjs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACP (Agent Client Protocol, Zed) — доступ до `cursor`/`codex` через
|
|
3
|
+
* особисту підписку (вже залогінений локально CLI), не API-ключ.
|
|
4
|
+
*
|
|
5
|
+
* Тонкий JS-клієнт до Rust-крейта `llm_cascade::acp` через napi FFI
|
|
6
|
+
* in-process (`llm-lib/crates/llm-cascade-napi`) — жодного власного
|
|
7
|
+
* ACP JSON-RPC/`ClientSideConnection` тут; уся протокольна логіка (спавн
|
|
8
|
+
* агента, `session/prompt`, автоапрув `session/request_permission`) живе
|
|
9
|
+
* в Rust, разом з watchdog-поведінкою на мертвий/незапущений дочірній процес.
|
|
10
|
+
*
|
|
11
|
+
* `claude` тут немає — Rust-крейт моделює лише `cursor`/`codex`
|
|
12
|
+
* (`AcpAgentKind`); deprecated `claude`-раннер лишається окремим
|
|
13
|
+
* JS-шимом у `@7n/rules` (`npm/scripts/lib/acp-runner.mjs`).
|
|
14
|
+
*/
|
|
15
|
+
import { loadNative } from './internal/native.mjs'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Один виклик через ACP-агента з особистою підпискою.
|
|
19
|
+
* @param {'cursor' | 'codex'} kind провайдер
|
|
20
|
+
* @param {string} prompt промпт
|
|
21
|
+
* @param {string} cwd робочий каталог сесії агента (каталог проєкту-викликача)
|
|
22
|
+
* @param {{ native?: { oneShotAcp: (kind: string, prompt: string, cwd: string) => Promise<string> } }} [deps] інжект для тестів
|
|
23
|
+
* @returns {Promise<string>} повний текст відповіді до кінця ходу
|
|
24
|
+
*/
|
|
25
|
+
export function runAcpAgent(kind, prompt, cwd, deps = {}) {
|
|
26
|
+
const native = deps.native ?? loadNative()
|
|
27
|
+
return native.oneShotAcp(kind, prompt, cwd)
|
|
28
|
+
}
|
package/lib/docs/acp.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: acp.mjs
|
|
4
|
+
resource: llm-lib/lib/acp.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 5c32e90c
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.97
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
Файл надає тонкий JS-доступ до `cursor` або `codex` через публічну `runAcpAgent`, покладаючись на вже авторизовану локальну CLI-сесію без API-ключів. Уся ACP-логіка живе в нативному Rust-шарі `llm_cascade::acp`, який викликається in-process через `napi FFI` у `llm-lib/crates/llm-cascade-napi`; тут немає власного `ClientSideConnection` чи JSON-RPC. Саме Rust запускає агента, обробляє `session/prompt`, автоматично погоджує `session/request_permission` і стежить за живістю дочірнього процесу. Крейт підтримує лише `cursor`/`codex`; `claude`-runner лишається окремим JS-шимом у `@7n/rules` (`npm/scripts/lib/acp-runner.mjs`).
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. `runAcpAgent` запускає один ACP-хід для `cursor` або `codex` через вже авторизовану локальну CLI-сесію, без API-ключів.
|
|
20
|
+
2. Вона звертається до нативного Rust-шару `llm_cascade::acp`, який бере на себе весь протокол взаємодії: старт агента, обмін `session/prompt`, автоапрув запитів на дозвіл і контроль живості дочірнього процесу.
|
|
21
|
+
3. Вона передає робочий каталог поточного проєкту як контекст сесії, щоб агент працював у межах каталогу викликача.
|
|
22
|
+
4. Вона повертає повний текст відповіді агента за один хід.
|
|
23
|
+
5. Вона не виконує власну протокольну логіку, не працює з `claude`, і не покладається на `ClientSideConnection`; підтримка `claude` живе окремо в JS-шимі `npm/scripts/lib/acp-runner.mjs`.
|
|
24
|
+
|
|
25
|
+
## Публічний API
|
|
26
|
+
|
|
27
|
+
- runAcpAgent — запускає один запит через ACP-агента з власною підпискою
|
|
28
|
+
|
|
29
|
+
## Гарантії поведінки
|
|
30
|
+
|
|
31
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
package/lib/docs/index.md
CHANGED
|
@@ -4,22 +4,21 @@ title: llm-lib/lib
|
|
|
4
4
|
resource: llm-lib/lib/
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# llm-lib/lib
|
|
8
|
-
|
|
9
|
-
Публічні модулі пакета `@7n/llm-lib` (див. README пакета; спека
|
|
10
|
-
docs/specs/2026-07-05-llm-lib-extraction-spec.md).
|
|
11
|
-
|
|
12
7
|
| Файл | Тип |
|
|
13
8
|
| ----------------------------------------- | --------- |
|
|
9
|
+
| [acp.mjs](acp.md) | JS Module |
|
|
14
10
|
| [agent-fix.mjs](agent-fix.md) | JS Module |
|
|
15
11
|
| [agent-skill.mjs](agent-skill.md) | JS Module |
|
|
12
|
+
| [anchored-edit.mjs](anchored-edit.md) | JS Module |
|
|
16
13
|
| [body-capture.mjs](body-capture.md) | JS Module |
|
|
17
14
|
| [chain.mjs](chain.md) | JS Module |
|
|
18
15
|
| [chains-report.mjs](chains-report.md) | JS Module |
|
|
16
|
+
| [harness.mjs](harness.md) | JS Module |
|
|
19
17
|
| [model-tiers.mjs](model-tiers.md) | JS Module |
|
|
20
18
|
| [one-shot.mjs](one-shot.md) | JS Module |
|
|
21
19
|
| [prompt-budget.mjs](prompt-budget.md) | JS Module |
|
|
22
20
|
| [telemetry-store.mjs](telemetry-store.md) | JS Module |
|
|
23
21
|
| [trace.mjs](trace.md) | JS Module |
|
|
22
|
+
| [web-tools.mjs](web-tools.md) | JS Module |
|
|
24
23
|
| [with-timeout.mjs](with-timeout.md) | JS Module |
|
|
25
24
|
| [write-guard.mjs](write-guard.md) | JS Module |
|
|
@@ -12,4 +12,5 @@ resource: llm-lib/lib/internal/
|
|
|
12
12
|
| [compress-context.mjs](compress-context.md) | JS Module |
|
|
13
13
|
| [max-tokens.mjs](max-tokens.md) | JS Module |
|
|
14
14
|
| [memory-guard.mjs](memory-guard.md) | JS Module |
|
|
15
|
+
| [native.mjs](native.md) | JS Module |
|
|
15
16
|
| [registry.mjs](registry.md) | JS Module |
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: native.mjs
|
|
4
|
+
resource: llm-lib/lib/internal/native.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 205418d5
|
|
7
|
+
model: openai-codex/gpt-5.5
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.98
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
Файл знаходить і завантажує native-аддон `llm-cascade`, щоб JavaScript-код використовував Rust-ядро через napi-артефакт. `resolveNativeAddon` визначає шлях за єдиним порядком: явний override `N_LLM_LIB_NATIVE_ADDON`, platform-підпакет `@7n/llm-lib-<platform>-<arch>` з артефактом `llm-cascade-napi.<triple>.node`, dev-fallback у `target/release|debug/` після `cargo build -p llm-cascade-napi` або вивід у `llm-lib/crates/llm-cascade-napi/`. `loadNative` завантажує знайдений аддон через `process.dlopen` і кешує результат у межах процесу. На непідтриманих платформах запуск зупиняється зрозумілою помилкою без JS-fallback.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
- `resolveNativeAddon` визначає шлях до native-аддона `llm-cascade`: спершу бере явний override, далі шукає platform-підпакет, потім локальні dev-збірки; для непідтриманої або незібраної платформи завершується зрозумілою помилкою без JS-fallback.
|
|
20
|
+
- `loadNative` завантажує native-аддон один раз за процес і повертає закешовані exports для повторних викликів.
|
|
21
|
+
|
|
22
|
+
## Публічний API
|
|
23
|
+
|
|
24
|
+
- resolveNativeAddon — знаходить файл native addon `llm-cascade` для поточного середовища або тестових підмін.
|
|
25
|
+
- loadNative — повертає native addon із кешу, щоб завантажувати його лише один раз за час роботи процесу.
|
|
26
|
+
|
|
27
|
+
## Гарантії поведінки
|
|
28
|
+
|
|
29
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
30
|
+
- Кешує результати в межах одного прогону.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader napi-аддона `llm-cascade` (Rust-ядро `llm-lib/crates/llm-cascade-napi`
|
|
3
|
+
* → `llm-cascade`) — за зразком `mt/npm/lib/core/native.mjs`.
|
|
4
|
+
*
|
|
5
|
+
* Порядок пошуку:
|
|
6
|
+
* 1. N_LLM_LIB_NATIVE_ADDON — явний override шляху до аддона (dev / CI / тести).
|
|
7
|
+
* 2. Platform-підпакет `@7n/llm-lib-<platform>-<arch>` (napi-артефакт
|
|
8
|
+
* `llm-cascade-napi.<triple>.node`).
|
|
9
|
+
* 3. Dev-fallback: `<repoRoot>/target/release|debug/` (сирий cdylib з
|
|
10
|
+
* `cargo build -p llm-cascade-napi`) та вивід `napi build` у
|
|
11
|
+
* `llm-lib/crates/llm-cascade-napi/`.
|
|
12
|
+
* 4. Інакше — зрозуміла помилка з підказкою.
|
|
13
|
+
*
|
|
14
|
+
* Аддон завантажується через `process.dlopen` — працює і для `.node`, і для
|
|
15
|
+
* сирих cdylib (`.dylib`/`.so`). Результат кешується (одне завантаження на процес).
|
|
16
|
+
* Без JS-fallback на неоголошеній платформі — hard error, свідома межа v1
|
|
17
|
+
* (darwin-arm64, linux-x64), не регресія.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync } from 'node:fs'
|
|
20
|
+
import { createRequire } from 'node:module'
|
|
21
|
+
import { dirname, join } from 'node:path'
|
|
22
|
+
import process, { arch as osArch, env as procEnv, platform as osPlatform } from 'node:process'
|
|
23
|
+
import { fileURLToPath } from 'node:url'
|
|
24
|
+
|
|
25
|
+
const require = createRequire(import.meta.url)
|
|
26
|
+
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
27
|
+
/** Корінь репо: llm-lib/lib/internal → up 3. */
|
|
28
|
+
const REPO_ROOT = join(HERE, '..', '..', '..')
|
|
29
|
+
|
|
30
|
+
/** Підтримувані platform-arch → napi-суфікс артефакта (v1: darwin-arm64, linux-x64). */
|
|
31
|
+
const NAPI_SUFFIXES = {
|
|
32
|
+
'darwin-arm64': 'darwin-arm64',
|
|
33
|
+
'linux-x64': 'linux-x64-gnu'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @type {Record<string, unknown> | null} */
|
|
37
|
+
let cached = null
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Завантажує аддон за шляхом через process.dlopen.
|
|
41
|
+
* @param {string} p шлях до .node / .dylib / .so
|
|
42
|
+
* @returns {Record<string, unknown>} exports аддона
|
|
43
|
+
*/
|
|
44
|
+
function dlopenAddon(p) {
|
|
45
|
+
const mod = { exports: {} }
|
|
46
|
+
process.dlopen(mod, p)
|
|
47
|
+
return mod.exports
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Ім'я cdylib-файлу для платформи (вивід `cargo build -p llm-cascade-napi`).
|
|
52
|
+
* @param {string} platform process.platform
|
|
53
|
+
* @returns {string} ім'я бібліотеки
|
|
54
|
+
*/
|
|
55
|
+
function cdylibName(platform) {
|
|
56
|
+
return platform === 'darwin' ? 'libllm_cascade_napi.dylib' : 'libllm_cascade_napi.so'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Резолвить шлях до napi-аддона `llm-cascade`.
|
|
61
|
+
* @param {{
|
|
62
|
+
* env?: Record<string, string | undefined>,
|
|
63
|
+
* platform?: string,
|
|
64
|
+
* arch?: string,
|
|
65
|
+
* existsSync?: (p: string) => boolean,
|
|
66
|
+
* requireResolve?: (id: string) => string,
|
|
67
|
+
* repoRoot?: string
|
|
68
|
+
* }} [deps] ін'єкції для тестів
|
|
69
|
+
* @returns {string} шлях до файлу аддона
|
|
70
|
+
*/
|
|
71
|
+
export function resolveNativeAddon(deps = {}) {
|
|
72
|
+
const env = deps.env ?? procEnv
|
|
73
|
+
const platform = deps.platform ?? osPlatform
|
|
74
|
+
const arch = deps.arch ?? osArch
|
|
75
|
+
const exists = deps.existsSync ?? existsSync
|
|
76
|
+
const requireResolve = deps.requireResolve ?? (id => require.resolve(id))
|
|
77
|
+
const repoRoot = deps.repoRoot ?? REPO_ROOT
|
|
78
|
+
|
|
79
|
+
// 1. Явний override.
|
|
80
|
+
const override = env.N_LLM_LIB_NATIVE_ADDON
|
|
81
|
+
if (override) return override
|
|
82
|
+
|
|
83
|
+
const key = `${platform}-${arch}`
|
|
84
|
+
const suffix = NAPI_SUFFIXES[key]
|
|
85
|
+
|
|
86
|
+
// 2. Platform-підпакет.
|
|
87
|
+
if (suffix) {
|
|
88
|
+
try {
|
|
89
|
+
return requireResolve(`@7n/llm-lib-${key}/llm-cascade-napi.${suffix}.node`)
|
|
90
|
+
} catch {
|
|
91
|
+
// не встановлено — пробуємо dev-fallback
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 3. Dev-fallback: cargo-збірка (сирий cdylib) або вивід napi build.
|
|
96
|
+
const candidates = Array.from(['release', 'debug'], profile =>
|
|
97
|
+
join(repoRoot, 'target', profile, cdylibName(platform))
|
|
98
|
+
)
|
|
99
|
+
if (suffix) {
|
|
100
|
+
candidates.push(join(repoRoot, 'llm-lib', 'crates', 'llm-cascade-napi', `llm-cascade-napi.${suffix}.node`))
|
|
101
|
+
}
|
|
102
|
+
for (const candidate of candidates) {
|
|
103
|
+
if (exists(candidate)) return candidate
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 4. Помилка з підказкою.
|
|
107
|
+
throw new Error(
|
|
108
|
+
`llm-cascade native addon: немає збірки для "${key}". ` +
|
|
109
|
+
`Постав N_LLM_LIB_NATIVE_ADDON=/шлях/до/аддона, додай підпакет @7n/llm-lib-${key}, ` +
|
|
110
|
+
`або збери локально: cargo build --release -p llm-cascade-napi`
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Кешований доступ до аддона (одне завантаження на процес).
|
|
116
|
+
* @param {{ resolve?: () => string, dlopen?: (p: string) => Record<string, unknown> }} [deps] ін'єкції
|
|
117
|
+
* @returns {Record<string, unknown>} exports аддона (oneShotAcp, resolveModel, oneShotLocalCloud)
|
|
118
|
+
*/
|
|
119
|
+
export function loadNative(deps = {}) {
|
|
120
|
+
if (cached === null) {
|
|
121
|
+
const path = (deps.resolve ?? resolveNativeAddon)()
|
|
122
|
+
cached = (deps.dlopen ?? dlopenAddon)(path)
|
|
123
|
+
}
|
|
124
|
+
return cached
|
|
125
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7n/llm-lib",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
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
|
+
"./acp": "./lib/acp.mjs",
|
|
39
40
|
"./chain": "./lib/chain.mjs",
|
|
40
41
|
"./chains-report": "./lib/chains-report.mjs",
|
|
41
42
|
"./one-shot": "./lib/one-shot.mjs",
|