@mce-bt/microagents-memory 0.7.0 → 0.8.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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/knowledge-graph.d.ts +13 -1
- package/dist/knowledge-graph.d.ts.map +1 -1
- package/dist/knowledge-graph.js +95 -47
- package/dist/knowledge-graph.js.map +1 -1
- package/dist/ltm.d.ts +10 -1
- package/dist/ltm.d.ts.map +1 -1
- package/dist/ltm.js +40 -21
- package/dist/ltm.js.map +1 -1
- package/dist/manager.d.ts +40 -0
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +79 -4
- package/dist/manager.js.map +1 -1
- package/dist/memory-tools.js +38 -13
- package/dist/memory-tools.js.map +1 -1
- package/dist/mtm.d.ts +8 -1
- package/dist/mtm.d.ts.map +1 -1
- package/dist/mtm.js +19 -6
- package/dist/mtm.js.map +1 -1
- package/dist/vector-index.d.ts +46 -0
- package/dist/vector-index.d.ts.map +1 -0
- package/dist/vector-index.js +83 -0
- package/dist/vector-index.js.map +1 -0
- package/package.json +1 -1
package/dist/mtm.js
CHANGED
|
@@ -11,8 +11,10 @@ export class MidTermMemory {
|
|
|
11
11
|
pool = null;
|
|
12
12
|
config;
|
|
13
13
|
agentId = '';
|
|
14
|
+
namespace;
|
|
14
15
|
constructor(config) {
|
|
15
16
|
this.config = config;
|
|
17
|
+
this.namespace = config.namespace ?? 'default';
|
|
16
18
|
}
|
|
17
19
|
async start(agentId) {
|
|
18
20
|
this.agentId = agentId;
|
|
@@ -32,6 +34,7 @@ export class MidTermMemory {
|
|
|
32
34
|
CREATE TABLE IF NOT EXISTS mtm_episodes (
|
|
33
35
|
id TEXT PRIMARY KEY,
|
|
34
36
|
agent_id TEXT NOT NULL,
|
|
37
|
+
namespace TEXT NOT NULL DEFAULT 'default',
|
|
35
38
|
session_id TEXT NOT NULL,
|
|
36
39
|
summary TEXT NOT NULL,
|
|
37
40
|
tags TEXT[] DEFAULT '{}',
|
|
@@ -42,7 +45,10 @@ export class MidTermMemory {
|
|
|
42
45
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
43
46
|
);
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
ALTER TABLE mtm_episodes
|
|
49
|
+
ADD COLUMN IF NOT EXISTS namespace TEXT NOT NULL DEFAULT 'default';
|
|
50
|
+
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_mtm_agent_id ON mtm_episodes(namespace, agent_id);
|
|
46
52
|
CREATE INDEX IF NOT EXISTS idx_mtm_domain ON mtm_episodes(domain);
|
|
47
53
|
CREATE INDEX IF NOT EXISTS idx_mtm_tags ON mtm_episodes USING GIN(tags);
|
|
48
54
|
CREATE INDEX IF NOT EXISTS idx_mtm_started_at ON mtm_episodes(started_at DESC);
|
|
@@ -55,10 +61,11 @@ export class MidTermMemory {
|
|
|
55
61
|
if (!this.pool)
|
|
56
62
|
throw new Error('MTM not started');
|
|
57
63
|
const id = `ep-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
58
|
-
await this.pool.query(`INSERT INTO mtm_episodes (id, agent_id, session_id, summary, tags, domain, started_at, ended_at, metadata)
|
|
59
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, [
|
|
64
|
+
await this.pool.query(`INSERT INTO mtm_episodes (id, agent_id, namespace, session_id, summary, tags, domain, started_at, ended_at, metadata)
|
|
65
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, [
|
|
60
66
|
id,
|
|
61
67
|
episode.agentId,
|
|
68
|
+
this.namespace,
|
|
62
69
|
episode.sessionId,
|
|
63
70
|
episode.summary,
|
|
64
71
|
episode.tags,
|
|
@@ -78,6 +85,11 @@ export class MidTermMemory {
|
|
|
78
85
|
const conditions = [];
|
|
79
86
|
const params = [];
|
|
80
87
|
let idx = 1;
|
|
88
|
+
// The namespace is never caller-overridable: `options.agentId` may reach
|
|
89
|
+
// across agents, but only ever within this instance's own boundary.
|
|
90
|
+
conditions.push(`namespace = $${idx}`);
|
|
91
|
+
params.push(this.namespace);
|
|
92
|
+
idx++;
|
|
81
93
|
// Default to current agent
|
|
82
94
|
conditions.push(`agent_id = $${idx}`);
|
|
83
95
|
params.push(options.agentId ?? this.agentId);
|
|
@@ -103,12 +115,13 @@ export class MidTermMemory {
|
|
|
103
115
|
return result.rows.map(this.rowToEpisode);
|
|
104
116
|
}
|
|
105
117
|
/**
|
|
106
|
-
* Get a specific episode by ID.
|
|
118
|
+
* Get a specific episode by ID, within this instance's scope. An id from
|
|
119
|
+
* another namespace or agent reads as "not found".
|
|
107
120
|
*/
|
|
108
121
|
async getById(id) {
|
|
109
122
|
if (!this.pool)
|
|
110
123
|
throw new Error('MTM not started');
|
|
111
|
-
const result = await this.pool.query('SELECT * FROM mtm_episodes WHERE id = $1', [id]);
|
|
124
|
+
const result = await this.pool.query('SELECT * FROM mtm_episodes WHERE id = $1 AND namespace = $2 AND agent_id = $3', [id, this.namespace, this.agentId]);
|
|
112
125
|
if (result.rows.length === 0)
|
|
113
126
|
return null;
|
|
114
127
|
return this.rowToEpisode(result.rows[0]);
|
|
@@ -119,7 +132,7 @@ export class MidTermMemory {
|
|
|
119
132
|
async delete(id) {
|
|
120
133
|
if (!this.pool)
|
|
121
134
|
throw new Error('MTM not started');
|
|
122
|
-
await this.pool.query('DELETE FROM mtm_episodes WHERE id = $1', [id]);
|
|
135
|
+
await this.pool.query('DELETE FROM mtm_episodes WHERE id = $1 AND namespace = $2 AND agent_id = $3', [id, this.namespace, this.agentId]);
|
|
123
136
|
}
|
|
124
137
|
rowToEpisode(row) {
|
|
125
138
|
return {
|
package/dist/mtm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mtm.js","sourceRoot":"","sources":["../src/mtm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"mtm.js","sourceRoot":"","sources":["../src/mtm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type pg from 'pg';
|
|
2
|
+
/**
|
|
3
|
+
* Below this many rows an exact sequential scan is both fast and correct, and
|
|
4
|
+
* an approximate index is actively harmful — see why in ensureVectorIndex.
|
|
5
|
+
*/
|
|
6
|
+
export declare const IVFFLAT_MIN_ROWS = 1000;
|
|
7
|
+
/** pgvector's own guidance: roughly rows/1000 lists, with a sane floor. */
|
|
8
|
+
export declare function listsForRowCount(rows: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Create — or deliberately decline to create — the ivfflat index for a vector
|
|
11
|
+
* column.
|
|
12
|
+
*
|
|
13
|
+
* This exists because of a silent, measured failure. `CREATE INDEX ... USING
|
|
14
|
+
* ivfflat WITH (lists = 100)` succeeds on an empty table, and ivfflat is an
|
|
15
|
+
* APPROXIMATE index: at the default `ivfflat.probes = 1` a query scans exactly
|
|
16
|
+
* one list. Built on no data, the lists are degenerate, so a query usually
|
|
17
|
+
* probes a list that holds nothing and returns ZERO rows — even for
|
|
18
|
+
* `ORDER BY ... LIMIT 1` against a table that does contain a match.
|
|
19
|
+
*
|
|
20
|
+
* Observed on a table with one row: three of four query vectors returned
|
|
21
|
+
* nothing; dropping the index made all four return the row. Nothing errors.
|
|
22
|
+
* Semantic recall simply appears to find nothing, which is indistinguishable
|
|
23
|
+
* from having no memories at all.
|
|
24
|
+
*
|
|
25
|
+
* So: no index until there is enough data for one to be meaningful, and when
|
|
26
|
+
* there is, size `lists` from the actual row count rather than a constant. An
|
|
27
|
+
* existing wrongly-sized index is dropped rather than left in place, since a
|
|
28
|
+
* deployment that grew past the threshold would otherwise keep the degenerate
|
|
29
|
+
* one it built while empty.
|
|
30
|
+
*/
|
|
31
|
+
export declare function ensureVectorIndex(pool: pg.Pool, table: string, indexName: string): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Minimum cosine similarity for a vector hit to count.
|
|
34
|
+
*
|
|
35
|
+
* Measured, not chosen: against a stored fact reading "strongly prefers
|
|
36
|
+
* espresso over filter coffee", text-embedding-3-small scored genuinely
|
|
37
|
+
* relevant questions at 0.31 ("what beverage should I be offered at a morning
|
|
38
|
+
* meeting"), 0.44, 0.47 ("what does the user like to drink") and 0.55 ("coffee
|
|
39
|
+
* preference"). The previous 0.7 default admitted none of them, so recall
|
|
40
|
+
* returned nothing for every real question while appearing to work.
|
|
41
|
+
*
|
|
42
|
+
* Short, asymmetric question-vs-statement text does not reach 0.7 with this
|
|
43
|
+
* model family. `limit` still bounds how much reaches the prompt.
|
|
44
|
+
*/
|
|
45
|
+
export declare const DEFAULT_SIMILARITY_THRESHOLD = 0.25;
|
|
46
|
+
//# sourceMappingURL=vector-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-index.d.ts","sourceRoot":"","sources":["../src/vector-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAEtC,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,4BAA4B,OAAO,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Below this many rows an exact sequential scan is both fast and correct, and
|
|
3
|
+
* an approximate index is actively harmful — see why in ensureVectorIndex.
|
|
4
|
+
*/
|
|
5
|
+
export const IVFFLAT_MIN_ROWS = 1_000;
|
|
6
|
+
/** pgvector's own guidance: roughly rows/1000 lists, with a sane floor. */
|
|
7
|
+
export function listsForRowCount(rows) {
|
|
8
|
+
return Math.max(1, Math.min(2_000, Math.round(rows / 1_000)));
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Create — or deliberately decline to create — the ivfflat index for a vector
|
|
12
|
+
* column.
|
|
13
|
+
*
|
|
14
|
+
* This exists because of a silent, measured failure. `CREATE INDEX ... USING
|
|
15
|
+
* ivfflat WITH (lists = 100)` succeeds on an empty table, and ivfflat is an
|
|
16
|
+
* APPROXIMATE index: at the default `ivfflat.probes = 1` a query scans exactly
|
|
17
|
+
* one list. Built on no data, the lists are degenerate, so a query usually
|
|
18
|
+
* probes a list that holds nothing and returns ZERO rows — even for
|
|
19
|
+
* `ORDER BY ... LIMIT 1` against a table that does contain a match.
|
|
20
|
+
*
|
|
21
|
+
* Observed on a table with one row: three of four query vectors returned
|
|
22
|
+
* nothing; dropping the index made all four return the row. Nothing errors.
|
|
23
|
+
* Semantic recall simply appears to find nothing, which is indistinguishable
|
|
24
|
+
* from having no memories at all.
|
|
25
|
+
*
|
|
26
|
+
* So: no index until there is enough data for one to be meaningful, and when
|
|
27
|
+
* there is, size `lists` from the actual row count rather than a constant. An
|
|
28
|
+
* existing wrongly-sized index is dropped rather than left in place, since a
|
|
29
|
+
* deployment that grew past the threshold would otherwise keep the degenerate
|
|
30
|
+
* one it built while empty.
|
|
31
|
+
*/
|
|
32
|
+
export async function ensureVectorIndex(pool, table, indexName) {
|
|
33
|
+
let rows;
|
|
34
|
+
try {
|
|
35
|
+
const result = await pool.query(`SELECT COUNT(*)::int AS c FROM ${table} WHERE embedding IS NOT NULL`);
|
|
36
|
+
rows = result.rows[0]?.c ?? 0;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Table not ready yet; a later boot will settle it.
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (rows < IVFFLAT_MIN_ROWS) {
|
|
43
|
+
// Exact search below the threshold. Dropping matters: an index built when
|
|
44
|
+
// the table was empty stays degenerate forever otherwise.
|
|
45
|
+
await pool.query(`DROP INDEX IF EXISTS ${indexName}`).catch(() => { });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const lists = listsForRowCount(rows);
|
|
49
|
+
const existing = await pool
|
|
50
|
+
.query(`SELECT indexdef FROM pg_indexes WHERE indexname = $1`, [indexName])
|
|
51
|
+
.catch(() => ({ rows: [] }));
|
|
52
|
+
const current = existing.rows[0]?.indexdef;
|
|
53
|
+
// Rebuild only when the list count is actually wrong, so a normal boot is
|
|
54
|
+
// not paying to reindex a large table every time.
|
|
55
|
+
if (current) {
|
|
56
|
+
if (current.includes(`lists='${lists}'`) || current.includes(`lists=${lists}`))
|
|
57
|
+
return;
|
|
58
|
+
await pool.query(`DROP INDEX IF EXISTS ${indexName}`).catch(() => { });
|
|
59
|
+
}
|
|
60
|
+
await pool
|
|
61
|
+
.query(`CREATE INDEX IF NOT EXISTS ${indexName}
|
|
62
|
+
ON ${table} USING ivfflat (embedding vector_cosine_ops)
|
|
63
|
+
WITH (lists = ${lists})`)
|
|
64
|
+
.catch(() => {
|
|
65
|
+
// An index is an optimisation; failing to build one must never stop an
|
|
66
|
+
// agent booting. Exact search still returns correct results.
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Minimum cosine similarity for a vector hit to count.
|
|
71
|
+
*
|
|
72
|
+
* Measured, not chosen: against a stored fact reading "strongly prefers
|
|
73
|
+
* espresso over filter coffee", text-embedding-3-small scored genuinely
|
|
74
|
+
* relevant questions at 0.31 ("what beverage should I be offered at a morning
|
|
75
|
+
* meeting"), 0.44, 0.47 ("what does the user like to drink") and 0.55 ("coffee
|
|
76
|
+
* preference"). The previous 0.7 default admitted none of them, so recall
|
|
77
|
+
* returned nothing for every real question while appearing to work.
|
|
78
|
+
*
|
|
79
|
+
* Short, asymmetric question-vs-statement text does not reach 0.7 with this
|
|
80
|
+
* model family. `limit` still bounds how much reaches the prompt.
|
|
81
|
+
*/
|
|
82
|
+
export const DEFAULT_SIMILARITY_THRESHOLD = 0.25;
|
|
83
|
+
//# sourceMappingURL=vector-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-index.js","sourceRoot":"","sources":["../src/vector-index.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC,2EAA2E;AAC3E,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAa,EACb,KAAa,EACb,SAAiB;IAEjB,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,kCAAkC,KAAK,8BAA8B,CACtE,CAAC;QACF,IAAI,GAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAY,IAAI,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,oDAAoD;QACpD,OAAO;IACT,CAAC;IAED,IAAI,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAC5B,0EAA0E;QAC1E,0DAA0D;QAC1D,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,IAAI;SACxB,KAAK,CAAC,sDAAsD,EAAE,CAAC,SAAS,CAAC,CAAC;SAC1E,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAkC,EAAE,CAAC,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;IAE3C,0EAA0E;IAC1E,kDAAkD;IAClD,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,KAAK,EAAE,CAAC;YAAE,OAAO;QACvF,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,IAAI;SACP,KAAK,CACJ,8BAA8B,SAAS;YACjC,KAAK;uBACM,KAAK,GAAG,CAC1B;SACA,KAAK,CAAC,GAAG,EAAE;QACV,uEAAuE;QACvE,6DAA6D;IAC/D,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC"}
|