@usewhisper/sdk 1.0.0 → 1.1.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/index.js CHANGED
@@ -21,57 +21,290 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  WhisperContext: () => WhisperContext,
24
+ WhisperError: () => WhisperError,
24
25
  default: () => index_default
25
26
  });
26
27
  module.exports = __toCommonJS(index_exports);
27
- var WhisperContext = class {
28
+ var WhisperError = class extends Error {
29
+ code;
30
+ status;
31
+ retryable;
32
+ details;
33
+ constructor(args) {
34
+ super(args.message);
35
+ this.name = "WhisperError";
36
+ this.code = args.code;
37
+ this.status = args.status;
38
+ this.retryable = args.retryable ?? false;
39
+ this.details = args.details;
40
+ }
41
+ };
42
+ var DEFAULT_MAX_ATTEMPTS = 3;
43
+ var DEFAULT_BASE_DELAY_MS = 250;
44
+ var DEFAULT_MAX_DELAY_MS = 2e3;
45
+ var DEFAULT_TIMEOUT_MS = 15e3;
46
+ var PROJECT_CACHE_TTL_MS = 3e4;
47
+ function sleep(ms) {
48
+ return new Promise((resolve) => setTimeout(resolve, ms));
49
+ }
50
+ function getBackoffDelay(attempt, base, max) {
51
+ const jitter = 0.8 + Math.random() * 0.4;
52
+ return Math.min(max, Math.floor(base * Math.pow(2, attempt) * jitter));
53
+ }
54
+ function isLikelyProjectId(projectRef) {
55
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(projectRef);
56
+ }
57
+ var WhisperContext = class _WhisperContext {
28
58
  apiKey;
29
59
  baseUrl;
60
+ defaultProject;
61
+ orgId;
62
+ timeoutMs;
63
+ retryConfig;
64
+ projectRefToId = /* @__PURE__ */ new Map();
65
+ projectCache = [];
66
+ projectCacheExpiresAt = 0;
30
67
  constructor(config) {
31
68
  if (!config.apiKey) {
32
- throw new Error("API key is required");
69
+ throw new WhisperError({
70
+ code: "INVALID_API_KEY",
71
+ message: "API key is required"
72
+ });
33
73
  }
34
74
  this.apiKey = config.apiKey;
35
75
  this.baseUrl = config.baseUrl || "https://context.usewhisper.dev";
76
+ this.defaultProject = config.project;
77
+ this.orgId = config.orgId;
78
+ this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
79
+ this.retryConfig = {
80
+ maxAttempts: config.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
81
+ baseDelayMs: config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS,
82
+ maxDelayMs: config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS
83
+ };
84
+ }
85
+ withProject(project) {
86
+ return new _WhisperContext({
87
+ apiKey: this.apiKey,
88
+ baseUrl: this.baseUrl,
89
+ project,
90
+ orgId: this.orgId,
91
+ timeoutMs: this.timeoutMs,
92
+ retry: this.retryConfig
93
+ });
36
94
  }
37
- async request(endpoint, options = {}) {
38
- const response = await fetch(`${this.baseUrl}${endpoint}`, {
39
- ...options,
40
- headers: {
41
- Authorization: `Bearer ${this.apiKey}`,
42
- "Content-Type": "application/json",
43
- ...options.headers
95
+ getRequiredProject(project) {
96
+ const resolved = project || this.defaultProject;
97
+ if (!resolved) {
98
+ throw new WhisperError({
99
+ code: "MISSING_PROJECT",
100
+ message: "Project is required. Pass project in params or set a default project in WhisperContext config."
101
+ });
102
+ }
103
+ return resolved;
104
+ }
105
+ async refreshProjectCache(force = false) {
106
+ if (!force && Date.now() < this.projectCacheExpiresAt && this.projectCache.length > 0) {
107
+ return this.projectCache;
108
+ }
109
+ const response = await this.request("/v1/projects", { method: "GET" });
110
+ this.projectRefToId.clear();
111
+ this.projectCache = response.projects || [];
112
+ for (const p of this.projectCache) {
113
+ this.projectRefToId.set(p.id, p.id);
114
+ this.projectRefToId.set(p.slug, p.id);
115
+ this.projectRefToId.set(p.name, p.id);
116
+ }
117
+ this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
118
+ return this.projectCache;
119
+ }
120
+ async resolveProjectId(projectRef) {
121
+ if (this.projectRefToId.has(projectRef)) {
122
+ return this.projectRefToId.get(projectRef);
123
+ }
124
+ const projects = await this.refreshProjectCache(true);
125
+ const byDirect = projects.find((p) => p.id === projectRef);
126
+ if (byDirect) return byDirect.id;
127
+ const matches = projects.filter((p) => p.slug === projectRef || p.name === projectRef);
128
+ if (matches.length === 1) {
129
+ return matches[0].id;
130
+ }
131
+ if (matches.length > 1) {
132
+ throw new WhisperError({
133
+ code: "PROJECT_AMBIGUOUS",
134
+ message: `Project reference '${projectRef}' matched multiple projects. Use project id instead.`
135
+ });
136
+ }
137
+ if (isLikelyProjectId(projectRef)) {
138
+ return projectRef;
139
+ }
140
+ throw new WhisperError({
141
+ code: "PROJECT_NOT_FOUND",
142
+ message: `Project '${projectRef}' not found`
143
+ });
144
+ }
145
+ async getProjectRefCandidates(projectRef) {
146
+ const candidates = /* @__PURE__ */ new Set([projectRef]);
147
+ try {
148
+ const projects = await this.refreshProjectCache(false);
149
+ const match = projects.find((p) => p.id === projectRef || p.slug === projectRef || p.name === projectRef);
150
+ if (match) {
151
+ candidates.add(match.id);
152
+ candidates.add(match.slug);
153
+ candidates.add(match.name);
154
+ } else if (isLikelyProjectId(projectRef)) {
155
+ const byId = projects.find((p) => p.id === projectRef);
156
+ if (byId) {
157
+ candidates.add(byId.slug);
158
+ candidates.add(byId.name);
159
+ }
160
+ }
161
+ } catch {
162
+ }
163
+ return Array.from(candidates).filter(Boolean);
164
+ }
165
+ async withProjectRefFallback(projectRef, execute) {
166
+ const refs = await this.getProjectRefCandidates(projectRef);
167
+ let lastError;
168
+ for (const ref of refs) {
169
+ try {
170
+ return await execute(ref);
171
+ } catch (error) {
172
+ lastError = error;
173
+ if (error instanceof WhisperError && error.code === "PROJECT_NOT_FOUND") {
174
+ continue;
175
+ }
176
+ throw error;
44
177
  }
178
+ }
179
+ if (lastError instanceof Error) {
180
+ throw lastError;
181
+ }
182
+ throw new WhisperError({
183
+ code: "PROJECT_NOT_FOUND",
184
+ message: `Project '${projectRef}' not found`
45
185
  });
46
- if (!response.ok) {
47
- const error = await response.json().catch(() => ({ error: "Request failed" }));
48
- throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);
186
+ }
187
+ classifyError(status, message) {
188
+ if (status === 401 || /api key|unauthorized|forbidden/i.test(message)) {
189
+ return { code: "INVALID_API_KEY", retryable: false };
190
+ }
191
+ if (status === 404 || /project not found/i.test(message)) {
192
+ return { code: "PROJECT_NOT_FOUND", retryable: false };
49
193
  }
50
- return response.json();
194
+ if (status === 408) {
195
+ return { code: "TIMEOUT", retryable: true };
196
+ }
197
+ if (status === 429) {
198
+ return { code: "RATE_LIMITED", retryable: true };
199
+ }
200
+ if (status !== void 0 && status >= 500) {
201
+ return { code: "TEMPORARY_UNAVAILABLE", retryable: true };
202
+ }
203
+ return { code: "REQUEST_FAILED", retryable: false };
204
+ }
205
+ async request(endpoint, options = {}) {
206
+ const maxAttempts = Math.max(1, this.retryConfig.maxAttempts);
207
+ let lastError;
208
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
209
+ const controller = new AbortController();
210
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
211
+ try {
212
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
213
+ ...options,
214
+ signal: controller.signal,
215
+ headers: {
216
+ Authorization: `Bearer ${this.apiKey}`,
217
+ "Content-Type": "application/json",
218
+ ...this.orgId ? { "X-Whisper-Org-Id": this.orgId } : {},
219
+ ...options.headers
220
+ }
221
+ });
222
+ clearTimeout(timeout);
223
+ if (!response.ok) {
224
+ let payload = null;
225
+ try {
226
+ payload = await response.json();
227
+ } catch {
228
+ payload = await response.text().catch(() => "");
229
+ }
230
+ const message = typeof payload === "string" ? payload : payload?.error || payload?.message || `HTTP ${response.status}: ${response.statusText}`;
231
+ const { code, retryable } = this.classifyError(response.status, message);
232
+ const err = new WhisperError({
233
+ code,
234
+ message,
235
+ status: response.status,
236
+ retryable,
237
+ details: payload
238
+ });
239
+ if (!retryable || attempt === maxAttempts - 1) {
240
+ throw err;
241
+ }
242
+ await sleep(getBackoffDelay(attempt, this.retryConfig.baseDelayMs, this.retryConfig.maxDelayMs));
243
+ continue;
244
+ }
245
+ return response.json();
246
+ } catch (error) {
247
+ clearTimeout(timeout);
248
+ const isAbort = error?.name === "AbortError";
249
+ const mapped = error instanceof WhisperError ? error : new WhisperError({
250
+ code: isAbort ? "TIMEOUT" : "NETWORK_ERROR",
251
+ message: isAbort ? "Request timed out" : error?.message || "Network request failed",
252
+ retryable: true,
253
+ details: error
254
+ });
255
+ lastError = mapped;
256
+ if (!mapped.retryable || attempt === maxAttempts - 1) {
257
+ throw mapped;
258
+ }
259
+ await sleep(getBackoffDelay(attempt, this.retryConfig.baseDelayMs, this.retryConfig.maxDelayMs));
260
+ }
261
+ }
262
+ throw lastError instanceof Error ? lastError : new WhisperError({ code: "REQUEST_FAILED", message: "Request failed" });
51
263
  }
52
264
  async query(params) {
53
- return this.request("/v1/context/query", {
265
+ const projectRef = this.getRequiredProject(params.project);
266
+ return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/context/query", {
54
267
  method: "POST",
55
- body: JSON.stringify(params)
56
- });
268
+ body: JSON.stringify({ ...params, project })
269
+ }));
57
270
  }
58
271
  async createProject(params) {
59
- return this.request("/v1/projects", {
272
+ const project = await this.request("/v1/projects", {
60
273
  method: "POST",
61
274
  body: JSON.stringify(params)
62
275
  });
276
+ this.projectRefToId.set(project.id, project.id);
277
+ this.projectRefToId.set(project.slug, project.id);
278
+ this.projectRefToId.set(project.name, project.id);
279
+ this.projectCache = [
280
+ ...this.projectCache.filter((p) => p.id !== project.id),
281
+ project
282
+ ];
283
+ this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
284
+ return project;
63
285
  }
64
286
  async listProjects() {
65
- return this.request("/v1/projects");
287
+ const projects = await this.request("/v1/projects", { method: "GET" });
288
+ this.projectCache = projects.projects || [];
289
+ for (const p of projects.projects || []) {
290
+ this.projectRefToId.set(p.id, p.id);
291
+ this.projectRefToId.set(p.slug, p.id);
292
+ this.projectRefToId.set(p.name, p.id);
293
+ }
294
+ this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
295
+ return projects;
66
296
  }
67
297
  async getProject(id) {
68
- return this.request(`/v1/projects/${id}`);
298
+ const projectId = await this.resolveProjectId(id);
299
+ return this.request(`/v1/projects/${projectId}`);
69
300
  }
70
301
  async deleteProject(id) {
71
- return this.request(`/v1/projects/${id}`, { method: "DELETE" });
302
+ const projectId = await this.resolveProjectId(id);
303
+ return this.request(`/v1/projects/${projectId}`, { method: "DELETE" });
72
304
  }
73
305
  async addSource(projectId, params) {
74
- return this.request(`/v1/projects/${projectId}/sources`, {
306
+ const resolvedProjectId = await this.resolveProjectId(projectId);
307
+ return this.request(`/v1/projects/${resolvedProjectId}/sources`, {
75
308
  method: "POST",
76
309
  body: JSON.stringify(params)
77
310
  });
@@ -80,30 +313,15 @@ var WhisperContext = class {
80
313
  return this.request(`/v1/sources/${sourceId}/sync`, { method: "POST" });
81
314
  }
82
315
  async ingest(projectId, documents) {
83
- return this.request(`/v1/projects/${projectId}/ingest`, {
316
+ const resolvedProjectId = await this.resolveProjectId(projectId);
317
+ return this.request(`/v1/projects/${resolvedProjectId}/ingest`, {
84
318
  method: "POST",
85
319
  body: JSON.stringify({ documents })
86
320
  });
87
321
  }
88
- /**
89
- * Add Context - Quick method to inject context without full document format
90
- * Ideal for agents to add context on the fly
91
- *
92
- * @example
93
- * await client.addContext({
94
- * project: "my-app",
95
- * content: "User prefers dark mode and TypeScript over JavaScript"
96
- * });
97
- */
98
322
  async addContext(params) {
99
- const projectData = await this.listProjects();
100
- const project = projectData.projects.find(
101
- (p) => p.name === params.project || p.slug === params.project
102
- );
103
- if (!project) {
104
- throw new Error(`Project '${params.project}' not found`);
105
- }
106
- return this.ingest(project.id, [
323
+ const projectId = await this.resolveProjectId(this.getRequiredProject(params.project));
324
+ return this.ingest(projectId, [
107
325
  {
108
326
  title: params.title || "Context",
109
327
  content: params.content,
@@ -111,41 +329,96 @@ var WhisperContext = class {
111
329
  }
112
330
  ]);
113
331
  }
114
- /**
115
- * Add Memory - Creates a memory using the SOTA memory system
116
- * This is the recommended method for conversational memory
117
- */
118
332
  async addMemory(params) {
119
- return this.request("/v1/memory/ingest/session", {
120
- method: "POST",
121
- body: JSON.stringify({
122
- project: params.project,
123
- session_id: params.session_id || `single-${Date.now()}`,
124
- user_id: params.user_id,
125
- messages: [{
126
- role: "user",
333
+ const projectRef = this.getRequiredProject(params.project);
334
+ return this.withProjectRefFallback(projectRef, async (project) => {
335
+ const toSotaType = (memoryType) => {
336
+ switch (memoryType) {
337
+ case "episodic":
338
+ return "event";
339
+ case "semantic":
340
+ return "factual";
341
+ case "procedural":
342
+ return "instruction";
343
+ default:
344
+ return memoryType;
345
+ }
346
+ };
347
+ const toLegacyType = (memoryType) => {
348
+ switch (memoryType) {
349
+ case "event":
350
+ return "episodic";
351
+ case "instruction":
352
+ return "procedural";
353
+ case "preference":
354
+ case "relationship":
355
+ case "opinion":
356
+ case "goal":
357
+ return "semantic";
358
+ default:
359
+ return memoryType;
360
+ }
361
+ };
362
+ try {
363
+ const direct = await this.request("/v1/memory", {
364
+ method: "POST",
365
+ body: JSON.stringify({
366
+ project,
367
+ content: params.content,
368
+ memory_type: toSotaType(params.memory_type),
369
+ user_id: params.user_id,
370
+ session_id: params.session_id,
371
+ agent_id: params.agent_id,
372
+ importance: params.importance,
373
+ metadata: params.metadata
374
+ })
375
+ });
376
+ const id2 = direct?.memory?.id || direct?.id || direct?.memory_id;
377
+ if (id2) {
378
+ return { id: id2, success: true, path: "sota", fallback_used: false };
379
+ }
380
+ } catch (error) {
381
+ if (params.allow_legacy_fallback === false) {
382
+ throw error;
383
+ }
384
+ }
385
+ const legacy = await this.request("/v1/memories", {
386
+ method: "POST",
387
+ body: JSON.stringify({
388
+ project,
127
389
  content: params.content,
128
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
129
- }]
130
- })
390
+ memory_type: toLegacyType(params.memory_type),
391
+ user_id: params.user_id,
392
+ session_id: params.session_id,
393
+ agent_id: params.agent_id,
394
+ importance: params.importance,
395
+ metadata: params.metadata,
396
+ expires_in_seconds: params.expires_in_seconds
397
+ })
398
+ });
399
+ const id = legacy?.memory?.id || legacy?.id || legacy?.memory_id;
400
+ if (!id) {
401
+ throw new WhisperError({
402
+ code: "REQUEST_FAILED",
403
+ message: "Memory create succeeded but no memory id was returned by the API"
404
+ });
405
+ }
406
+ return { id, success: true, path: "legacy", fallback_used: true };
131
407
  });
132
408
  }
133
- /**
134
- * Search Memories - Searches memories using SOTA memory search with temporal reasoning
135
- * This is the recommended method for memory retrieval
136
- */
137
409
  async searchMemories(params) {
138
- return this.request("/v1/memory/search", {
410
+ const projectRef = this.getRequiredProject(params.project);
411
+ return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/search", {
139
412
  method: "POST",
140
413
  body: JSON.stringify({
141
414
  query: params.query,
142
- project: params.project,
415
+ project,
143
416
  user_id: params.user_id,
144
417
  session_id: params.session_id,
145
418
  memory_types: params.memory_type ? [params.memory_type] : void 0,
146
419
  top_k: params.top_k || 10
147
420
  })
148
- });
421
+ }));
149
422
  }
150
423
  async createApiKey(params) {
151
424
  return this.request("/v1/keys", {
@@ -159,182 +432,130 @@ var WhisperContext = class {
159
432
  async getUsage(days = 30) {
160
433
  return this.request(`/v1/usage?days=${days}`);
161
434
  }
162
- // ─── SOTA Memory System ─────────────────────────────────────────
163
- /**
164
- * SOTA Memory Search - Search memories with temporal and type filtering
165
- */
166
435
  async searchMemoriesSOTA(params) {
167
- return this.request("/v1/memory/search", {
436
+ const projectRef = this.getRequiredProject(params.project);
437
+ return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/search", {
168
438
  method: "POST",
169
- body: JSON.stringify(params)
170
- });
439
+ body: JSON.stringify({ ...params, project })
440
+ }));
171
441
  }
172
- /**
173
- * Ingest Session - Create memories from a conversation
174
- */
175
442
  async ingestSession(params) {
176
- return this.request("/v1/memory/ingest/session", {
443
+ const projectRef = this.getRequiredProject(params.project);
444
+ return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/ingest/session", {
177
445
  method: "POST",
178
- body: JSON.stringify(params)
179
- });
446
+ body: JSON.stringify({ ...params, project })
447
+ }));
180
448
  }
181
- /**
182
- * Get Session Memories - Recent memories from a session
183
- */
184
449
  async getSessionMemories(params) {
450
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
185
451
  const query = new URLSearchParams({
186
- project: params.project,
452
+ project,
187
453
  ...params.limit && { limit: params.limit.toString() },
188
454
  ...params.since_date && { since_date: params.since_date }
189
455
  });
190
456
  return this.request(`/v1/memory/session/${params.session_id}?${query}`);
191
457
  }
192
- /**
193
- * Get User Profile - Long-term user preferences and facts
194
- */
195
458
  async getUserProfile(params) {
459
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
196
460
  const query = new URLSearchParams({
197
- project: params.project,
461
+ project,
198
462
  ...params.memory_types && { memory_types: params.memory_types }
199
463
  });
200
464
  return this.request(`/v1/memory/profile/${params.user_id}?${query}`);
201
465
  }
202
- /**
203
- * Get Memory Versions - Version chain history
204
- */
205
466
  async getMemoryVersions(memoryId) {
206
467
  return this.request(`/v1/memory/${memoryId}/versions`);
207
468
  }
208
- /**
209
- * Update Memory - Create a new version
210
- */
211
469
  async updateMemory(memoryId, params) {
212
470
  return this.request(`/v1/memory/${memoryId}`, {
213
471
  method: "PUT",
214
472
  body: JSON.stringify(params)
215
473
  });
216
474
  }
217
- /**
218
- * Delete Memory - Soft delete
219
- */
220
475
  async deleteMemory(memoryId) {
221
476
  return this.request(`/v1/memory/${memoryId}`, { method: "DELETE" });
222
477
  }
223
- /**
224
- * Get Memory Relations - Graph connections
225
- */
226
478
  async getMemoryRelations(memoryId) {
227
479
  return this.request(`/v1/memory/${memoryId}/relations`);
228
480
  }
229
- // ─── Context Layer ──────────────────────────────────────────────
230
- /**
231
- * Oracle Search - Tree-guided document navigation with research mode
232
- */
233
481
  async oracleSearch(params) {
482
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
234
483
  return this.request("/v1/oracle/search", {
235
484
  method: "POST",
236
- body: JSON.stringify(params)
485
+ body: JSON.stringify({ ...params, project })
237
486
  });
238
487
  }
239
- /**
240
- * Autosubscribe - Auto-index project dependencies
241
- */
242
488
  async autosubscribe(params) {
489
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
243
490
  return this.request("/v1/autosubscribe", {
244
491
  method: "POST",
245
- body: JSON.stringify(params)
492
+ body: JSON.stringify({ ...params, project })
246
493
  });
247
494
  }
248
- /**
249
- * Create Shared Context - Save and share a conversation
250
- */
251
495
  async createSharedContext(params) {
496
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
252
497
  return this.request("/v1/context/share", {
253
498
  method: "POST",
254
- body: JSON.stringify(params)
499
+ body: JSON.stringify({ ...params, project })
255
500
  });
256
501
  }
257
- /**
258
- * Load Shared Context - View shared context (public endpoint)
259
- */
260
502
  async loadSharedContext(shareId) {
261
503
  return this.request(`/v1/context/shared/${shareId}`);
262
504
  }
263
- /**
264
- * Resume from Shared Context - Fork shared context to new session
265
- */
266
505
  async resumeFromSharedContext(params) {
506
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
267
507
  return this.request("/v1/context/resume", {
268
508
  method: "POST",
269
- body: JSON.stringify(params)
509
+ body: JSON.stringify({ ...params, project })
270
510
  });
271
511
  }
272
- // ─── Optimization ───────────────────────────────────────────────
273
- /**
274
- * Consolidate Memories - Find and merge duplicates
275
- */
276
512
  async consolidateMemories(params) {
513
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
277
514
  return this.request("/v1/memory/consolidate", {
278
515
  method: "POST",
279
- body: JSON.stringify(params)
516
+ body: JSON.stringify({ ...params, project })
280
517
  });
281
518
  }
282
- /**
283
- * Update Importance Decay - Apply time-based relevance scoring
284
- */
285
519
  async updateImportanceDecay(params) {
520
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
286
521
  return this.request("/v1/memory/decay/update", {
287
522
  method: "POST",
288
- body: JSON.stringify(params)
523
+ body: JSON.stringify({ ...params, project })
289
524
  });
290
525
  }
291
- /**
292
- * Get Importance Statistics
293
- */
294
526
  async getImportanceStats(project) {
295
- return this.request(`/v1/memory/decay/stats?project=${project}`);
527
+ const resolvedProject = await this.resolveProjectId(this.getRequiredProject(project));
528
+ return this.request(`/v1/memory/decay/stats?project=${resolvedProject}`);
296
529
  }
297
- /**
298
- * Get Cache Statistics
299
- */
300
530
  async getCacheStats() {
301
531
  return this.request("/v1/cache/stats");
302
532
  }
303
- /**
304
- * Warm Cache - Preload common queries
305
- */
306
533
  async warmCache(params) {
534
+ const project = await this.resolveProjectId(this.getRequiredProject(params.project));
307
535
  return this.request("/v1/cache/warm", {
308
536
  method: "POST",
309
- body: JSON.stringify(params)
537
+ body: JSON.stringify({ ...params, project })
310
538
  });
311
539
  }
312
- /**
313
- * Clear Cache Pattern
314
- */
315
540
  async clearCache(params) {
316
541
  return this.request("/v1/cache/clear", {
317
542
  method: "DELETE",
318
543
  body: JSON.stringify(params)
319
544
  });
320
545
  }
321
- /**
322
- * Get Cost Summary - Cost tracking overview
323
- */
324
- async getCostSummary(params) {
546
+ async getCostSummary(params = {}) {
547
+ const resolvedProject = params.project ? await this.resolveProjectId(params.project) : void 0;
325
548
  const query = new URLSearchParams({
326
- ...params.project && { project: params.project },
549
+ ...resolvedProject && { project: resolvedProject },
327
550
  ...params.start_date && { start_date: params.start_date },
328
551
  ...params.end_date && { end_date: params.end_date }
329
552
  });
330
553
  return this.request(`/v1/cost/summary?${query}`);
331
554
  }
332
- /**
333
- * Get Cost Breakdown - Detailed cost analysis
334
- */
335
- async getCostBreakdown(params) {
555
+ async getCostBreakdown(params = {}) {
556
+ const resolvedProject = params.project ? await this.resolveProjectId(params.project) : void 0;
336
557
  const query = new URLSearchParams({
337
- ...params.project && { project: params.project },
558
+ ...resolvedProject && { project: resolvedProject },
338
559
  ...params.group_by && { group_by: params.group_by },
339
560
  ...params.start_date && { start_date: params.start_date },
340
561
  ...params.end_date && { end_date: params.end_date }
@@ -342,19 +563,83 @@ var WhisperContext = class {
342
563
  return this.request(`/v1/cost/breakdown?${query}`);
343
564
  }
344
565
  /**
345
- * Get Savings Report - Compare actual vs always-Opus costs
566
+ * Semantic search over raw documents without pre-indexing.
567
+ * Send file contents/summaries directly — the API embeds them in-memory and ranks by similarity.
568
+ * Perfect for AI agents to semantically explore a codebase on-the-fly.
346
569
  */
347
- async getCostSavings(params) {
570
+ async semanticSearch(params) {
571
+ return this.request("/v1/search/semantic", {
572
+ method: "POST",
573
+ body: JSON.stringify(params)
574
+ });
575
+ }
576
+ async searchFiles(params) {
577
+ return this.request("/v1/search/files", {
578
+ method: "POST",
579
+ body: JSON.stringify(params)
580
+ });
581
+ }
582
+ async getCostSavings(params = {}) {
583
+ const resolvedProject = params.project ? await this.resolveProjectId(params.project) : void 0;
348
584
  const query = new URLSearchParams({
349
- ...params.project && { project: params.project },
585
+ ...resolvedProject && { project: resolvedProject },
350
586
  ...params.start_date && { start_date: params.start_date },
351
587
  ...params.end_date && { end_date: params.end_date }
352
588
  });
353
589
  return this.request(`/v1/cost/savings?${query}`);
354
590
  }
591
+ // Backward-compatible grouped namespaces.
592
+ projects = {
593
+ create: (params) => this.createProject(params),
594
+ list: () => this.listProjects(),
595
+ get: (id) => this.getProject(id),
596
+ delete: (id) => this.deleteProject(id)
597
+ };
598
+ sources = {
599
+ add: (projectId, params) => this.addSource(projectId, params),
600
+ sync: (sourceId) => this.syncSource(sourceId),
601
+ syncSource: (sourceId) => this.syncSource(sourceId)
602
+ };
603
+ memory = {
604
+ add: (params) => this.addMemory(params),
605
+ search: (params) => this.searchMemories(params),
606
+ searchSOTA: (params) => this.searchMemoriesSOTA(params),
607
+ ingestSession: (params) => this.ingestSession(params),
608
+ getSessionMemories: (params) => this.getSessionMemories(params),
609
+ getUserProfile: (params) => this.getUserProfile(params),
610
+ getVersions: (memoryId) => this.getMemoryVersions(memoryId),
611
+ update: (memoryId, params) => this.updateMemory(memoryId, params),
612
+ delete: (memoryId) => this.deleteMemory(memoryId),
613
+ getRelations: (memoryId) => this.getMemoryRelations(memoryId),
614
+ consolidate: (params) => this.consolidateMemories(params),
615
+ updateDecay: (params) => this.updateImportanceDecay(params),
616
+ getImportanceStats: (project) => this.getImportanceStats(project)
617
+ };
618
+ keys = {
619
+ create: (params) => this.createApiKey(params),
620
+ list: () => this.listApiKeys(),
621
+ getUsage: (days) => this.getUsage(days)
622
+ };
623
+ oracle = {
624
+ search: (params) => this.oracleSearch(params)
625
+ };
626
+ context = {
627
+ createShare: (params) => this.createSharedContext(params),
628
+ loadShare: (shareId) => this.loadSharedContext(shareId),
629
+ resumeShare: (params) => this.resumeFromSharedContext(params)
630
+ };
631
+ optimization = {
632
+ getCacheStats: () => this.getCacheStats(),
633
+ warmCache: (params) => this.warmCache(params),
634
+ clearCache: (params) => this.clearCache(params),
635
+ getCostSummary: (params) => this.getCostSummary(params),
636
+ getCostBreakdown: (params) => this.getCostBreakdown(params),
637
+ getCostSavings: (params) => this.getCostSavings(params)
638
+ };
355
639
  };
356
640
  var index_default = WhisperContext;
357
641
  // Annotate the CommonJS export names for ESM import in node:
358
642
  0 && (module.exports = {
359
- WhisperContext
643
+ WhisperContext,
644
+ WhisperError
360
645
  });