@onenomad/engram-mcp 1.0.0 → 2.0.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 +685 -691
- package/dist/auth/login.d.ts +107 -68
- package/dist/auth/login.js +227 -216
- package/dist/auth/login.js.map +1 -1
- package/dist/cli.js +41 -41
- package/dist/consolidator.js +519 -519
- package/dist/context-pressure.js +91 -91
- package/dist/governance.js +6 -6
- package/dist/handoff.d.ts +11 -6
- package/dist/handoff.js +32 -10
- package/dist/handoff.js.map +1 -1
- package/dist/migrate.js +5 -5
- package/dist/server.js +1101 -927
- package/dist/server.js.map +1 -1
- package/dist/source-dedup.d.ts +86 -86
- package/dist/source-dedup.js +147 -147
- package/dist/storage-postgres.js +61 -61
- package/dist/update-metadata.d.ts +29 -29
- package/dist/update-metadata.js +51 -51
- package/dist/wal.d.ts +95 -95
- package/dist/wal.js +295 -295
- package/migrations/postgres/001_init.sql +70 -70
- package/migrations/postgres/002_indexes.sql +45 -45
- package/package.json +69 -69
package/dist/update-metadata.js
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure helper: build the storage patch for a
|
|
3
|
-
* call. Separated from server.ts so importing it (e.g. from tests)
|
|
4
|
-
* doesn't pull in the MCP stdio server bootstrap.
|
|
5
|
-
*
|
|
6
|
-
* - `merge`: only fields the caller specified land in the patch.
|
|
7
|
-
* Untouched fields are absent → Storage.updateChunk leaves them alone.
|
|
8
|
-
* - `replace`: every metadata-shape field is set, with caller values
|
|
9
|
-
* where present and engram defaults otherwise. Existing untouched
|
|
10
|
-
* fields get overwritten with the default. Footgun-y; the tool
|
|
11
|
-
* layer logs a warning when this mode fires.
|
|
12
|
-
*
|
|
13
|
-
* Immutable fields (id, createdAt, embedding, embeddingVersion) are
|
|
14
|
-
* never produced by this helper; the tool layer doesn't accept them
|
|
15
|
-
* in its input schema either.
|
|
16
|
-
*/
|
|
17
|
-
export function buildUpdateMetadataPatch(metadata, mode) {
|
|
18
|
-
const patch = {};
|
|
19
|
-
if (mode === 'replace') {
|
|
20
|
-
patch.tags = metadata.tags ?? [];
|
|
21
|
-
patch.source = metadata.source ?? '';
|
|
22
|
-
patch.domain = metadata.domain ?? '';
|
|
23
|
-
patch.topic = metadata.topic ?? '';
|
|
24
|
-
patch.type = metadata.type ?? 'context';
|
|
25
|
-
patch.sentiment = metadata.sentiment ?? 'neutral';
|
|
26
|
-
patch.importance = metadata.importance ?? 0.5;
|
|
27
|
-
if (metadata.cognitiveLayer !== undefined) {
|
|
28
|
-
patch.cognitiveLayer = metadata.cognitiveLayer;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
if (metadata.tags !== undefined)
|
|
33
|
-
patch.tags = metadata.tags;
|
|
34
|
-
if (metadata.source !== undefined)
|
|
35
|
-
patch.source = metadata.source;
|
|
36
|
-
if (metadata.domain !== undefined)
|
|
37
|
-
patch.domain = metadata.domain;
|
|
38
|
-
if (metadata.topic !== undefined)
|
|
39
|
-
patch.topic = metadata.topic;
|
|
40
|
-
if (metadata.type !== undefined)
|
|
41
|
-
patch.type = metadata.type;
|
|
42
|
-
if (metadata.sentiment !== undefined)
|
|
43
|
-
patch.sentiment = metadata.sentiment;
|
|
44
|
-
if (metadata.importance !== undefined)
|
|
45
|
-
patch.importance = metadata.importance;
|
|
46
|
-
if (metadata.cognitiveLayer !== undefined) {
|
|
47
|
-
patch.cognitiveLayer = metadata.cognitiveLayer;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return patch;
|
|
51
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Pure helper: build the storage patch for a engram-update-metadata
|
|
3
|
+
* call. Separated from server.ts so importing it (e.g. from tests)
|
|
4
|
+
* doesn't pull in the MCP stdio server bootstrap.
|
|
5
|
+
*
|
|
6
|
+
* - `merge`: only fields the caller specified land in the patch.
|
|
7
|
+
* Untouched fields are absent → Storage.updateChunk leaves them alone.
|
|
8
|
+
* - `replace`: every metadata-shape field is set, with caller values
|
|
9
|
+
* where present and engram defaults otherwise. Existing untouched
|
|
10
|
+
* fields get overwritten with the default. Footgun-y; the tool
|
|
11
|
+
* layer logs a warning when this mode fires.
|
|
12
|
+
*
|
|
13
|
+
* Immutable fields (id, createdAt, embedding, embeddingVersion) are
|
|
14
|
+
* never produced by this helper; the tool layer doesn't accept them
|
|
15
|
+
* in its input schema either.
|
|
16
|
+
*/
|
|
17
|
+
export function buildUpdateMetadataPatch(metadata, mode) {
|
|
18
|
+
const patch = {};
|
|
19
|
+
if (mode === 'replace') {
|
|
20
|
+
patch.tags = metadata.tags ?? [];
|
|
21
|
+
patch.source = metadata.source ?? '';
|
|
22
|
+
patch.domain = metadata.domain ?? '';
|
|
23
|
+
patch.topic = metadata.topic ?? '';
|
|
24
|
+
patch.type = metadata.type ?? 'context';
|
|
25
|
+
patch.sentiment = metadata.sentiment ?? 'neutral';
|
|
26
|
+
patch.importance = metadata.importance ?? 0.5;
|
|
27
|
+
if (metadata.cognitiveLayer !== undefined) {
|
|
28
|
+
patch.cognitiveLayer = metadata.cognitiveLayer;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
if (metadata.tags !== undefined)
|
|
33
|
+
patch.tags = metadata.tags;
|
|
34
|
+
if (metadata.source !== undefined)
|
|
35
|
+
patch.source = metadata.source;
|
|
36
|
+
if (metadata.domain !== undefined)
|
|
37
|
+
patch.domain = metadata.domain;
|
|
38
|
+
if (metadata.topic !== undefined)
|
|
39
|
+
patch.topic = metadata.topic;
|
|
40
|
+
if (metadata.type !== undefined)
|
|
41
|
+
patch.type = metadata.type;
|
|
42
|
+
if (metadata.sentiment !== undefined)
|
|
43
|
+
patch.sentiment = metadata.sentiment;
|
|
44
|
+
if (metadata.importance !== undefined)
|
|
45
|
+
patch.importance = metadata.importance;
|
|
46
|
+
if (metadata.cognitiveLayer !== undefined) {
|
|
47
|
+
patch.cognitiveLayer = metadata.cognitiveLayer;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return patch;
|
|
51
|
+
}
|
|
52
52
|
//# sourceMappingURL=update-metadata.js.map
|
package/dist/wal.d.ts
CHANGED
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
import type { SmartMemoryConfig, MemoryType, CognitiveLayer, Sentiment, MemoryOrigin, MemoryTier } from './types.js';
|
|
2
|
-
import type { StoredChunk } from './storage.js';
|
|
3
|
-
import { Storage } from './storage.js';
|
|
4
|
-
/**
|
|
5
|
-
* Write-Ahead Log (WAL) — real-time memory capture during conversations.
|
|
6
|
-
*
|
|
7
|
-
* The WAL principle: write state BEFORE responding, not after.
|
|
8
|
-
* This ensures no memory is lost if the agent crashes, compacts, or restarts.
|
|
9
|
-
*
|
|
10
|
-
* Use `ingest` for immediate capture of facts/decisions/preferences
|
|
11
|
-
* as they happen, rather than waiting for post-conversation extraction.
|
|
12
|
-
*/
|
|
13
|
-
export interface IngestEntry {
|
|
14
|
-
content: string;
|
|
15
|
-
type?: MemoryType;
|
|
16
|
-
layer?: CognitiveLayer;
|
|
17
|
-
importance?: number;
|
|
18
|
-
tags?: string[];
|
|
19
|
-
source?: string;
|
|
20
|
-
domain?: string;
|
|
21
|
-
topic?: string;
|
|
22
|
-
sentiment?: Sentiment;
|
|
23
|
-
emotionalValence?: number;
|
|
24
|
-
emotionalArousal?: number;
|
|
25
|
-
origin?: MemoryOrigin;
|
|
26
|
-
tier?: MemoryTier;
|
|
27
|
-
/**
|
|
28
|
-
* ISO 8601 timestamp override. Default: ingest time (Date.now()).
|
|
29
|
-
*
|
|
30
|
-
* Critical when the content represents an event that originally
|
|
31
|
-
* happened at a different time — meeting notes from yesterday,
|
|
32
|
-
* dated documents, imported chat history, benchmark fixtures.
|
|
33
|
-
*
|
|
34
|
-
* The createdAt timestamp flows into `buildContextPrefix()` which
|
|
35
|
-
* is included in the embedded text. The retrieval pipeline uses
|
|
36
|
-
* this as a temporal signal — both via similarity match against
|
|
37
|
-
* the prefix in queries, and via downstream temporal-boost logic
|
|
38
|
-
* in `search.ts`.
|
|
39
|
-
*
|
|
40
|
-
* Without an override, every ingested memory shares the ingest-
|
|
41
|
-
* time prefix (which is the same for everything ingested in the
|
|
42
|
-
* same hour), losing all temporal differentiation.
|
|
43
|
-
*/
|
|
44
|
-
createdAt?: string;
|
|
45
|
-
/**
|
|
46
|
-
* When true, skip the per-chunk KG triple extraction. The standalone
|
|
47
|
-
* locomo bench bypasses this (calls saveChunk directly, never enters
|
|
48
|
-
* wal.ts), which is why its wall-clock is ~50× faster than Pyre's
|
|
49
|
-
* MCP-boundary bench on the same dataset.
|
|
50
|
-
*
|
|
51
|
-
* Real users keep KG extraction (it powers
|
|
52
|
-
*
|
|
53
|
-
* apples-to-apples vs the standalone bench should pass this flag
|
|
54
|
-
* so they're measuring the same code path.
|
|
55
|
-
*/
|
|
56
|
-
skipKgExtraction?: boolean;
|
|
57
|
-
/**
|
|
58
|
-
* When true, skip the post-batch appendDailyEntry write. Same
|
|
59
|
-
* rationale as skipKgExtraction — the standalone bench doesn't
|
|
60
|
-
* touch the daily-entries store; bench harnesses matching it
|
|
61
|
-
* should skip the write to compare on equal footing.
|
|
62
|
-
*/
|
|
63
|
-
skipDailyEntry?: boolean;
|
|
64
|
-
/**
|
|
65
|
-
* When false, KG extraction + daily-entry append run in the
|
|
66
|
-
* BACKGROUND after ingest() returns. The caller gets its chunks
|
|
67
|
-
* back as soon as the saveChunk loop finishes; the side effects
|
|
68
|
-
* complete on their own pace.
|
|
69
|
-
*
|
|
70
|
-
* Default true (backwards compatible — caller awaits everything).
|
|
71
|
-
* Production callers where the agent doesn't immediately query
|
|
72
|
-
* the just-written content (chat WAL, tool-vault bridge) should
|
|
73
|
-
* pass false for ~5-30× faster perceived ingest latency.
|
|
74
|
-
*
|
|
75
|
-
* To wait for background work to drain (tests, shutdown), call
|
|
76
|
-
* `flushPendingSideEffects()` from this module.
|
|
77
|
-
*/
|
|
78
|
-
awaitSideEffects?: boolean;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Wait for all in-flight background side-effects (KG extraction +
|
|
82
|
-
* daily-entry append fired with `awaitSideEffects: false`) to
|
|
83
|
-
* complete. No-op when nothing is pending.
|
|
84
|
-
*
|
|
85
|
-
* Tests should call this between ingest and assert; shutdown code
|
|
86
|
-
* should call before process exit to avoid losing KG writes.
|
|
87
|
-
*/
|
|
88
|
-
export declare function flushPendingSideEffects(): Promise<void>;
|
|
89
|
-
/** Pending count — for tests + telemetry. */
|
|
90
|
-
export declare function pendingSideEffectCount(): number;
|
|
91
|
-
/**
|
|
92
|
-
* Immediately persist one or more memory entries.
|
|
93
|
-
* Designed to be called mid-conversation, before the agent responds.
|
|
94
|
-
*/
|
|
95
|
-
export declare function ingest(config: SmartMemoryConfig, storage: Storage, entries: IngestEntry[]): Promise<StoredChunk[]>;
|
|
1
|
+
import type { SmartMemoryConfig, MemoryType, CognitiveLayer, Sentiment, MemoryOrigin, MemoryTier } from './types.js';
|
|
2
|
+
import type { StoredChunk } from './storage.js';
|
|
3
|
+
import { Storage } from './storage.js';
|
|
4
|
+
/**
|
|
5
|
+
* Write-Ahead Log (WAL) — real-time memory capture during conversations.
|
|
6
|
+
*
|
|
7
|
+
* The WAL principle: write state BEFORE responding, not after.
|
|
8
|
+
* This ensures no memory is lost if the agent crashes, compacts, or restarts.
|
|
9
|
+
*
|
|
10
|
+
* Use `ingest` for immediate capture of facts/decisions/preferences
|
|
11
|
+
* as they happen, rather than waiting for post-conversation extraction.
|
|
12
|
+
*/
|
|
13
|
+
export interface IngestEntry {
|
|
14
|
+
content: string;
|
|
15
|
+
type?: MemoryType;
|
|
16
|
+
layer?: CognitiveLayer;
|
|
17
|
+
importance?: number;
|
|
18
|
+
tags?: string[];
|
|
19
|
+
source?: string;
|
|
20
|
+
domain?: string;
|
|
21
|
+
topic?: string;
|
|
22
|
+
sentiment?: Sentiment;
|
|
23
|
+
emotionalValence?: number;
|
|
24
|
+
emotionalArousal?: number;
|
|
25
|
+
origin?: MemoryOrigin;
|
|
26
|
+
tier?: MemoryTier;
|
|
27
|
+
/**
|
|
28
|
+
* ISO 8601 timestamp override. Default: ingest time (Date.now()).
|
|
29
|
+
*
|
|
30
|
+
* Critical when the content represents an event that originally
|
|
31
|
+
* happened at a different time — meeting notes from yesterday,
|
|
32
|
+
* dated documents, imported chat history, benchmark fixtures.
|
|
33
|
+
*
|
|
34
|
+
* The createdAt timestamp flows into `buildContextPrefix()` which
|
|
35
|
+
* is included in the embedded text. The retrieval pipeline uses
|
|
36
|
+
* this as a temporal signal — both via similarity match against
|
|
37
|
+
* the prefix in queries, and via downstream temporal-boost logic
|
|
38
|
+
* in `search.ts`.
|
|
39
|
+
*
|
|
40
|
+
* Without an override, every ingested memory shares the ingest-
|
|
41
|
+
* time prefix (which is the same for everything ingested in the
|
|
42
|
+
* same hour), losing all temporal differentiation.
|
|
43
|
+
*/
|
|
44
|
+
createdAt?: string;
|
|
45
|
+
/**
|
|
46
|
+
* When true, skip the per-chunk KG triple extraction. The standalone
|
|
47
|
+
* locomo bench bypasses this (calls saveChunk directly, never enters
|
|
48
|
+
* wal.ts), which is why its wall-clock is ~50× faster than Pyre's
|
|
49
|
+
* MCP-boundary bench on the same dataset.
|
|
50
|
+
*
|
|
51
|
+
* Real users keep KG extraction (it powers engram-dossier,
|
|
52
|
+
* engram-kg-query, graph rerank). Benchmark harnesses comparing
|
|
53
|
+
* apples-to-apples vs the standalone bench should pass this flag
|
|
54
|
+
* so they're measuring the same code path.
|
|
55
|
+
*/
|
|
56
|
+
skipKgExtraction?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* When true, skip the post-batch appendDailyEntry write. Same
|
|
59
|
+
* rationale as skipKgExtraction — the standalone bench doesn't
|
|
60
|
+
* touch the daily-entries store; bench harnesses matching it
|
|
61
|
+
* should skip the write to compare on equal footing.
|
|
62
|
+
*/
|
|
63
|
+
skipDailyEntry?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* When false, KG extraction + daily-entry append run in the
|
|
66
|
+
* BACKGROUND after ingest() returns. The caller gets its chunks
|
|
67
|
+
* back as soon as the saveChunk loop finishes; the side effects
|
|
68
|
+
* complete on their own pace.
|
|
69
|
+
*
|
|
70
|
+
* Default true (backwards compatible — caller awaits everything).
|
|
71
|
+
* Production callers where the agent doesn't immediately query
|
|
72
|
+
* the just-written content (chat WAL, tool-vault bridge) should
|
|
73
|
+
* pass false for ~5-30× faster perceived ingest latency.
|
|
74
|
+
*
|
|
75
|
+
* To wait for background work to drain (tests, shutdown), call
|
|
76
|
+
* `flushPendingSideEffects()` from this module.
|
|
77
|
+
*/
|
|
78
|
+
awaitSideEffects?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Wait for all in-flight background side-effects (KG extraction +
|
|
82
|
+
* daily-entry append fired with `awaitSideEffects: false`) to
|
|
83
|
+
* complete. No-op when nothing is pending.
|
|
84
|
+
*
|
|
85
|
+
* Tests should call this between ingest and assert; shutdown code
|
|
86
|
+
* should call before process exit to avoid losing KG writes.
|
|
87
|
+
*/
|
|
88
|
+
export declare function flushPendingSideEffects(): Promise<void>;
|
|
89
|
+
/** Pending count — for tests + telemetry. */
|
|
90
|
+
export declare function pendingSideEffectCount(): number;
|
|
91
|
+
/**
|
|
92
|
+
* Immediately persist one or more memory entries.
|
|
93
|
+
* Designed to be called mid-conversation, before the agent responds.
|
|
94
|
+
*/
|
|
95
|
+
export declare function ingest(config: SmartMemoryConfig, storage: Storage, entries: IngestEntry[]): Promise<StoredChunk[]>;
|