@miller-tech/uap 1.8.1 → 1.10.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/README.md +285 -642
- package/config/chat_template.jinja +76 -0
- package/config/lora-finetune.yaml +82 -0
- package/config/model-profiles/claude-haiku-3.5.json +62 -0
- package/config/model-profiles/claude-opus-4.6.json +63 -0
- package/config/model-profiles/claude-sonnet-4.6.json +63 -0
- package/config/model-profiles/gemini-2.5-flash.json +62 -0
- package/config/model-profiles/gemini-2.5-pro.json +62 -0
- package/config/model-profiles/generic.json +54 -0
- package/config/model-profiles/glm-5.json +61 -0
- package/config/model-profiles/gpt-4.1.json +64 -0
- package/config/model-profiles/gpt-4o.json +64 -0
- package/config/model-profiles/gpt-o3.json +61 -0
- package/config/model-profiles/kimi-k2.5.json +70 -0
- package/config/model-profiles/llama.json +86 -0
- package/config/model-profiles/qwen35.json +218 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +78 -9
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/llama-server-optimize.js +0 -10
- package/dist/bin/llama-server-optimize.js.map +1 -1
- package/dist/bin/policy.js +11 -195
- package/dist/bin/policy.js.map +1 -1
- package/dist/cli/dashboard.d.ts.map +1 -1
- package/dist/cli/dashboard.js +14 -14
- package/dist/cli/dashboard.js.map +1 -1
- package/dist/cli/generate.d.ts +0 -7
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +10 -22
- package/dist/cli/generate.js.map +1 -1
- package/dist/cli/hooks.d.ts +1 -1
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +371 -0
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +120 -3
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/memory.d.ts.map +1 -1
- package/dist/cli/memory.js +43 -109
- package/dist/cli/memory.js.map +1 -1
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +8 -25
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/patterns.d.ts.map +1 -1
- package/dist/cli/patterns.js +11 -9
- package/dist/cli/patterns.js.map +1 -1
- package/dist/cli/policy.d.ts.map +1 -1
- package/dist/cli/policy.js +165 -1
- package/dist/cli/policy.js.map +1 -1
- package/dist/cli/rtk-validation.d.ts +0 -4
- package/dist/cli/rtk-validation.d.ts.map +1 -1
- package/dist/cli/rtk-validation.js +5 -23
- package/dist/cli/rtk-validation.js.map +1 -1
- package/dist/cli/schema-diff.d.ts.map +1 -1
- package/dist/cli/schema-diff.js +25 -16
- package/dist/cli/schema-diff.js.map +1 -1
- package/dist/cli/setup-wizard.d.ts.map +1 -1
- package/dist/cli/setup-wizard.js +13 -9
- package/dist/cli/setup-wizard.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +3 -4
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/visualize.d.ts +6 -13
- package/dist/cli/visualize.d.ts.map +1 -1
- package/dist/cli/visualize.js +35 -64
- package/dist/cli/visualize.js.map +1 -1
- package/dist/cli/worktree.d.ts.map +1 -1
- package/dist/cli/worktree.js +12 -13
- package/dist/cli/worktree.js.map +1 -1
- package/dist/coordination/adaptive-patterns.d.ts.map +1 -1
- package/dist/coordination/adaptive-patterns.js +7 -3
- package/dist/coordination/adaptive-patterns.js.map +1 -1
- package/dist/coordination/deploy-batcher.d.ts.map +1 -1
- package/dist/coordination/deploy-batcher.js +8 -8
- package/dist/coordination/deploy-batcher.js.map +1 -1
- package/dist/dashboard/data-service.d.ts.map +1 -1
- package/dist/dashboard/data-service.js +12 -13
- package/dist/dashboard/data-service.js.map +1 -1
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +23 -8
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-router/executor/client.d.ts +0 -6
- package/dist/mcp-router/executor/client.d.ts.map +1 -1
- package/dist/mcp-router/executor/client.js +1 -27
- package/dist/mcp-router/executor/client.js.map +1 -1
- package/dist/mcp-router/index.d.ts +1 -1
- package/dist/mcp-router/index.d.ts.map +1 -1
- package/dist/mcp-router/index.js.map +1 -1
- package/dist/mcp-router/output-compressor.js +114 -112
- package/dist/mcp-router/output-compressor.js.map +1 -1
- package/dist/mcp-router/types.d.ts +0 -5
- package/dist/mcp-router/types.d.ts.map +1 -1
- package/dist/memory/backends/github.d.ts.map +1 -1
- package/dist/memory/backends/github.js +21 -13
- package/dist/memory/backends/github.js.map +1 -1
- package/dist/memory/context-pruner.d.ts +2 -9
- package/dist/memory/context-pruner.d.ts.map +1 -1
- package/dist/memory/context-pruner.js +5 -22
- package/dist/memory/context-pruner.js.map +1 -1
- package/dist/memory/correction-propagator.d.ts.map +1 -1
- package/dist/memory/correction-propagator.js +19 -19
- package/dist/memory/correction-propagator.js.map +1 -1
- package/dist/memory/dynamic-retrieval.d.ts.map +1 -1
- package/dist/memory/dynamic-retrieval.js +263 -132
- package/dist/memory/dynamic-retrieval.js.map +1 -1
- package/dist/memory/embeddings.d.ts.map +1 -1
- package/dist/memory/embeddings.js +2 -15
- package/dist/memory/embeddings.js.map +1 -1
- package/dist/memory/hierarchical-memory.d.ts.map +1 -1
- package/dist/memory/hierarchical-memory.js +6 -0
- package/dist/memory/hierarchical-memory.js.map +1 -1
- package/dist/memory/knowledge-graph.d.ts.map +1 -1
- package/dist/memory/knowledge-graph.js +2 -1
- package/dist/memory/knowledge-graph.js.map +1 -1
- package/dist/memory/memory-consolidator.d.ts +1 -0
- package/dist/memory/memory-consolidator.d.ts.map +1 -1
- package/dist/memory/memory-consolidator.js +27 -3
- package/dist/memory/memory-consolidator.js.map +1 -1
- package/dist/memory/predictive-memory.d.ts +9 -1
- package/dist/memory/predictive-memory.d.ts.map +1 -1
- package/dist/memory/predictive-memory.js +77 -1
- package/dist/memory/predictive-memory.js.map +1 -1
- package/dist/memory/serverless-qdrant.d.ts +1 -0
- package/dist/memory/serverless-qdrant.d.ts.map +1 -1
- package/dist/memory/serverless-qdrant.js +3 -9
- package/dist/memory/serverless-qdrant.js.map +1 -1
- package/dist/memory/short-term/schema.d.ts.map +1 -1
- package/dist/memory/short-term/schema.js +44 -6
- package/dist/memory/short-term/schema.js.map +1 -1
- package/dist/memory/short-term/sqlite.d.ts +4 -3
- package/dist/memory/short-term/sqlite.d.ts.map +1 -1
- package/dist/memory/short-term/sqlite.js +3 -12
- package/dist/memory/short-term/sqlite.js.map +1 -1
- package/dist/memory/speculative-cache.js +2 -2
- package/dist/memory/speculative-cache.js.map +1 -1
- package/dist/models/executor.d.ts +21 -0
- package/dist/models/executor.d.ts.map +1 -1
- package/dist/models/executor.js +116 -4
- package/dist/models/executor.js.map +1 -1
- package/dist/models/planner.d.ts +1 -0
- package/dist/models/planner.d.ts.map +1 -1
- package/dist/models/planner.js +13 -1
- package/dist/models/planner.js.map +1 -1
- package/dist/policies/enforced-tool-router.d.ts +3 -1
- package/dist/policies/enforced-tool-router.d.ts.map +1 -1
- package/dist/policies/enforced-tool-router.js.map +1 -1
- package/dist/tasks/service.d.ts +1 -0
- package/dist/tasks/service.d.ts.map +1 -1
- package/dist/tasks/service.js +10 -6
- package/dist/tasks/service.js.map +1 -1
- package/dist/telemetry/session-telemetry.d.ts.map +1 -1
- package/dist/telemetry/session-telemetry.js +73 -17
- package/dist/telemetry/session-telemetry.js.map +1 -1
- package/dist/types/config.d.ts +377 -263
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +13 -67
- package/dist/types/config.js.map +1 -1
- package/dist/utils/config-loader.d.ts +34 -0
- package/dist/utils/config-loader.d.ts.map +1 -0
- package/dist/utils/config-loader.js +93 -0
- package/dist/utils/config-loader.js.map +1 -0
- package/dist/utils/lazy-imports.d.ts +18 -0
- package/dist/utils/lazy-imports.d.ts.map +1 -0
- package/dist/utils/lazy-imports.js +39 -0
- package/dist/utils/lazy-imports.js.map +1 -0
- package/dist/utils/stopwords.d.ts +12 -0
- package/dist/utils/stopwords.d.ts.map +1 -0
- package/dist/utils/stopwords.js +196 -0
- package/dist/utils/stopwords.js.map +1 -0
- package/dist/utils/string-similarity.d.ts +10 -3
- package/dist/utils/string-similarity.d.ts.map +1 -1
- package/dist/utils/string-similarity.js +49 -25
- package/dist/utils/string-similarity.js.map +1 -1
- package/docs/INDEX.md +35 -34
- package/package.json +13 -14
- package/scripts/maintenance/publish-npm.sh +82 -0
- package/scripts/maintenance/publish.sh +29 -0
- package/scripts/maintenance/update-droids.py +93 -0
- package/scripts/maintenance/update-skills.py +148 -0
- package/scripts/maintenance/update-uap-compliance.sh +45 -0
- package/scripts/maintenance/validate-skills.py +83 -0
- package/scripts/maintenance/verify-compliance.sh +117 -0
- package/scripts/setup/install-cloakbrowser.ts +14 -0
- package/scripts/setup/install-desktop.sh +105 -0
- package/scripts/setup/install-rtk.sh +184 -0
- package/scripts/setup/install-web.sh +73 -0
- package/scripts/setup/setup.sh +375 -0
- package/scripts/validate-build.sh +62 -0
- package/scripts/version-bump.sh +130 -0
- package/tools/agents/scripts/migrate_memory_to_qdrant.py +1 -1
- /package/docs/{BENCHMARK_GAPS_AND_PLAN.md → archive/BENCHMARK_GAPS_AND_PLAN.md} +0 -0
- /package/docs/{MODEL_ROUTING_IMPLEMENTATION_SUMMARY.md → archive/MODEL_ROUTING_IMPLEMENTATION_SUMMARY.md} +0 -0
- /package/docs/{MODEL_ROUTING_OPTIMIZATION_PLAN.md → archive/MODEL_ROUTING_OPTIMIZATION_PLAN.md} +0 -0
- /package/docs/{PARALLELISM_GAPS_AND_OPTIONS.md → archive/PARALLELISM_GAPS_AND_OPTIONS.md} +0 -0
- /package/docs/{POLICY_GATE_IMPLEMENTATION.md → archive/POLICY_GATE_IMPLEMENTATION.md} +0 -0
- /package/docs/{UAP_OPTIMIZATION_PLAN.md → archive/UAP_OPTIMIZATION_PLAN.md} +0 -0
- /package/docs/{opencode-integration-guide.md → archive/opencode-integration-guide.md} +0 -0
- /package/docs/{opencode-integration-quickref.md → archive/opencode-integration-quickref.md} +0 -0
|
@@ -52,12 +52,14 @@ export function propagateCorrection(dbPath, searchContent, correctedContent, rea
|
|
|
52
52
|
const searchLower = searchContent.toLowerCase();
|
|
53
53
|
try {
|
|
54
54
|
// 1. Search in memories (working memory / L1)
|
|
55
|
-
const memRows = db
|
|
55
|
+
const memRows = db
|
|
56
|
+
.prepare(`
|
|
56
57
|
SELECT id, content FROM memories
|
|
57
58
|
WHERE LOWER(content) LIKE ?
|
|
58
59
|
ORDER BY id DESC
|
|
59
60
|
LIMIT 5
|
|
60
|
-
`)
|
|
61
|
+
`)
|
|
62
|
+
.all(`%${searchLower}%`);
|
|
61
63
|
for (const row of memRows) {
|
|
62
64
|
result.originalFound = true;
|
|
63
65
|
result.originalId = result.originalId || row.id;
|
|
@@ -77,12 +79,14 @@ export function propagateCorrection(dbPath, searchContent, correctedContent, rea
|
|
|
77
79
|
result.tiersUpdated.push('memories');
|
|
78
80
|
}
|
|
79
81
|
// 2. Search in session_memories (L2)
|
|
80
|
-
const sessRows = db
|
|
82
|
+
const sessRows = db
|
|
83
|
+
.prepare(`
|
|
81
84
|
SELECT id, content FROM session_memories
|
|
82
85
|
WHERE LOWER(content) LIKE ?
|
|
83
86
|
ORDER BY id DESC
|
|
84
87
|
LIMIT 5
|
|
85
|
-
`)
|
|
88
|
+
`)
|
|
89
|
+
.all(`%${searchLower}%`);
|
|
86
90
|
for (const row of sessRows) {
|
|
87
91
|
result.originalFound = true;
|
|
88
92
|
db.prepare(`
|
|
@@ -104,21 +108,15 @@ export function propagateCorrection(dbPath, searchContent, correctedContent, rea
|
|
|
104
108
|
`).run(today, now, `[CORRECTION] ${reason}: ${correctedContent}`);
|
|
105
109
|
result.tiersUpdated.push('daily_log');
|
|
106
110
|
// 4. Write corrected version as new working memory entry
|
|
107
|
-
const insertResult = db
|
|
111
|
+
const insertResult = db
|
|
112
|
+
.prepare(`
|
|
108
113
|
INSERT INTO memories (timestamp, type, content, project_id, importance)
|
|
109
114
|
VALUES (?, 'observation', ?, 'default', 8)
|
|
110
|
-
`)
|
|
115
|
+
`)
|
|
116
|
+
.run(now, correctedContent);
|
|
111
117
|
result.correctedEntryId = Number(insertResult.lastInsertRowid);
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
db.prepare(`
|
|
115
|
-
INSERT INTO memories_fts(rowid, content, type)
|
|
116
|
-
VALUES (?, ?, 'observation')
|
|
117
|
-
`).run(result.correctedEntryId, correctedContent);
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
// FTS not available
|
|
121
|
-
}
|
|
118
|
+
// FTS5 index is automatically updated via AFTER INSERT trigger in schema.ts
|
|
119
|
+
// (no manual insert needed — the trigger handles synchronization)
|
|
122
120
|
}
|
|
123
121
|
finally {
|
|
124
122
|
db.close();
|
|
@@ -134,13 +132,15 @@ export function getSupersededHistory(dbPath, limit = 20) {
|
|
|
134
132
|
const db = new Database(dbPath);
|
|
135
133
|
ensureSupersededSchema(db);
|
|
136
134
|
try {
|
|
137
|
-
const rows = db
|
|
135
|
+
const rows = db
|
|
136
|
+
.prepare(`
|
|
138
137
|
SELECT id, tier, original_entry_id, original_content, superseded_date, reason
|
|
139
138
|
FROM superseded_entries
|
|
140
139
|
ORDER BY id DESC
|
|
141
140
|
LIMIT ?
|
|
142
|
-
`)
|
|
143
|
-
|
|
141
|
+
`)
|
|
142
|
+
.all(limit);
|
|
143
|
+
return rows.map((r) => ({
|
|
144
144
|
id: r.id,
|
|
145
145
|
tier: r.tier,
|
|
146
146
|
originalContent: r.original_content,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"correction-propagator.js","sourceRoot":"","sources":["../../src/memory/correction-propagator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAoBtD;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,EAAqB;IAC1D,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;GAWP,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAc,EACd,aAAqB,EACrB,gBAAwB,EACxB,SAAiB,iBAAiB;IAElC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC3B,oBAAoB,CAAC,EAAE,CAAC,CAAC;IAEzB,MAAM,MAAM,GAAqB;QAC/B,aAAa,EAAE,KAAK;QACpB,YAAY,EAAE,EAAE;QAChB,eAAe,EAAE,CAAC;KACnB,CAAC;IAEF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,WAAW,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IAEhD,IAAI,CAAC;QACH,8CAA8C;QAC9C,MAAM,OAAO,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"correction-propagator.js","sourceRoot":"","sources":["../../src/memory/correction-propagator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-retrieval.d.ts","sourceRoot":"","sources":["../../src/memory/dynamic-retrieval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"dynamic-retrieval.d.ts","sourceRoot":"","sources":["../../src/memory/dynamic-retrieval.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ import { existsSync, readFileSync, statSync } from 'fs';
|
|
|
13
13
|
import { join } from 'path';
|
|
14
14
|
import Database from 'better-sqlite3';
|
|
15
15
|
import { classifyTask, extractTaskEntities, getSuggestedMemoryQueries, } from './task-classifier.js';
|
|
16
|
-
import { ContextBudget } from './context-compressor.js';
|
|
16
|
+
import { ContextBudget, DynamicCompressor, estimateTokens } from './context-compressor.js';
|
|
17
17
|
import { compressToSemanticUnits } from './semantic-compression.js';
|
|
18
18
|
import { decideContextLevel, recordOutcome, } from './adaptive-context.js';
|
|
19
19
|
import { getRelevantKnowledge, recordKnowledgeOutcome } from './terminal-bench-knowledge.js';
|
|
@@ -23,8 +23,70 @@ import { getSpeculativeCache } from './speculative-cache.js';
|
|
|
23
23
|
import { contentHash, jaccardSimilarity } from '../utils/string-similarity.js';
|
|
24
24
|
import { getPerformanceMonitor } from '../utils/performance-monitor.js';
|
|
25
25
|
import { detectAmbiguity, formatAmbiguityForContext, } from './ambiguity-detector.js';
|
|
26
|
+
import { getMemoryConsolidator } from './memory-consolidator.js';
|
|
27
|
+
import { KnowledgeGraph } from './knowledge-graph.js';
|
|
28
|
+
// Singleton KnowledgeGraph to avoid open/close per retrieval call
|
|
29
|
+
let _knowledgeGraph = null;
|
|
30
|
+
let _knowledgeGraphPath = null;
|
|
31
|
+
function getOrCreateKnowledgeGraph(dbPath) {
|
|
32
|
+
if (!_knowledgeGraph || _knowledgeGraphPath !== dbPath) {
|
|
33
|
+
if (_knowledgeGraph)
|
|
34
|
+
try {
|
|
35
|
+
_knowledgeGraph.close();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
/* ignore */
|
|
39
|
+
}
|
|
40
|
+
_knowledgeGraph = new KnowledgeGraph(dbPath);
|
|
41
|
+
_knowledgeGraphPath = dbPath;
|
|
42
|
+
}
|
|
43
|
+
return _knowledgeGraph;
|
|
44
|
+
}
|
|
26
45
|
const FILE_CACHE_TTL = 60_000; // 1 minute TTL
|
|
46
|
+
const FILE_CACHE_MAX = 20; // Maximum cached files (prevents unbounded growth)
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
48
|
const fileReadCache = new Map();
|
|
49
|
+
// Evict oldest entries if cache exceeds max size (runs on cleanup interval)
|
|
50
|
+
function trimFileCache() {
|
|
51
|
+
while (fileReadCache.size > FILE_CACHE_MAX) {
|
|
52
|
+
const firstKey = fileReadCache.keys().next().value;
|
|
53
|
+
if (firstKey)
|
|
54
|
+
fileReadCache.delete(firstKey);
|
|
55
|
+
else
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ── Shared readonly DB connection pool (avoids N+1 connection opens per retrieval) ──
|
|
60
|
+
const readonlyDbPool = new Map();
|
|
61
|
+
const DB_POOL_TTL = 30_000; // Close idle connections after 30s
|
|
62
|
+
function getReadonlyDb(dbPath) {
|
|
63
|
+
const existing = readonlyDbPool.get(dbPath);
|
|
64
|
+
if (existing) {
|
|
65
|
+
existing.lastUsed = Date.now();
|
|
66
|
+
return existing.db;
|
|
67
|
+
}
|
|
68
|
+
const db = new Database(dbPath, { readonly: true });
|
|
69
|
+
readonlyDbPool.set(dbPath, { db, lastUsed: Date.now() });
|
|
70
|
+
return db;
|
|
71
|
+
}
|
|
72
|
+
// Periodic cleanup of idle connections (runs every 60s, unref'd so it doesn't block exit)
|
|
73
|
+
const dbPoolCleanupInterval = setInterval(() => {
|
|
74
|
+
const now = Date.now();
|
|
75
|
+
for (const [path, entry] of readonlyDbPool) {
|
|
76
|
+
if (now - entry.lastUsed > DB_POOL_TTL) {
|
|
77
|
+
try {
|
|
78
|
+
entry.db.close();
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* ignore */
|
|
82
|
+
}
|
|
83
|
+
readonlyDbPool.delete(path);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Also trim file cache
|
|
87
|
+
trimFileCache();
|
|
88
|
+
}, 60_000);
|
|
89
|
+
dbPoolCleanupInterval.unref();
|
|
28
90
|
const DEFAULT_RETRIEVAL_DEPTHS = {
|
|
29
91
|
simple: { shortTerm: 3, sessionMem: 2, longTerm: 5, patterns: 3 },
|
|
30
92
|
moderate: { shortTerm: 6, sessionMem: 5, longTerm: 8, patterns: 5 },
|
|
@@ -96,15 +158,11 @@ export async function retrieveDynamicMemoryContext(taskInstruction, projectRoot
|
|
|
96
158
|
// T5: Read token budget from config if available, fall back to parameter or default
|
|
97
159
|
let configMaxTokens = 2000;
|
|
98
160
|
try {
|
|
99
|
-
const {
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
const budgetFromConfig = config?.costOptimization?.tokenBudget?.maxContextTokens;
|
|
105
|
-
if (typeof budgetFromConfig === 'number' && budgetFromConfig > 0) {
|
|
106
|
-
configMaxTokens = budgetFromConfig;
|
|
107
|
-
}
|
|
161
|
+
const { loadUapConfig: loadCfg } = await import('../utils/config-loader.js');
|
|
162
|
+
const cfg = loadCfg(projectRoot);
|
|
163
|
+
const budgetFromConfig = cfg?.costOptimization?.tokenBudget?.maxContextTokens;
|
|
164
|
+
if (typeof budgetFromConfig === 'number' && budgetFromConfig > 0) {
|
|
165
|
+
configMaxTokens = budgetFromConfig;
|
|
108
166
|
}
|
|
109
167
|
}
|
|
110
168
|
catch {
|
|
@@ -140,6 +198,39 @@ export async function retrieveDynamicMemoryContext(taskInstruction, projectRoot
|
|
|
140
198
|
const budget = new ContextBudget(effectiveMaxTokens);
|
|
141
199
|
// Step 4: Extract entities from task
|
|
142
200
|
const entities = extractTaskEntities(taskInstruction);
|
|
201
|
+
// Step 4b: Enrich entities with knowledge graph relationships
|
|
202
|
+
// Uses a singleton KnowledgeGraph to avoid open/close per retrieval call
|
|
203
|
+
try {
|
|
204
|
+
const kgDbPath = join(projectRoot, 'agents/data/memory/short_term.db');
|
|
205
|
+
if (existsSync(kgDbPath)) {
|
|
206
|
+
const kg = getOrCreateKnowledgeGraph(kgDbPath);
|
|
207
|
+
// Query knowledge graph for each extracted entity to find related concepts
|
|
208
|
+
for (const tech of entities.technologies.slice(0, 3)) {
|
|
209
|
+
const result = kg.queryEntityGraph('technology', tech);
|
|
210
|
+
if (result) {
|
|
211
|
+
for (const rel of result.relationships.slice(0, 3)) {
|
|
212
|
+
if (!entities.technologies.includes(rel.relatedEntity.name)) {
|
|
213
|
+
entities.technologies.push(rel.relatedEntity.name);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
for (const file of entities.files.slice(0, 2)) {
|
|
219
|
+
const result = kg.queryEntityGraph('file', file);
|
|
220
|
+
if (result) {
|
|
221
|
+
for (const rel of result.relationships.slice(0, 2)) {
|
|
222
|
+
if (!entities.files.includes(rel.relatedEntity.name)) {
|
|
223
|
+
entities.files.push(rel.relatedEntity.name);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Don't close — singleton is reused across calls
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// Knowledge graph enrichment is non-fatal
|
|
233
|
+
}
|
|
143
234
|
// Step 5: Get suggested memory queries (enhanced with predictive prefetch)
|
|
144
235
|
const suggestedQueries = getSuggestedMemoryQueries(classification);
|
|
145
236
|
// Step 5b: Predictive memory prefetch - predict additional queries based on task history
|
|
@@ -216,7 +307,23 @@ export async function retrieveDynamicMemoryContext(taskInstruction, projectRoot
|
|
|
216
307
|
})));
|
|
217
308
|
}
|
|
218
309
|
}
|
|
219
|
-
// Step 7b:
|
|
310
|
+
// Step 7b: Apply budget-aware dynamic compression to individual memories
|
|
311
|
+
// Track consumed tokens so each memory sees a decreasing budget
|
|
312
|
+
let compressorConsumedTokens = 0;
|
|
313
|
+
try {
|
|
314
|
+
const dynamicCompressor = new DynamicCompressor();
|
|
315
|
+
processedMemories = processedMemories.map((m) => {
|
|
316
|
+
const budgetRemaining = Math.max(0, budget.remaining() - compressorConsumedTokens);
|
|
317
|
+
const { compressed } = dynamicCompressor.compressDynamic(m.content, budgetRemaining, effectiveMaxTokens);
|
|
318
|
+
compressorConsumedTokens += estimateTokens(compressed);
|
|
319
|
+
return { ...m, content: compressed };
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// DynamicCompressor failure is non-fatal
|
|
324
|
+
}
|
|
325
|
+
// Step 7c: Prune memories to fit token budget using ContextPruner
|
|
326
|
+
// Subtract tokens already consumed by compression from the available budget
|
|
220
327
|
try {
|
|
221
328
|
const pruner = new ContextPruner();
|
|
222
329
|
const prunableMemories = processedMemories.map((m, i) => ({
|
|
@@ -225,7 +332,8 @@ export async function retrieveDynamicMemoryContext(taskInstruction, projectRoot
|
|
|
225
332
|
age: i, // Use index as age proxy (older = higher index)
|
|
226
333
|
accessCount: 1,
|
|
227
334
|
}));
|
|
228
|
-
const
|
|
335
|
+
const adjustedBudget = Math.max(0, budget.remaining() - compressorConsumedTokens);
|
|
336
|
+
const pruned = pruner.prune(prunableMemories, adjustedBudget);
|
|
229
337
|
if (pruned.length < processedMemories.length) {
|
|
230
338
|
// Map pruned back to processed memories by content match
|
|
231
339
|
const prunedContents = new Set(pruned.map((p) => p.content));
|
|
@@ -263,11 +371,67 @@ export async function retrieveDynamicMemoryContext(taskInstruction, projectRoot
|
|
|
263
371
|
// Record access for predictive memory learning
|
|
264
372
|
try {
|
|
265
373
|
const predictive = getPredictiveMemoryService();
|
|
266
|
-
predictive.recordAccess(taskInstruction, processedMemories.map(m => m.source).filter((v, i, a) => a.indexOf(v) === i));
|
|
374
|
+
predictive.recordAccess(taskInstruction, processedMemories.map((m) => m.source).filter((v, i, a) => a.indexOf(v) === i));
|
|
267
375
|
}
|
|
268
376
|
catch {
|
|
269
377
|
// Non-fatal
|
|
270
378
|
}
|
|
379
|
+
// Record memory access for quality scoring (enables access-pattern learning)
|
|
380
|
+
try {
|
|
381
|
+
const consolidator = getMemoryConsolidator();
|
|
382
|
+
for (const mem of processedMemories) {
|
|
383
|
+
// Use content hash as memory ID for quality tracking
|
|
384
|
+
const memId = contentHash(mem.content);
|
|
385
|
+
consolidator.recordAccess(memId);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
// Non-fatal — quality scoring is an optimization, not a requirement
|
|
390
|
+
}
|
|
391
|
+
// Pre-warm speculative cache for predicted next queries (async, non-blocking)
|
|
392
|
+
try {
|
|
393
|
+
const speculativeCache = getSpeculativeCache();
|
|
394
|
+
// Fire-and-forget: pre-warm cache with a real fetcher that queries short-term memory
|
|
395
|
+
void speculativeCache.preWarm(taskInstruction, async (query) => {
|
|
396
|
+
const stDbPath = join(projectRoot, 'agents/data/memory/short_term.db');
|
|
397
|
+
if (!existsSync(stDbPath))
|
|
398
|
+
return [];
|
|
399
|
+
try {
|
|
400
|
+
const db = getReadonlyDb(stDbPath);
|
|
401
|
+
const rows = db
|
|
402
|
+
.prepare(`
|
|
403
|
+
SELECT type, content FROM memories
|
|
404
|
+
WHERE content LIKE ?
|
|
405
|
+
ORDER BY id DESC LIMIT 5
|
|
406
|
+
`)
|
|
407
|
+
.all(`%${query.slice(0, 50)}%`);
|
|
408
|
+
return rows;
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
return [];
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
// Non-fatal
|
|
417
|
+
}
|
|
418
|
+
// Periodically persist learned data (fire-and-forget, every ~10th call)
|
|
419
|
+
if (Math.random() < 0.1) {
|
|
420
|
+
try {
|
|
421
|
+
const predictive = getPredictiveMemoryService();
|
|
422
|
+
predictive.saveToDb('./agents/data/memory/predictive.db');
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
/* non-fatal */
|
|
426
|
+
}
|
|
427
|
+
try {
|
|
428
|
+
const { saveHierarchicalMemory } = await import('./hierarchical-memory.js');
|
|
429
|
+
saveHierarchicalMemory(join(projectRoot, 'agents/data/memory/hierarchical.db'));
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
/* non-fatal */
|
|
433
|
+
}
|
|
434
|
+
}
|
|
271
435
|
return {
|
|
272
436
|
classification,
|
|
273
437
|
relevantMemories: processedMemories,
|
|
@@ -296,12 +460,38 @@ export async function retrieveDynamicMemoryContext(taskInstruction, projectRoot
|
|
|
296
460
|
*/
|
|
297
461
|
async function queryAllMemorySources(taskInstruction, classification, entities, suggestedQueries, projectRoot, depth, maxTokens) {
|
|
298
462
|
const memories = [];
|
|
299
|
-
// Source 1:
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
463
|
+
// Source 1+2: Hierarchical tiered memory (replaces flat short-term + session queries)
|
|
464
|
+
// Uses hot/warm/cold tiering with automatic promotion/demotion and semantic search
|
|
465
|
+
try {
|
|
466
|
+
const { getHierarchicalMemoryManager } = await import('./hierarchical-memory.js');
|
|
467
|
+
const stDbPath = join(projectRoot, 'agents/data/memory/short_term.db');
|
|
468
|
+
const hmm = getHierarchicalMemoryManager(undefined, existsSync(stDbPath) ? stDbPath : undefined);
|
|
469
|
+
// Run tier maintenance periodically (~every 5th retrieval)
|
|
470
|
+
if (Math.random() < 0.2) {
|
|
471
|
+
hmm.pruneStale();
|
|
472
|
+
hmm.enforceTokenBudget();
|
|
473
|
+
}
|
|
474
|
+
const tieredResults = await hmm.query(taskInstruction, depth.shortTerm + depth.sessionMem);
|
|
475
|
+
for (const entry of tieredResults) {
|
|
476
|
+
memories.push({
|
|
477
|
+
content: entry.compressed || entry.content,
|
|
478
|
+
type: entry.type === 'observation'
|
|
479
|
+
? 'lesson'
|
|
480
|
+
: entry.type === 'action' || entry.type === 'goal'
|
|
481
|
+
? 'context'
|
|
482
|
+
: 'pattern',
|
|
483
|
+
relevance: Math.min(0.95, entry.importance / 10 + (entry.tier === 'hot' ? 0.2 : entry.tier === 'warm' ? 0.1 : 0)),
|
|
484
|
+
source: `hierarchical-${entry.tier}`,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
// Fallback to flat queries if hierarchical memory fails
|
|
490
|
+
const shortTermMemories = await queryShortTermMemory(classification, entities, projectRoot, depth.shortTerm);
|
|
491
|
+
memories.push(...shortTermMemories);
|
|
492
|
+
const sessionMemories = await querySessionMemory(taskInstruction, projectRoot, depth.sessionMem);
|
|
493
|
+
memories.push(...sessionMemories);
|
|
494
|
+
}
|
|
305
495
|
// Source 3: Long-term prepopulated memory (limited by depth)
|
|
306
496
|
const longTermMemories = await queryLongTermMemory(suggestedQueries, projectRoot, depth.longTerm);
|
|
307
497
|
memories.push(...longTermMemories);
|
|
@@ -331,7 +521,7 @@ async function queryAllMemorySources(taskInstruction, classification, entities,
|
|
|
331
521
|
const budgeted = [];
|
|
332
522
|
let usedTokens = 0;
|
|
333
523
|
for (const mem of uniqueMemories) {
|
|
334
|
-
const memTokens =
|
|
524
|
+
const memTokens = estimateTokens(mem.content);
|
|
335
525
|
if (usedTokens + memTokens > effectiveBudget && budgeted.length > 0)
|
|
336
526
|
break;
|
|
337
527
|
budgeted.push(mem);
|
|
@@ -349,9 +539,8 @@ async function queryShortTermMemory(classification, entities, projectRoot, limit
|
|
|
349
539
|
return [];
|
|
350
540
|
const memories = [];
|
|
351
541
|
const perKeywordLimit = Math.max(1, Math.ceil(limit / 3));
|
|
352
|
-
let db = null;
|
|
353
542
|
try {
|
|
354
|
-
db =
|
|
543
|
+
const db = getReadonlyDb(dbPath);
|
|
355
544
|
// Check if FTS5 index exists
|
|
356
545
|
const hasFts = db
|
|
357
546
|
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='memories_fts'")
|
|
@@ -452,140 +641,82 @@ async function queryShortTermMemory(classification, entities, projectRoot, limit
|
|
|
452
641
|
}
|
|
453
642
|
}
|
|
454
643
|
catch {
|
|
455
|
-
// Ignore query errors
|
|
456
|
-
}
|
|
457
|
-
finally {
|
|
458
|
-
db?.close();
|
|
644
|
+
// Ignore query errors — pooled connection stays open for reuse
|
|
459
645
|
}
|
|
460
646
|
return memories;
|
|
461
647
|
}
|
|
462
648
|
/**
|
|
463
|
-
* Query session memories for recent decisions using parameterized queries (secure)
|
|
649
|
+
* Query session memories for recent decisions using parameterized queries (secure).
|
|
650
|
+
* Uses FTS5 full-text search when a task instruction is provided for content-aware recall,
|
|
651
|
+
* falling back to importance-based recency query.
|
|
464
652
|
*/
|
|
465
|
-
async function querySessionMemory(
|
|
653
|
+
async function querySessionMemory(taskInstruction, projectRoot, limit = 5) {
|
|
466
654
|
const dbPath = join(projectRoot, 'agents/data/memory/short_term.db');
|
|
467
655
|
if (!existsSync(dbPath))
|
|
468
656
|
return [];
|
|
469
657
|
const memories = [];
|
|
470
|
-
let db = null;
|
|
471
658
|
try {
|
|
472
|
-
db =
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
659
|
+
const db = getReadonlyDb(dbPath);
|
|
660
|
+
// Try FTS5 content-aware search first if we have a task instruction
|
|
661
|
+
let rows = [];
|
|
662
|
+
if (taskInstruction && taskInstruction.trim().length > 3) {
|
|
663
|
+
try {
|
|
664
|
+
// Extract key terms from task instruction for FTS5 query
|
|
665
|
+
// Quote each word to prevent FTS5 reserved words (AND, OR, NOT, NEAR) from being
|
|
666
|
+
// interpreted as operators — matches the sanitization pattern in sqlite.ts:186-194
|
|
667
|
+
const FTS5_RESERVED = new Set(['and', 'or', 'not', 'near']);
|
|
668
|
+
const ftsQuery = taskInstruction
|
|
669
|
+
.replace(/[^\w\s]/g, ' ')
|
|
670
|
+
.split(/\s+/)
|
|
671
|
+
.filter((w) => w.length > 2 && !FTS5_RESERVED.has(w.toLowerCase()))
|
|
672
|
+
.slice(0, 8)
|
|
673
|
+
.map((w) => '"' + w.replace(/"/g, '""') + '"')
|
|
674
|
+
.join(' OR ');
|
|
675
|
+
if (ftsQuery.length > 0) {
|
|
676
|
+
const ftsStmt = db.prepare(`
|
|
677
|
+
SELECT sm.type, sm.content, fts.rank
|
|
678
|
+
FROM session_memories_fts fts
|
|
679
|
+
JOIN session_memories sm ON sm.id = fts.rowid
|
|
680
|
+
WHERE session_memories_fts MATCH ?
|
|
681
|
+
ORDER BY fts.rank
|
|
682
|
+
LIMIT ?
|
|
683
|
+
`);
|
|
684
|
+
rows = ftsStmt.all(ftsQuery, limit);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
catch {
|
|
688
|
+
// FTS5 table may not exist yet or query may fail — fall through to fallback
|
|
689
|
+
rows = [];
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
// Fallback: importance-based recency query
|
|
693
|
+
if (rows.length === 0) {
|
|
694
|
+
const stmt = db.prepare(`
|
|
695
|
+
SELECT type, content FROM session_memories
|
|
696
|
+
WHERE importance >= 7
|
|
697
|
+
ORDER BY id DESC
|
|
698
|
+
LIMIT ?
|
|
699
|
+
`);
|
|
700
|
+
rows = stmt.all(limit);
|
|
701
|
+
}
|
|
480
702
|
for (const row of rows) {
|
|
481
703
|
if (row.content) {
|
|
482
704
|
memories.push({
|
|
483
705
|
content: row.content.slice(0, 500),
|
|
484
706
|
type: row.type === 'lesson' ? 'lesson' : row.type === 'decision' ? 'context' : 'pattern',
|
|
485
|
-
relevance: 0.8,
|
|
707
|
+
relevance: row.rank ? Math.min(0.95, 0.8 + Math.abs(row.rank) * 0.01) : 0.8,
|
|
486
708
|
source: 'session-memory',
|
|
487
709
|
});
|
|
488
710
|
}
|
|
489
711
|
}
|
|
490
712
|
}
|
|
491
713
|
catch {
|
|
492
|
-
// Ignore query errors
|
|
493
|
-
}
|
|
494
|
-
finally {
|
|
495
|
-
db?.close();
|
|
714
|
+
// Ignore query errors — pooled connection stays open for reuse
|
|
496
715
|
}
|
|
497
716
|
return memories;
|
|
498
717
|
}
|
|
499
|
-
// OPTIMIZATION 9: Stopwords
|
|
500
|
-
|
|
501
|
-
const QUERY_STOPWORDS = new Set([
|
|
502
|
-
'a',
|
|
503
|
-
'an',
|
|
504
|
-
'the',
|
|
505
|
-
'is',
|
|
506
|
-
'are',
|
|
507
|
-
'was',
|
|
508
|
-
'were',
|
|
509
|
-
'be',
|
|
510
|
-
'been',
|
|
511
|
-
'being',
|
|
512
|
-
'have',
|
|
513
|
-
'has',
|
|
514
|
-
'had',
|
|
515
|
-
'do',
|
|
516
|
-
'does',
|
|
517
|
-
'did',
|
|
518
|
-
'will',
|
|
519
|
-
'would',
|
|
520
|
-
'could',
|
|
521
|
-
'should',
|
|
522
|
-
'may',
|
|
523
|
-
'might',
|
|
524
|
-
'shall',
|
|
525
|
-
'can',
|
|
526
|
-
'need',
|
|
527
|
-
'must',
|
|
528
|
-
'to',
|
|
529
|
-
'of',
|
|
530
|
-
'in',
|
|
531
|
-
'for',
|
|
532
|
-
'on',
|
|
533
|
-
'with',
|
|
534
|
-
'at',
|
|
535
|
-
'by',
|
|
536
|
-
'from',
|
|
537
|
-
'as',
|
|
538
|
-
'into',
|
|
539
|
-
'through',
|
|
540
|
-
'during',
|
|
541
|
-
'before',
|
|
542
|
-
'after',
|
|
543
|
-
'above',
|
|
544
|
-
'below',
|
|
545
|
-
'and',
|
|
546
|
-
'but',
|
|
547
|
-
'or',
|
|
548
|
-
'nor',
|
|
549
|
-
'not',
|
|
550
|
-
'so',
|
|
551
|
-
'yet',
|
|
552
|
-
'both',
|
|
553
|
-
'either',
|
|
554
|
-
'this',
|
|
555
|
-
'that',
|
|
556
|
-
'these',
|
|
557
|
-
'those',
|
|
558
|
-
'it',
|
|
559
|
-
'its',
|
|
560
|
-
'best',
|
|
561
|
-
'most',
|
|
562
|
-
'very',
|
|
563
|
-
'good',
|
|
564
|
-
'great',
|
|
565
|
-
'well',
|
|
566
|
-
'new',
|
|
567
|
-
'more',
|
|
568
|
-
'common',
|
|
569
|
-
'general',
|
|
570
|
-
'basic',
|
|
571
|
-
'simple',
|
|
572
|
-
'all',
|
|
573
|
-
'any',
|
|
574
|
-
'some',
|
|
575
|
-
'how',
|
|
576
|
-
'what',
|
|
577
|
-
'when',
|
|
578
|
-
'where',
|
|
579
|
-
'which',
|
|
580
|
-
'who',
|
|
581
|
-
'why',
|
|
582
|
-
'practices',
|
|
583
|
-
'tips',
|
|
584
|
-
'implementation',
|
|
585
|
-
'gotchas',
|
|
586
|
-
'mistakes',
|
|
587
|
-
'patterns',
|
|
588
|
-
]);
|
|
718
|
+
// OPTIMIZATION 9: Stopwords from shared utility (replaces 88-line inline set)
|
|
719
|
+
import { QUERY_STOPWORDS } from '../utils/stopwords.js';
|
|
589
720
|
/**
|
|
590
721
|
* Query long-term prepopulated memory
|
|
591
722
|
* OPTIMIZATION 9: Added stopword filtering for better query precision
|