solver-sdk 1.7.5 → 1.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.
@@ -0,0 +1,342 @@
1
+ # Примеры интеграции с VS Code/Cursor
2
+
3
+ В этом документе приведены примеры использования SDK с VS Code или Cursor расширениями.
4
+
5
+ ## Содержание
6
+ - [Инициализация SDK](#инициализация-sdk)
7
+ - [Работа с проектами](#работа-с-проектами)
8
+ - [Отслеживание прогресса индексации](#отслеживание-прогресса-индексации)
9
+ - [Потоковый чат с мышлением](#потоковый-чат-с-мышлением)
10
+ - [Поиск в коде](#поиск-в-коде)
11
+
12
+ ## Инициализация SDK
13
+
14
+ Пример инициализации SDK в расширении VS Code/Cursor:
15
+
16
+ ```typescript
17
+ import * as vscode from 'vscode';
18
+ import { CodeSolverSDK } from 'solver-sdk';
19
+
20
+ // Инициализация SDK
21
+ const sdk = new CodeSolverSDK({
22
+ baseURL: 'https://api.example.com',
23
+ apiKey: 'your-api-key',
24
+ websocket: {
25
+ reconnect: true,
26
+ reconnectAttempts: 5,
27
+ reconnectDelay: 3000,
28
+ rejectUnauthorized: false // для самоподписанных сертификатов
29
+ }
30
+ });
31
+
32
+ // Проверка доступности API
33
+ async function checkConnection() {
34
+ try {
35
+ const isHealthy = await sdk.checkHealth();
36
+ if (isHealthy) {
37
+ vscode.window.showInformationMessage('API доступен');
38
+ } else {
39
+ vscode.window.showErrorMessage('API недоступен');
40
+ }
41
+ } catch (error) {
42
+ vscode.window.showErrorMessage(`Ошибка соединения: ${error.message}`);
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Работа с проектами
48
+
49
+ Пример автоматической работы с проектом при открытии рабочей области:
50
+
51
+ ```typescript
52
+ import * as path from 'path';
53
+
54
+ // Получение проекта по пути рабочей области
55
+ async function handleWorkspace() {
56
+ try {
57
+ // Получаем путь к текущей рабочей области
58
+ const workspaceFolders = vscode.workspace.workspaceFolders;
59
+ if (!workspaceFolders || workspaceFolders.length === 0) {
60
+ vscode.window.showWarningMessage('Откройте папку проекта');
61
+ return;
62
+ }
63
+
64
+ const workspacePath = workspaceFolders[0].uri.fsPath;
65
+ const projectName = path.basename(workspacePath);
66
+
67
+ // Получаем проект или создаем новый
68
+ const project = await sdk.projects.getOrCreateProject(
69
+ workspacePath,
70
+ projectName
71
+ );
72
+
73
+ if (project) {
74
+ vscode.window.showInformationMessage(`Проект "${projectName}" идентифицирован (ID: ${project.id})`);
75
+ return project;
76
+ }
77
+ } catch (error) {
78
+ vscode.window.showErrorMessage(`Ошибка: ${error.message}`);
79
+ }
80
+
81
+ return null;
82
+ }
83
+ ```
84
+
85
+ ## Отслеживание прогресса индексации
86
+
87
+ Пример отслеживания прогресса индексации:
88
+
89
+ ```typescript
90
+ // Запуск индексации проекта
91
+ async function indexProject(projectId, projectName) {
92
+ try {
93
+ // Запускаем индексацию
94
+ await sdk.projects.indexProject(projectId);
95
+
96
+ // Показываем прогресс
97
+ vscode.window.withProgress({
98
+ location: vscode.ProgressLocation.Notification,
99
+ title: `Индексация проекта "${projectName}"`,
100
+ cancellable: true
101
+ }, async (progress, token) => {
102
+ // Подключаемся к WebSocket для индексации
103
+ await sdk.projects.connectWebSocket();
104
+
105
+ return new Promise((resolve) => {
106
+ // Отслеживаем прогресс
107
+ sdk.projects.on('indexing_progress', (data) => {
108
+ progress.report({
109
+ message: `${data.progress}% (${data.processedFiles}/${data.totalFiles} файлов)`,
110
+ increment: data.progress
111
+ });
112
+ });
113
+
114
+ // Отслеживаем завершение
115
+ sdk.projects.on('indexing_complete', (data) => {
116
+ if (data.success) {
117
+ vscode.window.showInformationMessage('Индексация успешно завершена!');
118
+ } else {
119
+ vscode.window.showWarningMessage(`Индексация завершена с ошибками: ${data.errorMessage || 'неизвестная ошибка'}`);
120
+ }
121
+ sdk.projects.disconnectWebSocket();
122
+ resolve();
123
+ });
124
+
125
+ // Обработка отмены
126
+ token.onCancellationRequested(() => {
127
+ sdk.projects.stopIndexing(projectId)
128
+ .then(() => {
129
+ vscode.window.showInformationMessage('Индексация отменена');
130
+ sdk.projects.disconnectWebSocket();
131
+ resolve();
132
+ });
133
+ });
134
+ });
135
+ });
136
+ } catch (error) {
137
+ vscode.window.showErrorMessage(`Ошибка индексации: ${error.message}`);
138
+ }
139
+ }
140
+ ```
141
+
142
+ ## Потоковый чат с мышлением
143
+
144
+ Пример использования потокового чата с мышлением:
145
+
146
+ ```typescript
147
+ // Регистрация команды чата с мышлением
148
+ context.subscriptions.push(
149
+ vscode.commands.registerCommand('solver.chatWithThinking', async () => {
150
+ try {
151
+ // Запрашиваем ввод от пользователя
152
+ const question = await vscode.window.showInputBox({
153
+ prompt: 'Введите вопрос'
154
+ });
155
+
156
+ if (!question) return;
157
+
158
+ // Создаем и показываем панель для результата
159
+ const panel = vscode.window.createWebviewPanel(
160
+ 'chatWithThinking',
161
+ 'Ответ с мышлением',
162
+ vscode.ViewColumn.Beside,
163
+ { enableScripts: true }
164
+ );
165
+
166
+ // Начальный HTML для панели
167
+ panel.webview.html = `
168
+ <!DOCTYPE html>
169
+ <html>
170
+ <head>
171
+ <style>
172
+ body { font-family: var(--vscode-font-family); padding: 10px; }
173
+ .thinking { color: #666; font-style: italic; white-space: pre-wrap; }
174
+ .answer { white-space: pre-wrap; }
175
+ </style>
176
+ </head>
177
+ <body>
178
+ <h3>Вопрос: ${question}</h3>
179
+ <div class="thinking" id="thinking"></div>
180
+ <h4>Ответ:</h4>
181
+ <div class="answer" id="answer"></div>
182
+ </body>
183
+ </html>
184
+ `;
185
+
186
+ // Сообщения для чата
187
+ const messages = [
188
+ { role: 'user', content: question }
189
+ ];
190
+
191
+ // Опции для чата
192
+ const options = {
193
+ model: 'claude-3-7-sonnet-20240229',
194
+ thinking: true,
195
+ temperature: 0.7
196
+ };
197
+
198
+ // Обработчик событий чата
199
+ const handleEvent = (eventType, data) => {
200
+ if (eventType === 'thinking_delta' && data.thinking) {
201
+ // Обновляем содержимое мышления
202
+ panel.webview.postMessage({
203
+ command: 'appendThinking',
204
+ content: data.thinking
205
+ });
206
+ } else if (eventType === 'text_delta' && data.text) {
207
+ // Обновляем содержимое ответа
208
+ panel.webview.postMessage({
209
+ command: 'appendAnswer',
210
+ content: data.text
211
+ });
212
+ }
213
+ };
214
+
215
+ // Отправляем запрос с мышлением
216
+ await sdk.chat.streamChatWithThinking(
217
+ messages,
218
+ options,
219
+ handleEvent
220
+ );
221
+
222
+ // Настраиваем обработку сообщений в WebView
223
+ panel.webview.onDidReceiveMessage(message => {
224
+ const thinkingElement = document.getElementById('thinking');
225
+ const answerElement = document.getElementById('answer');
226
+
227
+ if (message.command === 'appendThinking') {
228
+ thinkingElement.textContent += message.content;
229
+ } else if (message.command === 'appendAnswer') {
230
+ answerElement.textContent += message.content;
231
+ }
232
+ });
233
+
234
+ } catch (error) {
235
+ vscode.window.showErrorMessage(`Ошибка чата: ${error.message}`);
236
+ }
237
+ })
238
+ );
239
+ ```
240
+
241
+ ## Поиск в коде
242
+
243
+ Пример семантического поиска в проекте:
244
+
245
+ ```typescript
246
+ // Поиск в проекте
247
+ async function searchInProject(projectId, query) {
248
+ try {
249
+ // Показываем индикатор прогресса
250
+ return vscode.window.withProgress({
251
+ location: vscode.ProgressLocation.Notification,
252
+ title: 'Поиск в проекте...',
253
+ cancellable: false
254
+ }, async (progress) => {
255
+ // Выполняем поиск
256
+ const results = await sdk.search.semanticSearch(projectId, {
257
+ query: query,
258
+ limit: 10,
259
+ includeContent: true
260
+ });
261
+
262
+ if (results.results.length === 0) {
263
+ vscode.window.showInformationMessage('Результаты не найдены');
264
+ return;
265
+ }
266
+
267
+ // Отображаем результаты
268
+ const panel = vscode.window.createWebviewPanel(
269
+ 'searchResults',
270
+ 'Результаты поиска',
271
+ vscode.ViewColumn.Beside,
272
+ { enableScripts: true }
273
+ );
274
+
275
+ // Формируем HTML для отображения результатов
276
+ panel.webview.html = `
277
+ <!DOCTYPE html>
278
+ <html>
279
+ <head>
280
+ <style>
281
+ body { font-family: var(--vscode-font-family); padding: 10px; }
282
+ .result { margin-bottom: 15px; padding: 10px; border: 1px solid #ccc; }
283
+ .path { cursor: pointer; color: var(--vscode-textLink-foreground); }
284
+ .snippet { background: var(--vscode-editor-inactiveSelectionBackground); padding: 10px; margin-top: 5px; white-space: pre-wrap; }
285
+ </style>
286
+ </head>
287
+ <body>
288
+ <h3>Результаты для: ${query}</h3>
289
+ ${results.results.map((result, index) => `
290
+ <div class="result">
291
+ <div class="path" data-path="${result.filePath}" data-start="${result.startLine}" data-end="${result.endLine}">
292
+ ${result.filePath}:${result.startLine}-${result.endLine}
293
+ </div>
294
+ <div class="snippet">${result.snippet || result.content || ''}</div>
295
+ </div>
296
+ `).join('')}
297
+
298
+ <script>
299
+ // Добавляем обработчик для открытия файлов
300
+ document.querySelectorAll('.path').forEach(elem => {
301
+ elem.addEventListener('click', () => {
302
+ const vscode = acquireVsCodeApi();
303
+ vscode.postMessage({
304
+ command: 'openFile',
305
+ filePath: elem.dataset.path,
306
+ startLine: parseInt(elem.dataset.start),
307
+ endLine: parseInt(elem.dataset.end)
308
+ });
309
+ });
310
+ });
311
+ </script>
312
+ </body>
313
+ </html>
314
+ `;
315
+
316
+ // Обработка сообщений от WebView
317
+ panel.webview.onDidReceiveMessage(
318
+ message => {
319
+ if (message.command === 'openFile') {
320
+ const uri = vscode.Uri.file(message.filePath);
321
+ vscode.workspace.openTextDocument(uri).then(doc => {
322
+ vscode.window.showTextDocument(doc).then(editor => {
323
+ const range = new vscode.Range(
324
+ new vscode.Position(message.startLine - 1, 0),
325
+ new vscode.Position(message.endLine - 1, 0)
326
+ );
327
+ editor.revealRange(range);
328
+ });
329
+ });
330
+ }
331
+ },
332
+ undefined,
333
+ context.subscriptions
334
+ );
335
+
336
+ return results;
337
+ });
338
+ } catch (error) {
339
+ vscode.window.showErrorMessage(`Ошибка поиска: ${error.message}`);
340
+ }
341
+ }
342
+ ```
package/docs/README.md CHANGED
@@ -1,53 +1,102 @@
1
- # Документация SDK
1
+ 23# Code Solver SDK
2
2
 
3
- Добро пожаловать в документацию SDK для интеграции с Code Solver Backend API.
3
+ JavaScript/TypeScript SDK для взаимодействия с API Code Solver, предназначенного для умной работы с кодом, семантического поиска и AI-ассистентов.
4
4
 
5
- ## Содержание
5
+ ## Установка
6
6
 
7
- ### Введение
8
- - [Быстрый старт](../README.md) - основная информация по установке и использованию SDK
7
+ ```bash
8
+ npm install @code-solver/sdk
9
+ ```
9
10
 
10
- ### Основные функции
11
- - [Потоковая передача мышления](./features/THINKING.md) - получение процесса мышления модели
12
- - [Работа с WebSocket](./WEBSOCKET.md) - соединения и потоковая передача данных
13
- - [Работа с проектами](./PROJECTS.md) - создание и управление проектами
11
+ ## Основные возможности
14
12
 
15
- ### API Reference
16
- - [Аутентификация](./AUTHENTICATION.md) - способы аутентификации в API
17
- - [Обработка ошибок](./ERROR_HANDLING.md) - типы ошибок и их обработка
18
- - [API Reference](./API_REFERENCE.md) - полное описание всех методов SDK
13
+ - **Работа с проектами**: создание, индексация и управление проектами
14
+ - **Семантический поиск**: поиск по смыслу в коде проекта
15
+ - **AI-чат с контекстом**: взаимодействие с AI-моделями в контексте проекта
16
+ - **Работа с WebSocket**: потоковая обработка событий и ответов
17
+ - **Мультиплатформенность**: поддержка как браузеров, так и Node.js
19
18
 
20
- ### Расширенные возможности
21
- - [Механизм ping/pong](./advanced/PING_PONG.md) - мониторинг состояния соединений
19
+ ## Быстрый старт
22
20
 
23
- ## Начало работы
21
+ ```javascript
22
+ import { CodeSolverSDK } from '@code-solver/sdk';
24
23
 
25
- Установите SDK с помощью npm:
24
+ // Инициализация SDK
25
+ const sdk = new CodeSolverSDK({
26
+ baseURL: 'https://api.code-solver.com',
27
+ apiKey: 'ваш-api-ключ',
28
+ websocket: {
29
+ reconnect: true,
30
+ reconnectAttempts: 5
31
+ }
32
+ });
26
33
 
27
- ```bash
28
- npm install solver-sdk
29
- ```
34
+ // Проверка доступности API
35
+ const isAvailable = await sdk.checkHealth();
36
+ if (!isAvailable) {
37
+ console.error('API недоступен');
38
+ return;
39
+ }
30
40
 
31
- Простой пример использования:
41
+ // Создание проекта
42
+ const project = await sdk.projects.createProject(
43
+ 'Мой проект',
44
+ '/путь/к/проекту',
45
+ {
46
+ excludePatterns: ['node_modules', '.git', 'dist']
47
+ }
48
+ );
49
+
50
+ // Индексация проекта
51
+ await sdk.projects.indexProject(project.id);
52
+
53
+ // Отслеживание прогресса индексации через WebSocket
54
+ sdk.projects.on('indexing_progress', (data) => {
55
+ console.log(`Прогресс индексации: ${data.progress}%`);
56
+ });
32
57
 
33
- ```javascript
34
- const { CodeSolverSDK } = require('solver-sdk');
58
+ sdk.projects.on('indexing_complete', (data) => {
59
+ console.log('Индексация завершена!');
60
+ });
35
61
 
36
- // Создание экземпляра SDK
37
- const sdk = new CodeSolverSDK({
38
- baseURL: 'https://api.example.com',
39
- apiKey: 'your-api-key'
62
+ // Семантический поиск
63
+ const searchResults = await sdk.search.semanticSearch(project.id, {
64
+ query: 'функция для обработки HTTP запросов',
65
+ limit: 10
40
66
  });
41
67
 
42
- // Получение списка моделей
43
- async function getModels() {
44
- const models = await sdk.chat.getModels();
45
- console.log('Доступные модели:', models);
46
- }
68
+ // Взаимодействие с AI-ассистентом
69
+ const chatResponse = await sdk.chat.chat([
70
+ {
71
+ role: 'system',
72
+ content: 'Ты опытный программист, помогающий разработчику.'
73
+ },
74
+ {
75
+ role: 'user',
76
+ content: 'Объясни, как работает функция getUserProfile в моем проекте.'
77
+ }
78
+ ], {
79
+ projectId: project.id,
80
+ model: 'claude-3-7-sonnet-20240229'
81
+ });
47
82
 
48
- getModels().catch(console.error);
83
+ console.log(chatResponse.answer);
49
84
  ```
50
85
 
51
- ## Примеры использования
86
+ ## Документация
87
+
88
+ Подробная документация доступна в следующих файлах:
89
+
90
+ - [API Reference](./API_REFERENCE.md) - подробное описание всех методов SDK
91
+ - [Authentication](./AUTHENTICATION.md) - информация по аутентификации
92
+ - [Работа с WebSocket](./WEBSOCKET.md) - примеры работы с WebSocket соединениями
93
+ - [Примеры интеграции](./INTEGRATION_EXAMPLES.md) - примеры интеграции с VS Code/Cursor
94
+
95
+ ## Поддерживаемые платформы
96
+
97
+ - **Браузеры**: Chrome, Firefox, Safari, Edge
98
+ - **Node.js**: 14.x и выше
99
+
100
+ ## Лицензия
52
101
 
53
- Полный набор примеров доступен в директории [examples](../examples).
102
+ MIT
package/docs/WEBSOCKET.md CHANGED
@@ -1,34 +1,165 @@
1
1
  # Работа с WebSocket соединениями
2
2
 
3
- В этом разделе описаны методы SDK для работы с WebSocket соединениями и потоковой передачей данных.
3
+ В этом разделе описаны основные методы для работы с WebSocket соединениями.
4
4
 
5
- ## Основы работы с WebSocket
6
-
7
- SDK предоставляет высокоуровневое API для работы с WebSocket, интегрированное в основные классы:
5
+ ## Получение WebSocket клиента
8
6
 
9
7
  ```javascript
10
8
  const { CodeSolverSDK } = require('solver-sdk');
11
9
 
12
10
  const sdk = new CodeSolverSDK({
13
11
  baseURL: 'https://api.example.com',
14
- apiKey: 'your-api-key'
12
+ apiKey: 'your-api-key',
13
+ websocket: {
14
+ reconnect: true,
15
+ reconnectAttempts: 5,
16
+ reconnectDelay: 3000,
17
+ rejectUnauthorized: true // false для самоподписанных сертификатов
18
+ }
15
19
  });
16
20
 
17
21
  // Получение WebSocket клиента
18
22
  const wsClient = sdk.getWebSocketClient();
19
23
 
20
- // Подключение к пространству имен рассуждений
21
- await wsClient.connectToReasoning('reasoning-id');
24
+ // Подключение к namespace рассуждений
25
+ await wsClient.connectToReasoning();
26
+
27
+ // Подключение к namespace индексации
28
+ await wsClient.connectToIndexing();
29
+
30
+ // Проверка статуса подключения
31
+ const isConnected = wsClient.isConnected(WebSocketNamespace.REASONING);
32
+
33
+ // Отключение от определенного namespace
34
+ await wsClient.disconnect(WebSocketNamespace.REASONING);
35
+
36
+ // Отключение от всех namespace
37
+ await wsClient.disconnectAll();
38
+ ```
39
+
40
+ ## Мониторинг индексации проектов
41
+
42
+ ```javascript
43
+ // Подключение к WebSocket для проектов
44
+ await sdk.projects.connectWebSocket();
45
+
46
+ // Отслеживание прогресса индексации
47
+ sdk.projects.on('indexing_progress', (data) => {
48
+ console.log(`Прогресс индексации: ${data.progress}%`);
49
+ console.log(`Обработано файлов: ${data.processedFiles} из ${data.totalFiles}`);
50
+ });
51
+
52
+ // Завершение индексации
53
+ sdk.projects.on('indexing_complete', (data) => {
54
+ console.log('Индексация завершена!', data.success ? 'Успешно' : 'С ошибками');
55
+
56
+ // Отключение после завершения
57
+ sdk.projects.disconnectWebSocket();
58
+ });
59
+
60
+ // Остановка индексации
61
+ await sdk.projects.stopIndexing(projectId);
62
+ ```
63
+
64
+ ## Потоковый чат с мышлением AI
65
+
66
+ ```javascript
67
+ // Обработчик событий для потокового получения ответа и мышления
68
+ const handleEvent = (eventType, data) => {
69
+ if (eventType === 'thinking_delta' && data.thinking) {
70
+ console.log('Мышление:', data.thinking);
71
+ } else if (eventType === 'text_delta' && data.text) {
72
+ process.stdout.write(data.text); // Вывод текста без переноса строки
73
+ } else if (eventType === 'message_stop') {
74
+ console.log('\nОтвет завершен');
75
+ }
76
+ };
77
+
78
+ // Отправка запроса
79
+ const messages = [
80
+ { role: 'user', content: 'Расскажи о JavaScript' }
81
+ ];
82
+
83
+ const options = {
84
+ model: 'claude-3-7-sonnet-20240229',
85
+ thinking: true,
86
+ temperature: 0.7
87
+ };
88
+
89
+ const response = await sdk.chat.streamChatWithThinking(
90
+ messages,
91
+ options,
92
+ handleEvent
93
+ );
94
+
95
+ console.log(`Socket ID: ${response.socketId}`);
96
+ ```
97
+
98
+ ## Работа с рассуждениями через WebSocket
99
+
100
+ ```javascript
101
+ // Создание рассуждения
102
+ const reasoning = await sdk.reasoning.createReasoning({
103
+ projectId: 'project-id',
104
+ query: 'Объясни этот проект'
105
+ });
106
+
107
+ // Подключение к WebSocket для рассуждений
108
+ await sdk.reasoning.connectWebSocket(reasoning.id);
22
109
 
23
110
  // Подписка на события
24
- wsClient.on('content_block_delta', (data) => {
25
- if (data.delta?.type === 'thinking_delta') {
26
- console.log('Фрагмент мышления:', data.delta.thinking);
111
+ sdk.reasoning.on('thinking', (data) => {
112
+ console.log('Мышление:', data.content);
113
+ });
114
+
115
+ sdk.reasoning.on('complete', (data) => {
116
+ console.log('Результат:', data.content);
117
+ // Отключение после завершения
118
+ sdk.reasoning.disconnectWebSocket();
119
+ });
120
+
121
+ // Запуск рассуждения
122
+ await sdk.reasoning.startReasoning(reasoning.id);
123
+ ```
124
+
125
+ ## Настройка параметров WebSocket
126
+
127
+ ```javascript
128
+ // Настройка параметров WebSocket при создании SDK
129
+ const sdk = new CodeSolverSDK({
130
+ baseURL: 'https://api.example.com',
131
+ apiKey: 'your-api-key',
132
+ websocket: {
133
+ reconnect: true, // Автоматическое переподключение
134
+ reconnectAttempts: 5, // Максимальное количество попыток
135
+ reconnectDelay: 3000, // Задержка между попытками (мс)
136
+ rejectUnauthorized: true, // Проверка SSL-сертификатов
137
+ reconnectStrategy: 'exponential', // Стратегия задержки между попытками
138
+ enableAutoPing: true, // Автоматический ping/pong
139
+ pingInterval: 25000, // Интервал ping в мс
140
+ enableSessionPersistence: true // Сохранение сессии
27
141
  }
28
142
  });
143
+ ```
29
144
 
30
- // Отключение
31
- wsClient.disconnect(WebSocketNamespace.REASONING);
145
+ ## Обработка ошибок в WebSocket
146
+
147
+ ```javascript
148
+ try {
149
+ await sdk.projects.connectWebSocket();
150
+
151
+ // Подписка на события ошибок
152
+ sdk.projects.on('error', (error) => {
153
+ console.error('Ошибка WebSocket:', error.message);
154
+ if (error.type === 'connection_error') {
155
+ console.error('Проблема с подключением');
156
+ } else if (error.type === 'authentication_error') {
157
+ console.error('Ошибка аутентификации');
158
+ }
159
+ });
160
+ } catch (error) {
161
+ console.error('Ошибка при подключении:', error.message);
162
+ }
32
163
  ```
33
164
 
34
165
  ## Модули с поддержкой WebSocket
@@ -163,7 +294,6 @@ const sdk = new CodeSolverSDK({
163
294
  }
164
295
  });
165
296
  ```
166
-
167
297
  ## Дополнительная информация
168
298
 
169
- Для детального описания всех возможностей WebSocket, смотрите [руководство по мышлению](./features/THINKING.md) и примеры в директории [examples/websocket](../examples/websocket).
299
+ Для детального описания всех возможностей WebSocket, смотрите [руководство по мышлению](./features/THINKING.md) и примеры в директории [examples/websocket](../examples/websocket).