@recursorsdk/sdk 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,458 +1,18 @@
1
+ // Export all types
2
+ export * from "./types.js";
1
3
  export { RecursorWebSocket } from "./websocket.js";
2
- export class RecursorSDK {
3
- constructor(options) {
4
- const envBase = process.env.RECURSOR_API_URL ?? "http://localhost:8000/api/v1";
5
- this.baseUrl = (options?.baseUrl ?? envBase).replace(/\/$/, "");
6
- this.apiKey = options?.apiKey ?? process.env.RECURSOR_API_KEY;
7
- this.accessToken = options?.accessToken ?? process.env.RECURSOR_ACCESS_TOKEN;
8
- this.timeoutMs = options?.timeoutMs ?? 10000;
9
- }
10
- setAccessToken(token) {
11
- this.accessToken = token;
12
- }
13
- setApiKey(key) {
14
- this.apiKey = key;
15
- }
16
- headers() {
17
- const h = { "Content-Type": "application/json" };
18
- if (this.accessToken) {
19
- h["Authorization"] = `Bearer ${this.accessToken}`;
20
- }
21
- else if (this.apiKey) {
22
- h["X-API-Key"] = this.apiKey;
23
- }
24
- return h;
25
- }
26
- async get(path, params) {
27
- const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : "/" + path}`);
28
- if (params)
29
- Object.entries(params).forEach(([k, v]) => {
30
- if (v !== undefined && v !== null)
31
- url.searchParams.set(k, String(v));
32
- });
33
- const ctrl = new AbortController();
34
- const t = setTimeout(() => ctrl.abort(), this.timeoutMs);
35
- try {
36
- const res = await fetch(url, { headers: this.headers(), signal: ctrl.signal });
37
- if (!res.ok)
38
- throw new Error(`HTTP ${res.status}`);
39
- return (await res.json());
40
- }
41
- finally {
42
- clearTimeout(t);
43
- }
44
- }
45
- async post(path, body, method = "POST") {
46
- const url = `${this.baseUrl}${path.startsWith("/") ? path : "/" + path}`;
47
- const ctrl = new AbortController();
48
- const t = setTimeout(() => ctrl.abort(), this.timeoutMs);
49
- try {
50
- const res = await fetch(url, {
51
- method,
52
- headers: this.headers(),
53
- body: body ? JSON.stringify(body) : undefined,
54
- signal: ctrl.signal,
55
- });
56
- if (!res.ok) {
57
- const errorText = await res.text();
58
- throw new Error(`HTTP ${res.status}: ${errorText}`);
59
- }
60
- // Handle 204 No Content
61
- if (res.status === 204)
62
- return undefined;
63
- return (await res.json());
64
- }
65
- finally {
66
- clearTimeout(t);
67
- }
68
- }
69
- async put(path, body) {
70
- return this.post(path, body, "PUT");
71
- }
72
- async patch(path, body) {
73
- return this.post(path, body, "PATCH");
74
- }
75
- async delete(path) {
76
- return this.post(path, undefined, "DELETE");
77
- }
78
- async checkHealth() {
79
- try {
80
- const res = await fetch(`${this.baseUrl.replace('/api/v1', '')}/v1/status/health`);
81
- return res.ok;
82
- }
83
- catch {
84
- return false;
85
- }
86
- }
87
- /**
88
- * Close the SDK client and cleanup resources
89
- * Disconnects WebSocket if connected
90
- */
91
- close() {
92
- this.disconnectWebSocket();
93
- // In Node.js, fetch doesn't need explicit closing like Python's httpx.Client
94
- // But we clean up WebSocket connections
95
- }
96
- async detectIntent(args) {
97
- const payload = {
98
- user_request: (args.user_request ?? "").trim().slice(0, 4000),
99
- current_file: args.current_file ?? null,
100
- user_id: args.user_id ?? null,
101
- project_id: args.project_id ?? null,
102
- tags: args.tags ?? [],
103
- similar_limit: args.similar_limit ?? 5,
104
- };
105
- return await this.post("/client/code_intelligence/detect-intent", payload);
106
- }
107
- // LLM Gateway
108
- async getLLMGatewayPolicy() {
109
- return await this.get("/recursor/llm/gateway/policy");
110
- }
111
- async gatewayChat(args) {
112
- const body = {
113
- provider: args.provider ?? "openai",
114
- model: args.model ?? undefined,
115
- messages: (args.messages ?? []).map(m => ({ role: m.role, content: String(m.content).slice(0, 4000) })),
116
- call_provider: !!(args.call_provider ?? false),
117
- user_id: args.user_id ?? undefined,
118
- };
119
- return await this.post("/recursor/llm/gateway/chat", body);
120
- }
121
- // Robotics Gateway
122
- async getRoboticsGatewayPolicy() {
123
- return await this.get("/recursor/robotics/gateway/policy");
124
- }
125
- async roboticsGatewayObserve(args) {
126
- const body = {
127
- state: args.state,
128
- command: args.command ?? undefined,
129
- environment: args.environment ?? [],
130
- user_id: args.user_id ?? undefined,
131
- };
132
- return await this.post("/recursor/robotics/gateway/observe", body);
133
- }
134
- // AV Gateway
135
- async getAvGatewayPolicy() {
136
- return await this.get("/recursor/av/gateway/policy");
137
- }
138
- async avGatewayObserve(args) {
139
- const body = {
140
- sensors: args.sensors,
141
- state: args.state,
142
- action: args.action,
143
- timestamp: args.timestamp,
144
- vehicle_id: args.vehicle_id,
145
- user_id: args.user_id ?? undefined,
146
- };
147
- return await this.post("/recursor/av/gateway/observe", body);
148
- }
149
- async getIntentHistory(limit = 50, project_id) {
150
- const params = { limit: Math.max(1, Math.min(limit, 200)) };
151
- if (project_id)
152
- params.project_id = project_id;
153
- return await this.get("/client/code_intelligence/intent-history", params);
154
- }
155
- async createCorrection(args) {
156
- const body = {
157
- input_text: (args.input_text ?? "").slice(0, 4000),
158
- output_text: (args.output_text ?? "").slice(0, 4000),
159
- expected_output: (args.expected_output ?? args.output_text ?? "").slice(0, 4000),
160
- context: args.context ?? {},
161
- correction_type: args.correction_type ?? null,
162
- };
163
- return await this.post("/client/corrections/", body);
164
- }
165
- async listCorrections(args) {
166
- const params = {
167
- page: Math.max(1, args?.page ?? 1),
168
- page_size: Math.max(1, Math.min(args?.page_size ?? 50, 100)),
169
- include_inactive: !!(args?.include_inactive ?? false),
170
- };
171
- return await this.get("/client/corrections/", params);
172
- }
173
- async searchCorrections(query, limit = 10) {
174
- const params = {
175
- query: (query ?? "").trim().slice(0, 4000),
176
- limit: Math.max(1, Math.min(limit, 50)),
177
- };
178
- return await this.get("/client/corrections/search", params);
179
- }
180
- async getAnalyticsDashboard(user_id, period = "30d", project_id) {
181
- const params = { user_id, period };
182
- if (project_id)
183
- params.project_id = project_id;
184
- return await this.get("/client/code_intelligence/analytics/dashboard", params);
185
- }
186
- async getTimeSaved(user_id, period = "30d", project_id) {
187
- const params = { user_id, period };
188
- if (project_id)
189
- params.project_id = project_id;
190
- return await this.get("/client/code_intelligence/analytics/time-saved", params);
191
- }
192
- async getQualityMetrics(user_id, period = "30d", project_id) {
193
- const params = { user_id, period };
194
- if (project_id)
195
- params.project_id = project_id;
196
- return await this.get("/client/code_intelligence/analytics/quality", params);
197
- }
198
- async getAIAgentMetrics(user_id, project_id) {
199
- const params = { user_id };
200
- if (project_id)
201
- params.project_id = project_id;
202
- return await this.get("/client/code_intelligence/analytics/ai-agent", params);
203
- }
204
- async correctCode(code, language, project_profile) {
205
- const body = { code, language, project_profile: project_profile ?? {} };
206
- return await this.post("/client/code_intelligence/correct/code", body);
207
- }
208
- async correctConfig(config, config_type) {
209
- const body = { config, config_type };
210
- return await this.post("/client/code_intelligence/correct/config", body);
211
- }
212
- async correctDocumentation(markdown, doc_type = "README") {
213
- const body = { markdown, doc_type };
214
- return await this.post("/client/code_intelligence/correct/documentation", body);
215
- }
216
- async applyAutoCorrections(user_id, model_name, corrections) {
217
- const body = { user_id, model_name, corrections };
218
- return await this.post("/client/code_intelligence/auto-correct", body);
219
- }
220
- async getTrustScore(user_id, model_name) {
221
- const data = await this.get("/client/code_intelligence/trust-score", { user_id, model_name });
222
- const v = data.trust_score;
223
- return typeof v === "number" ? v : Number(v ?? 0);
224
- }
225
- async submitFeedback(prediction_id, accepted) {
226
- await this.post("/client/code_intelligence/feedback", { prediction_id, accepted: !!accepted });
227
- }
228
- async getAutoCorrectStats(user_id) {
229
- return await this.get("/client/code_intelligence/stats", { user_id });
230
- }
231
- async getPatterns(user_id) {
232
- const params = user_id ? { user_id } : undefined;
233
- const data = await this.get("/client/code_intelligence/patterns", params);
234
- return Array.isArray(data) ? data : [];
235
- }
236
- // ==================== Authentication & User Management ====================
237
- async register(userData) {
238
- return await this.post("/client/auth/register", userData);
239
- }
240
- async login(credentials) {
241
- const response = await this.post("/client/auth/login", credentials);
242
- // Automatically set access token for future requests
243
- if (response.access_token) {
244
- this.setAccessToken(response.access_token);
245
- // Update WebSocket token if connected
246
- if (this.wsClient) {
247
- this.wsClient.updateToken(response.access_token);
248
- }
249
- }
250
- return response;
251
- }
252
- async logout() {
253
- await this.post("/client/auth/logout", {});
254
- }
255
- async refreshToken(refreshToken) {
256
- return await this.post("/client/auth/refresh", { refresh_token: refreshToken });
257
- }
258
- async getProfile() {
259
- return await this.get("/client/auth/me");
260
- }
261
- async updateProfile(updates) {
262
- return await this.put("/client/auth/me", updates);
263
- }
264
- async changePassword(passwordChange) {
265
- await this.post("/client/auth/change-password", passwordChange);
266
- }
267
- async generateApiKey() {
268
- return await this.post("/client/auth/api-key", {});
269
- }
270
- async revokeApiKey() {
271
- await this.delete("/client/auth/api-key");
272
- }
273
- async getPasswordRequirements() {
274
- return await this.get("/client/auth/password-requirements");
275
- }
276
- // ==================== Project Management ====================
277
- async createProject(projectData) {
278
- return await this.post("/client/projects/", projectData);
279
- }
280
- async getProject(projectId) {
281
- return await this.get(`/client/projects/${projectId}`);
282
- }
283
- async listProjects() {
284
- return await this.get("/client/projects/");
285
- }
286
- async updateProject(projectId, updates) {
287
- return await this.patch(`/client/projects/${projectId}`, updates);
288
- }
289
- async deleteProject(projectId) {
290
- await this.delete(`/client/projects/${projectId}`);
291
- }
292
- async regenerateProjectApiKey(projectId) {
293
- return await this.post(`/client/projects/${projectId}/api-key`, {});
294
- }
295
- async getMcpConfig(projectId) {
296
- return await this.get(`/client/projects/${projectId}/mcp-config`);
297
- }
298
- async getMcpStats(projectId) {
299
- return await this.get(`/client/projects/${projectId}/mcp-stats`);
300
- }
301
- // ==================== Billing & Usage ====================
302
- async getUsage() {
303
- return await this.get("/client/billing/usage");
304
- }
305
- async getUsageHistory(days = 30, resourceType) {
306
- const params = { days };
307
- if (resourceType)
308
- params.resource_type = resourceType;
309
- return await this.get("/client/billing/usage/history", params);
310
- }
311
- async listBillingPlans() {
312
- const data = await this.get("/client/billing/plans");
313
- return Array.isArray(data.plans) ? data.plans : [];
314
- }
315
- async getSubscription() {
316
- return await this.get("/client/billing/subscription");
317
- }
318
- // ==================== Notifications ====================
319
- async listNotifications() {
320
- const data = await this.get("/client/notifications");
321
- return Array.isArray(data.notifications) ? data.notifications : [];
322
- }
323
- async markNotificationAsRead(notificationId) {
324
- return await this.post(`/client/notifications/${notificationId}/read`, {});
325
- }
326
- async markAllNotificationsAsRead() {
327
- await this.post("/client/notifications/read-all", {});
328
- }
329
- async deleteNotification(notificationId) {
330
- await this.delete(`/client/notifications/${notificationId}`);
331
- }
332
- // ==================== Settings ====================
333
- async getSettings() {
334
- return await this.get("/client/settings");
335
- }
336
- async updateAccount(updates) {
337
- return await this.put("/client/settings/account", updates);
338
- }
339
- async updatePreferences(preferences) {
340
- return await this.put("/client/settings/preferences", preferences);
341
- }
342
- async getGuidelines() {
343
- return await this.get("/client/settings/guidelines");
344
- }
345
- async changePasswordViaSettings(passwordChange) {
346
- await this.post("/client/settings/password", passwordChange);
347
- }
348
- async deleteAccount(confirm) {
349
- await this.delete("/client/settings/account");
350
- }
351
- // ==================== Activity Logs ====================
352
- async listActivityLogs(page = 1, pageSize = 50) {
353
- return await this.get("/client/activity", { page, page_size: pageSize });
354
- }
355
- async exportActivityLogs() {
356
- const url = `${this.baseUrl}/client/activity/export`;
357
- const res = await fetch(url, { headers: this.headers() });
358
- if (!res.ok)
359
- throw new Error(`HTTP ${res.status}`);
360
- return await res.blob();
361
- }
362
- // ==================== Corrections (Additional Methods) ====================
363
- async getCorrection(correctionId) {
364
- return await this.get(`/client/corrections/${correctionId}`);
365
- }
366
- async updateCorrection(correctionId, updates) {
367
- return await this.put(`/client/corrections/${correctionId}`, updates);
368
- }
369
- async getCorrectionStats() {
370
- return await this.get("/client/corrections/stats");
371
- }
372
- // ==================== WebSocket Support ====================
373
- /**
374
- * Create WebSocket connection for real-time updates
375
- * Requires access token (use login() first or setAccessToken())
376
- */
377
- async createWebSocket() {
378
- if (!this.accessToken) {
379
- throw new Error("Access token required for WebSocket connection. Use login() first or setAccessToken()");
380
- }
381
- if (!this.wsClient) {
382
- // Dynamic import for WebSocket
383
- const { RecursorWebSocket } = await import("./websocket.js");
384
- this.wsClient = new RecursorWebSocket(this.baseUrl, this.accessToken);
385
- }
386
- return this.wsClient;
387
- }
388
- /**
389
- * Connect WebSocket and return client
390
- */
391
- async connectWebSocket() {
392
- const ws = await this.createWebSocket();
393
- await ws.connect();
394
- return ws;
395
- }
396
- /**
397
- * Disconnect WebSocket if connected
398
- */
399
- disconnectWebSocket() {
400
- if (this.wsClient) {
401
- this.wsClient.disconnect();
402
- this.wsClient = undefined;
403
- }
404
- }
405
- // ==================== Memory Operations ====================
406
- /**
407
- * Create a conversation summary
408
- */
409
- async createConversationSummary(data) {
410
- return this.post("/client/memory/conversations/summaries", data);
411
- }
412
- /**
413
- * Get a conversation summary by ID
414
- */
415
- async getConversationSummary(conversationId) {
416
- return this.get(`/client/memory/conversations/summaries/${conversationId}`);
417
- }
418
- /**
419
- * List recent conversation summaries
420
- */
421
- async listConversationSummaries(params) {
422
- return this.get("/client/memory/conversations/summaries", params);
423
- }
424
- /**
425
- * Record an architectural change
426
- */
427
- async recordArchitecturalChange(data) {
428
- return this.post("/client/memory/architectural/changes", data);
429
- }
430
- /**
431
- * List recent architectural changes
432
- */
433
- async listArchitecturalChanges(params) {
434
- return this.get("/client/memory/architectural/changes", params);
435
- }
436
- // ==================== Rotatable Memory Operations ====================
437
- /**
438
- * Query rotatable memory patterns
439
- */
440
- async queryRotatableMemory(params) {
441
- return this.post("/client/memory/rotatable/query", params || {});
442
- }
443
- /**
444
- * Record pattern usage and update effectiveness
445
- */
446
- async recordPatternUsage(patternId, successful) {
447
- return this.post("/client/memory/rotatable/usage", {
448
- pattern_id: patternId,
449
- successful,
450
- });
451
- }
452
- /**
453
- * Get rotatable memory statistics
454
- */
455
- async getRotatableMemoryStats() {
456
- return this.get("/client/memory/rotatable/stats");
457
- }
4
+ import { RecursorBase } from "./base.js";
5
+ import { CodebaseMixin } from "./mixins/codebase.js";
6
+ import { WorkflowMixin } from "./mixins/workflows.js";
7
+ import { IntelligenceMixin } from "./mixins/intelligence.js";
8
+ import { EnterpriseMixin } from "./mixins/enterprise.js";
9
+ import { WebSocketMixin } from "./mixins/websocket.js";
10
+ /**
11
+ * RecursorSDK
12
+ *
13
+ * The main client for the Recursor API.
14
+ * Composed of multiple mixins to provide a modular yet flat API.
15
+ */
16
+ export class RecursorSDK extends WebSocketMixin(EnterpriseMixin(IntelligenceMixin(WorkflowMixin(CodebaseMixin(RecursorBase))))) {
458
17
  }
18
+ export default RecursorSDK;
@@ -0,0 +1,34 @@
1
+ import { RecursorBase, Constructor } from "../base.js";
2
+ import { CodebaseIndexResponse } from "../types.js";
3
+ export declare function CodebaseMixin<TBase extends Constructor<RecursorBase>>(Base: TBase): {
4
+ new (...args: any[]): {
5
+ listCodebaseFiles(limit?: number, offset?: number): Promise<any[]>;
6
+ getCodebaseIndex(): Promise<CodebaseIndexResponse>;
7
+ getDirectoryStructure(max_depth?: number, include_files?: boolean): Promise<any>;
8
+ validateCodebaseOperation(action: string, path: string): Promise<any>;
9
+ findSimilarFiles(name: string, threshold?: number): Promise<string[]>;
10
+ syncFile(filePath: string, content?: string): Promise<Record<string, unknown>>;
11
+ syncBatch(files: Array<{
12
+ path: string;
13
+ content?: string;
14
+ }>): Promise<any>;
15
+ syncDelete(filePath: string): Promise<any>;
16
+ syncHybridIndex(user_id: string, index: Record<string, any>): Promise<any>;
17
+ baseUrl: string;
18
+ apiKey?: string;
19
+ accessToken?: string;
20
+ timeoutMs: number;
21
+ wsClient?: any;
22
+ localIndex: Record<string, any>;
23
+ offlineQueue: any[];
24
+ setAccessToken(token: string): void;
25
+ setApiKey(key: string): void;
26
+ headers(): import("../types.js").HeadersInit;
27
+ get<T>(path: string, params?: Record<string, unknown>): Promise<T>;
28
+ post<T>(path: string, body?: unknown, method?: string): Promise<T>;
29
+ put<T>(path: string, body?: unknown): Promise<T>;
30
+ patch<T>(path: string, body?: unknown): Promise<T>;
31
+ delete<T>(path: string): Promise<T>;
32
+ checkHealth(): Promise<boolean>;
33
+ };
34
+ } & TBase;
@@ -0,0 +1,39 @@
1
+ export function CodebaseMixin(Base) {
2
+ return class extends Base {
3
+ async listCodebaseFiles(limit = 100, offset = 0) {
4
+ return await this.get("/client/codebase/files", { limit, offset });
5
+ }
6
+ async getCodebaseIndex() {
7
+ return await this.get("/client/codebase/index");
8
+ }
9
+ async getDirectoryStructure(max_depth = 3, include_files = true) {
10
+ return await this.get("/client/codebase/structure", { max_depth, include_files });
11
+ }
12
+ async validateCodebaseOperation(action, path) {
13
+ return await this.post("/client/codebase/validate", { action, path });
14
+ }
15
+ async findSimilarFiles(name, threshold = 0.6) {
16
+ return await this.get("/client/codebase/similar", { name, threshold });
17
+ }
18
+ async syncFile(filePath, content) {
19
+ // Local Indexing logic omitted
20
+ try {
21
+ const payload = { path: filePath, content };
22
+ return await this.post("/client/codebase/sync-file", payload);
23
+ }
24
+ catch (error) {
25
+ this.offlineQueue.push({ action: "sync_file", path: filePath });
26
+ return { status: "queued", local_index: true };
27
+ }
28
+ }
29
+ async syncBatch(files) {
30
+ return await this.post("/client/codebase/sync-batch", { files });
31
+ }
32
+ async syncDelete(filePath) {
33
+ return await this.post("/client/codebase/sync-delete", { path: filePath });
34
+ }
35
+ async syncHybridIndex(user_id, index) {
36
+ return await this.post("/client/indexing/hybrid/sync", { user_id, index });
37
+ }
38
+ };
39
+ }
@@ -0,0 +1,51 @@
1
+ import { RecursorBase, Constructor } from "../base.js";
2
+ import { ProjectCreate, ProjectResponse, ProjectUpdate, UserLogin, TokenResponse, UserProfile, AuditLogResponse } from "../types.js";
3
+ export declare function EnterpriseMixin<TBase extends Constructor<RecursorBase>>(Base: TBase): {
4
+ new (...args: any[]): {
5
+ createProject(projectData: ProjectCreate): Promise<ProjectResponse>;
6
+ getProject(projectId: string): Promise<ProjectResponse>;
7
+ listProjects(): Promise<ProjectResponse[]>;
8
+ updateProject(projectId: string, updates: ProjectUpdate): Promise<ProjectResponse>;
9
+ deleteProject(projectId: string): Promise<void>;
10
+ getMcpConfig(projectId: string): Promise<Record<string, unknown>>;
11
+ login(credentials: UserLogin): Promise<TokenResponse>;
12
+ getProfile(): Promise<UserProfile>;
13
+ register(data: Record<string, any>): Promise<any>;
14
+ refreshToken(refreshToken: string): Promise<TokenResponse>;
15
+ listActivityLogs(params?: {
16
+ limit?: number;
17
+ offset?: number;
18
+ resource_type?: string;
19
+ action?: string;
20
+ start_date?: string;
21
+ end_date?: string;
22
+ }): Promise<any>;
23
+ getUserAuditLogs(limit?: number, offset?: number, action?: string): Promise<AuditLogResponse>;
24
+ exportActivityLogs(format?: string, start_date?: string, end_date?: string): Promise<Blob>;
25
+ getSettings(): Promise<any>;
26
+ updateAccount(data: {
27
+ full_name?: string;
28
+ email?: string;
29
+ }): Promise<any>;
30
+ listNotifications(): Promise<any[]>;
31
+ markNotificationAsRead(notificationId: string): Promise<void>;
32
+ getUsage(): Promise<any>;
33
+ listBillingPlans(): Promise<any[]>;
34
+ baseUrl: string;
35
+ apiKey?: string;
36
+ accessToken?: string;
37
+ timeoutMs: number;
38
+ wsClient?: any;
39
+ localIndex: Record<string, any>;
40
+ offlineQueue: any[];
41
+ setAccessToken(token: string): void;
42
+ setApiKey(key: string): void;
43
+ headers(): import("../types.js").HeadersInit;
44
+ get<T>(path: string, params?: Record<string, unknown>): Promise<T>;
45
+ post<T>(path: string, body?: unknown, method?: string): Promise<T>;
46
+ put<T>(path: string, body?: unknown): Promise<T>;
47
+ patch<T>(path: string, body?: unknown): Promise<T>;
48
+ delete<T>(path: string): Promise<T>;
49
+ checkHealth(): Promise<boolean>;
50
+ };
51
+ } & TBase;
@@ -0,0 +1,85 @@
1
+ export function EnterpriseMixin(Base) {
2
+ return class extends Base {
3
+ // ==================== Projects ====================
4
+ async createProject(projectData) {
5
+ return await this.post("/client/projects", projectData);
6
+ }
7
+ async getProject(projectId) {
8
+ return await this.get(`/client/projects/${projectId}`);
9
+ }
10
+ async listProjects() {
11
+ return await this.get("/client/projects");
12
+ }
13
+ async updateProject(projectId, updates) {
14
+ return await this.patch(`/client/projects/${projectId}`, updates);
15
+ }
16
+ async deleteProject(projectId) {
17
+ await this.delete(`/client/projects/${projectId}`);
18
+ }
19
+ async getMcpConfig(projectId) {
20
+ return await this.get(`/client/projects/${projectId}/mcp-config`);
21
+ }
22
+ // ==================== Auth & Users ====================
23
+ async login(credentials) {
24
+ const response = await this.post("/client/auth/login", credentials);
25
+ if (response.access_token) {
26
+ this.setAccessToken(response.access_token);
27
+ }
28
+ return response;
29
+ }
30
+ async getProfile() {
31
+ return await this.get("/client/auth/me");
32
+ }
33
+ async register(data) {
34
+ return await this.post("/client/auth/register", data);
35
+ }
36
+ async refreshToken(refreshToken) {
37
+ return await this.post("/client/auth/refresh", { refresh_token: refreshToken });
38
+ }
39
+ // ==================== Activity Logs ====================
40
+ async listActivityLogs(params) {
41
+ return await this.get("/client/activity", params);
42
+ }
43
+ async getUserAuditLogs(limit = 50, offset = 0, action) {
44
+ const params = { limit, offset };
45
+ if (action)
46
+ params.action = action;
47
+ return await this.get("/client/audit/audit-logs", params);
48
+ }
49
+ async exportActivityLogs(format = "csv", start_date, end_date) {
50
+ // @ts-ignore - access to protected baseUrl
51
+ const url = new URL(`${this.baseUrl}/client/activity/export`);
52
+ url.searchParams.set("format", format);
53
+ if (start_date)
54
+ url.searchParams.set("start_date", start_date);
55
+ if (end_date)
56
+ url.searchParams.set("end_date", end_date);
57
+ // @ts-ignore - access to protected headers
58
+ const res = await fetch(url.toString(), { headers: this.headers() });
59
+ if (!res.ok)
60
+ throw new Error(`HTTP ${res.status}`);
61
+ return await res.blob();
62
+ }
63
+ // ==================== Settings ====================
64
+ async getSettings() {
65
+ return await this.get("/client/settings");
66
+ }
67
+ async updateAccount(data) {
68
+ return await this.patch("/client/settings/account", data);
69
+ }
70
+ // ==================== Notifications ====================
71
+ async listNotifications() {
72
+ return await this.get("/client/notifications");
73
+ }
74
+ async markNotificationAsRead(notificationId) {
75
+ await this.post(`/client/notifications/${notificationId}/read`, {});
76
+ }
77
+ // ==================== Billing ====================
78
+ async getUsage() {
79
+ return await this.get("/client/billing/usage");
80
+ }
81
+ async listBillingPlans() {
82
+ return await this.get("/client/billing/plans");
83
+ }
84
+ };
85
+ }