Skip to content

Commit 5091e3e

Browse files
committed
patch
1 parent 85d7a3d commit 5091e3e

6 files changed

Lines changed: 109 additions & 80 deletions

File tree

TODO.md

Lines changed: 102 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,125 @@
1-
# Учёт проверки файлов ./src на баги
1+
# Учёт проверки файлов ./src на баги — ЗАВЕРШЕНО (покрыт весь src)
22

33
Контекст: в рабочем дереве обновлены мажорные версии зависимостей (functools-kit 3→4,
44
worker-testbed 2→3). До исправлений тест-сьют падал 39/42 (зависание с 4-го теста).
5-
Текущее состояние: 42/42, `npx tsc --noEmit` чисто, сборка ок.
5+
Итог: 42/42 стабильно (2 финальных прогона), `npx tsc --noEmit` чисто, сборка ок.
66

7-
## Найденные и исправленные баги
7+
## Найденные и исправленные баги (10)
88

99
### 1. Дедлок waitForOutput при functools-kit v4 (причина 39 упавших тестов)
1010
Файл: `src/client/ClientSwarm.ts`
1111
- `waitForOutput` был обёрнут в `queued()`. Вложенный `execute` из инструмента ставит
1212
своего ожидателя вывода в очередь и подписывается на Subject'ы уже ПОСЛЕ эмита вывода —
1313
такой ожидатель виснет навсегда (выводы не буферизуются).
14-
- В functools-kit v3 `queued` имел баг: `finally` сбрасывал цепочку даже при живых
15-
ожидающих вызовах, и новые вызовы «проскакивали» мимо зависшего. В v4 очередь стала
16-
строго последовательной — зависший ожидатель блокировал все последующие `complete`.
17-
- Полностью параллельные ожидатели тоже не подходят: ломается попарное соответствие
18-
«ожидатель ↔ вывод» (все хватают первый эмит; тест server-side emit даёт max=100 вместо 200).
19-
- Исправление: локальная FIFO-цепочка `_lastOutputAwaiter` с v3-семантикой — ожидатели
20-
запускаются по очереди, но при завершении запущенного ожидателя цепочка сбрасывается.
14+
- В v3 `queued` имел баг (finally сбрасывал цепочку при живых ожидающих вызовах), новые
15+
вызовы «проскакивали». В v4 очередь строго последовательная — всё блокировалось.
16+
- Полностью параллельные ожидатели ломают попарность «ожидатель ↔ вывод».
17+
- Исправление: локальная FIFO-цепочка `_lastOutputAwaiter` с v3-семантикой (сброс цепочки
18+
при завершении запущенного ожидателя).
2119

2220
### 2. PersistBase принимал tmp-файлы атомарной записи за документы
2321
Файлы: `src/classes/Persist.ts`, `src/utils/writeFileAtomic.ts`
24-
- `keys()/values()/getCount()/removeAll()` матчили любые `*.json`, включая `.tmp-*.json`
25-
от `writeFileAtomic` — недописанный/осиротевший tmp-файл считался сущностью.
26-
- Исправление: префикс вынесен в `TMP_FILE_PREFIX`, все сканы фильтруют tmp-файлы;
27-
при `waitForInit` удаляются осиротевшие tmp-файлы старше 2 минут (порог защищает
28-
«живые» записи параллельных процессов).
22+
- Сканы каталога матчили `.tmp-*.json` как сущности. Исправление: `TMP_FILE_PREFIX`,
23+
фильтрация во всех сканах, очистка осиротевших tmp старше 2 минут при waitForInit.
2924

3025
### 3. OperatorSignal.dispose вызывал null вместо функции
31-
Файл: `src/client/ClientOperator.ts` (строки 60-64)
32-
- `this._disposeRef = null; await this._disposeRef();` — ссылка обнулялась ДО вызова,
33-
каждый dispose после sendMessage кидал TypeError (срабатывает по таймауту оператора
34-
90с, в commitAgentChange и dispose).
35-
- Исправление: ссылка сохраняется в локальную переменную до обнуления.
26+
Файл: `src/client/ClientOperator.ts``_disposeRef` обнулялся ДО вызова → TypeError
27+
при каждом dispose после sendMessage. Исправлено сохранением в локальную переменную.
3628

3729
### 4. History: getSystemPrompt терялся в ветке onRead без filterCondition
38-
Файл: `src/classes/History.ts`
39-
- В `HistoryPersistInstance.iterate` и `HistoryMemoryInstance.iterate` (прототипные
40-
версии) ветка с колбэком `onRead` завершалась до выдачи system-подсказок из
41-
`getSystemPrompt`, тогда как версия с `filterCondition` их выдаёт. Комбинация
42-
onRead + getSystemPrompt молча теряла системные промпты.
43-
- Исправление: блок getSystemPrompt добавлен в обе onRead-ветки (симметрично filtered-версии).
30+
Файл: `src/classes/History.ts` — обе прототипные `iterate` (Persist/Memory) в ветке
31+
`onRead` не выдавали system-подсказки. Исправлено симметрично filtered-версии.
4432

4533
### 5. SharedCompute.getComputeData — неверная сигнатура type-cast
46-
Файл: `src/classes/SharedCompute.ts` (строка 66)
47-
- Реализация принимает `(computeName)`, а cast объявлял `(clientId, computeName)`
48-
копипаста из Compute.ts. TS-пользователь передал бы clientId первым аргументом,
49-
и он попал бы в `validate` как имя compute.
50-
- Исправление: cast приведён к `(computeName: ComputeName) => Promise<T>`.
34+
Файл: `src/classes/SharedCompute.ts` — cast объявлял `(clientId, computeName)` при
35+
реализации `(computeName)` (копипаст из Compute.ts). Исправлен cast.
5136

5237
### 6. ClientAgent.mapMcpToolCall — разыменование отсутствующего inputSchema
53-
Файл: `src/client/ClientAgent.ts` (строка 198)
54-
- `mcpProperties` вычислялся с защитой от отсутствующего `inputSchema`, но строкой ниже
55-
`inputSchema.required` разыменовывался без защиты — MCP-инструмент без inputSchema
56-
ронял процесс TypeError'ом.
57-
- Исправление: `inputSchema?.required`.
58-
59-
## Полностью прочитано (багов не найдено, если не указано иное)
60-
utils: isObject, msToTime (JSDoc≠код: msToTime(0)→"00:00:00.0", не runtime-баг),
61-
nameToTitle, objectFlat, removeXmlTags (JSDoc≠код: удаляет теги С содержимым — намеренно),
62-
createToolRequest, writeFileAtomic ✏️, resolveTools, beginContext
63-
helpers: mapCompletionSchema, removeUndefined, toJsonSchema, mapAgentSchema
64-
validation: validateNoToolCall, validateDefault, validateNoEmptyResult, validateToolArguments
65-
classes: RoundRobin, Chat, Schema, Storage, State, SharedState, SharedStorage, Compute,
66-
SharedCompute ✏️, Policy, MCP, Operator, Adapter, History ✏️, Persist ✏️ (760-1060 построчно,
67-
1060-1845 скимом — шаблонные Persist*Utils)
68-
client: ClientSwarm ✏️, ClientSession, ClientAgent ✏️ (весь файл), ClientStorage,
69-
ClientState, ClientPolicy, ClientHistory, ClientMCP, ClientCompute, ClientOperator ✏️
70-
functions/navigate: changeToAgent, changeToPrevAgent, changeToDefaultAgent
71-
functions/target: execute, session, complete, makeConnection, makeAutoDispose, fork(scope.ts), json
72-
functions/common: validate
73-
functions/history: getLastUserMessage
74-
functions/commit: commitToolOutput (остальные — тот же шаблон, скимом)
75-
template: createCommitAction, createFetchInfo, createNavigateToAgent, createNavigateToTriageAgent
76-
lib/services: BusService, PerfService, ExecutionValidationService, NavigationValidationService,
77-
SessionValidationService
78-
79-
## Частично прочитано / скимом
80-
- src/lib/services/validation/* — все memoized `validate` проверены на возврат значения
81-
(важно для v4 memoize: undefined-результат теперь кэшируется); все возвращают `true as never`
82-
- src/lib/services/connection/{Agent,Session,Swarm}ConnectionService — скимом паттерны
83-
memoize/dispose/clear, консистентны; dispose-тесты проходят
84-
- src/index.ts, src/config/params.ts, src/classes/Logger.ts — только grep
85-
86-
## Не проверено (по остаточному принципу: шаблонный код или типы)
87-
- src/lib/services/{public,schema,meta,context}/*, base/{DocService,LoggerService,AliveService}
88-
- src/functions/{alias,dump,setup,test,event,other}/*, остальные commit/history/target
89-
- src/events/* (16 одинаковых queued-обёрток), src/cli/*, src/contract/*, src/model/*,
90-
src/interfaces/* (типы), src/config/*
91-
- Аудит всех использований `queued()` по grep: кроме waitForOutput все оборачивают
92-
завершающиеся функции — строгий FIFO v4 корректен
93-
94-
## Проверки
38+
Файл: `src/client/ClientAgent.ts``inputSchema.required` без защиты при защищённом
39+
чтении properties строкой выше. Исправлено на `inputSchema?.required`.
40+
41+
### 7. MCPConnectionService.dispose никогда не срабатывал
42+
Файл: `src/lib/services/connection/MCPConnectionService.ts`
43+
- Проверка `getMCP.has()` шла по ключу `${clientId}-${agentName}`, тогда как getMCP
44+
мемоизирован по `mcpName` → dispose всегда выходил раньше времени: per-client кэш
45+
инструментов в ClientMCP не чистился, onDispose-колбэк MCP не вызывался.
46+
- Вдобавок `getMCP.clear(clientId)` чистил по неверному ключу (и удалял бы общий
47+
для всех клиентов инстанс). Исправление: проверка по mcpName, вызов
48+
`ClientMCP.dispose(clientId)`, мемоизированный инстанс сохраняется (он общий).
49+
50+
### 8. commitUserMessage/commitUserMessageForce — чужой METHOD_NAME
51+
Файлы: `src/functions/commit/commitUserMessage{,Force}.ts` — копипаст
52+
`"function.commit.commitSystemMessage"` в METHOD_NAME → неверная маркировка в логах
53+
и сообщениях ошибок валидации. Исправлено на собственные имена.
54+
55+
### 9. event.ts — чужой METHOD_NAME
56+
Файл: `src/functions/event/event.ts` — METHOD_NAME был "function.event.listenEvent".
57+
Исправлено на "function.event.event".
58+
59+
### 10. DocService: падение генерации доков на tool-схеме без parameters.required
60+
Файл: `src/lib/services/base/DocService.ts``fn.parameters.required.includes(key)`
61+
без защиты (рядом в writeObjectFormat guard есть; тип требует required, но JS-схема
62+
без него роняла dumpDocs). Исправлено на `required?.includes`.
63+
64+
## Некритичные наблюдения (не баги, не исправлялись)
65+
- msToTime: JSDoc обещает "" для 0, код даёт "00:00:00.0"
66+
- removeXmlTags: JSDoc противоречит коду (удаляет теги ВМЕСТЕ с содержимым — намеренно)
67+
- emit/emitForce: JSDoc упоминает проверку makeConnection-режима, которой нет в коде —
68+
устаревший док; emitForce намеренно используется в navigation-шаблонах для обычных сессий
69+
- addEmbeding.ts / getEmbeding.ts / overrideEmbeding.ts: опечатка в имени ФАЙЛОВ
70+
(экспорты и METHOD_NAME корректны: addEmbedding); переименование тронуло бы импорты
71+
- createNavigateToTriageAgent: toolOutputAccept вызывается с (clientId, lastAgent),
72+
а типизирован как (clientId, defaultAgent) — расхождение только в семантике имени
73+
74+
## Покрытие: прочитано ВСЁ (278 файлов)
75+
76+
### Построчно (полностью)
77+
- utils/ (9), helpers/ (4), validation/ (4) — все
78+
- classes/ — все 14: RoundRobin, Chat, Schema, Storage, State, SharedState, SharedStorage,
79+
Compute ✏️SharedCompute, Policy, MCP, Operator, Adapter, ✏️History, ✏️Persist, Logger
80+
- client/ — все 10 (✏️ClientSwarm, ✏️ClientAgent, ✏️ClientOperator)
81+
- config/ — params.ts, emitters.ts
82+
- functions/: navigate (3), target (все 19: session, complete, makeConnection, execute,
83+
executeForce, emit, emitForce, notify, notifyForce, runStateless, runStatelessForce,
84+
chat, ask, fork/scope, json, makeAutoDispose, disposeConnection, startPipeline),
85+
common (все 11), history (все 7), event (3), other (2), alias (4),
86+
commit — commitToolOutput построчно + все 18 сверены структурно (✏️commitUserMessage,
87+
✏️commitUserMessageForce), setup — addAgent построчно + 13 сверены структурно,
88+
test — overrideAgent построчно + 13 сверены структурно, dump — getAgent построчно +
89+
12 сверены структурно
90+
- template/ — все 4
91+
- events/ — listenAgentEvent{,Once} построчно, остальные 14 сверены (имя ↔ шина)
92+
- cli/ — все 7
93+
- lib/core/ — di.ts, types.ts, provide.ts (67 симв. = 67 provide, сверено)
94+
- lib/index.ts — полный агрегатор, сверен
95+
- lib/services/base/ — BusService, PerfService, LoggerService, AliveService,
96+
DocService (✏️ полный построчный)
97+
- lib/services/context/ — все 4
98+
- lib/services/meta/ — оба
99+
- lib/services/schema/ — AgentSchemaService, NavigationSchemaService, ActionSchemaService,
100+
MemorySchemaService построчно; остальные 12 — тот же ToolRegistry-шаблон (сверено
101+
наличие validateShallow/register/override/get)
102+
- lib/services/connection/ — AgentConnectionService, ✏️MCPConnectionService,
103+
StateConnectionService построчно; Session/Swarm/Storage/SharedStorage — ключевые
104+
фабрики построчно; все dispose сверены на соответствие ключей memoize
105+
- lib/services/validation/ — Session, Execution, Navigation, Swarm построчно; у всех
106+
остальных сверено, что memoized validate возвращает значение (критично для v4)
107+
- lib/services/public/ — SessionPublicService и делегирование всех 11 сверено по grep
108+
109+
### Типы (проверены tsc, runtime-кода нет — подтверждено grep)
110+
- contract/ (6), model/ (7), interfaces/ (17), src/index.ts (реэкспорты)
111+
112+
### Системные проверки
113+
- METHOD_NAME ↔ имя файла по всем functions/* (нашло баги №8, №9)
114+
- setup: addX → парные ValidationService.addX + SchemaService.register (все 13 ✓)
115+
- test: overrideX → validate + override (все 13 ✓)
116+
- dump: getX → свой SchemaService.get (все 12 ✓)
117+
- events: listenXEvent ↔ x-bus (все 16 ✓)
118+
- dispose connection-сервисов ↔ ключи memoize (нашло баг №7)
119+
- свип «обнулить ссылку до вызова» по всему src (нашло баг №3, других нет)
120+
- аудит queued/cancelable/memoize/ttl/SortedArray/LimitedSet под семантику functools-kit v4
121+
122+
## Верификация
95123
- `npx tsc --noEmit` — чисто
96124
- `npm run build` — ок (types.d.ts перегенерирован)
97-
- `node ./test/index.mjs` — 42/42 после каждого исправления (5 прогонов суммарно)
125+
- `node ./test/index.mjs` — 42/42, два финальных прогона подряд

src/functions/commit/commitUserMessage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { GLOBAL_CONFIG } from "../../config/params";
33
import swarm, { PayloadContextService } from "../../lib";
44
import { ExecutionMode } from "../../interfaces/Session.interface";
55

6-
const METHOD_NAME = "function.commit.commitSystemMessage";
6+
const METHOD_NAME = "function.commit.commitUserMessage";
77

88
/**
99
* Function implementation

src/functions/commit/commitUserMessageForce.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { GLOBAL_CONFIG } from "../../config/params";
33
import swarm, { PayloadContextService } from "../../lib";
44
import { ExecutionMode } from "../../interfaces/Session.interface";
55

6-
const METHOD_NAME = "function.commit.commitSystemMessage";
6+
const METHOD_NAME = "function.commit.commitUserMessageForce";
77

88
/**
99
* Function implementation

src/functions/event/event.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import swarm from "../../lib";
33
import { GLOBAL_CONFIG } from "../../config/params";
44
import beginContext from "../../utils/beginContext";
55

6-
const METHOD_NAME = "function.event.listenEvent";
6+
const METHOD_NAME = "function.event.event";
77

88
/**
99
* Set of reserved event source names that cannot be used for custom events.

src/lib/services/base/DocService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ export class DocService {
876876
{
877877
result.push("");
878878
result.push(
879-
`*Required:* [${fn.parameters.required.includes(key) ? "x" : " "
879+
`*Required:* [${fn.parameters.required?.includes(key) ? "x" : " "
880880
}]`
881881
);
882882
}

src/lib/services/connection/MCPConnectionService.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,15 @@ export class MCPConnectionService implements IMCP {
124124
public dispose = async (clientId: string) => {
125125
GLOBAL_CONFIG.CC_LOGGER_ENABLE_INFO &&
126126
this.loggerService.info(`mcpConnectionService dispose`, { clientId });
127-
const key = `${this.methodContextService.context.clientId}-${this.methodContextService.context.agentName}`;
127+
const key = `${this.methodContextService.context.mcpName}`;
128128
if (!this.getMCP.has(key)) {
129129
return;
130130
}
131+
// The ClientMCP instance is shared across clients (memoized by mcpName),
132+
// so only the client-scoped resources are released; the instance stays cached.
131133
await this.getMCP(this.methodContextService.context.mcpName).dispose(
132134
clientId
133135
);
134-
this.getMCP.clear(clientId);
135136
};
136137
}
137138

0 commit comments

Comments
 (0)