@recursorsdk/sdk 1.0.0
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/LICENSE +19 -0
- package/README.md +412 -0
- package/dist/index.d.ts +386 -0
- package/dist/index.js +480 -0
- package/dist/plugins/vscodeStub.d.ts +2 -0
- package/dist/plugins/vscodeStub.js +24 -0
- package/dist/plugins/windsurfStub.d.ts +1 -0
- package/dist/plugins/windsurfStub.js +14 -0
- package/dist/websocket.d.ts +73 -0
- package/dist/websocket.js +190 -0
- package/package.json +33 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
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
|
+
async detectIntent(args) {
|
|
88
|
+
const payload = {
|
|
89
|
+
user_request: (args.user_request ?? "").trim().slice(0, 4000),
|
|
90
|
+
current_file: args.current_file ?? null,
|
|
91
|
+
user_id: args.user_id ?? null,
|
|
92
|
+
project_id: args.project_id ?? null,
|
|
93
|
+
tags: args.tags ?? [],
|
|
94
|
+
similar_limit: args.similar_limit ?? 5,
|
|
95
|
+
organization_id: args.organization_id ?? null,
|
|
96
|
+
};
|
|
97
|
+
return await this.post("/client/code_intelligence/detect-intent", payload);
|
|
98
|
+
}
|
|
99
|
+
// LLM Gateway
|
|
100
|
+
async getLLMGatewayPolicy() {
|
|
101
|
+
return await this.get("/recursor/llm/gateway/policy");
|
|
102
|
+
}
|
|
103
|
+
async gatewayChat(args) {
|
|
104
|
+
const body = {
|
|
105
|
+
provider: args.provider ?? "openai",
|
|
106
|
+
model: args.model ?? undefined,
|
|
107
|
+
messages: (args.messages ?? []).map(m => ({ role: m.role, content: String(m.content).slice(0, 4000) })),
|
|
108
|
+
call_provider: !!(args.call_provider ?? false),
|
|
109
|
+
user_id: args.user_id ?? undefined,
|
|
110
|
+
organization_id: args.organization_id ?? undefined,
|
|
111
|
+
};
|
|
112
|
+
return await this.post("/recursor/llm/gateway/chat", body);
|
|
113
|
+
}
|
|
114
|
+
// Robotics Gateway
|
|
115
|
+
async getRoboticsGatewayPolicy() {
|
|
116
|
+
return await this.get("/recursor/robotics/gateway/policy");
|
|
117
|
+
}
|
|
118
|
+
async roboticsGatewayObserve(args) {
|
|
119
|
+
const body = {
|
|
120
|
+
state: args.state,
|
|
121
|
+
command: args.command ?? undefined,
|
|
122
|
+
environment: args.environment ?? [],
|
|
123
|
+
user_id: args.user_id ?? undefined,
|
|
124
|
+
organization_id: args.organization_id ?? undefined,
|
|
125
|
+
};
|
|
126
|
+
return await this.post("/recursor/robotics/gateway/observe", body);
|
|
127
|
+
}
|
|
128
|
+
// AV Gateway
|
|
129
|
+
async getAvGatewayPolicy() {
|
|
130
|
+
return await this.get("/recursor/av/gateway/policy");
|
|
131
|
+
}
|
|
132
|
+
async avGatewayObserve(args) {
|
|
133
|
+
const body = {
|
|
134
|
+
sensors: args.sensors,
|
|
135
|
+
state: args.state,
|
|
136
|
+
action: args.action,
|
|
137
|
+
timestamp: args.timestamp,
|
|
138
|
+
vehicle_id: args.vehicle_id,
|
|
139
|
+
user_id: args.user_id ?? undefined,
|
|
140
|
+
organization_id: args.organization_id ?? undefined,
|
|
141
|
+
};
|
|
142
|
+
return await this.post("/recursor/av/gateway/observe", body);
|
|
143
|
+
}
|
|
144
|
+
async getIntentHistory(limit = 50, project_id) {
|
|
145
|
+
const params = { limit: Math.max(1, Math.min(limit, 200)) };
|
|
146
|
+
if (project_id)
|
|
147
|
+
params.project_id = project_id;
|
|
148
|
+
return await this.get("/client/code_intelligence/intent-history", params);
|
|
149
|
+
}
|
|
150
|
+
async createCorrection(args) {
|
|
151
|
+
const body = {
|
|
152
|
+
input_text: (args.input_text ?? "").slice(0, 4000),
|
|
153
|
+
output_text: (args.output_text ?? "").slice(0, 4000),
|
|
154
|
+
expected_output: (args.expected_output ?? args.output_text ?? "").slice(0, 4000),
|
|
155
|
+
context: args.context ?? {},
|
|
156
|
+
correction_type: args.correction_type ?? null,
|
|
157
|
+
};
|
|
158
|
+
const path = args.organization_id
|
|
159
|
+
? `/client/corrections/?organization_id=${encodeURIComponent(args.organization_id)}`
|
|
160
|
+
: "/client/corrections/";
|
|
161
|
+
return await this.post(path, body);
|
|
162
|
+
}
|
|
163
|
+
async listCorrections(args) {
|
|
164
|
+
const params = {
|
|
165
|
+
page: Math.max(1, args?.page ?? 1),
|
|
166
|
+
page_size: Math.max(1, Math.min(args?.page_size ?? 50, 100)),
|
|
167
|
+
include_inactive: !!(args?.include_inactive ?? false),
|
|
168
|
+
};
|
|
169
|
+
if (args?.organization_id)
|
|
170
|
+
params.organization_id = args.organization_id;
|
|
171
|
+
return await this.get("/client/corrections/", params);
|
|
172
|
+
}
|
|
173
|
+
async searchCorrections(query, limit = 10, organization_id) {
|
|
174
|
+
const params = {
|
|
175
|
+
query: (query ?? "").trim().slice(0, 4000),
|
|
176
|
+
limit: Math.max(1, Math.min(limit, 50)),
|
|
177
|
+
};
|
|
178
|
+
if (organization_id)
|
|
179
|
+
params.organization_id = organization_id;
|
|
180
|
+
return await this.get("/client/corrections/search", params);
|
|
181
|
+
}
|
|
182
|
+
async getAnalyticsDashboard(user_id, period = "30d", project_id) {
|
|
183
|
+
const params = { user_id, period };
|
|
184
|
+
if (project_id)
|
|
185
|
+
params.project_id = project_id;
|
|
186
|
+
return await this.get("/client/code_intelligence/analytics/dashboard", params);
|
|
187
|
+
}
|
|
188
|
+
async getTimeSaved(user_id, period = "30d", project_id) {
|
|
189
|
+
const params = { user_id, period };
|
|
190
|
+
if (project_id)
|
|
191
|
+
params.project_id = project_id;
|
|
192
|
+
return await this.get("/client/code_intelligence/analytics/time-saved", params);
|
|
193
|
+
}
|
|
194
|
+
async getQualityMetrics(user_id, period = "30d", project_id) {
|
|
195
|
+
const params = { user_id, period };
|
|
196
|
+
if (project_id)
|
|
197
|
+
params.project_id = project_id;
|
|
198
|
+
return await this.get("/client/code_intelligence/analytics/quality", params);
|
|
199
|
+
}
|
|
200
|
+
async getAIAgentMetrics(user_id, project_id) {
|
|
201
|
+
const params = { user_id };
|
|
202
|
+
if (project_id)
|
|
203
|
+
params.project_id = project_id;
|
|
204
|
+
return await this.get("/client/code_intelligence/analytics/ai-agent", params);
|
|
205
|
+
}
|
|
206
|
+
async correctCode(code, language, project_profile) {
|
|
207
|
+
const body = { code, language, project_profile: project_profile ?? {} };
|
|
208
|
+
return await this.post("/client/code_intelligence/correct/code", body);
|
|
209
|
+
}
|
|
210
|
+
async correctConfig(config, config_type) {
|
|
211
|
+
const body = { config, config_type };
|
|
212
|
+
return await this.post("/client/code_intelligence/correct/config", body);
|
|
213
|
+
}
|
|
214
|
+
async correctDocumentation(markdown, doc_type = "README") {
|
|
215
|
+
const body = { markdown, doc_type };
|
|
216
|
+
return await this.post("/client/code_intelligence/correct/documentation", body);
|
|
217
|
+
}
|
|
218
|
+
async applyAutoCorrections(user_id, model_name, corrections) {
|
|
219
|
+
const body = { user_id, model_name, corrections };
|
|
220
|
+
return await this.post("/client/code_intelligence/auto-correct", body);
|
|
221
|
+
}
|
|
222
|
+
async getTrustScore(user_id, model_name) {
|
|
223
|
+
const data = await this.get("/client/code_intelligence/trust-score", { user_id, model_name });
|
|
224
|
+
const v = data.trust_score;
|
|
225
|
+
return typeof v === "number" ? v : Number(v ?? 0);
|
|
226
|
+
}
|
|
227
|
+
async submitFeedback(prediction_id, accepted) {
|
|
228
|
+
await this.post("/client/code_intelligence/feedback", { prediction_id, accepted: !!accepted });
|
|
229
|
+
}
|
|
230
|
+
async getAutoCorrectStats(user_id) {
|
|
231
|
+
return await this.get("/client/code_intelligence/stats", { user_id });
|
|
232
|
+
}
|
|
233
|
+
async getPatterns(user_id) {
|
|
234
|
+
const params = user_id ? { user_id } : undefined;
|
|
235
|
+
const data = await this.get("/client/code_intelligence/patterns", params);
|
|
236
|
+
return Array.isArray(data) ? data : [];
|
|
237
|
+
}
|
|
238
|
+
// ==================== Authentication & User Management ====================
|
|
239
|
+
async register(userData) {
|
|
240
|
+
return await this.post("/client/auth/register", userData);
|
|
241
|
+
}
|
|
242
|
+
async login(credentials) {
|
|
243
|
+
const response = await this.post("/client/auth/login", credentials);
|
|
244
|
+
// Automatically set access token for future requests
|
|
245
|
+
if (response.access_token) {
|
|
246
|
+
this.setAccessToken(response.access_token);
|
|
247
|
+
// Update WebSocket token if connected
|
|
248
|
+
if (this.wsClient) {
|
|
249
|
+
this.wsClient.updateToken(response.access_token);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return response;
|
|
253
|
+
}
|
|
254
|
+
async logout() {
|
|
255
|
+
await this.post("/client/auth/logout", {});
|
|
256
|
+
}
|
|
257
|
+
async refreshToken(refreshToken) {
|
|
258
|
+
return await this.post("/client/auth/refresh", { refresh_token: refreshToken });
|
|
259
|
+
}
|
|
260
|
+
async getProfile() {
|
|
261
|
+
return await this.get("/client/auth/me");
|
|
262
|
+
}
|
|
263
|
+
async updateProfile(updates) {
|
|
264
|
+
return await this.put("/client/auth/me", updates);
|
|
265
|
+
}
|
|
266
|
+
async changePassword(passwordChange) {
|
|
267
|
+
await this.post("/client/auth/change-password", passwordChange);
|
|
268
|
+
}
|
|
269
|
+
async generateApiKey() {
|
|
270
|
+
return await this.post("/client/auth/api-key", {});
|
|
271
|
+
}
|
|
272
|
+
async revokeApiKey() {
|
|
273
|
+
await this.delete("/client/auth/api-key");
|
|
274
|
+
}
|
|
275
|
+
async getPasswordRequirements() {
|
|
276
|
+
return await this.get("/client/auth/password-requirements");
|
|
277
|
+
}
|
|
278
|
+
// ==================== Project Management ====================
|
|
279
|
+
async createProject(projectData) {
|
|
280
|
+
return await this.post("/client/projects/", projectData);
|
|
281
|
+
}
|
|
282
|
+
async getProject(projectId) {
|
|
283
|
+
return await this.get(`/client/projects/${projectId}`);
|
|
284
|
+
}
|
|
285
|
+
async listProjects(organizationId) {
|
|
286
|
+
const path = organizationId ? `/client/projects/org/${organizationId}` : "/client/projects/";
|
|
287
|
+
return await this.get(path);
|
|
288
|
+
}
|
|
289
|
+
async updateProject(projectId, updates) {
|
|
290
|
+
return await this.patch(`/client/projects/${projectId}`, updates);
|
|
291
|
+
}
|
|
292
|
+
async deleteProject(projectId) {
|
|
293
|
+
await this.delete(`/client/projects/${projectId}`);
|
|
294
|
+
}
|
|
295
|
+
async regenerateProjectApiKey(projectId) {
|
|
296
|
+
return await this.post(`/client/projects/${projectId}/api-key`, {});
|
|
297
|
+
}
|
|
298
|
+
async getMcpConfig(projectId) {
|
|
299
|
+
return await this.get(`/client/projects/${projectId}/mcp-config`);
|
|
300
|
+
}
|
|
301
|
+
async getMcpStats(projectId) {
|
|
302
|
+
return await this.get(`/client/projects/${projectId}/mcp-stats`);
|
|
303
|
+
}
|
|
304
|
+
// ==================== Organizations & Teams ====================
|
|
305
|
+
async createOrganization(orgData) {
|
|
306
|
+
return await this.post("/client/organizations/", orgData);
|
|
307
|
+
}
|
|
308
|
+
async listOrganizations() {
|
|
309
|
+
return await this.get("/client/organizations/");
|
|
310
|
+
}
|
|
311
|
+
async getOrganization(orgId) {
|
|
312
|
+
return await this.get(`/client/organizations/${orgId}`);
|
|
313
|
+
}
|
|
314
|
+
async updateOrganization(orgId, updates) {
|
|
315
|
+
return await this.put(`/client/organizations/${orgId}`, updates);
|
|
316
|
+
}
|
|
317
|
+
async addMemberToOrganization(orgId, userId) {
|
|
318
|
+
await this.post(`/client/organizations/${orgId}/members`, { user_id: userId });
|
|
319
|
+
}
|
|
320
|
+
async removeMemberFromOrganization(orgId, userId) {
|
|
321
|
+
await this.post(`/client/organizations/${orgId}/members/${userId}`, {});
|
|
322
|
+
}
|
|
323
|
+
// ==================== Billing & Usage ====================
|
|
324
|
+
async getUsage() {
|
|
325
|
+
return await this.get("/client/billing/usage");
|
|
326
|
+
}
|
|
327
|
+
async getUsageHistory(days = 30, resourceType) {
|
|
328
|
+
const params = { days };
|
|
329
|
+
if (resourceType)
|
|
330
|
+
params.resource_type = resourceType;
|
|
331
|
+
return await this.get("/client/billing/usage/history", params);
|
|
332
|
+
}
|
|
333
|
+
async listBillingPlans() {
|
|
334
|
+
const data = await this.get("/client/billing/plans");
|
|
335
|
+
return Array.isArray(data.plans) ? data.plans : [];
|
|
336
|
+
}
|
|
337
|
+
async getSubscription() {
|
|
338
|
+
return await this.get("/client/billing/subscription");
|
|
339
|
+
}
|
|
340
|
+
// ==================== Notifications ====================
|
|
341
|
+
async listNotifications() {
|
|
342
|
+
const data = await this.get("/client/notifications");
|
|
343
|
+
return Array.isArray(data.notifications) ? data.notifications : [];
|
|
344
|
+
}
|
|
345
|
+
async markNotificationAsRead(notificationId) {
|
|
346
|
+
return await this.post(`/client/notifications/${notificationId}/read`, {});
|
|
347
|
+
}
|
|
348
|
+
async markAllNotificationsAsRead() {
|
|
349
|
+
await this.post("/client/notifications/read-all", {});
|
|
350
|
+
}
|
|
351
|
+
async deleteNotification(notificationId) {
|
|
352
|
+
await this.delete(`/client/notifications/${notificationId}`);
|
|
353
|
+
}
|
|
354
|
+
// ==================== Settings ====================
|
|
355
|
+
async getSettings() {
|
|
356
|
+
return await this.get("/client/settings");
|
|
357
|
+
}
|
|
358
|
+
async updateAccount(updates) {
|
|
359
|
+
return await this.put("/client/settings/account", updates);
|
|
360
|
+
}
|
|
361
|
+
async updatePreferences(preferences) {
|
|
362
|
+
return await this.put("/client/settings/preferences", preferences);
|
|
363
|
+
}
|
|
364
|
+
async getGuidelines() {
|
|
365
|
+
return await this.get("/client/settings/guidelines");
|
|
366
|
+
}
|
|
367
|
+
async changePasswordViaSettings(passwordChange) {
|
|
368
|
+
await this.post("/client/settings/password", passwordChange);
|
|
369
|
+
}
|
|
370
|
+
async deleteAccount(confirm) {
|
|
371
|
+
await this.delete("/client/settings/account");
|
|
372
|
+
}
|
|
373
|
+
// ==================== Activity Logs ====================
|
|
374
|
+
async listActivityLogs(page = 1, pageSize = 50) {
|
|
375
|
+
return await this.get("/client/activity", { page, page_size: pageSize });
|
|
376
|
+
}
|
|
377
|
+
async exportActivityLogs() {
|
|
378
|
+
const url = `${this.baseUrl}/client/activity/export`;
|
|
379
|
+
const res = await fetch(url, { headers: this.headers() });
|
|
380
|
+
if (!res.ok)
|
|
381
|
+
throw new Error(`HTTP ${res.status}`);
|
|
382
|
+
return await res.blob();
|
|
383
|
+
}
|
|
384
|
+
// ==================== Corrections (Additional Methods) ====================
|
|
385
|
+
async getCorrection(correctionId) {
|
|
386
|
+
return await this.get(`/client/corrections/${correctionId}`);
|
|
387
|
+
}
|
|
388
|
+
async updateCorrection(correctionId, updates) {
|
|
389
|
+
return await this.put(`/client/corrections/${correctionId}`, updates);
|
|
390
|
+
}
|
|
391
|
+
async getCorrectionStats() {
|
|
392
|
+
return await this.get("/client/corrections/stats");
|
|
393
|
+
}
|
|
394
|
+
// ==================== WebSocket Support ====================
|
|
395
|
+
/**
|
|
396
|
+
* Create WebSocket connection for real-time updates
|
|
397
|
+
* Requires access token (use login() first or setAccessToken())
|
|
398
|
+
*/
|
|
399
|
+
async createWebSocket() {
|
|
400
|
+
if (!this.accessToken) {
|
|
401
|
+
throw new Error("Access token required for WebSocket connection. Use login() first or setAccessToken()");
|
|
402
|
+
}
|
|
403
|
+
if (!this.wsClient) {
|
|
404
|
+
// Dynamic import for WebSocket
|
|
405
|
+
const { RecursorWebSocket } = await import("./websocket.js");
|
|
406
|
+
this.wsClient = new RecursorWebSocket(this.baseUrl, this.accessToken);
|
|
407
|
+
}
|
|
408
|
+
return this.wsClient;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Connect WebSocket and return client
|
|
412
|
+
*/
|
|
413
|
+
async connectWebSocket() {
|
|
414
|
+
const ws = await this.createWebSocket();
|
|
415
|
+
await ws.connect();
|
|
416
|
+
return ws;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Disconnect WebSocket if connected
|
|
420
|
+
*/
|
|
421
|
+
disconnectWebSocket() {
|
|
422
|
+
if (this.wsClient) {
|
|
423
|
+
this.wsClient.disconnect();
|
|
424
|
+
this.wsClient = undefined;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
// ==================== Memory Operations ====================
|
|
428
|
+
/**
|
|
429
|
+
* Create a conversation summary
|
|
430
|
+
*/
|
|
431
|
+
async createConversationSummary(data) {
|
|
432
|
+
return this.post("/client/memory/conversations/summaries", data);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Get a conversation summary by ID
|
|
436
|
+
*/
|
|
437
|
+
async getConversationSummary(conversationId) {
|
|
438
|
+
return this.get(`/client/memory/conversations/summaries/${conversationId}`);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* List recent conversation summaries
|
|
442
|
+
*/
|
|
443
|
+
async listConversationSummaries(params) {
|
|
444
|
+
return this.get("/client/memory/conversations/summaries", params);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Record an architectural change
|
|
448
|
+
*/
|
|
449
|
+
async recordArchitecturalChange(data) {
|
|
450
|
+
return this.post("/client/memory/architectural/changes", data);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* List recent architectural changes
|
|
454
|
+
*/
|
|
455
|
+
async listArchitecturalChanges(params) {
|
|
456
|
+
return this.get("/client/memory/architectural/changes", params);
|
|
457
|
+
}
|
|
458
|
+
// ==================== Rotatable Memory Operations ====================
|
|
459
|
+
/**
|
|
460
|
+
* Query rotatable memory patterns
|
|
461
|
+
*/
|
|
462
|
+
async queryRotatableMemory(params) {
|
|
463
|
+
return this.post("/client/memory/rotatable/query", params || {});
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Record pattern usage and update effectiveness
|
|
467
|
+
*/
|
|
468
|
+
async recordPatternUsage(patternId, successful) {
|
|
469
|
+
return this.post("/client/memory/rotatable/usage", {
|
|
470
|
+
pattern_id: patternId,
|
|
471
|
+
successful,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Get rotatable memory statistics
|
|
476
|
+
*/
|
|
477
|
+
async getRotatableMemoryStats() {
|
|
478
|
+
return this.get("/client/memory/rotatable/stats");
|
|
479
|
+
}
|
|
480
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RecursorSDK } from "../index";
|
|
2
|
+
export async function activate() {
|
|
3
|
+
const sdk = new RecursorSDK();
|
|
4
|
+
try {
|
|
5
|
+
const policy = await sdk.getLLMGatewayPolicy();
|
|
6
|
+
const messages = [
|
|
7
|
+
{ role: "system", content: "Agent start: enforce governance and consistency" },
|
|
8
|
+
];
|
|
9
|
+
await sdk.gatewayChat({ provider: "openai", model: undefined, messages, call_provider: false });
|
|
10
|
+
// Optionally pre-warm robotics/av policies for domain projects
|
|
11
|
+
try {
|
|
12
|
+
await sdk.getRoboticsGatewayPolicy();
|
|
13
|
+
}
|
|
14
|
+
catch { }
|
|
15
|
+
try {
|
|
16
|
+
await sdk.getAvGatewayPolicy();
|
|
17
|
+
}
|
|
18
|
+
catch { }
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
// noop – extension should not crash if server unavailable
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function deactivate() { }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initAgentSession(userId?: string, orgId?: string): Promise<void>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RecursorSDK } from "../index";
|
|
2
|
+
export async function initAgentSession(userId, orgId) {
|
|
3
|
+
const sdk = new RecursorSDK();
|
|
4
|
+
try {
|
|
5
|
+
const policy = await sdk.getLLMGatewayPolicy();
|
|
6
|
+
const messages = [
|
|
7
|
+
{ role: "system", content: "Windsurf agent: route through Recursor gateway" },
|
|
8
|
+
];
|
|
9
|
+
await sdk.gatewayChat({ provider: "openai", model: undefined, messages, call_provider: false, user_id: userId, organization_id: orgId });
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
// silent fail to avoid disrupting agent
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Client for Recursor SDK
|
|
3
|
+
* Provides real-time updates via WebSocket connection
|
|
4
|
+
*/
|
|
5
|
+
export interface WebSocketMessage {
|
|
6
|
+
type: string;
|
|
7
|
+
data?: unknown;
|
|
8
|
+
user_id?: string;
|
|
9
|
+
timestamp?: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
}
|
|
12
|
+
export type WebSocketEventHandler = (data: unknown) => void;
|
|
13
|
+
export declare class RecursorWebSocket {
|
|
14
|
+
private ws;
|
|
15
|
+
private reconnectAttempts;
|
|
16
|
+
private maxReconnectAttempts;
|
|
17
|
+
private reconnectDelay;
|
|
18
|
+
private pingInterval;
|
|
19
|
+
private isConnecting;
|
|
20
|
+
private shouldReconnect;
|
|
21
|
+
private eventHandlers;
|
|
22
|
+
private baseUrl;
|
|
23
|
+
private accessToken;
|
|
24
|
+
constructor(baseUrl: string, accessToken: string);
|
|
25
|
+
/**
|
|
26
|
+
* Connect to WebSocket server
|
|
27
|
+
*/
|
|
28
|
+
connect(): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Attempt to reconnect with exponential backoff
|
|
31
|
+
*/
|
|
32
|
+
private attemptReconnect;
|
|
33
|
+
/**
|
|
34
|
+
* Start ping interval to keep connection alive
|
|
35
|
+
*/
|
|
36
|
+
private startPing;
|
|
37
|
+
/**
|
|
38
|
+
* Stop ping interval
|
|
39
|
+
*/
|
|
40
|
+
private stopPing;
|
|
41
|
+
/**
|
|
42
|
+
* Send message to server
|
|
43
|
+
*/
|
|
44
|
+
send(message: WebSocketMessage): void;
|
|
45
|
+
/**
|
|
46
|
+
* Subscribe to event type
|
|
47
|
+
*/
|
|
48
|
+
on(event: string, handler: WebSocketEventHandler): void;
|
|
49
|
+
/**
|
|
50
|
+
* Unsubscribe from event type
|
|
51
|
+
*/
|
|
52
|
+
off(event: string, handler: WebSocketEventHandler): void;
|
|
53
|
+
/**
|
|
54
|
+
* Handle incoming message
|
|
55
|
+
*/
|
|
56
|
+
private handleMessage;
|
|
57
|
+
/**
|
|
58
|
+
* Emit event to handlers
|
|
59
|
+
*/
|
|
60
|
+
private emit;
|
|
61
|
+
/**
|
|
62
|
+
* Disconnect WebSocket
|
|
63
|
+
*/
|
|
64
|
+
disconnect(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Check if WebSocket is connected
|
|
67
|
+
*/
|
|
68
|
+
isConnected(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Update access token (useful after token refresh)
|
|
71
|
+
*/
|
|
72
|
+
updateToken(newToken: string): void;
|
|
73
|
+
}
|