feat(memory): implement persistent project-level Knowledge Graph and RAG (#899)

- Shift memory from session-scope to persistent project-scope\n- Add native JSON RAG with BM25-lite ranking\n- Implement passive technical concept extraction (IPs, versions, frameworks)\n- Orchestrate hierarchical context injection in the conversation loop
This commit is contained in:
3kin0x
2026-04-26 02:17:02 +02:00
committed by GitHub
parent 9e23c2bec4
commit 29f7579377
8 changed files with 649 additions and 145 deletions

View File

@@ -2,9 +2,15 @@ import { describe, expect, it, beforeEach } from 'bun:test'
import { call as knowledgeCall } from './knowledge.js'
import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js'
import { getArc, addEntity, resetArc } from '../../utils/conversationArc.js'
import { getGlobalGraph, resetGlobalGraph } from '../../utils/knowledgeGraph.js'
describe('knowledge command', () => {
const mockContext = {} as any
beforeEach(() => {
resetArc()
resetGlobalGraph()
})
const knowledgeCallWithCapture = async (args: string) => {
const result = await knowledgeCall(args, mockContext)
@@ -51,12 +57,13 @@ describe('knowledge command', () => {
it('clears the knowledge graph', async () => {
// Add a fact first
addEntity('test', 'fact')
const arc = getArc()
expect(Object.keys(arc!.knowledgeGraph.entities).length).toBe(1)
const graph = getGlobalGraph()
expect(Object.keys(graph.entities).length).toBe(1)
// Clear it
const res = await knowledgeCallWithCapture('clear')
expect(Object.keys(getArc()!.knowledgeGraph.entities).length).toBe(0)
const graphAfter = getGlobalGraph()
expect(Object.keys(graphAfter.entities).length).toBe(0)
expect(res.toLowerCase()).toContain('cleared')
})

View File

@@ -1,5 +1,6 @@
import type { LocalCommandCall } from '../../types/command.js';
import { getArcSummary, resetArc, getArcStats, getArc } from '../../utils/conversationArc.js';
import { getArcSummary, resetArc, getArcStats } from '../../utils/conversationArc.js';
import { getGlobalGraph, resetGlobalGraph } from '../../utils/knowledgeGraph.js';
import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js';
import chalk from 'chalk';
@@ -11,8 +12,8 @@ export const call: LocalCommandCall = async (args, _context) => {
if (!subCommand || subCommand === 'status') {
const config = getGlobalConfig();
const stats = getArcStats();
const arc = getArc();
const entityCount = Object.keys(arc?.knowledgeGraph.entities || {}).length;
const graph = getGlobalGraph();
const entityCount = Object.keys(graph.entities).length;
const statusText = (config.knowledgeGraphEnabled !== false)
? chalk.green('ENABLED')
@@ -44,6 +45,7 @@ export const call: LocalCommandCall = async (args, _context) => {
if (subCommand === 'clear') {
resetArc();
resetGlobalGraph();
return {
type: 'text',
value: '🗑️ Knowledge graph memory has been cleared for this session.'