solver-sdk 3.1.5 → 3.1.8

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Code Solver SDK v3.1.3
1
+ # Code Solver SDK v3.1.8
2
2
 
3
3
  > **JavaScript/TypeScript SDK для VS Code Extensions**
4
4
  > Подключение к AI бэкенду для индексации, поиска и работы с кодом
@@ -12,6 +12,56 @@ JavaScript/TypeScript SDK для работы с Code Solver API. Предост
12
12
  - **📊 Project Indexing** - индексация и анализ проектов
13
13
  - **📝 Context API** - получение контекста для AI
14
14
  - **🛠️ Code Modification** - модификация кода через AI
15
+ - **🔇 Настраиваемое логирование** - полный контроль над выводом в консоль
16
+
17
+ ## 🔄 Последние обновления v3.1.8
18
+
19
+ ### 🚨 КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: onEvent callback данные
20
+ - **Проблема решена**: onEvent callback теперь получает **оригинальные события Anthropic API**
21
+ - **Исправлено**: `content_block_start` содержит полный `content_block` объект с правильными `id`, `name`, `input`
22
+ - **Исправлено**: `input_json_delta` передается как `delta.type: 'input_json_delta'` вместо обычного text
23
+ - **Убрано**: Лишние поля `projectId`, `timestamp` которые нарушали стандарт Anthropic
24
+ - **Результат**: Полная совместимость с Anthropic API стандартом для tool_use событий
25
+
26
+ ### 🔧 Что было исправлено:
27
+ ```javascript
28
+ // ❌ БЫЛО (v3.1.7): onEvent получал обработанные данные
29
+ onEvent: (type, data) => {
30
+ // data содержал: { projectId, timestamp, content_block: null }
31
+ }
32
+
33
+ // ✅ СТАЛО (v3.1.8): onEvent получает оригинальные данные
34
+ onEvent: (type, data) => {
35
+ // data содержит стандартные Anthropic события:
36
+ // content_block_start: { type, index, content_block: { type: 'tool_use', id, name, input } }
37
+ // content_block_delta: { type, index, delta: { type: 'input_json_delta', partial_json } }
38
+ }
39
+ ```
40
+
41
+ ### v3.1.7 (предыдущие обновления)
42
+
43
+ ### 🚨 ИСПРАВЛЕНО: Избыточное логирование в консоли
44
+ - **Проблема решена**: SDK больше не создает спам в Developer Console VS Code
45
+ - **Новые уровни логирования**: `'silent' | 'error' | 'warn' | 'info' | 'debug'`
46
+ - **Детальный контроль потоков**: Настройка логирования SSE событий, chunk'ов и callbacks
47
+ - **Обратная совместимость**: Старые опции `debug: true/false/'verbose'` работают как раньше
48
+
49
+ ### v3.1.6 (предыдущие обновления)
50
+
51
+ - **🔧 КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ**: Восстановлена передача `content_block_start` событий для `tool_use` блоков
52
+ - **✅ Tool Continuation**: Исправлена поддержка tool continuation функциональности
53
+ - **🛠️ Новые события**: Добавлена обработка `input_json_delta`, `signature_delta` для инструментов
54
+ - **📊 Улучшенная обработка**: Корректная обработка всех типов content блоков (thinking, text, tool_use)
55
+ - **🔒 Валидация**: Исправлена валидация `tool_choice` согласно документации Anthropic
56
+
57
+ ### v3.1.5 (предыдущие улучшения)
58
+ - **✅ Исправлена критическая проблема `toJSON`** - решена ошибка сериализации в VS Code IPC
59
+ - **🆕 Новые API методы**: `getIndexingStatus()`, `getProjectInfo()` для безопасной работы
60
+ - **🔧 Безопасная сериализация**: Все Date объекты автоматически преобразуются в ISO строки
61
+ - **🧠 Thinking API**: Полная поддержка мышления Claude с real-time выводом
62
+ - **📊 Real-time данные**: Приоритет live данных над статическими из БД
63
+
64
+ > **Для разработчиков инструментов**: v3.1.6 восстанавливает корректную работу tool continuation!
15
65
 
16
66
  ## 📦 Установка
17
67
 
@@ -19,14 +69,81 @@ JavaScript/TypeScript SDK для работы с Code Solver API. Предост
19
69
  npm install solver-sdk
20
70
  ```
21
71
 
72
+ ## 🔇 Настройка логирования (v3.1.7+)
73
+
74
+ SDK предлагает гибкую систему логирования для контроля вывода в консоль:
75
+
76
+ ### 📊 Уровни логирования
77
+ ```javascript
78
+ const sdk = await CodeSolverSDK.create({
79
+ baseURL: 'http://localhost:3000',
80
+
81
+ // Уровни логирования (от тихого к подробному):
82
+ debug: 'silent', // Полное отключение (даже ошибки)
83
+ debug: 'error', // Только ошибки (рекомендуется для VS Code)
84
+ debug: 'warn', // Предупреждения и ошибки
85
+ debug: 'info', // Базовая информация
86
+ debug: 'debug', // Подробная отладка
87
+
88
+ // Обратная совместимость:
89
+ debug: false, // Отключено
90
+ debug: true, // Базовое логирование
91
+ debug: 'verbose' // Подробное (аналог 'debug')
92
+ });
93
+ ```
94
+
95
+ ### 🎛️ Детальный контроль потоков
96
+ ```javascript
97
+ const sdk = await CodeSolverSDK.create({
98
+ baseURL: 'http://localhost:3000',
99
+ debug: 'debug', // или любой уровень
100
+
101
+ // Точная настройка логирования потоков:
102
+ streamLogging: {
103
+ sseEvents: false, // SSE события (content_block_start/delta/stop)
104
+ streamChunks: false, // Chunk'и потока (каждый кусок текста)
105
+ eventCallbacks: false,// onEvent callback'и
106
+ importantOnly: true // Только важные события (start, stop, errors)
107
+ }
108
+ });
109
+ ```
110
+
111
+ ### 🎯 Рекомендуемые настройки
112
+ ```javascript
113
+ // 🔹 VS Code Extension (production):
114
+ debug: 'error'
115
+
116
+ // 🔹 Development:
117
+ debug: 'info'
118
+
119
+ // 🔹 Deep debugging:
120
+ debug: 'debug',
121
+ streamLogging: { sseEvents: true, streamChunks: true }
122
+
123
+ // 🔹 Полная тишина:
124
+ debug: 'silent'
125
+ ```
126
+
22
127
  ## 🚀 Быстрый старт
23
128
 
24
129
  ```javascript
25
130
  import { CodeSolverSDK } from 'solver-sdk';
26
131
 
27
- // Создание SDK
132
+ // Создание SDK с чистой консолью (рекомендуется для VS Code)
28
133
  const sdk = await CodeSolverSDK.create({
29
- baseURL: 'http://localhost:3000'
134
+ baseURL: 'http://localhost:3000',
135
+ debug: 'error' // Только ошибки, никакого спама
136
+ });
137
+
138
+ // Или с детальным логированием для отладки
139
+ const debugSdk = await CodeSolverSDK.create({
140
+ baseURL: 'http://localhost:3000',
141
+ debug: 'debug',
142
+ streamLogging: {
143
+ sseEvents: true, // Логировать SSE события
144
+ streamChunks: true, // Логировать chunk'и потока
145
+ eventCallbacks: true // Логировать onEvent callbacks
146
+ }
30
147
  });
31
148
 
32
149
  // Создание и индексация проекта
@@ -53,64 +170,155 @@ const functions = await sdk.search.searchFunctions(project.id, {
53
170
  const response = await sdk.chat.chat([
54
171
  { role: 'user', content: 'Объясни этот код' }
55
172
  ], { projectId: project.id });
173
+
174
+ // Потоковый чат с thinking (мышлением)
175
+ for await (const chunk of sdk.chat.streamChat([
176
+ { role: 'user', content: 'Объясни рекурсию пошагово' }
177
+ ], {
178
+ projectId: project.id,
179
+ thinking: {
180
+ type: 'enabled',
181
+ budget_tokens: 5000
182
+ },
183
+ onEvent: (type, data) => {
184
+ if (type === 'content_block_delta' && data.delta?.type === 'thinking_delta') {
185
+ console.log(`🧠 Думает: ${data.delta.thinking}`);
186
+ } else if (type === 'content_block_delta' && data.delta?.type === 'text_delta') {
187
+ console.log(`💬 Отвечает: ${data.delta.text}`);
188
+ }
189
+ }
190
+ })) {
191
+ if (chunk.text) {
192
+ process.stdout.write(chunk.text);
193
+ }
194
+ }
56
195
  ```
57
196
 
58
197
  ## 📋 API Методы
59
198
 
60
199
  ### 📁 Projects API
61
200
  ```javascript
62
- // Создание проекта
63
- await sdk.projects.createProject({
64
- name: 'Project Name',
65
- path: '/project/path',
66
- description: 'Description'
67
- });
201
+ // Создание проекта (исправленная сигнатура)
202
+ await sdk.projects.createProject(
203
+ 'Project Name', // name
204
+ '/project/path', // path
205
+ { description: 'Desc' } // data (опционально)
206
+ );
68
207
 
69
208
  // Получение списка проектов
70
209
  await sdk.projects.getProjects();
71
210
 
72
211
  // Получение информации о проекте
73
212
  await sdk.projects.getProject(projectId);
213
+
214
+ // Получение готовых проектов
215
+ await sdk.projects.getReadyProjects();
74
216
  ```
75
217
 
76
218
  ### 🔄 Projects & Indexing API
77
219
  ```javascript
78
220
  // Создание/поиск проекта и запуск индексации
79
221
  const project = await sdk.projects.findOrCreateProject('/path/to/project', 'Project Name');
80
- await sdk.projects.startIndexing(project.id);
222
+ await sdk.projects.startIndexing(project.id, { force: false }); // options опционально
81
223
 
82
- // Получение статуса индексации
83
- const status = await sdk.projects.getProjectStatus(project.id);
224
+ // Получение real-time статуса индексации
225
+ const indexingStatus = await sdk.projects.getIndexingStatus(project.id);
226
+ console.log('Статус:', indexingStatus.status, 'Прогресс:', indexingStatus.progress + '%');
227
+
228
+ // Получение общей информации о проекте
229
+ const projectInfo = await sdk.projects.getProjectInfo(project.id);
84
230
 
85
231
  // Ожидание завершения индексации
86
232
  while (true) {
87
- const status = await sdk.projects.getProjectStatus(project.id);
88
- if (status.status === 'ready') break;
89
- if (status.status === 'error') throw new Error('Ошибка индексации');
233
+ const status = await sdk.projects.getIndexingStatus(project.id);
234
+ console.log(`Прогресс: ${status.progress}%, Файлы: ${status.processedFiles}/${status.totalFiles}`);
235
+
236
+ if (status.status === 'complete') break;
237
+ if (status.status === 'failed') throw new Error('Ошибка индексации: ' + status.error);
238
+
90
239
  await new Promise(resolve => setTimeout(resolve, 2000));
91
240
  }
92
241
  ```
93
242
 
94
243
  ### 🔍 Search API
95
244
  ```javascript
96
- // Поиск кода
245
+ // Поиск кода (гибкая сигнатура)
246
+ // Способ 1: projectId отдельно
97
247
  await sdk.search.searchCode(projectId, {
98
248
  query: 'search query',
99
249
  limit: 20
100
250
  });
251
+
252
+ // Способ 2: projectId в параметрах
253
+ await sdk.search.searchCode({
254
+ projectId: projectId,
255
+ query: 'search query',
256
+ limit: 20
257
+ });
258
+
259
+ // Поиск функций (гибкая сигнатура)
260
+ // Способ 1: projectId отдельно
261
+ const functions = await sdk.search.searchFunctions(projectId, {
262
+ query: 'calculateSum',
263
+ limit: 10
264
+ });
265
+
266
+ // Способ 2: projectId в параметрах
267
+ const functions = await sdk.search.searchFunctions({
268
+ projectId: projectId,
269
+ query: 'calculateSum',
270
+ limit: 10
271
+ });
272
+
273
+ // Статистика функций в проекте
274
+ const stats = await sdk.search.getFunctionStats(projectId);
275
+ console.log(`Всего функций: ${stats.stats.totalFunctions}`);
101
276
  ```
102
277
 
103
278
  ### 💬 Chat API
104
279
  ```javascript
105
- // Обычный чат (projectId ОБЯЗАТЕЛЕН!)
280
+ // Обычный чат (projectId опционален в реализации, но рекомендуется)
106
281
  const response = await sdk.chat.chat([
107
282
  { role: 'user', content: 'Объясни этот код' }
108
- ], { projectId: 'your-project-id' });
283
+ ], { projectId: 'your-project-id' }); // projectId опционален
109
284
 
110
285
  // Потоковый чат
111
286
  for await (const chunk of sdk.chat.streamChat(messages, { projectId: 'your-project-id' })) {
112
287
  console.log(chunk.text);
113
288
  }
289
+
290
+ // 🧠 Chat с thinking (мышлением Claude)
291
+ const response = await sdk.chat.chat([
292
+ { role: 'user', content: 'Объясни рекурсию подробно' }
293
+ ], {
294
+ projectId: 'your-project-id',
295
+ thinking: {
296
+ type: 'enabled',
297
+ budget_tokens: 5000 // Бюджет для мышления
298
+ }
299
+ });
300
+
301
+ // 🧠 Потоковый чат с thinking и real-time выводом
302
+ for await (const chunk of sdk.chat.streamChat([
303
+ { role: 'user', content: 'Проанализируй архитектуру проекта' }
304
+ ], {
305
+ projectId: 'your-project-id',
306
+ thinking: {
307
+ type: 'enabled',
308
+ budget_tokens: 8000
309
+ },
310
+ onEvent: (type, data) => {
311
+ if (type === 'content_block_delta' && data.delta?.type === 'thinking_delta') {
312
+ console.log(`🧠 Думает: ${data.delta.thinking}`);
313
+ } else if (type === 'content_block_delta' && data.delta?.type === 'text_delta') {
314
+ console.log(`💬 Отвечает: ${data.delta.text}`);
315
+ }
316
+ }
317
+ })) {
318
+ if (chunk.text) {
319
+ process.stdout.write(chunk.text);
320
+ }
321
+ }
114
322
  ```
115
323
 
116
324
  ## ⚙️ Конфигурация
@@ -124,12 +332,12 @@ const sdk = await CodeSolverSDK.create({
124
332
  });
125
333
  ```
126
334
 
127
- **⚠️ Важно**: Для Chat API **обязательно** нужен `projectId`:
335
+ **⚠️ Важно**: Для Chat API `projectId` **рекомендуется**, но не обязателен в реализации:
128
336
  ```javascript
129
- // НЕ РАБОТАЕТ
337
+ // РАБОТАЕТ (но без контекста проекта)
130
338
  const response = await sdk.chat.chat(messages);
131
339
 
132
- // ✅ ПРАВИЛЬНО
340
+ // ✅ РЕКОМЕНДУЕТСЯ (с контекстом проекта)
133
341
  const response = await sdk.chat.chat(messages, { projectId: 'your-project-id' });
134
342
 
135
343
  // 💡 Получить projectId можно так:
@@ -179,9 +387,9 @@ async function fullWorkflow() {
179
387
  // 3. Ждем завершения индексации
180
388
  console.log('Ожидание завершения индексации...');
181
389
  while (true) {
182
- const status = await sdk.projects.getProjectStatus(project.id);
183
- if (status.status === 'ready') break;
184
- if (status.status === 'error') throw new Error('Ошибка индексации');
390
+ const status = await sdk.projects.getIndexingStatus(project.id);
391
+ if (status.status === 'complete') break;
392
+ if (status.status === 'failed') throw new Error('Ошибка индексации: ' + status.error);
185
393
  await new Promise(resolve => setTimeout(resolve, 2000));
186
394
  }
187
395
 
@@ -200,7 +408,7 @@ async function fullWorkflow() {
200
408
  ], { projectId: project.id });
201
409
 
202
410
  console.log('✅ Анализ завершен');
203
- console.log('📊 Компоненты:', components.length);
411
+ console.log('📊 Компоненты:', components.results.length);
204
412
  console.log('🤖 AI анализ:', aiResponse.content);
205
413
 
206
414
  } catch (error) {
@@ -213,6 +421,19 @@ fullWorkflow();
213
421
 
214
422
  ## 🔧 Устранение неполадок
215
423
 
424
+ ### ✅ Исправлена проблема toJSON (v3.1.5)
425
+ ```javascript
426
+ // ❌ СТАРАЯ ОШИБКА (до v3.1.5):
427
+ // CodeExpectedError: Method not found: toJSON
428
+
429
+ // ✅ РЕШЕНИЕ: Обновите SDK до v3.1.5+
430
+ npm install solver-sdk@latest
431
+
432
+ // ✅ Теперь все API возвращают JSON-совместимые объекты
433
+ const status = await sdk.projects.getIndexingStatus(projectId);
434
+ // Все Date объекты автоматически преобразуются в ISO строки
435
+ ```
436
+
216
437
  ### Проблемы с подключением
217
438
  ```javascript
218
439
  // Проверка здоровья API
@@ -229,43 +450,10 @@ const sdk = await CodeSolverSDK.create({
229
450
  });
230
451
  ```
231
452
 
232
- ## 📝 Changelog v3.1.3
233
-
234
- ### ✅ Добавлено
235
- - Поиск функций через `/search/functions` API
236
- - Методы `searchFunctions()` и `searchFunctionsGet()`
237
- - Статистика функций `getFunctionStats()`
238
- - Автоматический выбор модели и токенов на бэкенде
239
- - Упрощенные Chat API без параметров модели
240
-
241
- ### ❌ Удалено
242
- - `AgentsApi` - больше не используется
243
- - `DependenciesApi` - работает внутренне
244
- - `simple-indexing-client.ts` - дублировал ProjectsApi
245
- - Все устаревшие методы и примеры
246
- - Ручной выбор модели и лимитов токенов клиентом
247
- - **Папка docs/** - удалена вся неактуальная документация
248
-
249
- ### 🔄 Изменено
250
- - Обновлены все примеры кода на актуальный синтаксис
251
- - Упрощена документация в один файл
252
- - Исправлены пути API с префиксом `/api/v1`
253
- - Улучшена обработка ошибок индексации
254
- - Chat API упрощен - модель выбирается автоматически
255
- - Полная синхронизация документации с реальным кодом
256
- - **Один README.md** содержит всю необходимую информацию
257
-
258
453
  ## 📄 Лицензия
259
454
 
260
455
  MIT License
261
456
 
262
- **Q: Пустые результаты поиска**
263
- ```javascript
264
- // Убедитесь что проект проиндексирован
265
- const readyProjects = await sdk.projects.getReadyProjects();
266
- console.log('Готовые проекты:', readyProjects);
267
- ```
268
-
269
457
  ## 🔧 Индексация: полный workflow
270
458
 
271
459
  ```javascript
@@ -282,12 +470,12 @@ async function indexProject(projectPath, projectName) {
282
470
 
283
471
  // 3. Мониторинг прогресса
284
472
  while (true) {
285
- const status = await sdk.projects.getProjectStatus(project.id);
473
+ const status = await sdk.projects.getIndexingStatus(project.id);
286
474
 
287
- if (status.status === 'ready') {
475
+ if (status.status === 'complete') {
288
476
  console.log('✅ Индексация завершена!');
289
477
  break;
290
- } else if (status.status === 'error') {
478
+ } else if (status.status === 'failed') {
291
479
  console.log('❌ Ошибка:', status.error);
292
480
  break;
293
481
  }
@@ -327,8 +515,8 @@ export async function activate(context: vscode.ExtensionContext) {
327
515
  await sdk.projects.startIndexing(project.id);
328
516
 
329
517
  while (true) {
330
- const status = await sdk.projects.getProjectStatus(project.id);
331
- if (status.status === 'ready') break;
518
+ const status = await sdk.projects.getIndexingStatus(project.id);
519
+ if (status.status === 'complete') break;
332
520
  progress.report({ message: `${status.progress || 0}%` });
333
521
  await new Promise(resolve => setTimeout(resolve, 2000));
334
522
  }
@@ -385,7 +573,7 @@ export async function activate(context: vscode.ExtensionContext) {
385
573
  { "command": "extension.searchFunctions", "title": "🔍 Поиск функций" }
386
574
  ]
387
575
  },
388
- "dependencies": { "solver-sdk": "^3.1.3" }
576
+ "dependencies": { "solver-sdk": "^3.1.5" }
389
577
  }
390
578
  ```
391
579
 
@@ -30,9 +30,53 @@ class ChatApi {
30
30
  /**
31
31
  * Создает новый экземпляр API для работы с чатом
32
32
  * @param {IHttpClient} httpClient HTTP клиент
33
+ * @param {ChatApiOptions} options Опции логирования (опционально)
33
34
  */
34
- constructor(httpClient) {
35
+ constructor(httpClient, options = {}) {
35
36
  this.httpClient = httpClient;
37
+ /** Logger для ChatApi с настраиваемыми уровнями */
38
+ this.logger = {
39
+ streamEvent: (message, data) => {
40
+ const debugLevel = this.options.debug;
41
+ const streamLogging = this.options.streamLogging;
42
+ if (debugLevel === 'silent')
43
+ return;
44
+ if (streamLogging?.sseEvents || (debugLevel === 'verbose' || debugLevel === 'debug')) {
45
+ console.log(`🔍 [SDK] SSE Event: ${message}`, data);
46
+ }
47
+ },
48
+ streamChunk: (message, data) => {
49
+ const debugLevel = this.options.debug;
50
+ const streamLogging = this.options.streamLogging;
51
+ if (debugLevel === 'silent')
52
+ return;
53
+ if (streamLogging?.streamChunks || (debugLevel === 'verbose' || debugLevel === 'debug')) {
54
+ console.log(`🔍 [CHAT-API] Получен chunk: ${message}`, data);
55
+ }
56
+ },
57
+ eventCallback: (message, data) => {
58
+ const debugLevel = this.options.debug;
59
+ const streamLogging = this.options.streamLogging;
60
+ if (debugLevel === 'silent')
61
+ return;
62
+ if (streamLogging?.eventCallbacks || (debugLevel === 'verbose' || debugLevel === 'debug')) {
63
+ console.log(`📞 [CHAT-API] Вызываем onEvent: ${message}`, data);
64
+ }
65
+ },
66
+ info: (message) => {
67
+ const debugLevel = this.options.debug;
68
+ if (debugLevel && debugLevel !== 'silent' && debugLevel !== 'error' && debugLevel !== 'warn') {
69
+ console.log(`🔧 [SDK] ${message}`);
70
+ }
71
+ },
72
+ error: (message) => {
73
+ const debugLevel = this.options.debug;
74
+ if (debugLevel !== 'silent') {
75
+ console.error(`❌ [SDK] ${message}`);
76
+ }
77
+ }
78
+ };
79
+ this.options = options;
36
80
  }
37
81
  /**
38
82
  * Отправляет сообщение в чат и получает ответ от модели
@@ -183,18 +227,16 @@ class ChatApi {
183
227
  // Валидация параметров
184
228
  this.validateChatOptions(options);
185
229
  try {
186
- // Формируем эндпоинт для стриминга
187
- const endpoint = '/api/v1/chat/stream';
188
230
  // Создаем параметры запроса
189
231
  const params = this.buildRequestParams(messages, {
190
232
  ...options,
191
233
  stream: true
192
234
  });
193
- // Генерируем socketId если нужен для thinking
194
- if (options?.thinking && !options?.socketId) {
195
- options.socketId = generateId(10);
196
- params.socketId = options.socketId;
197
- }
235
+ // УПРОЩЕНО: Всегда используем /stream с автоматическим выполнением инструментов
236
+ const endpoint = '/api/v1/chat/stream';
237
+ this.logger.info(`Используем эндпоинт: ${endpoint} (всегда с auto-execution)`);
238
+ // ИСПРАВЛЕНИЕ: socketId больше не используется для HTTP SSE
239
+ // В HTTP потоках thinking работает напрямую без WebSocket socketId
198
240
  // ИСПРАВЛЕНИЕ: Используем postStream вместо общего request метода
199
241
  const response = await this.httpClient.postStream(endpoint, params);
200
242
  // ИСПРАВЛЕНИЕ: Простой подход - обрабатываем как текст с Node.js stream
@@ -225,6 +267,21 @@ class ChatApi {
225
267
  const lines = buffer.split('\n');
226
268
  buffer = lines.pop() || ''; // Сохраняем неполную строку
227
269
  for (const line of lines) {
270
+ // 📝 ОТЛАДКА: Логируем все SSE события через новый логгер
271
+ if (line.startsWith('data: ') && line.slice(6).trim() !== '[DONE]') {
272
+ try {
273
+ const eventData = JSON.parse(line.slice(6).trim());
274
+ this.logger.streamEvent(eventData.type, {
275
+ type: eventData.type,
276
+ delta: eventData.delta,
277
+ content_block: eventData.content_block,
278
+ index: eventData.index
279
+ });
280
+ }
281
+ catch (e) {
282
+ this.logger.streamEvent(`Raw SSE line: ${line}`);
283
+ }
284
+ }
228
285
  // ✅ КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Используем processStreamChunk
229
286
  const result = (0, stream_utils_1.processStreamChunk)(line, isInThinkingBlock, thinkingContent, textContent, thinkingSignature, options?.onToken);
230
287
  // Обновляем состояние
@@ -234,6 +291,12 @@ class ChatApi {
234
291
  thinkingSignature = result.thinkingSignature;
235
292
  // Если есть чанк для отправки
236
293
  if (result.chunk) {
294
+ this.logger.streamChunk('', {
295
+ type: result.chunk.type,
296
+ isThinking: result.chunk.isThinking,
297
+ text: typeof result.chunk.text === 'string' ? result.chunk.text.substring(0, 30) : result.chunk.text,
298
+ hasOnEvent: !!options?.onEvent
299
+ });
237
300
  // НОВОЕ: Обработка VS Code команд
238
301
  if (result.chunk.type === 'vscode_command' && options?.onVSCodeCommand) {
239
302
  try {
@@ -257,9 +320,29 @@ class ChatApi {
257
320
  continue;
258
321
  }
259
322
  yield result.chunk;
260
- // Вызываем onEvent callback если передан
261
- if (options && options.onEvent) {
262
- options.onEvent(result.chunk.type, result.chunk);
323
+ // 🔧 КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Передаем оригинальные данные события в onEvent
324
+ if (options && options.onEvent && line.startsWith('data: ') && line.slice(6).trim() !== '[DONE]') {
325
+ try {
326
+ const originalEventData = JSON.parse(line.slice(6).trim());
327
+ this.logger.eventCallback('Передаем оригинальные данные события', {
328
+ eventType: originalEventData.type,
329
+ hasContentBlock: !!originalEventData.content_block,
330
+ hasDelta: !!originalEventData.delta
331
+ });
332
+ // ✅ ИСПРАВЛЕНО: передаем оригинальные данные вместо обработанного chunk
333
+ options.onEvent(originalEventData.type, {
334
+ data: originalEventData
335
+ });
336
+ }
337
+ catch (e) {
338
+ // Fallback: если не удалось распарсить, используем обработанный chunk
339
+ this.logger.eventCallback('Fallback к chunk данным', {
340
+ eventType: result.chunk.type,
341
+ isThinking: result.chunk.isThinking,
342
+ hasText: !!result.chunk.text
343
+ });
344
+ options.onEvent(result.chunk.type, result.chunk);
345
+ }
263
346
  }
264
347
  }
265
348
  // Проверяем завершение
@@ -303,11 +386,20 @@ class ChatApi {
303
386
  validateChatOptions(options) {
304
387
  if (!options)
305
388
  return;
306
- // Валидация thinking + tools
389
+ // ✅ ИСПРАВЛЕНИЕ: Валидация thinking + tools согласно документации Anthropic
307
390
  if (options.thinking && options.tools && options.tool_choice) {
308
391
  const choice = options.tool_choice;
309
- if (typeof choice === 'object' && choice.type !== 'auto' && choice.type !== 'none') {
310
- throw new Error('При использовании thinking с инструментами поддерживаются только tool_choice: { type: "auto" } или { type: "none" }');
392
+ if (typeof choice === 'object' && choice.type === 'any') {
393
+ // Только { type: "any" } поддерживается с thinking
394
+ }
395
+ else if (typeof choice === 'object' && choice.type === 'none') {
396
+ // ✅ { type: "none" } также поддерживается
397
+ }
398
+ else if (typeof choice === 'object' && choice.type === 'auto') {
399
+ // ✅ { type: "auto" } тоже поддерживается
400
+ }
401
+ else {
402
+ throw new Error('При использовании thinking с инструментами поддерживаются только tool_choice: { type: "any" }, { type: "auto" } или { type: "none" }. НЕ поддерживаются: { type: "tool", name: "..." }');
311
403
  }
312
404
  }
313
405
  // Валидация temperature с thinking