solver-sdk 1.0.1

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.
Files changed (167) hide show
  1. package/README.md +248 -0
  2. package/dist/cjs/api/agents-api.js +94 -0
  3. package/dist/cjs/api/agents-api.js.map +1 -0
  4. package/dist/cjs/api/code-modification-api.js +60 -0
  5. package/dist/cjs/api/code-modification-api.js.map +1 -0
  6. package/dist/cjs/api/context-api.js +58 -0
  7. package/dist/cjs/api/context-api.js.map +1 -0
  8. package/dist/cjs/api/projects-api.js +82 -0
  9. package/dist/cjs/api/projects-api.js.map +1 -0
  10. package/dist/cjs/api/reasoning-api.js +73 -0
  11. package/dist/cjs/api/reasoning-api.js.map +1 -0
  12. package/dist/cjs/api/search-api.js +54 -0
  13. package/dist/cjs/api/search-api.js.map +1 -0
  14. package/dist/cjs/code-solver-sdk.js +327 -0
  15. package/dist/cjs/code-solver-sdk.js.map +1 -0
  16. package/dist/cjs/index.js +118 -0
  17. package/dist/cjs/index.js.map +1 -0
  18. package/dist/cjs/interfaces/http-client.js +3 -0
  19. package/dist/cjs/interfaces/http-client.js.map +1 -0
  20. package/dist/cjs/interfaces/sdk-options.js +3 -0
  21. package/dist/cjs/interfaces/sdk-options.js.map +1 -0
  22. package/dist/cjs/models/types.js +17 -0
  23. package/dist/cjs/models/types.js.map +1 -0
  24. package/dist/cjs/utils/code-solver-websocket-client.js +267 -0
  25. package/dist/cjs/utils/code-solver-websocket-client.js.map +1 -0
  26. package/dist/cjs/utils/http-client.js +234 -0
  27. package/dist/cjs/utils/http-client.js.map +1 -0
  28. package/dist/cjs/utils/indexing-websocket-client.js +107 -0
  29. package/dist/cjs/utils/indexing-websocket-client.js.map +1 -0
  30. package/dist/cjs/utils/sse-client.js +233 -0
  31. package/dist/cjs/utils/sse-client.js.map +1 -0
  32. package/dist/cjs/utils/websocket-client.js +268 -0
  33. package/dist/cjs/utils/websocket-client.js.map +1 -0
  34. package/dist/esm/api/agents-api.js +90 -0
  35. package/dist/esm/api/agents-api.js.map +1 -0
  36. package/dist/esm/api/code-modification-api.js +56 -0
  37. package/dist/esm/api/code-modification-api.js.map +1 -0
  38. package/dist/esm/api/context-api.js +54 -0
  39. package/dist/esm/api/context-api.js.map +1 -0
  40. package/dist/esm/api/projects-api.js +78 -0
  41. package/dist/esm/api/projects-api.js.map +1 -0
  42. package/dist/esm/api/reasoning-api.js +69 -0
  43. package/dist/esm/api/reasoning-api.js.map +1 -0
  44. package/dist/esm/api/search-api.js +50 -0
  45. package/dist/esm/api/search-api.js.map +1 -0
  46. package/dist/esm/code-solver-sdk.js +323 -0
  47. package/dist/esm/code-solver-sdk.js.map +1 -0
  48. package/dist/esm/index.js +1882 -0
  49. package/dist/esm/index.js.map +1 -0
  50. package/dist/esm/interfaces/http-client.js +2 -0
  51. package/dist/esm/interfaces/http-client.js.map +1 -0
  52. package/dist/esm/interfaces/sdk-options.js +2 -0
  53. package/dist/esm/interfaces/sdk-options.js.map +1 -0
  54. package/dist/esm/models/types.js +14 -0
  55. package/dist/esm/models/types.js.map +1 -0
  56. package/dist/esm/types/api/agents-api.d.ts +141 -0
  57. package/dist/esm/types/api/agents-api.d.ts.map +1 -0
  58. package/dist/esm/types/api/code-modification-api.d.ts +104 -0
  59. package/dist/esm/types/api/code-modification-api.d.ts.map +1 -0
  60. package/dist/esm/types/api/context-api.d.ts +86 -0
  61. package/dist/esm/types/api/context-api.d.ts.map +1 -0
  62. package/dist/esm/types/api/projects-api.d.ts +89 -0
  63. package/dist/esm/types/api/projects-api.d.ts.map +1 -0
  64. package/dist/esm/types/api/reasoning-api.d.ts +130 -0
  65. package/dist/esm/types/api/reasoning-api.d.ts.map +1 -0
  66. package/dist/esm/types/api/search-api.d.ts +92 -0
  67. package/dist/esm/types/api/search-api.d.ts.map +1 -0
  68. package/dist/esm/types/code-solver-sdk.d.ts +145 -0
  69. package/dist/esm/types/code-solver-sdk.d.ts.map +1 -0
  70. package/dist/esm/types/index.d.ts +81 -0
  71. package/dist/esm/types/index.d.ts.map +1 -0
  72. package/dist/esm/types/interfaces/http-client.d.ts +110 -0
  73. package/dist/esm/types/interfaces/http-client.d.ts.map +1 -0
  74. package/dist/esm/types/interfaces/sdk-options.d.ts +34 -0
  75. package/dist/esm/types/interfaces/sdk-options.d.ts.map +1 -0
  76. package/dist/esm/types/models/types.d.ts +139 -0
  77. package/dist/esm/types/models/types.d.ts.map +1 -0
  78. package/dist/esm/types/utils/code-solver-websocket-client.d.ts +138 -0
  79. package/dist/esm/types/utils/code-solver-websocket-client.d.ts.map +1 -0
  80. package/dist/esm/types/utils/http-client.d.ts +85 -0
  81. package/dist/esm/types/utils/http-client.d.ts.map +1 -0
  82. package/dist/esm/types/utils/indexing-websocket-client.d.ts +123 -0
  83. package/dist/esm/types/utils/indexing-websocket-client.d.ts.map +1 -0
  84. package/dist/esm/types/utils/sse-client.d.ts +92 -0
  85. package/dist/esm/types/utils/sse-client.d.ts.map +1 -0
  86. package/dist/esm/types/utils/websocket-client.d.ts +118 -0
  87. package/dist/esm/types/utils/websocket-client.d.ts.map +1 -0
  88. package/dist/esm/utils/code-solver-websocket-client.js +263 -0
  89. package/dist/esm/utils/code-solver-websocket-client.js.map +1 -0
  90. package/dist/esm/utils/http-client.js +227 -0
  91. package/dist/esm/utils/http-client.js.map +1 -0
  92. package/dist/esm/utils/indexing-websocket-client.js +103 -0
  93. package/dist/esm/utils/indexing-websocket-client.js.map +1 -0
  94. package/dist/esm/utils/sse-client.js +229 -0
  95. package/dist/esm/utils/sse-client.js.map +1 -0
  96. package/dist/esm/utils/websocket-client.js +264 -0
  97. package/dist/esm/utils/websocket-client.js.map +1 -0
  98. package/dist/index.d.ts +1599 -0
  99. package/dist/types/api/agents-api.d.ts +141 -0
  100. package/dist/types/api/agents-api.d.ts.map +1 -0
  101. package/dist/types/api/code-modification-api.d.ts +104 -0
  102. package/dist/types/api/code-modification-api.d.ts.map +1 -0
  103. package/dist/types/api/context-api.d.ts +86 -0
  104. package/dist/types/api/context-api.d.ts.map +1 -0
  105. package/dist/types/api/projects-api.d.ts +89 -0
  106. package/dist/types/api/projects-api.d.ts.map +1 -0
  107. package/dist/types/api/reasoning-api.d.ts +130 -0
  108. package/dist/types/api/reasoning-api.d.ts.map +1 -0
  109. package/dist/types/api/search-api.d.ts +92 -0
  110. package/dist/types/api/search-api.d.ts.map +1 -0
  111. package/dist/types/code-solver-sdk.d.ts +145 -0
  112. package/dist/types/code-solver-sdk.d.ts.map +1 -0
  113. package/dist/types/index.d.ts +81 -0
  114. package/dist/types/index.d.ts.map +1 -0
  115. package/dist/types/interfaces/http-client.d.ts +110 -0
  116. package/dist/types/interfaces/http-client.d.ts.map +1 -0
  117. package/dist/types/interfaces/sdk-options.d.ts +34 -0
  118. package/dist/types/interfaces/sdk-options.d.ts.map +1 -0
  119. package/dist/types/models/types.d.ts +139 -0
  120. package/dist/types/models/types.d.ts.map +1 -0
  121. package/dist/types/utils/code-solver-websocket-client.d.ts +138 -0
  122. package/dist/types/utils/code-solver-websocket-client.d.ts.map +1 -0
  123. package/dist/types/utils/http-client.d.ts +85 -0
  124. package/dist/types/utils/http-client.d.ts.map +1 -0
  125. package/dist/types/utils/indexing-websocket-client.d.ts +123 -0
  126. package/dist/types/utils/indexing-websocket-client.d.ts.map +1 -0
  127. package/dist/types/utils/sse-client.d.ts +92 -0
  128. package/dist/types/utils/sse-client.d.ts.map +1 -0
  129. package/dist/types/utils/websocket-client.d.ts +118 -0
  130. package/dist/types/utils/websocket-client.d.ts.map +1 -0
  131. package/dist/umd/code-solver-sdk.js +1902 -0
  132. package/dist/umd/code-solver-sdk.js.map +1 -0
  133. package/dist/umd/code-solver-sdk.min.js +2 -0
  134. package/dist/umd/code-solver-sdk.min.js.map +1 -0
  135. package/dist/umd/types/api/agents-api.d.ts +141 -0
  136. package/dist/umd/types/api/agents-api.d.ts.map +1 -0
  137. package/dist/umd/types/api/code-modification-api.d.ts +104 -0
  138. package/dist/umd/types/api/code-modification-api.d.ts.map +1 -0
  139. package/dist/umd/types/api/context-api.d.ts +86 -0
  140. package/dist/umd/types/api/context-api.d.ts.map +1 -0
  141. package/dist/umd/types/api/projects-api.d.ts +89 -0
  142. package/dist/umd/types/api/projects-api.d.ts.map +1 -0
  143. package/dist/umd/types/api/reasoning-api.d.ts +130 -0
  144. package/dist/umd/types/api/reasoning-api.d.ts.map +1 -0
  145. package/dist/umd/types/api/search-api.d.ts +92 -0
  146. package/dist/umd/types/api/search-api.d.ts.map +1 -0
  147. package/dist/umd/types/code-solver-sdk.d.ts +145 -0
  148. package/dist/umd/types/code-solver-sdk.d.ts.map +1 -0
  149. package/dist/umd/types/index.d.ts +81 -0
  150. package/dist/umd/types/index.d.ts.map +1 -0
  151. package/dist/umd/types/interfaces/http-client.d.ts +110 -0
  152. package/dist/umd/types/interfaces/http-client.d.ts.map +1 -0
  153. package/dist/umd/types/interfaces/sdk-options.d.ts +34 -0
  154. package/dist/umd/types/interfaces/sdk-options.d.ts.map +1 -0
  155. package/dist/umd/types/models/types.d.ts +139 -0
  156. package/dist/umd/types/models/types.d.ts.map +1 -0
  157. package/dist/umd/types/utils/code-solver-websocket-client.d.ts +138 -0
  158. package/dist/umd/types/utils/code-solver-websocket-client.d.ts.map +1 -0
  159. package/dist/umd/types/utils/http-client.d.ts +85 -0
  160. package/dist/umd/types/utils/http-client.d.ts.map +1 -0
  161. package/dist/umd/types/utils/indexing-websocket-client.d.ts +123 -0
  162. package/dist/umd/types/utils/indexing-websocket-client.d.ts.map +1 -0
  163. package/dist/umd/types/utils/sse-client.d.ts +92 -0
  164. package/dist/umd/types/utils/sse-client.d.ts.map +1 -0
  165. package/dist/umd/types/utils/websocket-client.d.ts +118 -0
  166. package/dist/umd/types/utils/websocket-client.d.ts.map +1 -0
  167. package/package.json +98 -0
@@ -0,0 +1,1882 @@
1
+ import axios from 'axios';
2
+ import { EventSourcePolyfill } from 'event-source-polyfill';
3
+
4
+ /**
5
+ * Определение типа среды выполнения
6
+ * @returns 'browser' | 'node'
7
+ */
8
+ function getEnvironment$1() {
9
+ return (typeof window !== 'undefined' && typeof window.document !== 'undefined')
10
+ ? 'browser'
11
+ : 'node';
12
+ }
13
+ /**
14
+ * HTTP клиент для выполнения запросов к API
15
+ *
16
+ * Предоставляет методы для работы с REST API, включая обработку ошибок,
17
+ * повторные попытки и таймауты.
18
+ */
19
+ class HttpClient {
20
+ /**
21
+ * Создает новый HTTP клиент
22
+ * @param {string} baseURL Базовый URL для запросов
23
+ * @param {HttpClientOptions} [options] Опции для HTTP клиента
24
+ */
25
+ constructor(baseURL, options = {}) {
26
+ this.baseURL = baseURL;
27
+ this.options = {
28
+ headers: {
29
+ 'Content-Type': 'application/json',
30
+ 'Accept': 'application/json',
31
+ ...(options.headers || {})
32
+ },
33
+ timeout: options.timeout || 30000,
34
+ retry: options.retry || {
35
+ maxRetries: 3,
36
+ retryDelay: 1000,
37
+ maxRetryDelay: 10000,
38
+ retryStatusCodes: [408, 429, 500, 502, 503, 504]
39
+ },
40
+ httpsAgent: options.httpsAgent
41
+ };
42
+ this.environment = getEnvironment$1();
43
+ // Создаем Axios инстанс с базовыми настройками
44
+ this.axiosInstance = axios.create({
45
+ baseURL: this.baseURL,
46
+ timeout: this.options.timeout,
47
+ headers: this.options.headers,
48
+ ...(this.environment === 'node' && this.options.httpsAgent ? { httpsAgent: this.options.httpsAgent } : {})
49
+ });
50
+ // Добавляем интерцептор для обработки ошибок и повторных попыток
51
+ this.setupInterceptors();
52
+ }
53
+ /**
54
+ * Настраивает интерцепторы Axios
55
+ */
56
+ setupInterceptors() {
57
+ // Интерцептор для ответов
58
+ this.axiosInstance.interceptors.response.use((response) => response.data, async (error) => {
59
+ const { config, response } = error;
60
+ // Если нет конфига запроса или это уже повторный запрос, или skipRetry установлен, возвращаем ошибку
61
+ if (!config || config._retryCount || config.skipRetry) {
62
+ return Promise.reject(error);
63
+ }
64
+ config._retryCount = config._retryCount || 0;
65
+ const retryConfig = this.options.retry;
66
+ // Проверяем, нужно ли делать повторную попытку для данного статуса
67
+ const shouldRetry = response &&
68
+ retryConfig.retryStatusCodes?.includes(response.status) &&
69
+ config._retryCount < (retryConfig.maxRetries || 3);
70
+ if (shouldRetry) {
71
+ config._retryCount += 1;
72
+ // Вычисляем время задержки перед повторной попыткой
73
+ const delay = Math.min((retryConfig.retryDelay || 1000) * Math.pow(2, config._retryCount - 1), retryConfig.maxRetryDelay || 10000);
74
+ // Ждем перед повторной попыткой
75
+ await new Promise(resolve => setTimeout(resolve, delay));
76
+ // Делаем повторную попытку
77
+ return this.axiosInstance(config);
78
+ }
79
+ // Если не нужно делать повторную попытку, возвращаем ошибку
80
+ return Promise.reject(error);
81
+ });
82
+ }
83
+ /**
84
+ * Выполняет HTTP запрос
85
+ * @param {RequestOptions} options Опции запроса
86
+ * @returns {Promise<T>} Ответ от API
87
+ */
88
+ async request(options) {
89
+ const axiosConfig = {
90
+ url: options.url,
91
+ method: options.method,
92
+ data: options.data,
93
+ params: options.params,
94
+ headers: {
95
+ ...this.options.headers,
96
+ ...(options.headers || {})
97
+ },
98
+ timeout: options.timeout || this.options.timeout
99
+ };
100
+ // Если указано не делать повторные попытки, добавляем специальный флаг
101
+ if (options.noRetry) {
102
+ axiosConfig.skipRetry = true;
103
+ }
104
+ try {
105
+ return await this.axiosInstance.request(axiosConfig);
106
+ }
107
+ catch (error) {
108
+ throw this.handleError(error);
109
+ }
110
+ }
111
+ /**
112
+ * Выполняет GET запрос
113
+ * @param {string} url URL для запроса
114
+ * @param {Record<string, any>} [params] Query параметры
115
+ * @param {Record<string, string>} [headers] HTTP заголовки
116
+ * @returns {Promise<T>} Ответ от API
117
+ */
118
+ async get(url, params, headers) {
119
+ return this.request({
120
+ url,
121
+ method: 'GET',
122
+ params,
123
+ headers
124
+ });
125
+ }
126
+ /**
127
+ * Выполняет POST запрос
128
+ * @param {string} url URL для запроса
129
+ * @param {any} [data] Данные для отправки
130
+ * @param {Record<string, string>} [headers] HTTP заголовки
131
+ * @returns {Promise<T>} Ответ от API
132
+ */
133
+ async post(url, data, headers) {
134
+ return this.request({
135
+ url,
136
+ method: 'POST',
137
+ data,
138
+ headers
139
+ });
140
+ }
141
+ /**
142
+ * Выполняет PUT запрос
143
+ * @param {string} url URL для запроса
144
+ * @param {any} [data] Данные для отправки
145
+ * @param {Record<string, string>} [headers] HTTP заголовки
146
+ * @returns {Promise<T>} Ответ от API
147
+ */
148
+ async put(url, data, headers) {
149
+ return this.request({
150
+ url,
151
+ method: 'PUT',
152
+ data,
153
+ headers
154
+ });
155
+ }
156
+ /**
157
+ * Выполняет DELETE запрос
158
+ * @param {string} url URL для запроса
159
+ * @param {Record<string, any>} [params] Query параметры
160
+ * @param {Record<string, string>} [headers] HTTP заголовки
161
+ * @returns {Promise<T>} Ответ от API
162
+ */
163
+ async delete(url, params, headers) {
164
+ return this.request({
165
+ url,
166
+ method: 'DELETE',
167
+ params,
168
+ headers
169
+ });
170
+ }
171
+ /**
172
+ * Выполняет PATCH запрос
173
+ * @param {string} url URL для запроса
174
+ * @param {any} [data] Данные для отправки
175
+ * @param {Record<string, string>} [headers] HTTP заголовки
176
+ * @returns {Promise<T>} Ответ от API
177
+ */
178
+ async patch(url, data, headers) {
179
+ return this.request({
180
+ url,
181
+ method: 'PATCH',
182
+ data,
183
+ headers
184
+ });
185
+ }
186
+ /**
187
+ * Обрабатывает ошибки от Axios
188
+ * @param {any} error Ошибка от Axios
189
+ * @returns {Error} Обработанная ошибка
190
+ */
191
+ handleError(error) {
192
+ let enhancedError;
193
+ if (error.response) {
194
+ // Ошибка от сервера с кодом ответа
195
+ const { status, data } = error.response;
196
+ const message = data?.message || data?.error || `HTTP ошибка ${status}`;
197
+ enhancedError = new Error(message);
198
+ enhancedError.status = status;
199
+ enhancedError.data = data;
200
+ enhancedError.isApiError = true;
201
+ }
202
+ else if (error.request) {
203
+ // Запрос был сделан, но ответ не получен
204
+ enhancedError = new Error('Нет ответа от сервера. Проверьте подключение к интернету.');
205
+ enhancedError.request = error.request;
206
+ enhancedError.isNetworkError = true;
207
+ }
208
+ else {
209
+ // Произошла ошибка при настройке запроса
210
+ enhancedError = new Error(error.message || 'Произошла неизвестная ошибка');
211
+ enhancedError.isUnknownError = true;
212
+ }
213
+ // Сохраняем оригинальную ошибку для отладки
214
+ enhancedError.originalError = error;
215
+ // Пытаемся обработать ошибку через глобальный обработчик
216
+ try {
217
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
218
+ const { CodeSolverSDK } = require('../code-solver-sdk.js');
219
+ if (typeof CodeSolverSDK.handleError === 'function') {
220
+ CodeSolverSDK.handleError(enhancedError);
221
+ }
222
+ }
223
+ catch (e) {
224
+ // Игнорируем ошибки при импорте или вызове обработчика
225
+ }
226
+ return enhancedError;
227
+ }
228
+ }
229
+
230
+ /**
231
+ * API для работы с проектами
232
+ */
233
+ class ProjectsApi {
234
+ /**
235
+ * Создает новый экземпляр API для работы с проектами
236
+ * @param {HttpClient} httpClient HTTP клиент
237
+ */
238
+ constructor(httpClient) {
239
+ this.httpClient = httpClient;
240
+ }
241
+ /**
242
+ * Получает список всех проектов
243
+ * @returns {Promise<Project[]>} Список проектов
244
+ */
245
+ async getAllProjects() {
246
+ return this.httpClient.get('/api/projects');
247
+ }
248
+ /**
249
+ * Получает проект по идентификатору
250
+ * @param {string} projectId Идентификатор проекта
251
+ * @returns {Promise<Project>} Проект
252
+ */
253
+ async getProject(projectId) {
254
+ return this.httpClient.get(`/api/projects/${projectId}`);
255
+ }
256
+ /**
257
+ * Создает новый проект
258
+ * @param {string} name Название проекта
259
+ * @param {string} path Путь к проекту
260
+ * @returns {Promise<Project>} Созданный проект
261
+ */
262
+ async createProject(name, path) {
263
+ return this.httpClient.post('/api/projects', { name, path });
264
+ }
265
+ /**
266
+ * Обновляет проект
267
+ * @param {string} projectId Идентификатор проекта
268
+ * @param {Partial<Pick<Project, 'name' | 'path'>>} data Данные для обновления
269
+ * @returns {Promise<Project>} Обновленный проект
270
+ */
271
+ async updateProject(projectId, data) {
272
+ return this.httpClient.put(`/api/projects/${projectId}`, data);
273
+ }
274
+ /**
275
+ * Удаляет проект
276
+ * @param {string} projectId Идентификатор проекта
277
+ * @returns {Promise<void>}
278
+ */
279
+ async deleteProject(projectId) {
280
+ return this.httpClient.delete(`/api/projects/${projectId}`);
281
+ }
282
+ /**
283
+ * Запускает индексацию проекта
284
+ * @param {string} projectId Идентификатор проекта
285
+ * @returns {Promise<Project>} Обновленный проект
286
+ */
287
+ async indexProject(projectId) {
288
+ return this.httpClient.post(`/api/projects/${projectId}/index`);
289
+ }
290
+ /**
291
+ * Останавливает индексацию проекта
292
+ * @param {string} projectId Идентификатор проекта
293
+ * @returns {Promise<Project>} Обновленный проект
294
+ */
295
+ async stopIndexing(projectId) {
296
+ return this.httpClient.post(`/api/projects/${projectId}/stop-indexing`);
297
+ }
298
+ /**
299
+ * Получает статус индексации проекта
300
+ * @param {string} projectId Идентификатор проекта
301
+ * @returns {Promise<Project>} Проект с обновленным статусом индексации
302
+ */
303
+ async getIndexingStatus(projectId) {
304
+ return this.httpClient.get(`/api/projects/${projectId}/indexing-status`);
305
+ }
306
+ }
307
+
308
+ /**
309
+ * API для поиска кода
310
+ */
311
+ class SearchApi {
312
+ /**
313
+ * Создает новый экземпляр API для поиска кода
314
+ * @param {HttpClient} httpClient HTTP клиент
315
+ */
316
+ constructor(httpClient) {
317
+ this.httpClient = httpClient;
318
+ }
319
+ /**
320
+ * Выполняет поиск кода в проекте
321
+ * @param {string} projectId Идентификатор проекта
322
+ * @param {SearchCodeParams} params Параметры поиска
323
+ * @returns {Promise<SearchResults>} Результаты поиска
324
+ */
325
+ async searchCode(projectId, params) {
326
+ return this.httpClient.post(`/api/projects/${projectId}/search`, params);
327
+ }
328
+ /**
329
+ * Выполняет семантический поиск кода в проекте
330
+ * @param {string} projectId Идентификатор проекта
331
+ * @param {SearchCodeParams} params Параметры поиска
332
+ * @returns {Promise<SearchResults>} Результаты поиска
333
+ */
334
+ async semanticSearch(projectId, params) {
335
+ return this.httpClient.post(`/api/projects/${projectId}/semantic-search`, params);
336
+ }
337
+ /**
338
+ * Получает популярные поисковые запросы
339
+ * @param {string} projectId Идентификатор проекта
340
+ * @param {number} [limit=10] Лимит результатов
341
+ * @returns {Promise<string[]>} Популярные поисковые запросы
342
+ */
343
+ async getPopularQueries(projectId, limit = 10) {
344
+ return this.httpClient.get(`/api/projects/${projectId}/popular-queries`, { limit });
345
+ }
346
+ /**
347
+ * Получает подсказки для автозаполнения поискового запроса
348
+ * @param {string} projectId Идентификатор проекта
349
+ * @param {string} query Начало поискового запроса
350
+ * @param {number} [limit=5] Лимит результатов
351
+ * @returns {Promise<string[]>} Подсказки для автозаполнения
352
+ */
353
+ async getQuerySuggestions(projectId, query, limit = 5) {
354
+ return this.httpClient.get(`/api/projects/${projectId}/query-suggestions`, { query, limit });
355
+ }
356
+ }
357
+
358
+ /**
359
+ * API для работы с контекстом
360
+ */
361
+ class ContextApi {
362
+ /**
363
+ * Создает новый экземпляр API для работы с контекстом
364
+ * @param {HttpClient} httpClient HTTP клиент
365
+ */
366
+ constructor(httpClient) {
367
+ this.httpClient = httpClient;
368
+ }
369
+ /**
370
+ * Определяет контекст для запроса
371
+ * @param {DetectContextParams} params Параметры определения контекста
372
+ * @returns {Promise<AutoContext>} Определенный контекст
373
+ */
374
+ async detectContext(params) {
375
+ return this.httpClient.post('/api/context/detect', params);
376
+ }
377
+ /**
378
+ * Получает содержимое файла
379
+ * @param {string} projectId Идентификатор проекта
380
+ * @param {string} filePath Путь к файлу
381
+ * @returns {Promise<string>} Содержимое файла
382
+ */
383
+ async getFileContent(projectId, filePath) {
384
+ return this.httpClient.get(`/api/projects/${projectId}/files`, { path: filePath });
385
+ }
386
+ /**
387
+ * Получает содержимое фрагмента файла
388
+ * @param {string} projectId Идентификатор проекта
389
+ * @param {string} filePath Путь к файлу
390
+ * @param {number} startLine Начальная строка
391
+ * @param {number} endLine Конечная строка
392
+ * @returns {Promise<CodeSnippet>} Фрагмент кода
393
+ */
394
+ async getFileSnippet(projectId, filePath, startLine, endLine) {
395
+ return this.httpClient.get(`/api/projects/${projectId}/snippets`, {
396
+ path: filePath,
397
+ startLine,
398
+ endLine
399
+ });
400
+ }
401
+ /**
402
+ * Получает структуру директории
403
+ * @param {string} projectId Идентификатор проекта
404
+ * @param {string} [dirPath='/'] Путь к директории
405
+ * @returns {Promise<Array<{name: string, type: 'file' | 'directory', path: string}>>} Структура директории
406
+ */
407
+ async getDirectoryStructure(projectId, dirPath = '/') {
408
+ return this.httpClient.get(`/api/projects/${projectId}/directory`, { path: dirPath });
409
+ }
410
+ }
411
+
412
+ /**
413
+ * API для работы с рассуждениями
414
+ */
415
+ class ReasoningApi {
416
+ /**
417
+ * Создает новый экземпляр API для работы с рассуждениями
418
+ * @param {HttpClient} httpClient HTTP клиент
419
+ */
420
+ constructor(httpClient) {
421
+ this.httpClient = httpClient;
422
+ }
423
+ /**
424
+ * Получает список рассуждений
425
+ * @param {GetReasoningsParams} [params] Параметры для получения списка
426
+ * @returns {Promise<Reasoning[]>} Список рассуждений
427
+ */
428
+ async getReasonings(params) {
429
+ return this.httpClient.get('/api/reasonings', params);
430
+ }
431
+ /**
432
+ * Получает рассуждение по идентификатору
433
+ * @param {string} reasoningId Идентификатор рассуждения
434
+ * @returns {Promise<Reasoning>} Рассуждение
435
+ */
436
+ async getReasoning(reasoningId) {
437
+ return this.httpClient.get(`/api/reasonings/${reasoningId}`);
438
+ }
439
+ /**
440
+ * Создает новое рассуждение
441
+ * @param {CreateReasoningParams} params Параметры рассуждения
442
+ * @returns {Promise<Reasoning>} Созданное рассуждение
443
+ */
444
+ async createReasoning(params) {
445
+ return this.httpClient.post('/api/reasonings', params);
446
+ }
447
+ /**
448
+ * Запускает процесс рассуждения
449
+ * @param {string} reasoningId Идентификатор рассуждения
450
+ * @returns {Promise<Reasoning>} Рассуждение
451
+ */
452
+ async startReasoning(reasoningId) {
453
+ return this.httpClient.post(`/api/reasonings/${reasoningId}/start`);
454
+ }
455
+ /**
456
+ * Останавливает процесс рассуждения
457
+ * @param {string} reasoningId Идентификатор рассуждения
458
+ * @returns {Promise<Reasoning>} Рассуждение
459
+ */
460
+ async stopReasoning(reasoningId) {
461
+ return this.httpClient.post(`/api/reasonings/${reasoningId}/stop`);
462
+ }
463
+ /**
464
+ * Удаляет рассуждение
465
+ * @param {string} reasoningId Идентификатор рассуждения
466
+ * @returns {Promise<void>}
467
+ */
468
+ async deleteReasoning(reasoningId) {
469
+ return this.httpClient.delete(`/api/reasonings/${reasoningId}`);
470
+ }
471
+ /**
472
+ * Получает промежуточные мысли рассуждения
473
+ * @param {string} reasoningId Идентификатор рассуждения
474
+ * @returns {Promise<string[]>} Промежуточные мысли
475
+ */
476
+ async getThinking(reasoningId) {
477
+ return this.httpClient.get(`/api/reasonings/${reasoningId}/thinking`);
478
+ }
479
+ }
480
+
481
+ /**
482
+ * API для модификации кода
483
+ */
484
+ class CodeModificationApi {
485
+ /**
486
+ * Создает новый экземпляр API для модификации кода
487
+ * @param {HttpClient} httpClient HTTP клиент
488
+ */
489
+ constructor(httpClient) {
490
+ this.httpClient = httpClient;
491
+ }
492
+ /**
493
+ * Выполняет модификацию кода
494
+ * @param {CodeModificationParams} params Параметры модификации
495
+ * @returns {Promise<CodeModificationResult>} Результат модификации
496
+ */
497
+ async modifyCode(params) {
498
+ return this.httpClient.post('/api/code-modifications', params);
499
+ }
500
+ /**
501
+ * Применяет результат модификации к файлу
502
+ * @param {string} modificationId Идентификатор модификации
503
+ * @returns {Promise<CodeModificationResult>} Обновленный результат модификации
504
+ */
505
+ async applyModification(modificationId) {
506
+ return this.httpClient.post(`/api/code-modifications/${modificationId}/apply`);
507
+ }
508
+ /**
509
+ * Отменяет применение модификации
510
+ * @param {string} modificationId Идентификатор модификации
511
+ * @returns {Promise<CodeModificationResult>} Обновленный результат модификации
512
+ */
513
+ async revertModification(modificationId) {
514
+ return this.httpClient.post(`/api/code-modifications/${modificationId}/revert`);
515
+ }
516
+ /**
517
+ * Получает модификацию по идентификатору
518
+ * @param {string} modificationId Идентификатор модификации
519
+ * @returns {Promise<CodeModificationResult>} Результат модификации
520
+ */
521
+ async getModification(modificationId) {
522
+ return this.httpClient.get(`/api/code-modifications/${modificationId}`);
523
+ }
524
+ /**
525
+ * Получает список модификаций для проекта
526
+ * @param {string} projectId Идентификатор проекта
527
+ * @param {object} [params] Параметры запроса
528
+ * @param {number} [params.limit] Лимит результатов
529
+ * @param {number} [params.offset] Смещение для пагинации
530
+ * @returns {Promise<CodeModificationResult[]>} Список результатов модификации
531
+ */
532
+ async getModifications(projectId, params) {
533
+ return this.httpClient.get(`/api/projects/${projectId}/code-modifications`, params);
534
+ }
535
+ }
536
+
537
+ /**
538
+ * Базовый класс для WebSocket клиентов
539
+ */
540
+ class WebSocketClient {
541
+ /**
542
+ * Создает новый WebSocket клиент
543
+ * @param {string} url URL для подключения
544
+ * @param {WebSocketClientOptions} [options] Опции клиента
545
+ */
546
+ constructor(url, options = {}) {
547
+ /** Экземпляр WebSocket */
548
+ this.webSocket = null;
549
+ /** Счетчик попыток переподключения */
550
+ this.retryCount = 0;
551
+ /** Флаг, указывающий, что соединение было закрыто намеренно */
552
+ this.intentionallyClosed = false;
553
+ /** Таймер переподключения */
554
+ this.reconnectTimer = null;
555
+ /** Таймер таймаута соединения */
556
+ this.connectionTimeoutTimer = null;
557
+ /** Обработчики событий */
558
+ this.eventHandlers = {};
559
+ /** Очередь сообщений для отправки после подключения */
560
+ this.messageQueue = [];
561
+ /** Состояние соединения */
562
+ this.connected = false;
563
+ this.url = url;
564
+ this.options = {
565
+ headers: options.headers || {},
566
+ connectionTimeout: options.connectionTimeout || 30000,
567
+ protocols: options.protocols || [],
568
+ maxRetries: options.maxRetries || 5,
569
+ retryDelay: options.retryDelay || 1000,
570
+ maxRetryDelay: options.maxRetryDelay || 30000,
571
+ autoReconnect: options.autoReconnect !== undefined ? options.autoReconnect : true
572
+ };
573
+ // Определяем среду выполнения
574
+ this.isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
575
+ }
576
+ /**
577
+ * Подключается к WebSocket серверу
578
+ * @returns {Promise<void>}
579
+ */
580
+ connect() {
581
+ // Если соединение уже установлено, возвращаем Promise.resolve
582
+ if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
583
+ return Promise.resolve();
584
+ }
585
+ // Сбрасываем флаг намеренного закрытия
586
+ this.intentionallyClosed = false;
587
+ return new Promise((resolve, reject) => {
588
+ try {
589
+ // Создаем новый экземпляр WebSocket
590
+ if (this.isBrowser) {
591
+ // Браузерное окружение
592
+ this.webSocket = new WebSocket(this.url, this.options.protocols);
593
+ }
594
+ else {
595
+ // Node.js окружение
596
+ try {
597
+ // Динамически импортируем ws модуль в Node.js
598
+ const WebSocketImpl = require('ws');
599
+ this.webSocket = new WebSocketImpl(this.url, {
600
+ headers: this.options.headers,
601
+ protocol: this.options.protocols
602
+ });
603
+ }
604
+ catch (error) {
605
+ reject(new Error('Не удалось загрузить модуль ws в Node.js: ' + error.message));
606
+ return;
607
+ }
608
+ }
609
+ // Устанавливаем таймаут соединения
610
+ this.connectionTimeoutTimer = setTimeout(() => {
611
+ if (this.webSocket && this.webSocket.readyState !== WebSocket.OPEN) {
612
+ reject(new Error('Таймаут подключения WebSocket'));
613
+ this.close();
614
+ }
615
+ }, this.options.connectionTimeout);
616
+ // Обработчик открытия соединения
617
+ this.webSocket.onopen = () => {
618
+ clearTimeout(this.connectionTimeoutTimer);
619
+ this.retryCount = 0;
620
+ this.connected = true;
621
+ // Отправляем сообщения из очереди
622
+ while (this.messageQueue.length > 0) {
623
+ const message = this.messageQueue.shift();
624
+ if (message && this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
625
+ this.webSocket.send(message);
626
+ }
627
+ }
628
+ resolve();
629
+ this.dispatchEvent('open', {});
630
+ };
631
+ // Обработчик сообщений
632
+ this.webSocket.onmessage = (event) => {
633
+ try {
634
+ // Пытаемся распарсить сообщение как JSON
635
+ let data = event.data;
636
+ if (typeof data === 'string') {
637
+ try {
638
+ data = JSON.parse(data);
639
+ }
640
+ catch (e) {
641
+ // Если не удалось распарсить, оставляем как есть
642
+ }
643
+ }
644
+ this.dispatchEvent('message', data);
645
+ }
646
+ catch (e) {
647
+ console.error('Ошибка при обработке сообщения WebSocket:', e);
648
+ }
649
+ };
650
+ // Обработчик закрытия соединения
651
+ this.webSocket.onclose = (event) => {
652
+ clearTimeout(this.connectionTimeoutTimer);
653
+ this.connected = false;
654
+ this.dispatchEvent('close', { code: event.code, reason: event.reason });
655
+ // Если соединение было закрыто намеренно, не пытаемся переподключиться
656
+ if (this.intentionallyClosed) {
657
+ return;
658
+ }
659
+ // Если включено автоматическое переподключение, пытаемся переподключиться
660
+ if (this.options.autoReconnect) {
661
+ this.reconnect();
662
+ }
663
+ };
664
+ // Обработчик ошибок
665
+ this.webSocket.onerror = (error) => {
666
+ this.dispatchEvent('error', error);
667
+ // Если соединение не установлено и это первая попытка, отклоняем Promise
668
+ if (!this.connected && this.retryCount === 0) {
669
+ clearTimeout(this.connectionTimeoutTimer);
670
+ reject(new Error('Ошибка подключения WebSocket'));
671
+ }
672
+ };
673
+ }
674
+ catch (error) {
675
+ reject(error);
676
+ }
677
+ });
678
+ }
679
+ /**
680
+ * Переподключается к WebSocket серверу
681
+ * @private
682
+ */
683
+ reconnect() {
684
+ // Увеличиваем счетчик попыток
685
+ this.retryCount++;
686
+ // Если превышено максимальное количество попыток, не пытаемся переподключиться
687
+ if (this.retryCount > (this.options.maxRetries || 5)) {
688
+ this.dispatchEvent('maxRetries', { retries: this.retryCount });
689
+ return;
690
+ }
691
+ // Вычисляем задержку перед переподключением с экспоненциальным ростом
692
+ const delay = Math.min((this.options.retryDelay || 1000) * Math.pow(2, this.retryCount - 1), this.options.maxRetryDelay || 30000);
693
+ // Пытаемся переподключиться после задержки
694
+ this.reconnectTimer = setTimeout(() => {
695
+ this.dispatchEvent('reconnect', { attempt: this.retryCount });
696
+ this.connect().catch(() => { });
697
+ }, delay);
698
+ }
699
+ /**
700
+ * Закрывает WebSocket соединение
701
+ * @param {number} [code=1000] Код закрытия
702
+ * @param {string} [reason] Причина закрытия
703
+ */
704
+ close(code = 1000, reason) {
705
+ this.intentionallyClosed = true;
706
+ // Очищаем таймеры
707
+ clearTimeout(this.reconnectTimer);
708
+ clearTimeout(this.connectionTimeoutTimer);
709
+ // Очищаем очередь сообщений
710
+ this.messageQueue = [];
711
+ // Закрываем соединение
712
+ if (this.webSocket) {
713
+ if (this.webSocket.readyState === WebSocket.OPEN) {
714
+ this.webSocket.close(code, reason);
715
+ }
716
+ this.webSocket = null;
717
+ }
718
+ this.connected = false;
719
+ }
720
+ /**
721
+ * Отправляет сообщение через WebSocket
722
+ * @param {string | object} message Сообщение для отправки
723
+ * @returns {boolean} Успешно ли отправлено сообщение
724
+ */
725
+ send(message) {
726
+ const data = typeof message === 'string' ? message : JSON.stringify(message);
727
+ if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
728
+ this.webSocket.send(data);
729
+ return true;
730
+ }
731
+ else {
732
+ // Если соединение не установлено, добавляем сообщение в очередь
733
+ this.messageQueue.push(data);
734
+ // Если соединение не установлено и не закрыто намеренно, пытаемся подключиться
735
+ if ((!this.webSocket || this.webSocket.readyState === WebSocket.CLOSED) && !this.intentionallyClosed) {
736
+ this.connect().catch(() => { });
737
+ }
738
+ return false;
739
+ }
740
+ }
741
+ /**
742
+ * Проверяет, установлено ли соединение
743
+ * @returns {boolean} Установлено ли соединение
744
+ */
745
+ isConnected() {
746
+ return this.webSocket !== null && this.webSocket.readyState === WebSocket.OPEN;
747
+ }
748
+ /**
749
+ * Добавляет обработчик события
750
+ * @param {string} eventType Тип события
751
+ * @param {WebSocketEventHandler} handler Обработчик события
752
+ */
753
+ on(eventType, handler) {
754
+ if (!this.eventHandlers[eventType]) {
755
+ this.eventHandlers[eventType] = [];
756
+ }
757
+ this.eventHandlers[eventType].push(handler);
758
+ }
759
+ /**
760
+ * Удаляет обработчик события
761
+ * @param {string} eventType Тип события
762
+ * @param {WebSocketEventHandler} [handler] Обработчик события (если не указан, удаляются все обработчики)
763
+ */
764
+ off(eventType, handler) {
765
+ if (!this.eventHandlers[eventType]) {
766
+ return;
767
+ }
768
+ if (!handler) {
769
+ // Если обработчик не указан, удаляем все обработчики для данного события
770
+ delete this.eventHandlers[eventType];
771
+ }
772
+ else {
773
+ // Если обработчик указан, удаляем только его
774
+ this.eventHandlers[eventType] = this.eventHandlers[eventType].filter(h => h !== handler);
775
+ // Если обработчиков больше нет, удаляем массив
776
+ if (this.eventHandlers[eventType].length === 0) {
777
+ delete this.eventHandlers[eventType];
778
+ }
779
+ }
780
+ }
781
+ /**
782
+ * Вызывает обработчики для указанного события
783
+ * @param {string} eventType Тип события
784
+ * @param {any} data Данные события
785
+ */
786
+ dispatchEvent(eventType, data) {
787
+ if (!this.eventHandlers[eventType]) {
788
+ return;
789
+ }
790
+ for (const handler of this.eventHandlers[eventType]) {
791
+ try {
792
+ handler(data);
793
+ }
794
+ catch (e) {
795
+ console.error(`Ошибка в обработчике события ${eventType}:`, e);
796
+ }
797
+ }
798
+ }
799
+ }
800
+
801
+ /**
802
+ * Пространства имен для WebSocket
803
+ */
804
+ var WebSocketNamespace;
805
+ (function (WebSocketNamespace) {
806
+ /** Пространство имен для рассуждений */
807
+ WebSocketNamespace["REASONING"] = "reasoning";
808
+ /** Пространство имен для индексации */
809
+ WebSocketNamespace["INDEXING"] = "indexing";
810
+ /** Пространство имен для уведомлений */
811
+ WebSocketNamespace["NOTIFICATIONS"] = "notifications";
812
+ })(WebSocketNamespace || (WebSocketNamespace = {}));
813
+ /**
814
+ * WebSocket клиент для работы с Code Solver API
815
+ */
816
+ class CodeSolverWebSocketClient {
817
+ /**
818
+ * Создает новый WebSocket клиент для Code Solver API
819
+ * @param {string} baseURL Базовый URL API
820
+ * @param {CodeSolverWebSocketOptions} [options] Опции клиента
821
+ */
822
+ constructor(baseURL, options = {}) {
823
+ /** WebSocket клиенты для разных пространств имен */
824
+ this.clients = new Map();
825
+ /** Активная сессия рассуждения */
826
+ this.activeReasoningId = null;
827
+ /** Активная сессия индексации */
828
+ this.activeProjectId = null;
829
+ this.baseURL = baseURL.replace(/^http/, 'ws');
830
+ this.options = {
831
+ ...options,
832
+ headers: {
833
+ ...(options.headers || {}),
834
+ ...(options.apiKey ? { 'Authorization': `Bearer ${options.apiKey}` } : {})
835
+ }
836
+ };
837
+ }
838
+ /**
839
+ * Подключается к пространству имен WebSocket
840
+ * @param {WebSocketNamespace} namespace Пространство имен
841
+ * @param {Record<string, any>} [params] Параметры подключения
842
+ * @returns {Promise<WebSocketClient>} WebSocket клиент
843
+ */
844
+ async connect(namespace, params = {}) {
845
+ // Если клиент уже существует, возвращаем его
846
+ if (this.clients.has(namespace)) {
847
+ const client = this.clients.get(namespace);
848
+ // Если клиент уже подключен, возвращаем его
849
+ if (client.isConnected()) {
850
+ return client;
851
+ }
852
+ }
853
+ // Формируем URL для подключения
854
+ const url = new URL(`${this.baseURL}/${namespace}`);
855
+ // Добавляем параметры к URL
856
+ Object.entries(params).forEach(([key, value]) => {
857
+ url.searchParams.append(key, String(value));
858
+ });
859
+ // Создаем новый WebSocket клиент
860
+ const client = new WebSocketClient(url.toString(), this.options);
861
+ // Подключаемся к серверу
862
+ await client.connect();
863
+ // Сохраняем клиент
864
+ this.clients.set(namespace, client);
865
+ return client;
866
+ }
867
+ /**
868
+ * Подключается к сессии рассуждения
869
+ * @param {string} [reasoningId] Идентификатор рассуждения
870
+ * @returns {Promise<void>}
871
+ */
872
+ async connectToReasoning(reasoningId) {
873
+ // Если reasoningId не указан, используем активный
874
+ const id = reasoningId || this.activeReasoningId;
875
+ if (!id) {
876
+ throw new Error('Необходимо указать идентификатор рассуждения');
877
+ }
878
+ // Сохраняем активный идентификатор рассуждения
879
+ this.activeReasoningId = id;
880
+ // Подключаемся к пространству имен
881
+ await this.connect(WebSocketNamespace.REASONING, { reasoningId: id });
882
+ }
883
+ /**
884
+ * Подключается к сессии индексации проекта
885
+ * @param {string} [projectId] Идентификатор проекта
886
+ * @returns {Promise<void>}
887
+ */
888
+ async connectToIndexing(projectId) {
889
+ // Если projectId не указан, используем активный
890
+ const id = projectId || this.activeProjectId;
891
+ if (!id) {
892
+ throw new Error('Необходимо указать идентификатор проекта');
893
+ }
894
+ // Сохраняем активный идентификатор проекта
895
+ this.activeProjectId = id;
896
+ // Подключаемся к пространству имен
897
+ await this.connect(WebSocketNamespace.INDEXING, { projectId: id });
898
+ }
899
+ /**
900
+ * Подключается к уведомлениям
901
+ * @returns {Promise<void>}
902
+ */
903
+ async connectToNotifications() {
904
+ // Подключаемся к пространству имен
905
+ await this.connect(WebSocketNamespace.NOTIFICATIONS);
906
+ }
907
+ /**
908
+ * Отключается от пространства имен
909
+ * @param {WebSocketNamespace} namespace Пространство имен
910
+ */
911
+ disconnect(namespace) {
912
+ const client = this.clients.get(namespace);
913
+ if (client) {
914
+ client.close();
915
+ this.clients.delete(namespace);
916
+ }
917
+ // Сбрасываем активные сессии
918
+ if (namespace === WebSocketNamespace.REASONING) {
919
+ this.activeReasoningId = null;
920
+ }
921
+ else if (namespace === WebSocketNamespace.INDEXING) {
922
+ this.activeProjectId = null;
923
+ }
924
+ }
925
+ /**
926
+ * Отключается от всех пространств имен
927
+ */
928
+ disconnectAll() {
929
+ for (const [namespace, client] of this.clients.entries()) {
930
+ client.close();
931
+ this.clients.delete(namespace);
932
+ }
933
+ // Сбрасываем активные сессии
934
+ this.activeReasoningId = null;
935
+ this.activeProjectId = null;
936
+ }
937
+ /**
938
+ * Добавляет обработчик события для пространства имен
939
+ * @param {string} eventType Тип события
940
+ * @param {Function} handler Обработчик события
941
+ * @param {WebSocketNamespace} [namespace] Пространство имен (если не указано, добавляется ко всем активным)
942
+ */
943
+ on(eventType, handler, namespace) {
944
+ if (namespace) {
945
+ // Если указано пространство имен, добавляем обработчик только к нему
946
+ const client = this.clients.get(namespace);
947
+ if (!client) {
948
+ throw new Error(`Не подключен к пространству имен ${namespace}`);
949
+ }
950
+ client.on(eventType, handler);
951
+ }
952
+ else {
953
+ // Если пространство имен не указано, добавляем обработчик ко всем активным пространствам
954
+ for (const client of this.clients.values()) {
955
+ client.on(eventType, handler);
956
+ }
957
+ }
958
+ }
959
+ /**
960
+ * Удаляет обработчик события для пространства имен
961
+ * @param {string} eventType Тип события
962
+ * @param {Function} [handler] Обработчик события (если не указан, удаляются все обработчики)
963
+ * @param {WebSocketNamespace} [namespace] Пространство имен (если не указано, удаляется из всех активных)
964
+ */
965
+ off(eventType, handler, namespace) {
966
+ if (namespace) {
967
+ // Если указано пространство имен, удаляем обработчик только из него
968
+ const client = this.clients.get(namespace);
969
+ if (!client) {
970
+ return;
971
+ }
972
+ client.off(eventType, handler);
973
+ }
974
+ else {
975
+ // Если пространство имен не указано, удаляем обработчик из всех активных пространств
976
+ for (const client of this.clients.values()) {
977
+ client.off(eventType, handler);
978
+ }
979
+ }
980
+ }
981
+ /**
982
+ * Отправляет сообщение в пространство имен
983
+ * @param {WebSocketNamespace} namespace Пространство имен
984
+ * @param {string} eventType Тип события
985
+ * @param {any} [data] Данные сообщения
986
+ * @returns {boolean} Успешно ли отправлено сообщение
987
+ */
988
+ send(namespace, eventType, data) {
989
+ const client = this.clients.get(namespace);
990
+ if (!client) {
991
+ throw new Error(`Не подключен к пространству имен ${namespace}`);
992
+ }
993
+ return client.send({
994
+ event: eventType,
995
+ data
996
+ });
997
+ }
998
+ /**
999
+ * Отправляет сообщение в активную сессию рассуждения
1000
+ * @param {string} eventType Тип события
1001
+ * @param {any} [data] Данные сообщения
1002
+ * @returns {boolean} Успешно ли отправлено сообщение
1003
+ */
1004
+ sendToReasoning(eventType, data) {
1005
+ if (!this.activeReasoningId) {
1006
+ throw new Error('Не подключен к сессии рассуждения');
1007
+ }
1008
+ return this.send(WebSocketNamespace.REASONING, eventType, data);
1009
+ }
1010
+ /**
1011
+ * Отправляет сообщение в активную сессию индексации
1012
+ * @param {string} eventType Тип события
1013
+ * @param {any} [data] Данные сообщения
1014
+ * @returns {boolean} Успешно ли отправлено сообщение
1015
+ */
1016
+ sendToIndexing(eventType, data) {
1017
+ if (!this.activeProjectId) {
1018
+ throw new Error('Не подключен к сессии индексации');
1019
+ }
1020
+ return this.send(WebSocketNamespace.INDEXING, eventType, data);
1021
+ }
1022
+ /**
1023
+ * Отправляет сообщение в уведомления
1024
+ * @param {string} eventType Тип события
1025
+ * @param {any} [data] Данные сообщения
1026
+ * @returns {boolean} Успешно ли отправлено сообщение
1027
+ */
1028
+ sendToNotifications(eventType, data) {
1029
+ return this.send(WebSocketNamespace.NOTIFICATIONS, eventType, data);
1030
+ }
1031
+ /**
1032
+ * Проверяет, подключен ли клиент к указанному пространству имен
1033
+ * @param {WebSocketNamespace} namespace Пространство имен
1034
+ * @returns {boolean} Статус подключения
1035
+ */
1036
+ isConnected(namespace) {
1037
+ const client = this.clients.get(namespace);
1038
+ return client ? client.isConnected() : false;
1039
+ }
1040
+ /**
1041
+ * Проверяет, подключен ли клиент к пространству имен рассуждений
1042
+ * @returns {boolean} Статус подключения
1043
+ */
1044
+ isConnectedToReasoning() {
1045
+ return this.isConnected(WebSocketNamespace.REASONING);
1046
+ }
1047
+ /**
1048
+ * Проверяет, подключен ли клиент к пространству имен индексации
1049
+ * @returns {boolean} Статус подключения
1050
+ */
1051
+ isConnectedToIndexing() {
1052
+ return this.isConnected(WebSocketNamespace.INDEXING);
1053
+ }
1054
+ /**
1055
+ * Проверяет, подключен ли клиент к пространству имен уведомлений
1056
+ * @returns {boolean} Статус подключения
1057
+ */
1058
+ isConnectedToNotifications() {
1059
+ return this.isConnected(WebSocketNamespace.NOTIFICATIONS);
1060
+ }
1061
+ }
1062
+
1063
+ /**
1064
+ * API для работы с агентами
1065
+ */
1066
+ class AgentsApi {
1067
+ /**
1068
+ * Создает новый экземпляр API для работы с агентами
1069
+ * @param {HttpClient} httpClient HTTP клиент
1070
+ */
1071
+ constructor(httpClient) {
1072
+ this.httpClient = httpClient;
1073
+ }
1074
+ /**
1075
+ * Получает список всех агентов проекта
1076
+ * @param {string} projectId Идентификатор проекта
1077
+ * @returns {Promise<Agent[]>} Список агентов
1078
+ */
1079
+ async getAgents(projectId) {
1080
+ return this.httpClient.get(`/api/projects/${projectId}/agents`);
1081
+ }
1082
+ /**
1083
+ * Получает агента по идентификатору
1084
+ * @param {string} agentId Идентификатор агента
1085
+ * @returns {Promise<Agent>} Агент
1086
+ */
1087
+ async getAgent(agentId) {
1088
+ return this.httpClient.get(`/api/agents/${agentId}`);
1089
+ }
1090
+ /**
1091
+ * Создает нового агента
1092
+ * @param {CreateAgentParams} params Параметры создания агента
1093
+ * @returns {Promise<Agent>} Созданный агент
1094
+ */
1095
+ async createAgent(params) {
1096
+ return this.httpClient.post('/api/agents', params);
1097
+ }
1098
+ /**
1099
+ * Обновляет агента
1100
+ * @param {string} agentId Идентификатор агента
1101
+ * @param {Partial<Pick<Agent, 'name' | 'description' | 'settings'>>} data Данные для обновления
1102
+ * @returns {Promise<Agent>} Обновленный агент
1103
+ */
1104
+ async updateAgent(agentId, data) {
1105
+ return this.httpClient.put(`/api/agents/${agentId}`, data);
1106
+ }
1107
+ /**
1108
+ * Удаляет агента
1109
+ * @param {string} agentId Идентификатор агента
1110
+ * @returns {Promise<void>}
1111
+ */
1112
+ async deleteAgent(agentId) {
1113
+ return this.httpClient.delete(`/api/agents/${agentId}`);
1114
+ }
1115
+ /**
1116
+ * Запускает агента
1117
+ * @param {string} agentId Идентификатор агента
1118
+ * @param {object} [params] Параметры запуска
1119
+ * @returns {Promise<Agent>} Обновленный агент
1120
+ */
1121
+ async startAgent(agentId, params) {
1122
+ return this.httpClient.post(`/api/agents/${agentId}/start`, params);
1123
+ }
1124
+ /**
1125
+ * Останавливает агента
1126
+ * @param {string} agentId Идентификатор агента
1127
+ * @returns {Promise<Agent>} Обновленный агент
1128
+ */
1129
+ async stopAgent(agentId) {
1130
+ return this.httpClient.post(`/api/agents/${agentId}/stop`);
1131
+ }
1132
+ /**
1133
+ * Получает задачи агента
1134
+ * @param {string} agentId Идентификатор агента
1135
+ * @returns {Promise<AgentTask[]>} Список задач
1136
+ */
1137
+ async getAgentTasks(agentId) {
1138
+ return this.httpClient.get(`/api/agents/${agentId}/tasks`);
1139
+ }
1140
+ /**
1141
+ * Создает новую задачу для агента
1142
+ * @param {string} agentId Идентификатор агента
1143
+ * @param {object} params Параметры задачи
1144
+ * @param {string} params.description Описание задачи
1145
+ * @param {object} [params.context] Контекст задачи
1146
+ * @returns {Promise<AgentTask>} Созданная задача
1147
+ */
1148
+ async createAgentTask(agentId, params) {
1149
+ return this.httpClient.post(`/api/agents/${agentId}/tasks`, params);
1150
+ }
1151
+ }
1152
+
1153
+ // Версия SDK
1154
+ const SDK_VERSION = '1.0.0';
1155
+ /**
1156
+ * Определение типа среды выполнения
1157
+ * @returns 'browser' | 'node' | 'unknown'
1158
+ */
1159
+ function getEnvironment() {
1160
+ if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
1161
+ return 'browser';
1162
+ }
1163
+ else if (typeof process !== 'undefined' && process.versions && process.versions.node) {
1164
+ return 'node';
1165
+ }
1166
+ return 'unknown';
1167
+ }
1168
+ /**
1169
+ * Основной класс SDK для работы с Code Solver API
1170
+ * Поддерживает работу как в браузере, так и в Node.js
1171
+ */
1172
+ class CodeSolverSDK {
1173
+ /**
1174
+ * Создает новый экземпляр SDK
1175
+ * @param {CodeSolverSDKOptions} options Опции SDK
1176
+ */
1177
+ constructor(options) {
1178
+ /** WebSocket клиент для работы с реалтайм API */
1179
+ this.wsClient = null;
1180
+ this._options = {
1181
+ ...options,
1182
+ mode: options.mode || 'auto'
1183
+ };
1184
+ // Определяем среду выполнения
1185
+ this.environment = this._options.mode === 'auto'
1186
+ ? getEnvironment()
1187
+ : this._options.mode === 'browser' ? 'browser' : 'node';
1188
+ // Инициализируем HTTP клиент
1189
+ this.httpClient = new HttpClient(this._options.baseURL, {
1190
+ headers: {
1191
+ ...(this._options.apiKey ? { 'Authorization': `Bearer ${this._options.apiKey}` } : {}),
1192
+ ...(this._options.headers || {})
1193
+ },
1194
+ timeout: this._options.timeout,
1195
+ httpsAgent: this.environment === 'node' ? this._options.httpsAgent : undefined
1196
+ });
1197
+ // Инициализируем API клиенты
1198
+ this._agents = new AgentsApi(this.httpClient);
1199
+ this._context = new ContextApi(this.httpClient);
1200
+ this._projects = new ProjectsApi(this.httpClient);
1201
+ this._search = new SearchApi(this.httpClient);
1202
+ this._reasoning = new ReasoningApi(this.httpClient);
1203
+ this._codeModification = new CodeModificationApi(this.httpClient);
1204
+ }
1205
+ /**
1206
+ * Проверяет доступность API
1207
+ * @returns {Promise<boolean>} Доступен ли API
1208
+ */
1209
+ async checkHealth() {
1210
+ try {
1211
+ await this.httpClient.get('/health');
1212
+ return true;
1213
+ }
1214
+ catch (error) {
1215
+ return false;
1216
+ }
1217
+ }
1218
+ /**
1219
+ * Получает WebSocket клиент
1220
+ * @returns {CodeSolverWebSocketClient} WebSocket клиент
1221
+ */
1222
+ getWebSocketClient() {
1223
+ if (!this.wsClient) {
1224
+ this.wsClient = new CodeSolverWebSocketClient(this._options.baseURL, {
1225
+ apiKey: this._options.apiKey,
1226
+ headers: this._options.headers
1227
+ });
1228
+ }
1229
+ return this.wsClient;
1230
+ }
1231
+ /**
1232
+ * API для работы с агентами
1233
+ */
1234
+ get agents() {
1235
+ return this._agents;
1236
+ }
1237
+ /**
1238
+ * API для работы с контекстом
1239
+ */
1240
+ get context() {
1241
+ return this._context;
1242
+ }
1243
+ /**
1244
+ * API для работы с проектами
1245
+ */
1246
+ get projects() {
1247
+ return this._projects;
1248
+ }
1249
+ /**
1250
+ * API для поиска кода
1251
+ */
1252
+ get search() {
1253
+ return this._search;
1254
+ }
1255
+ /**
1256
+ * API для работы с рассуждениями
1257
+ */
1258
+ get reasoning() {
1259
+ return this._reasoning;
1260
+ }
1261
+ /**
1262
+ * API для модификации кода
1263
+ */
1264
+ get codeModification() {
1265
+ return this._codeModification;
1266
+ }
1267
+ /**
1268
+ * Опции SDK
1269
+ */
1270
+ get options() {
1271
+ return this._options;
1272
+ }
1273
+ /**
1274
+ * Получает текущую среду выполнения
1275
+ * @returns {string} Среда выполнения ('browser', 'node', 'unknown')
1276
+ */
1277
+ getEnvironment() {
1278
+ return this.environment;
1279
+ }
1280
+ /**
1281
+ * Закрывает все соединения и освобождает ресурсы
1282
+ */
1283
+ dispose() {
1284
+ if (this.wsClient) {
1285
+ this.wsClient.disconnectAll();
1286
+ this.wsClient = null;
1287
+ }
1288
+ }
1289
+ /**
1290
+ * Устанавливает глобальный обработчик ошибок SDK
1291
+ * @param {(error: Error) => void} handler Функция-обработчик ошибок
1292
+ */
1293
+ static setErrorHandler(handler) {
1294
+ CodeSolverSDK.errorHandler = handler;
1295
+ }
1296
+ /**
1297
+ * Обрабатывает ошибку через глобальный обработчик, если он установлен
1298
+ * @param {Error} error Ошибка для обработки
1299
+ */
1300
+ static handleError(error) {
1301
+ if (CodeSolverSDK.errorHandler) {
1302
+ CodeSolverSDK.errorHandler(error);
1303
+ }
1304
+ else {
1305
+ console.error('[CodeSolverSDK]', error);
1306
+ }
1307
+ }
1308
+ /**
1309
+ * Возвращает текущую версию SDK
1310
+ * @returns {string} Версия SDK
1311
+ */
1312
+ static getVersion() {
1313
+ return SDK_VERSION;
1314
+ }
1315
+ /**
1316
+ * Возвращает текущую версию SDK
1317
+ * @returns {string} Версия SDK
1318
+ */
1319
+ getVersion() {
1320
+ return SDK_VERSION;
1321
+ }
1322
+ /**
1323
+ * Устанавливает новый API ключ для SDK
1324
+ * @param {string} apiKey Новый API ключ
1325
+ */
1326
+ setApiKey(apiKey) {
1327
+ if (!apiKey) {
1328
+ throw new Error('API ключ не может быть пустым');
1329
+ }
1330
+ // Обновляем опции
1331
+ this._options.apiKey = apiKey;
1332
+ // Пересоздаем HTTP клиент с новым API ключом
1333
+ const newHttpClient = new HttpClient(this._options.baseURL, {
1334
+ headers: {
1335
+ ...this._options.headers,
1336
+ 'Authorization': `Bearer ${apiKey}`
1337
+ },
1338
+ timeout: this._options.timeout,
1339
+ httpsAgent: this.environment === 'node' ? this._options.httpsAgent : undefined
1340
+ });
1341
+ // Обновляем ссылки на клиент и API
1342
+ this.httpClient = newHttpClient;
1343
+ this._agents = new AgentsApi(newHttpClient);
1344
+ this._context = new ContextApi(newHttpClient);
1345
+ this._projects = new ProjectsApi(newHttpClient);
1346
+ this._search = new SearchApi(newHttpClient);
1347
+ this._reasoning = new ReasoningApi(newHttpClient);
1348
+ this._codeModification = new CodeModificationApi(newHttpClient);
1349
+ // Если есть WebSocket клиент, пересоздаем его
1350
+ if (this.wsClient) {
1351
+ const isConnected = this.wsClient.isConnectedToReasoning() || this.wsClient.isConnectedToIndexing();
1352
+ this.wsClient.disconnectAll();
1353
+ this.wsClient = new CodeSolverWebSocketClient(this._options.baseURL, {
1354
+ apiKey,
1355
+ headers: this._options.headers
1356
+ });
1357
+ // Если был подключен, восстанавливаем соединение
1358
+ if (isConnected) {
1359
+ this.connect().catch(() => { });
1360
+ }
1361
+ }
1362
+ }
1363
+ /**
1364
+ * Подключается к WebSocket серверу
1365
+ * @returns {Promise<boolean>} Promise с результатом подключения
1366
+ */
1367
+ async connect() {
1368
+ try {
1369
+ const wsClient = this.getWebSocketClient();
1370
+ // Подключаемся к обоим пространствам имен
1371
+ await wsClient.connectToReasoning();
1372
+ await wsClient.connectToIndexing();
1373
+ return true;
1374
+ }
1375
+ catch (error) {
1376
+ CodeSolverSDK.handleError(error);
1377
+ return false;
1378
+ }
1379
+ }
1380
+ /**
1381
+ * Отключается от WebSocket сервера
1382
+ * @returns {Promise<void>} Promise без результата
1383
+ */
1384
+ async disconnect() {
1385
+ if (this.wsClient) {
1386
+ await this.wsClient.disconnectAll();
1387
+ }
1388
+ }
1389
+ /**
1390
+ * Проверяет, подключен ли SDK к WebSocket серверу
1391
+ * @returns {boolean} Статус подключения
1392
+ */
1393
+ isConnected() {
1394
+ if (!this.wsClient)
1395
+ return false;
1396
+ return this.wsClient.isConnectedToReasoning() || this.wsClient.isConnectedToIndexing();
1397
+ }
1398
+ /**
1399
+ * Проверяет доступность API (алиас для checkHealth)
1400
+ * @returns {Promise<boolean>} Promise с результатом проверки
1401
+ */
1402
+ async isHealthy() {
1403
+ return this.checkHealth();
1404
+ }
1405
+ /**
1406
+ * Проверяет доступность всех сервисов API
1407
+ * @returns {Promise<{[key: string]: boolean}>} Статус каждого сервиса
1408
+ */
1409
+ async checkServices() {
1410
+ try {
1411
+ const results = {
1412
+ api: false,
1413
+ websocket: false,
1414
+ database: false,
1415
+ search: false
1416
+ };
1417
+ try {
1418
+ // Проверка API
1419
+ results.api = await this.checkHealth();
1420
+ // Проверка других компонентов через запрос статуса
1421
+ const response = await this.httpClient.get('/api/v1/status');
1422
+ if (response && typeof response === 'object') {
1423
+ results.database = Boolean(response.database?.connected);
1424
+ results.search = Boolean(response.search?.connected);
1425
+ // Проверка WebSocket соединения
1426
+ if (this.wsClient) {
1427
+ results.websocket = this.wsClient.isConnectedToReasoning() ||
1428
+ this.wsClient.isConnectedToIndexing();
1429
+ }
1430
+ else {
1431
+ try {
1432
+ const wsClient = this.getWebSocketClient();
1433
+ await wsClient.connectToReasoning();
1434
+ results.websocket = true;
1435
+ await wsClient.disconnect(WebSocketNamespace.REASONING);
1436
+ }
1437
+ catch (e) {
1438
+ results.websocket = false;
1439
+ }
1440
+ }
1441
+ }
1442
+ }
1443
+ catch (error) {
1444
+ // Игнорируем ошибки при проверке
1445
+ }
1446
+ return results;
1447
+ }
1448
+ catch (error) {
1449
+ return {
1450
+ api: false,
1451
+ websocket: false,
1452
+ database: false,
1453
+ search: false
1454
+ };
1455
+ }
1456
+ }
1457
+ /**
1458
+ * Закрывает соединение с сервером (алиас для dispose)
1459
+ */
1460
+ close() {
1461
+ this.dispose();
1462
+ return Promise.resolve();
1463
+ }
1464
+ }
1465
+ /** Глобальный обработчик ошибок */
1466
+ CodeSolverSDK.errorHandler = null;
1467
+
1468
+ // В браузере будем использовать нативный EventSource или полифилл
1469
+ const BrowserEventSource = typeof EventSource !== 'undefined' ? EventSource : EventSourcePolyfill;
1470
+ // Проверяем, находимся ли мы в браузере
1471
+ const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
1472
+ /**
1473
+ * Клиент для работы с Server-Sent Events (SSE)
1474
+ * Поддерживает работу как в браузере, так и в Node.js
1475
+ */
1476
+ class SseClient {
1477
+ /**
1478
+ * Создает новый SSE клиент
1479
+ * @param {string} url URL для подключения
1480
+ * @param {SseClientOptions} [options] Опции клиента
1481
+ */
1482
+ constructor(url, options = {}) {
1483
+ /** Экземпляр EventSource */
1484
+ this.eventSource = null;
1485
+ /** Счетчик попыток переподключения */
1486
+ this.retryCount = 0;
1487
+ /** Флаг, указывающий, что соединение было закрыто намеренно */
1488
+ this.intentionallyClosed = false;
1489
+ /** Таймер переподключения */
1490
+ this.reconnectTimer = null;
1491
+ /** Таймер таймаута соединения */
1492
+ this.connectionTimeoutTimer = null;
1493
+ /** Обработчики событий */
1494
+ this.eventHandlers = {};
1495
+ this.url = url;
1496
+ this.options = {
1497
+ headers: options.headers || {},
1498
+ connectionTimeout: options.connectionTimeout || 30000,
1499
+ maxRetries: options.maxRetries || 5,
1500
+ retryDelay: options.retryDelay || 1000,
1501
+ maxRetryDelay: options.maxRetryDelay || 30000
1502
+ };
1503
+ }
1504
+ /**
1505
+ * Подключается к SSE эндпоинту
1506
+ * @returns {Promise<void>}
1507
+ */
1508
+ connect() {
1509
+ // Если соединение уже установлено, возвращаем Promise.resolve
1510
+ if (this.eventSource && this.eventSource.readyState === 1) {
1511
+ return Promise.resolve();
1512
+ }
1513
+ // Сбрасываем флаг намеренного закрытия
1514
+ this.intentionallyClosed = false;
1515
+ return new Promise((resolve, reject) => {
1516
+ try {
1517
+ // Создаем новый экземпляр EventSource
1518
+ const EventSourceImpl = isBrowser ? BrowserEventSource : require('eventsource');
1519
+ this.eventSource = new EventSourceImpl(this.url, {
1520
+ headers: this.options.headers,
1521
+ withCredentials: true
1522
+ });
1523
+ // Устанавливаем таймаут соединения
1524
+ this.connectionTimeoutTimer = setTimeout(() => {
1525
+ if (this.eventSource && this.eventSource.readyState !== 1) {
1526
+ reject(new Error('Таймаут подключения SSE'));
1527
+ this.close();
1528
+ }
1529
+ }, this.options.connectionTimeout);
1530
+ // Проверяем, что this.eventSource не null
1531
+ if (!this.eventSource) {
1532
+ reject(new Error('Не удалось создать EventSource'));
1533
+ return;
1534
+ }
1535
+ // Обработчик открытия соединения
1536
+ this.eventSource.onopen = () => {
1537
+ clearTimeout(this.connectionTimeoutTimer);
1538
+ this.retryCount = 0;
1539
+ resolve();
1540
+ this.dispatchEvent('open', {});
1541
+ };
1542
+ // Обработчик сообщений
1543
+ this.eventSource.onmessage = (event) => {
1544
+ try {
1545
+ const data = JSON.parse(event.data);
1546
+ this.dispatchEvent('message', data);
1547
+ // Также вызываем специальный обработчик для конкретного типа события,
1548
+ // если такой тип указан в данных
1549
+ if (data && data.type) {
1550
+ this.dispatchEvent(data.type, data);
1551
+ }
1552
+ }
1553
+ catch (error) {
1554
+ this.dispatchEvent('error', { error, message: 'Ошибка при обработке сообщения SSE' });
1555
+ }
1556
+ };
1557
+ // Обработчик ошибок
1558
+ this.eventSource.onerror = (error) => {
1559
+ clearTimeout(this.connectionTimeoutTimer);
1560
+ if (this.intentionallyClosed) {
1561
+ return;
1562
+ }
1563
+ // Если соединение уже установлено и произошла ошибка, просто сообщаем об ошибке
1564
+ if (this.eventSource && this.eventSource.readyState === 1) {
1565
+ this.dispatchEvent('error', { error, message: 'Ошибка SSE соединения' });
1566
+ return;
1567
+ }
1568
+ // Если это первая попытка подключения, отклоняем Promise
1569
+ if (this.retryCount === 0) {
1570
+ reject(new Error('Ошибка подключения SSE'));
1571
+ }
1572
+ // Запускаем процесс переподключения
1573
+ this.reconnect();
1574
+ };
1575
+ // Настраиваем обработчики для всех добавленных событий
1576
+ for (const eventType in this.eventHandlers) {
1577
+ if (eventType !== 'message' && eventType !== 'open' && eventType !== 'error') {
1578
+ this.eventSource.addEventListener(eventType, (event) => {
1579
+ try {
1580
+ const data = JSON.parse(event.data);
1581
+ this.dispatchEvent(eventType, data);
1582
+ }
1583
+ catch (e) {
1584
+ this.dispatchEvent(eventType, event.data);
1585
+ }
1586
+ });
1587
+ }
1588
+ }
1589
+ }
1590
+ catch (error) {
1591
+ reject(error);
1592
+ }
1593
+ });
1594
+ }
1595
+ /**
1596
+ * Закрывает SSE соединение
1597
+ */
1598
+ close() {
1599
+ this.intentionallyClosed = true;
1600
+ // Очищаем таймеры
1601
+ clearTimeout(this.reconnectTimer);
1602
+ clearTimeout(this.connectionTimeoutTimer);
1603
+ // Закрываем соединение
1604
+ if (this.eventSource) {
1605
+ this.eventSource.close();
1606
+ this.eventSource = null;
1607
+ }
1608
+ this.dispatchEvent('close', {});
1609
+ }
1610
+ /**
1611
+ * Добавляет обработчик события
1612
+ * @param {string} eventType Тип события
1613
+ * @param {SseEventHandler} handler Обработчик события
1614
+ */
1615
+ on(eventType, handler) {
1616
+ if (!this.eventHandlers[eventType]) {
1617
+ this.eventHandlers[eventType] = [];
1618
+ // Если соединение уже установлено, добавляем обработчик события
1619
+ if (this.eventSource && this.eventSource.readyState === 1 &&
1620
+ eventType !== 'message' && eventType !== 'open' && eventType !== 'error') {
1621
+ this.eventSource.addEventListener(eventType, (event) => {
1622
+ try {
1623
+ const data = JSON.parse(event.data);
1624
+ this.dispatchEvent(eventType, data);
1625
+ }
1626
+ catch (e) {
1627
+ this.dispatchEvent(eventType, event.data);
1628
+ }
1629
+ });
1630
+ }
1631
+ }
1632
+ this.eventHandlers[eventType].push(handler);
1633
+ }
1634
+ /**
1635
+ * Удаляет обработчик события
1636
+ * @param {string} eventType Тип события
1637
+ * @param {SseEventHandler} [handler] Обработчик события (если не указан, удаляются все обработчики)
1638
+ */
1639
+ off(eventType, handler) {
1640
+ if (!this.eventHandlers[eventType]) {
1641
+ return;
1642
+ }
1643
+ if (!handler) {
1644
+ // Если обработчик не указан, удаляем все обработчики для данного события
1645
+ delete this.eventHandlers[eventType];
1646
+ }
1647
+ else {
1648
+ // Если обработчик указан, удаляем только его
1649
+ this.eventHandlers[eventType] = this.eventHandlers[eventType].filter(h => h !== handler);
1650
+ // Если обработчиков больше нет, удаляем массив
1651
+ if (this.eventHandlers[eventType].length === 0) {
1652
+ delete this.eventHandlers[eventType];
1653
+ }
1654
+ }
1655
+ }
1656
+ /**
1657
+ * Вызывает обработчики для указанного события
1658
+ * @param {string} eventType Тип события
1659
+ * @param {any} data Данные события
1660
+ */
1661
+ dispatchEvent(eventType, data) {
1662
+ if (!this.eventHandlers[eventType]) {
1663
+ return;
1664
+ }
1665
+ for (const handler of this.eventHandlers[eventType]) {
1666
+ try {
1667
+ handler(data);
1668
+ }
1669
+ catch (e) {
1670
+ console.error(`Ошибка в обработчике события ${eventType}:`, e);
1671
+ }
1672
+ }
1673
+ }
1674
+ /**
1675
+ * Переподключается к SSE эндпоинту с экспоненциальной задержкой
1676
+ * @private
1677
+ */
1678
+ reconnect() {
1679
+ // Увеличиваем счетчик попыток
1680
+ this.retryCount++;
1681
+ // Если превышено максимальное количество попыток, прекращаем
1682
+ if (this.retryCount > (this.options.maxRetries || 5)) {
1683
+ this.dispatchEvent('maxRetries', { retries: this.retryCount });
1684
+ return;
1685
+ }
1686
+ // Вычисляем задержку перед переподключением с экспоненциальным ростом
1687
+ const delay = Math.min((this.options.retryDelay || 1000) * Math.pow(2, this.retryCount - 1), this.options.maxRetryDelay || 30000);
1688
+ // Пытаемся переподключиться после задержки
1689
+ this.reconnectTimer = setTimeout(() => {
1690
+ this.dispatchEvent('reconnect', { attempt: this.retryCount });
1691
+ this.connect().catch(() => { });
1692
+ }, delay);
1693
+ }
1694
+ }
1695
+
1696
+ /**
1697
+ * События индексации
1698
+ */
1699
+ var IndexingEvent;
1700
+ (function (IndexingEvent) {
1701
+ /** Начало индексации */
1702
+ IndexingEvent["START"] = "indexing_start";
1703
+ /** Прогресс индексации */
1704
+ IndexingEvent["PROGRESS"] = "indexing_progress";
1705
+ /** Завершение индексации */
1706
+ IndexingEvent["COMPLETE"] = "indexing_complete";
1707
+ /** Ошибка индексации */
1708
+ IndexingEvent["ERROR"] = "indexing_error";
1709
+ })(IndexingEvent || (IndexingEvent = {}));
1710
+ /**
1711
+ * WebSocket клиент для работы с индексацией
1712
+ */
1713
+ class IndexingWebSocketClient extends WebSocketClient {
1714
+ /**
1715
+ * Создает новый WebSocket клиент для индексации
1716
+ * @param {string} url URL для подключения
1717
+ * @param {IndexingWebSocketOptions} [options] Опции клиента
1718
+ */
1719
+ constructor(url, options = {}) {
1720
+ // Сохраняем базовый URL
1721
+ const baseUrl = url;
1722
+ // Формируем URL с параметрами для проекта если он указан
1723
+ let targetUrl = url;
1724
+ if (options.projectId) {
1725
+ const urlWithParams = new URL(url);
1726
+ urlWithParams.searchParams.append('projectId', options.projectId);
1727
+ urlWithParams.searchParams.append('type', 'indexing');
1728
+ targetUrl = urlWithParams.toString();
1729
+ }
1730
+ super(targetUrl, {
1731
+ ...options,
1732
+ headers: {
1733
+ ...(options.headers || {}),
1734
+ ...(options.apiKey ? { 'Authorization': `Bearer ${options.apiKey}` } : {})
1735
+ }
1736
+ });
1737
+ /** Идентификатор проекта */
1738
+ this.projectId = null;
1739
+ this.baseUrl = baseUrl;
1740
+ this.projectId = options.projectId || null;
1741
+ }
1742
+ /**
1743
+ * Устанавливает идентификатор проекта
1744
+ * @param {string} projectId Идентификатор проекта
1745
+ */
1746
+ setProjectId(projectId) {
1747
+ this.projectId = projectId;
1748
+ }
1749
+ /**
1750
+ * Подключается к WebSocket для отслеживания индексации
1751
+ * @param {string} [projectId] Идентификатор проекта (если не был указан в конструкторе)
1752
+ * @returns {Promise<void>}
1753
+ */
1754
+ async connect(projectId) {
1755
+ const targetProjectId = projectId || this.projectId;
1756
+ if (!targetProjectId) {
1757
+ throw new Error('Project ID is required for indexing WebSocket connection');
1758
+ }
1759
+ // Сохраняем ID проекта
1760
+ this.projectId = targetProjectId;
1761
+ // Если проект изменился и клиент уже подключен, отключаемся
1762
+ if (projectId && this.isConnected()) {
1763
+ this.close();
1764
+ }
1765
+ // Выполняем соединение
1766
+ await super.connect();
1767
+ }
1768
+ /**
1769
+ * Подписывается на события начала индексации
1770
+ * @param {(data: {projectId: string}) => void} handler Обработчик события
1771
+ */
1772
+ onStart(handler) {
1773
+ this.on(IndexingEvent.START, handler);
1774
+ }
1775
+ /**
1776
+ * Подписывается на события прогресса индексации
1777
+ * @param {(data: IndexingProgressData) => void} handler Обработчик события
1778
+ */
1779
+ onProgress(handler) {
1780
+ this.on(IndexingEvent.PROGRESS, handler);
1781
+ }
1782
+ /**
1783
+ * Подписывается на события завершения индексации
1784
+ * @param {(data: IndexingCompleteData) => void} handler Обработчик события
1785
+ */
1786
+ onComplete(handler) {
1787
+ this.on(IndexingEvent.COMPLETE, handler);
1788
+ }
1789
+ /**
1790
+ * Подписывается на события ошибок индексации
1791
+ * @param {(data: IndexingErrorData) => void} handler Обработчик события
1792
+ */
1793
+ onError(handler) {
1794
+ this.on(IndexingEvent.ERROR, handler);
1795
+ }
1796
+ }
1797
+
1798
+ /**
1799
+ * Общие типы данных для SDK
1800
+ */
1801
+ /**
1802
+ * Уровень логирования
1803
+ */
1804
+ var LogLevel;
1805
+ (function (LogLevel) {
1806
+ LogLevel["DEBUG"] = "debug";
1807
+ LogLevel["INFO"] = "info";
1808
+ LogLevel["WARN"] = "warn";
1809
+ LogLevel["ERROR"] = "error";
1810
+ })(LogLevel || (LogLevel = {}));
1811
+
1812
+ // Экспорт основного класса SDK
1813
+ // Версия SDK
1814
+ const VERSION = '1.0.0';
1815
+ // Простой пример использования SDK
1816
+ /**
1817
+ * Пример использования SDK:
1818
+ *
1819
+ * ```typescript
1820
+ * // ESM импорт (браузер, современный Node.js)
1821
+ * import { CodeSolverSDK } from 'code-solver-sdk';
1822
+ *
1823
+ * // CommonJS импорт (Node.js)
1824
+ * // const { CodeSolverSDK } = require('code-solver-sdk');
1825
+ *
1826
+ * const sdk = new CodeSolverSDK({
1827
+ * baseURL: 'https://api.example.com',
1828
+ * apiKey: 'your-api-key' // если требуется
1829
+ * });
1830
+ *
1831
+ * // Пример работы с проектами
1832
+ * async function example() {
1833
+ * // Проверка доступности API
1834
+ * const isHealthy = await sdk.checkHealth();
1835
+ * console.log('API доступен:', isHealthy);
1836
+ *
1837
+ * // Получение списка проектов
1838
+ * const projects = await sdk.projects.getAllProjects();
1839
+ * console.log('Проекты:', projects);
1840
+ *
1841
+ * // Создание нового проекта
1842
+ * const newProject = await sdk.projects.createProject('Мой проект', '/path/to/project');
1843
+ * console.log('Новый проект:', newProject);
1844
+ *
1845
+ * // Запуск индексации
1846
+ * await sdk.projects.indexProject(newProject.id);
1847
+ *
1848
+ * // Поиск кода
1849
+ * const searchResults = await sdk.search.searchCode(newProject.id, {
1850
+ * query: 'function example',
1851
+ * limit: 10
1852
+ * });
1853
+ * console.log('Результаты поиска:', searchResults);
1854
+ *
1855
+ * // Работа с рассуждениями
1856
+ * const reasoning = await sdk.reasoning.createReasoning({
1857
+ * projectId: newProject.id,
1858
+ * query: 'Объясни, как работает этот проект'
1859
+ * });
1860
+ *
1861
+ * // Запуск процесса рассуждения
1862
+ * await sdk.reasoning.startReasoning(reasoning.id);
1863
+ *
1864
+ * // Подключение через WebSocket
1865
+ * const wsClient = sdk.getWebSocketClient();
1866
+ * await wsClient.connectToReasoning();
1867
+ *
1868
+ * // Обработка событий
1869
+ * wsClient.on('thinking', (data) => {
1870
+ * console.log('Размышление:', data.content);
1871
+ * });
1872
+ *
1873
+ * wsClient.on('complete', (data) => {
1874
+ * console.log('Завершено:', data.content);
1875
+ * wsClient.disconnectAll();
1876
+ * });
1877
+ * }
1878
+ * ```
1879
+ */
1880
+
1881
+ export { AgentsApi, CodeModificationApi, CodeSolverSDK, CodeSolverWebSocketClient, ContextApi, HttpClient, IndexingWebSocketClient, LogLevel, ProjectsApi, ReasoningApi, SearchApi, SseClient, VERSION, WebSocketClient, WebSocketNamespace, CodeSolverSDK as default };
1882
+ //# sourceMappingURL=index.js.map