@7n/llm-lib 2.7.4 → 2.7.6
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/agent-skill.mjs +10 -5
- package/lib/chain.mjs +14 -4
- package/lib/docs/agent-skill.md +1 -1
- package/lib/docs/chain.md +1 -1
- package/lib/docs/model-tiers.md +1 -1
- package/lib/docs/one-shot.md +1 -1
- package/lib/model-tiers.mjs +13 -0
- package/lib/one-shot.mjs +10 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.7.6] - 2026-07-18
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- `runOneShot`/`runAgentSkill` з нерозв'язаним `modelSpec` (`''`/`null` — consumer лишає вибір pi) більше не потрапляють у `chain.note()` як `model: ''`, через що `chain.mjs` мовчки класифікував їх cloud (`isLocalModel('') === false`) навіть коли pi фактично резолвив локальну модель. Тепер обидва раннери підставляють фактично резолвлену pi-модель (`session.model`, нове `formatModelSpec`), а `chain.note()` для випадків, коли резолвлена модель усе ж недоступна, веде окремий бакет `unknownCalls` замість неявного cloud.
|
|
8
|
+
|
|
9
|
+
## [2.7.5] - 2026-07-17
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `llm_cascade::acp` — дока (`src/docs/acp.md`) синхронізована з поточним кодом (CRC-дрейф без функціональних змін).
|
|
14
|
+
|
|
3
15
|
## [2.7.4] - 2026-07-17
|
|
4
16
|
|
|
5
17
|
### Fixed
|
package/lib/agent-skill.mjs
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { env, stdout } from 'node:process'
|
|
21
|
-
import { isLocalModel, resolveModel } from './model-tiers.mjs'
|
|
21
|
+
import { formatModelSpec, isLocalModel, resolveModel } from './model-tiers.mjs'
|
|
22
22
|
import { getRegistry, resolveModelSpec } from './internal/registry.mjs'
|
|
23
23
|
import { failOnMemoryGuard } from './internal/memory-guard.mjs'
|
|
24
24
|
import { writeTrace } from './trace.mjs'
|
|
@@ -194,23 +194,28 @@ export async function runAgentSkill(prompt, opts = {}) {
|
|
|
194
194
|
failOnMemoryGuard(error, prompt)
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
// spec порожній/нерозв'язаний ('' → pi сам вибирає дефолт) — беремо фактично
|
|
198
|
+
// резолвлену pi-модель із сесії, щоб chain.note()/trace не бачили порожній
|
|
199
|
+
// model і не потрапляли в неявний cloud-бакет (isLocalModel('') === false).
|
|
200
|
+
const resolvedModel = spec || formatModelSpec(session.model)
|
|
201
|
+
|
|
197
202
|
const telemetry = {
|
|
198
203
|
skill: skillId,
|
|
199
204
|
tier,
|
|
200
|
-
model:
|
|
205
|
+
model: resolvedModel,
|
|
201
206
|
turnCount,
|
|
202
207
|
toolCallCount,
|
|
203
208
|
backstopHit,
|
|
204
209
|
wallMs: clock() - startedAt
|
|
205
210
|
}
|
|
206
|
-
chain?.note({ model:
|
|
211
|
+
chain?.note({ model: resolvedModel, usage, error })
|
|
207
212
|
trace({
|
|
208
213
|
caller,
|
|
209
214
|
backend: 'pi-ai',
|
|
210
215
|
kind: 'skill',
|
|
211
216
|
skill: skillId,
|
|
212
217
|
tier,
|
|
213
|
-
model:
|
|
218
|
+
model: resolvedModel,
|
|
214
219
|
cwd,
|
|
215
220
|
turnCount,
|
|
216
221
|
toolCallCount,
|
|
@@ -224,7 +229,7 @@ export async function runAgentSkill(prompt, opts = {}) {
|
|
|
224
229
|
chainId: chain?.traceFields()?.chainId,
|
|
225
230
|
caller,
|
|
226
231
|
step: chain?.traceFields()?.chainStep,
|
|
227
|
-
model:
|
|
232
|
+
model: resolvedModel,
|
|
228
233
|
promptHash: pHash,
|
|
229
234
|
prompt,
|
|
230
235
|
output: outputText,
|
package/lib/chain.mjs
CHANGED
|
@@ -104,6 +104,7 @@ export function startChain({ kind, unit, cwd, meta = {}, deps = {} }) {
|
|
|
104
104
|
let step = 0
|
|
105
105
|
let localCalls = 0
|
|
106
106
|
let cloudCalls = 0
|
|
107
|
+
let unknownCalls = 0
|
|
107
108
|
let errors = 0
|
|
108
109
|
let finalModel = null
|
|
109
110
|
let ended = null
|
|
@@ -126,15 +127,23 @@ export function startChain({ kind, unit, cwd, meta = {}, deps = {} }) {
|
|
|
126
127
|
|
|
127
128
|
/**
|
|
128
129
|
* Раннер репортує результат кроку — акумуляція local/cloud/usage/errors.
|
|
130
|
+
* `call.model` falsy (нерозв'язаний modelSpec, напр. `''`/`null` — консюмер
|
|
131
|
+
* лишив вибір pi) — бакет `unknownCalls`, НЕ cloud: без факту резолву модель
|
|
132
|
+
* могла піти на локальний pi-дефолт, і мовчазний запис у cloudCalls/usageCloud
|
|
133
|
+
* спотворює local/cloud cost-аналітику для будь-кого, хто не передає `model`.
|
|
129
134
|
* @param {{ model?: string|null, usage?: object|null, error?: string|null, stopReason?: string|null }} call результат виклику
|
|
130
135
|
* @returns {void}
|
|
131
136
|
*/
|
|
132
137
|
note(call = {}) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
else
|
|
138
|
+
if (!call.model) {
|
|
139
|
+
unknownCalls++
|
|
140
|
+
} else if (isLocal(call.model)) {
|
|
141
|
+
localCalls++
|
|
142
|
+
} else {
|
|
143
|
+
cloudCalls++
|
|
144
|
+
addUsage(usageCloud, call.usage)
|
|
145
|
+
}
|
|
136
146
|
addUsage(usage, call.usage)
|
|
137
|
-
if (!local) addUsage(usageCloud, call.usage)
|
|
138
147
|
if (call.error) errors++
|
|
139
148
|
else if (call.model) finalModel = call.model
|
|
140
149
|
},
|
|
@@ -179,6 +188,7 @@ export function startChain({ kind, unit, cwd, meta = {}, deps = {} }) {
|
|
|
179
188
|
steps: step,
|
|
180
189
|
localCalls,
|
|
181
190
|
cloudCalls,
|
|
191
|
+
unknownCalls,
|
|
182
192
|
escalated: localCalls > 0 && cloudCalls > 0,
|
|
183
193
|
finalModel,
|
|
184
194
|
errors,
|
package/lib/docs/agent-skill.md
CHANGED
package/lib/docs/chain.md
CHANGED
package/lib/docs/model-tiers.md
CHANGED
package/lib/docs/one-shot.md
CHANGED
package/lib/model-tiers.mjs
CHANGED
|
@@ -77,6 +77,19 @@ export function parseModelId(spec) {
|
|
|
77
77
|
return { provider: spec.slice(0, i), id: spec.slice(i + 1) }
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Форматує pi `Model`-об'єкт (`{provider, id}`) назад у `"provider/model-id"`.
|
|
82
|
+
* Інверсія {@link parseModelId} — застосовується до фактично резолвленої
|
|
83
|
+
* pi-моделі (`session.model`), коли consumer лишив `modelSpec` порожнім і pi
|
|
84
|
+
* сам вибрав дефолт (локальний чи хмарний).
|
|
85
|
+
* @param {{provider: string, id: string}|null|undefined} model pi Model-об'єкт
|
|
86
|
+
* @returns {string|null} `"provider/model-id"` або `null`, якщо модель відсутня
|
|
87
|
+
*/
|
|
88
|
+
export function formatModelSpec(model) {
|
|
89
|
+
if (!model || !model.provider || !model.id) return null
|
|
90
|
+
return `${model.provider}/${model.id}`
|
|
91
|
+
}
|
|
92
|
+
|
|
80
93
|
// ── Класифікація local vs cloud ──────────────────────────────────────────────
|
|
81
94
|
|
|
82
95
|
/** Провайдери, що вважаються локальними. Override: `N_LLM_LOCAL_PROVIDERS` (кома-список). */
|
package/lib/one-shot.mjs
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* ретраїти нема куди, RAM-стеля фіксована (fail-fast політика пакета).
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { isLocalModel, resolveModel } from './model-tiers.mjs'
|
|
20
|
+
import { formatModelSpec, isLocalModel, resolveModel } from './model-tiers.mjs'
|
|
21
21
|
import { getRegistry, resolveModelSpec } from './internal/registry.mjs'
|
|
22
22
|
import { failOnMemoryGuard } from './internal/memory-guard.mjs'
|
|
23
23
|
import { writeTrace } from './trace.mjs'
|
|
@@ -158,12 +158,17 @@ export async function runOneShot({
|
|
|
158
158
|
failOnMemoryGuard(promptError, userText)
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
// spec порожній/нерозв'язаний ('' → pi сам вибирає дефолт) — беремо фактично
|
|
162
|
+
// резолвлену pi-модель із сесії, щоб chain.note()/trace не бачили порожній
|
|
163
|
+
// model і не потрапляли в неявний cloud-бакет (isLocalModel('') === false).
|
|
164
|
+
const resolvedModel = spec || formatModelSpec(session.model)
|
|
165
|
+
|
|
166
|
+
chain?.note({ model: resolvedModel, usage, error: promptError, stopReason })
|
|
162
167
|
trace({
|
|
163
168
|
caller,
|
|
164
169
|
backend: 'pi-ai',
|
|
165
170
|
kind: 'one-shot',
|
|
166
|
-
model:
|
|
171
|
+
model: resolvedModel,
|
|
167
172
|
cwd: cwd ?? null,
|
|
168
173
|
usage,
|
|
169
174
|
stopReason,
|
|
@@ -175,12 +180,12 @@ export async function runOneShot({
|
|
|
175
180
|
chainId: chain?.traceFields()?.chainId,
|
|
176
181
|
caller,
|
|
177
182
|
step: chain?.traceFields()?.chainStep,
|
|
178
|
-
model:
|
|
183
|
+
model: resolvedModel,
|
|
179
184
|
promptHash: pHash,
|
|
180
185
|
prompt: userText,
|
|
181
186
|
output: text.trim(),
|
|
182
187
|
usage,
|
|
183
188
|
error: promptError
|
|
184
189
|
})
|
|
185
|
-
return { content: text.trim(), usage, error: promptError, model:
|
|
190
|
+
return { content: text.trim(), usage, error: promptError, model: resolvedModel, stopReason, caller }
|
|
186
191
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7n/llm-lib",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.6",
|
|
4
4
|
"description": "Тонкий шар роботи з LLM (локальні omlx + хмарні провайдери) поверх pi: model tiers, one-shot, agentic-раннери, write-guard, trace, telemetry, prompt-budget",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nitra",
|