@almadar/agent 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/index.d.ts +7 -245
- package/dist/agent/index.js +325 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/{firestore-checkpointer-DxbQ10ve.d.ts → firestore-checkpointer-CkNKXoun.d.ts} +1 -1
- package/dist/index-D-Ahuo6F.d.ts +854 -0
- package/dist/index.d.ts +708 -56
- package/dist/index.js +2070 -4
- package/dist/index.js.map +1 -1
- package/dist/persistence/index.d.ts +2 -2
- package/package.json +17 -16
- package/LICENSE +0 -72
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { exec, spawn } from 'child_process';
|
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import { promisify } from 'util';
|
|
7
7
|
import * as fs4 from 'fs/promises';
|
|
8
|
-
import { isStructuredOutputAvailable, getStructuredOutputClient, LLMClient, ANTHROPIC_MODELS, createAnthropicClient, OPENAI_MODELS, createOpenAIClient, DEEPSEEK_MODELS, createDeepSeekClient } from '@almadar/llm';
|
|
8
|
+
import { isStructuredOutputAvailable, getStructuredOutputClient, LLMClient, createRequirementsClient, ANTHROPIC_MODELS, createAnthropicClient, OPENAI_MODELS, createOpenAIClient, DEEPSEEK_MODELS, createDeepSeekClient } from '@almadar/llm';
|
|
9
9
|
import * as domain_language_star from '@almadar/core/domain-language';
|
|
10
10
|
import * as fs3 from 'fs';
|
|
11
11
|
import crypto, { randomUUID } from 'crypto';
|
|
@@ -18,6 +18,7 @@ import { MemorySaver } from '@langchain/langgraph';
|
|
|
18
18
|
export { Command } from '@langchain/langgraph';
|
|
19
19
|
import { v4 } from 'uuid';
|
|
20
20
|
import { BaseCheckpointSaver, BaseStore } from '@langchain/langgraph-checkpoint';
|
|
21
|
+
import { EventEmitter } from 'events';
|
|
21
22
|
|
|
22
23
|
var __defProp = Object.defineProperty;
|
|
23
24
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -4431,9 +4432,13 @@ var SessionManager = class {
|
|
|
4431
4432
|
constructor(options = {}) {
|
|
4432
4433
|
this.firestoreCheckpointer = null;
|
|
4433
4434
|
this.firestoreSessionStore = null;
|
|
4435
|
+
this.memoryManager = null;
|
|
4436
|
+
this.compactionConfig = null;
|
|
4434
4437
|
this.mode = options.mode ?? "memory";
|
|
4435
4438
|
this.memoryBackend = new MemorySessionBackend();
|
|
4436
4439
|
this.memoryCheckpointers = /* @__PURE__ */ new Map();
|
|
4440
|
+
this.memoryManager = options.memoryManager ?? null;
|
|
4441
|
+
this.compactionConfig = options.compactionConfig ?? null;
|
|
4437
4442
|
if (this.mode === "firestore" && options.firestoreDb) {
|
|
4438
4443
|
this.firestoreCheckpointer = new FirestoreCheckpointer({ db: options.firestoreDb });
|
|
4439
4444
|
this.firestoreSessionStore = new FirestoreSessionStore({ db: options.firestoreDb });
|
|
@@ -4533,6 +4538,260 @@ var SessionManager = class {
|
|
|
4533
4538
|
}
|
|
4534
4539
|
return this.memoryBackend.list();
|
|
4535
4540
|
}
|
|
4541
|
+
// ============================================================================
|
|
4542
|
+
// Session → Memory Sync (GAP-002D)
|
|
4543
|
+
// ============================================================================
|
|
4544
|
+
/**
|
|
4545
|
+
* Sync a completed session to orbital memory.
|
|
4546
|
+
* This enables the agent to learn from past sessions.
|
|
4547
|
+
*
|
|
4548
|
+
* @param threadId - The session thread ID
|
|
4549
|
+
* @param userId - The user ID for memory association
|
|
4550
|
+
* @param sessionData - Additional session data to record
|
|
4551
|
+
* @returns Promise that resolves when sync is complete
|
|
4552
|
+
*/
|
|
4553
|
+
async syncSessionToMemory(threadId, userId, sessionData) {
|
|
4554
|
+
if (!this.memoryManager) {
|
|
4555
|
+
console.warn("[SessionManager] No memory manager configured, skipping session sync");
|
|
4556
|
+
return;
|
|
4557
|
+
}
|
|
4558
|
+
const metadata = this.get(threadId);
|
|
4559
|
+
if (!metadata) {
|
|
4560
|
+
console.warn(`[SessionManager] Session ${threadId} not found, skipping sync`);
|
|
4561
|
+
return;
|
|
4562
|
+
}
|
|
4563
|
+
try {
|
|
4564
|
+
await this.memoryManager.recordGeneration(userId, {
|
|
4565
|
+
threadId,
|
|
4566
|
+
prompt: sessionData.inputDescription,
|
|
4567
|
+
skill: metadata.skill,
|
|
4568
|
+
generatedSchema: sessionData.generatedOrbital ? { name: sessionData.generatedOrbital } : void 0,
|
|
4569
|
+
patterns: sessionData.patternsUsed ?? [],
|
|
4570
|
+
entities: sessionData.entities ?? [],
|
|
4571
|
+
success: sessionData.success,
|
|
4572
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
4573
|
+
});
|
|
4574
|
+
if (sessionData.patternsUsed && sessionData.patternsUsed.length > 0) {
|
|
4575
|
+
await this.memoryManager.updateUserPreferences(userId, {
|
|
4576
|
+
preferredPatterns: sessionData.patternsUsed,
|
|
4577
|
+
commonEntities: sessionData.entities
|
|
4578
|
+
});
|
|
4579
|
+
}
|
|
4580
|
+
if (sessionData.entities && sessionData.entities.length > 0) {
|
|
4581
|
+
await this.memoryManager.updateProjectContext(sessionData.appId, {
|
|
4582
|
+
userId,
|
|
4583
|
+
existingEntities: sessionData.entities
|
|
4584
|
+
});
|
|
4585
|
+
}
|
|
4586
|
+
console.log(`[SessionManager] Session ${threadId} synced to memory for user ${userId}`);
|
|
4587
|
+
} catch (error) {
|
|
4588
|
+
console.error("[SessionManager] Failed to sync session to memory:", error);
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4591
|
+
// ============================================================================
|
|
4592
|
+
// Interrupt → Memory Sync (GAP-003: Interrupt Memory)
|
|
4593
|
+
// ============================================================================
|
|
4594
|
+
/**
|
|
4595
|
+
* Record an interrupt decision to memory.
|
|
4596
|
+
* This enables learning from HITL (Human-in-the-Loop) decisions.
|
|
4597
|
+
*
|
|
4598
|
+
* @param sessionId - The session thread ID
|
|
4599
|
+
* @param userId - The user who made the decision
|
|
4600
|
+
* @param interruptData - The interrupt decision data
|
|
4601
|
+
* @returns Promise that resolves when sync is complete
|
|
4602
|
+
*/
|
|
4603
|
+
async recordInterruptDecision(sessionId, userId, interruptData) {
|
|
4604
|
+
if (!this.memoryManager) {
|
|
4605
|
+
console.warn("[SessionManager] No memory manager configured, skipping interrupt sync");
|
|
4606
|
+
return;
|
|
4607
|
+
}
|
|
4608
|
+
try {
|
|
4609
|
+
await this.memoryManager.recordInterruptDecision(sessionId, userId, interruptData);
|
|
4610
|
+
console.log(`[SessionManager] Interrupt recorded for user ${userId}: ${interruptData.toolName} ${interruptData.decision}`);
|
|
4611
|
+
} catch (error) {
|
|
4612
|
+
console.error("[SessionManager] Failed to record interrupt:", error);
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
/**
|
|
4616
|
+
* Get interrupt history for a session.
|
|
4617
|
+
*/
|
|
4618
|
+
async getSessionInterrupts(sessionId) {
|
|
4619
|
+
if (!this.memoryManager) {
|
|
4620
|
+
return [];
|
|
4621
|
+
}
|
|
4622
|
+
return this.memoryManager.getSessionInterrupts(sessionId);
|
|
4623
|
+
}
|
|
4624
|
+
/**
|
|
4625
|
+
* Check if a tool should be auto-approved for a user.
|
|
4626
|
+
*/
|
|
4627
|
+
async shouldAutoApproveTool(userId, toolName) {
|
|
4628
|
+
if (!this.memoryManager) {
|
|
4629
|
+
return false;
|
|
4630
|
+
}
|
|
4631
|
+
return this.memoryManager.shouldAutoApproveTool(userId, toolName);
|
|
4632
|
+
}
|
|
4633
|
+
// ============================================================================
|
|
4634
|
+
// Checkpoint Management (GAP-004: Checkpoint → Memory)
|
|
4635
|
+
// ============================================================================
|
|
4636
|
+
/**
|
|
4637
|
+
* Record a checkpoint to memory for learning.
|
|
4638
|
+
*
|
|
4639
|
+
* @param userId - The user who owns this checkpoint
|
|
4640
|
+
* @param checkpointData - Checkpoint information
|
|
4641
|
+
* @returns Promise that resolves when checkpoint is recorded
|
|
4642
|
+
*/
|
|
4643
|
+
async recordCheckpoint(userId, checkpointData) {
|
|
4644
|
+
if (!this.memoryManager) {
|
|
4645
|
+
console.warn("[SessionManager] No memory manager configured, skipping checkpoint record");
|
|
4646
|
+
return;
|
|
4647
|
+
}
|
|
4648
|
+
try {
|
|
4649
|
+
await this.memoryManager.recordCheckpoint(userId, checkpointData);
|
|
4650
|
+
console.log(`[SessionManager] Checkpoint ${checkpointData.checkpointId} recorded for user ${userId}`);
|
|
4651
|
+
} catch (error) {
|
|
4652
|
+
console.error("[SessionManager] Failed to record checkpoint:", error);
|
|
4653
|
+
}
|
|
4654
|
+
}
|
|
4655
|
+
/**
|
|
4656
|
+
* Record a rollback to a checkpoint.
|
|
4657
|
+
*
|
|
4658
|
+
* @param userId - The user who performed the rollback
|
|
4659
|
+
* @param checkpointId - The checkpoint rolled back to
|
|
4660
|
+
* @param reason - Optional reason for rollback
|
|
4661
|
+
* @returns Promise that resolves when rollback is recorded
|
|
4662
|
+
*/
|
|
4663
|
+
async recordRollback(userId, checkpointId, reason) {
|
|
4664
|
+
if (!this.memoryManager) {
|
|
4665
|
+
console.warn("[SessionManager] No memory manager configured, skipping rollback record");
|
|
4666
|
+
return;
|
|
4667
|
+
}
|
|
4668
|
+
try {
|
|
4669
|
+
await this.memoryManager.recordRollback(userId, checkpointId, reason);
|
|
4670
|
+
console.log(`[SessionManager] Rollback to ${checkpointId} recorded for user ${userId}`);
|
|
4671
|
+
} catch (error) {
|
|
4672
|
+
console.error("[SessionManager] Failed to record rollback:", error);
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4675
|
+
/**
|
|
4676
|
+
* Mark a checkpoint as successful (terminal state).
|
|
4677
|
+
*
|
|
4678
|
+
* @param userId - The user who owns this checkpoint
|
|
4679
|
+
* @param checkpointId - The checkpoint that was successful
|
|
4680
|
+
* @returns Promise that resolves when success is recorded
|
|
4681
|
+
*/
|
|
4682
|
+
async markCheckpointSuccessful(userId, checkpointId) {
|
|
4683
|
+
if (!this.memoryManager) {
|
|
4684
|
+
console.warn("[SessionManager] No memory manager configured, skipping success mark");
|
|
4685
|
+
return;
|
|
4686
|
+
}
|
|
4687
|
+
try {
|
|
4688
|
+
await this.memoryManager.markCheckpointSuccessful(userId, checkpointId);
|
|
4689
|
+
console.log(`[SessionManager] Checkpoint ${checkpointId} marked as successful for user ${userId}`);
|
|
4690
|
+
} catch (error) {
|
|
4691
|
+
console.error("[SessionManager] Failed to mark checkpoint as successful:", error);
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
/**
|
|
4695
|
+
* Get checkpoint history for a thread.
|
|
4696
|
+
*
|
|
4697
|
+
* @param threadId - The thread to get checkpoints for
|
|
4698
|
+
* @returns Array of checkpoint records
|
|
4699
|
+
*/
|
|
4700
|
+
async getThreadCheckpoints(threadId) {
|
|
4701
|
+
if (!this.memoryManager) {
|
|
4702
|
+
return [];
|
|
4703
|
+
}
|
|
4704
|
+
return this.memoryManager.getThreadCheckpoints(threadId);
|
|
4705
|
+
}
|
|
4706
|
+
/**
|
|
4707
|
+
* Get frequently rolled-back checkpoints (problem areas).
|
|
4708
|
+
*
|
|
4709
|
+
* @param userId - The user to get problem checkpoints for
|
|
4710
|
+
* @param minRollbackCount - Minimum rollback count (default: 2)
|
|
4711
|
+
* @returns Array of checkpoint records with rollback issues
|
|
4712
|
+
*/
|
|
4713
|
+
async getProblemCheckpoints(userId, minRollbackCount = 2) {
|
|
4714
|
+
if (!this.memoryManager) {
|
|
4715
|
+
return [];
|
|
4716
|
+
}
|
|
4717
|
+
return this.memoryManager.getProblemCheckpoints(userId, minRollbackCount);
|
|
4718
|
+
}
|
|
4719
|
+
// ============================================================================
|
|
4720
|
+
// Context Compaction (GAP-005)
|
|
4721
|
+
// ============================================================================
|
|
4722
|
+
/**
|
|
4723
|
+
* Get the context compaction configuration.
|
|
4724
|
+
* @returns The compaction configuration or null if not configured.
|
|
4725
|
+
*/
|
|
4726
|
+
getCompactionConfig() {
|
|
4727
|
+
return this.compactionConfig;
|
|
4728
|
+
}
|
|
4729
|
+
/**
|
|
4730
|
+
* Check if a session's messages need compaction based on token count.
|
|
4731
|
+
* Uses character-based estimation for quick checks.
|
|
4732
|
+
*
|
|
4733
|
+
* @param messages - Array of messages to check
|
|
4734
|
+
* @returns True if compaction is recommended
|
|
4735
|
+
*/
|
|
4736
|
+
shouldCompactMessages(messages) {
|
|
4737
|
+
if (!this.compactionConfig) {
|
|
4738
|
+
return false;
|
|
4739
|
+
}
|
|
4740
|
+
const totalChars = messages.reduce((sum, msg) => {
|
|
4741
|
+
const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
4742
|
+
return sum + content.length;
|
|
4743
|
+
}, 0);
|
|
4744
|
+
const estimatedTokens = totalChars / 4;
|
|
4745
|
+
const threshold = this.compactionConfig.maxTokens ?? 15e4;
|
|
4746
|
+
return estimatedTokens > threshold * 0.8;
|
|
4747
|
+
}
|
|
4748
|
+
/**
|
|
4749
|
+
* Record a compaction event for a session.
|
|
4750
|
+
* This helps track when and why compaction occurs.
|
|
4751
|
+
*
|
|
4752
|
+
* @param threadId - The session thread ID
|
|
4753
|
+
* @param originalMessageCount - Number of messages before compaction
|
|
4754
|
+
* @param compactedMessageCount - Number of messages after compaction
|
|
4755
|
+
* @param reason - Reason for compaction
|
|
4756
|
+
*/
|
|
4757
|
+
async recordCompaction(threadId, originalMessageCount, compactedMessageCount, reason) {
|
|
4758
|
+
if (!this.memoryManager) {
|
|
4759
|
+
console.warn("[SessionManager] No memory manager configured, skipping compaction record");
|
|
4760
|
+
return;
|
|
4761
|
+
}
|
|
4762
|
+
try {
|
|
4763
|
+
const metadata = this.get(threadId);
|
|
4764
|
+
if (metadata) {
|
|
4765
|
+
const compactionInfo = {
|
|
4766
|
+
timestamp: Date.now(),
|
|
4767
|
+
originalMessageCount,
|
|
4768
|
+
compactedMessageCount,
|
|
4769
|
+
reason: reason ?? "token_limit"
|
|
4770
|
+
};
|
|
4771
|
+
const meta = metadata;
|
|
4772
|
+
const existingCompactions = meta.compactions ?? [];
|
|
4773
|
+
meta.compactions = [...existingCompactions, compactionInfo];
|
|
4774
|
+
this.store(threadId, metadata);
|
|
4775
|
+
}
|
|
4776
|
+
console.log(`[SessionManager] Compaction recorded for ${threadId}: ${originalMessageCount} \u2192 ${compactedMessageCount} messages`);
|
|
4777
|
+
} catch (error) {
|
|
4778
|
+
console.error("[SessionManager] Failed to record compaction:", error);
|
|
4779
|
+
}
|
|
4780
|
+
}
|
|
4781
|
+
/**
|
|
4782
|
+
* Get compaction history for a session.
|
|
4783
|
+
*
|
|
4784
|
+
* @param threadId - The session thread ID
|
|
4785
|
+
* @returns Array of compaction events
|
|
4786
|
+
*/
|
|
4787
|
+
getCompactionHistory(threadId) {
|
|
4788
|
+
const metadata = this.get(threadId);
|
|
4789
|
+
if (!metadata) {
|
|
4790
|
+
return [];
|
|
4791
|
+
}
|
|
4792
|
+
const meta = metadata;
|
|
4793
|
+
return meta.compactions ?? [];
|
|
4794
|
+
}
|
|
4536
4795
|
};
|
|
4537
4796
|
|
|
4538
4797
|
// src/agent/interrupt-config.ts
|
|
@@ -4693,10 +4952,30 @@ ${skillSummaries}
|
|
|
4693
4952
|
|
|
4694
4953
|
${skillContents}`;
|
|
4695
4954
|
}
|
|
4955
|
+
let userPreferences = null;
|
|
4956
|
+
let projectContext = null;
|
|
4957
|
+
if (options.memoryManager && options.userId) {
|
|
4958
|
+
try {
|
|
4959
|
+
userPreferences = await options.memoryManager.getUserPreferences(options.userId);
|
|
4960
|
+
if (userPreferences && verbose) {
|
|
4961
|
+
console.log(`[SkillAgent] Loaded user preferences: ${userPreferences.namingConvention} naming, ${userPreferences.preferredPatterns.length} patterns`);
|
|
4962
|
+
}
|
|
4963
|
+
if (options.appId) {
|
|
4964
|
+
projectContext = await options.memoryManager.getProjectContext(options.appId);
|
|
4965
|
+
if (projectContext && verbose) {
|
|
4966
|
+
console.log(`[SkillAgent] Loaded project context: ${projectContext.existingEntities.length} entities`);
|
|
4967
|
+
}
|
|
4968
|
+
}
|
|
4969
|
+
} catch (error) {
|
|
4970
|
+
console.warn("[SkillAgent] Failed to load memory:", error);
|
|
4971
|
+
}
|
|
4972
|
+
}
|
|
4973
|
+
const memoryContext = buildMemoryContext(userPreferences, projectContext);
|
|
4696
4974
|
const systemPrompt = [
|
|
4697
4975
|
BASE_SYSTEM_PROMPT,
|
|
4698
4976
|
"\n## Skill Instructions\n\n" + skillInstructions,
|
|
4699
|
-
references ? "\n## Reference Documentation\n\n" + references : ""
|
|
4977
|
+
references ? "\n## Reference Documentation\n\n" + references : "",
|
|
4978
|
+
memoryContext ? "\n## User Context\n\n" + memoryContext : ""
|
|
4700
4979
|
].filter(Boolean).join("\n");
|
|
4701
4980
|
const threadId = providedThreadId || v4();
|
|
4702
4981
|
const llmClient = createLLMClient(provider, model, verbose);
|
|
@@ -4799,9 +5078,54 @@ ${skillContents}`;
|
|
|
4799
5078
|
workDir,
|
|
4800
5079
|
setOrbitalEventCallback,
|
|
4801
5080
|
setOrbitalCompleteCallback,
|
|
4802
|
-
setDomainCompleteCallback
|
|
5081
|
+
setDomainCompleteCallback,
|
|
5082
|
+
userPreferences,
|
|
5083
|
+
projectContext,
|
|
5084
|
+
memoryManager: options.memoryManager
|
|
4803
5085
|
};
|
|
4804
5086
|
}
|
|
5087
|
+
function buildMemoryContext(userPreferences, projectContext) {
|
|
5088
|
+
const sections = [];
|
|
5089
|
+
if (userPreferences) {
|
|
5090
|
+
const prefs = [];
|
|
5091
|
+
if (userPreferences.namingConvention) {
|
|
5092
|
+
prefs.push(`- Preferred naming: ${userPreferences.namingConvention}`);
|
|
5093
|
+
}
|
|
5094
|
+
if (userPreferences.validationStyle) {
|
|
5095
|
+
prefs.push(`- Validation style: ${userPreferences.validationStyle}`);
|
|
5096
|
+
}
|
|
5097
|
+
if (userPreferences.preferredPatterns.length > 0) {
|
|
5098
|
+
prefs.push(`- Preferred patterns: ${userPreferences.preferredPatterns.join(", ")}`);
|
|
5099
|
+
}
|
|
5100
|
+
if (userPreferences.commonEntities.length > 0) {
|
|
5101
|
+
prefs.push(`- Commonly used entities: ${userPreferences.commonEntities.join(", ")}`);
|
|
5102
|
+
}
|
|
5103
|
+
if (prefs.length > 0) {
|
|
5104
|
+
sections.push(`### User Preferences
|
|
5105
|
+
${prefs.join("\n")}`);
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
5108
|
+
if (projectContext) {
|
|
5109
|
+
const ctx = [];
|
|
5110
|
+
if (projectContext.projectName) {
|
|
5111
|
+
ctx.push(`- Project: ${projectContext.projectName}`);
|
|
5112
|
+
}
|
|
5113
|
+
if (projectContext.domain) {
|
|
5114
|
+
ctx.push(`- Domain: ${projectContext.domain}`);
|
|
5115
|
+
}
|
|
5116
|
+
if (projectContext.existingEntities.length > 0) {
|
|
5117
|
+
ctx.push(`- Existing entities: ${projectContext.existingEntities.join(", ")}`);
|
|
5118
|
+
}
|
|
5119
|
+
if (projectContext.conventions.length > 0) {
|
|
5120
|
+
ctx.push(`- Project conventions: ${projectContext.conventions.join(", ")}`);
|
|
5121
|
+
}
|
|
5122
|
+
if (ctx.length > 0) {
|
|
5123
|
+
sections.push(`### Project Context
|
|
5124
|
+
${ctx.join("\n")}`);
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
return sections.length > 0 ? sections.join("\n\n") : null;
|
|
5128
|
+
}
|
|
4805
5129
|
async function resumeSkillAgent(threadId, options) {
|
|
4806
5130
|
const sessions = options.sessionManager ?? getDefaultSessionManager();
|
|
4807
5131
|
const metadata = sessions.get(threadId);
|
|
@@ -5310,11 +5634,1753 @@ function extractFileOperation(event) {
|
|
|
5310
5634
|
}
|
|
5311
5635
|
return null;
|
|
5312
5636
|
}
|
|
5637
|
+
|
|
5638
|
+
// src/memory/memory-orbital.ts
|
|
5639
|
+
var UserPreferenceEntity = {
|
|
5640
|
+
name: "UserPreference",
|
|
5641
|
+
persistence: "persistent",
|
|
5642
|
+
fields: [
|
|
5643
|
+
{ name: "id", type: "string", required: true },
|
|
5644
|
+
{ name: "userId", type: "string", required: true },
|
|
5645
|
+
{ name: "namingConvention", type: "enum", values: ["PascalCase", "camelCase", "snake_case"], default: "PascalCase" },
|
|
5646
|
+
{ name: "validationStyle", type: "enum", values: ["strict", "minimal", "none"], default: "strict" },
|
|
5647
|
+
{ name: "preferredPatterns", type: "array", items: { name: "pattern", type: "string" }, default: [] },
|
|
5648
|
+
{ name: "commonEntities", type: "array", items: { name: "entity", type: "string" }, default: [] },
|
|
5649
|
+
{ name: "commonTraits", type: "array", items: { name: "trait", type: "string" }, default: [] },
|
|
5650
|
+
{ name: "learnedAt", type: "timestamp" },
|
|
5651
|
+
{ name: "confidence", type: "number", default: 0.5 }
|
|
5652
|
+
]
|
|
5653
|
+
};
|
|
5654
|
+
var GenerationSessionEntity = {
|
|
5655
|
+
name: "GenerationSession",
|
|
5656
|
+
persistence: "persistent",
|
|
5657
|
+
fields: [
|
|
5658
|
+
{ name: "id", type: "string", required: true },
|
|
5659
|
+
{ name: "userId", type: "string", required: true },
|
|
5660
|
+
{ name: "threadId", type: "string", required: true },
|
|
5661
|
+
{ name: "prompt", type: "string", required: true },
|
|
5662
|
+
{ name: "skill", type: "string", required: true },
|
|
5663
|
+
{ name: "entities", type: "array", items: { name: "entity", type: "string" }, default: [] },
|
|
5664
|
+
{ name: "patterns", type: "array", items: { name: "pattern", type: "string" }, default: [] },
|
|
5665
|
+
{ name: "createdAt", type: "timestamp", required: true },
|
|
5666
|
+
{ name: "completedAt", type: "timestamp" },
|
|
5667
|
+
{ name: "success", type: "boolean", default: false }
|
|
5668
|
+
]
|
|
5669
|
+
};
|
|
5670
|
+
var ProjectContextEntity = {
|
|
5671
|
+
name: "ProjectContext",
|
|
5672
|
+
persistence: "persistent",
|
|
5673
|
+
fields: [
|
|
5674
|
+
{ name: "id", type: "string", required: true },
|
|
5675
|
+
{ name: "appId", type: "string", required: true },
|
|
5676
|
+
{ name: "userId", type: "string", required: true },
|
|
5677
|
+
{ name: "projectName", type: "string" },
|
|
5678
|
+
{ name: "description", type: "string" },
|
|
5679
|
+
{ name: "existingEntities", type: "array", items: { name: "entity", type: "string" }, default: [] },
|
|
5680
|
+
{ name: "conventions", type: "array", items: { name: "convention", type: "string" }, default: [] },
|
|
5681
|
+
{ name: "domain", type: "enum", values: ["business", "ecommerce", "cms", "dashboard", "workflow"], default: "business" },
|
|
5682
|
+
{ name: "lastUpdatedAt", type: "timestamp", required: true }
|
|
5683
|
+
]
|
|
5684
|
+
};
|
|
5685
|
+
var MemoryOrbitalSchema = {
|
|
5686
|
+
name: "AgentMemory",
|
|
5687
|
+
version: "1.0.0",
|
|
5688
|
+
description: "Memory system for KFlow DeepAgent - stores user preferences, generation history, and project context",
|
|
5689
|
+
orbitals: [
|
|
5690
|
+
{
|
|
5691
|
+
name: "UserPreferenceMemory",
|
|
5692
|
+
entity: UserPreferenceEntity,
|
|
5693
|
+
traits: [],
|
|
5694
|
+
pages: []
|
|
5695
|
+
},
|
|
5696
|
+
{
|
|
5697
|
+
name: "GenerationHistoryMemory",
|
|
5698
|
+
entity: GenerationSessionEntity,
|
|
5699
|
+
traits: [],
|
|
5700
|
+
pages: []
|
|
5701
|
+
},
|
|
5702
|
+
{
|
|
5703
|
+
name: "ProjectContextMemory",
|
|
5704
|
+
entity: ProjectContextEntity,
|
|
5705
|
+
traits: [],
|
|
5706
|
+
pages: []
|
|
5707
|
+
}
|
|
5708
|
+
]
|
|
5709
|
+
};
|
|
5710
|
+
|
|
5711
|
+
// src/memory/MemoryManager.ts
|
|
5712
|
+
var MemoryManager = class {
|
|
5713
|
+
constructor(options) {
|
|
5714
|
+
this.db = options.db;
|
|
5715
|
+
this.usersCollection = options.usersCollection ?? "agent_memory_users";
|
|
5716
|
+
this.generationsCollection = options.generationsCollection ?? "agent_memory_generations";
|
|
5717
|
+
this.projectsCollection = options.projectsCollection ?? "agent_memory_projects";
|
|
5718
|
+
this.patternsCollection = options.patternsCollection ?? "agent_memory_patterns";
|
|
5719
|
+
this.feedbackCollection = options.feedbackCollection ?? "agent_memory_feedback";
|
|
5720
|
+
this.interruptsCollection = options.interruptsCollection ?? "agent_memory_interrupts";
|
|
5721
|
+
this.toolPreferencesCollection = options.toolPreferencesCollection ?? "agent_memory_tool_preferences";
|
|
5722
|
+
this.checkpointsCollection = options.checkpointsCollection ?? "agent_memory_checkpoints";
|
|
5723
|
+
}
|
|
5724
|
+
// ============================================================================
|
|
5725
|
+
// User Preferences
|
|
5726
|
+
// ============================================================================
|
|
5727
|
+
/**
|
|
5728
|
+
* Get user preferences with defaults
|
|
5729
|
+
*/
|
|
5730
|
+
async getUserPreferences(userId) {
|
|
5731
|
+
const doc = await this.db.collection(this.usersCollection).doc(userId).get();
|
|
5732
|
+
if (!doc.exists) return null;
|
|
5733
|
+
return this.parsePreference(doc.data());
|
|
5734
|
+
}
|
|
5735
|
+
/**
|
|
5736
|
+
* Update user preferences
|
|
5737
|
+
*/
|
|
5738
|
+
async updateUserPreferences(userId, preferences) {
|
|
5739
|
+
const existing = await this.getUserPreferences(userId);
|
|
5740
|
+
const merged = {
|
|
5741
|
+
id: existing?.id ?? `pref_${Date.now()}`,
|
|
5742
|
+
userId,
|
|
5743
|
+
namingConvention: preferences.namingConvention ?? existing?.namingConvention ?? "PascalCase",
|
|
5744
|
+
validationStyle: preferences.validationStyle ?? existing?.validationStyle ?? "strict",
|
|
5745
|
+
preferredPatterns: [
|
|
5746
|
+
...existing?.preferredPatterns ?? [],
|
|
5747
|
+
...preferences.preferredPatterns ?? []
|
|
5748
|
+
],
|
|
5749
|
+
commonEntities: [
|
|
5750
|
+
...existing?.commonEntities ?? [],
|
|
5751
|
+
...preferences.commonEntities ?? []
|
|
5752
|
+
],
|
|
5753
|
+
commonTraits: [
|
|
5754
|
+
...existing?.commonTraits ?? [],
|
|
5755
|
+
...preferences.commonTraits ?? []
|
|
5756
|
+
],
|
|
5757
|
+
learnedAt: existing?.learnedAt ?? /* @__PURE__ */ new Date(),
|
|
5758
|
+
confidence: preferences.confidence ?? existing?.confidence ?? 0.5
|
|
5759
|
+
};
|
|
5760
|
+
await this.db.collection(this.usersCollection).doc(userId).set(this.serializePreference(merged));
|
|
5761
|
+
}
|
|
5762
|
+
// ============================================================================
|
|
5763
|
+
// Generation Session History
|
|
5764
|
+
// ============================================================================
|
|
5765
|
+
/**
|
|
5766
|
+
* Record a new generation session
|
|
5767
|
+
*/
|
|
5768
|
+
async recordGeneration(userId, session) {
|
|
5769
|
+
const sessionId = `gen_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
5770
|
+
const fullSession = {
|
|
5771
|
+
id: sessionId,
|
|
5772
|
+
userId,
|
|
5773
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
5774
|
+
...session
|
|
5775
|
+
};
|
|
5776
|
+
await this.db.collection(this.generationsCollection).doc(sessionId).set(this.serializeSession(fullSession));
|
|
5777
|
+
return sessionId;
|
|
5778
|
+
}
|
|
5779
|
+
/**
|
|
5780
|
+
* Get a specific generation session
|
|
5781
|
+
*/
|
|
5782
|
+
async getGenerationSession(sessionId) {
|
|
5783
|
+
const doc = await this.db.collection(this.generationsCollection).doc(sessionId).get();
|
|
5784
|
+
if (!doc.exists) return null;
|
|
5785
|
+
return this.parseSession(doc.data());
|
|
5786
|
+
}
|
|
5787
|
+
/**
|
|
5788
|
+
* Get generation history for a user
|
|
5789
|
+
*/
|
|
5790
|
+
async getUserGenerationHistory(userId, limit = 50) {
|
|
5791
|
+
const snapshot = await this.db.collection(this.generationsCollection).where("userId", "==", userId).orderBy("createdAt", "desc").limit(limit).get();
|
|
5792
|
+
return snapshot.docs.map((doc) => this.parseSession(doc.data()));
|
|
5793
|
+
}
|
|
5794
|
+
/**
|
|
5795
|
+
* Update generation session status
|
|
5796
|
+
*/
|
|
5797
|
+
async updateGenerationStatus(sessionId, status, validationResult) {
|
|
5798
|
+
const doc = await this.db.collection(this.generationsCollection).doc(sessionId).get();
|
|
5799
|
+
if (!doc.exists) return;
|
|
5800
|
+
const data = doc.data();
|
|
5801
|
+
await this.db.collection(this.generationsCollection).doc(sessionId).set({
|
|
5802
|
+
...data,
|
|
5803
|
+
success: status,
|
|
5804
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
5805
|
+
...validationResult && { validationResult }
|
|
5806
|
+
});
|
|
5807
|
+
}
|
|
5808
|
+
// ============================================================================
|
|
5809
|
+
// Project Context
|
|
5810
|
+
// ============================================================================
|
|
5811
|
+
/**
|
|
5812
|
+
* Get project context
|
|
5813
|
+
*/
|
|
5814
|
+
async getProjectContext(appId) {
|
|
5815
|
+
const doc = await this.db.collection(this.projectsCollection).doc(appId).get();
|
|
5816
|
+
if (!doc.exists) return null;
|
|
5817
|
+
return this.parseContext(doc.data());
|
|
5818
|
+
}
|
|
5819
|
+
/**
|
|
5820
|
+
* Update project context with new information
|
|
5821
|
+
*/
|
|
5822
|
+
async updateProjectContext(appId, update) {
|
|
5823
|
+
const existing = await this.getProjectContext(appId);
|
|
5824
|
+
if (!existing) {
|
|
5825
|
+
if (!update.userId) {
|
|
5826
|
+
throw new Error("userId is required when creating new project context");
|
|
5827
|
+
}
|
|
5828
|
+
const newContext = {
|
|
5829
|
+
id: `ctx_${Date.now()}`,
|
|
5830
|
+
appId,
|
|
5831
|
+
userId: update.userId,
|
|
5832
|
+
existingEntities: update.existingEntities ?? [],
|
|
5833
|
+
conventions: update.conventions ?? [],
|
|
5834
|
+
domain: update.domain ?? "business",
|
|
5835
|
+
lastUpdatedAt: /* @__PURE__ */ new Date(),
|
|
5836
|
+
...update.projectName && { projectName: update.projectName },
|
|
5837
|
+
...update.description && { description: update.description }
|
|
5838
|
+
};
|
|
5839
|
+
await this.db.collection(this.projectsCollection).doc(appId).set(this.serializeContext(newContext));
|
|
5840
|
+
return;
|
|
5841
|
+
}
|
|
5842
|
+
const merged = {
|
|
5843
|
+
...existing,
|
|
5844
|
+
existingEntities: [
|
|
5845
|
+
...existing.existingEntities,
|
|
5846
|
+
...update.existingEntities ?? []
|
|
5847
|
+
],
|
|
5848
|
+
conventions: [
|
|
5849
|
+
...existing.conventions,
|
|
5850
|
+
...update.conventions ?? []
|
|
5851
|
+
],
|
|
5852
|
+
lastUpdatedAt: /* @__PURE__ */ new Date(),
|
|
5853
|
+
...update.projectName && { projectName: update.projectName },
|
|
5854
|
+
...update.description && { description: update.description },
|
|
5855
|
+
...update.domain && { domain: update.domain }
|
|
5856
|
+
};
|
|
5857
|
+
await this.db.collection(this.projectsCollection).doc(appId).set(this.serializeContext(merged));
|
|
5858
|
+
}
|
|
5859
|
+
// ============================================================================
|
|
5860
|
+
// Pattern Affinity
|
|
5861
|
+
// ============================================================================
|
|
5862
|
+
/**
|
|
5863
|
+
* Update pattern affinity based on usage
|
|
5864
|
+
*/
|
|
5865
|
+
async updatePatternAffinity(userId, patternId, outcome, context) {
|
|
5866
|
+
const affinityId = `${userId}_${patternId}`;
|
|
5867
|
+
const existing = await this.db.collection(this.patternsCollection).doc(affinityId).get();
|
|
5868
|
+
if (!existing.exists) {
|
|
5869
|
+
const affinity = {
|
|
5870
|
+
userId,
|
|
5871
|
+
patternId,
|
|
5872
|
+
usageCount: 1,
|
|
5873
|
+
successCount: outcome === "success" ? 1 : 0,
|
|
5874
|
+
failureCount: outcome === "failure" ? 1 : 0,
|
|
5875
|
+
contexts: context ? [context] : [],
|
|
5876
|
+
lastUsedAt: /* @__PURE__ */ new Date(),
|
|
5877
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
5878
|
+
};
|
|
5879
|
+
await this.db.collection(this.patternsCollection).doc(affinityId).set(affinity);
|
|
5880
|
+
} else {
|
|
5881
|
+
const data = existing.data();
|
|
5882
|
+
const affinity = {
|
|
5883
|
+
...data,
|
|
5884
|
+
usageCount: data.usageCount + 1,
|
|
5885
|
+
successCount: data.successCount + (outcome === "success" ? 1 : 0),
|
|
5886
|
+
failureCount: data.failureCount + (outcome === "failure" ? 1 : 0),
|
|
5887
|
+
contexts: context ? [...data.contexts ?? [], context] : data.contexts,
|
|
5888
|
+
lastUsedAt: /* @__PURE__ */ new Date()
|
|
5889
|
+
};
|
|
5890
|
+
await this.db.collection(this.patternsCollection).doc(affinityId).set(affinity);
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5893
|
+
/**
|
|
5894
|
+
* Get pattern affinity for a user
|
|
5895
|
+
*/
|
|
5896
|
+
async getPatternAffinity(userId, patternId) {
|
|
5897
|
+
const affinityId = `${userId}_${patternId}`;
|
|
5898
|
+
const doc = await this.db.collection(this.patternsCollection).doc(affinityId).get();
|
|
5899
|
+
if (!doc.exists) return null;
|
|
5900
|
+
return doc.data();
|
|
5901
|
+
}
|
|
5902
|
+
/**
|
|
5903
|
+
* Get all patterns used by a user
|
|
5904
|
+
*/
|
|
5905
|
+
async getUserPatterns(userId) {
|
|
5906
|
+
const snapshot = await this.db.collection(this.patternsCollection).where("userId", "==", userId).orderBy("usageCount", "desc").get();
|
|
5907
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
5908
|
+
}
|
|
5909
|
+
// ============================================================================
|
|
5910
|
+
// User Feedback
|
|
5911
|
+
// ============================================================================
|
|
5912
|
+
/**
|
|
5913
|
+
* Record user feedback on a generation
|
|
5914
|
+
*/
|
|
5915
|
+
async recordFeedback(sessionId, feedback) {
|
|
5916
|
+
const feedbackId = `fb_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
5917
|
+
const fullFeedback = {
|
|
5918
|
+
feedbackId,
|
|
5919
|
+
sessionId,
|
|
5920
|
+
...feedback,
|
|
5921
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
5922
|
+
};
|
|
5923
|
+
await this.db.collection(this.feedbackCollection).doc(feedbackId).set(fullFeedback);
|
|
5924
|
+
}
|
|
5925
|
+
/**
|
|
5926
|
+
* Get feedback for a session
|
|
5927
|
+
*/
|
|
5928
|
+
async getSessionFeedback(sessionId) {
|
|
5929
|
+
const snapshot = await this.db.collection(this.feedbackCollection).where("sessionId", "==", sessionId).orderBy("timestamp", "desc").get();
|
|
5930
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
5931
|
+
}
|
|
5932
|
+
// ============================================================================
|
|
5933
|
+
// Serialization Helpers
|
|
5934
|
+
// ============================================================================
|
|
5935
|
+
parsePreference(data) {
|
|
5936
|
+
const timestampToDate = (ts) => {
|
|
5937
|
+
if (ts instanceof Date) return ts;
|
|
5938
|
+
if (typeof ts === "object" && ts !== null && "toDate" in ts) {
|
|
5939
|
+
return ts.toDate();
|
|
5940
|
+
}
|
|
5941
|
+
return new Date(ts);
|
|
5942
|
+
};
|
|
5943
|
+
return {
|
|
5944
|
+
id: data.id,
|
|
5945
|
+
userId: data.userId,
|
|
5946
|
+
namingConvention: data.namingConvention,
|
|
5947
|
+
validationStyle: data.validationStyle,
|
|
5948
|
+
preferredPatterns: data.preferredPatterns ?? [],
|
|
5949
|
+
commonEntities: data.commonEntities ?? [],
|
|
5950
|
+
commonTraits: data.commonTraits ?? [],
|
|
5951
|
+
learnedAt: timestampToDate(data.learnedAt),
|
|
5952
|
+
confidence: data.confidence ?? 0.5
|
|
5953
|
+
};
|
|
5954
|
+
}
|
|
5955
|
+
serializePreference(pref) {
|
|
5956
|
+
return { ...pref };
|
|
5957
|
+
}
|
|
5958
|
+
parseSession(data) {
|
|
5959
|
+
const timestampToDate = (ts) => {
|
|
5960
|
+
if (ts instanceof Date) return ts;
|
|
5961
|
+
if (typeof ts === "object" && ts !== null && "toDate" in ts) {
|
|
5962
|
+
return ts.toDate();
|
|
5963
|
+
}
|
|
5964
|
+
return new Date(ts);
|
|
5965
|
+
};
|
|
5966
|
+
return {
|
|
5967
|
+
id: data.id,
|
|
5968
|
+
userId: data.userId,
|
|
5969
|
+
threadId: data.threadId,
|
|
5970
|
+
prompt: data.prompt,
|
|
5971
|
+
skill: data.skill,
|
|
5972
|
+
generatedSchema: data.generatedSchema,
|
|
5973
|
+
entities: data.entities ?? [],
|
|
5974
|
+
patterns: data.patterns ?? [],
|
|
5975
|
+
validationResult: data.validationResult,
|
|
5976
|
+
createdAt: timestampToDate(data.createdAt),
|
|
5977
|
+
completedAt: data.completedAt ? timestampToDate(data.completedAt) : void 0,
|
|
5978
|
+
success: data.success
|
|
5979
|
+
};
|
|
5980
|
+
}
|
|
5981
|
+
serializeSession(session) {
|
|
5982
|
+
return { ...session };
|
|
5983
|
+
}
|
|
5984
|
+
parseContext(data) {
|
|
5985
|
+
const timestampToDate = (ts) => {
|
|
5986
|
+
if (ts instanceof Date) return ts;
|
|
5987
|
+
if (typeof ts === "object" && ts !== null && "toDate" in ts) {
|
|
5988
|
+
return ts.toDate();
|
|
5989
|
+
}
|
|
5990
|
+
return new Date(ts);
|
|
5991
|
+
};
|
|
5992
|
+
return {
|
|
5993
|
+
id: data.id,
|
|
5994
|
+
appId: data.appId,
|
|
5995
|
+
userId: data.userId,
|
|
5996
|
+
projectName: data.projectName,
|
|
5997
|
+
description: data.description,
|
|
5998
|
+
existingEntities: data.existingEntities ?? [],
|
|
5999
|
+
conventions: data.conventions ?? [],
|
|
6000
|
+
domain: data.domain,
|
|
6001
|
+
lastUpdatedAt: timestampToDate(data.lastUpdatedAt)
|
|
6002
|
+
};
|
|
6003
|
+
}
|
|
6004
|
+
serializeContext(context) {
|
|
6005
|
+
return { ...context };
|
|
6006
|
+
}
|
|
6007
|
+
// ============================================================================
|
|
6008
|
+
// Interrupt Tracking (GAP-003: Interrupt Memory)
|
|
6009
|
+
// ============================================================================
|
|
6010
|
+
/**
|
|
6011
|
+
* Record an interrupt decision for learning
|
|
6012
|
+
*/
|
|
6013
|
+
async recordInterruptDecision(sessionId, userId, interruptData) {
|
|
6014
|
+
const interruptId = `int_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
6015
|
+
const record = {
|
|
6016
|
+
interruptId,
|
|
6017
|
+
sessionId,
|
|
6018
|
+
userId,
|
|
6019
|
+
toolName: interruptData.toolName,
|
|
6020
|
+
toolArgs: interruptData.toolArgs,
|
|
6021
|
+
decision: interruptData.decision,
|
|
6022
|
+
modifiedArgs: interruptData.modifiedArgs,
|
|
6023
|
+
reason: interruptData.reason,
|
|
6024
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
6025
|
+
};
|
|
6026
|
+
await this.db.collection(this.interruptsCollection).doc(interruptId).set(record);
|
|
6027
|
+
await this.updateToolApprovalPreference(userId, interruptData.toolName, interruptData.decision);
|
|
6028
|
+
}
|
|
6029
|
+
/**
|
|
6030
|
+
* Get interrupt history for a session
|
|
6031
|
+
*/
|
|
6032
|
+
async getSessionInterrupts(sessionId) {
|
|
6033
|
+
const snapshot = await this.db.collection(this.interruptsCollection).where("sessionId", "==", sessionId).orderBy("timestamp", "desc").get();
|
|
6034
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
6035
|
+
}
|
|
6036
|
+
/**
|
|
6037
|
+
* Get interrupt history for a user
|
|
6038
|
+
*/
|
|
6039
|
+
async getUserInterrupts(userId, limit = 50) {
|
|
6040
|
+
const snapshot = await this.db.collection(this.interruptsCollection).where("userId", "==", userId).orderBy("timestamp", "desc").limit(limit).get();
|
|
6041
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
6042
|
+
}
|
|
6043
|
+
/**
|
|
6044
|
+
* Get tool approval preference for a user
|
|
6045
|
+
*/
|
|
6046
|
+
async getToolApprovalPreference(userId, toolName) {
|
|
6047
|
+
const prefId = `${userId}_${toolName}`;
|
|
6048
|
+
const doc = await this.db.collection(this.toolPreferencesCollection).doc(prefId).get();
|
|
6049
|
+
if (!doc.exists) return null;
|
|
6050
|
+
return doc.data();
|
|
6051
|
+
}
|
|
6052
|
+
/**
|
|
6053
|
+
* Update tool approval preference based on interrupt decisions
|
|
6054
|
+
*/
|
|
6055
|
+
async updateToolApprovalPreference(userId, toolName, decision) {
|
|
6056
|
+
const prefId = `${userId}_${toolName}`;
|
|
6057
|
+
const existing = await this.db.collection(this.toolPreferencesCollection).doc(prefId).get();
|
|
6058
|
+
if (!existing.exists) {
|
|
6059
|
+
const pref = {
|
|
6060
|
+
userId,
|
|
6061
|
+
toolName,
|
|
6062
|
+
autoApprove: decision === "approved",
|
|
6063
|
+
confidence: decision === "approved" ? 0.5 : 0,
|
|
6064
|
+
approvedCount: decision === "approved" ? 1 : 0,
|
|
6065
|
+
rejectedCount: decision === "rejected" ? 1 : 0,
|
|
6066
|
+
lastDecisionAt: /* @__PURE__ */ new Date()
|
|
6067
|
+
};
|
|
6068
|
+
await this.db.collection(this.toolPreferencesCollection).doc(prefId).set(pref);
|
|
6069
|
+
} else {
|
|
6070
|
+
const data = existing.data();
|
|
6071
|
+
const approvedCount = data.approvedCount + (decision === "approved" ? 1 : 0);
|
|
6072
|
+
const rejectedCount = data.rejectedCount + (decision === "rejected" ? 1 : 0);
|
|
6073
|
+
const total = approvedCount + rejectedCount;
|
|
6074
|
+
const approvalRate = approvedCount / total;
|
|
6075
|
+
const pref = {
|
|
6076
|
+
...data,
|
|
6077
|
+
approvedCount,
|
|
6078
|
+
rejectedCount,
|
|
6079
|
+
// Auto-approve if approval rate > 80% and at least 5 decisions
|
|
6080
|
+
autoApprove: total >= 5 && approvalRate > 0.8,
|
|
6081
|
+
confidence: Math.min(0.95, total * 0.1),
|
|
6082
|
+
lastDecisionAt: /* @__PURE__ */ new Date()
|
|
6083
|
+
};
|
|
6084
|
+
await this.db.collection(this.toolPreferencesCollection).doc(prefId).set(pref);
|
|
6085
|
+
}
|
|
6086
|
+
}
|
|
6087
|
+
/**
|
|
6088
|
+
* Get all tool approval preferences for a user
|
|
6089
|
+
*/
|
|
6090
|
+
async getUserToolPreferences(userId) {
|
|
6091
|
+
const snapshot = await this.db.collection(this.toolPreferencesCollection).where("userId", "==", userId).get();
|
|
6092
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
6093
|
+
}
|
|
6094
|
+
/**
|
|
6095
|
+
* Check if a tool should be auto-approved for a user
|
|
6096
|
+
*/
|
|
6097
|
+
async shouldAutoApproveTool(userId, toolName) {
|
|
6098
|
+
const pref = await this.getToolApprovalPreference(userId, toolName);
|
|
6099
|
+
return pref?.autoApprove ?? false;
|
|
6100
|
+
}
|
|
6101
|
+
// ============================================================================
|
|
6102
|
+
// Checkpoint Tracking (GAP-004: Checkpoint → Memory)
|
|
6103
|
+
// ============================================================================
|
|
6104
|
+
/**
|
|
6105
|
+
* Record a checkpoint for learning
|
|
6106
|
+
*/
|
|
6107
|
+
async recordCheckpoint(userId, checkpointData) {
|
|
6108
|
+
const record = {
|
|
6109
|
+
checkpointId: checkpointData.checkpointId,
|
|
6110
|
+
threadId: checkpointData.threadId,
|
|
6111
|
+
userId,
|
|
6112
|
+
parentCheckpointId: checkpointData.parentCheckpointId,
|
|
6113
|
+
metadata: checkpointData.metadata ?? {},
|
|
6114
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
6115
|
+
rollbackCount: 0,
|
|
6116
|
+
wasSuccessful: false
|
|
6117
|
+
};
|
|
6118
|
+
const docId = `${userId}_${checkpointData.checkpointId}`;
|
|
6119
|
+
await this.db.collection(this.checkpointsCollection).doc(docId).set(record);
|
|
6120
|
+
}
|
|
6121
|
+
/**
|
|
6122
|
+
* Record a rollback to a checkpoint
|
|
6123
|
+
*/
|
|
6124
|
+
async recordRollback(userId, checkpointId, reason) {
|
|
6125
|
+
const docId = `${userId}_${checkpointId}`;
|
|
6126
|
+
const doc = await this.db.collection(this.checkpointsCollection).doc(docId).get();
|
|
6127
|
+
if (doc.exists) {
|
|
6128
|
+
const data = doc.data();
|
|
6129
|
+
await this.db.collection(this.checkpointsCollection).doc(docId).set({
|
|
6130
|
+
...data,
|
|
6131
|
+
rollbackCount: data.rollbackCount + 1,
|
|
6132
|
+
lastRollbackReason: reason,
|
|
6133
|
+
lastRollbackAt: /* @__PURE__ */ new Date()
|
|
6134
|
+
});
|
|
6135
|
+
}
|
|
6136
|
+
}
|
|
6137
|
+
/**
|
|
6138
|
+
* Mark a checkpoint as successful (terminal state)
|
|
6139
|
+
*/
|
|
6140
|
+
async markCheckpointSuccessful(userId, checkpointId) {
|
|
6141
|
+
const docId = `${userId}_${checkpointId}`;
|
|
6142
|
+
const doc = await this.db.collection(this.checkpointsCollection).doc(docId).get();
|
|
6143
|
+
if (doc.exists) {
|
|
6144
|
+
const data = doc.data();
|
|
6145
|
+
await this.db.collection(this.checkpointsCollection).doc(docId).set({
|
|
6146
|
+
...data,
|
|
6147
|
+
wasSuccessful: true
|
|
6148
|
+
});
|
|
6149
|
+
}
|
|
6150
|
+
}
|
|
6151
|
+
/**
|
|
6152
|
+
* Get checkpoint history for a user
|
|
6153
|
+
*/
|
|
6154
|
+
async getUserCheckpoints(userId, limit = 50) {
|
|
6155
|
+
const snapshot = await this.db.collection(this.checkpointsCollection).where("userId", "==", userId).orderBy("createdAt", "desc").limit(limit).get();
|
|
6156
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
6157
|
+
}
|
|
6158
|
+
/**
|
|
6159
|
+
* Get checkpoints for a thread
|
|
6160
|
+
*/
|
|
6161
|
+
async getThreadCheckpoints(threadId) {
|
|
6162
|
+
const snapshot = await this.db.collection(this.checkpointsCollection).where("threadId", "==", threadId).orderBy("createdAt", "desc").get();
|
|
6163
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
6164
|
+
}
|
|
6165
|
+
/**
|
|
6166
|
+
* Get frequently rolled-back checkpoints (problem areas)
|
|
6167
|
+
*/
|
|
6168
|
+
async getProblemCheckpoints(userId, minRollbackCount = 2) {
|
|
6169
|
+
const snapshot = await this.db.collection(this.checkpointsCollection).where("userId", "==", userId).where("rollbackCount", ">=", minRollbackCount).orderBy("rollbackCount", "desc").get();
|
|
6170
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
6171
|
+
}
|
|
6172
|
+
/**
|
|
6173
|
+
* Get successful checkpoint patterns for learning
|
|
6174
|
+
*/
|
|
6175
|
+
async getSuccessfulCheckpoints(userId, limit = 20) {
|
|
6176
|
+
const snapshot = await this.db.collection(this.checkpointsCollection).where("userId", "==", userId).where("wasSuccessful", "==", true).orderBy("createdAt", "desc").limit(limit).get();
|
|
6177
|
+
return snapshot.docs.map((doc) => doc.data());
|
|
6178
|
+
}
|
|
6179
|
+
};
|
|
6180
|
+
var PreferenceLearner = class {
|
|
6181
|
+
constructor(options) {
|
|
6182
|
+
this.llmClient = options.llmClient ?? createRequirementsClient();
|
|
6183
|
+
this.memoryManager = options.memoryManager;
|
|
6184
|
+
this.confidenceThreshold = options.confidenceThreshold ?? 0.7;
|
|
6185
|
+
}
|
|
6186
|
+
/**
|
|
6187
|
+
* Analyze a session and infer user preferences
|
|
6188
|
+
*/
|
|
6189
|
+
async analyzeSession(session) {
|
|
6190
|
+
const prompt = this.buildAnalysisPrompt(session);
|
|
6191
|
+
const content = await this.llmClient.call({
|
|
6192
|
+
systemPrompt: "You analyze generation sessions and infer user preferences. Respond with JSON.",
|
|
6193
|
+
userPrompt: prompt
|
|
6194
|
+
});
|
|
6195
|
+
return this.parseAnalysisResponse(content);
|
|
6196
|
+
}
|
|
6197
|
+
/**
|
|
6198
|
+
* Learn from a session and update preferences if confidence is high
|
|
6199
|
+
*/
|
|
6200
|
+
async learnFromSession(session) {
|
|
6201
|
+
let preferences = await this.memoryManager.getUserPreferences(session.userId);
|
|
6202
|
+
if (!preferences) {
|
|
6203
|
+
preferences = {
|
|
6204
|
+
id: session.userId,
|
|
6205
|
+
userId: session.userId,
|
|
6206
|
+
namingConvention: "PascalCase",
|
|
6207
|
+
validationStyle: "strict",
|
|
6208
|
+
preferredPatterns: [],
|
|
6209
|
+
commonEntities: [],
|
|
6210
|
+
commonTraits: [],
|
|
6211
|
+
learnedAt: /* @__PURE__ */ new Date(),
|
|
6212
|
+
confidence: 0.5
|
|
6213
|
+
};
|
|
6214
|
+
}
|
|
6215
|
+
const analysis = await this.analyzeSession(session);
|
|
6216
|
+
let updated = false;
|
|
6217
|
+
for (const inference of analysis.inferences) {
|
|
6218
|
+
if (inference.confidence >= this.confidenceThreshold) {
|
|
6219
|
+
switch (inference.field) {
|
|
6220
|
+
case "namingConvention":
|
|
6221
|
+
if (this.isValidNamingConvention(inference.value)) {
|
|
6222
|
+
preferences.namingConvention = inference.value;
|
|
6223
|
+
updated = true;
|
|
6224
|
+
}
|
|
6225
|
+
break;
|
|
6226
|
+
case "validationStyle":
|
|
6227
|
+
if (this.isValidValidationStyle(inference.value)) {
|
|
6228
|
+
preferences.validationStyle = inference.value;
|
|
6229
|
+
updated = true;
|
|
6230
|
+
}
|
|
6231
|
+
break;
|
|
6232
|
+
case "preferredPatterns":
|
|
6233
|
+
if (Array.isArray(inference.value)) {
|
|
6234
|
+
preferences.preferredPatterns = [
|
|
6235
|
+
.../* @__PURE__ */ new Set([...preferences.preferredPatterns, ...inference.value])
|
|
6236
|
+
].slice(0, 10);
|
|
6237
|
+
updated = true;
|
|
6238
|
+
}
|
|
6239
|
+
break;
|
|
6240
|
+
case "commonEntities":
|
|
6241
|
+
if (Array.isArray(inference.value)) {
|
|
6242
|
+
preferences.commonEntities = [
|
|
6243
|
+
.../* @__PURE__ */ new Set([...preferences.commonEntities, ...inference.value])
|
|
6244
|
+
].slice(0, 20);
|
|
6245
|
+
updated = true;
|
|
6246
|
+
}
|
|
6247
|
+
break;
|
|
6248
|
+
}
|
|
6249
|
+
}
|
|
6250
|
+
}
|
|
6251
|
+
if (updated) {
|
|
6252
|
+
preferences.confidence = Math.min(1, preferences.confidence + 0.05);
|
|
6253
|
+
await this.memoryManager.updateUserPreferences(session.userId, preferences);
|
|
6254
|
+
}
|
|
6255
|
+
return updated ? preferences : null;
|
|
6256
|
+
}
|
|
6257
|
+
/**
|
|
6258
|
+
* Batch learn from multiple sessions
|
|
6259
|
+
*/
|
|
6260
|
+
async batchLearn(sessions) {
|
|
6261
|
+
if (sessions.length === 0) return null;
|
|
6262
|
+
const userId = sessions[0].userId;
|
|
6263
|
+
let preferences = await this.memoryManager.getUserPreferences(userId);
|
|
6264
|
+
if (!preferences) {
|
|
6265
|
+
preferences = {
|
|
6266
|
+
id: userId,
|
|
6267
|
+
userId,
|
|
6268
|
+
namingConvention: "PascalCase",
|
|
6269
|
+
validationStyle: "strict",
|
|
6270
|
+
preferredPatterns: [],
|
|
6271
|
+
commonEntities: [],
|
|
6272
|
+
commonTraits: [],
|
|
6273
|
+
learnedAt: /* @__PURE__ */ new Date(),
|
|
6274
|
+
confidence: 0.5
|
|
6275
|
+
};
|
|
6276
|
+
}
|
|
6277
|
+
const allPatterns = /* @__PURE__ */ new Set();
|
|
6278
|
+
const allEntities = /* @__PURE__ */ new Set();
|
|
6279
|
+
for (const session of sessions) {
|
|
6280
|
+
session.patterns.forEach((p) => allPatterns.add(p));
|
|
6281
|
+
session.entities.forEach((e) => allEntities.add(e));
|
|
6282
|
+
}
|
|
6283
|
+
preferences.preferredPatterns = [...allPatterns].slice(0, 10);
|
|
6284
|
+
preferences.commonEntities = [...allEntities].slice(0, 20);
|
|
6285
|
+
preferences.confidence = Math.min(1, 0.5 + sessions.length * 0.05);
|
|
6286
|
+
const aggregatePrompt = this.buildAggregatePrompt(sessions);
|
|
6287
|
+
const content = await this.llmClient.call({
|
|
6288
|
+
systemPrompt: "You analyze generation sessions and infer user preferences. Respond with JSON.",
|
|
6289
|
+
userPrompt: aggregatePrompt
|
|
6290
|
+
});
|
|
6291
|
+
const analysis = this.parseAnalysisResponse(content);
|
|
6292
|
+
for (const inference of analysis.inferences) {
|
|
6293
|
+
if (inference.confidence >= this.confidenceThreshold) {
|
|
6294
|
+
if (inference.field === "namingConvention" && this.isValidNamingConvention(inference.value)) {
|
|
6295
|
+
preferences.namingConvention = inference.value;
|
|
6296
|
+
}
|
|
6297
|
+
if (inference.field === "validationStyle" && this.isValidValidationStyle(inference.value)) {
|
|
6298
|
+
preferences.validationStyle = inference.value;
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
6301
|
+
}
|
|
6302
|
+
await this.memoryManager.updateUserPreferences(userId, preferences);
|
|
6303
|
+
return preferences;
|
|
6304
|
+
}
|
|
6305
|
+
// ==========================================================================
|
|
6306
|
+
// Prompt Building
|
|
6307
|
+
// ==========================================================================
|
|
6308
|
+
buildAnalysisPrompt(session) {
|
|
6309
|
+
return `Analyze this generation session and infer the user's preferences.
|
|
6310
|
+
|
|
6311
|
+
Session Details:
|
|
6312
|
+
- Prompt: "${session.prompt}"
|
|
6313
|
+
- Generated Entities: ${session.entities.join(", ")}
|
|
6314
|
+
- Used Patterns: ${session.patterns.join(", ")}
|
|
6315
|
+
- Skill: ${session.skill}
|
|
6316
|
+
|
|
6317
|
+
Schema Excerpt:
|
|
6318
|
+
${JSON.stringify(session.generatedSchema, null, 2).slice(0, 2e3)}
|
|
6319
|
+
|
|
6320
|
+
Analyze and infer:
|
|
6321
|
+
1. Naming convention preference (PascalCase, camelCase, snake_case)
|
|
6322
|
+
2. Validation style (strict, minimal, none)
|
|
6323
|
+
3. Preferred UI patterns
|
|
6324
|
+
4. Common entity types
|
|
6325
|
+
|
|
6326
|
+
Respond in JSON format:
|
|
6327
|
+
{
|
|
6328
|
+
"inferences": [
|
|
6329
|
+
{
|
|
6330
|
+
"field": "namingConvention",
|
|
6331
|
+
"value": "PascalCase",
|
|
6332
|
+
"confidence": 0.85,
|
|
6333
|
+
"reasoning": "User consistently uses PascalCase for entity names"
|
|
6334
|
+
}
|
|
6335
|
+
],
|
|
6336
|
+
"isHighConfidence": true
|
|
6337
|
+
}`;
|
|
6338
|
+
}
|
|
6339
|
+
buildAggregatePrompt(sessions) {
|
|
6340
|
+
const summaries = sessions.slice(0, 10).map((s) => ({
|
|
6341
|
+
prompt: s.prompt.slice(0, 100),
|
|
6342
|
+
entities: s.entities,
|
|
6343
|
+
patterns: s.patterns
|
|
6344
|
+
}));
|
|
6345
|
+
return `Analyze these ${sessions.length} generation sessions and infer the user's aggregate preferences.
|
|
6346
|
+
|
|
6347
|
+
Session Summaries:
|
|
6348
|
+
${JSON.stringify(summaries, null, 2)}
|
|
6349
|
+
|
|
6350
|
+
Infer the user's overall:
|
|
6351
|
+
1. Naming convention preference (PascalCase, camelCase, snake_case)
|
|
6352
|
+
2. Validation style (strict, minimal, none)
|
|
6353
|
+
|
|
6354
|
+
Respond in JSON format:
|
|
6355
|
+
{
|
|
6356
|
+
"inferences": [
|
|
6357
|
+
{
|
|
6358
|
+
"field": "namingConvention",
|
|
6359
|
+
"value": "PascalCase",
|
|
6360
|
+
"confidence": 0.9,
|
|
6361
|
+
"reasoning": "Used PascalCase in 8 out of 10 sessions"
|
|
6362
|
+
}
|
|
6363
|
+
],
|
|
6364
|
+
"isHighConfidence": true
|
|
6365
|
+
}`;
|
|
6366
|
+
}
|
|
6367
|
+
// ==========================================================================
|
|
6368
|
+
// Response Parsing
|
|
6369
|
+
// ==========================================================================
|
|
6370
|
+
parseAnalysisResponse(content) {
|
|
6371
|
+
try {
|
|
6372
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
6373
|
+
if (!jsonMatch) {
|
|
6374
|
+
return { inferences: [], isHighConfidence: false };
|
|
6375
|
+
}
|
|
6376
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
6377
|
+
if (Array.isArray(parsed.inferences)) {
|
|
6378
|
+
return {
|
|
6379
|
+
inferences: parsed.inferences.filter(
|
|
6380
|
+
(inf) => inf.field && inf.value !== void 0 && typeof inf.confidence === "number"
|
|
6381
|
+
),
|
|
6382
|
+
isHighConfidence: parsed.isHighConfidence ?? false
|
|
6383
|
+
};
|
|
6384
|
+
}
|
|
6385
|
+
return { inferences: [], isHighConfidence: false };
|
|
6386
|
+
} catch {
|
|
6387
|
+
return { inferences: [], isHighConfidence: false };
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6390
|
+
// ==========================================================================
|
|
6391
|
+
// Validation Helpers
|
|
6392
|
+
// ==========================================================================
|
|
6393
|
+
isValidNamingConvention(value) {
|
|
6394
|
+
return typeof value === "string" && ["PascalCase", "camelCase", "snake_case"].includes(value);
|
|
6395
|
+
}
|
|
6396
|
+
isValidValidationStyle(value) {
|
|
6397
|
+
return typeof value === "string" && ["strict", "minimal", "none"].includes(value);
|
|
6398
|
+
}
|
|
6399
|
+
};
|
|
6400
|
+
function createPreferenceLearner(options) {
|
|
6401
|
+
return new PreferenceLearner(options);
|
|
6402
|
+
}
|
|
6403
|
+
|
|
6404
|
+
// src/memory/agentic-search.ts
|
|
6405
|
+
var AgenticSearchEngine = class {
|
|
6406
|
+
constructor(memoryManager) {
|
|
6407
|
+
this.memoryManager = memoryManager;
|
|
6408
|
+
}
|
|
6409
|
+
/**
|
|
6410
|
+
* Perform agentic search through memory
|
|
6411
|
+
*/
|
|
6412
|
+
async search(params) {
|
|
6413
|
+
const startTime = Date.now();
|
|
6414
|
+
const strategy = params.strategy ?? "hybrid";
|
|
6415
|
+
const depth = params.depth ?? 3;
|
|
6416
|
+
const limit = params.limit ?? 10;
|
|
6417
|
+
let results = [];
|
|
6418
|
+
switch (strategy) {
|
|
6419
|
+
case "temporal":
|
|
6420
|
+
results = await this.temporalSearch(params, depth, limit);
|
|
6421
|
+
break;
|
|
6422
|
+
case "semantic":
|
|
6423
|
+
results = await this.semanticSearch(params, depth, limit);
|
|
6424
|
+
break;
|
|
6425
|
+
case "pattern":
|
|
6426
|
+
results = await this.patternSearch(params, depth, limit);
|
|
6427
|
+
break;
|
|
6428
|
+
case "hybrid":
|
|
6429
|
+
default:
|
|
6430
|
+
results = await this.hybridSearch(params, depth, limit);
|
|
6431
|
+
break;
|
|
6432
|
+
}
|
|
6433
|
+
results.sort((a, b) => b.relevance - a.relevance);
|
|
6434
|
+
const insights = this.generateInsights(results, params.query);
|
|
6435
|
+
const duration = Date.now() - startTime;
|
|
6436
|
+
return {
|
|
6437
|
+
results: results.slice(0, limit),
|
|
6438
|
+
insights,
|
|
6439
|
+
metadata: {
|
|
6440
|
+
strategy,
|
|
6441
|
+
depth,
|
|
6442
|
+
duration,
|
|
6443
|
+
totalResults: results.length
|
|
6444
|
+
}
|
|
6445
|
+
};
|
|
6446
|
+
}
|
|
6447
|
+
// ============================================================================
|
|
6448
|
+
// Search Strategies
|
|
6449
|
+
// ============================================================================
|
|
6450
|
+
/**
|
|
6451
|
+
* Temporal search - "What did I do last week?"
|
|
6452
|
+
* Navigates memory by time relationships
|
|
6453
|
+
*/
|
|
6454
|
+
async temporalSearch(params, _depth, limit) {
|
|
6455
|
+
const results = [];
|
|
6456
|
+
const isRecentQuery = /recent|last|latest|newest/i.test(params.query);
|
|
6457
|
+
/week|month|day|ago/i.test(params.query);
|
|
6458
|
+
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit * 2);
|
|
6459
|
+
for (const session of sessions) {
|
|
6460
|
+
let relevance = 0.5;
|
|
6461
|
+
let reasoning = "Recent generation session";
|
|
6462
|
+
if (isRecentQuery) {
|
|
6463
|
+
const daysAgo = (Date.now() - session.createdAt.getTime()) / (1e3 * 60 * 60 * 24);
|
|
6464
|
+
relevance = Math.max(0.1, 1 - daysAgo / 30);
|
|
6465
|
+
reasoning = `Created ${Math.round(daysAgo)} days ago`;
|
|
6466
|
+
}
|
|
6467
|
+
const sessionText = `${session.prompt} ${session.entities.join(" ")} ${session.patterns.join(" ")}`.toLowerCase();
|
|
6468
|
+
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
6469
|
+
const termMatches = queryTerms.filter((term) => sessionText.includes(term)).length;
|
|
6470
|
+
relevance += termMatches * 0.1;
|
|
6471
|
+
if (relevance > 0.3) {
|
|
6472
|
+
results.push({
|
|
6473
|
+
type: "session",
|
|
6474
|
+
data: session,
|
|
6475
|
+
relevance: Math.min(1, relevance),
|
|
6476
|
+
reasoning,
|
|
6477
|
+
source: "generation_history",
|
|
6478
|
+
timestamp: session.createdAt
|
|
6479
|
+
});
|
|
6480
|
+
}
|
|
6481
|
+
}
|
|
6482
|
+
return results;
|
|
6483
|
+
}
|
|
6484
|
+
/**
|
|
6485
|
+
* Semantic search - "How did I handle user roles?"
|
|
6486
|
+
* Reasoning-based understanding of structure
|
|
6487
|
+
*/
|
|
6488
|
+
async semanticSearch(params, _depth, limit) {
|
|
6489
|
+
const results = [];
|
|
6490
|
+
const concepts = this.extractConcepts(params.query);
|
|
6491
|
+
const prefs = await this.memoryManager.getUserPreferences(params.userId);
|
|
6492
|
+
if (prefs) {
|
|
6493
|
+
let relevance = 0.3;
|
|
6494
|
+
const matchedConcepts = [];
|
|
6495
|
+
if (concepts.naming && prefs.namingConvention) {
|
|
6496
|
+
relevance += 0.2;
|
|
6497
|
+
matchedConcepts.push(`uses ${prefs.namingConvention}`);
|
|
6498
|
+
}
|
|
6499
|
+
if (concepts.patterns && prefs.preferredPatterns.length > 0) {
|
|
6500
|
+
const matched = prefs.preferredPatterns.filter(
|
|
6501
|
+
(p) => concepts.patterns?.some((cp) => p.toLowerCase().includes(cp.toLowerCase()))
|
|
6502
|
+
);
|
|
6503
|
+
relevance += matched.length * 0.1;
|
|
6504
|
+
matchedConcepts.push(`patterns: ${matched.join(", ")}`);
|
|
6505
|
+
}
|
|
6506
|
+
if (concepts.entities && prefs.commonEntities.length > 0) {
|
|
6507
|
+
const matched = prefs.commonEntities.filter(
|
|
6508
|
+
(e) => concepts.entities?.some((ce) => e.toLowerCase().includes(ce.toLowerCase()))
|
|
6509
|
+
);
|
|
6510
|
+
relevance += matched.length * 0.1;
|
|
6511
|
+
matchedConcepts.push(`entities: ${matched.join(", ")}`);
|
|
6512
|
+
}
|
|
6513
|
+
if (relevance > 0.4) {
|
|
6514
|
+
results.push({
|
|
6515
|
+
type: "preference",
|
|
6516
|
+
data: prefs,
|
|
6517
|
+
relevance: Math.min(1, relevance),
|
|
6518
|
+
reasoning: `User preferences match query concepts: ${matchedConcepts.join("; ")}`,
|
|
6519
|
+
source: "user_preferences",
|
|
6520
|
+
timestamp: prefs.learnedAt
|
|
6521
|
+
});
|
|
6522
|
+
}
|
|
6523
|
+
}
|
|
6524
|
+
if (params.appId) {
|
|
6525
|
+
const project = await this.memoryManager.getProjectContext(params.appId);
|
|
6526
|
+
if (project) {
|
|
6527
|
+
let relevance = 0.3;
|
|
6528
|
+
const projectText = `${project.projectName ?? ""} ${project.description ?? ""} ${project.existingEntities.join(" ")}`.toLowerCase();
|
|
6529
|
+
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
6530
|
+
const termMatches = queryTerms.filter((term) => projectText.includes(term)).length;
|
|
6531
|
+
relevance += termMatches * 0.15;
|
|
6532
|
+
if (relevance > 0.4) {
|
|
6533
|
+
results.push({
|
|
6534
|
+
type: "project",
|
|
6535
|
+
data: project,
|
|
6536
|
+
relevance: Math.min(1, relevance),
|
|
6537
|
+
reasoning: `Project context contains ${termMatches} matching terms`,
|
|
6538
|
+
source: "project_context",
|
|
6539
|
+
timestamp: project.lastUpdatedAt
|
|
6540
|
+
});
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
}
|
|
6544
|
+
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit);
|
|
6545
|
+
for (const session of sessions) {
|
|
6546
|
+
const sessionText = `${session.prompt} ${session.entities.join(" ")}`.toLowerCase();
|
|
6547
|
+
let relevance = 0.3;
|
|
6548
|
+
if (concepts.entities) {
|
|
6549
|
+
const entityMatches = session.entities.filter(
|
|
6550
|
+
(e) => concepts.entities?.some((ce) => e.toLowerCase().includes(ce.toLowerCase()))
|
|
6551
|
+
);
|
|
6552
|
+
relevance += entityMatches.length * 0.15;
|
|
6553
|
+
}
|
|
6554
|
+
if (concepts.patterns) {
|
|
6555
|
+
const patternMatches = session.patterns.filter(
|
|
6556
|
+
(p) => concepts.patterns?.some((cp) => p.toLowerCase().includes(cp.toLowerCase()))
|
|
6557
|
+
);
|
|
6558
|
+
relevance += patternMatches.length * 0.1;
|
|
6559
|
+
}
|
|
6560
|
+
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
6561
|
+
const termMatches = queryTerms.filter((term) => sessionText.includes(term)).length;
|
|
6562
|
+
relevance += termMatches * 0.05;
|
|
6563
|
+
if (relevance > 0.4) {
|
|
6564
|
+
results.push({
|
|
6565
|
+
type: "session",
|
|
6566
|
+
data: session,
|
|
6567
|
+
relevance: Math.min(1, relevance),
|
|
6568
|
+
reasoning: `Session contains relevant entities, patterns, or keywords`,
|
|
6569
|
+
source: "generation_history",
|
|
6570
|
+
timestamp: session.createdAt
|
|
6571
|
+
});
|
|
6572
|
+
}
|
|
6573
|
+
}
|
|
6574
|
+
return results;
|
|
6575
|
+
}
|
|
6576
|
+
/**
|
|
6577
|
+
* Pattern search - "Show me all list views I've built"
|
|
6578
|
+
* Searches for specific patterns and effects
|
|
6579
|
+
*/
|
|
6580
|
+
async patternSearch(params, _depth, limit) {
|
|
6581
|
+
const results = [];
|
|
6582
|
+
const patternTerms = ["list", "form", "detail", "card", "table", "chart", "map", "calendar"];
|
|
6583
|
+
const matchedTerms = patternTerms.filter(
|
|
6584
|
+
(term) => params.query.toLowerCase().includes(term)
|
|
6585
|
+
);
|
|
6586
|
+
const patterns = await this.memoryManager.getUserPatterns(params.userId);
|
|
6587
|
+
for (const pattern of patterns) {
|
|
6588
|
+
let relevance = 0.3;
|
|
6589
|
+
let reasoning = `Pattern usage: ${pattern.usageCount} times`;
|
|
6590
|
+
if (matchedTerms.some((term) => pattern.patternId.toLowerCase().includes(term))) {
|
|
6591
|
+
relevance += 0.3;
|
|
6592
|
+
reasoning += ", matches query pattern type";
|
|
6593
|
+
}
|
|
6594
|
+
const successRate = pattern.usageCount > 0 ? pattern.successCount / pattern.usageCount : 0;
|
|
6595
|
+
relevance += successRate * 0.2;
|
|
6596
|
+
if (relevance > 0.4) {
|
|
6597
|
+
results.push({
|
|
6598
|
+
type: "pattern",
|
|
6599
|
+
data: pattern,
|
|
6600
|
+
relevance: Math.min(1, relevance),
|
|
6601
|
+
reasoning: `${reasoning}, ${Math.round(successRate * 100)}% success rate`,
|
|
6602
|
+
source: "pattern_affinity",
|
|
6603
|
+
timestamp: pattern.lastUsedAt
|
|
6604
|
+
});
|
|
6605
|
+
}
|
|
6606
|
+
}
|
|
6607
|
+
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit);
|
|
6608
|
+
for (const session of sessions) {
|
|
6609
|
+
const matchingPatterns = session.patterns.filter(
|
|
6610
|
+
(p) => matchedTerms.some((term) => p.toLowerCase().includes(term))
|
|
6611
|
+
);
|
|
6612
|
+
if (matchingPatterns.length > 0) {
|
|
6613
|
+
results.push({
|
|
6614
|
+
type: "session",
|
|
6615
|
+
data: session,
|
|
6616
|
+
relevance: 0.5 + matchingPatterns.length * 0.1,
|
|
6617
|
+
reasoning: `Session uses patterns: ${matchingPatterns.join(", ")}`,
|
|
6618
|
+
source: "generation_history",
|
|
6619
|
+
timestamp: session.createdAt
|
|
6620
|
+
});
|
|
6621
|
+
}
|
|
6622
|
+
}
|
|
6623
|
+
return results;
|
|
6624
|
+
}
|
|
6625
|
+
/**
|
|
6626
|
+
* Hybrid search - combines all strategies
|
|
6627
|
+
*/
|
|
6628
|
+
async hybridSearch(params, depth, limit) {
|
|
6629
|
+
const [temporal, semantic, pattern] = await Promise.all([
|
|
6630
|
+
this.temporalSearch(params, depth, Math.ceil(limit / 2)),
|
|
6631
|
+
this.semanticSearch(params, depth, Math.ceil(limit / 2)),
|
|
6632
|
+
this.patternSearch(params, depth, Math.ceil(limit / 2))
|
|
6633
|
+
]);
|
|
6634
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6635
|
+
const combined = [];
|
|
6636
|
+
for (const result of [...temporal, ...semantic, ...pattern]) {
|
|
6637
|
+
const key = `${result.type}-${JSON.stringify(result.data)}`;
|
|
6638
|
+
if (!seen.has(key)) {
|
|
6639
|
+
seen.add(key);
|
|
6640
|
+
combined.push(result);
|
|
6641
|
+
}
|
|
6642
|
+
}
|
|
6643
|
+
return combined;
|
|
6644
|
+
}
|
|
6645
|
+
// ============================================================================
|
|
6646
|
+
// Helpers
|
|
6647
|
+
// ============================================================================
|
|
6648
|
+
/**
|
|
6649
|
+
* Extract semantic concepts from query
|
|
6650
|
+
*/
|
|
6651
|
+
extractConcepts(query) {
|
|
6652
|
+
const lower = query.toLowerCase();
|
|
6653
|
+
return {
|
|
6654
|
+
naming: /naming|case|pascal|camel|snake/i.test(lower),
|
|
6655
|
+
validation: /validat|schema|required|optional/i.test(lower),
|
|
6656
|
+
patterns: ["entity", "list", "form", "detail", "card"].filter((p) => lower.includes(p)),
|
|
6657
|
+
entities: this.extractEntityNames(lower),
|
|
6658
|
+
actions: ["create", "update", "delete", "list", "view"].filter((a) => lower.includes(a))
|
|
6659
|
+
};
|
|
6660
|
+
}
|
|
6661
|
+
/**
|
|
6662
|
+
* Extract potential entity names from query
|
|
6663
|
+
*/
|
|
6664
|
+
extractEntityNames(query) {
|
|
6665
|
+
const words = query.split(/\s+/);
|
|
6666
|
+
const entities = [];
|
|
6667
|
+
for (const word of words) {
|
|
6668
|
+
const clean = word.replace(/[^a-zA-Z]/g, "");
|
|
6669
|
+
if (clean.length > 2 && clean[0] === clean[0].toUpperCase()) {
|
|
6670
|
+
entities.push(clean);
|
|
6671
|
+
}
|
|
6672
|
+
}
|
|
6673
|
+
return entities;
|
|
6674
|
+
}
|
|
6675
|
+
/**
|
|
6676
|
+
* Generate insights from search results
|
|
6677
|
+
*/
|
|
6678
|
+
generateInsights(results, query) {
|
|
6679
|
+
const summary = `Found ${results.length} relevant memory items for "${query}"`;
|
|
6680
|
+
const patternResults = results.filter((r) => r.type === "pattern");
|
|
6681
|
+
const patterns = patternResults.length > 0 ? patternResults.slice(0, 3).map((r) => r.data.patternId) : ["No dominant patterns identified"];
|
|
6682
|
+
const sessions = results.filter((r) => r.type === "session");
|
|
6683
|
+
const trends = [];
|
|
6684
|
+
if (sessions.length > 0) {
|
|
6685
|
+
const timestamps = sessions.filter((s) => s.timestamp).map((s) => s.timestamp.getTime()).sort((a, b) => b - a);
|
|
6686
|
+
if (timestamps.length >= 2) {
|
|
6687
|
+
const avgGap = (timestamps[0] - timestamps[timestamps.length - 1]) / (timestamps.length - 1);
|
|
6688
|
+
const daysGap = avgGap / (1e3 * 60 * 60 * 24);
|
|
6689
|
+
if (daysGap < 7) {
|
|
6690
|
+
trends.push("High activity - multiple sessions per week");
|
|
6691
|
+
} else if (daysGap > 30) {
|
|
6692
|
+
trends.push("Sporadic usage - sessions spread out over time");
|
|
6693
|
+
}
|
|
6694
|
+
}
|
|
6695
|
+
}
|
|
6696
|
+
const suggestions = [];
|
|
6697
|
+
if (patterns.length > 0 && !patterns[0].includes("No dominant")) {
|
|
6698
|
+
suggestions.push(`Consider reusing pattern: ${patterns[0]}`);
|
|
6699
|
+
}
|
|
6700
|
+
const projectResults = results.filter((r) => r.type === "project");
|
|
6701
|
+
if (projectResults.length > 0) {
|
|
6702
|
+
suggestions.push("Review existing project conventions for consistency");
|
|
6703
|
+
}
|
|
6704
|
+
const interruptResults = results.filter((r) => r.type === "interrupt");
|
|
6705
|
+
if (interruptResults.length > 3) {
|
|
6706
|
+
suggestions.push("High interrupt frequency - consider adjusting auto-approval settings");
|
|
6707
|
+
}
|
|
6708
|
+
if (suggestions.length === 0) {
|
|
6709
|
+
suggestions.push("No specific suggestions based on current memory");
|
|
6710
|
+
}
|
|
6711
|
+
return { summary, patterns, trends, suggestions };
|
|
6712
|
+
}
|
|
6713
|
+
};
|
|
6714
|
+
function createAgenticSearchEngine(memoryManager) {
|
|
6715
|
+
return new AgenticSearchEngine(memoryManager);
|
|
6716
|
+
}
|
|
6717
|
+
|
|
6718
|
+
// src/observability.ts
|
|
6719
|
+
var ObservabilityCollector = class {
|
|
6720
|
+
constructor(options = {}) {
|
|
6721
|
+
this.events = [];
|
|
6722
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
6723
|
+
this.maxEvents = options.maxEvents ?? 1e4;
|
|
6724
|
+
}
|
|
6725
|
+
/**
|
|
6726
|
+
* Record an observable event
|
|
6727
|
+
*/
|
|
6728
|
+
recordEvent(event) {
|
|
6729
|
+
const fullEvent = {
|
|
6730
|
+
...event,
|
|
6731
|
+
timestamp: Date.now()
|
|
6732
|
+
};
|
|
6733
|
+
this.events.push(fullEvent);
|
|
6734
|
+
if (this.events.length > this.maxEvents) {
|
|
6735
|
+
this.events = this.events.slice(-this.maxEvents);
|
|
6736
|
+
}
|
|
6737
|
+
this.updateSessionTelemetry(fullEvent);
|
|
6738
|
+
}
|
|
6739
|
+
/**
|
|
6740
|
+
* Start session tracking
|
|
6741
|
+
*/
|
|
6742
|
+
startSession(sessionId, userId) {
|
|
6743
|
+
this.sessions.set(sessionId, {
|
|
6744
|
+
sessionId,
|
|
6745
|
+
userId,
|
|
6746
|
+
startedAt: Date.now(),
|
|
6747
|
+
toolCallCount: 0,
|
|
6748
|
+
llmCallCount: 0,
|
|
6749
|
+
interruptCount: 0,
|
|
6750
|
+
checkpointCount: 0,
|
|
6751
|
+
totalTokens: 0,
|
|
6752
|
+
errors: [],
|
|
6753
|
+
status: "running"
|
|
6754
|
+
});
|
|
6755
|
+
this.recordEvent({
|
|
6756
|
+
type: "session_start",
|
|
6757
|
+
sessionId,
|
|
6758
|
+
userId,
|
|
6759
|
+
payload: { startedAt: Date.now() }
|
|
6760
|
+
});
|
|
6761
|
+
}
|
|
6762
|
+
/**
|
|
6763
|
+
* End session tracking
|
|
6764
|
+
*/
|
|
6765
|
+
endSession(sessionId, status = "completed") {
|
|
6766
|
+
const session = this.sessions.get(sessionId);
|
|
6767
|
+
if (session) {
|
|
6768
|
+
session.endedAt = Date.now();
|
|
6769
|
+
session.status = status;
|
|
6770
|
+
this.recordEvent({
|
|
6771
|
+
type: "session_end",
|
|
6772
|
+
sessionId,
|
|
6773
|
+
userId: session.userId,
|
|
6774
|
+
payload: {
|
|
6775
|
+
status,
|
|
6776
|
+
duration: session.endedAt - session.startedAt,
|
|
6777
|
+
toolCalls: session.toolCallCount,
|
|
6778
|
+
llmCalls: session.llmCallCount
|
|
6779
|
+
},
|
|
6780
|
+
duration: session.endedAt - session.startedAt
|
|
6781
|
+
});
|
|
6782
|
+
}
|
|
6783
|
+
}
|
|
6784
|
+
/**
|
|
6785
|
+
* Record tool call
|
|
6786
|
+
*/
|
|
6787
|
+
recordToolCall(sessionId, toolName, args, duration) {
|
|
6788
|
+
this.recordEvent({
|
|
6789
|
+
type: "tool_call",
|
|
6790
|
+
sessionId,
|
|
6791
|
+
payload: { tool: toolName, args },
|
|
6792
|
+
duration
|
|
6793
|
+
});
|
|
6794
|
+
const session = this.sessions.get(sessionId);
|
|
6795
|
+
if (session) {
|
|
6796
|
+
session.toolCallCount++;
|
|
6797
|
+
}
|
|
6798
|
+
}
|
|
6799
|
+
/**
|
|
6800
|
+
* Record LLM call
|
|
6801
|
+
*/
|
|
6802
|
+
recordLLMCall(sessionId, model, tokens, duration) {
|
|
6803
|
+
this.recordEvent({
|
|
6804
|
+
type: "llm_call",
|
|
6805
|
+
sessionId,
|
|
6806
|
+
payload: { model, tokens },
|
|
6807
|
+
duration
|
|
6808
|
+
});
|
|
6809
|
+
const session = this.sessions.get(sessionId);
|
|
6810
|
+
if (session) {
|
|
6811
|
+
session.llmCallCount++;
|
|
6812
|
+
session.totalTokens += tokens.input + tokens.output;
|
|
6813
|
+
}
|
|
6814
|
+
}
|
|
6815
|
+
/**
|
|
6816
|
+
* Record error
|
|
6817
|
+
*/
|
|
6818
|
+
recordError(sessionId, error, context) {
|
|
6819
|
+
this.recordEvent({
|
|
6820
|
+
type: "error",
|
|
6821
|
+
sessionId,
|
|
6822
|
+
payload: { ...context, message: error.message },
|
|
6823
|
+
error: {
|
|
6824
|
+
message: error.message,
|
|
6825
|
+
code: error.code,
|
|
6826
|
+
stack: error.stack
|
|
6827
|
+
}
|
|
6828
|
+
});
|
|
6829
|
+
const session = this.sessions.get(sessionId);
|
|
6830
|
+
if (session) {
|
|
6831
|
+
session.errors.push({
|
|
6832
|
+
timestamp: Date.now(),
|
|
6833
|
+
message: error.message,
|
|
6834
|
+
type: error.constructor.name
|
|
6835
|
+
});
|
|
6836
|
+
}
|
|
6837
|
+
}
|
|
6838
|
+
/**
|
|
6839
|
+
* Get events by type
|
|
6840
|
+
*/
|
|
6841
|
+
getEvents(type, sessionId) {
|
|
6842
|
+
let filtered = this.events;
|
|
6843
|
+
if (type) {
|
|
6844
|
+
filtered = filtered.filter((e) => e.type === type);
|
|
6845
|
+
}
|
|
6846
|
+
if (sessionId) {
|
|
6847
|
+
filtered = filtered.filter((e) => e.sessionId === sessionId);
|
|
6848
|
+
}
|
|
6849
|
+
return filtered;
|
|
6850
|
+
}
|
|
6851
|
+
/**
|
|
6852
|
+
* Get session telemetry
|
|
6853
|
+
*/
|
|
6854
|
+
getSessionTelemetry(sessionId) {
|
|
6855
|
+
return this.sessions.get(sessionId);
|
|
6856
|
+
}
|
|
6857
|
+
/**
|
|
6858
|
+
* Get all active sessions
|
|
6859
|
+
*/
|
|
6860
|
+
getActiveSessions() {
|
|
6861
|
+
return Array.from(this.sessions.values()).filter((s) => s.status === "running");
|
|
6862
|
+
}
|
|
6863
|
+
/**
|
|
6864
|
+
* Get performance snapshot
|
|
6865
|
+
*/
|
|
6866
|
+
getPerformanceSnapshot() {
|
|
6867
|
+
const now = Date.now();
|
|
6868
|
+
const sessions = Array.from(this.sessions.values());
|
|
6869
|
+
const activeSessions = sessions.filter((s) => s.status === "running");
|
|
6870
|
+
const last24h = sessions.filter((s) => s.startedAt > now - 24 * 60 * 60 * 1e3);
|
|
6871
|
+
const completed24h = last24h.filter((s) => s.status === "completed");
|
|
6872
|
+
const failed24h = last24h.filter((s) => s.status === "failed");
|
|
6873
|
+
const successRate24h = last24h.length > 0 ? completed24h.length / last24h.length * 100 : 0;
|
|
6874
|
+
const errorRate24h = last24h.length > 0 ? failed24h.length / last24h.length * 100 : 0;
|
|
6875
|
+
const completedSessions = sessions.filter((s) => s.endedAt);
|
|
6876
|
+
const avgSessionDuration = completedSessions.length > 0 ? completedSessions.reduce((sum, s) => sum + ((s.endedAt || now) - s.startedAt), 0) / completedSessions.length : 0;
|
|
6877
|
+
const sessionsWithTokens = sessions.filter((s) => s.totalTokens > 0);
|
|
6878
|
+
const avgTokensPerSession = sessionsWithTokens.length > 0 ? sessionsWithTokens.reduce((sum, s) => sum + s.totalTokens, 0) / sessionsWithTokens.length : 0;
|
|
6879
|
+
return {
|
|
6880
|
+
timestamp: now,
|
|
6881
|
+
activeSessions: activeSessions.length,
|
|
6882
|
+
totalSessions: sessions.length,
|
|
6883
|
+
avgSessionDuration,
|
|
6884
|
+
successRate24h,
|
|
6885
|
+
errorRate24h,
|
|
6886
|
+
avgTokensPerSession
|
|
6887
|
+
};
|
|
6888
|
+
}
|
|
6889
|
+
/**
|
|
6890
|
+
* Perform health check
|
|
6891
|
+
*/
|
|
6892
|
+
async healthCheck() {
|
|
6893
|
+
const checks = [];
|
|
6894
|
+
const now = Date.now();
|
|
6895
|
+
checks.push({
|
|
6896
|
+
component: "event_buffer",
|
|
6897
|
+
status: this.events.length < this.maxEvents * 0.9 ? "healthy" : "degraded",
|
|
6898
|
+
responseTime: 0,
|
|
6899
|
+
checkedAt: now
|
|
6900
|
+
});
|
|
6901
|
+
const activeSessions = this.getActiveSessions();
|
|
6902
|
+
const staleSessions = activeSessions.filter(
|
|
6903
|
+
(s) => now - s.startedAt > 30 * 60 * 1e3
|
|
6904
|
+
// 30 minutes
|
|
6905
|
+
);
|
|
6906
|
+
checks.push({
|
|
6907
|
+
component: "sessions",
|
|
6908
|
+
status: staleSessions.length < 10 ? "healthy" : "degraded",
|
|
6909
|
+
responseTime: 0,
|
|
6910
|
+
checkedAt: now,
|
|
6911
|
+
error: staleSessions.length > 0 ? `${staleSessions.length} stale sessions` : void 0
|
|
6912
|
+
});
|
|
6913
|
+
return checks;
|
|
6914
|
+
}
|
|
6915
|
+
/**
|
|
6916
|
+
* Export metrics for external systems
|
|
6917
|
+
*/
|
|
6918
|
+
exportMetrics() {
|
|
6919
|
+
return {
|
|
6920
|
+
events: this.events.slice(-1e3),
|
|
6921
|
+
// Last 1000 events
|
|
6922
|
+
sessions: Array.from(this.sessions.values()),
|
|
6923
|
+
snapshot: this.getPerformanceSnapshot(),
|
|
6924
|
+
health: []
|
|
6925
|
+
// Populated by healthCheck
|
|
6926
|
+
};
|
|
6927
|
+
}
|
|
6928
|
+
/**
|
|
6929
|
+
* Clear all data
|
|
6930
|
+
*/
|
|
6931
|
+
clear() {
|
|
6932
|
+
this.events = [];
|
|
6933
|
+
this.sessions.clear();
|
|
6934
|
+
}
|
|
6935
|
+
// ============================================================================
|
|
6936
|
+
// Private Helpers
|
|
6937
|
+
// ============================================================================
|
|
6938
|
+
updateSessionTelemetry(event) {
|
|
6939
|
+
const session = this.sessions.get(event.sessionId);
|
|
6940
|
+
if (!session) return;
|
|
6941
|
+
switch (event.type) {
|
|
6942
|
+
case "interrupt":
|
|
6943
|
+
session.interruptCount++;
|
|
6944
|
+
break;
|
|
6945
|
+
case "checkpoint_save":
|
|
6946
|
+
session.checkpointCount++;
|
|
6947
|
+
break;
|
|
6948
|
+
}
|
|
6949
|
+
}
|
|
6950
|
+
};
|
|
6951
|
+
var globalCollector = null;
|
|
6952
|
+
function getObservabilityCollector() {
|
|
6953
|
+
if (!globalCollector) {
|
|
6954
|
+
globalCollector = new ObservabilityCollector();
|
|
6955
|
+
}
|
|
6956
|
+
return globalCollector;
|
|
6957
|
+
}
|
|
6958
|
+
function resetObservabilityCollector() {
|
|
6959
|
+
globalCollector = null;
|
|
6960
|
+
}
|
|
6961
|
+
function recordEvent(event) {
|
|
6962
|
+
getObservabilityCollector().recordEvent(event);
|
|
6963
|
+
}
|
|
6964
|
+
function startObservabilitySession(sessionId, userId) {
|
|
6965
|
+
getObservabilityCollector().startSession(sessionId, userId);
|
|
6966
|
+
}
|
|
6967
|
+
function endObservabilitySession(sessionId, status) {
|
|
6968
|
+
getObservabilityCollector().endSession(sessionId, status);
|
|
6969
|
+
}
|
|
6970
|
+
function getPerformanceSnapshot() {
|
|
6971
|
+
return getObservabilityCollector().getPerformanceSnapshot();
|
|
6972
|
+
}
|
|
6973
|
+
|
|
6974
|
+
// src/multi-user.ts
|
|
6975
|
+
var MultiUserManager = class {
|
|
6976
|
+
constructor() {
|
|
6977
|
+
this.sessionOwnership = /* @__PURE__ */ new Map();
|
|
6978
|
+
// threadId -> userId
|
|
6979
|
+
this.userSessions = /* @__PURE__ */ new Map();
|
|
6980
|
+
}
|
|
6981
|
+
// userId -> Set<threadId>
|
|
6982
|
+
/**
|
|
6983
|
+
* Check if a user owns a session
|
|
6984
|
+
*/
|
|
6985
|
+
isSessionOwner(threadId, userId) {
|
|
6986
|
+
const owner = this.sessionOwnership.get(threadId);
|
|
6987
|
+
return owner === userId;
|
|
6988
|
+
}
|
|
6989
|
+
/**
|
|
6990
|
+
* Check if a user can access a session
|
|
6991
|
+
*/
|
|
6992
|
+
canAccessSession(threadId, userContext) {
|
|
6993
|
+
const owner = this.sessionOwnership.get(threadId);
|
|
6994
|
+
if (!owner) {
|
|
6995
|
+
return { allowed: true };
|
|
6996
|
+
}
|
|
6997
|
+
if (owner === userContext.userId) {
|
|
6998
|
+
return { allowed: true };
|
|
6999
|
+
}
|
|
7000
|
+
if (userContext.roles?.includes("admin")) {
|
|
7001
|
+
return { allowed: true };
|
|
7002
|
+
}
|
|
7003
|
+
if (userContext.sessionScope?.includes(threadId)) {
|
|
7004
|
+
return { allowed: true };
|
|
7005
|
+
}
|
|
7006
|
+
return {
|
|
7007
|
+
allowed: false,
|
|
7008
|
+
reason: "Session does not belong to user",
|
|
7009
|
+
requiredRole: "owner or admin"
|
|
7010
|
+
};
|
|
7011
|
+
}
|
|
7012
|
+
/**
|
|
7013
|
+
* Assign session ownership
|
|
7014
|
+
*/
|
|
7015
|
+
assignSessionOwnership(threadId, userId) {
|
|
7016
|
+
const previousOwner = this.sessionOwnership.get(threadId);
|
|
7017
|
+
if (previousOwner) {
|
|
7018
|
+
const previousSessions = this.userSessions.get(previousOwner);
|
|
7019
|
+
if (previousSessions) {
|
|
7020
|
+
previousSessions.delete(threadId);
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
7023
|
+
this.sessionOwnership.set(threadId, userId);
|
|
7024
|
+
if (!this.userSessions.has(userId)) {
|
|
7025
|
+
this.userSessions.set(userId, /* @__PURE__ */ new Set());
|
|
7026
|
+
}
|
|
7027
|
+
this.userSessions.get(userId).add(threadId);
|
|
7028
|
+
}
|
|
7029
|
+
/**
|
|
7030
|
+
* Get all sessions for a user
|
|
7031
|
+
*/
|
|
7032
|
+
getUserSessions(userId) {
|
|
7033
|
+
const sessions = this.userSessions.get(userId);
|
|
7034
|
+
return sessions ? Array.from(sessions) : [];
|
|
7035
|
+
}
|
|
7036
|
+
/**
|
|
7037
|
+
* Get session owner
|
|
7038
|
+
*/
|
|
7039
|
+
getSessionOwner(threadId) {
|
|
7040
|
+
return this.sessionOwnership.get(threadId);
|
|
7041
|
+
}
|
|
7042
|
+
/**
|
|
7043
|
+
* Remove session ownership
|
|
7044
|
+
*/
|
|
7045
|
+
removeSession(threadId) {
|
|
7046
|
+
const owner = this.sessionOwnership.get(threadId);
|
|
7047
|
+
if (owner) {
|
|
7048
|
+
const sessions = this.userSessions.get(owner);
|
|
7049
|
+
if (sessions) {
|
|
7050
|
+
sessions.delete(threadId);
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
this.sessionOwnership.delete(threadId);
|
|
7054
|
+
}
|
|
7055
|
+
/**
|
|
7056
|
+
* Check if user has any sessions
|
|
7057
|
+
*/
|
|
7058
|
+
hasSessions(userId) {
|
|
7059
|
+
const sessions = this.userSessions.get(userId);
|
|
7060
|
+
return sessions ? sessions.size > 0 : false;
|
|
7061
|
+
}
|
|
7062
|
+
/**
|
|
7063
|
+
* Get user session count
|
|
7064
|
+
*/
|
|
7065
|
+
getSessionCount(userId) {
|
|
7066
|
+
const sessions = this.userSessions.get(userId);
|
|
7067
|
+
return sessions ? sessions.size : 0;
|
|
7068
|
+
}
|
|
7069
|
+
/**
|
|
7070
|
+
* Transfer session ownership
|
|
7071
|
+
*/
|
|
7072
|
+
transferOwnership(threadId, fromUserId, toUserId) {
|
|
7073
|
+
const owner = this.sessionOwnership.get(threadId);
|
|
7074
|
+
if (owner !== fromUserId) {
|
|
7075
|
+
return {
|
|
7076
|
+
allowed: false,
|
|
7077
|
+
reason: "Only the owner can transfer session ownership"
|
|
7078
|
+
};
|
|
7079
|
+
}
|
|
7080
|
+
this.assignSessionOwnership(threadId, toUserId);
|
|
7081
|
+
return { allowed: true };
|
|
7082
|
+
}
|
|
7083
|
+
/**
|
|
7084
|
+
* Share session with another user
|
|
7085
|
+
*/
|
|
7086
|
+
shareSession(threadId, ownerId, targetUserId, permission = "read") {
|
|
7087
|
+
const owner = this.sessionOwnership.get(threadId);
|
|
7088
|
+
if (owner !== ownerId) {
|
|
7089
|
+
return {
|
|
7090
|
+
allowed: false,
|
|
7091
|
+
reason: "Only the owner can share a session"
|
|
7092
|
+
};
|
|
7093
|
+
}
|
|
7094
|
+
return { allowed: true };
|
|
7095
|
+
}
|
|
7096
|
+
/**
|
|
7097
|
+
* Get all user IDs with sessions
|
|
7098
|
+
*/
|
|
7099
|
+
getAllUsers() {
|
|
7100
|
+
return Array.from(this.userSessions.keys());
|
|
7101
|
+
}
|
|
7102
|
+
/**
|
|
7103
|
+
* Clear all data (for testing)
|
|
7104
|
+
*/
|
|
7105
|
+
clear() {
|
|
7106
|
+
this.sessionOwnership.clear();
|
|
7107
|
+
this.userSessions.clear();
|
|
7108
|
+
}
|
|
7109
|
+
/**
|
|
7110
|
+
* Create scoped session metadata
|
|
7111
|
+
*/
|
|
7112
|
+
createScopedMetadata(metadata, userContext) {
|
|
7113
|
+
return {
|
|
7114
|
+
...metadata,
|
|
7115
|
+
userId: userContext.userId,
|
|
7116
|
+
orgId: userContext.orgId,
|
|
7117
|
+
createdBy: userContext.userId,
|
|
7118
|
+
lastAccessedBy: userContext.userId,
|
|
7119
|
+
acl: {
|
|
7120
|
+
readers: [userContext.userId],
|
|
7121
|
+
writers: [userContext.userId],
|
|
7122
|
+
isPublic: false
|
|
7123
|
+
}
|
|
7124
|
+
};
|
|
7125
|
+
}
|
|
7126
|
+
/**
|
|
7127
|
+
* Validate user context
|
|
7128
|
+
*/
|
|
7129
|
+
validateUserContext(userContext) {
|
|
7130
|
+
if (!userContext || typeof userContext !== "object") {
|
|
7131
|
+
return false;
|
|
7132
|
+
}
|
|
7133
|
+
const ctx = userContext;
|
|
7134
|
+
if (!ctx.userId || typeof ctx.userId !== "string") {
|
|
7135
|
+
return false;
|
|
7136
|
+
}
|
|
7137
|
+
if (ctx.orgId !== void 0 && typeof ctx.orgId !== "string") {
|
|
7138
|
+
return false;
|
|
7139
|
+
}
|
|
7140
|
+
if (ctx.roles !== void 0 && !Array.isArray(ctx.roles)) {
|
|
7141
|
+
return false;
|
|
7142
|
+
}
|
|
7143
|
+
return true;
|
|
7144
|
+
}
|
|
7145
|
+
};
|
|
7146
|
+
var globalMultiUserManager = null;
|
|
7147
|
+
function getMultiUserManager() {
|
|
7148
|
+
if (!globalMultiUserManager) {
|
|
7149
|
+
globalMultiUserManager = new MultiUserManager();
|
|
7150
|
+
}
|
|
7151
|
+
return globalMultiUserManager;
|
|
7152
|
+
}
|
|
7153
|
+
function resetMultiUserManager() {
|
|
7154
|
+
globalMultiUserManager = null;
|
|
7155
|
+
}
|
|
7156
|
+
function createUserContext(userId, options = {}) {
|
|
7157
|
+
return {
|
|
7158
|
+
userId,
|
|
7159
|
+
orgId: options.orgId,
|
|
7160
|
+
roles: options.roles ?? ["user"]
|
|
7161
|
+
};
|
|
7162
|
+
}
|
|
7163
|
+
function isAdmin(userContext) {
|
|
7164
|
+
return userContext.roles?.includes("admin") ?? false;
|
|
7165
|
+
}
|
|
7166
|
+
function requireOwnership(threadId, userContext, manager = getMultiUserManager()) {
|
|
7167
|
+
const check = manager.canAccessSession(threadId, userContext);
|
|
7168
|
+
if (!check.allowed) {
|
|
7169
|
+
throw new Error(`Access denied: ${check.reason}`);
|
|
7170
|
+
}
|
|
7171
|
+
}
|
|
7172
|
+
var StateSyncManager = class extends EventEmitter {
|
|
7173
|
+
constructor(config = {}) {
|
|
7174
|
+
super();
|
|
7175
|
+
this.sequenceNumber = 0;
|
|
7176
|
+
this.pendingChanges = [];
|
|
7177
|
+
this.throttleTimer = null;
|
|
7178
|
+
this.config = {
|
|
7179
|
+
enabled: config.enabled ?? true,
|
|
7180
|
+
conflictStrategy: config.conflictStrategy ?? "last_write_wins",
|
|
7181
|
+
throttleInterval: config.throttleInterval ?? 100,
|
|
7182
|
+
maxRetries: config.maxRetries ?? 3,
|
|
7183
|
+
clientId: config.clientId ?? this.generateClientId()
|
|
7184
|
+
};
|
|
7185
|
+
}
|
|
7186
|
+
/**
|
|
7187
|
+
* Notify that state has changed (called by agent internals)
|
|
7188
|
+
*/
|
|
7189
|
+
notifyStateChange(type, threadId, payload, userId) {
|
|
7190
|
+
if (!this.config.enabled) return;
|
|
7191
|
+
const event = {
|
|
7192
|
+
type,
|
|
7193
|
+
threadId,
|
|
7194
|
+
userId,
|
|
7195
|
+
timestamp: Date.now(),
|
|
7196
|
+
payload,
|
|
7197
|
+
version: this.createVersionVector(),
|
|
7198
|
+
sourceClientId: this.config.clientId
|
|
7199
|
+
};
|
|
7200
|
+
this.pendingChanges.push(event);
|
|
7201
|
+
this.emit("stateChange", event);
|
|
7202
|
+
this.scheduleSync();
|
|
7203
|
+
}
|
|
7204
|
+
/**
|
|
7205
|
+
* Receive state change from server (called by server transport)
|
|
7206
|
+
*/
|
|
7207
|
+
receiveRemoteChange(event) {
|
|
7208
|
+
if (event.sourceClientId === this.config.clientId) return;
|
|
7209
|
+
const conflicts = this.findConflicts(event);
|
|
7210
|
+
if (conflicts.length > 0) {
|
|
7211
|
+
const resolution = this.resolveConflicts(event, conflicts);
|
|
7212
|
+
if (resolution.resolved) {
|
|
7213
|
+
this.emit("stateReconciled", resolution.winningState, event);
|
|
7214
|
+
} else {
|
|
7215
|
+
this.emit("conflictDetected", conflicts, event);
|
|
7216
|
+
}
|
|
7217
|
+
} else {
|
|
7218
|
+
this.emit("remoteChange", event);
|
|
7219
|
+
}
|
|
7220
|
+
}
|
|
7221
|
+
/**
|
|
7222
|
+
* Create sync snapshot for current state
|
|
7223
|
+
*/
|
|
7224
|
+
createSnapshot(threadId, state) {
|
|
7225
|
+
return {
|
|
7226
|
+
threadId,
|
|
7227
|
+
checkpoint: state.checkpoint,
|
|
7228
|
+
sessionMetadata: state.sessionMetadata,
|
|
7229
|
+
memoryState: state.memoryState,
|
|
7230
|
+
version: this.createVersionVector(),
|
|
7231
|
+
lastUpdated: Date.now()
|
|
7232
|
+
};
|
|
7233
|
+
}
|
|
7234
|
+
/**
|
|
7235
|
+
* Compare two version vectors
|
|
7236
|
+
* Returns: -1 if a < b, 0 if concurrent/equal, 1 if a > b
|
|
7237
|
+
*/
|
|
7238
|
+
compareVersions(a, b) {
|
|
7239
|
+
if (a.timestamp < b.timestamp) return -1;
|
|
7240
|
+
if (a.timestamp > b.timestamp) return 1;
|
|
7241
|
+
if (a.sequence < b.sequence) return -1;
|
|
7242
|
+
if (a.sequence > b.sequence) return 1;
|
|
7243
|
+
return 0;
|
|
7244
|
+
}
|
|
7245
|
+
/**
|
|
7246
|
+
* Check if there are pending changes to sync
|
|
7247
|
+
*/
|
|
7248
|
+
hasPendingChanges() {
|
|
7249
|
+
return this.pendingChanges.length > 0;
|
|
7250
|
+
}
|
|
7251
|
+
/**
|
|
7252
|
+
* Get and clear pending changes
|
|
7253
|
+
*/
|
|
7254
|
+
flushPendingChanges() {
|
|
7255
|
+
const changes = [...this.pendingChanges];
|
|
7256
|
+
this.pendingChanges = [];
|
|
7257
|
+
return changes;
|
|
7258
|
+
}
|
|
7259
|
+
/**
|
|
7260
|
+
* Get sync configuration
|
|
7261
|
+
*/
|
|
7262
|
+
getConfig() {
|
|
7263
|
+
return { ...this.config };
|
|
7264
|
+
}
|
|
7265
|
+
/**
|
|
7266
|
+
* Update sync configuration
|
|
7267
|
+
*/
|
|
7268
|
+
updateConfig(config) {
|
|
7269
|
+
this.config = { ...this.config, ...config };
|
|
7270
|
+
this.emit("configUpdated", this.config);
|
|
7271
|
+
}
|
|
7272
|
+
/**
|
|
7273
|
+
* Dispose resources
|
|
7274
|
+
*/
|
|
7275
|
+
dispose() {
|
|
7276
|
+
if (this.throttleTimer) {
|
|
7277
|
+
clearTimeout(this.throttleTimer);
|
|
7278
|
+
this.throttleTimer = null;
|
|
7279
|
+
}
|
|
7280
|
+
this.removeAllListeners();
|
|
7281
|
+
this.pendingChanges = [];
|
|
7282
|
+
}
|
|
7283
|
+
// ============================================================================
|
|
7284
|
+
// Private Helpers
|
|
7285
|
+
// ============================================================================
|
|
7286
|
+
generateClientId() {
|
|
7287
|
+
return `client_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
7288
|
+
}
|
|
7289
|
+
createVersionVector() {
|
|
7290
|
+
this.sequenceNumber++;
|
|
7291
|
+
return {
|
|
7292
|
+
timestamp: Date.now(),
|
|
7293
|
+
sequence: this.sequenceNumber,
|
|
7294
|
+
nodeId: this.config.clientId
|
|
7295
|
+
};
|
|
7296
|
+
}
|
|
7297
|
+
scheduleSync() {
|
|
7298
|
+
if (this.throttleTimer) return;
|
|
7299
|
+
this.throttleTimer = setTimeout(() => {
|
|
7300
|
+
this.throttleTimer = null;
|
|
7301
|
+
if (this.pendingChanges.length > 0) {
|
|
7302
|
+
this.emit("syncRequired", this.flushPendingChanges());
|
|
7303
|
+
}
|
|
7304
|
+
}, this.config.throttleInterval);
|
|
7305
|
+
}
|
|
7306
|
+
findConflicts(incoming) {
|
|
7307
|
+
return this.pendingChanges.filter(
|
|
7308
|
+
(local) => local.threadId === incoming.threadId && local.type === incoming.type && this.compareVersions(local.version, incoming.version) !== 0
|
|
7309
|
+
);
|
|
7310
|
+
}
|
|
7311
|
+
resolveConflicts(incoming, conflicts) {
|
|
7312
|
+
switch (this.config.conflictStrategy) {
|
|
7313
|
+
case "last_write_wins":
|
|
7314
|
+
let winningEvent = incoming;
|
|
7315
|
+
for (const conflict of conflicts) {
|
|
7316
|
+
if (this.compareVersions(conflict.version, winningEvent.version) > 0) {
|
|
7317
|
+
winningEvent = conflict;
|
|
7318
|
+
}
|
|
7319
|
+
}
|
|
7320
|
+
return {
|
|
7321
|
+
resolved: true,
|
|
7322
|
+
strategy: "last_write_wins"
|
|
7323
|
+
};
|
|
7324
|
+
case "manual":
|
|
7325
|
+
return {
|
|
7326
|
+
resolved: false,
|
|
7327
|
+
strategy: "manual",
|
|
7328
|
+
conflicts: conflicts.map((c) => ({ clientA: c, clientB: incoming }))
|
|
7329
|
+
};
|
|
7330
|
+
case "merge":
|
|
7331
|
+
default:
|
|
7332
|
+
return {
|
|
7333
|
+
resolved: conflicts.length === 0,
|
|
7334
|
+
strategy: conflicts.length === 0 ? "merge" : "manual",
|
|
7335
|
+
conflicts: conflicts.length > 0 ? conflicts.map((c) => ({ clientA: c, clientB: incoming })) : void 0
|
|
7336
|
+
};
|
|
7337
|
+
}
|
|
7338
|
+
}
|
|
7339
|
+
};
|
|
7340
|
+
var globalStateSyncManager = null;
|
|
7341
|
+
function getStateSyncManager(config) {
|
|
7342
|
+
if (!globalStateSyncManager) {
|
|
7343
|
+
globalStateSyncManager = new StateSyncManager(config);
|
|
7344
|
+
}
|
|
7345
|
+
return globalStateSyncManager;
|
|
7346
|
+
}
|
|
7347
|
+
function resetStateSyncManager() {
|
|
7348
|
+
globalStateSyncManager?.dispose();
|
|
7349
|
+
globalStateSyncManager = null;
|
|
7350
|
+
}
|
|
7351
|
+
function withSync(fn, syncManager, options) {
|
|
7352
|
+
return ((...args) => {
|
|
7353
|
+
const result = fn(...args);
|
|
7354
|
+
syncManager.notifyStateChange(
|
|
7355
|
+
options.type,
|
|
7356
|
+
options.threadId,
|
|
7357
|
+
options.getPayload(...args)
|
|
7358
|
+
);
|
|
7359
|
+
return result;
|
|
7360
|
+
});
|
|
7361
|
+
}
|
|
7362
|
+
function debounceSync(syncManager, delay = 100) {
|
|
7363
|
+
let timeout = null;
|
|
7364
|
+
let pending = null;
|
|
7365
|
+
return (type, threadId, payload) => {
|
|
7366
|
+
pending = { type, threadId, payload };
|
|
7367
|
+
if (timeout) {
|
|
7368
|
+
clearTimeout(timeout);
|
|
7369
|
+
}
|
|
7370
|
+
timeout = setTimeout(() => {
|
|
7371
|
+
if (pending) {
|
|
7372
|
+
syncManager.notifyStateChange(pending.type, pending.threadId, pending.payload);
|
|
7373
|
+
pending = null;
|
|
7374
|
+
}
|
|
7375
|
+
timeout = null;
|
|
7376
|
+
}, delay);
|
|
7377
|
+
};
|
|
7378
|
+
}
|
|
5313
7379
|
var export_applySectionUpdate = domain_language_exports.applySectionUpdate;
|
|
5314
7380
|
var export_convertDomainToSchema = domain_language_exports.convertDomainToSchema;
|
|
5315
7381
|
var export_convertSchemaToDomain = domain_language_exports.convertSchemaToDomain;
|
|
5316
7382
|
var export_deleteSection = domain_language_exports.deleteSection;
|
|
5317
7383
|
|
|
5318
|
-
export { ContinueRequestSchema, DEFAULT_COMPACTION_CONFIG, EVENT_BUDGETS, ExtractedRequirementsSchema, FirestoreCheckpointer, FirestoreSessionStore, FirestoreStore, GenerateRequestSchema, MemorySessionBackend, MetricsCollector, ResumeRequestSchema, SessionManager, analyzeFailures, export_applySectionUpdate as applySectionUpdate, combineOrbitals, combineOrbitalsToSchema, export_convertDomainToSchema as convertDomainToSchema, export_convertSchemaToDomain as convertSchemaToDomain, createAgentTools, createApplyChunkTool, createCombineSchemasTool, createCompactSystemPrompt, createConstructCombinedDomainTool, createDomainOrbitalTools, createErrorFixerSubagent, createExecuteTool, createExtractChunkTool, createFinishTaskTool, createGenerateOrbitalDomainTool, createGenerateSchemaTool, createOrbitalSubagentTool, createQuerySchemaStructureTool, createSSEEvent, createSchemaChunkingTools, createSchemaGeneratorSubagent, createSkillAgent, createSubagentConfigs, createSubagentEventWrapper, createSubagents, createSummaryPrompt, createSystemPrompt, createTestAnalyzerSubagent, createTraitEventWrapper, createTraitSubagentTool, createValidateSchemaTool, export_deleteSection as deleteSection, estimateCacheSavings, estimateCombineComplexity, estimateTokens, extractFileOperation, extractInterruptData, formatSSEEvent, formatSummary, generateFullOrbital, getBudgetWarningMessage, getEventBudget, getInterruptConfig, hasInterrupt, isCompleteEvent, isErrorEvent, isExecutionEvent, isFileOperation, isSSECompleteEvent, isSSEErrorEvent, isSSEGenerationLogEvent, isSSEInterruptEvent, isSSEMessageEvent, isSSEStartEvent, isSSESubagentEvent, isSSETodoDetailEvent, isSSETodoUpdateEvent, isSSEToolCallEvent, isSchemaEvent, isStartEvent, isTodoUpdate, needsCompaction, parseDeepAgentEvent, parseSSEEvent, resumeSkillAgent, transformAgentEvent, transformAgentEventMulti, validateCommandPaths };
|
|
7384
|
+
export { AgenticSearchEngine, ContinueRequestSchema, DEFAULT_COMPACTION_CONFIG, EVENT_BUDGETS, ExtractedRequirementsSchema, FirestoreCheckpointer, FirestoreSessionStore, FirestoreStore, GenerateRequestSchema, MemoryManager, MemoryOrbitalSchema, MemorySessionBackend, MetricsCollector, MultiUserManager, ObservabilityCollector, PreferenceLearner, ResumeRequestSchema, SessionManager, StateSyncManager, analyzeFailures, export_applySectionUpdate as applySectionUpdate, combineOrbitals, combineOrbitalsToSchema, export_convertDomainToSchema as convertDomainToSchema, export_convertSchemaToDomain as convertSchemaToDomain, createAgentTools, createAgenticSearchEngine, createApplyChunkTool, createCombineSchemasTool, createCompactSystemPrompt, createConstructCombinedDomainTool, createDomainOrbitalTools, createErrorFixerSubagent, createExecuteTool, createExtractChunkTool, createFinishTaskTool, createGenerateOrbitalDomainTool, createGenerateSchemaTool, createOrbitalSubagentTool, createPreferenceLearner, createQuerySchemaStructureTool, createSSEEvent, createSchemaChunkingTools, createSchemaGeneratorSubagent, createSkillAgent, createSubagentConfigs, createSubagentEventWrapper, createSubagents, createSummaryPrompt, createSystemPrompt, createTestAnalyzerSubagent, createTraitEventWrapper, createTraitSubagentTool, createUserContext, createValidateSchemaTool, debounceSync, export_deleteSection as deleteSection, endObservabilitySession, estimateCacheSavings, estimateCombineComplexity, estimateTokens, extractFileOperation, extractInterruptData, formatSSEEvent, formatSummary, generateFullOrbital, getBudgetWarningMessage, getEventBudget, getInterruptConfig, getMultiUserManager, getObservabilityCollector, getPerformanceSnapshot, getStateSyncManager, hasInterrupt, isAdmin, isCompleteEvent, isErrorEvent, isExecutionEvent, isFileOperation, isSSECompleteEvent, isSSEErrorEvent, isSSEGenerationLogEvent, isSSEInterruptEvent, isSSEMessageEvent, isSSEStartEvent, isSSESubagentEvent, isSSETodoDetailEvent, isSSETodoUpdateEvent, isSSEToolCallEvent, isSchemaEvent, isStartEvent, isTodoUpdate, needsCompaction, parseDeepAgentEvent, parseSSEEvent, recordEvent, requireOwnership, resetMultiUserManager, resetObservabilityCollector, resetStateSyncManager, resumeSkillAgent, startObservabilitySession, transformAgentEvent, transformAgentEventMulti, validateCommandPaths, withSync };
|
|
5319
7385
|
//# sourceMappingURL=index.js.map
|
|
5320
7386
|
//# sourceMappingURL=index.js.map
|