@7n/llm-lib 2.9.0 → 2.9.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.9.2] - 2026-07-26
4
+
5
+ ### Fixed
6
+
7
+ - Pi transport errors із `message_end` більше не маскуються як порожнє успішне завершення.
8
+
9
+ ## [2.9.1] - 2026-07-25
10
+
11
+ ### Fixed
12
+
13
+ - Виправлено profile генерації тестів для survived Stryker-мутантів
14
+
3
15
  ## [2.9.0] - 2026-07-25
4
16
 
5
17
  ### Added
package/lib/agent-fix.mjs CHANGED
@@ -106,10 +106,11 @@ function astUnavailable() {
106
106
  * джерелом правди — тут лише рання й точніша петля всередині рунга.
107
107
  * @param {{ session: object, verify: (args: { touchedFiles: string[] }) => Promise<{ ok: boolean, output?: string }> | { ok: boolean, output?: string },
108
108
  * verifyMax: number, timeoutMs: number, startedAt: number, clock: () => number,
109
- * guard: { touchedFiles: () => string[] }, fixPrompt: string }} args контекст петлі.
109
+ * guard: { touchedFiles: () => string[] }, fixPrompt: string,
110
+ * getTransportError: () => string|null }} args контекст петлі.
110
111
  * @returns {Promise<{ verifyAttempts: Array<{ ok: boolean, infra?: boolean }>, error: string|null }>} результат петлі.
111
112
  */
112
- async function runVerifyLoop({ session, verify, verifyMax, timeoutMs, startedAt, clock, guard, fixPrompt }) {
113
+ async function runVerifyLoop({ session, verify, verifyMax, timeoutMs, startedAt, clock, guard, fixPrompt, getTransportError }) {
113
114
  const verifyAttempts = []
114
115
  for (let attempt = 0; ; attempt++) {
115
116
  let evidence
@@ -137,6 +138,8 @@ async function runVerifyLoop({ session, verify, verifyMax, timeoutMs, startedAt,
137
138
  failOnMemoryGuard(promptError.message, fixPrompt)
138
139
  return { verifyAttempts, error: promptError.message }
139
140
  }
141
+ const transportError = getTransportError()
142
+ if (transportError) return { verifyAttempts, error: transportError }
140
143
  }
141
144
  }
142
145
 
@@ -414,6 +417,7 @@ export async function runAgentFix(ruleId, violation, cwd, opts = {}) {
414
417
  let turnCount = 0
415
418
  let toolCallCount = 0
416
419
  let backstopHit = false
420
+ let transportError = null
417
421
  session.subscribe(event => {
418
422
  switch (event.type) {
419
423
  case 'turn_start': {
@@ -435,9 +439,16 @@ export async function runAgentFix(ruleId, violation, cwd, opts = {}) {
435
439
  }
436
440
  case 'message_end': {
437
441
  const t = turns.at(-1)
438
- if (t && event.message?.usage) {
439
- t.usage = event.message.usage
440
- t.finish = event.message.stopReason ?? null
442
+ if (t) {
443
+ t.usage = event.message?.usage ?? null
444
+ t.finish = event.message?.stopReason ?? null
445
+ }
446
+ if (event.message?.stopReason === 'error') {
447
+ const messageError = event.message.errorMessage
448
+ transportError ??=
449
+ typeof messageError === 'string' && messageError.trim()
450
+ ? messageError
451
+ : 'LLM transport завершився з помилкою без повідомлення'
441
452
  }
442
453
  break
443
454
  }
@@ -466,11 +477,22 @@ export async function runAgentFix(ruleId, violation, cwd, opts = {}) {
466
477
  error = promptError.message
467
478
  failOnMemoryGuard(error, fixPrompt)
468
479
  }
480
+ if (!error && transportError) error = transportError
469
481
 
470
482
  // Evidence-гейт: verify → (не ok) → фідбек у ТУ САМУ сесію (див. runVerifyLoop).
471
483
  let verifyAttempts = []
472
484
  if (verify && !error) {
473
- const loop = await runVerifyLoop({ session, verify, verifyMax, timeoutMs, startedAt, clock, guard, fixPrompt })
485
+ const loop = await runVerifyLoop({
486
+ session,
487
+ verify,
488
+ verifyMax,
489
+ timeoutMs,
490
+ startedAt,
491
+ clock,
492
+ guard,
493
+ fixPrompt,
494
+ getTransportError: () => transportError
495
+ })
474
496
  verifyAttempts = loop.verifyAttempts
475
497
  error = loop.error
476
498
  }
@@ -3,25 +3,41 @@ type: JS Module
3
3
  title: agent-fix.mjs
4
4
  resource: llm-lib/lib/agent-fix.mjs
5
5
  docgen:
6
- crc: 907ba309
6
+ crc: 73c7797b
7
7
  model: openai-codex/gpt-5.4-mini
8
8
  tier: cloud-min
9
- score: 55
10
- issues: no-overview,short-behavior,best-of-2:retry-lost
9
+ score: 90
10
+ issues: internal-name:runVerifyLoop,judge-refine:kept-original,judge:inaccurate:0.98
11
+ judgeModel: openai-codex/gpt-5.4-mini
11
12
  ---
12
13
 
14
+ ## Огляд
15
+
16
+ `buildVerifyFeedbackPrompt`, `buildFixPrompt` і `runAgentFix` описують локальний agent-fix цикл: перші дві функції формують промпти для перевірки та виправлення, а `runAgentFix` запускає саму спробу правки. Це потрібно, щоб тримати зміни в межах заданого `violation` і пов’язаного контексту та віддавати керований результат для подальшого кроку.
17
+
18
+ Усі публічні точки входу працюють fail-safe: помилки перехоплюються всередині, назовні винятки не виходять.
19
+
20
+ ## Поведінка
21
+
22
+ Поточний `violation` стає джерелом правди для стартового fix-пrompt, а `ruleText`, `feedback`, `targetFiles`, `sourceFiles` і `editMode` лише уточнюють межі та контекст правки. `buildFixPrompt` формує жорстко обмежений запит на механічні зміни, щоб агент не розмивав помилку семантичними “виправленнями” поза дозволеними файлами; далі цей prompt передається в ту саму сесію, де виконуються правки, і після цього запускається внутрішня verify-петля.
23
+
24
+ `runAgentFix` оркеструє один рунг від старту до завершення: створює сесію, дає їй prompt для правки, збирає результати редагування, а потім передає контроль у verify-loop. Якщо перевірка повертає порушення, `buildVerifyFeedbackPrompt` перетворює їх на фідбек для тієї ж сесії, щоб ітерація була локальною і не втрачала вже зроблені зміни.
25
+
26
+ `runVerifyLoop` зупиняється лише коли перевірка стає ok, вичерпується ліміт спроб або закінчується спільний time budget рунга; він не заводить нові таймери й не маскує помилки самої перевірки. Якщо перевірка падає як інфраструктура, це повертається як помилка без спалювання ітерацій. Фінальний результат `runAgentFix` завжди fail-safe: або застосована правка з переліком touched files і telemetry, або контрольована помилка з можливістю rollback.
27
+
13
28
  ## Публічний API
14
29
 
15
30
  - buildVerifyFeedbackPrompt — Будує фідбек-prompt verify-ітерації: точний вивід canonical-перевірки + нагадування
16
- обмежень (той самий semantic-collateral guard, що й у buildFixPrompt).
31
+ обмежень (той самий semantic-collateral guard, що й у buildFixPrompt).
17
32
  - buildFixPrompt — Будує fix-промпт для рунга: правило + порушення + (опц.) target-файли + (опц.) feedback
18
- попереднього провалу + жорсткий блок обмежень (лише механічні зміни) + інструкція
19
- «ast_facts перед edit, self_check після».
33
+ попереднього провалу + жорсткий блок обмежень (лише механічні зміни) + інструкція
34
+ «ast_facts перед edit, self_check після».
20
35
 
21
36
  Блок обмежень — перший шар semantic-collateral guard (спека pi-migration §12,
22
37
  addendum 2026-07-05): слабкі локальні моделі схильні «виправляти» правило семантичною
23
38
  правкою (хардкод значення, симуляція поведінки) — промпт явно це забороняє, а
24
39
  verdict-veto consumer-а (re-check) відхиляє такі правки поза target-файлами.
40
+
25
41
  - runAgentFix — Проводить ОДНУ агентну fix-спробу (рунг) для правила.
26
42
 
27
43
  ## Гарантії поведінки
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/llm-lib",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
4
4
  "description": "Тонкий шар роботи з LLM (локальні omlx + хмарні провайдери) поверх pi: model tiers, one-shot, agentic-раннери, write-guard, trace, telemetry, prompt-budget",
5
5
  "keywords": [
6
6
  "nitra",
@@ -55,8 +55,8 @@
55
55
  "access": "public"
56
56
  },
57
57
  "optionalDependencies": {
58
- "@7n/llm-lib-darwin-arm64": "2.9.0",
59
- "@7n/llm-lib-linux-x64": "2.9.0"
58
+ "@7n/llm-lib-darwin-arm64": "2.9.2",
59
+ "@7n/llm-lib-linux-x64": "2.9.2"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "@earendil-works/pi-ai": "~0.80.10",