Feature/memory pr (#894)
* feat: multi-turn context and conversation arc memory PR 2E - Section 2.9, 2.10: - Add multiTurnContext.ts with turn tracking and state preservation - Add conversationArc.ts with goal/decision/milestone tracking - Wire into query.ts after tool execution - Feature-flags: MULTI_TURN_CONTEXT, CONVERSATION_ARC - Add comprehensive tests (22 passing) * feat(cli): add /knowledge command to manage native memory - Add /knowledge enable <yes|no> to toggle Knowledge Graph learning\n- Add /knowledge clear to reset memory\n- Add persistent knowledgeGraphEnabled setting to global config\n- Integrated user setting into the query execution loop * feat(cli): add /knowledge command (stable local-jsx version) - Resolve conflicts between .ts and .tsx files\n- Align with LocalJSXCommandCall signature\n- Fix onDone and args errors * test(cli): fix knowledge command tests by properly isolating global config * fix(cli): make knowledge command defensive against undefined args and leaky tests * fix(cli): correct data source for entity count and fix test isolation * fix(cli): reinforce knowledge test by explicitly defining property on test config * fix(cli): explicitly define property in test config to avoid undefined in CI * fix(cli): make knowledge tests resistant to global config mocks in CI * chore(memory): surgical improvements from architectural audit - Fix: Implement entity deduplication in Knowledge Graph\n- Fix: Ensure fact extraction from user messages in query loop\n- Fix: Refine regexes for better quality learning (less noise) --------- Co-authored-by: LifeJiggy <Bloomtonjovish@gmail.com>
This commit is contained in:
@@ -119,25 +119,26 @@ function extractFactsAutomatically(content: string): void {
|
||||
const arc = getArc()
|
||||
if (!arc) return
|
||||
|
||||
// 1. Detect Environment Variables (KEY=VALUE)
|
||||
const envMatches = content.matchAll(/(?:export\s+)?([A-Z_]+)=([^\s\n"']+)/g)
|
||||
// 1. Detect Environment Variables (KEY=VALUE) - strictly uppercase keys
|
||||
const envMatches = content.matchAll(/(?:export\s+)?([A-Z_]{3,})=([^\s\n"']+)/g)
|
||||
for (const match of envMatches) {
|
||||
addEntity('environment_variable', match[1], { value: match[2] })
|
||||
}
|
||||
|
||||
// 2. Detect Absolute Paths
|
||||
// 2. Detect Absolute Paths - ensure it looks like a path and not a div or code
|
||||
const pathMatches = content.matchAll(/(\/(?:[\w.-]+\/)+[\w.-]+)/g)
|
||||
for (const match of pathMatches) {
|
||||
const path = match[1]
|
||||
if (path.length > 5 && !path.includes('node_modules')) {
|
||||
// Exclude common noise and ensure it's a long enough path
|
||||
if (path.length > 8 && !path.includes('node_modules') && !path.includes('://')) {
|
||||
addEntity('path', path, { type: 'absolute' })
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Detect Versions (v1.2.3 or version 1.2.3)
|
||||
// 3. Detect Versions - require vX.Y.Z or version X.Y.Z
|
||||
const versionMatches = content.matchAll(/(?:v|version\s+)(\d+\.\d+(?:\.\d+)?)/gi)
|
||||
for (const match of versionMatches) {
|
||||
addEntity('version', match[0], { semver: match[1] })
|
||||
addEntity('version', match[0].toLowerCase(), { semver: match[1] })
|
||||
}
|
||||
|
||||
// 4. Detect Hostnames/URLs
|
||||
@@ -145,7 +146,9 @@ function extractFactsAutomatically(content: string): void {
|
||||
for (const match of urlMatches) {
|
||||
try {
|
||||
const url = new URL(match[1])
|
||||
addEntity('endpoint', url.hostname, { url: url.toString() })
|
||||
if (url.hostname.includes('.')) {
|
||||
addEntity('endpoint', url.hostname, { url: url.toString() })
|
||||
}
|
||||
} catch {
|
||||
// Ignore invalid URLs
|
||||
}
|
||||
@@ -262,6 +265,17 @@ export function addEntity(
|
||||
const arc = getArc()
|
||||
if (!arc) throw new Error('Arc not initialized')
|
||||
|
||||
// Check for existing entity to avoid duplicates (Deduplication Logic)
|
||||
const existingEntity = Object.values(arc.knowledgeGraph.entities).find(
|
||||
e => e.type === type && e.name === name,
|
||||
)
|
||||
|
||||
if (existingEntity) {
|
||||
existingEntity.attributes = { ...existingEntity.attributes, ...attributes }
|
||||
arc.lastUpdateTime = Date.now()
|
||||
return existingEntity
|
||||
}
|
||||
|
||||
const id = `entity_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`
|
||||
const entity: Entity = { id, type, name, attributes }
|
||||
|
||||
@@ -360,4 +374,4 @@ export function getArcStats() {
|
||||
milestoneCount: arc.milestones.length,
|
||||
durationMs: arc.lastUpdateTime - arc.startTime,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user