@usewhisper/sdk 2.0.0 → 2.2.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/README.md +2 -2
- package/index.d.mts +204 -11
- package/index.d.ts +204 -11
- package/index.js +277 -16
- package/index.mjs +273 -15
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -21,10 +21,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
Whisper: () => Whisper,
|
|
24
|
+
WhisperAgentMiddleware: () => WhisperAgentMiddleware,
|
|
24
25
|
WhisperContext: () => WhisperContext,
|
|
25
26
|
WhisperDefault: () => whisper_agent_default,
|
|
26
27
|
WhisperError: () => WhisperError,
|
|
27
|
-
|
|
28
|
+
createAgentMiddleware: () => createAgentMiddleware,
|
|
29
|
+
default: () => index_default,
|
|
30
|
+
memoryGraphToMermaid: () => memoryGraphToMermaid
|
|
28
31
|
});
|
|
29
32
|
module.exports = __toCommonJS(index_exports);
|
|
30
33
|
|
|
@@ -43,7 +46,6 @@ var Whisper = class {
|
|
|
43
46
|
baseUrl: options.baseUrl,
|
|
44
47
|
project: options.project || "default"
|
|
45
48
|
};
|
|
46
|
-
if (options.orgId) clientConfig.orgId = options.orgId;
|
|
47
49
|
if (options.timeoutMs) clientConfig.timeoutMs = options.timeoutMs;
|
|
48
50
|
if (options.retry) clientConfig.retry = options.retry;
|
|
49
51
|
this.client = new WhisperContext(clientConfig);
|
|
@@ -52,12 +54,14 @@ var Whisper = class {
|
|
|
52
54
|
apiKey: options.apiKey,
|
|
53
55
|
baseUrl: options.baseUrl || "https://context.usewhisper.dev",
|
|
54
56
|
project: options.project || "default",
|
|
55
|
-
orgId: options.orgId || "",
|
|
56
57
|
timeoutMs: options.timeoutMs || 15e3,
|
|
57
58
|
retry: finalRetry,
|
|
58
59
|
contextLimit: options.contextLimit ?? 10,
|
|
59
60
|
memoryTypes: options.memoryTypes ?? ["factual", "preference", "event", "goal", "relationship", "opinion", "instruction"],
|
|
60
|
-
contextPrefix: options.contextPrefix ?? "Relevant context:"
|
|
61
|
+
contextPrefix: options.contextPrefix ?? "Relevant context:",
|
|
62
|
+
autoExtract: options.autoExtract ?? true,
|
|
63
|
+
autoExtractMinConfidence: options.autoExtractMinConfidence ?? 0.65,
|
|
64
|
+
maxMemoriesPerCapture: options.maxMemoriesPerCapture ?? 5
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
67
|
/**
|
|
@@ -132,6 +136,47 @@ ${context}` : "",
|
|
|
132
136
|
return { success: false };
|
|
133
137
|
}
|
|
134
138
|
try {
|
|
139
|
+
if (this.options.autoExtract) {
|
|
140
|
+
const extraction = await this.client.extractMemories({
|
|
141
|
+
project: options?.project ?? this.options.project,
|
|
142
|
+
message: content,
|
|
143
|
+
user_id: options?.userId ?? this.userId,
|
|
144
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
145
|
+
enable_pattern: true,
|
|
146
|
+
enable_inference: true,
|
|
147
|
+
min_confidence: this.options.autoExtractMinConfidence
|
|
148
|
+
});
|
|
149
|
+
const extractedMemories = (extraction.all || []).filter((m) => (m.confidence || 0) >= this.options.autoExtractMinConfidence).slice(0, this.options.maxMemoriesPerCapture);
|
|
150
|
+
if (extractedMemories.length > 0) {
|
|
151
|
+
const bulk = await this.client.addMemoriesBulk({
|
|
152
|
+
project: options?.project ?? this.options.project,
|
|
153
|
+
async: false,
|
|
154
|
+
memories: extractedMemories.map((m) => ({
|
|
155
|
+
content: m.content,
|
|
156
|
+
memory_type: m.memoryType,
|
|
157
|
+
user_id: options?.userId ?? this.userId,
|
|
158
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
159
|
+
importance: Math.max(0.5, Math.min(1, m.confidence || 0.7)),
|
|
160
|
+
confidence: m.confidence || 0.7,
|
|
161
|
+
entity_mentions: m.entityMentions || [],
|
|
162
|
+
event_date: m.eventDate || void 0,
|
|
163
|
+
metadata: {
|
|
164
|
+
extracted: true,
|
|
165
|
+
extraction_method: extraction.extractionMethod,
|
|
166
|
+
extraction_reasoning: m.reasoning,
|
|
167
|
+
inferred: Boolean(m.inferred)
|
|
168
|
+
}
|
|
169
|
+
}))
|
|
170
|
+
});
|
|
171
|
+
const memoryIds = this.extractMemoryIdsFromBulkResponse(bulk);
|
|
172
|
+
return {
|
|
173
|
+
success: true,
|
|
174
|
+
memoryId: memoryIds[0],
|
|
175
|
+
memoryIds: memoryIds.length > 0 ? memoryIds : void 0,
|
|
176
|
+
extracted: extractedMemories.length
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
135
180
|
const result = await this.client.addMemory({
|
|
136
181
|
project: options?.project ?? this.options.project,
|
|
137
182
|
content,
|
|
@@ -177,15 +222,156 @@ ${context}` : "",
|
|
|
177
222
|
return { success: false, extracted: 0 };
|
|
178
223
|
}
|
|
179
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Run a full agent turn with automatic memory read (before) + write (after).
|
|
227
|
+
*/
|
|
228
|
+
async runTurn(params) {
|
|
229
|
+
const contextResult = await this.getContext(params.userMessage, {
|
|
230
|
+
userId: params.userId,
|
|
231
|
+
sessionId: params.sessionId,
|
|
232
|
+
project: params.project,
|
|
233
|
+
limit: params.limit
|
|
234
|
+
});
|
|
235
|
+
const prompt = contextResult.context ? `${contextResult.context}
|
|
236
|
+
|
|
237
|
+
User: ${params.userMessage}` : params.userMessage;
|
|
238
|
+
const response = await params.generate(prompt);
|
|
239
|
+
const captureResult = await this.captureSession(
|
|
240
|
+
[
|
|
241
|
+
{ role: "user", content: params.userMessage },
|
|
242
|
+
{ role: "assistant", content: response }
|
|
243
|
+
],
|
|
244
|
+
{
|
|
245
|
+
userId: params.userId,
|
|
246
|
+
sessionId: params.sessionId,
|
|
247
|
+
project: params.project
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
return {
|
|
251
|
+
response,
|
|
252
|
+
context: contextResult.context,
|
|
253
|
+
count: contextResult.count,
|
|
254
|
+
extracted: captureResult.extracted
|
|
255
|
+
};
|
|
256
|
+
}
|
|
180
257
|
/**
|
|
181
258
|
* Direct access to WhisperContext for advanced usage
|
|
182
259
|
*/
|
|
183
260
|
raw() {
|
|
184
261
|
return this.client;
|
|
185
262
|
}
|
|
263
|
+
extractMemoryIdsFromBulkResponse(bulkResponse) {
|
|
264
|
+
const ids = [];
|
|
265
|
+
if (Array.isArray(bulkResponse?.memories)) {
|
|
266
|
+
for (const memory of bulkResponse.memories) {
|
|
267
|
+
if (memory?.id) ids.push(memory.id);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (bulkResponse?.memory?.id) {
|
|
271
|
+
ids.push(bulkResponse.memory.id);
|
|
272
|
+
}
|
|
273
|
+
if (bulkResponse?.id) {
|
|
274
|
+
ids.push(bulkResponse.id);
|
|
275
|
+
}
|
|
276
|
+
return Array.from(new Set(ids));
|
|
277
|
+
}
|
|
186
278
|
};
|
|
187
279
|
var whisper_agent_default = Whisper;
|
|
188
280
|
|
|
281
|
+
// ../src/sdk/middleware.ts
|
|
282
|
+
var WhisperAgentMiddleware = class {
|
|
283
|
+
whisper;
|
|
284
|
+
promptBuilder;
|
|
285
|
+
constructor(config) {
|
|
286
|
+
this.whisper = new Whisper(config);
|
|
287
|
+
this.promptBuilder = config.promptBuilder || (({ context, userMessage }) => {
|
|
288
|
+
if (!context) return userMessage;
|
|
289
|
+
return `${context}
|
|
290
|
+
|
|
291
|
+
User: ${userMessage}`;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
async beforeTurn(params) {
|
|
295
|
+
const contextResult = await this.whisper.getContext(params.userMessage, {
|
|
296
|
+
userId: params.userId,
|
|
297
|
+
sessionId: params.sessionId,
|
|
298
|
+
project: params.project,
|
|
299
|
+
limit: params.contextLimit
|
|
300
|
+
});
|
|
301
|
+
const prompt = this.promptBuilder({
|
|
302
|
+
context: contextResult.context,
|
|
303
|
+
userMessage: params.userMessage
|
|
304
|
+
});
|
|
305
|
+
return {
|
|
306
|
+
prompt,
|
|
307
|
+
context: contextResult.context,
|
|
308
|
+
contextCount: contextResult.count
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
async afterTurn(params) {
|
|
312
|
+
return this.whisper.captureSession(
|
|
313
|
+
[
|
|
314
|
+
{ role: "user", content: params.userMessage },
|
|
315
|
+
{ role: "assistant", content: params.assistantMessage }
|
|
316
|
+
],
|
|
317
|
+
{
|
|
318
|
+
userId: params.userId,
|
|
319
|
+
sessionId: params.sessionId,
|
|
320
|
+
project: params.project
|
|
321
|
+
}
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
async wrapGenerate(params) {
|
|
325
|
+
const before = await this.beforeTurn(params);
|
|
326
|
+
const response = await params.generate(before.prompt);
|
|
327
|
+
const after = await this.afterTurn({
|
|
328
|
+
userMessage: params.userMessage,
|
|
329
|
+
assistantMessage: response,
|
|
330
|
+
userId: params.userId,
|
|
331
|
+
sessionId: params.sessionId,
|
|
332
|
+
project: params.project
|
|
333
|
+
});
|
|
334
|
+
return {
|
|
335
|
+
response,
|
|
336
|
+
prompt: before.prompt,
|
|
337
|
+
context: before.context,
|
|
338
|
+
contextCount: before.contextCount,
|
|
339
|
+
extracted: after.extracted
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
raw() {
|
|
343
|
+
return this.whisper;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
function createAgentMiddleware(config) {
|
|
347
|
+
return new WhisperAgentMiddleware(config);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// ../src/sdk/graph-utils.ts
|
|
351
|
+
function sanitizeId(id) {
|
|
352
|
+
return `n_${id.replace(/[^a-zA-Z0-9_]/g, "_")}`;
|
|
353
|
+
}
|
|
354
|
+
function shortLabel(input, max = 48) {
|
|
355
|
+
const text = (input || "").replace(/\s+/g, " ").trim();
|
|
356
|
+
if (text.length <= max) return text;
|
|
357
|
+
return `${text.slice(0, max - 3)}...`;
|
|
358
|
+
}
|
|
359
|
+
function memoryGraphToMermaid(graph) {
|
|
360
|
+
const lines = ["flowchart LR"];
|
|
361
|
+
for (const node of graph.nodes || []) {
|
|
362
|
+
const sid = sanitizeId(node.id);
|
|
363
|
+
const label = shortLabel(node.label || node.id);
|
|
364
|
+
lines.push(` ${sid}["${label.replace(/"/g, '\\"')}"]`);
|
|
365
|
+
}
|
|
366
|
+
for (const edge of graph.edges || []) {
|
|
367
|
+
const s = sanitizeId(edge.source);
|
|
368
|
+
const t = sanitizeId(edge.target);
|
|
369
|
+
const rel = shortLabel(edge.type || "rel", 18).replace(/"/g, '\\"');
|
|
370
|
+
lines.push(` ${s} -->|${rel}| ${t}`);
|
|
371
|
+
}
|
|
372
|
+
return lines.join("\n");
|
|
373
|
+
}
|
|
374
|
+
|
|
189
375
|
// ../src/sdk/index.ts
|
|
190
376
|
var WhisperError = class extends Error {
|
|
191
377
|
code;
|
|
@@ -216,11 +402,24 @@ function getBackoffDelay(attempt, base, max) {
|
|
|
216
402
|
function isLikelyProjectId(projectRef) {
|
|
217
403
|
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);
|
|
218
404
|
}
|
|
405
|
+
function normalizeBaseUrl(url) {
|
|
406
|
+
let normalized = url.trim().replace(/\/+$/, "");
|
|
407
|
+
normalized = normalized.replace(/\/api\/v1$/i, "");
|
|
408
|
+
normalized = normalized.replace(/\/v1$/i, "");
|
|
409
|
+
normalized = normalized.replace(/\/api$/i, "");
|
|
410
|
+
return normalized;
|
|
411
|
+
}
|
|
412
|
+
function normalizeEndpoint(endpoint) {
|
|
413
|
+
const withLeadingSlash = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
414
|
+
if (/^\/api\/v1(\/|$)/i.test(withLeadingSlash)) {
|
|
415
|
+
return withLeadingSlash.replace(/^\/api/i, "");
|
|
416
|
+
}
|
|
417
|
+
return withLeadingSlash;
|
|
418
|
+
}
|
|
219
419
|
var WhisperContext = class _WhisperContext {
|
|
220
420
|
apiKey;
|
|
221
421
|
baseUrl;
|
|
222
422
|
defaultProject;
|
|
223
|
-
orgId;
|
|
224
423
|
timeoutMs;
|
|
225
424
|
retryConfig;
|
|
226
425
|
projectRefToId = /* @__PURE__ */ new Map();
|
|
@@ -234,9 +433,8 @@ var WhisperContext = class _WhisperContext {
|
|
|
234
433
|
});
|
|
235
434
|
}
|
|
236
435
|
this.apiKey = config.apiKey;
|
|
237
|
-
this.baseUrl = config.baseUrl || "https://context.usewhisper.dev";
|
|
436
|
+
this.baseUrl = normalizeBaseUrl(config.baseUrl || "https://context.usewhisper.dev");
|
|
238
437
|
this.defaultProject = config.project;
|
|
239
|
-
this.orgId = config.orgId;
|
|
240
438
|
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
241
439
|
this.retryConfig = {
|
|
242
440
|
maxAttempts: config.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
|
@@ -249,7 +447,6 @@ var WhisperContext = class _WhisperContext {
|
|
|
249
447
|
apiKey: this.apiKey,
|
|
250
448
|
baseUrl: this.baseUrl,
|
|
251
449
|
project,
|
|
252
|
-
orgId: this.orgId,
|
|
253
450
|
timeoutMs: this.timeoutMs,
|
|
254
451
|
retry: this.retryConfig
|
|
255
452
|
});
|
|
@@ -366,20 +563,28 @@ var WhisperContext = class _WhisperContext {
|
|
|
366
563
|
}
|
|
367
564
|
async request(endpoint, options = {}) {
|
|
368
565
|
const maxAttempts = Math.max(1, this.retryConfig.maxAttempts);
|
|
566
|
+
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
|
369
567
|
let lastError;
|
|
370
568
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
371
569
|
const controller = new AbortController();
|
|
372
570
|
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
373
571
|
try {
|
|
374
|
-
const
|
|
572
|
+
const headers = {
|
|
573
|
+
"Content-Type": "application/json",
|
|
574
|
+
...options.headers
|
|
575
|
+
};
|
|
576
|
+
const hasAuthHeader = Object.keys(headers).some((k) => k.toLowerCase() === "authorization");
|
|
577
|
+
const hasApiKeyHeader = Object.keys(headers).some((k) => k.toLowerCase() === "x-api-key");
|
|
578
|
+
if (!hasAuthHeader) {
|
|
579
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
580
|
+
}
|
|
581
|
+
if (!hasApiKeyHeader) {
|
|
582
|
+
headers["X-API-Key"] = this.apiKey;
|
|
583
|
+
}
|
|
584
|
+
const response = await fetch(`${this.baseUrl}${normalizedEndpoint}`, {
|
|
375
585
|
...options,
|
|
376
586
|
signal: controller.signal,
|
|
377
|
-
headers
|
|
378
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
379
|
-
"Content-Type": "application/json",
|
|
380
|
-
...this.orgId ? { "X-Whisper-Org-Id": this.orgId } : {},
|
|
381
|
-
...options.headers
|
|
382
|
-
}
|
|
587
|
+
headers
|
|
383
588
|
});
|
|
384
589
|
clearTimeout(timeout);
|
|
385
590
|
if (!response.ok) {
|
|
@@ -568,6 +773,34 @@ var WhisperContext = class _WhisperContext {
|
|
|
568
773
|
return { id, success: true, path: "legacy", fallback_used: true };
|
|
569
774
|
});
|
|
570
775
|
}
|
|
776
|
+
async addMemoriesBulk(params) {
|
|
777
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
778
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/bulk", {
|
|
779
|
+
method: "POST",
|
|
780
|
+
body: JSON.stringify({ ...params, project })
|
|
781
|
+
}));
|
|
782
|
+
}
|
|
783
|
+
async extractMemories(params) {
|
|
784
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
785
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract", {
|
|
786
|
+
method: "POST",
|
|
787
|
+
body: JSON.stringify({ ...params, project })
|
|
788
|
+
}));
|
|
789
|
+
}
|
|
790
|
+
async extractSessionMemories(params) {
|
|
791
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
792
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract/session", {
|
|
793
|
+
method: "POST",
|
|
794
|
+
body: JSON.stringify({
|
|
795
|
+
...params,
|
|
796
|
+
project,
|
|
797
|
+
messages: params.messages.map((m) => ({
|
|
798
|
+
...m,
|
|
799
|
+
timestamp: m.timestamp || (/* @__PURE__ */ new Date()).toISOString()
|
|
800
|
+
}))
|
|
801
|
+
})
|
|
802
|
+
}));
|
|
803
|
+
}
|
|
571
804
|
async searchMemories(params) {
|
|
572
805
|
const projectRef = this.getRequiredProject(params.project);
|
|
573
806
|
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/search", {
|
|
@@ -640,6 +873,26 @@ var WhisperContext = class _WhisperContext {
|
|
|
640
873
|
async getMemoryRelations(memoryId) {
|
|
641
874
|
return this.request(`/v1/memory/${memoryId}/relations`);
|
|
642
875
|
}
|
|
876
|
+
async getMemoryGraph(params) {
|
|
877
|
+
const project = await this.resolveProjectId(this.getRequiredProject(params.project));
|
|
878
|
+
const query = new URLSearchParams({
|
|
879
|
+
project,
|
|
880
|
+
...params.user_id && { user_id: params.user_id },
|
|
881
|
+
...params.session_id && { session_id: params.session_id },
|
|
882
|
+
...params.include_inactive !== void 0 && { include_inactive: String(params.include_inactive) },
|
|
883
|
+
...params.limit !== void 0 && { limit: String(params.limit) }
|
|
884
|
+
});
|
|
885
|
+
return this.request(`/v1/memory/graph?${query}`);
|
|
886
|
+
}
|
|
887
|
+
async getConversationGraph(params) {
|
|
888
|
+
const project = await this.resolveProjectId(this.getRequiredProject(params.project));
|
|
889
|
+
const query = new URLSearchParams({
|
|
890
|
+
project,
|
|
891
|
+
...params.include_inactive !== void 0 && { include_inactive: String(params.include_inactive) },
|
|
892
|
+
...params.limit !== void 0 && { limit: String(params.limit) }
|
|
893
|
+
});
|
|
894
|
+
return this.request(`/v1/memory/graph/conversation/${params.session_id}?${query}`);
|
|
895
|
+
}
|
|
643
896
|
async oracleSearch(params) {
|
|
644
897
|
const project = await this.resolveProjectId(this.getRequiredProject(params.project));
|
|
645
898
|
return this.request("/v1/oracle/search", {
|
|
@@ -764,6 +1017,9 @@ var WhisperContext = class _WhisperContext {
|
|
|
764
1017
|
};
|
|
765
1018
|
memory = {
|
|
766
1019
|
add: (params) => this.addMemory(params),
|
|
1020
|
+
addBulk: (params) => this.addMemoriesBulk(params),
|
|
1021
|
+
extract: (params) => this.extractMemories(params),
|
|
1022
|
+
extractSession: (params) => this.extractSessionMemories(params),
|
|
767
1023
|
search: (params) => this.searchMemories(params),
|
|
768
1024
|
searchSOTA: (params) => this.searchMemoriesSOTA(params),
|
|
769
1025
|
ingestSession: (params) => this.ingestSession(params),
|
|
@@ -773,6 +1029,8 @@ var WhisperContext = class _WhisperContext {
|
|
|
773
1029
|
update: (memoryId, params) => this.updateMemory(memoryId, params),
|
|
774
1030
|
delete: (memoryId) => this.deleteMemory(memoryId),
|
|
775
1031
|
getRelations: (memoryId) => this.getMemoryRelations(memoryId),
|
|
1032
|
+
getGraph: (params) => this.getMemoryGraph(params),
|
|
1033
|
+
getConversationGraph: (params) => this.getConversationGraph(params),
|
|
776
1034
|
consolidate: (params) => this.consolidateMemories(params),
|
|
777
1035
|
updateDecay: (params) => this.updateImportanceDecay(params),
|
|
778
1036
|
getImportanceStats: (project) => this.getImportanceStats(project)
|
|
@@ -803,7 +1061,10 @@ var index_default = WhisperContext;
|
|
|
803
1061
|
// Annotate the CommonJS export names for ESM import in node:
|
|
804
1062
|
0 && (module.exports = {
|
|
805
1063
|
Whisper,
|
|
1064
|
+
WhisperAgentMiddleware,
|
|
806
1065
|
WhisperContext,
|
|
807
1066
|
WhisperDefault,
|
|
808
|
-
WhisperError
|
|
1067
|
+
WhisperError,
|
|
1068
|
+
createAgentMiddleware,
|
|
1069
|
+
memoryGraphToMermaid
|
|
809
1070
|
});
|