@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.mjs
CHANGED
|
@@ -13,7 +13,6 @@ var Whisper = class {
|
|
|
13
13
|
baseUrl: options.baseUrl,
|
|
14
14
|
project: options.project || "default"
|
|
15
15
|
};
|
|
16
|
-
if (options.orgId) clientConfig.orgId = options.orgId;
|
|
17
16
|
if (options.timeoutMs) clientConfig.timeoutMs = options.timeoutMs;
|
|
18
17
|
if (options.retry) clientConfig.retry = options.retry;
|
|
19
18
|
this.client = new WhisperContext(clientConfig);
|
|
@@ -22,12 +21,14 @@ var Whisper = class {
|
|
|
22
21
|
apiKey: options.apiKey,
|
|
23
22
|
baseUrl: options.baseUrl || "https://context.usewhisper.dev",
|
|
24
23
|
project: options.project || "default",
|
|
25
|
-
orgId: options.orgId || "",
|
|
26
24
|
timeoutMs: options.timeoutMs || 15e3,
|
|
27
25
|
retry: finalRetry,
|
|
28
26
|
contextLimit: options.contextLimit ?? 10,
|
|
29
27
|
memoryTypes: options.memoryTypes ?? ["factual", "preference", "event", "goal", "relationship", "opinion", "instruction"],
|
|
30
|
-
contextPrefix: options.contextPrefix ?? "Relevant context:"
|
|
28
|
+
contextPrefix: options.contextPrefix ?? "Relevant context:",
|
|
29
|
+
autoExtract: options.autoExtract ?? true,
|
|
30
|
+
autoExtractMinConfidence: options.autoExtractMinConfidence ?? 0.65,
|
|
31
|
+
maxMemoriesPerCapture: options.maxMemoriesPerCapture ?? 5
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
34
|
/**
|
|
@@ -102,6 +103,47 @@ ${context}` : "",
|
|
|
102
103
|
return { success: false };
|
|
103
104
|
}
|
|
104
105
|
try {
|
|
106
|
+
if (this.options.autoExtract) {
|
|
107
|
+
const extraction = await this.client.extractMemories({
|
|
108
|
+
project: options?.project ?? this.options.project,
|
|
109
|
+
message: content,
|
|
110
|
+
user_id: options?.userId ?? this.userId,
|
|
111
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
112
|
+
enable_pattern: true,
|
|
113
|
+
enable_inference: true,
|
|
114
|
+
min_confidence: this.options.autoExtractMinConfidence
|
|
115
|
+
});
|
|
116
|
+
const extractedMemories = (extraction.all || []).filter((m) => (m.confidence || 0) >= this.options.autoExtractMinConfidence).slice(0, this.options.maxMemoriesPerCapture);
|
|
117
|
+
if (extractedMemories.length > 0) {
|
|
118
|
+
const bulk = await this.client.addMemoriesBulk({
|
|
119
|
+
project: options?.project ?? this.options.project,
|
|
120
|
+
async: false,
|
|
121
|
+
memories: extractedMemories.map((m) => ({
|
|
122
|
+
content: m.content,
|
|
123
|
+
memory_type: m.memoryType,
|
|
124
|
+
user_id: options?.userId ?? this.userId,
|
|
125
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
126
|
+
importance: Math.max(0.5, Math.min(1, m.confidence || 0.7)),
|
|
127
|
+
confidence: m.confidence || 0.7,
|
|
128
|
+
entity_mentions: m.entityMentions || [],
|
|
129
|
+
event_date: m.eventDate || void 0,
|
|
130
|
+
metadata: {
|
|
131
|
+
extracted: true,
|
|
132
|
+
extraction_method: extraction.extractionMethod,
|
|
133
|
+
extraction_reasoning: m.reasoning,
|
|
134
|
+
inferred: Boolean(m.inferred)
|
|
135
|
+
}
|
|
136
|
+
}))
|
|
137
|
+
});
|
|
138
|
+
const memoryIds = this.extractMemoryIdsFromBulkResponse(bulk);
|
|
139
|
+
return {
|
|
140
|
+
success: true,
|
|
141
|
+
memoryId: memoryIds[0],
|
|
142
|
+
memoryIds: memoryIds.length > 0 ? memoryIds : void 0,
|
|
143
|
+
extracted: extractedMemories.length
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
105
147
|
const result = await this.client.addMemory({
|
|
106
148
|
project: options?.project ?? this.options.project,
|
|
107
149
|
content,
|
|
@@ -147,15 +189,156 @@ ${context}` : "",
|
|
|
147
189
|
return { success: false, extracted: 0 };
|
|
148
190
|
}
|
|
149
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Run a full agent turn with automatic memory read (before) + write (after).
|
|
194
|
+
*/
|
|
195
|
+
async runTurn(params) {
|
|
196
|
+
const contextResult = await this.getContext(params.userMessage, {
|
|
197
|
+
userId: params.userId,
|
|
198
|
+
sessionId: params.sessionId,
|
|
199
|
+
project: params.project,
|
|
200
|
+
limit: params.limit
|
|
201
|
+
});
|
|
202
|
+
const prompt = contextResult.context ? `${contextResult.context}
|
|
203
|
+
|
|
204
|
+
User: ${params.userMessage}` : params.userMessage;
|
|
205
|
+
const response = await params.generate(prompt);
|
|
206
|
+
const captureResult = await this.captureSession(
|
|
207
|
+
[
|
|
208
|
+
{ role: "user", content: params.userMessage },
|
|
209
|
+
{ role: "assistant", content: response }
|
|
210
|
+
],
|
|
211
|
+
{
|
|
212
|
+
userId: params.userId,
|
|
213
|
+
sessionId: params.sessionId,
|
|
214
|
+
project: params.project
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
return {
|
|
218
|
+
response,
|
|
219
|
+
context: contextResult.context,
|
|
220
|
+
count: contextResult.count,
|
|
221
|
+
extracted: captureResult.extracted
|
|
222
|
+
};
|
|
223
|
+
}
|
|
150
224
|
/**
|
|
151
225
|
* Direct access to WhisperContext for advanced usage
|
|
152
226
|
*/
|
|
153
227
|
raw() {
|
|
154
228
|
return this.client;
|
|
155
229
|
}
|
|
230
|
+
extractMemoryIdsFromBulkResponse(bulkResponse) {
|
|
231
|
+
const ids = [];
|
|
232
|
+
if (Array.isArray(bulkResponse?.memories)) {
|
|
233
|
+
for (const memory of bulkResponse.memories) {
|
|
234
|
+
if (memory?.id) ids.push(memory.id);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (bulkResponse?.memory?.id) {
|
|
238
|
+
ids.push(bulkResponse.memory.id);
|
|
239
|
+
}
|
|
240
|
+
if (bulkResponse?.id) {
|
|
241
|
+
ids.push(bulkResponse.id);
|
|
242
|
+
}
|
|
243
|
+
return Array.from(new Set(ids));
|
|
244
|
+
}
|
|
156
245
|
};
|
|
157
246
|
var whisper_agent_default = Whisper;
|
|
158
247
|
|
|
248
|
+
// ../src/sdk/middleware.ts
|
|
249
|
+
var WhisperAgentMiddleware = class {
|
|
250
|
+
whisper;
|
|
251
|
+
promptBuilder;
|
|
252
|
+
constructor(config) {
|
|
253
|
+
this.whisper = new Whisper(config);
|
|
254
|
+
this.promptBuilder = config.promptBuilder || (({ context, userMessage }) => {
|
|
255
|
+
if (!context) return userMessage;
|
|
256
|
+
return `${context}
|
|
257
|
+
|
|
258
|
+
User: ${userMessage}`;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
async beforeTurn(params) {
|
|
262
|
+
const contextResult = await this.whisper.getContext(params.userMessage, {
|
|
263
|
+
userId: params.userId,
|
|
264
|
+
sessionId: params.sessionId,
|
|
265
|
+
project: params.project,
|
|
266
|
+
limit: params.contextLimit
|
|
267
|
+
});
|
|
268
|
+
const prompt = this.promptBuilder({
|
|
269
|
+
context: contextResult.context,
|
|
270
|
+
userMessage: params.userMessage
|
|
271
|
+
});
|
|
272
|
+
return {
|
|
273
|
+
prompt,
|
|
274
|
+
context: contextResult.context,
|
|
275
|
+
contextCount: contextResult.count
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
async afterTurn(params) {
|
|
279
|
+
return this.whisper.captureSession(
|
|
280
|
+
[
|
|
281
|
+
{ role: "user", content: params.userMessage },
|
|
282
|
+
{ role: "assistant", content: params.assistantMessage }
|
|
283
|
+
],
|
|
284
|
+
{
|
|
285
|
+
userId: params.userId,
|
|
286
|
+
sessionId: params.sessionId,
|
|
287
|
+
project: params.project
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
async wrapGenerate(params) {
|
|
292
|
+
const before = await this.beforeTurn(params);
|
|
293
|
+
const response = await params.generate(before.prompt);
|
|
294
|
+
const after = await this.afterTurn({
|
|
295
|
+
userMessage: params.userMessage,
|
|
296
|
+
assistantMessage: response,
|
|
297
|
+
userId: params.userId,
|
|
298
|
+
sessionId: params.sessionId,
|
|
299
|
+
project: params.project
|
|
300
|
+
});
|
|
301
|
+
return {
|
|
302
|
+
response,
|
|
303
|
+
prompt: before.prompt,
|
|
304
|
+
context: before.context,
|
|
305
|
+
contextCount: before.contextCount,
|
|
306
|
+
extracted: after.extracted
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
raw() {
|
|
310
|
+
return this.whisper;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
function createAgentMiddleware(config) {
|
|
314
|
+
return new WhisperAgentMiddleware(config);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ../src/sdk/graph-utils.ts
|
|
318
|
+
function sanitizeId(id) {
|
|
319
|
+
return `n_${id.replace(/[^a-zA-Z0-9_]/g, "_")}`;
|
|
320
|
+
}
|
|
321
|
+
function shortLabel(input, max = 48) {
|
|
322
|
+
const text = (input || "").replace(/\s+/g, " ").trim();
|
|
323
|
+
if (text.length <= max) return text;
|
|
324
|
+
return `${text.slice(0, max - 3)}...`;
|
|
325
|
+
}
|
|
326
|
+
function memoryGraphToMermaid(graph) {
|
|
327
|
+
const lines = ["flowchart LR"];
|
|
328
|
+
for (const node of graph.nodes || []) {
|
|
329
|
+
const sid = sanitizeId(node.id);
|
|
330
|
+
const label = shortLabel(node.label || node.id);
|
|
331
|
+
lines.push(` ${sid}["${label.replace(/"/g, '\\"')}"]`);
|
|
332
|
+
}
|
|
333
|
+
for (const edge of graph.edges || []) {
|
|
334
|
+
const s = sanitizeId(edge.source);
|
|
335
|
+
const t = sanitizeId(edge.target);
|
|
336
|
+
const rel = shortLabel(edge.type || "rel", 18).replace(/"/g, '\\"');
|
|
337
|
+
lines.push(` ${s} -->|${rel}| ${t}`);
|
|
338
|
+
}
|
|
339
|
+
return lines.join("\n");
|
|
340
|
+
}
|
|
341
|
+
|
|
159
342
|
// ../src/sdk/index.ts
|
|
160
343
|
var WhisperError = class extends Error {
|
|
161
344
|
code;
|
|
@@ -186,11 +369,24 @@ function getBackoffDelay(attempt, base, max) {
|
|
|
186
369
|
function isLikelyProjectId(projectRef) {
|
|
187
370
|
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);
|
|
188
371
|
}
|
|
372
|
+
function normalizeBaseUrl(url) {
|
|
373
|
+
let normalized = url.trim().replace(/\/+$/, "");
|
|
374
|
+
normalized = normalized.replace(/\/api\/v1$/i, "");
|
|
375
|
+
normalized = normalized.replace(/\/v1$/i, "");
|
|
376
|
+
normalized = normalized.replace(/\/api$/i, "");
|
|
377
|
+
return normalized;
|
|
378
|
+
}
|
|
379
|
+
function normalizeEndpoint(endpoint) {
|
|
380
|
+
const withLeadingSlash = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
381
|
+
if (/^\/api\/v1(\/|$)/i.test(withLeadingSlash)) {
|
|
382
|
+
return withLeadingSlash.replace(/^\/api/i, "");
|
|
383
|
+
}
|
|
384
|
+
return withLeadingSlash;
|
|
385
|
+
}
|
|
189
386
|
var WhisperContext = class _WhisperContext {
|
|
190
387
|
apiKey;
|
|
191
388
|
baseUrl;
|
|
192
389
|
defaultProject;
|
|
193
|
-
orgId;
|
|
194
390
|
timeoutMs;
|
|
195
391
|
retryConfig;
|
|
196
392
|
projectRefToId = /* @__PURE__ */ new Map();
|
|
@@ -204,9 +400,8 @@ var WhisperContext = class _WhisperContext {
|
|
|
204
400
|
});
|
|
205
401
|
}
|
|
206
402
|
this.apiKey = config.apiKey;
|
|
207
|
-
this.baseUrl = config.baseUrl || "https://context.usewhisper.dev";
|
|
403
|
+
this.baseUrl = normalizeBaseUrl(config.baseUrl || "https://context.usewhisper.dev");
|
|
208
404
|
this.defaultProject = config.project;
|
|
209
|
-
this.orgId = config.orgId;
|
|
210
405
|
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
211
406
|
this.retryConfig = {
|
|
212
407
|
maxAttempts: config.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
|
@@ -219,7 +414,6 @@ var WhisperContext = class _WhisperContext {
|
|
|
219
414
|
apiKey: this.apiKey,
|
|
220
415
|
baseUrl: this.baseUrl,
|
|
221
416
|
project,
|
|
222
|
-
orgId: this.orgId,
|
|
223
417
|
timeoutMs: this.timeoutMs,
|
|
224
418
|
retry: this.retryConfig
|
|
225
419
|
});
|
|
@@ -336,20 +530,28 @@ var WhisperContext = class _WhisperContext {
|
|
|
336
530
|
}
|
|
337
531
|
async request(endpoint, options = {}) {
|
|
338
532
|
const maxAttempts = Math.max(1, this.retryConfig.maxAttempts);
|
|
533
|
+
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
|
339
534
|
let lastError;
|
|
340
535
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
341
536
|
const controller = new AbortController();
|
|
342
537
|
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
343
538
|
try {
|
|
344
|
-
const
|
|
539
|
+
const headers = {
|
|
540
|
+
"Content-Type": "application/json",
|
|
541
|
+
...options.headers
|
|
542
|
+
};
|
|
543
|
+
const hasAuthHeader = Object.keys(headers).some((k) => k.toLowerCase() === "authorization");
|
|
544
|
+
const hasApiKeyHeader = Object.keys(headers).some((k) => k.toLowerCase() === "x-api-key");
|
|
545
|
+
if (!hasAuthHeader) {
|
|
546
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
547
|
+
}
|
|
548
|
+
if (!hasApiKeyHeader) {
|
|
549
|
+
headers["X-API-Key"] = this.apiKey;
|
|
550
|
+
}
|
|
551
|
+
const response = await fetch(`${this.baseUrl}${normalizedEndpoint}`, {
|
|
345
552
|
...options,
|
|
346
553
|
signal: controller.signal,
|
|
347
|
-
headers
|
|
348
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
349
|
-
"Content-Type": "application/json",
|
|
350
|
-
...this.orgId ? { "X-Whisper-Org-Id": this.orgId } : {},
|
|
351
|
-
...options.headers
|
|
352
|
-
}
|
|
554
|
+
headers
|
|
353
555
|
});
|
|
354
556
|
clearTimeout(timeout);
|
|
355
557
|
if (!response.ok) {
|
|
@@ -538,6 +740,34 @@ var WhisperContext = class _WhisperContext {
|
|
|
538
740
|
return { id, success: true, path: "legacy", fallback_used: true };
|
|
539
741
|
});
|
|
540
742
|
}
|
|
743
|
+
async addMemoriesBulk(params) {
|
|
744
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
745
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/bulk", {
|
|
746
|
+
method: "POST",
|
|
747
|
+
body: JSON.stringify({ ...params, project })
|
|
748
|
+
}));
|
|
749
|
+
}
|
|
750
|
+
async extractMemories(params) {
|
|
751
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
752
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract", {
|
|
753
|
+
method: "POST",
|
|
754
|
+
body: JSON.stringify({ ...params, project })
|
|
755
|
+
}));
|
|
756
|
+
}
|
|
757
|
+
async extractSessionMemories(params) {
|
|
758
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
759
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract/session", {
|
|
760
|
+
method: "POST",
|
|
761
|
+
body: JSON.stringify({
|
|
762
|
+
...params,
|
|
763
|
+
project,
|
|
764
|
+
messages: params.messages.map((m) => ({
|
|
765
|
+
...m,
|
|
766
|
+
timestamp: m.timestamp || (/* @__PURE__ */ new Date()).toISOString()
|
|
767
|
+
}))
|
|
768
|
+
})
|
|
769
|
+
}));
|
|
770
|
+
}
|
|
541
771
|
async searchMemories(params) {
|
|
542
772
|
const projectRef = this.getRequiredProject(params.project);
|
|
543
773
|
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/search", {
|
|
@@ -610,6 +840,26 @@ var WhisperContext = class _WhisperContext {
|
|
|
610
840
|
async getMemoryRelations(memoryId) {
|
|
611
841
|
return this.request(`/v1/memory/${memoryId}/relations`);
|
|
612
842
|
}
|
|
843
|
+
async getMemoryGraph(params) {
|
|
844
|
+
const project = await this.resolveProjectId(this.getRequiredProject(params.project));
|
|
845
|
+
const query = new URLSearchParams({
|
|
846
|
+
project,
|
|
847
|
+
...params.user_id && { user_id: params.user_id },
|
|
848
|
+
...params.session_id && { session_id: params.session_id },
|
|
849
|
+
...params.include_inactive !== void 0 && { include_inactive: String(params.include_inactive) },
|
|
850
|
+
...params.limit !== void 0 && { limit: String(params.limit) }
|
|
851
|
+
});
|
|
852
|
+
return this.request(`/v1/memory/graph?${query}`);
|
|
853
|
+
}
|
|
854
|
+
async getConversationGraph(params) {
|
|
855
|
+
const project = await this.resolveProjectId(this.getRequiredProject(params.project));
|
|
856
|
+
const query = new URLSearchParams({
|
|
857
|
+
project,
|
|
858
|
+
...params.include_inactive !== void 0 && { include_inactive: String(params.include_inactive) },
|
|
859
|
+
...params.limit !== void 0 && { limit: String(params.limit) }
|
|
860
|
+
});
|
|
861
|
+
return this.request(`/v1/memory/graph/conversation/${params.session_id}?${query}`);
|
|
862
|
+
}
|
|
613
863
|
async oracleSearch(params) {
|
|
614
864
|
const project = await this.resolveProjectId(this.getRequiredProject(params.project));
|
|
615
865
|
return this.request("/v1/oracle/search", {
|
|
@@ -734,6 +984,9 @@ var WhisperContext = class _WhisperContext {
|
|
|
734
984
|
};
|
|
735
985
|
memory = {
|
|
736
986
|
add: (params) => this.addMemory(params),
|
|
987
|
+
addBulk: (params) => this.addMemoriesBulk(params),
|
|
988
|
+
extract: (params) => this.extractMemories(params),
|
|
989
|
+
extractSession: (params) => this.extractSessionMemories(params),
|
|
737
990
|
search: (params) => this.searchMemories(params),
|
|
738
991
|
searchSOTA: (params) => this.searchMemoriesSOTA(params),
|
|
739
992
|
ingestSession: (params) => this.ingestSession(params),
|
|
@@ -743,6 +996,8 @@ var WhisperContext = class _WhisperContext {
|
|
|
743
996
|
update: (memoryId, params) => this.updateMemory(memoryId, params),
|
|
744
997
|
delete: (memoryId) => this.deleteMemory(memoryId),
|
|
745
998
|
getRelations: (memoryId) => this.getMemoryRelations(memoryId),
|
|
999
|
+
getGraph: (params) => this.getMemoryGraph(params),
|
|
1000
|
+
getConversationGraph: (params) => this.getConversationGraph(params),
|
|
746
1001
|
consolidate: (params) => this.consolidateMemories(params),
|
|
747
1002
|
updateDecay: (params) => this.updateImportanceDecay(params),
|
|
748
1003
|
getImportanceStats: (project) => this.getImportanceStats(project)
|
|
@@ -772,8 +1027,11 @@ var WhisperContext = class _WhisperContext {
|
|
|
772
1027
|
var index_default = WhisperContext;
|
|
773
1028
|
export {
|
|
774
1029
|
Whisper,
|
|
1030
|
+
WhisperAgentMiddleware,
|
|
775
1031
|
WhisperContext,
|
|
776
1032
|
whisper_agent_default as WhisperDefault,
|
|
777
1033
|
WhisperError,
|
|
778
|
-
|
|
1034
|
+
createAgentMiddleware,
|
|
1035
|
+
index_default as default,
|
|
1036
|
+
memoryGraphToMermaid
|
|
779
1037
|
};
|