agent-working-memory 0.6.1 → 0.7.1
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 +27 -8
- package/dist/adapters/common.d.ts.map +1 -1
- package/dist/adapters/common.js +9 -1
- package/dist/adapters/common.js.map +1 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +108 -10
- package/dist/api/routes.js.map +1 -1
- package/dist/cli.js +103 -103
- package/dist/core/auto-tagger.d.ts +29 -0
- package/dist/core/auto-tagger.d.ts.map +1 -0
- package/dist/core/auto-tagger.js +139 -0
- package/dist/core/auto-tagger.js.map +1 -0
- package/dist/core/hebbian.d.ts +25 -1
- package/dist/core/hebbian.d.ts.map +1 -1
- package/dist/core/hebbian.js +71 -3
- package/dist/core/hebbian.js.map +1 -1
- package/dist/core/query-expander.d.ts.map +1 -1
- package/dist/core/query-expander.js.map +1 -1
- package/dist/core/reranker.d.ts.map +1 -1
- package/dist/core/reranker.js.map +1 -1
- package/dist/engine/activation.d.ts +22 -4
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +136 -73
- package/dist/engine/activation.js.map +1 -1
- package/dist/engine/consolidation.d.ts +1 -0
- package/dist/engine/consolidation.d.ts.map +1 -1
- package/dist/engine/consolidation.js +149 -9
- package/dist/engine/consolidation.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp.js +123 -84
- package/dist/mcp.js.map +1 -1
- package/dist/storage/sqlite.d.ts +17 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +73 -0
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/types/engram.d.ts +2 -0
- package/dist/types/engram.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapters/common.ts +9 -1
- package/src/api/routes.ts +723 -600
- package/src/cli.ts +719 -719
- package/src/core/auto-tagger.ts +168 -0
- package/src/core/hebbian.ts +84 -3
- package/src/core/query-expander.ts +0 -1
- package/src/core/reranker.ts +0 -1
- package/src/engine/activation.ts +136 -70
- package/src/engine/consolidation.ts +165 -9
- package/src/index.ts +199 -199
- package/src/mcp.ts +1134 -1099
- package/src/storage/sqlite.ts +77 -0
- package/src/types/engram.ts +2 -0
package/dist/cli.js
CHANGED
|
@@ -38,44 +38,44 @@ catch { /* No .env file */ }
|
|
|
38
38
|
const args = process.argv.slice(2);
|
|
39
39
|
const command = args[0];
|
|
40
40
|
function printUsage() {
|
|
41
|
-
console.log(`
|
|
42
|
-
AgentWorkingMemory — Cognitive memory for AI agents
|
|
43
|
-
|
|
44
|
-
Usage:
|
|
45
|
-
awm setup [target] [options] Configure AWM for an AI CLI
|
|
46
|
-
awm doctor [target|--all] Validate AWM integrations
|
|
47
|
-
awm mcp Start MCP server (stdio)
|
|
48
|
-
awm serve [--port <port>] Start HTTP API server
|
|
49
|
-
awm health [--port <port>] Check server health
|
|
50
|
-
awm export --db <path> [--agent <id>] [--output <file>] [--active-only]
|
|
51
|
-
Export memories to JSON
|
|
52
|
-
awm import <file> --db <path> [--remap-agent <id>] [--dedupe] [--dry-run]
|
|
53
|
-
Import memories from JSON
|
|
54
|
-
awm merge --target <db> --source <db> [--source ...]
|
|
55
|
-
[--remap uuid=name] [--remap-all-uuids <name>]
|
|
56
|
-
[--dedupe] [--dry-run] Merge multiple memory DBs
|
|
57
|
-
|
|
58
|
-
Setup targets:
|
|
59
|
-
claude-code (default) .mcp.json + CLAUDE.md + hooks
|
|
60
|
-
codex ~/.codex/config.toml + AGENTS.md
|
|
61
|
-
cursor .cursor/mcp.json + .cursorrules
|
|
62
|
-
http Connection info for HTTP API
|
|
63
|
-
|
|
64
|
-
Setup options:
|
|
65
|
-
--global Use global scope (recommended for claude-code)
|
|
66
|
-
--agent-id <id> Agent identifier (default: project name)
|
|
67
|
-
--db-path <path> Database path (default: <awm>/data/memory.db)
|
|
68
|
-
--no-instructions Skip instruction file (CLAUDE.md, AGENTS.md, etc.)
|
|
69
|
-
--no-claude-md Alias for --no-instructions
|
|
70
|
-
--no-hooks Skip hook installation
|
|
71
|
-
--hook-port PORT Sidecar port for hooks (default: 8401)
|
|
72
|
-
|
|
73
|
-
Examples:
|
|
74
|
-
awm setup --global Claude Code, global (recommended)
|
|
75
|
-
awm setup codex Codex CLI
|
|
76
|
-
awm setup cursor Cursor IDE
|
|
77
|
-
awm setup http Generic HTTP integration
|
|
78
|
-
awm doctor --all Check all configured targets
|
|
41
|
+
console.log(`
|
|
42
|
+
AgentWorkingMemory — Cognitive memory for AI agents
|
|
43
|
+
|
|
44
|
+
Usage:
|
|
45
|
+
awm setup [target] [options] Configure AWM for an AI CLI
|
|
46
|
+
awm doctor [target|--all] Validate AWM integrations
|
|
47
|
+
awm mcp Start MCP server (stdio)
|
|
48
|
+
awm serve [--port <port>] Start HTTP API server
|
|
49
|
+
awm health [--port <port>] Check server health
|
|
50
|
+
awm export --db <path> [--agent <id>] [--output <file>] [--active-only]
|
|
51
|
+
Export memories to JSON
|
|
52
|
+
awm import <file> --db <path> [--remap-agent <id>] [--dedupe] [--dry-run]
|
|
53
|
+
Import memories from JSON
|
|
54
|
+
awm merge --target <db> --source <db> [--source ...]
|
|
55
|
+
[--remap uuid=name] [--remap-all-uuids <name>]
|
|
56
|
+
[--dedupe] [--dry-run] Merge multiple memory DBs
|
|
57
|
+
|
|
58
|
+
Setup targets:
|
|
59
|
+
claude-code (default) .mcp.json + CLAUDE.md + hooks
|
|
60
|
+
codex ~/.codex/config.toml + AGENTS.md
|
|
61
|
+
cursor .cursor/mcp.json + .cursorrules
|
|
62
|
+
http Connection info for HTTP API
|
|
63
|
+
|
|
64
|
+
Setup options:
|
|
65
|
+
--global Use global scope (recommended for claude-code)
|
|
66
|
+
--agent-id <id> Agent identifier (default: project name)
|
|
67
|
+
--db-path <path> Database path (default: <awm>/data/memory.db)
|
|
68
|
+
--no-instructions Skip instruction file (CLAUDE.md, AGENTS.md, etc.)
|
|
69
|
+
--no-claude-md Alias for --no-instructions
|
|
70
|
+
--no-hooks Skip hook installation
|
|
71
|
+
--hook-port PORT Sidecar port for hooks (default: 8401)
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
awm setup --global Claude Code, global (recommended)
|
|
75
|
+
awm setup codex Codex CLI
|
|
76
|
+
awm setup cursor Cursor IDE
|
|
77
|
+
awm setup http Generic HTTP integration
|
|
78
|
+
awm doctor --all Check all configured targets
|
|
79
79
|
`.trim());
|
|
80
80
|
}
|
|
81
81
|
// ─── SETUP ──────────────────────────────────────
|
|
@@ -133,18 +133,18 @@ async function setup() {
|
|
|
133
133
|
const configAction = adapter.writeMcpConfig(ctx);
|
|
134
134
|
const instructionsAction = adapter.writeInstructions(ctx, skipInstructions);
|
|
135
135
|
const hooksAction = adapter.writeHooks(ctx, skipHooks);
|
|
136
|
-
console.log(`
|
|
137
|
-
AWM configured for ${adapter.name}${isGlobal ? ' (global)' : ''}
|
|
138
|
-
|
|
139
|
-
Agent ID: ${ctx.agentId}
|
|
140
|
-
DB path: ${ctx.dbPath}
|
|
141
|
-
${configAction}
|
|
142
|
-
${instructionsAction}
|
|
143
|
-
${hooksAction}
|
|
144
|
-
|
|
145
|
-
Next steps:
|
|
146
|
-
1. Restart ${adapter.name} to pick up the MCP server
|
|
147
|
-
2. Memory tools will appear automatically${adapter.id === 'codex' ? ' (verify with /mcp)' : ''}
|
|
136
|
+
console.log(`
|
|
137
|
+
AWM configured for ${adapter.name}${isGlobal ? ' (global)' : ''}
|
|
138
|
+
|
|
139
|
+
Agent ID: ${ctx.agentId}
|
|
140
|
+
DB path: ${ctx.dbPath}
|
|
141
|
+
${configAction}
|
|
142
|
+
${instructionsAction}
|
|
143
|
+
${hooksAction}
|
|
144
|
+
|
|
145
|
+
Next steps:
|
|
146
|
+
1. Restart ${adapter.name} to pick up the MCP server
|
|
147
|
+
2. Memory tools will appear automatically${adapter.id === 'codex' ? ' (verify with /mcp)' : ''}
|
|
148
148
|
`.trim());
|
|
149
149
|
}
|
|
150
150
|
// ─── DOCTOR ──────────────────────────────────────
|
|
@@ -307,7 +307,7 @@ async function exportMemories() {
|
|
|
307
307
|
// Collect unique agents
|
|
308
308
|
const agents = [...new Set(memories.map((m) => m.agent_id))];
|
|
309
309
|
const exportData = {
|
|
310
|
-
version: '0.
|
|
310
|
+
version: '0.7.1',
|
|
311
311
|
exported_at: new Date().toISOString(),
|
|
312
312
|
source_db: dbPath,
|
|
313
313
|
agent_filter: agentFilter,
|
|
@@ -372,23 +372,23 @@ async function importMemories() {
|
|
|
372
372
|
const Database = (await import('better-sqlite3')).default;
|
|
373
373
|
const db = new Database(dbPath);
|
|
374
374
|
// Ensure tables exist in target
|
|
375
|
-
db.exec(`
|
|
376
|
-
CREATE TABLE IF NOT EXISTS engrams (
|
|
377
|
-
id TEXT PRIMARY KEY, agent_id TEXT NOT NULL, concept TEXT NOT NULL, content TEXT NOT NULL,
|
|
378
|
-
embedding BLOB, confidence REAL NOT NULL DEFAULT 0.5, salience REAL NOT NULL DEFAULT 0.5,
|
|
379
|
-
access_count INTEGER NOT NULL DEFAULT 0, last_accessed TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
380
|
-
salience_features TEXT NOT NULL DEFAULT '{}', reason_codes TEXT NOT NULL DEFAULT '[]',
|
|
381
|
-
stage TEXT NOT NULL DEFAULT 'active', ttl INTEGER, retracted INTEGER NOT NULL DEFAULT 0,
|
|
382
|
-
retracted_by TEXT, retracted_at TEXT, tags TEXT NOT NULL DEFAULT '[]',
|
|
383
|
-
episode_id TEXT, task_status TEXT, task_priority TEXT, blocked_by TEXT,
|
|
384
|
-
memory_class TEXT NOT NULL DEFAULT 'working', superseded_by TEXT, supersedes TEXT
|
|
385
|
-
);
|
|
386
|
-
CREATE TABLE IF NOT EXISTS associations (
|
|
387
|
-
id TEXT PRIMARY KEY, from_engram_id TEXT NOT NULL, to_engram_id TEXT NOT NULL,
|
|
388
|
-
weight REAL NOT NULL DEFAULT 0.1, confidence REAL NOT NULL DEFAULT 0.5,
|
|
389
|
-
type TEXT NOT NULL DEFAULT 'hebbian', activation_count INTEGER NOT NULL DEFAULT 0,
|
|
390
|
-
created_at TEXT NOT NULL, last_activated TEXT
|
|
391
|
-
);
|
|
375
|
+
db.exec(`
|
|
376
|
+
CREATE TABLE IF NOT EXISTS engrams (
|
|
377
|
+
id TEXT PRIMARY KEY, agent_id TEXT NOT NULL, concept TEXT NOT NULL, content TEXT NOT NULL,
|
|
378
|
+
embedding BLOB, confidence REAL NOT NULL DEFAULT 0.5, salience REAL NOT NULL DEFAULT 0.5,
|
|
379
|
+
access_count INTEGER NOT NULL DEFAULT 0, last_accessed TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
380
|
+
salience_features TEXT NOT NULL DEFAULT '{}', reason_codes TEXT NOT NULL DEFAULT '[]',
|
|
381
|
+
stage TEXT NOT NULL DEFAULT 'active', ttl INTEGER, retracted INTEGER NOT NULL DEFAULT 0,
|
|
382
|
+
retracted_by TEXT, retracted_at TEXT, tags TEXT NOT NULL DEFAULT '[]',
|
|
383
|
+
episode_id TEXT, task_status TEXT, task_priority TEXT, blocked_by TEXT,
|
|
384
|
+
memory_class TEXT NOT NULL DEFAULT 'working', superseded_by TEXT, supersedes TEXT
|
|
385
|
+
);
|
|
386
|
+
CREATE TABLE IF NOT EXISTS associations (
|
|
387
|
+
id TEXT PRIMARY KEY, from_engram_id TEXT NOT NULL, to_engram_id TEXT NOT NULL,
|
|
388
|
+
weight REAL NOT NULL DEFAULT 0.1, confidence REAL NOT NULL DEFAULT 0.5,
|
|
389
|
+
type TEXT NOT NULL DEFAULT 'hebbian', activation_count INTEGER NOT NULL DEFAULT 0,
|
|
390
|
+
created_at TEXT NOT NULL, last_activated TEXT
|
|
391
|
+
);
|
|
392
392
|
`);
|
|
393
393
|
// Build dedup set if needed
|
|
394
394
|
const existingHashes = new Set();
|
|
@@ -403,15 +403,15 @@ async function importMemories() {
|
|
|
403
403
|
let imported = 0;
|
|
404
404
|
let skippedDupes = 0;
|
|
405
405
|
let skippedRetracted = 0;
|
|
406
|
-
const insertMem = db.prepare(`
|
|
407
|
-
INSERT INTO engrams (id, agent_id, concept, content, confidence, salience,
|
|
408
|
-
access_count, last_accessed, created_at, stage, tags, memory_class,
|
|
409
|
-
episode_id, task_status, task_priority, supersedes, superseded_by, retracted)
|
|
410
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
406
|
+
const insertMem = db.prepare(`
|
|
407
|
+
INSERT INTO engrams (id, agent_id, concept, content, confidence, salience,
|
|
408
|
+
access_count, last_accessed, created_at, stage, tags, memory_class,
|
|
409
|
+
episode_id, task_status, task_priority, supersedes, superseded_by, retracted)
|
|
410
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
411
411
|
`);
|
|
412
|
-
const insertAssoc = db.prepare(`
|
|
413
|
-
INSERT INTO associations (id, from_engram_id, to_engram_id, weight, type, activation_count, created_at)
|
|
414
|
-
VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
|
|
412
|
+
const insertAssoc = db.prepare(`
|
|
413
|
+
INSERT INTO associations (id, from_engram_id, to_engram_id, weight, type, activation_count, created_at)
|
|
414
|
+
VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
|
|
415
415
|
`);
|
|
416
416
|
const importTx = db.transaction(() => {
|
|
417
417
|
// Import memories
|
|
@@ -514,21 +514,21 @@ async function mergeMemories() {
|
|
|
514
514
|
targetDb.pragma('journal_mode = WAL');
|
|
515
515
|
targetDb.pragma('foreign_keys = ON');
|
|
516
516
|
// Ensure tables exist in target
|
|
517
|
-
targetDb.exec(`
|
|
518
|
-
CREATE TABLE IF NOT EXISTS engrams (
|
|
519
|
-
id TEXT PRIMARY KEY, agent_id TEXT NOT NULL, concept TEXT NOT NULL, content TEXT NOT NULL,
|
|
520
|
-
embedding BLOB, confidence REAL NOT NULL DEFAULT 0.5, salience REAL NOT NULL DEFAULT 0.5,
|
|
521
|
-
access_count INTEGER NOT NULL DEFAULT 0, last_accessed TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
522
|
-
salience_features TEXT NOT NULL DEFAULT '{}', reason_codes TEXT NOT NULL DEFAULT '[]',
|
|
523
|
-
stage TEXT NOT NULL DEFAULT 'active', ttl INTEGER, retracted INTEGER NOT NULL DEFAULT 0,
|
|
524
|
-
retracted_by TEXT, retracted_at TEXT, tags TEXT NOT NULL DEFAULT '[]'
|
|
525
|
-
);
|
|
526
|
-
CREATE TABLE IF NOT EXISTS associations (
|
|
527
|
-
id TEXT PRIMARY KEY, from_engram_id TEXT NOT NULL, to_engram_id TEXT NOT NULL,
|
|
528
|
-
weight REAL NOT NULL DEFAULT 0.1, confidence REAL NOT NULL DEFAULT 0.5,
|
|
529
|
-
type TEXT NOT NULL DEFAULT 'hebbian', activation_count INTEGER NOT NULL DEFAULT 0,
|
|
530
|
-
created_at TEXT NOT NULL, last_activated TEXT NOT NULL
|
|
531
|
-
);
|
|
517
|
+
targetDb.exec(`
|
|
518
|
+
CREATE TABLE IF NOT EXISTS engrams (
|
|
519
|
+
id TEXT PRIMARY KEY, agent_id TEXT NOT NULL, concept TEXT NOT NULL, content TEXT NOT NULL,
|
|
520
|
+
embedding BLOB, confidence REAL NOT NULL DEFAULT 0.5, salience REAL NOT NULL DEFAULT 0.5,
|
|
521
|
+
access_count INTEGER NOT NULL DEFAULT 0, last_accessed TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
522
|
+
salience_features TEXT NOT NULL DEFAULT '{}', reason_codes TEXT NOT NULL DEFAULT '[]',
|
|
523
|
+
stage TEXT NOT NULL DEFAULT 'active', ttl INTEGER, retracted INTEGER NOT NULL DEFAULT 0,
|
|
524
|
+
retracted_by TEXT, retracted_at TEXT, tags TEXT NOT NULL DEFAULT '[]'
|
|
525
|
+
);
|
|
526
|
+
CREATE TABLE IF NOT EXISTS associations (
|
|
527
|
+
id TEXT PRIMARY KEY, from_engram_id TEXT NOT NULL, to_engram_id TEXT NOT NULL,
|
|
528
|
+
weight REAL NOT NULL DEFAULT 0.1, confidence REAL NOT NULL DEFAULT 0.5,
|
|
529
|
+
type TEXT NOT NULL DEFAULT 'hebbian', activation_count INTEGER NOT NULL DEFAULT 0,
|
|
530
|
+
created_at TEXT NOT NULL, last_activated TEXT NOT NULL
|
|
531
|
+
);
|
|
532
532
|
`);
|
|
533
533
|
// Build dedupe hash set from existing target memories
|
|
534
534
|
const existingHashes = new Set();
|
|
@@ -538,16 +538,16 @@ async function mergeMemories() {
|
|
|
538
538
|
existingHashes.add(contentHash(row.concept, row.content));
|
|
539
539
|
console.log(`Target has ${existingHashes.size} unique memories (for dedupe)\n`);
|
|
540
540
|
}
|
|
541
|
-
const insertEngram = targetDb.prepare(`
|
|
542
|
-
INSERT OR IGNORE INTO engrams (id, agent_id, concept, content, confidence, salience, access_count,
|
|
543
|
-
last_accessed, created_at, salience_features, reason_codes, stage, ttl,
|
|
544
|
-
retracted, retracted_by, retracted_at, tags)
|
|
545
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
541
|
+
const insertEngram = targetDb.prepare(`
|
|
542
|
+
INSERT OR IGNORE INTO engrams (id, agent_id, concept, content, confidence, salience, access_count,
|
|
543
|
+
last_accessed, created_at, salience_features, reason_codes, stage, ttl,
|
|
544
|
+
retracted, retracted_by, retracted_at, tags)
|
|
545
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
546
546
|
`);
|
|
547
|
-
const insertAssoc = targetDb.prepare(`
|
|
548
|
-
INSERT OR IGNORE INTO associations (id, from_engram_id, to_engram_id, weight, confidence, type,
|
|
549
|
-
activation_count, created_at, last_activated)
|
|
550
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
547
|
+
const insertAssoc = targetDb.prepare(`
|
|
548
|
+
INSERT OR IGNORE INTO associations (id, from_engram_id, to_engram_id, weight, confidence, type,
|
|
549
|
+
activation_count, created_at, last_activated)
|
|
550
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
551
551
|
`);
|
|
552
552
|
let totalMemories = 0, totalAssociations = 0, totalSkipped = 0;
|
|
553
553
|
for (const sourcePath of sources) {
|
|
@@ -556,10 +556,10 @@ async function mergeMemories() {
|
|
|
556
556
|
continue;
|
|
557
557
|
}
|
|
558
558
|
const sourceDb = new Database(sourcePath, { readonly: true });
|
|
559
|
-
const engrams = sourceDb.prepare(`SELECT id, agent_id, concept, content, confidence, salience, access_count,
|
|
560
|
-
last_accessed, created_at, salience_features, reason_codes, stage, ttl,
|
|
559
|
+
const engrams = sourceDb.prepare(`SELECT id, agent_id, concept, content, confidence, salience, access_count,
|
|
560
|
+
last_accessed, created_at, salience_features, reason_codes, stage, ttl,
|
|
561
561
|
retracted, retracted_by, retracted_at, tags FROM engrams`).all();
|
|
562
|
-
const assocs = sourceDb.prepare(`SELECT id, from_engram_id, to_engram_id, weight, confidence, type,
|
|
562
|
+
const assocs = sourceDb.prepare(`SELECT id, from_engram_id, to_engram_id, weight, confidence, type,
|
|
563
563
|
activation_count, created_at, last_activated FROM associations`).all();
|
|
564
564
|
const idMap = new Map();
|
|
565
565
|
const skippedIds = new Set();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Tagger — generates meta-tags for memories at write time.
|
|
3
|
+
*
|
|
4
|
+
* Meta-tags serve as categorical signals that boost BM25 recall.
|
|
5
|
+
* They're indexed in FTS5 alongside concept/content/tags, so queries
|
|
6
|
+
* that match a category tag get better BM25 scores.
|
|
7
|
+
*
|
|
8
|
+
* Three sources of tags:
|
|
9
|
+
* 1. Content analysis — extract topics, entities, categories from the text
|
|
10
|
+
* 2. Context propagation — inherit relevant tags from related memories
|
|
11
|
+
* 3. Type classification — fact/experience/belief/entity markers
|
|
12
|
+
*
|
|
13
|
+
* Design: lightweight heuristics, no LLM calls. Tags are additive —
|
|
14
|
+
* they enrich the existing tag set without replacing user-provided tags.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Extract meta-tags from memory content using keyword patterns.
|
|
18
|
+
* Returns tags prefixed with 'cat:' to distinguish from user tags.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractMetaTags(concept: string, content: string): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Propagate relevant tags from related memories to a new memory.
|
|
23
|
+
* Called after connection engine links the new memory to existing ones.
|
|
24
|
+
*
|
|
25
|
+
* Strategy: inherit meta-tags from strongly connected neighbors,
|
|
26
|
+
* but only tags that appear in 2+ neighbors (consensus filtering).
|
|
27
|
+
*/
|
|
28
|
+
export declare function propagateTagsFromNeighbors(existingTags: string[], neighborTagSets: string[][]): string[];
|
|
29
|
+
//# sourceMappingURL=auto-tagger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-tagger.d.ts","sourceRoot":"","sources":["../../src/core/auto-tagger.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AAEH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA8G1E;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,MAAM,EAAE,EAAE,GAC1B,MAAM,EAAE,CAuBV"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Auto-Tagger — generates meta-tags for memories at write time.
|
|
5
|
+
*
|
|
6
|
+
* Meta-tags serve as categorical signals that boost BM25 recall.
|
|
7
|
+
* They're indexed in FTS5 alongside concept/content/tags, so queries
|
|
8
|
+
* that match a category tag get better BM25 scores.
|
|
9
|
+
*
|
|
10
|
+
* Three sources of tags:
|
|
11
|
+
* 1. Content analysis — extract topics, entities, categories from the text
|
|
12
|
+
* 2. Context propagation — inherit relevant tags from related memories
|
|
13
|
+
* 3. Type classification — fact/experience/belief/entity markers
|
|
14
|
+
*
|
|
15
|
+
* Design: lightweight heuristics, no LLM calls. Tags are additive —
|
|
16
|
+
* they enrich the existing tag set without replacing user-provided tags.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Extract meta-tags from memory content using keyword patterns.
|
|
20
|
+
* Returns tags prefixed with 'cat:' to distinguish from user tags.
|
|
21
|
+
*/
|
|
22
|
+
export function extractMetaTags(concept, content) {
|
|
23
|
+
const tags = [];
|
|
24
|
+
const text = `${concept} ${content}`.toLowerCase();
|
|
25
|
+
// --- Category tags (broad topic classification) ---
|
|
26
|
+
// People / personal
|
|
27
|
+
if (/\b(i |my |i'm |i've |we |our |me )\b/.test(text)) {
|
|
28
|
+
tags.push('cat:personal');
|
|
29
|
+
}
|
|
30
|
+
// Work / professional
|
|
31
|
+
if (/\b(work|job|office|meeting|project|team|manager|colleague|career|salary|hired)\b/.test(text)) {
|
|
32
|
+
tags.push('cat:work');
|
|
33
|
+
}
|
|
34
|
+
// Technology / computing
|
|
35
|
+
if (/\b(code|programming|software|database|api|server|deploy|bug|git|typescript|python|react|node)\b/.test(text)) {
|
|
36
|
+
tags.push('cat:tech');
|
|
37
|
+
}
|
|
38
|
+
// Health / wellness
|
|
39
|
+
if (/\b(health|doctor|exercise|yoga|gym|diet|sleep|meditation|therapy|medicine|symptom)\b/.test(text)) {
|
|
40
|
+
tags.push('cat:health');
|
|
41
|
+
}
|
|
42
|
+
// Finance / money
|
|
43
|
+
if (/\b(money|budget|savings|invest|salary|cost|price|payment|bank|credit|expense|coupon|store|bought|purchased)\b/.test(text)) {
|
|
44
|
+
tags.push('cat:finance');
|
|
45
|
+
}
|
|
46
|
+
// Home / living
|
|
47
|
+
if (/\b(home|house|apartment|room|kitchen|bedroom|furniture|garden|repair|renovation|neighbor|moved)\b/.test(text)) {
|
|
48
|
+
tags.push('cat:home');
|
|
49
|
+
}
|
|
50
|
+
// Travel / location
|
|
51
|
+
if (/\b(travel|trip|vacation|flight|hotel|restaurant|city|country|visited|downtown|park)\b/.test(text)) {
|
|
52
|
+
tags.push('cat:location');
|
|
53
|
+
}
|
|
54
|
+
// Education / learning
|
|
55
|
+
if (/\b(school|university|college|degree|course|class|study|learn|graduate|student|teacher|exam)\b/.test(text)) {
|
|
56
|
+
tags.push('cat:education');
|
|
57
|
+
}
|
|
58
|
+
// Social / relationships
|
|
59
|
+
if (/\b(friend|family|partner|spouse|child|parent|sibling|birthday|party|dinner|wedding|date)\b/.test(text)) {
|
|
60
|
+
tags.push('cat:social');
|
|
61
|
+
}
|
|
62
|
+
// Hobbies / entertainment
|
|
63
|
+
if (/\b(music|movie|book|game|sport|hobby|play|concert|theater|playlist|podcast|guitar|tennis|yoga|painting)\b/.test(text)) {
|
|
64
|
+
tags.push('cat:hobby');
|
|
65
|
+
}
|
|
66
|
+
// Shopping / consumer
|
|
67
|
+
if (/\b(bought|purchased|ordered|shop|store|amazon|target|walmart|coupon|sale|discount|delivery)\b/.test(text)) {
|
|
68
|
+
tags.push('cat:shopping');
|
|
69
|
+
}
|
|
70
|
+
// Food / cooking
|
|
71
|
+
if (/\b(cook|recipe|restaurant|meal|food|dinner|lunch|breakfast|coffee|tea|bake|kitchen)\b/.test(text)) {
|
|
72
|
+
tags.push('cat:food');
|
|
73
|
+
}
|
|
74
|
+
// Pets / animals
|
|
75
|
+
if (/\b(pet|dog|cat|animal|vet|shelter|walk|breed)\b/.test(text)) {
|
|
76
|
+
tags.push('cat:pets');
|
|
77
|
+
}
|
|
78
|
+
// Time markers
|
|
79
|
+
if (/\b(yesterday|today|last week|last month|tomorrow|next week|this morning|this evening|monday|tuesday|wednesday|thursday|friday|saturday|sunday)\b/.test(text)) {
|
|
80
|
+
tags.push('cat:temporal');
|
|
81
|
+
}
|
|
82
|
+
// --- Entity extraction (simple noun phrase patterns) ---
|
|
83
|
+
// Proper nouns (capitalized words that aren't sentence starters)
|
|
84
|
+
const properNouns = content.match(/(?:^|\.\s+)?([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)/g);
|
|
85
|
+
if (properNouns) {
|
|
86
|
+
const unique = [...new Set(properNouns.map(n => n.trim()).filter(n => n.length > 2 && n.length < 30))];
|
|
87
|
+
for (const noun of unique.slice(0, 5)) {
|
|
88
|
+
tags.push(`entity:${noun}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// --- Knowledge type tags ---
|
|
92
|
+
// Preference (I like/prefer/enjoy/love/hate)
|
|
93
|
+
if (/\b(i like|i prefer|i enjoy|i love|i hate|my favorite|i don't like)\b/.test(text)) {
|
|
94
|
+
tags.push('cat:preference');
|
|
95
|
+
}
|
|
96
|
+
// Fact (declarative statements about identity/attributes)
|
|
97
|
+
if (/\b(my name is|i am a|i work at|i live in|i graduated|my birthday|i was born)\b/.test(text)) {
|
|
98
|
+
tags.push('cat:identity');
|
|
99
|
+
}
|
|
100
|
+
// Plan / intention
|
|
101
|
+
if (/\b(i plan to|i'm going to|i want to|i'm thinking of|i'm considering|next week i|planning to)\b/.test(text)) {
|
|
102
|
+
tags.push('cat:plan');
|
|
103
|
+
}
|
|
104
|
+
// Experience / event
|
|
105
|
+
if (/\b(i went|i visited|i attended|i tried|i saw|i heard|i found|i discovered)\b/.test(text)) {
|
|
106
|
+
tags.push('cat:experience');
|
|
107
|
+
}
|
|
108
|
+
return tags;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Propagate relevant tags from related memories to a new memory.
|
|
112
|
+
* Called after connection engine links the new memory to existing ones.
|
|
113
|
+
*
|
|
114
|
+
* Strategy: inherit meta-tags from strongly connected neighbors,
|
|
115
|
+
* but only tags that appear in 2+ neighbors (consensus filtering).
|
|
116
|
+
*/
|
|
117
|
+
export function propagateTagsFromNeighbors(existingTags, neighborTagSets) {
|
|
118
|
+
if (neighborTagSets.length === 0)
|
|
119
|
+
return [];
|
|
120
|
+
// Count meta-tag occurrences across neighbors
|
|
121
|
+
const tagCounts = new Map();
|
|
122
|
+
for (const tags of neighborTagSets) {
|
|
123
|
+
for (const tag of tags) {
|
|
124
|
+
if (tag.startsWith('cat:') || tag.startsWith('entity:')) {
|
|
125
|
+
tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Only propagate tags that appear in 2+ neighbors (consensus)
|
|
130
|
+
const propagated = [];
|
|
131
|
+
const existingSet = new Set(existingTags);
|
|
132
|
+
for (const [tag, count] of tagCounts) {
|
|
133
|
+
if (count >= 2 && !existingSet.has(tag)) {
|
|
134
|
+
propagated.push(tag);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return propagated.slice(0, 5); // Cap to avoid tag bloat
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=auto-tagger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-tagger.js","sourceRoot":"","sources":["../../src/core/auto-tagger.ts"],"names":[],"mappings":"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"}
|
package/dist/core/hebbian.d.ts
CHANGED
|
@@ -15,7 +15,16 @@
|
|
|
15
15
|
export declare function strengthenAssociation(currentWeight: number, signal?: number, rate?: number): number;
|
|
16
16
|
/**
|
|
17
17
|
* Weaken an association weight due to lack of co-activation.
|
|
18
|
-
*
|
|
18
|
+
* Uses power-law decay (DASH model) instead of exponential.
|
|
19
|
+
* Power law has a longer tail — old but valuable associations
|
|
20
|
+
* don't vanish as aggressively as exponential decay.
|
|
21
|
+
*
|
|
22
|
+
* DASH: weight = initial × (1 + t/scale)^(-exponent)
|
|
23
|
+
* vs exponential: weight = initial × 0.5^(t/halfLife)
|
|
24
|
+
*
|
|
25
|
+
* At 7 days: power-law retains ~58% vs exponential 50%
|
|
26
|
+
* At 30 days: power-law retains ~32% vs exponential 6%
|
|
27
|
+
* At 90 days: power-law retains ~20% vs exponential 0.02%
|
|
19
28
|
*/
|
|
20
29
|
export declare function decayAssociation(currentWeight: number, daysSinceActivation: number, halfLife?: number): number;
|
|
21
30
|
/**
|
|
@@ -35,4 +44,19 @@ export declare class CoActivationBuffer {
|
|
|
35
44
|
getCoActivatedPairs(windowMs?: number): [string, string][];
|
|
36
45
|
clear(): void;
|
|
37
46
|
}
|
|
47
|
+
export declare class ValidationGatedBuffer {
|
|
48
|
+
private pending;
|
|
49
|
+
/** Record co-activated pairs as pending (awaiting feedback validation) */
|
|
50
|
+
addPending(engramIds: string[], pairs: [string, string][]): void;
|
|
51
|
+
/**
|
|
52
|
+
* Resolve pending updates for an engram that received feedback.
|
|
53
|
+
* Returns pairs to strengthen (positive) or weaken (negative).
|
|
54
|
+
*/
|
|
55
|
+
resolveFeedback(engramId: string, useful: boolean): {
|
|
56
|
+
pairs: [string, string][];
|
|
57
|
+
signal: number;
|
|
58
|
+
};
|
|
59
|
+
/** Get count of pending updates (for stats) */
|
|
60
|
+
get pendingCount(): number;
|
|
61
|
+
}
|
|
38
62
|
//# sourceMappingURL=hebbian.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hebbian.d.ts","sourceRoot":"","sources":["../../src/core/hebbian.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAKH;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,GAAE,MAAY,EACpB,IAAI,GAAE,MAAa,GAClB,MAAM,CAIR;AAED
|
|
1
|
+
{"version":3,"file":"hebbian.d.ts","sourceRoot":"","sources":["../../src/core/hebbian.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAKH;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,GAAE,MAAY,EACpB,IAAI,GAAE,MAAa,GAClB,MAAM,CAIR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,MAAM,EACrB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,GAAE,MAAY,GACrB,MAAM,CAKR;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiD;IAC/D,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,MAAW;IAIhC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAO5B,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAMpC;;OAEG;IACH,mBAAmB,CAAC,QAAQ,GAAE,MAAa,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;IAiBhE,KAAK,IAAI,IAAI;CAGd;AAsBD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,OAAO,CAA8B;IAE7C,0EAA0E;IAC1E,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI;IAOhE;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IA+BjG,+CAA+C;IAC/C,IAAI,YAAY,IAAI,MAAM,CAAgC;CAC3D"}
|
package/dist/core/hebbian.js
CHANGED
|
@@ -23,11 +23,22 @@ export function strengthenAssociation(currentWeight, signal = 1.0, rate = 0.25)
|
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Weaken an association weight due to lack of co-activation.
|
|
26
|
-
*
|
|
26
|
+
* Uses power-law decay (DASH model) instead of exponential.
|
|
27
|
+
* Power law has a longer tail — old but valuable associations
|
|
28
|
+
* don't vanish as aggressively as exponential decay.
|
|
29
|
+
*
|
|
30
|
+
* DASH: weight = initial × (1 + t/scale)^(-exponent)
|
|
31
|
+
* vs exponential: weight = initial × 0.5^(t/halfLife)
|
|
32
|
+
*
|
|
33
|
+
* At 7 days: power-law retains ~58% vs exponential 50%
|
|
34
|
+
* At 30 days: power-law retains ~32% vs exponential 6%
|
|
35
|
+
* At 90 days: power-law retains ~20% vs exponential 0.02%
|
|
27
36
|
*/
|
|
28
|
-
export function decayAssociation(currentWeight, daysSinceActivation, halfLife = 7.0 // days
|
|
37
|
+
export function decayAssociation(currentWeight, daysSinceActivation, halfLife = 7.0 // scale parameter (days)
|
|
29
38
|
) {
|
|
30
|
-
|
|
39
|
+
// Power-law decay: (1 + t/scale)^(-exponent)
|
|
40
|
+
const exponent = 0.8; // Controls steepness — 0.8 gives a good balance
|
|
41
|
+
const decayFactor = Math.pow(1 + daysSinceActivation / halfLife, -exponent);
|
|
31
42
|
return Math.max(currentWeight * decayFactor, MIN_WEIGHT);
|
|
32
43
|
}
|
|
33
44
|
/**
|
|
@@ -73,4 +84,61 @@ export class CoActivationBuffer {
|
|
|
73
84
|
this.buffer = [];
|
|
74
85
|
}
|
|
75
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Validation-gated Hebbian buffer (Kairos-inspired).
|
|
89
|
+
*
|
|
90
|
+
* Instead of strengthening associations immediately on co-activation,
|
|
91
|
+
* pairs are held pending until feedback arrives. This prevents hub toxicity
|
|
92
|
+
* from noisy co-retrieval — edges only strengthen when the retrieval was
|
|
93
|
+
* actually useful.
|
|
94
|
+
*
|
|
95
|
+
* - Positive feedback → strengthen the pending pairs
|
|
96
|
+
* - Negative feedback → slightly weaken them
|
|
97
|
+
* - No feedback within GATE_TIMEOUT_MS → discard (neutral)
|
|
98
|
+
*/
|
|
99
|
+
const GATE_TIMEOUT_MS = 60_000; // 60 seconds to receive feedback
|
|
100
|
+
export class ValidationGatedBuffer {
|
|
101
|
+
pending = [];
|
|
102
|
+
/** Record co-activated pairs as pending (awaiting feedback validation) */
|
|
103
|
+
addPending(engramIds, pairs) {
|
|
104
|
+
this.pending.push({ pairs, engramIds, timestamp: Date.now() });
|
|
105
|
+
// Evict expired entries
|
|
106
|
+
const cutoff = Date.now() - GATE_TIMEOUT_MS;
|
|
107
|
+
this.pending = this.pending.filter(p => p.timestamp > cutoff);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Resolve pending updates for an engram that received feedback.
|
|
111
|
+
* Returns pairs to strengthen (positive) or weaken (negative).
|
|
112
|
+
*/
|
|
113
|
+
resolveFeedback(engramId, useful) {
|
|
114
|
+
const cutoff = Date.now() - GATE_TIMEOUT_MS;
|
|
115
|
+
const matching = [];
|
|
116
|
+
// Find all pending updates that include this engram and are still within the gate window
|
|
117
|
+
this.pending = this.pending.filter(p => {
|
|
118
|
+
if (p.timestamp < cutoff)
|
|
119
|
+
return false; // expired
|
|
120
|
+
if (p.engramIds.includes(engramId)) {
|
|
121
|
+
matching.push(...p.pairs);
|
|
122
|
+
return false; // consumed
|
|
123
|
+
}
|
|
124
|
+
return true; // keep
|
|
125
|
+
});
|
|
126
|
+
// Deduplicate pairs
|
|
127
|
+
const seen = new Set();
|
|
128
|
+
const unique = [];
|
|
129
|
+
for (const [a, b] of matching) {
|
|
130
|
+
const key = a < b ? `${a}:${b}` : `${b}:${a}`;
|
|
131
|
+
if (!seen.has(key)) {
|
|
132
|
+
seen.add(key);
|
|
133
|
+
unique.push([a, b]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
pairs: unique,
|
|
138
|
+
signal: useful ? 1.0 : -0.3, // positive = full strengthen, negative = slight weaken
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/** Get count of pending updates (for stats) */
|
|
142
|
+
get pendingCount() { return this.pending.length; }
|
|
143
|
+
}
|
|
76
144
|
//# sourceMappingURL=hebbian.js.map
|
package/dist/core/hebbian.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hebbian.js","sourceRoot":"","sources":["../../src/core/hebbian.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;GAUG;AAEH,MAAM,UAAU,GAAG,KAAK,CAAC;AACzB,MAAM,UAAU,GAAG,GAAG,CAAC,CAAE,2CAA2C;AAEpE;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAAqB,EACrB,SAAiB,GAAG,EACpB,OAAe,IAAI;IAEnB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;AAChD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"hebbian.js","sourceRoot":"","sources":["../../src/core/hebbian.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-expander.d.ts","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAY,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"query-expander.d.ts","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAY,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAMvF;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,2BAA2B,CAAC,CAaxE;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBxE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-expander.js","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAoC,MAAM,2BAA2B,CAAC;AAEvF,MAAM,QAAQ,GAAG,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"query-expander.js","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAoC,MAAM,2BAA2B,CAAC;AAEvF,MAAM,QAAQ,GAAG,sBAAsB,CAAC;AACxC,IAAI,QAAQ,GAAuC,IAAI,CAAC;AACxD,IAAI,WAAW,GAAgD,IAAI,CAAC;AAEpE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,WAAW,GAAG,QAAQ,CAAC,sBAAsB,EAAE,QAAQ,EAAE;QACvD,KAAK,EAAE,MAAM;KACd,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACb,QAAQ,GAAG,IAAmC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,aAAqB;IACrD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,8HAA8H,aAAa,qBAAqB,CAAC;QAEhL,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE;YACpC,cAAc,EAAE,EAAE;YAClB,oBAAoB,EAAE,CAAC;SACxB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,CAAC,CAAS,EAAE,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEtC,IAAI,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,OAAO,GAAG,aAAa,IAAI,aAAa,EAAE,CAAC;QAC7C,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,aAAa,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AA8BH,yEAAyE;AACzE,wBAAsB,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,CAGhD;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAMD;;;GAGG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CAiCzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reranker.js","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,aAAa,EACb,kCAAkC,GAGnC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,aAAa,GAAG,+BAA+B,CAAC;AACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"reranker.js","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,aAAa,EACb,kCAAkC,GAGnC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,aAAa,GAAG,+BAA+B,CAAC;AACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,aAAa,CAAC;AACjE,IAAI,SAAS,GAA+B,IAAI,CAAC;AACjD,IAAI,KAAK,GAA2B,IAAI,CAAC;AACzC,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C,KAAK,UAAU,YAAY;IACzB,IAAI,SAAS,IAAI,KAAK;QAAE,OAAO;IAC/B,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;QACxB,SAAS,GAAG,MAAM,aAAa,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC1D,KAAK,GAAG,MAAM,kCAAkC,CAAC,eAAe,CAAC,QAAQ,EAAE;YACzE,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,YAAY,EAAE,CAAC;IACrB,OAAO,KAAK,CAAC;AACf,CAAC;AAOD,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAAa,EACb,QAAkB;IAElB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,YAAY,EAAE,CAAC;IAErB,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,mDAAmD;YACnD,MAAM,MAAM,GAAG,SAAU,CAAC,KAAK,EAAE;gBAC/B,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACtB,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,IAAI;gBAChB,cAAc,EAAE,IAAI;aACrB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,KAAM,CAAC,MAAM,CAAC,CAAC;YAEpC,gEAAgE;YAChE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,iBAAiB,CAAC;YACzD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAW,CAAC;YAE1C,0CAA0C;YAC1C,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC;AACjB,CAAC"}
|