@usewhisper/sdk 3.5.0 → 3.6.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.d.mts +7 -0
- package/index.d.ts +7 -0
- package/index.js +514 -495
- package/index.mjs +514 -495
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -379,368 +379,83 @@ var RuntimeClient = class {
|
|
|
379
379
|
}
|
|
380
380
|
};
|
|
381
381
|
|
|
382
|
-
// ../src/sdk/
|
|
383
|
-
var
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
382
|
+
// ../src/sdk/core/cache.ts
|
|
383
|
+
var SearchResponseCache = class {
|
|
384
|
+
ttlMs;
|
|
385
|
+
capacity;
|
|
386
|
+
byKey = /* @__PURE__ */ new Map();
|
|
387
|
+
scopeIndex = /* @__PURE__ */ new Map();
|
|
388
|
+
constructor(ttlMs = 7e3, capacity = 500) {
|
|
389
|
+
this.ttlMs = Math.max(1e3, ttlMs);
|
|
390
|
+
this.capacity = Math.max(10, capacity);
|
|
389
391
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
client;
|
|
393
|
-
options;
|
|
394
|
-
sessionId;
|
|
395
|
-
userId;
|
|
396
|
-
constructor(options) {
|
|
397
|
-
if (!options.apiKey) {
|
|
398
|
-
throw new Error("API key is required");
|
|
399
|
-
}
|
|
400
|
-
const clientConfig = {
|
|
401
|
-
apiKey: options.apiKey,
|
|
402
|
-
baseUrl: options.baseUrl,
|
|
403
|
-
project: options.project || "default"
|
|
404
|
-
};
|
|
405
|
-
if (options.timeoutMs) clientConfig.timeoutMs = options.timeoutMs;
|
|
406
|
-
if (options.retry) clientConfig.retry = options.retry;
|
|
407
|
-
this.client = new WhisperContext(clientConfig);
|
|
408
|
-
warnDeprecatedOnce(
|
|
409
|
-
"whisper_agent_wrapper",
|
|
410
|
-
"[Whisper SDK] Whisper wrapper is supported for v2 compatibility. Prefer WhisperClient for new integrations."
|
|
411
|
-
);
|
|
412
|
-
const finalRetry = options.retry || { maxAttempts: 3, baseDelayMs: 250, maxDelayMs: 2e3 };
|
|
413
|
-
this.options = {
|
|
414
|
-
apiKey: options.apiKey,
|
|
415
|
-
baseUrl: options.baseUrl || "https://context.usewhisper.dev",
|
|
416
|
-
project: options.project || "default",
|
|
417
|
-
timeoutMs: options.timeoutMs || 15e3,
|
|
418
|
-
retry: finalRetry,
|
|
419
|
-
contextLimit: options.contextLimit ?? 10,
|
|
420
|
-
memoryTypes: options.memoryTypes ?? ["factual", "preference", "event", "goal", "relationship", "opinion", "instruction"],
|
|
421
|
-
contextPrefix: options.contextPrefix ?? "Relevant context:",
|
|
422
|
-
autoExtract: options.autoExtract ?? true,
|
|
423
|
-
autoExtractMinConfidence: options.autoExtractMinConfidence ?? 0.65,
|
|
424
|
-
maxMemoriesPerCapture: options.maxMemoriesPerCapture ?? 5
|
|
425
|
-
};
|
|
392
|
+
makeScopeKey(project, userId, sessionId) {
|
|
393
|
+
return `${project}:${userId || "_"}:${sessionId || "_"}`;
|
|
426
394
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
395
|
+
makeKey(input) {
|
|
396
|
+
const normalized = {
|
|
397
|
+
project: input.project,
|
|
398
|
+
userId: input.userId || "",
|
|
399
|
+
sessionId: input.sessionId || "",
|
|
400
|
+
query: normalizeQuery(input.query),
|
|
401
|
+
topK: input.topK,
|
|
402
|
+
profile: input.profile,
|
|
403
|
+
includePending: input.includePending
|
|
404
|
+
};
|
|
405
|
+
return `search:${stableHash(JSON.stringify(normalized))}`;
|
|
433
406
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
407
|
+
get(key) {
|
|
408
|
+
const found = this.byKey.get(key);
|
|
409
|
+
if (!found) return null;
|
|
410
|
+
if (found.expiresAt <= Date.now()) {
|
|
411
|
+
this.deleteByKey(key);
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
found.touchedAt = Date.now();
|
|
415
|
+
return found.value;
|
|
440
416
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
* @example
|
|
448
|
-
* ```typescript
|
|
449
|
-
* const { context, results, count } = await whisper.getContext(
|
|
450
|
-
* "What are user's preferences?",
|
|
451
|
-
* { userId: "user-123" }
|
|
452
|
-
* );
|
|
453
|
-
*
|
|
454
|
-
* // Results: [
|
|
455
|
-
* // { content: "User prefers dark mode", type: "preference", score: 0.95 },
|
|
456
|
-
* // { content: "Allergic to nuts", type: "factual", score: 0.89 }
|
|
457
|
-
* // ]
|
|
458
|
-
* ```
|
|
459
|
-
*/
|
|
460
|
-
async getContext(query, options) {
|
|
461
|
-
const result = await this.client.query({
|
|
462
|
-
project: options?.project ?? this.options.project,
|
|
463
|
-
query,
|
|
464
|
-
top_k: options?.limit ?? this.options.contextLimit,
|
|
465
|
-
include_memories: true,
|
|
466
|
-
user_id: options?.userId ?? this.userId,
|
|
467
|
-
session_id: options?.sessionId ?? this.sessionId
|
|
417
|
+
set(key, scopeKey, value) {
|
|
418
|
+
this.byKey.set(key, {
|
|
419
|
+
value,
|
|
420
|
+
scopeKey,
|
|
421
|
+
touchedAt: Date.now(),
|
|
422
|
+
expiresAt: Date.now() + this.ttlMs
|
|
468
423
|
});
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
count: result.meta.total
|
|
475
|
-
};
|
|
424
|
+
if (!this.scopeIndex.has(scopeKey)) {
|
|
425
|
+
this.scopeIndex.set(scopeKey, /* @__PURE__ */ new Set());
|
|
426
|
+
}
|
|
427
|
+
this.scopeIndex.get(scopeKey).add(key);
|
|
428
|
+
this.evictIfNeeded();
|
|
476
429
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
*
|
|
482
|
-
* @param content - What your LLM responded with
|
|
483
|
-
* @returns Promise that resolves when stored (or fails silently)
|
|
484
|
-
*
|
|
485
|
-
* @example
|
|
486
|
-
* ```typescript
|
|
487
|
-
* const llmResponse = "I've set your theme to dark mode and removed nuts from recommendations.";
|
|
488
|
-
*
|
|
489
|
-
* await whisper.remember(llmResponse, { userId: "user-123" });
|
|
490
|
-
* // → Auto-extracts: "theme set to dark mode", "nut allergy"
|
|
491
|
-
* // → Stored as preferences
|
|
492
|
-
* ```
|
|
493
|
-
*/
|
|
494
|
-
async remember(content, options) {
|
|
495
|
-
if (!content || content.length < 5) {
|
|
496
|
-
return { success: false };
|
|
430
|
+
invalidateScope(scopeKey) {
|
|
431
|
+
const keys = this.scopeIndex.get(scopeKey);
|
|
432
|
+
if (!keys || keys.size === 0) {
|
|
433
|
+
return 0;
|
|
497
434
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
project: options?.project ?? this.options.project,
|
|
502
|
-
message: content,
|
|
503
|
-
user_id: options?.userId ?? this.userId,
|
|
504
|
-
session_id: options?.sessionId ?? this.sessionId,
|
|
505
|
-
enable_pattern: true,
|
|
506
|
-
enable_inference: true,
|
|
507
|
-
min_confidence: this.options.autoExtractMinConfidence
|
|
508
|
-
});
|
|
509
|
-
const extractedMemories = (extraction.all || []).filter((m) => (m.confidence || 0) >= this.options.autoExtractMinConfidence).slice(0, this.options.maxMemoriesPerCapture);
|
|
510
|
-
if (extractedMemories.length > 0) {
|
|
511
|
-
const bulk = await this.client.addMemoriesBulk({
|
|
512
|
-
project: options?.project ?? this.options.project,
|
|
513
|
-
write_mode: "async",
|
|
514
|
-
memories: extractedMemories.map((m) => ({
|
|
515
|
-
content: m.content,
|
|
516
|
-
memory_type: m.memoryType,
|
|
517
|
-
user_id: options?.userId ?? this.userId,
|
|
518
|
-
session_id: options?.sessionId ?? this.sessionId,
|
|
519
|
-
importance: Math.max(0.5, Math.min(1, m.confidence || 0.7)),
|
|
520
|
-
confidence: m.confidence || 0.7,
|
|
521
|
-
entity_mentions: m.entityMentions || [],
|
|
522
|
-
event_date: m.eventDate || void 0,
|
|
523
|
-
metadata: {
|
|
524
|
-
extracted: true,
|
|
525
|
-
extraction_method: extraction.extractionMethod,
|
|
526
|
-
extraction_reasoning: m.reasoning,
|
|
527
|
-
inferred: Boolean(m.inferred)
|
|
528
|
-
}
|
|
529
|
-
}))
|
|
530
|
-
});
|
|
531
|
-
const memoryIds = this.extractMemoryIdsFromBulkResponse(bulk);
|
|
532
|
-
return {
|
|
533
|
-
success: true,
|
|
534
|
-
memoryId: memoryIds[0],
|
|
535
|
-
memoryIds: memoryIds.length > 0 ? memoryIds : void 0,
|
|
536
|
-
extracted: extractedMemories.length
|
|
537
|
-
};
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
const result = await this.client.addMemory({
|
|
541
|
-
project: options?.project ?? this.options.project,
|
|
542
|
-
content,
|
|
543
|
-
user_id: options?.userId ?? this.userId,
|
|
544
|
-
session_id: options?.sessionId ?? this.sessionId
|
|
545
|
-
});
|
|
546
|
-
return {
|
|
547
|
-
success: true,
|
|
548
|
-
memoryId: result?.id
|
|
549
|
-
};
|
|
550
|
-
} catch (error) {
|
|
551
|
-
console.error("[Whisper] Remember failed:", error);
|
|
552
|
-
return { success: false };
|
|
435
|
+
const toDelete = Array.from(keys);
|
|
436
|
+
for (const key of toDelete) {
|
|
437
|
+
this.deleteByKey(key);
|
|
553
438
|
}
|
|
439
|
+
this.scopeIndex.delete(scopeKey);
|
|
440
|
+
return toDelete.length;
|
|
554
441
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
442
|
+
evictIfNeeded() {
|
|
443
|
+
if (this.byKey.size <= this.capacity) return;
|
|
444
|
+
const ordered = Array.from(this.byKey.entries()).sort((a, b) => a[1].touchedAt - b[1].touchedAt);
|
|
445
|
+
const removeCount = this.byKey.size - this.capacity;
|
|
446
|
+
for (let i = 0; i < removeCount; i += 1) {
|
|
447
|
+
this.deleteByKey(ordered[i][0]);
|
|
448
|
+
}
|
|
560
449
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
messages: messages.filter((m) => m.role !== "system").map((m) => ({
|
|
571
|
-
role: m.role,
|
|
572
|
-
content: m.content,
|
|
573
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
574
|
-
}))
|
|
575
|
-
});
|
|
576
|
-
return {
|
|
577
|
-
success: true,
|
|
578
|
-
extracted: result?.memories_created ?? 0
|
|
579
|
-
};
|
|
580
|
-
} catch (error) {
|
|
581
|
-
const fallback = await this.fallbackCaptureViaAddMemory(messages, options);
|
|
582
|
-
if (fallback.success) {
|
|
583
|
-
return fallback;
|
|
584
|
-
}
|
|
585
|
-
console.error("[Whisper] Session capture failed:", error);
|
|
586
|
-
return { success: false, extracted: 0 };
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Run a full agent turn with automatic memory read (before) + write (after).
|
|
591
|
-
*/
|
|
592
|
-
async runTurn(params) {
|
|
593
|
-
const contextResult = await this.getContext(params.userMessage, {
|
|
594
|
-
userId: params.userId,
|
|
595
|
-
sessionId: params.sessionId,
|
|
596
|
-
project: params.project,
|
|
597
|
-
limit: params.limit
|
|
598
|
-
});
|
|
599
|
-
const prompt = contextResult.context ? `${contextResult.context}
|
|
600
|
-
|
|
601
|
-
User: ${params.userMessage}` : params.userMessage;
|
|
602
|
-
const response = await params.generate(prompt);
|
|
603
|
-
const captureResult = await this.captureSession(
|
|
604
|
-
[
|
|
605
|
-
{ role: "user", content: params.userMessage },
|
|
606
|
-
{ role: "assistant", content: response }
|
|
607
|
-
],
|
|
608
|
-
{
|
|
609
|
-
userId: params.userId,
|
|
610
|
-
sessionId: params.sessionId,
|
|
611
|
-
project: params.project
|
|
612
|
-
}
|
|
613
|
-
);
|
|
614
|
-
return {
|
|
615
|
-
response,
|
|
616
|
-
context: contextResult.context,
|
|
617
|
-
count: contextResult.count,
|
|
618
|
-
extracted: captureResult.extracted
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
622
|
-
* Direct access to WhisperContext for advanced usage
|
|
623
|
-
*/
|
|
624
|
-
raw() {
|
|
625
|
-
return this.client;
|
|
626
|
-
}
|
|
627
|
-
extractMemoryIdsFromBulkResponse(bulkResponse) {
|
|
628
|
-
const ids = [];
|
|
629
|
-
if (Array.isArray(bulkResponse?.memories)) {
|
|
630
|
-
for (const memory of bulkResponse.memories) {
|
|
631
|
-
if (memory?.id) ids.push(memory.id);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
if (bulkResponse?.memory?.id) {
|
|
635
|
-
ids.push(bulkResponse.memory.id);
|
|
636
|
-
}
|
|
637
|
-
if (bulkResponse?.id) {
|
|
638
|
-
ids.push(bulkResponse.id);
|
|
639
|
-
}
|
|
640
|
-
return Array.from(new Set(ids));
|
|
641
|
-
}
|
|
642
|
-
async fallbackCaptureViaAddMemory(messages, options) {
|
|
643
|
-
const userMessages = messages.filter((m) => m.role === "user").map((m) => (m.content || "").trim()).filter((content) => content.length >= 5).slice(-2);
|
|
644
|
-
if (userMessages.length === 0) {
|
|
645
|
-
return { success: false, extracted: 0 };
|
|
646
|
-
}
|
|
647
|
-
let extracted = 0;
|
|
648
|
-
for (const content of userMessages) {
|
|
649
|
-
try {
|
|
650
|
-
await this.client.addMemory({
|
|
651
|
-
project: options?.project ?? this.options.project,
|
|
652
|
-
content,
|
|
653
|
-
memory_type: "factual",
|
|
654
|
-
user_id: options?.userId ?? this.userId,
|
|
655
|
-
session_id: options?.sessionId ?? this.sessionId,
|
|
656
|
-
allow_legacy_fallback: true
|
|
657
|
-
});
|
|
658
|
-
extracted += 1;
|
|
659
|
-
} catch {
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
return { success: extracted > 0, extracted };
|
|
663
|
-
}
|
|
664
|
-
};
|
|
665
|
-
var whisper_agent_default = Whisper;
|
|
666
|
-
|
|
667
|
-
// ../src/sdk/core/cache.ts
|
|
668
|
-
var SearchResponseCache = class {
|
|
669
|
-
ttlMs;
|
|
670
|
-
capacity;
|
|
671
|
-
byKey = /* @__PURE__ */ new Map();
|
|
672
|
-
scopeIndex = /* @__PURE__ */ new Map();
|
|
673
|
-
constructor(ttlMs = 7e3, capacity = 500) {
|
|
674
|
-
this.ttlMs = Math.max(1e3, ttlMs);
|
|
675
|
-
this.capacity = Math.max(10, capacity);
|
|
676
|
-
}
|
|
677
|
-
makeScopeKey(project, userId, sessionId) {
|
|
678
|
-
return `${project}:${userId || "_"}:${sessionId || "_"}`;
|
|
679
|
-
}
|
|
680
|
-
makeKey(input) {
|
|
681
|
-
const normalized = {
|
|
682
|
-
project: input.project,
|
|
683
|
-
userId: input.userId || "",
|
|
684
|
-
sessionId: input.sessionId || "",
|
|
685
|
-
query: normalizeQuery(input.query),
|
|
686
|
-
topK: input.topK,
|
|
687
|
-
profile: input.profile,
|
|
688
|
-
includePending: input.includePending
|
|
689
|
-
};
|
|
690
|
-
return `search:${stableHash(JSON.stringify(normalized))}`;
|
|
691
|
-
}
|
|
692
|
-
get(key) {
|
|
693
|
-
const found = this.byKey.get(key);
|
|
694
|
-
if (!found) return null;
|
|
695
|
-
if (found.expiresAt <= Date.now()) {
|
|
696
|
-
this.deleteByKey(key);
|
|
697
|
-
return null;
|
|
698
|
-
}
|
|
699
|
-
found.touchedAt = Date.now();
|
|
700
|
-
return found.value;
|
|
701
|
-
}
|
|
702
|
-
set(key, scopeKey, value) {
|
|
703
|
-
this.byKey.set(key, {
|
|
704
|
-
value,
|
|
705
|
-
scopeKey,
|
|
706
|
-
touchedAt: Date.now(),
|
|
707
|
-
expiresAt: Date.now() + this.ttlMs
|
|
708
|
-
});
|
|
709
|
-
if (!this.scopeIndex.has(scopeKey)) {
|
|
710
|
-
this.scopeIndex.set(scopeKey, /* @__PURE__ */ new Set());
|
|
711
|
-
}
|
|
712
|
-
this.scopeIndex.get(scopeKey).add(key);
|
|
713
|
-
this.evictIfNeeded();
|
|
714
|
-
}
|
|
715
|
-
invalidateScope(scopeKey) {
|
|
716
|
-
const keys = this.scopeIndex.get(scopeKey);
|
|
717
|
-
if (!keys || keys.size === 0) {
|
|
718
|
-
return 0;
|
|
719
|
-
}
|
|
720
|
-
const toDelete = Array.from(keys);
|
|
721
|
-
for (const key of toDelete) {
|
|
722
|
-
this.deleteByKey(key);
|
|
723
|
-
}
|
|
724
|
-
this.scopeIndex.delete(scopeKey);
|
|
725
|
-
return toDelete.length;
|
|
726
|
-
}
|
|
727
|
-
evictIfNeeded() {
|
|
728
|
-
if (this.byKey.size <= this.capacity) return;
|
|
729
|
-
const ordered = Array.from(this.byKey.entries()).sort((a, b) => a[1].touchedAt - b[1].touchedAt);
|
|
730
|
-
const removeCount = this.byKey.size - this.capacity;
|
|
731
|
-
for (let i = 0; i < removeCount; i += 1) {
|
|
732
|
-
this.deleteByKey(ordered[i][0]);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
deleteByKey(key) {
|
|
736
|
-
const found = this.byKey.get(key);
|
|
737
|
-
if (!found) return;
|
|
738
|
-
this.byKey.delete(key);
|
|
739
|
-
const scopeKeys = this.scopeIndex.get(found.scopeKey);
|
|
740
|
-
if (!scopeKeys) return;
|
|
741
|
-
scopeKeys.delete(key);
|
|
742
|
-
if (scopeKeys.size === 0) {
|
|
743
|
-
this.scopeIndex.delete(found.scopeKey);
|
|
450
|
+
deleteByKey(key) {
|
|
451
|
+
const found = this.byKey.get(key);
|
|
452
|
+
if (!found) return;
|
|
453
|
+
this.byKey.delete(key);
|
|
454
|
+
const scopeKeys = this.scopeIndex.get(found.scopeKey);
|
|
455
|
+
if (!scopeKeys) return;
|
|
456
|
+
scopeKeys.delete(key);
|
|
457
|
+
if (scopeKeys.size === 0) {
|
|
458
|
+
this.scopeIndex.delete(found.scopeKey);
|
|
744
459
|
}
|
|
745
460
|
}
|
|
746
461
|
};
|
|
@@ -2333,165 +2048,469 @@ var WhisperClient = class _WhisperClient {
|
|
|
2333
2048
|
retryable: false
|
|
2334
2049
|
});
|
|
2335
2050
|
}
|
|
2336
|
-
return resolved;
|
|
2051
|
+
return resolved;
|
|
2052
|
+
}
|
|
2053
|
+
async refreshProjectCache(force = false) {
|
|
2054
|
+
if (!force && Date.now() < this.projectCacheExpiresAt && this.projectCache.length > 0) {
|
|
2055
|
+
return this.projectCache;
|
|
2056
|
+
}
|
|
2057
|
+
const response = await this.runtimeClient.request({
|
|
2058
|
+
endpoint: "/v1/projects",
|
|
2059
|
+
method: "GET",
|
|
2060
|
+
operation: "get",
|
|
2061
|
+
idempotent: true
|
|
2062
|
+
});
|
|
2063
|
+
this.projectRefToId.clear();
|
|
2064
|
+
this.projectCache = response.data?.projects || [];
|
|
2065
|
+
for (const project of this.projectCache) {
|
|
2066
|
+
this.projectRefToId.set(project.id, project.id);
|
|
2067
|
+
this.projectRefToId.set(project.slug, project.id);
|
|
2068
|
+
this.projectRefToId.set(project.name, project.id);
|
|
2069
|
+
}
|
|
2070
|
+
this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
|
|
2071
|
+
return this.projectCache;
|
|
2072
|
+
}
|
|
2073
|
+
async fetchResolvedProject(projectRef) {
|
|
2074
|
+
try {
|
|
2075
|
+
const response = await this.runtimeClient.request({
|
|
2076
|
+
endpoint: `/v1/projects/resolve?project=${encodeURIComponent(projectRef)}`,
|
|
2077
|
+
method: "GET",
|
|
2078
|
+
operation: "get",
|
|
2079
|
+
idempotent: true
|
|
2080
|
+
});
|
|
2081
|
+
return response.data?.resolved || null;
|
|
2082
|
+
} catch (error) {
|
|
2083
|
+
if (error instanceof RuntimeClientError && error.status === 404) {
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
2086
|
+
throw error;
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
async resolveProject(projectRef) {
|
|
2090
|
+
const resolvedRef = this.getRequiredProject(projectRef);
|
|
2091
|
+
const cachedProjects = await this.refreshProjectCache(false);
|
|
2092
|
+
const cachedProject = cachedProjects.find(
|
|
2093
|
+
(project) => project.id === resolvedRef || project.slug === resolvedRef || project.name === resolvedRef
|
|
2094
|
+
);
|
|
2095
|
+
if (cachedProject) {
|
|
2096
|
+
return cachedProject;
|
|
2097
|
+
}
|
|
2098
|
+
const resolvedProject = await this.fetchResolvedProject(resolvedRef);
|
|
2099
|
+
if (resolvedProject) {
|
|
2100
|
+
this.projectRefToId.set(resolvedProject.id, resolvedProject.id);
|
|
2101
|
+
this.projectRefToId.set(resolvedProject.slug, resolvedProject.id);
|
|
2102
|
+
this.projectRefToId.set(resolvedProject.name, resolvedProject.id);
|
|
2103
|
+
this.projectCache = [
|
|
2104
|
+
...this.projectCache.filter((project) => project.id !== resolvedProject.id),
|
|
2105
|
+
resolvedProject
|
|
2106
|
+
];
|
|
2107
|
+
this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
|
|
2108
|
+
return resolvedProject;
|
|
2109
|
+
}
|
|
2110
|
+
if (isLikelyProjectId(resolvedRef)) {
|
|
2111
|
+
return {
|
|
2112
|
+
id: resolvedRef,
|
|
2113
|
+
orgId: "",
|
|
2114
|
+
name: resolvedRef,
|
|
2115
|
+
slug: resolvedRef,
|
|
2116
|
+
createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
2117
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
2118
|
+
};
|
|
2119
|
+
}
|
|
2120
|
+
throw new RuntimeClientError({
|
|
2121
|
+
code: "PROJECT_NOT_FOUND",
|
|
2122
|
+
message: `Project '${resolvedRef}' not found`,
|
|
2123
|
+
retryable: false
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
async query(params) {
|
|
2127
|
+
const project = (await this.resolveProject(params.project)).id;
|
|
2128
|
+
const response = await this.runtimeClient.request({
|
|
2129
|
+
endpoint: "/v1/context/query",
|
|
2130
|
+
method: "POST",
|
|
2131
|
+
operation: "search",
|
|
2132
|
+
body: {
|
|
2133
|
+
...params,
|
|
2134
|
+
project
|
|
2135
|
+
},
|
|
2136
|
+
idempotent: true
|
|
2137
|
+
});
|
|
2138
|
+
return response.data;
|
|
2139
|
+
}
|
|
2140
|
+
async ingestSession(params) {
|
|
2141
|
+
const project = (await this.resolveProject(params.project)).id;
|
|
2142
|
+
const response = await this.runtimeClient.request({
|
|
2143
|
+
endpoint: "/v1/memory/ingest/session",
|
|
2144
|
+
method: "POST",
|
|
2145
|
+
operation: "session",
|
|
2146
|
+
body: {
|
|
2147
|
+
...params,
|
|
2148
|
+
project
|
|
2149
|
+
}
|
|
2150
|
+
});
|
|
2151
|
+
return response.data;
|
|
2152
|
+
}
|
|
2153
|
+
createAgentRuntime(options = {}) {
|
|
2154
|
+
const baseContext = {
|
|
2155
|
+
workspacePath: options.workspacePath,
|
|
2156
|
+
project: options.project || this.config.project,
|
|
2157
|
+
userId: options.userId,
|
|
2158
|
+
sessionId: options.sessionId,
|
|
2159
|
+
traceId: options.traceId,
|
|
2160
|
+
clientName: options.clientName
|
|
2161
|
+
};
|
|
2162
|
+
return new WhisperAgentRuntime({
|
|
2163
|
+
baseContext,
|
|
2164
|
+
options,
|
|
2165
|
+
adapter: {
|
|
2166
|
+
resolveProject: (project) => this.resolveProject(project),
|
|
2167
|
+
query: (params) => this.query(params),
|
|
2168
|
+
ingestSession: (params) => this.ingestSession(params),
|
|
2169
|
+
getSessionMemories: (params) => this.memory.getSessionMemories(params),
|
|
2170
|
+
getUserProfile: (params) => this.memory.getUserProfile(params),
|
|
2171
|
+
searchMemories: (params) => this.memory.search(params),
|
|
2172
|
+
addMemory: (params) => this.memory.add(params),
|
|
2173
|
+
queueStatus: () => this.queue.status(),
|
|
2174
|
+
flushQueue: () => this.queue.flush()
|
|
2175
|
+
}
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
withRunContext(context) {
|
|
2179
|
+
const base = this;
|
|
2180
|
+
return {
|
|
2181
|
+
memory: {
|
|
2182
|
+
add: (params) => base.memory.add({
|
|
2183
|
+
...params,
|
|
2184
|
+
project: params.project || context.project || base.config.project,
|
|
2185
|
+
user_id: params.user_id || context.userId,
|
|
2186
|
+
session_id: params.session_id || context.sessionId
|
|
2187
|
+
}),
|
|
2188
|
+
search: (params) => base.memory.search({
|
|
2189
|
+
...params,
|
|
2190
|
+
project: params.project || context.project || base.config.project,
|
|
2191
|
+
user_id: params.user_id || context.userId,
|
|
2192
|
+
session_id: params.session_id || context.sessionId
|
|
2193
|
+
})
|
|
2194
|
+
},
|
|
2195
|
+
session: {
|
|
2196
|
+
event: (params) => base.session.event({
|
|
2197
|
+
...params,
|
|
2198
|
+
sessionId: params.sessionId || context.sessionId || ""
|
|
2199
|
+
})
|
|
2200
|
+
},
|
|
2201
|
+
queue: base.queue,
|
|
2202
|
+
diagnostics: base.diagnostics
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
async shutdown() {
|
|
2206
|
+
await this.writeQueue.stop();
|
|
2207
|
+
}
|
|
2208
|
+
};
|
|
2209
|
+
var whisper_default = WhisperClient;
|
|
2210
|
+
|
|
2211
|
+
// ../src/sdk/whisper-agent.ts
|
|
2212
|
+
var DEPRECATION_WARNINGS = /* @__PURE__ */ new Set();
|
|
2213
|
+
function warnDeprecatedOnce(key, message) {
|
|
2214
|
+
if (DEPRECATION_WARNINGS.has(key)) return;
|
|
2215
|
+
DEPRECATION_WARNINGS.add(key);
|
|
2216
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
2217
|
+
console.warn(message);
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
var Whisper = class {
|
|
2221
|
+
client;
|
|
2222
|
+
runtimeClient;
|
|
2223
|
+
options;
|
|
2224
|
+
sessionId;
|
|
2225
|
+
userId;
|
|
2226
|
+
constructor(options) {
|
|
2227
|
+
if (!options.apiKey) {
|
|
2228
|
+
throw new Error("API key is required");
|
|
2229
|
+
}
|
|
2230
|
+
const clientConfig = {
|
|
2231
|
+
apiKey: options.apiKey,
|
|
2232
|
+
baseUrl: options.baseUrl,
|
|
2233
|
+
project: options.project || "default"
|
|
2234
|
+
};
|
|
2235
|
+
if (options.timeoutMs) clientConfig.timeoutMs = options.timeoutMs;
|
|
2236
|
+
if (options.retry) clientConfig.retry = options.retry;
|
|
2237
|
+
this.client = new WhisperContext(clientConfig);
|
|
2238
|
+
this.runtimeClient = new WhisperClient({
|
|
2239
|
+
apiKey: options.apiKey,
|
|
2240
|
+
baseUrl: options.baseUrl,
|
|
2241
|
+
project: options.project || "default"
|
|
2242
|
+
});
|
|
2243
|
+
warnDeprecatedOnce(
|
|
2244
|
+
"whisper_agent_wrapper",
|
|
2245
|
+
"[Whisper SDK] Whisper wrapper is supported for v2 compatibility. Prefer WhisperClient for new integrations."
|
|
2246
|
+
);
|
|
2247
|
+
const finalRetry = options.retry || { maxAttempts: 3, baseDelayMs: 250, maxDelayMs: 2e3 };
|
|
2248
|
+
this.options = {
|
|
2249
|
+
apiKey: options.apiKey,
|
|
2250
|
+
baseUrl: options.baseUrl || "https://context.usewhisper.dev",
|
|
2251
|
+
project: options.project || "default",
|
|
2252
|
+
timeoutMs: options.timeoutMs || 15e3,
|
|
2253
|
+
retry: finalRetry,
|
|
2254
|
+
contextLimit: options.contextLimit ?? 10,
|
|
2255
|
+
memoryTypes: options.memoryTypes ?? ["factual", "preference", "event", "goal", "relationship", "opinion", "instruction"],
|
|
2256
|
+
contextPrefix: options.contextPrefix ?? "Relevant context:",
|
|
2257
|
+
autoExtract: options.autoExtract ?? true,
|
|
2258
|
+
autoExtractMinConfidence: options.autoExtractMinConfidence ?? 0.65,
|
|
2259
|
+
maxMemoriesPerCapture: options.maxMemoriesPerCapture ?? 5
|
|
2260
|
+
};
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Set session ID for conversation tracking
|
|
2264
|
+
*/
|
|
2265
|
+
session(sessionId) {
|
|
2266
|
+
this.sessionId = sessionId;
|
|
2267
|
+
return this;
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* Set user ID for user-specific memories
|
|
2271
|
+
*/
|
|
2272
|
+
user(userId) {
|
|
2273
|
+
this.userId = userId;
|
|
2274
|
+
return this;
|
|
2275
|
+
}
|
|
2276
|
+
/**
|
|
2277
|
+
* Get relevant context BEFORE your LLM call
|
|
2278
|
+
*
|
|
2279
|
+
* @param query - What you want to know / user question
|
|
2280
|
+
* @returns Context string and raw results
|
|
2281
|
+
*
|
|
2282
|
+
* @example
|
|
2283
|
+
* ```typescript
|
|
2284
|
+
* const { context, results, count } = await whisper.getContext(
|
|
2285
|
+
* "What are user's preferences?",
|
|
2286
|
+
* { userId: "user-123" }
|
|
2287
|
+
* );
|
|
2288
|
+
*
|
|
2289
|
+
* // Results: [
|
|
2290
|
+
* // { content: "User prefers dark mode", type: "preference", score: 0.95 },
|
|
2291
|
+
* // { content: "Allergic to nuts", type: "factual", score: 0.89 }
|
|
2292
|
+
* // ]
|
|
2293
|
+
* ```
|
|
2294
|
+
*/
|
|
2295
|
+
async getContext(query, options) {
|
|
2296
|
+
const runtime = this.runtimeClient.createAgentRuntime({
|
|
2297
|
+
project: options?.project ?? this.options.project,
|
|
2298
|
+
userId: options?.userId ?? this.userId,
|
|
2299
|
+
sessionId: options?.sessionId ?? this.sessionId,
|
|
2300
|
+
topK: options?.limit ?? this.options.contextLimit,
|
|
2301
|
+
clientName: "whisper-wrapper"
|
|
2302
|
+
});
|
|
2303
|
+
const prepared = await runtime.beforeTurn({
|
|
2304
|
+
userMessage: query
|
|
2305
|
+
});
|
|
2306
|
+
const results = prepared.items.map((item, index) => ({
|
|
2307
|
+
id: item.id || `runtime_${index}`,
|
|
2308
|
+
content: item.content,
|
|
2309
|
+
score: item.score,
|
|
2310
|
+
metadata: item.metadata || {},
|
|
2311
|
+
source: item.type === "memory" ? "memory" : "runtime",
|
|
2312
|
+
document: item.sourceQuery,
|
|
2313
|
+
type: item.type,
|
|
2314
|
+
retrieval_source: item.type === "memory" ? "memory" : "runtime"
|
|
2315
|
+
}));
|
|
2316
|
+
const context = results.map((r, i) => `[${i + 1}] ${r.content}`).join("\n");
|
|
2317
|
+
return {
|
|
2318
|
+
context: context ? `${this.options.contextPrefix}
|
|
2319
|
+
${context}` : "",
|
|
2320
|
+
results,
|
|
2321
|
+
count: prepared.items.length
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
2324
|
+
/**
|
|
2325
|
+
* Remember what happened AFTER your LLM response
|
|
2326
|
+
*
|
|
2327
|
+
* Fire-and-forget - doesn't block your response
|
|
2328
|
+
*
|
|
2329
|
+
* @param content - What your LLM responded with
|
|
2330
|
+
* @returns Promise that resolves when stored (or fails silently)
|
|
2331
|
+
*
|
|
2332
|
+
* @example
|
|
2333
|
+
* ```typescript
|
|
2334
|
+
* const llmResponse = "I've set your theme to dark mode and removed nuts from recommendations.";
|
|
2335
|
+
*
|
|
2336
|
+
* await whisper.remember(llmResponse, { userId: "user-123" });
|
|
2337
|
+
* // → Auto-extracts: "theme set to dark mode", "nut allergy"
|
|
2338
|
+
* // → Stored as preferences
|
|
2339
|
+
* ```
|
|
2340
|
+
*/
|
|
2341
|
+
async remember(content, options) {
|
|
2342
|
+
if (!content || content.length < 5) {
|
|
2343
|
+
return { success: false };
|
|
2344
|
+
}
|
|
2345
|
+
try {
|
|
2346
|
+
if (this.options.autoExtract) {
|
|
2347
|
+
const extraction = await this.client.extractMemories({
|
|
2348
|
+
project: options?.project ?? this.options.project,
|
|
2349
|
+
message: content,
|
|
2350
|
+
user_id: options?.userId ?? this.userId,
|
|
2351
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
2352
|
+
enable_pattern: true,
|
|
2353
|
+
enable_inference: true,
|
|
2354
|
+
min_confidence: this.options.autoExtractMinConfidence
|
|
2355
|
+
});
|
|
2356
|
+
const extractedMemories = (extraction.all || []).filter((m) => (m.confidence || 0) >= this.options.autoExtractMinConfidence).slice(0, this.options.maxMemoriesPerCapture);
|
|
2357
|
+
if (extractedMemories.length > 0) {
|
|
2358
|
+
const bulk = await this.client.addMemoriesBulk({
|
|
2359
|
+
project: options?.project ?? this.options.project,
|
|
2360
|
+
write_mode: "async",
|
|
2361
|
+
memories: extractedMemories.map((m) => ({
|
|
2362
|
+
content: m.content,
|
|
2363
|
+
memory_type: m.memoryType,
|
|
2364
|
+
user_id: options?.userId ?? this.userId,
|
|
2365
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
2366
|
+
importance: Math.max(0.5, Math.min(1, m.confidence || 0.7)),
|
|
2367
|
+
confidence: m.confidence || 0.7,
|
|
2368
|
+
entity_mentions: m.entityMentions || [],
|
|
2369
|
+
event_date: m.eventDate || void 0,
|
|
2370
|
+
metadata: {
|
|
2371
|
+
extracted: true,
|
|
2372
|
+
extraction_method: extraction.extractionMethod,
|
|
2373
|
+
extraction_reasoning: m.reasoning,
|
|
2374
|
+
inferred: Boolean(m.inferred)
|
|
2375
|
+
}
|
|
2376
|
+
}))
|
|
2377
|
+
});
|
|
2378
|
+
const memoryIds = this.extractMemoryIdsFromBulkResponse(bulk);
|
|
2379
|
+
return {
|
|
2380
|
+
success: true,
|
|
2381
|
+
memoryId: memoryIds[0],
|
|
2382
|
+
memoryIds: memoryIds.length > 0 ? memoryIds : void 0,
|
|
2383
|
+
extracted: extractedMemories.length
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
const result = await this.client.addMemory({
|
|
2388
|
+
project: options?.project ?? this.options.project,
|
|
2389
|
+
content,
|
|
2390
|
+
user_id: options?.userId ?? this.userId,
|
|
2391
|
+
session_id: options?.sessionId ?? this.sessionId
|
|
2392
|
+
});
|
|
2393
|
+
return {
|
|
2394
|
+
success: true,
|
|
2395
|
+
memoryId: result?.id
|
|
2396
|
+
};
|
|
2397
|
+
} catch (error) {
|
|
2398
|
+
console.error("[Whisper] Remember failed:", error);
|
|
2399
|
+
return { success: false };
|
|
2400
|
+
}
|
|
2337
2401
|
}
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
endpoint: "/v1/projects",
|
|
2344
|
-
method: "GET",
|
|
2345
|
-
operation: "get",
|
|
2346
|
-
idempotent: true
|
|
2347
|
-
});
|
|
2348
|
-
this.projectRefToId.clear();
|
|
2349
|
-
this.projectCache = response.data?.projects || [];
|
|
2350
|
-
for (const project of this.projectCache) {
|
|
2351
|
-
this.projectRefToId.set(project.id, project.id);
|
|
2352
|
-
this.projectRefToId.set(project.slug, project.id);
|
|
2353
|
-
this.projectRefToId.set(project.name, project.id);
|
|
2354
|
-
}
|
|
2355
|
-
this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
|
|
2356
|
-
return this.projectCache;
|
|
2402
|
+
/**
|
|
2403
|
+
* Alias for remember() - same thing
|
|
2404
|
+
*/
|
|
2405
|
+
async capture(content, options) {
|
|
2406
|
+
return this.remember(content, options);
|
|
2357
2407
|
}
|
|
2358
|
-
|
|
2408
|
+
/**
|
|
2409
|
+
* Capture from multiple messages (e.g., full conversation)
|
|
2410
|
+
*/
|
|
2411
|
+
async captureSession(messages, options) {
|
|
2359
2412
|
try {
|
|
2360
|
-
const
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2413
|
+
const filteredMessages = messages.filter((m) => m.role !== "system");
|
|
2414
|
+
const runtime = this.runtimeClient.createAgentRuntime({
|
|
2415
|
+
project: options?.project ?? this.options.project,
|
|
2416
|
+
userId: options?.userId ?? this.userId,
|
|
2417
|
+
sessionId: options?.sessionId ?? this.sessionId ?? "default",
|
|
2418
|
+
clientName: "whisper-wrapper"
|
|
2365
2419
|
});
|
|
2366
|
-
|
|
2420
|
+
const result = await runtime.afterTurn({
|
|
2421
|
+
userMessage: [...filteredMessages].reverse().find((m) => m.role === "user")?.content || "",
|
|
2422
|
+
assistantMessage: [...filteredMessages].reverse().find((m) => m.role === "assistant")?.content || ""
|
|
2423
|
+
});
|
|
2424
|
+
return {
|
|
2425
|
+
success: true,
|
|
2426
|
+
extracted: result.memoriesCreated ?? 0
|
|
2427
|
+
};
|
|
2367
2428
|
} catch (error) {
|
|
2368
|
-
|
|
2369
|
-
|
|
2429
|
+
const fallback = await this.fallbackCaptureViaAddMemory(messages, options);
|
|
2430
|
+
if (fallback.success) {
|
|
2431
|
+
return fallback;
|
|
2370
2432
|
}
|
|
2371
|
-
|
|
2433
|
+
console.error("[Whisper] Session capture failed:", error);
|
|
2434
|
+
return { success: false, extracted: 0 };
|
|
2372
2435
|
}
|
|
2373
2436
|
}
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
const resolvedProject = await this.fetchResolvedProject(resolvedRef);
|
|
2384
|
-
if (resolvedProject) {
|
|
2385
|
-
this.projectRefToId.set(resolvedProject.id, resolvedProject.id);
|
|
2386
|
-
this.projectRefToId.set(resolvedProject.slug, resolvedProject.id);
|
|
2387
|
-
this.projectRefToId.set(resolvedProject.name, resolvedProject.id);
|
|
2388
|
-
this.projectCache = [
|
|
2389
|
-
...this.projectCache.filter((project) => project.id !== resolvedProject.id),
|
|
2390
|
-
resolvedProject
|
|
2391
|
-
];
|
|
2392
|
-
this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
|
|
2393
|
-
return resolvedProject;
|
|
2394
|
-
}
|
|
2395
|
-
if (isLikelyProjectId(resolvedRef)) {
|
|
2396
|
-
return {
|
|
2397
|
-
id: resolvedRef,
|
|
2398
|
-
orgId: "",
|
|
2399
|
-
name: resolvedRef,
|
|
2400
|
-
slug: resolvedRef,
|
|
2401
|
-
createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
2402
|
-
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
2403
|
-
};
|
|
2404
|
-
}
|
|
2405
|
-
throw new RuntimeClientError({
|
|
2406
|
-
code: "PROJECT_NOT_FOUND",
|
|
2407
|
-
message: `Project '${resolvedRef}' not found`,
|
|
2408
|
-
retryable: false
|
|
2437
|
+
/**
|
|
2438
|
+
* Run a full agent turn with automatic memory read (before) + write (after).
|
|
2439
|
+
*/
|
|
2440
|
+
async runTurn(params) {
|
|
2441
|
+
const contextResult = await this.getContext(params.userMessage, {
|
|
2442
|
+
userId: params.userId,
|
|
2443
|
+
sessionId: params.sessionId,
|
|
2444
|
+
project: params.project,
|
|
2445
|
+
limit: params.limit
|
|
2409
2446
|
});
|
|
2447
|
+
const prompt = contextResult.context ? `${contextResult.context}
|
|
2448
|
+
|
|
2449
|
+
User: ${params.userMessage}` : params.userMessage;
|
|
2450
|
+
const response = await params.generate(prompt);
|
|
2451
|
+
const captureResult = await this.captureSession(
|
|
2452
|
+
[
|
|
2453
|
+
{ role: "user", content: params.userMessage },
|
|
2454
|
+
{ role: "assistant", content: response }
|
|
2455
|
+
],
|
|
2456
|
+
{
|
|
2457
|
+
userId: params.userId,
|
|
2458
|
+
sessionId: params.sessionId,
|
|
2459
|
+
project: params.project
|
|
2460
|
+
}
|
|
2461
|
+
);
|
|
2462
|
+
return {
|
|
2463
|
+
response,
|
|
2464
|
+
context: contextResult.context,
|
|
2465
|
+
count: contextResult.count,
|
|
2466
|
+
extracted: captureResult.extracted
|
|
2467
|
+
};
|
|
2410
2468
|
}
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
operation: "search",
|
|
2417
|
-
body: {
|
|
2418
|
-
...params,
|
|
2419
|
-
project
|
|
2420
|
-
},
|
|
2421
|
-
idempotent: true
|
|
2422
|
-
});
|
|
2423
|
-
return response.data;
|
|
2469
|
+
/**
|
|
2470
|
+
* Direct access to WhisperContext for advanced usage
|
|
2471
|
+
*/
|
|
2472
|
+
raw() {
|
|
2473
|
+
return this.client;
|
|
2424
2474
|
}
|
|
2425
|
-
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
operation: "session",
|
|
2431
|
-
body: {
|
|
2432
|
-
...params,
|
|
2433
|
-
project
|
|
2475
|
+
extractMemoryIdsFromBulkResponse(bulkResponse) {
|
|
2476
|
+
const ids = [];
|
|
2477
|
+
if (Array.isArray(bulkResponse?.memories)) {
|
|
2478
|
+
for (const memory of bulkResponse.memories) {
|
|
2479
|
+
if (memory?.id) ids.push(memory.id);
|
|
2434
2480
|
}
|
|
2435
|
-
}
|
|
2436
|
-
|
|
2481
|
+
}
|
|
2482
|
+
if (bulkResponse?.memory?.id) {
|
|
2483
|
+
ids.push(bulkResponse.memory.id);
|
|
2484
|
+
}
|
|
2485
|
+
if (bulkResponse?.id) {
|
|
2486
|
+
ids.push(bulkResponse.id);
|
|
2487
|
+
}
|
|
2488
|
+
return Array.from(new Set(ids));
|
|
2437
2489
|
}
|
|
2438
|
-
|
|
2439
|
-
const
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
searchMemories: (params) => this.memory.search(params),
|
|
2457
|
-
addMemory: (params) => this.memory.add(params),
|
|
2458
|
-
queueStatus: () => this.queue.status(),
|
|
2459
|
-
flushQueue: () => this.queue.flush()
|
|
2490
|
+
async fallbackCaptureViaAddMemory(messages, options) {
|
|
2491
|
+
const userMessages = messages.filter((m) => m.role === "user").map((m) => (m.content || "").trim()).filter((content) => content.length >= 5).slice(-2);
|
|
2492
|
+
if (userMessages.length === 0) {
|
|
2493
|
+
return { success: false, extracted: 0 };
|
|
2494
|
+
}
|
|
2495
|
+
let extracted = 0;
|
|
2496
|
+
for (const content of userMessages) {
|
|
2497
|
+
try {
|
|
2498
|
+
await this.client.addMemory({
|
|
2499
|
+
project: options?.project ?? this.options.project,
|
|
2500
|
+
content,
|
|
2501
|
+
memory_type: "factual",
|
|
2502
|
+
user_id: options?.userId ?? this.userId,
|
|
2503
|
+
session_id: options?.sessionId ?? this.sessionId,
|
|
2504
|
+
allow_legacy_fallback: true
|
|
2505
|
+
});
|
|
2506
|
+
extracted += 1;
|
|
2507
|
+
} catch {
|
|
2460
2508
|
}
|
|
2461
|
-
}
|
|
2462
|
-
|
|
2463
|
-
withRunContext(context) {
|
|
2464
|
-
const base = this;
|
|
2465
|
-
return {
|
|
2466
|
-
memory: {
|
|
2467
|
-
add: (params) => base.memory.add({
|
|
2468
|
-
...params,
|
|
2469
|
-
project: params.project || context.project || base.config.project,
|
|
2470
|
-
user_id: params.user_id || context.userId,
|
|
2471
|
-
session_id: params.session_id || context.sessionId
|
|
2472
|
-
}),
|
|
2473
|
-
search: (params) => base.memory.search({
|
|
2474
|
-
...params,
|
|
2475
|
-
project: params.project || context.project || base.config.project,
|
|
2476
|
-
user_id: params.user_id || context.userId,
|
|
2477
|
-
session_id: params.session_id || context.sessionId
|
|
2478
|
-
})
|
|
2479
|
-
},
|
|
2480
|
-
session: {
|
|
2481
|
-
event: (params) => base.session.event({
|
|
2482
|
-
...params,
|
|
2483
|
-
sessionId: params.sessionId || context.sessionId || ""
|
|
2484
|
-
})
|
|
2485
|
-
},
|
|
2486
|
-
queue: base.queue,
|
|
2487
|
-
diagnostics: base.diagnostics
|
|
2488
|
-
};
|
|
2489
|
-
}
|
|
2490
|
-
async shutdown() {
|
|
2491
|
-
await this.writeQueue.stop();
|
|
2509
|
+
}
|
|
2510
|
+
return { success: extracted > 0, extracted };
|
|
2492
2511
|
}
|
|
2493
2512
|
};
|
|
2494
|
-
var
|
|
2513
|
+
var whisper_agent_default = Whisper;
|
|
2495
2514
|
|
|
2496
2515
|
// ../src/sdk/middleware.ts
|
|
2497
2516
|
var WhisperAgentMiddleware = class {
|