@usewhisper/sdk 2.0.0 → 2.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/README.md +2 -2
- package/index.d.mts +168 -11
- package/index.d.ts +168 -11
- package/index.js +227 -15
- package/index.mjs +224 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npm install @usewhisper/sdk
|
|
|
14
14
|
import { WhisperContext } from '@usewhisper/sdk';
|
|
15
15
|
|
|
16
16
|
const whisper = new WhisperContext({
|
|
17
|
-
apiKey: '
|
|
17
|
+
apiKey: 'wsk_your_api_key_here'
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
// Create a project
|
|
@@ -48,7 +48,7 @@ Get your API key from the [Whisper dashboard](https://usewhisper.dev/dashboard):
|
|
|
48
48
|
|
|
49
49
|
```typescript
|
|
50
50
|
const whisper = new WhisperContext({
|
|
51
|
-
apiKey: '
|
|
51
|
+
apiKey: 'wsk_...', // Your API key
|
|
52
52
|
baseUrl: 'https://context.usewhisper.dev' // Optional, defaults to production
|
|
53
53
|
});
|
|
54
54
|
```
|
package/index.d.mts
CHANGED
|
@@ -24,12 +24,33 @@ interface WhisperOptions extends WhisperConfig {
|
|
|
24
24
|
* Default: "Relevant context:"
|
|
25
25
|
*/
|
|
26
26
|
contextPrefix?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Extract structured memories before writing.
|
|
29
|
+
* Default: true
|
|
30
|
+
*/
|
|
31
|
+
autoExtract?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Minimum extraction confidence for auto-write.
|
|
34
|
+
* Default: 0.65
|
|
35
|
+
*/
|
|
36
|
+
autoExtractMinConfidence?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Maximum extracted memories to write per remember/capture call.
|
|
39
|
+
* Default: 5
|
|
40
|
+
*/
|
|
41
|
+
maxMemoriesPerCapture?: number;
|
|
27
42
|
}
|
|
28
43
|
interface ContextResult {
|
|
29
44
|
context: string;
|
|
30
45
|
results: QueryResult["results"];
|
|
31
46
|
count: number;
|
|
32
47
|
}
|
|
48
|
+
interface RememberResult {
|
|
49
|
+
success: boolean;
|
|
50
|
+
memoryId?: string;
|
|
51
|
+
memoryIds?: string[];
|
|
52
|
+
extracted?: number;
|
|
53
|
+
}
|
|
33
54
|
/**
|
|
34
55
|
* Simple, transparent memory layer
|
|
35
56
|
*
|
|
@@ -114,10 +135,7 @@ declare class Whisper {
|
|
|
114
135
|
userId?: string;
|
|
115
136
|
sessionId?: string;
|
|
116
137
|
project?: string;
|
|
117
|
-
}): Promise<
|
|
118
|
-
success: boolean;
|
|
119
|
-
memoryId?: string;
|
|
120
|
-
}>;
|
|
138
|
+
}): Promise<RememberResult>;
|
|
121
139
|
/**
|
|
122
140
|
* Alias for remember() - same thing
|
|
123
141
|
*/
|
|
@@ -125,10 +143,7 @@ declare class Whisper {
|
|
|
125
143
|
userId?: string;
|
|
126
144
|
sessionId?: string;
|
|
127
145
|
project?: string;
|
|
128
|
-
}): Promise<
|
|
129
|
-
success: boolean;
|
|
130
|
-
memoryId?: string;
|
|
131
|
-
}>;
|
|
146
|
+
}): Promise<RememberResult>;
|
|
132
147
|
/**
|
|
133
148
|
* Capture from multiple messages (e.g., full conversation)
|
|
134
149
|
*/
|
|
@@ -143,11 +158,86 @@ declare class Whisper {
|
|
|
143
158
|
success: boolean;
|
|
144
159
|
extracted: number;
|
|
145
160
|
}>;
|
|
161
|
+
/**
|
|
162
|
+
* Run a full agent turn with automatic memory read (before) + write (after).
|
|
163
|
+
*/
|
|
164
|
+
runTurn(params: {
|
|
165
|
+
userMessage: string;
|
|
166
|
+
generate: (prompt: string) => Promise<string>;
|
|
167
|
+
userId?: string;
|
|
168
|
+
sessionId?: string;
|
|
169
|
+
project?: string;
|
|
170
|
+
limit?: number;
|
|
171
|
+
}): Promise<{
|
|
172
|
+
response: string;
|
|
173
|
+
context: string;
|
|
174
|
+
count: number;
|
|
175
|
+
extracted: number;
|
|
176
|
+
}>;
|
|
146
177
|
/**
|
|
147
178
|
* Direct access to WhisperContext for advanced usage
|
|
148
179
|
*/
|
|
149
180
|
raw(): WhisperContext;
|
|
181
|
+
private extractMemoryIdsFromBulkResponse;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
interface AgentMiddlewareConfig extends WhisperOptions {
|
|
185
|
+
/**
|
|
186
|
+
* Build the prompt passed to the model.
|
|
187
|
+
*/
|
|
188
|
+
promptBuilder?: (params: {
|
|
189
|
+
context: string;
|
|
190
|
+
userMessage: string;
|
|
191
|
+
}) => string;
|
|
192
|
+
}
|
|
193
|
+
interface AgentTurnParams {
|
|
194
|
+
userMessage: string;
|
|
195
|
+
userId?: string;
|
|
196
|
+
sessionId?: string;
|
|
197
|
+
project?: string;
|
|
198
|
+
contextLimit?: number;
|
|
199
|
+
}
|
|
200
|
+
interface AgentTurnResult {
|
|
201
|
+
prompt: string;
|
|
202
|
+
context: string;
|
|
203
|
+
contextCount: number;
|
|
150
204
|
}
|
|
205
|
+
interface WrappedGenerateResult {
|
|
206
|
+
response: string;
|
|
207
|
+
prompt: string;
|
|
208
|
+
context: string;
|
|
209
|
+
contextCount: number;
|
|
210
|
+
extracted: number;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Drop-in middleware for existing AI agents.
|
|
214
|
+
*
|
|
215
|
+
* Typical flow:
|
|
216
|
+
* 1) beforeTurn -> retrieve context
|
|
217
|
+
* 2) call your model
|
|
218
|
+
* 3) afterTurn -> store memories
|
|
219
|
+
*/
|
|
220
|
+
declare class WhisperAgentMiddleware {
|
|
221
|
+
private readonly whisper;
|
|
222
|
+
private readonly promptBuilder;
|
|
223
|
+
constructor(config: AgentMiddlewareConfig);
|
|
224
|
+
beforeTurn(params: AgentTurnParams): Promise<AgentTurnResult>;
|
|
225
|
+
afterTurn(params: {
|
|
226
|
+
userMessage: string;
|
|
227
|
+
assistantMessage: string;
|
|
228
|
+
userId?: string;
|
|
229
|
+
sessionId?: string;
|
|
230
|
+
project?: string;
|
|
231
|
+
}): Promise<{
|
|
232
|
+
success: boolean;
|
|
233
|
+
extracted: number;
|
|
234
|
+
}>;
|
|
235
|
+
wrapGenerate(params: AgentTurnParams & {
|
|
236
|
+
generate: (prompt: string) => Promise<string>;
|
|
237
|
+
}): Promise<WrappedGenerateResult>;
|
|
238
|
+
raw(): Whisper;
|
|
239
|
+
}
|
|
240
|
+
declare function createAgentMiddleware(config: AgentMiddlewareConfig): WhisperAgentMiddleware;
|
|
151
241
|
|
|
152
242
|
/**
|
|
153
243
|
* Whisper Context SDK
|
|
@@ -157,7 +247,6 @@ interface WhisperConfig {
|
|
|
157
247
|
apiKey: string;
|
|
158
248
|
baseUrl?: string;
|
|
159
249
|
project?: string;
|
|
160
|
-
orgId?: string;
|
|
161
250
|
timeoutMs?: number;
|
|
162
251
|
retry?: {
|
|
163
252
|
maxAttempts?: number;
|
|
@@ -246,6 +335,23 @@ interface Memory {
|
|
|
246
335
|
createdAt: string;
|
|
247
336
|
updatedAt: string;
|
|
248
337
|
}
|
|
338
|
+
type MemoryKind = "factual" | "preference" | "event" | "relationship" | "opinion" | "goal" | "instruction";
|
|
339
|
+
interface ExtractedMemory {
|
|
340
|
+
content: string;
|
|
341
|
+
memoryType: MemoryKind;
|
|
342
|
+
entityMentions: string[];
|
|
343
|
+
eventDate: string | null;
|
|
344
|
+
confidence: number;
|
|
345
|
+
reasoning?: string;
|
|
346
|
+
inferred?: boolean;
|
|
347
|
+
}
|
|
348
|
+
interface MemoryExtractionResult {
|
|
349
|
+
explicit: ExtractedMemory[];
|
|
350
|
+
implicit: ExtractedMemory[];
|
|
351
|
+
all: ExtractedMemory[];
|
|
352
|
+
extractionMethod: "pattern" | "inference" | "hybrid" | "skipped";
|
|
353
|
+
latencyMs: number;
|
|
354
|
+
}
|
|
249
355
|
type WhisperErrorCode = "INVALID_API_KEY" | "PROJECT_NOT_FOUND" | "PROJECT_AMBIGUOUS" | "RATE_LIMITED" | "TEMPORARY_UNAVAILABLE" | "NETWORK_ERROR" | "TIMEOUT" | "REQUEST_FAILED" | "MISSING_PROJECT";
|
|
250
356
|
declare class WhisperError extends Error {
|
|
251
357
|
code: WhisperErrorCode;
|
|
@@ -264,7 +370,6 @@ declare class WhisperContext {
|
|
|
264
370
|
private apiKey;
|
|
265
371
|
private baseUrl;
|
|
266
372
|
private defaultProject?;
|
|
267
|
-
private orgId?;
|
|
268
373
|
private timeoutMs;
|
|
269
374
|
private retryConfig;
|
|
270
375
|
private projectRefToId;
|
|
@@ -335,6 +440,51 @@ declare class WhisperContext {
|
|
|
335
440
|
path: "sota" | "legacy";
|
|
336
441
|
fallback_used: boolean;
|
|
337
442
|
}>;
|
|
443
|
+
addMemoriesBulk(params: {
|
|
444
|
+
project?: string;
|
|
445
|
+
memories: Array<{
|
|
446
|
+
content: string;
|
|
447
|
+
memory_type?: MemoryKind | "episodic" | "semantic" | "procedural";
|
|
448
|
+
user_id?: string;
|
|
449
|
+
session_id?: string;
|
|
450
|
+
agent_id?: string;
|
|
451
|
+
importance?: number;
|
|
452
|
+
confidence?: number;
|
|
453
|
+
metadata?: Record<string, any>;
|
|
454
|
+
entity_mentions?: string[];
|
|
455
|
+
document_date?: string;
|
|
456
|
+
event_date?: string;
|
|
457
|
+
}>;
|
|
458
|
+
namespace?: string;
|
|
459
|
+
tags?: string[];
|
|
460
|
+
async?: boolean;
|
|
461
|
+
webhook_url?: string;
|
|
462
|
+
}): Promise<any>;
|
|
463
|
+
extractMemories(params: {
|
|
464
|
+
project?: string;
|
|
465
|
+
message: string;
|
|
466
|
+
context?: string;
|
|
467
|
+
session_id?: string;
|
|
468
|
+
user_id?: string;
|
|
469
|
+
enable_pattern?: boolean;
|
|
470
|
+
enable_inference?: boolean;
|
|
471
|
+
min_confidence?: number;
|
|
472
|
+
}): Promise<MemoryExtractionResult>;
|
|
473
|
+
extractSessionMemories(params: {
|
|
474
|
+
project?: string;
|
|
475
|
+
user_id?: string;
|
|
476
|
+
messages: Array<{
|
|
477
|
+
role: "user" | "assistant" | "system";
|
|
478
|
+
content: string;
|
|
479
|
+
timestamp?: string;
|
|
480
|
+
}>;
|
|
481
|
+
enable_pattern?: boolean;
|
|
482
|
+
enable_inference?: boolean;
|
|
483
|
+
}): Promise<{
|
|
484
|
+
memories: ExtractedMemory[];
|
|
485
|
+
count: number;
|
|
486
|
+
latencyMs: number;
|
|
487
|
+
}>;
|
|
338
488
|
searchMemories(params: {
|
|
339
489
|
project?: string;
|
|
340
490
|
query: string;
|
|
@@ -641,6 +791,13 @@ declare class WhisperContext {
|
|
|
641
791
|
path: "sota" | "legacy";
|
|
642
792
|
fallback_used: boolean;
|
|
643
793
|
}>;
|
|
794
|
+
addBulk: (params: Parameters<WhisperContext["addMemoriesBulk"]>[0]) => Promise<any>;
|
|
795
|
+
extract: (params: Parameters<WhisperContext["extractMemories"]>[0]) => Promise<MemoryExtractionResult>;
|
|
796
|
+
extractSession: (params: Parameters<WhisperContext["extractSessionMemories"]>[0]) => Promise<{
|
|
797
|
+
memories: ExtractedMemory[];
|
|
798
|
+
count: number;
|
|
799
|
+
latencyMs: number;
|
|
800
|
+
}>;
|
|
644
801
|
search: (params: Parameters<WhisperContext["searchMemories"]>[0]) => Promise<any>;
|
|
645
802
|
searchSOTA: (params: Parameters<WhisperContext["searchMemoriesSOTA"]>[0]) => Promise<any>;
|
|
646
803
|
ingestSession: (params: Parameters<WhisperContext["ingestSession"]>[0]) => Promise<{
|
|
@@ -762,4 +919,4 @@ declare class WhisperContext {
|
|
|
762
919
|
};
|
|
763
920
|
}
|
|
764
921
|
|
|
765
|
-
export { type Memory, type Project, type QueryParams, type QueryResult, type Source, Whisper, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, WhisperContext as default };
|
|
922
|
+
export { type ExtractedMemory, type Memory, type MemoryExtractionResult, type MemoryKind, type Project, type QueryParams, type QueryResult, type Source, Whisper, WhisperAgentMiddleware, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, createAgentMiddleware, WhisperContext as default };
|
package/index.d.ts
CHANGED
|
@@ -24,12 +24,33 @@ interface WhisperOptions extends WhisperConfig {
|
|
|
24
24
|
* Default: "Relevant context:"
|
|
25
25
|
*/
|
|
26
26
|
contextPrefix?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Extract structured memories before writing.
|
|
29
|
+
* Default: true
|
|
30
|
+
*/
|
|
31
|
+
autoExtract?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Minimum extraction confidence for auto-write.
|
|
34
|
+
* Default: 0.65
|
|
35
|
+
*/
|
|
36
|
+
autoExtractMinConfidence?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Maximum extracted memories to write per remember/capture call.
|
|
39
|
+
* Default: 5
|
|
40
|
+
*/
|
|
41
|
+
maxMemoriesPerCapture?: number;
|
|
27
42
|
}
|
|
28
43
|
interface ContextResult {
|
|
29
44
|
context: string;
|
|
30
45
|
results: QueryResult["results"];
|
|
31
46
|
count: number;
|
|
32
47
|
}
|
|
48
|
+
interface RememberResult {
|
|
49
|
+
success: boolean;
|
|
50
|
+
memoryId?: string;
|
|
51
|
+
memoryIds?: string[];
|
|
52
|
+
extracted?: number;
|
|
53
|
+
}
|
|
33
54
|
/**
|
|
34
55
|
* Simple, transparent memory layer
|
|
35
56
|
*
|
|
@@ -114,10 +135,7 @@ declare class Whisper {
|
|
|
114
135
|
userId?: string;
|
|
115
136
|
sessionId?: string;
|
|
116
137
|
project?: string;
|
|
117
|
-
}): Promise<
|
|
118
|
-
success: boolean;
|
|
119
|
-
memoryId?: string;
|
|
120
|
-
}>;
|
|
138
|
+
}): Promise<RememberResult>;
|
|
121
139
|
/**
|
|
122
140
|
* Alias for remember() - same thing
|
|
123
141
|
*/
|
|
@@ -125,10 +143,7 @@ declare class Whisper {
|
|
|
125
143
|
userId?: string;
|
|
126
144
|
sessionId?: string;
|
|
127
145
|
project?: string;
|
|
128
|
-
}): Promise<
|
|
129
|
-
success: boolean;
|
|
130
|
-
memoryId?: string;
|
|
131
|
-
}>;
|
|
146
|
+
}): Promise<RememberResult>;
|
|
132
147
|
/**
|
|
133
148
|
* Capture from multiple messages (e.g., full conversation)
|
|
134
149
|
*/
|
|
@@ -143,11 +158,86 @@ declare class Whisper {
|
|
|
143
158
|
success: boolean;
|
|
144
159
|
extracted: number;
|
|
145
160
|
}>;
|
|
161
|
+
/**
|
|
162
|
+
* Run a full agent turn with automatic memory read (before) + write (after).
|
|
163
|
+
*/
|
|
164
|
+
runTurn(params: {
|
|
165
|
+
userMessage: string;
|
|
166
|
+
generate: (prompt: string) => Promise<string>;
|
|
167
|
+
userId?: string;
|
|
168
|
+
sessionId?: string;
|
|
169
|
+
project?: string;
|
|
170
|
+
limit?: number;
|
|
171
|
+
}): Promise<{
|
|
172
|
+
response: string;
|
|
173
|
+
context: string;
|
|
174
|
+
count: number;
|
|
175
|
+
extracted: number;
|
|
176
|
+
}>;
|
|
146
177
|
/**
|
|
147
178
|
* Direct access to WhisperContext for advanced usage
|
|
148
179
|
*/
|
|
149
180
|
raw(): WhisperContext;
|
|
181
|
+
private extractMemoryIdsFromBulkResponse;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
interface AgentMiddlewareConfig extends WhisperOptions {
|
|
185
|
+
/**
|
|
186
|
+
* Build the prompt passed to the model.
|
|
187
|
+
*/
|
|
188
|
+
promptBuilder?: (params: {
|
|
189
|
+
context: string;
|
|
190
|
+
userMessage: string;
|
|
191
|
+
}) => string;
|
|
192
|
+
}
|
|
193
|
+
interface AgentTurnParams {
|
|
194
|
+
userMessage: string;
|
|
195
|
+
userId?: string;
|
|
196
|
+
sessionId?: string;
|
|
197
|
+
project?: string;
|
|
198
|
+
contextLimit?: number;
|
|
199
|
+
}
|
|
200
|
+
interface AgentTurnResult {
|
|
201
|
+
prompt: string;
|
|
202
|
+
context: string;
|
|
203
|
+
contextCount: number;
|
|
150
204
|
}
|
|
205
|
+
interface WrappedGenerateResult {
|
|
206
|
+
response: string;
|
|
207
|
+
prompt: string;
|
|
208
|
+
context: string;
|
|
209
|
+
contextCount: number;
|
|
210
|
+
extracted: number;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Drop-in middleware for existing AI agents.
|
|
214
|
+
*
|
|
215
|
+
* Typical flow:
|
|
216
|
+
* 1) beforeTurn -> retrieve context
|
|
217
|
+
* 2) call your model
|
|
218
|
+
* 3) afterTurn -> store memories
|
|
219
|
+
*/
|
|
220
|
+
declare class WhisperAgentMiddleware {
|
|
221
|
+
private readonly whisper;
|
|
222
|
+
private readonly promptBuilder;
|
|
223
|
+
constructor(config: AgentMiddlewareConfig);
|
|
224
|
+
beforeTurn(params: AgentTurnParams): Promise<AgentTurnResult>;
|
|
225
|
+
afterTurn(params: {
|
|
226
|
+
userMessage: string;
|
|
227
|
+
assistantMessage: string;
|
|
228
|
+
userId?: string;
|
|
229
|
+
sessionId?: string;
|
|
230
|
+
project?: string;
|
|
231
|
+
}): Promise<{
|
|
232
|
+
success: boolean;
|
|
233
|
+
extracted: number;
|
|
234
|
+
}>;
|
|
235
|
+
wrapGenerate(params: AgentTurnParams & {
|
|
236
|
+
generate: (prompt: string) => Promise<string>;
|
|
237
|
+
}): Promise<WrappedGenerateResult>;
|
|
238
|
+
raw(): Whisper;
|
|
239
|
+
}
|
|
240
|
+
declare function createAgentMiddleware(config: AgentMiddlewareConfig): WhisperAgentMiddleware;
|
|
151
241
|
|
|
152
242
|
/**
|
|
153
243
|
* Whisper Context SDK
|
|
@@ -157,7 +247,6 @@ interface WhisperConfig {
|
|
|
157
247
|
apiKey: string;
|
|
158
248
|
baseUrl?: string;
|
|
159
249
|
project?: string;
|
|
160
|
-
orgId?: string;
|
|
161
250
|
timeoutMs?: number;
|
|
162
251
|
retry?: {
|
|
163
252
|
maxAttempts?: number;
|
|
@@ -246,6 +335,23 @@ interface Memory {
|
|
|
246
335
|
createdAt: string;
|
|
247
336
|
updatedAt: string;
|
|
248
337
|
}
|
|
338
|
+
type MemoryKind = "factual" | "preference" | "event" | "relationship" | "opinion" | "goal" | "instruction";
|
|
339
|
+
interface ExtractedMemory {
|
|
340
|
+
content: string;
|
|
341
|
+
memoryType: MemoryKind;
|
|
342
|
+
entityMentions: string[];
|
|
343
|
+
eventDate: string | null;
|
|
344
|
+
confidence: number;
|
|
345
|
+
reasoning?: string;
|
|
346
|
+
inferred?: boolean;
|
|
347
|
+
}
|
|
348
|
+
interface MemoryExtractionResult {
|
|
349
|
+
explicit: ExtractedMemory[];
|
|
350
|
+
implicit: ExtractedMemory[];
|
|
351
|
+
all: ExtractedMemory[];
|
|
352
|
+
extractionMethod: "pattern" | "inference" | "hybrid" | "skipped";
|
|
353
|
+
latencyMs: number;
|
|
354
|
+
}
|
|
249
355
|
type WhisperErrorCode = "INVALID_API_KEY" | "PROJECT_NOT_FOUND" | "PROJECT_AMBIGUOUS" | "RATE_LIMITED" | "TEMPORARY_UNAVAILABLE" | "NETWORK_ERROR" | "TIMEOUT" | "REQUEST_FAILED" | "MISSING_PROJECT";
|
|
250
356
|
declare class WhisperError extends Error {
|
|
251
357
|
code: WhisperErrorCode;
|
|
@@ -264,7 +370,6 @@ declare class WhisperContext {
|
|
|
264
370
|
private apiKey;
|
|
265
371
|
private baseUrl;
|
|
266
372
|
private defaultProject?;
|
|
267
|
-
private orgId?;
|
|
268
373
|
private timeoutMs;
|
|
269
374
|
private retryConfig;
|
|
270
375
|
private projectRefToId;
|
|
@@ -335,6 +440,51 @@ declare class WhisperContext {
|
|
|
335
440
|
path: "sota" | "legacy";
|
|
336
441
|
fallback_used: boolean;
|
|
337
442
|
}>;
|
|
443
|
+
addMemoriesBulk(params: {
|
|
444
|
+
project?: string;
|
|
445
|
+
memories: Array<{
|
|
446
|
+
content: string;
|
|
447
|
+
memory_type?: MemoryKind | "episodic" | "semantic" | "procedural";
|
|
448
|
+
user_id?: string;
|
|
449
|
+
session_id?: string;
|
|
450
|
+
agent_id?: string;
|
|
451
|
+
importance?: number;
|
|
452
|
+
confidence?: number;
|
|
453
|
+
metadata?: Record<string, any>;
|
|
454
|
+
entity_mentions?: string[];
|
|
455
|
+
document_date?: string;
|
|
456
|
+
event_date?: string;
|
|
457
|
+
}>;
|
|
458
|
+
namespace?: string;
|
|
459
|
+
tags?: string[];
|
|
460
|
+
async?: boolean;
|
|
461
|
+
webhook_url?: string;
|
|
462
|
+
}): Promise<any>;
|
|
463
|
+
extractMemories(params: {
|
|
464
|
+
project?: string;
|
|
465
|
+
message: string;
|
|
466
|
+
context?: string;
|
|
467
|
+
session_id?: string;
|
|
468
|
+
user_id?: string;
|
|
469
|
+
enable_pattern?: boolean;
|
|
470
|
+
enable_inference?: boolean;
|
|
471
|
+
min_confidence?: number;
|
|
472
|
+
}): Promise<MemoryExtractionResult>;
|
|
473
|
+
extractSessionMemories(params: {
|
|
474
|
+
project?: string;
|
|
475
|
+
user_id?: string;
|
|
476
|
+
messages: Array<{
|
|
477
|
+
role: "user" | "assistant" | "system";
|
|
478
|
+
content: string;
|
|
479
|
+
timestamp?: string;
|
|
480
|
+
}>;
|
|
481
|
+
enable_pattern?: boolean;
|
|
482
|
+
enable_inference?: boolean;
|
|
483
|
+
}): Promise<{
|
|
484
|
+
memories: ExtractedMemory[];
|
|
485
|
+
count: number;
|
|
486
|
+
latencyMs: number;
|
|
487
|
+
}>;
|
|
338
488
|
searchMemories(params: {
|
|
339
489
|
project?: string;
|
|
340
490
|
query: string;
|
|
@@ -641,6 +791,13 @@ declare class WhisperContext {
|
|
|
641
791
|
path: "sota" | "legacy";
|
|
642
792
|
fallback_used: boolean;
|
|
643
793
|
}>;
|
|
794
|
+
addBulk: (params: Parameters<WhisperContext["addMemoriesBulk"]>[0]) => Promise<any>;
|
|
795
|
+
extract: (params: Parameters<WhisperContext["extractMemories"]>[0]) => Promise<MemoryExtractionResult>;
|
|
796
|
+
extractSession: (params: Parameters<WhisperContext["extractSessionMemories"]>[0]) => Promise<{
|
|
797
|
+
memories: ExtractedMemory[];
|
|
798
|
+
count: number;
|
|
799
|
+
latencyMs: number;
|
|
800
|
+
}>;
|
|
644
801
|
search: (params: Parameters<WhisperContext["searchMemories"]>[0]) => Promise<any>;
|
|
645
802
|
searchSOTA: (params: Parameters<WhisperContext["searchMemoriesSOTA"]>[0]) => Promise<any>;
|
|
646
803
|
ingestSession: (params: Parameters<WhisperContext["ingestSession"]>[0]) => Promise<{
|
|
@@ -762,4 +919,4 @@ declare class WhisperContext {
|
|
|
762
919
|
};
|
|
763
920
|
}
|
|
764
921
|
|
|
765
|
-
export { type Memory, type Project, type QueryParams, type QueryResult, type Source, Whisper, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, WhisperContext as default };
|
|
922
|
+
export { type ExtractedMemory, type Memory, type MemoryExtractionResult, type MemoryKind, type Project, type QueryParams, type QueryResult, type Source, Whisper, WhisperAgentMiddleware, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, createAgentMiddleware, WhisperContext as default };
|
package/index.js
CHANGED
|
@@ -21,9 +21,11 @@ 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,
|
|
28
|
+
createAgentMiddleware: () => createAgentMiddleware,
|
|
27
29
|
default: () => index_default
|
|
28
30
|
});
|
|
29
31
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -43,7 +45,6 @@ var Whisper = class {
|
|
|
43
45
|
baseUrl: options.baseUrl,
|
|
44
46
|
project: options.project || "default"
|
|
45
47
|
};
|
|
46
|
-
if (options.orgId) clientConfig.orgId = options.orgId;
|
|
47
48
|
if (options.timeoutMs) clientConfig.timeoutMs = options.timeoutMs;
|
|
48
49
|
if (options.retry) clientConfig.retry = options.retry;
|
|
49
50
|
this.client = new WhisperContext(clientConfig);
|
|
@@ -52,12 +53,14 @@ var Whisper = class {
|
|
|
52
53
|
apiKey: options.apiKey,
|
|
53
54
|
baseUrl: options.baseUrl || "https://context.usewhisper.dev",
|
|
54
55
|
project: options.project || "default",
|
|
55
|
-
orgId: options.orgId || "",
|
|
56
56
|
timeoutMs: options.timeoutMs || 15e3,
|
|
57
57
|
retry: finalRetry,
|
|
58
58
|
contextLimit: options.contextLimit ?? 10,
|
|
59
59
|
memoryTypes: options.memoryTypes ?? ["factual", "preference", "event", "goal", "relationship", "opinion", "instruction"],
|
|
60
|
-
contextPrefix: options.contextPrefix ?? "Relevant context:"
|
|
60
|
+
contextPrefix: options.contextPrefix ?? "Relevant context:",
|
|
61
|
+
autoExtract: options.autoExtract ?? true,
|
|
62
|
+
autoExtractMinConfidence: options.autoExtractMinConfidence ?? 0.65,
|
|
63
|
+
maxMemoriesPerCapture: options.maxMemoriesPerCapture ?? 5
|
|
61
64
|
};
|
|
62
65
|
}
|
|
63
66
|
/**
|
|
@@ -132,6 +135,47 @@ ${context}` : "",
|
|
|
132
135
|
return { success: false };
|
|
133
136
|
}
|
|
134
137
|
try {
|
|
138
|
+
if (this.options.autoExtract) {
|
|
139
|
+
const extraction = await this.client.extractMemories({
|
|
140
|
+
project: options?.project ?? this.options.project,
|
|
141
|
+
message: content,
|
|
142
|
+
user_id: options?.userId ?? this.userId,
|
|
143
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
144
|
+
enable_pattern: true,
|
|
145
|
+
enable_inference: true,
|
|
146
|
+
min_confidence: this.options.autoExtractMinConfidence
|
|
147
|
+
});
|
|
148
|
+
const extractedMemories = (extraction.all || []).filter((m) => (m.confidence || 0) >= this.options.autoExtractMinConfidence).slice(0, this.options.maxMemoriesPerCapture);
|
|
149
|
+
if (extractedMemories.length > 0) {
|
|
150
|
+
const bulk = await this.client.addMemoriesBulk({
|
|
151
|
+
project: options?.project ?? this.options.project,
|
|
152
|
+
async: false,
|
|
153
|
+
memories: extractedMemories.map((m) => ({
|
|
154
|
+
content: m.content,
|
|
155
|
+
memory_type: m.memoryType,
|
|
156
|
+
user_id: options?.userId ?? this.userId,
|
|
157
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
158
|
+
importance: Math.max(0.5, Math.min(1, m.confidence || 0.7)),
|
|
159
|
+
confidence: m.confidence || 0.7,
|
|
160
|
+
entity_mentions: m.entityMentions || [],
|
|
161
|
+
event_date: m.eventDate || void 0,
|
|
162
|
+
metadata: {
|
|
163
|
+
extracted: true,
|
|
164
|
+
extraction_method: extraction.extractionMethod,
|
|
165
|
+
extraction_reasoning: m.reasoning,
|
|
166
|
+
inferred: Boolean(m.inferred)
|
|
167
|
+
}
|
|
168
|
+
}))
|
|
169
|
+
});
|
|
170
|
+
const memoryIds = this.extractMemoryIdsFromBulkResponse(bulk);
|
|
171
|
+
return {
|
|
172
|
+
success: true,
|
|
173
|
+
memoryId: memoryIds[0],
|
|
174
|
+
memoryIds: memoryIds.length > 0 ? memoryIds : void 0,
|
|
175
|
+
extracted: extractedMemories.length
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
135
179
|
const result = await this.client.addMemory({
|
|
136
180
|
project: options?.project ?? this.options.project,
|
|
137
181
|
content,
|
|
@@ -177,15 +221,131 @@ ${context}` : "",
|
|
|
177
221
|
return { success: false, extracted: 0 };
|
|
178
222
|
}
|
|
179
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Run a full agent turn with automatic memory read (before) + write (after).
|
|
226
|
+
*/
|
|
227
|
+
async runTurn(params) {
|
|
228
|
+
const contextResult = await this.getContext(params.userMessage, {
|
|
229
|
+
userId: params.userId,
|
|
230
|
+
sessionId: params.sessionId,
|
|
231
|
+
project: params.project,
|
|
232
|
+
limit: params.limit
|
|
233
|
+
});
|
|
234
|
+
const prompt = contextResult.context ? `${contextResult.context}
|
|
235
|
+
|
|
236
|
+
User: ${params.userMessage}` : params.userMessage;
|
|
237
|
+
const response = await params.generate(prompt);
|
|
238
|
+
const captureResult = await this.captureSession(
|
|
239
|
+
[
|
|
240
|
+
{ role: "user", content: params.userMessage },
|
|
241
|
+
{ role: "assistant", content: response }
|
|
242
|
+
],
|
|
243
|
+
{
|
|
244
|
+
userId: params.userId,
|
|
245
|
+
sessionId: params.sessionId,
|
|
246
|
+
project: params.project
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
return {
|
|
250
|
+
response,
|
|
251
|
+
context: contextResult.context,
|
|
252
|
+
count: contextResult.count,
|
|
253
|
+
extracted: captureResult.extracted
|
|
254
|
+
};
|
|
255
|
+
}
|
|
180
256
|
/**
|
|
181
257
|
* Direct access to WhisperContext for advanced usage
|
|
182
258
|
*/
|
|
183
259
|
raw() {
|
|
184
260
|
return this.client;
|
|
185
261
|
}
|
|
262
|
+
extractMemoryIdsFromBulkResponse(bulkResponse) {
|
|
263
|
+
const ids = [];
|
|
264
|
+
if (Array.isArray(bulkResponse?.memories)) {
|
|
265
|
+
for (const memory of bulkResponse.memories) {
|
|
266
|
+
if (memory?.id) ids.push(memory.id);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (bulkResponse?.memory?.id) {
|
|
270
|
+
ids.push(bulkResponse.memory.id);
|
|
271
|
+
}
|
|
272
|
+
if (bulkResponse?.id) {
|
|
273
|
+
ids.push(bulkResponse.id);
|
|
274
|
+
}
|
|
275
|
+
return Array.from(new Set(ids));
|
|
276
|
+
}
|
|
186
277
|
};
|
|
187
278
|
var whisper_agent_default = Whisper;
|
|
188
279
|
|
|
280
|
+
// ../src/sdk/middleware.ts
|
|
281
|
+
var WhisperAgentMiddleware = class {
|
|
282
|
+
whisper;
|
|
283
|
+
promptBuilder;
|
|
284
|
+
constructor(config) {
|
|
285
|
+
this.whisper = new Whisper(config);
|
|
286
|
+
this.promptBuilder = config.promptBuilder || (({ context, userMessage }) => {
|
|
287
|
+
if (!context) return userMessage;
|
|
288
|
+
return `${context}
|
|
289
|
+
|
|
290
|
+
User: ${userMessage}`;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
async beforeTurn(params) {
|
|
294
|
+
const contextResult = await this.whisper.getContext(params.userMessage, {
|
|
295
|
+
userId: params.userId,
|
|
296
|
+
sessionId: params.sessionId,
|
|
297
|
+
project: params.project,
|
|
298
|
+
limit: params.contextLimit
|
|
299
|
+
});
|
|
300
|
+
const prompt = this.promptBuilder({
|
|
301
|
+
context: contextResult.context,
|
|
302
|
+
userMessage: params.userMessage
|
|
303
|
+
});
|
|
304
|
+
return {
|
|
305
|
+
prompt,
|
|
306
|
+
context: contextResult.context,
|
|
307
|
+
contextCount: contextResult.count
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
async afterTurn(params) {
|
|
311
|
+
return this.whisper.captureSession(
|
|
312
|
+
[
|
|
313
|
+
{ role: "user", content: params.userMessage },
|
|
314
|
+
{ role: "assistant", content: params.assistantMessage }
|
|
315
|
+
],
|
|
316
|
+
{
|
|
317
|
+
userId: params.userId,
|
|
318
|
+
sessionId: params.sessionId,
|
|
319
|
+
project: params.project
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
async wrapGenerate(params) {
|
|
324
|
+
const before = await this.beforeTurn(params);
|
|
325
|
+
const response = await params.generate(before.prompt);
|
|
326
|
+
const after = await this.afterTurn({
|
|
327
|
+
userMessage: params.userMessage,
|
|
328
|
+
assistantMessage: response,
|
|
329
|
+
userId: params.userId,
|
|
330
|
+
sessionId: params.sessionId,
|
|
331
|
+
project: params.project
|
|
332
|
+
});
|
|
333
|
+
return {
|
|
334
|
+
response,
|
|
335
|
+
prompt: before.prompt,
|
|
336
|
+
context: before.context,
|
|
337
|
+
contextCount: before.contextCount,
|
|
338
|
+
extracted: after.extracted
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
raw() {
|
|
342
|
+
return this.whisper;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
function createAgentMiddleware(config) {
|
|
346
|
+
return new WhisperAgentMiddleware(config);
|
|
347
|
+
}
|
|
348
|
+
|
|
189
349
|
// ../src/sdk/index.ts
|
|
190
350
|
var WhisperError = class extends Error {
|
|
191
351
|
code;
|
|
@@ -216,11 +376,24 @@ function getBackoffDelay(attempt, base, max) {
|
|
|
216
376
|
function isLikelyProjectId(projectRef) {
|
|
217
377
|
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
378
|
}
|
|
379
|
+
function normalizeBaseUrl(url) {
|
|
380
|
+
let normalized = url.trim().replace(/\/+$/, "");
|
|
381
|
+
normalized = normalized.replace(/\/api\/v1$/i, "");
|
|
382
|
+
normalized = normalized.replace(/\/v1$/i, "");
|
|
383
|
+
normalized = normalized.replace(/\/api$/i, "");
|
|
384
|
+
return normalized;
|
|
385
|
+
}
|
|
386
|
+
function normalizeEndpoint(endpoint) {
|
|
387
|
+
const withLeadingSlash = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
388
|
+
if (/^\/api\/v1(\/|$)/i.test(withLeadingSlash)) {
|
|
389
|
+
return withLeadingSlash.replace(/^\/api/i, "");
|
|
390
|
+
}
|
|
391
|
+
return withLeadingSlash;
|
|
392
|
+
}
|
|
219
393
|
var WhisperContext = class _WhisperContext {
|
|
220
394
|
apiKey;
|
|
221
395
|
baseUrl;
|
|
222
396
|
defaultProject;
|
|
223
|
-
orgId;
|
|
224
397
|
timeoutMs;
|
|
225
398
|
retryConfig;
|
|
226
399
|
projectRefToId = /* @__PURE__ */ new Map();
|
|
@@ -234,9 +407,8 @@ var WhisperContext = class _WhisperContext {
|
|
|
234
407
|
});
|
|
235
408
|
}
|
|
236
409
|
this.apiKey = config.apiKey;
|
|
237
|
-
this.baseUrl = config.baseUrl || "https://context.usewhisper.dev";
|
|
410
|
+
this.baseUrl = normalizeBaseUrl(config.baseUrl || "https://context.usewhisper.dev");
|
|
238
411
|
this.defaultProject = config.project;
|
|
239
|
-
this.orgId = config.orgId;
|
|
240
412
|
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
241
413
|
this.retryConfig = {
|
|
242
414
|
maxAttempts: config.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
|
@@ -249,7 +421,6 @@ var WhisperContext = class _WhisperContext {
|
|
|
249
421
|
apiKey: this.apiKey,
|
|
250
422
|
baseUrl: this.baseUrl,
|
|
251
423
|
project,
|
|
252
|
-
orgId: this.orgId,
|
|
253
424
|
timeoutMs: this.timeoutMs,
|
|
254
425
|
retry: this.retryConfig
|
|
255
426
|
});
|
|
@@ -366,20 +537,28 @@ var WhisperContext = class _WhisperContext {
|
|
|
366
537
|
}
|
|
367
538
|
async request(endpoint, options = {}) {
|
|
368
539
|
const maxAttempts = Math.max(1, this.retryConfig.maxAttempts);
|
|
540
|
+
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
|
369
541
|
let lastError;
|
|
370
542
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
371
543
|
const controller = new AbortController();
|
|
372
544
|
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
373
545
|
try {
|
|
374
|
-
const
|
|
546
|
+
const headers = {
|
|
547
|
+
"Content-Type": "application/json",
|
|
548
|
+
...options.headers
|
|
549
|
+
};
|
|
550
|
+
const hasAuthHeader = Object.keys(headers).some((k) => k.toLowerCase() === "authorization");
|
|
551
|
+
const hasApiKeyHeader = Object.keys(headers).some((k) => k.toLowerCase() === "x-api-key");
|
|
552
|
+
if (!hasAuthHeader) {
|
|
553
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
554
|
+
}
|
|
555
|
+
if (!hasApiKeyHeader) {
|
|
556
|
+
headers["X-API-Key"] = this.apiKey;
|
|
557
|
+
}
|
|
558
|
+
const response = await fetch(`${this.baseUrl}${normalizedEndpoint}`, {
|
|
375
559
|
...options,
|
|
376
560
|
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
|
-
}
|
|
561
|
+
headers
|
|
383
562
|
});
|
|
384
563
|
clearTimeout(timeout);
|
|
385
564
|
if (!response.ok) {
|
|
@@ -568,6 +747,34 @@ var WhisperContext = class _WhisperContext {
|
|
|
568
747
|
return { id, success: true, path: "legacy", fallback_used: true };
|
|
569
748
|
});
|
|
570
749
|
}
|
|
750
|
+
async addMemoriesBulk(params) {
|
|
751
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
752
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/bulk", {
|
|
753
|
+
method: "POST",
|
|
754
|
+
body: JSON.stringify({ ...params, project })
|
|
755
|
+
}));
|
|
756
|
+
}
|
|
757
|
+
async extractMemories(params) {
|
|
758
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
759
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract", {
|
|
760
|
+
method: "POST",
|
|
761
|
+
body: JSON.stringify({ ...params, project })
|
|
762
|
+
}));
|
|
763
|
+
}
|
|
764
|
+
async extractSessionMemories(params) {
|
|
765
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
766
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract/session", {
|
|
767
|
+
method: "POST",
|
|
768
|
+
body: JSON.stringify({
|
|
769
|
+
...params,
|
|
770
|
+
project,
|
|
771
|
+
messages: params.messages.map((m) => ({
|
|
772
|
+
...m,
|
|
773
|
+
timestamp: m.timestamp || (/* @__PURE__ */ new Date()).toISOString()
|
|
774
|
+
}))
|
|
775
|
+
})
|
|
776
|
+
}));
|
|
777
|
+
}
|
|
571
778
|
async searchMemories(params) {
|
|
572
779
|
const projectRef = this.getRequiredProject(params.project);
|
|
573
780
|
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/search", {
|
|
@@ -764,6 +971,9 @@ var WhisperContext = class _WhisperContext {
|
|
|
764
971
|
};
|
|
765
972
|
memory = {
|
|
766
973
|
add: (params) => this.addMemory(params),
|
|
974
|
+
addBulk: (params) => this.addMemoriesBulk(params),
|
|
975
|
+
extract: (params) => this.extractMemories(params),
|
|
976
|
+
extractSession: (params) => this.extractSessionMemories(params),
|
|
767
977
|
search: (params) => this.searchMemories(params),
|
|
768
978
|
searchSOTA: (params) => this.searchMemoriesSOTA(params),
|
|
769
979
|
ingestSession: (params) => this.ingestSession(params),
|
|
@@ -803,7 +1013,9 @@ var index_default = WhisperContext;
|
|
|
803
1013
|
// Annotate the CommonJS export names for ESM import in node:
|
|
804
1014
|
0 && (module.exports = {
|
|
805
1015
|
Whisper,
|
|
1016
|
+
WhisperAgentMiddleware,
|
|
806
1017
|
WhisperContext,
|
|
807
1018
|
WhisperDefault,
|
|
808
|
-
WhisperError
|
|
1019
|
+
WhisperError,
|
|
1020
|
+
createAgentMiddleware
|
|
809
1021
|
});
|
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,131 @@ ${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
|
+
|
|
159
317
|
// ../src/sdk/index.ts
|
|
160
318
|
var WhisperError = class extends Error {
|
|
161
319
|
code;
|
|
@@ -186,11 +344,24 @@ function getBackoffDelay(attempt, base, max) {
|
|
|
186
344
|
function isLikelyProjectId(projectRef) {
|
|
187
345
|
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
346
|
}
|
|
347
|
+
function normalizeBaseUrl(url) {
|
|
348
|
+
let normalized = url.trim().replace(/\/+$/, "");
|
|
349
|
+
normalized = normalized.replace(/\/api\/v1$/i, "");
|
|
350
|
+
normalized = normalized.replace(/\/v1$/i, "");
|
|
351
|
+
normalized = normalized.replace(/\/api$/i, "");
|
|
352
|
+
return normalized;
|
|
353
|
+
}
|
|
354
|
+
function normalizeEndpoint(endpoint) {
|
|
355
|
+
const withLeadingSlash = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
356
|
+
if (/^\/api\/v1(\/|$)/i.test(withLeadingSlash)) {
|
|
357
|
+
return withLeadingSlash.replace(/^\/api/i, "");
|
|
358
|
+
}
|
|
359
|
+
return withLeadingSlash;
|
|
360
|
+
}
|
|
189
361
|
var WhisperContext = class _WhisperContext {
|
|
190
362
|
apiKey;
|
|
191
363
|
baseUrl;
|
|
192
364
|
defaultProject;
|
|
193
|
-
orgId;
|
|
194
365
|
timeoutMs;
|
|
195
366
|
retryConfig;
|
|
196
367
|
projectRefToId = /* @__PURE__ */ new Map();
|
|
@@ -204,9 +375,8 @@ var WhisperContext = class _WhisperContext {
|
|
|
204
375
|
});
|
|
205
376
|
}
|
|
206
377
|
this.apiKey = config.apiKey;
|
|
207
|
-
this.baseUrl = config.baseUrl || "https://context.usewhisper.dev";
|
|
378
|
+
this.baseUrl = normalizeBaseUrl(config.baseUrl || "https://context.usewhisper.dev");
|
|
208
379
|
this.defaultProject = config.project;
|
|
209
|
-
this.orgId = config.orgId;
|
|
210
380
|
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
211
381
|
this.retryConfig = {
|
|
212
382
|
maxAttempts: config.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
|
@@ -219,7 +389,6 @@ var WhisperContext = class _WhisperContext {
|
|
|
219
389
|
apiKey: this.apiKey,
|
|
220
390
|
baseUrl: this.baseUrl,
|
|
221
391
|
project,
|
|
222
|
-
orgId: this.orgId,
|
|
223
392
|
timeoutMs: this.timeoutMs,
|
|
224
393
|
retry: this.retryConfig
|
|
225
394
|
});
|
|
@@ -336,20 +505,28 @@ var WhisperContext = class _WhisperContext {
|
|
|
336
505
|
}
|
|
337
506
|
async request(endpoint, options = {}) {
|
|
338
507
|
const maxAttempts = Math.max(1, this.retryConfig.maxAttempts);
|
|
508
|
+
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
|
339
509
|
let lastError;
|
|
340
510
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
341
511
|
const controller = new AbortController();
|
|
342
512
|
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
343
513
|
try {
|
|
344
|
-
const
|
|
514
|
+
const headers = {
|
|
515
|
+
"Content-Type": "application/json",
|
|
516
|
+
...options.headers
|
|
517
|
+
};
|
|
518
|
+
const hasAuthHeader = Object.keys(headers).some((k) => k.toLowerCase() === "authorization");
|
|
519
|
+
const hasApiKeyHeader = Object.keys(headers).some((k) => k.toLowerCase() === "x-api-key");
|
|
520
|
+
if (!hasAuthHeader) {
|
|
521
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
522
|
+
}
|
|
523
|
+
if (!hasApiKeyHeader) {
|
|
524
|
+
headers["X-API-Key"] = this.apiKey;
|
|
525
|
+
}
|
|
526
|
+
const response = await fetch(`${this.baseUrl}${normalizedEndpoint}`, {
|
|
345
527
|
...options,
|
|
346
528
|
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
|
-
}
|
|
529
|
+
headers
|
|
353
530
|
});
|
|
354
531
|
clearTimeout(timeout);
|
|
355
532
|
if (!response.ok) {
|
|
@@ -538,6 +715,34 @@ var WhisperContext = class _WhisperContext {
|
|
|
538
715
|
return { id, success: true, path: "legacy", fallback_used: true };
|
|
539
716
|
});
|
|
540
717
|
}
|
|
718
|
+
async addMemoriesBulk(params) {
|
|
719
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
720
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/bulk", {
|
|
721
|
+
method: "POST",
|
|
722
|
+
body: JSON.stringify({ ...params, project })
|
|
723
|
+
}));
|
|
724
|
+
}
|
|
725
|
+
async extractMemories(params) {
|
|
726
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
727
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract", {
|
|
728
|
+
method: "POST",
|
|
729
|
+
body: JSON.stringify({ ...params, project })
|
|
730
|
+
}));
|
|
731
|
+
}
|
|
732
|
+
async extractSessionMemories(params) {
|
|
733
|
+
const projectRef = this.getRequiredProject(params.project);
|
|
734
|
+
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/extract/session", {
|
|
735
|
+
method: "POST",
|
|
736
|
+
body: JSON.stringify({
|
|
737
|
+
...params,
|
|
738
|
+
project,
|
|
739
|
+
messages: params.messages.map((m) => ({
|
|
740
|
+
...m,
|
|
741
|
+
timestamp: m.timestamp || (/* @__PURE__ */ new Date()).toISOString()
|
|
742
|
+
}))
|
|
743
|
+
})
|
|
744
|
+
}));
|
|
745
|
+
}
|
|
541
746
|
async searchMemories(params) {
|
|
542
747
|
const projectRef = this.getRequiredProject(params.project);
|
|
543
748
|
return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/memory/search", {
|
|
@@ -734,6 +939,9 @@ var WhisperContext = class _WhisperContext {
|
|
|
734
939
|
};
|
|
735
940
|
memory = {
|
|
736
941
|
add: (params) => this.addMemory(params),
|
|
942
|
+
addBulk: (params) => this.addMemoriesBulk(params),
|
|
943
|
+
extract: (params) => this.extractMemories(params),
|
|
944
|
+
extractSession: (params) => this.extractSessionMemories(params),
|
|
737
945
|
search: (params) => this.searchMemories(params),
|
|
738
946
|
searchSOTA: (params) => this.searchMemoriesSOTA(params),
|
|
739
947
|
ingestSession: (params) => this.ingestSession(params),
|
|
@@ -772,8 +980,10 @@ var WhisperContext = class _WhisperContext {
|
|
|
772
980
|
var index_default = WhisperContext;
|
|
773
981
|
export {
|
|
774
982
|
Whisper,
|
|
983
|
+
WhisperAgentMiddleware,
|
|
775
984
|
WhisperContext,
|
|
776
985
|
whisper_agent_default as WhisperDefault,
|
|
777
986
|
WhisperError,
|
|
987
|
+
createAgentMiddleware,
|
|
778
988
|
index_default as default
|
|
779
989
|
};
|