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