@mono-agent/memory-supermemory 0.6.1 → 0.8.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 +40 -5
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -1
- package/dist/store.d.ts +19 -6
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +136 -13
- package/dist/store.js.map +1 -1
- package/package.json +10 -3
- package/scripts/smoke.mjs +41 -0
- package/skills/mono-agent-supermemory/SKILL.md +58 -0
package/README.md
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
Category: `context`
|
|
6
6
|
|
|
7
|
+
Plugin tier: this package is released in the mono-agent lockstep, but is not
|
|
8
|
+
installed with `@mono-agent/agent-app`; the operator installs and selects it explicitly.
|
|
9
|
+
|
|
7
10
|
## Responsibility
|
|
8
11
|
|
|
9
12
|
Provides a `MemoryStore` (from `@mono-agent/agent-contracts`) backed by an external
|
|
@@ -16,9 +19,16 @@ embeddings model and no memory chat LLM — the adapter just posts turns and sea
|
|
|
16
19
|
## Install / Usage
|
|
17
20
|
|
|
18
21
|
```bash
|
|
19
|
-
|
|
22
|
+
npm install @mono-agent/memory-supermemory@<matching-mono-agent-version>
|
|
20
23
|
```
|
|
21
24
|
|
|
25
|
+
The package also ships `skills/mono-agent-supermemory/SKILL.md`, which guides a
|
|
26
|
+
local configuration agent through service selection, privacy disclosure,
|
|
27
|
+
validation, and a real recall smoke test. Installing the package never enables
|
|
28
|
+
the backend by itself; `memory.backend: "supermemory"` remains the explicit opt-in.
|
|
29
|
+
There is deliberately no separate plugin-preset loader: an installed plugin is
|
|
30
|
+
offered by the normal wizard, while the skill owns later configuration changes.
|
|
31
|
+
|
|
22
32
|
```ts
|
|
23
33
|
import { createSupermemoryStore } from "@mono-agent/memory-supermemory";
|
|
24
34
|
|
|
@@ -29,19 +39,38 @@ const store = createSupermemoryStore({
|
|
|
29
39
|
maxBytes: 64_000,
|
|
30
40
|
});
|
|
31
41
|
|
|
32
|
-
await store.
|
|
42
|
+
await store.persistCompletedTurn({
|
|
43
|
+
runId: "run-018f...",
|
|
44
|
+
conversationId: "conv-1",
|
|
45
|
+
summary: "User prefers dark mode.",
|
|
46
|
+
captureText: "User: Use dark mode.\nAssistant: Done.",
|
|
47
|
+
});
|
|
33
48
|
const block = await store.load("conv-1", "preferences");
|
|
34
49
|
```
|
|
35
50
|
|
|
36
51
|
- `load(query)` → `POST /v4/search` (cached `/v3` fallback), formats ranked hits into a
|
|
37
52
|
markdown block capped at `maxBytes`. Degrades to `undefined` on any error.
|
|
38
|
-
- `
|
|
39
|
-
|
|
53
|
+
- `persistCompletedTurn` → one awaited `POST /v3/documents` containing the deterministic
|
|
54
|
+
summary and optional full capture text. A SHA-256-derived custom id keyed only by `runId`
|
|
55
|
+
keeps remote retries on one logical upsert. During one store lifetime an exact retry returns
|
|
56
|
+
as a duplicate without another request, while conflicting reuse of a run id fails before a
|
|
57
|
+
request. That exact lifetime check retains only two SHA-256 digests per distinct run—never raw
|
|
58
|
+
run ids, conversation ids, or turn content. After a process restart the remote API does not
|
|
59
|
+
expose enough conditional/read state
|
|
60
|
+
to distinguish a new document from a retry. Success returns the stable custom id after remote
|
|
61
|
+
admission, while any failure emits a constant content-free warning and is thrown so the harness
|
|
62
|
+
can report degradation. Raw run and
|
|
63
|
+
conversation ids are not placed in remote metadata. Documents over 1,000,000 bytes are
|
|
64
|
+
rejected rather than partially captured.
|
|
65
|
+
- Legacy `appendHostSummary` / `scheduleCapture` remain compatible best-effort writes (one-liner /
|
|
66
|
+
full turn, async server-side extraction) and never throw. The harness does not call them when
|
|
67
|
+
the strong method is present.
|
|
40
68
|
- `recall(query)` → hits shaped for the in-app `MemoryRecall` MCP tool.
|
|
41
69
|
|
|
42
70
|
## Public API
|
|
43
71
|
|
|
44
72
|
- `createSupermemoryStore`, `SupermemoryMemoryStore`
|
|
73
|
+
- `validateSupermemoryConfig`, `SupermemoryConfigValidation`
|
|
45
74
|
- `createSupermemoryHttpClient`
|
|
46
75
|
- `formatHitsAsBlock`, `SUPERMEMORY_SOURCE`
|
|
47
76
|
- `CreateSupermemoryStoreConfig`, `SupermemoryStoreOptions`, `SupermemoryRecallHit`
|
|
@@ -71,4 +100,10 @@ pnpm --filter @mono-agent/memory-supermemory run test
|
|
|
71
100
|
```
|
|
72
101
|
|
|
73
102
|
A gated real-instance round-trip runs when `MONO_AGENT_TEST_SUPERMEMORY_BASE_URL` points
|
|
74
|
-
at a running Supermemory instance (skipped otherwise).
|
|
103
|
+
at a running Supermemory instance (skipped otherwise). To require and run the
|
|
104
|
+
package-owned, data-writing smoke explicitly:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
MONO_AGENT_TEST_SUPERMEMORY_BASE_URL=http://127.0.0.1:6767 \
|
|
108
|
+
pnpm --filter @mono-agent/memory-supermemory run smoke
|
|
109
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,16 @@ export interface CreateSupermemoryStoreConfig {
|
|
|
21
21
|
warn(message: string): void;
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
export interface SupermemoryConfigValidation {
|
|
25
|
+
readonly valid: boolean;
|
|
26
|
+
readonly errors: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate plugin-owned service settings without making a network request.
|
|
30
|
+
* Connectivity remains the explicit live smoke because installation must not
|
|
31
|
+
* send agent data to an external service implicitly.
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateSupermemoryConfig(config: CreateSupermemoryStoreConfig): SupermemoryConfigValidation;
|
|
24
34
|
/** Build a {@link SupermemoryMemoryStore} over the REST client. The single entry point hosts use. */
|
|
25
35
|
export declare function createSupermemoryStore(config: CreateSupermemoryStoreConfig): SupermemoryMemoryStore;
|
|
26
36
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,EACd,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEhF,wFAAwF;AACxF,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAC5C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACnD;AAED,qGAAqG;AACrG,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,4BAA4B,GAAG,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,EACd,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEhF,wFAAwF;AACxF,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAC5C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,4BAA4B,GACnC,2BAA2B,CA6B7B;AAED,qGAAqG;AACrG,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,4BAA4B,GAAG,sBAAsB,CAoBnG"}
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,46 @@ import { SupermemoryMemoryStore } from "./store.js";
|
|
|
3
3
|
export { createSupermemoryHttpClient } from "./client.js";
|
|
4
4
|
export { formatHitsAsBlock, SUPERMEMORY_SOURCE } from "./format.js";
|
|
5
5
|
export { SupermemoryMemoryStore } from "./store.js";
|
|
6
|
+
/**
|
|
7
|
+
* Validate plugin-owned service settings without making a network request.
|
|
8
|
+
* Connectivity remains the explicit live smoke because installation must not
|
|
9
|
+
* send agent data to an external service implicitly.
|
|
10
|
+
*/
|
|
11
|
+
export function validateSupermemoryConfig(config) {
|
|
12
|
+
const errors = [];
|
|
13
|
+
try {
|
|
14
|
+
const url = new URL(config.baseUrl);
|
|
15
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
16
|
+
errors.push("baseUrl must use http or https.");
|
|
17
|
+
}
|
|
18
|
+
if (url.username.length > 0 || url.password.length > 0) {
|
|
19
|
+
errors.push("baseUrl must not contain credentials; use apiKey instead.");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
errors.push("baseUrl must be a valid absolute URL.");
|
|
24
|
+
}
|
|
25
|
+
if (config.container.trim().length === 0) {
|
|
26
|
+
errors.push("container must not be empty.");
|
|
27
|
+
}
|
|
28
|
+
if (config.apiKey !== undefined && config.apiKey.trim().length === 0) {
|
|
29
|
+
errors.push("apiKey must be omitted rather than set to an empty value.");
|
|
30
|
+
}
|
|
31
|
+
positiveNumberError(errors, "timeoutMs", config.timeoutMs);
|
|
32
|
+
positiveNumberError(errors, "maxBytes", config.maxBytes);
|
|
33
|
+
positiveIntegerError(errors, "searchLimit", config.searchLimit);
|
|
34
|
+
if (config.threshold !== undefined
|
|
35
|
+
&& (!Number.isFinite(config.threshold) || config.threshold < 0 || config.threshold > 1)) {
|
|
36
|
+
errors.push("threshold must be between 0 and 1.");
|
|
37
|
+
}
|
|
38
|
+
return { valid: errors.length === 0, errors };
|
|
39
|
+
}
|
|
6
40
|
/** Build a {@link SupermemoryMemoryStore} over the REST client. The single entry point hosts use. */
|
|
7
41
|
export function createSupermemoryStore(config) {
|
|
42
|
+
const validation = validateSupermemoryConfig(config);
|
|
43
|
+
if (!validation.valid) {
|
|
44
|
+
throw new Error(`Invalid Supermemory configuration: ${validation.errors.join(" ")}`);
|
|
45
|
+
}
|
|
8
46
|
const client = createSupermemoryHttpClient({
|
|
9
47
|
baseUrl: config.baseUrl,
|
|
10
48
|
containerTag: config.container,
|
|
@@ -21,4 +59,14 @@ export function createSupermemoryStore(config) {
|
|
|
21
59
|
...(config.logger === undefined ? {} : { logger: config.logger }),
|
|
22
60
|
});
|
|
23
61
|
}
|
|
62
|
+
function positiveNumberError(errors, field, value) {
|
|
63
|
+
if (value !== undefined && (!Number.isFinite(value) || value <= 0)) {
|
|
64
|
+
errors.push(`${field} must be greater than zero.`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function positiveIntegerError(errors, field, value) {
|
|
68
|
+
if (value !== undefined && (!Number.isInteger(value) || value <= 0)) {
|
|
69
|
+
errors.push(`${field} must be a positive integer.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
24
72
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAY1D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MemoryBlock, MemoryStore, MemoryWriteResult } from "@mono-agent/agent-contracts";
|
|
1
|
+
import type { MemoryBlock, MemoryCompletedTurn, MemoryCompletedTurnResult, MemoryStore, MemoryWriteResult } from "@mono-agent/agent-contracts";
|
|
2
2
|
import type { SupermemoryClient } from "./client.js";
|
|
3
3
|
export interface SupermemoryStoreOptions {
|
|
4
4
|
/** Hard cap on the bytes a single `load` may return. */
|
|
@@ -20,11 +20,13 @@ export interface SupermemoryRecallHit {
|
|
|
20
20
|
/**
|
|
21
21
|
* MemoryStore backed by an external Supermemory instance (local OSS binary or hosted cloud).
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
23
|
+
* The strong `persistCompletedTurn` path awaits one run-keyed remote upsert, coalesces exact
|
|
24
|
+
* same-process retries, rejects same-process payload conflicts, and propagates failure so the
|
|
25
|
+
* harness can report degradation without changing the provider answer. Legacy
|
|
26
|
+
* writes remain best-effort and NEVER throw: `appendHostSummary` returns `bytesWritten: 0` on
|
|
27
|
+
* failure; `scheduleCapture` is fire-and-forget, serialized through a single chain so captures
|
|
28
|
+
* cannot overlap or reject the chain. Supermemory does extraction/consolidation server-side, so
|
|
29
|
+
* ingestion is async and a just-admitted turn may not be immediately searchable.
|
|
28
30
|
*
|
|
29
31
|
* `load` degrades to `undefined` on any client error (mirroring how the harness treats empty recall),
|
|
30
32
|
* so a slow/down backend yields no context rather than a failed turn.
|
|
@@ -32,12 +34,23 @@ export interface SupermemoryRecallHit {
|
|
|
32
34
|
export declare class SupermemoryMemoryStore implements MemoryStore {
|
|
33
35
|
private readonly client;
|
|
34
36
|
private captureChain;
|
|
37
|
+
/** Exact lifetime idempotency with no retained run/conversation/content. */
|
|
38
|
+
private readonly completedTurns;
|
|
39
|
+
private readonly completedTurnInflight;
|
|
35
40
|
private readonly maxBytes;
|
|
36
41
|
private readonly recallLimit;
|
|
37
42
|
private readonly logger;
|
|
38
43
|
constructor(client: SupermemoryClient, options?: SupermemoryStoreOptions);
|
|
39
44
|
load(conversationId: string, query?: string): Promise<MemoryBlock | undefined>;
|
|
40
45
|
appendHostSummary(conversationId: string, summary: string): Promise<MemoryWriteResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Strong, awaited completed-turn admission. The remote custom id is derived
|
|
48
|
+
* only from the stable run id, so a cross-process retry upserts the same
|
|
49
|
+
* logical document; local digests distinguish exact retry from conflict.
|
|
50
|
+
* Unlike the legacy write methods, any failure is logged and propagated for
|
|
51
|
+
* the harness to surface as memory degradation.
|
|
52
|
+
*/
|
|
53
|
+
persistCompletedTurn(turn: MemoryCompletedTurn): Promise<MemoryCompletedTurnResult>;
|
|
41
54
|
scheduleCapture(conversationId: string, text: string): void;
|
|
42
55
|
flush(): Promise<void>;
|
|
43
56
|
/** Drain queued captures (HTTP client owns no handle to close). */
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,yBAAyB,EACzB,WAAW,EACX,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYrD,MAAM,WAAW,uBAAuB;IACtC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACnD;AAED,mGAAmG;AACnG,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE;AAID;;;;;;;;;;;;;GAaG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IAatD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAZzB,OAAO,CAAC,YAAY,CAAoC;IACxD,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAGjC;IACL,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAGtC,MAAM,EAAE,iBAAiB,EAC1C,OAAO,GAAE,uBAA4B;IAOjC,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAc9E,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkB5F;;;;;;OAMG;IACG,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAoDzF,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAarD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,mEAAmE;IAC7D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;YAKpF,MAAM;CAIrB"}
|
package/dist/store.js
CHANGED
|
@@ -2,15 +2,23 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { formatHitsAsBlock, SUPERMEMORY_SOURCE } from "./format.js";
|
|
3
3
|
/** Default per-turn recall budget (bytes) — mirrors the host's DEFAULT_MEMORY_MAX_BYTES. */
|
|
4
4
|
const DEFAULT_MAX_BYTES = 64_000;
|
|
5
|
+
/** Refuse oversized remote writes instead of silently dropping part of a completed turn. */
|
|
6
|
+
const MAX_COMPLETED_TURN_BYTES = 1_000_000;
|
|
7
|
+
const RECALL_WARNING = "supermemory recall failed; continuing without remote memory.";
|
|
8
|
+
const SUMMARY_WARNING = "supermemory appendHostSummary failed; the turn continues.";
|
|
9
|
+
const COMPLETED_TURN_WARNING = "supermemory persistCompletedTurn failed; the provider response remains valid.";
|
|
10
|
+
const CAPTURE_WARNING = "supermemory capture failed; the queued turn continues.";
|
|
5
11
|
const NOOP_LOGGER = { warn: (_message) => { } };
|
|
6
12
|
/**
|
|
7
13
|
* MemoryStore backed by an external Supermemory instance (local OSS binary or hosted cloud).
|
|
8
14
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
15
|
+
* The strong `persistCompletedTurn` path awaits one run-keyed remote upsert, coalesces exact
|
|
16
|
+
* same-process retries, rejects same-process payload conflicts, and propagates failure so the
|
|
17
|
+
* harness can report degradation without changing the provider answer. Legacy
|
|
18
|
+
* writes remain best-effort and NEVER throw: `appendHostSummary` returns `bytesWritten: 0` on
|
|
19
|
+
* failure; `scheduleCapture` is fire-and-forget, serialized through a single chain so captures
|
|
20
|
+
* cannot overlap or reject the chain. Supermemory does extraction/consolidation server-side, so
|
|
21
|
+
* ingestion is async and a just-admitted turn may not be immediately searchable.
|
|
14
22
|
*
|
|
15
23
|
* `load` degrades to `undefined` on any client error (mirroring how the harness treats empty recall),
|
|
16
24
|
* so a slow/down backend yields no context rather than a failed turn.
|
|
@@ -18,6 +26,9 @@ const NOOP_LOGGER = { warn: (_message) => { } };
|
|
|
18
26
|
export class SupermemoryMemoryStore {
|
|
19
27
|
client;
|
|
20
28
|
captureChain = Promise.resolve();
|
|
29
|
+
/** Exact lifetime idempotency with no retained run/conversation/content. */
|
|
30
|
+
completedTurns = new Map();
|
|
31
|
+
completedTurnInflight = new Map();
|
|
21
32
|
maxBytes;
|
|
22
33
|
recallLimit;
|
|
23
34
|
logger;
|
|
@@ -36,8 +47,8 @@ export class SupermemoryMemoryStore {
|
|
|
36
47
|
}
|
|
37
48
|
return formatHitsAsBlock(hits, this.maxBytes);
|
|
38
49
|
}
|
|
39
|
-
catch
|
|
40
|
-
this.logger
|
|
50
|
+
catch {
|
|
51
|
+
safeWarn(this.logger, RECALL_WARNING);
|
|
41
52
|
return undefined;
|
|
42
53
|
}
|
|
43
54
|
}
|
|
@@ -54,19 +65,78 @@ export class SupermemoryMemoryStore {
|
|
|
54
65
|
});
|
|
55
66
|
return { conversationId, source: SUPERMEMORY_SOURCE, bytesWritten: bytes };
|
|
56
67
|
}
|
|
57
|
-
catch
|
|
58
|
-
this.logger
|
|
68
|
+
catch {
|
|
69
|
+
safeWarn(this.logger, SUMMARY_WARNING);
|
|
59
70
|
return { conversationId, source: SUPERMEMORY_SOURCE, bytesWritten: 0 };
|
|
60
71
|
}
|
|
61
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Strong, awaited completed-turn admission. The remote custom id is derived
|
|
75
|
+
* only from the stable run id, so a cross-process retry upserts the same
|
|
76
|
+
* logical document; local digests distinguish exact retry from conflict.
|
|
77
|
+
* Unlike the legacy write methods, any failure is logged and propagated for
|
|
78
|
+
* the harness to surface as memory degradation.
|
|
79
|
+
*/
|
|
80
|
+
async persistCompletedTurn(turn) {
|
|
81
|
+
try {
|
|
82
|
+
assertCompletedTurn(turn);
|
|
83
|
+
const content = completedTurnDocument(turn);
|
|
84
|
+
const bytesWritten = Buffer.byteLength(content, "utf8");
|
|
85
|
+
if (bytesWritten > MAX_COMPLETED_TURN_BYTES) {
|
|
86
|
+
throw new Error(`completed turn exceeds the ${MAX_COMPLETED_TURN_BYTES}-byte Supermemory admission limit`);
|
|
87
|
+
}
|
|
88
|
+
const runIdHash = safeHash(turn.runId);
|
|
89
|
+
const customId = `completed-turn-${runIdHash.slice(0, 32)}`;
|
|
90
|
+
const payloadDigest = completedTurnDigest(turn);
|
|
91
|
+
const completed = this.completedTurns.get(runIdHash);
|
|
92
|
+
if (completed !== undefined) {
|
|
93
|
+
assertMatchingCompletedTurn(completed, payloadDigest);
|
|
94
|
+
return completedTurnResult(turn, customId, 0, "duplicate");
|
|
95
|
+
}
|
|
96
|
+
const inflight = this.completedTurnInflight.get(runIdHash);
|
|
97
|
+
if (inflight !== undefined) {
|
|
98
|
+
assertMatchingCompletedTurn(inflight.payloadDigest, payloadDigest);
|
|
99
|
+
await inflight.promise;
|
|
100
|
+
return completedTurnResult(turn, customId, 0, "duplicate");
|
|
101
|
+
}
|
|
102
|
+
const result = completedTurnResult(turn, customId, bytesWritten, "admitted");
|
|
103
|
+
const promise = (async () => {
|
|
104
|
+
await this.client.add({
|
|
105
|
+
content,
|
|
106
|
+
customId,
|
|
107
|
+
// Keep remote indexing metadata flat and free of raw channel/run ids.
|
|
108
|
+
metadata: {
|
|
109
|
+
kind: "completed-turn",
|
|
110
|
+
schemaVersion: 1,
|
|
111
|
+
hasCapture: turn.captureText !== undefined,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
this.completedTurns.set(runIdHash, payloadDigest);
|
|
115
|
+
return result;
|
|
116
|
+
})();
|
|
117
|
+
this.completedTurnInflight.set(runIdHash, { payloadDigest, promise });
|
|
118
|
+
try {
|
|
119
|
+
return await promise;
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
if (this.completedTurnInflight.get(runIdHash)?.promise === promise) {
|
|
123
|
+
this.completedTurnInflight.delete(runIdHash);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
safeWarn(this.logger, COMPLETED_TURN_WARNING);
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
62
132
|
scheduleCapture(conversationId, text) {
|
|
63
133
|
this.captureChain = this.captureChain
|
|
64
134
|
.then(async () => {
|
|
65
135
|
try {
|
|
66
136
|
await this.client.add({ content: text, metadata: { kind: "turn-capture", conversationId } });
|
|
67
137
|
}
|
|
68
|
-
catch
|
|
69
|
-
this.logger
|
|
138
|
+
catch {
|
|
139
|
+
safeWarn(this.logger, CAPTURE_WARNING);
|
|
70
140
|
}
|
|
71
141
|
})
|
|
72
142
|
// Terminal guard: the chain must never settle rejected, or every future capture would be skipped.
|
|
@@ -95,7 +165,60 @@ export class SupermemoryMemoryStore {
|
|
|
95
165
|
function stableId(input) {
|
|
96
166
|
return createHash("sha1").update(input).digest("hex").slice(0, 24);
|
|
97
167
|
}
|
|
98
|
-
function
|
|
99
|
-
return
|
|
168
|
+
function safeHash(input) {
|
|
169
|
+
return createHash("sha256").update(input).digest("hex");
|
|
170
|
+
}
|
|
171
|
+
function completedTurnDigest(turn) {
|
|
172
|
+
return createHash("sha256").update(JSON.stringify({
|
|
173
|
+
conversationId: turn.conversationId,
|
|
174
|
+
summary: turn.summary,
|
|
175
|
+
...(turn.captureText === undefined ? {} : { captureText: turn.captureText }),
|
|
176
|
+
})).digest("hex");
|
|
177
|
+
}
|
|
178
|
+
function assertMatchingCompletedTurn(existing, incoming) {
|
|
179
|
+
if (existing !== incoming) {
|
|
180
|
+
throw new Error("supermemory: completed-turn run id conflicts with an already admitted payload");
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function completedTurnResult(turn, id, bytesWritten, admissionStatus) {
|
|
184
|
+
return {
|
|
185
|
+
id,
|
|
186
|
+
runId: turn.runId,
|
|
187
|
+
conversationId: turn.conversationId,
|
|
188
|
+
source: SUPERMEMORY_SOURCE,
|
|
189
|
+
bytesWritten,
|
|
190
|
+
// The documents endpoint exposes a successful upsert but cannot identify
|
|
191
|
+
// create versus cross-process retry; local exact retries use "duplicate".
|
|
192
|
+
admissionStatus,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function completedTurnDocument(turn) {
|
|
196
|
+
return [
|
|
197
|
+
"Completed turn summary:",
|
|
198
|
+
turn.summary,
|
|
199
|
+
...(turn.captureText === undefined
|
|
200
|
+
? []
|
|
201
|
+
: ["", "Completed turn capture:", turn.captureText]),
|
|
202
|
+
].join("\n");
|
|
203
|
+
}
|
|
204
|
+
function assertCompletedTurn(turn) {
|
|
205
|
+
for (const [field, value] of [
|
|
206
|
+
["runId", turn.runId],
|
|
207
|
+
["conversationId", turn.conversationId],
|
|
208
|
+
["summary", turn.summary],
|
|
209
|
+
]) {
|
|
210
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
211
|
+
throw new TypeError(`completed turn ${field} must be a non-empty string`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (turn.captureText !== undefined && typeof turn.captureText !== "string") {
|
|
215
|
+
throw new TypeError("completed turn captureText must be a string when provided");
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function safeWarn(logger, message) {
|
|
219
|
+
try {
|
|
220
|
+
logger.warn(message);
|
|
221
|
+
}
|
|
222
|
+
catch { /* Diagnostics cannot replace the backend result. */ }
|
|
100
223
|
}
|
|
101
224
|
//# sourceMappingURL=store.js.map
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mono-agent/memory-supermemory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Supermemory external memory backend: a MemoryStore over Supermemory's REST API (local OSS binary or hosted cloud).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"private": false,
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=22.19.0"
|
|
10
|
+
},
|
|
8
11
|
"main": "./dist/index.js",
|
|
9
12
|
"types": "./dist/index.d.ts",
|
|
10
13
|
"exports": {
|
|
11
14
|
".": {
|
|
12
15
|
"types": "./dist/index.d.ts",
|
|
13
16
|
"import": "./dist/index.js"
|
|
14
|
-
}
|
|
17
|
+
},
|
|
18
|
+
"./package.json": "./package.json"
|
|
15
19
|
},
|
|
16
20
|
"files": [
|
|
17
21
|
"dist",
|
|
22
|
+
"scripts",
|
|
23
|
+
"skills",
|
|
18
24
|
"README.md"
|
|
19
25
|
],
|
|
20
26
|
"dependencies": {
|
|
21
|
-
"@mono-agent/agent-contracts": "0.
|
|
27
|
+
"@mono-agent/agent-contracts": "0.8.0"
|
|
22
28
|
},
|
|
23
29
|
"publishConfig": {
|
|
24
30
|
"access": "public"
|
|
25
31
|
},
|
|
26
32
|
"scripts": {
|
|
27
33
|
"build": "tsc -p tsconfig.build.json",
|
|
34
|
+
"smoke": "node scripts/smoke.mjs",
|
|
28
35
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
29
36
|
"test": "vitest run --passWithNoTests"
|
|
30
37
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createSupermemoryStore } from "../dist/index.js";
|
|
4
|
+
|
|
5
|
+
const baseUrl = process.env.MONO_AGENT_TEST_SUPERMEMORY_BASE_URL;
|
|
6
|
+
if (baseUrl === undefined || baseUrl.trim().length === 0) {
|
|
7
|
+
console.error(
|
|
8
|
+
"Set MONO_AGENT_TEST_SUPERMEMORY_BASE_URL to the local or hosted Supermemory service to run this data-writing smoke test.",
|
|
9
|
+
);
|
|
10
|
+
process.exitCode = 2;
|
|
11
|
+
} else {
|
|
12
|
+
await smoke(baseUrl);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function smoke(serviceUrl) {
|
|
16
|
+
const marker = `mono-agent-plugin-smoke-${Date.now()}-${process.pid}`;
|
|
17
|
+
const store = createSupermemoryStore({
|
|
18
|
+
baseUrl: serviceUrl,
|
|
19
|
+
container: marker,
|
|
20
|
+
...(process.env.MONO_AGENT_TEST_SUPERMEMORY_API_KEY === undefined
|
|
21
|
+
? {}
|
|
22
|
+
: { apiKey: process.env.MONO_AGENT_TEST_SUPERMEMORY_API_KEY }),
|
|
23
|
+
});
|
|
24
|
+
try {
|
|
25
|
+
store.scheduleCapture("smoke", `The unique verification marker is ${marker}.`);
|
|
26
|
+
await store.flush();
|
|
27
|
+
|
|
28
|
+
const deadline = Date.now() + 60_000;
|
|
29
|
+
while (Date.now() < deadline) {
|
|
30
|
+
const hits = await store.recall(marker, { topK: 3 });
|
|
31
|
+
if (hits.some((hit) => hit.record.text.includes(marker))) {
|
|
32
|
+
console.log(`Supermemory plugin smoke passed for ${serviceUrl}.`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
await new Promise((resolve) => setTimeout(resolve, 2_000));
|
|
36
|
+
}
|
|
37
|
+
throw new Error("captured marker was not recallable within 60 seconds");
|
|
38
|
+
} finally {
|
|
39
|
+
await store.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mono-agent-supermemory
|
|
3
|
+
description: Configure an existing mono-agent to use the optional Supermemory memory plugin, with explicit service, privacy, credential, validation, and rollback checks.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configure Supermemory Memory
|
|
7
|
+
|
|
8
|
+
Use this skill only in an existing mono-agent folder whose operator explicitly
|
|
9
|
+
asked to install, enable, inspect, or remove the Supermemory plugin. Supermemory
|
|
10
|
+
is optional: never switch an agent from Lite, Journal, or BuJo implicitly.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
- Inspect `mono-agent.config.json`, `mono-agent config`, and `mono-agent validate`
|
|
15
|
+
for current state. Recalled memory is not evidence of current configuration.
|
|
16
|
+
- Ask whether data should stay on a local `supermemory-server` or be sent to the
|
|
17
|
+
hosted service. State that turns and recalled content leave mono-agent for the
|
|
18
|
+
selected service.
|
|
19
|
+
- Keep credentials out of chat, config, skill files, and traces. A hosted key is
|
|
20
|
+
collected by the host's masked secret flow as
|
|
21
|
+
`MONO_AGENT_MEMORY_SUPERMEMORY_API_KEY`; a keyless local service needs no key.
|
|
22
|
+
- Install the exact `@mono-agent/memory-supermemory` version matching
|
|
23
|
+
`@mono-agent/agent-app`. Do not use `latest` when versions differ.
|
|
24
|
+
- Propose the smallest config change and preserve the previous memory root. Do
|
|
25
|
+
not migrate or delete local memory automatically.
|
|
26
|
+
- Apply through the authenticated local configuration flow when available.
|
|
27
|
+
Otherwise show the patch and commands without claiming they ran.
|
|
28
|
+
|
|
29
|
+
## Config
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"memory": {
|
|
34
|
+
"backend": "supermemory",
|
|
35
|
+
"mode": "lite",
|
|
36
|
+
"path": "./.mono-agent/memory",
|
|
37
|
+
"writeMode": "capture",
|
|
38
|
+
"supermemory": {
|
|
39
|
+
"baseUrl": "http://127.0.0.1:6767"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The app derives the default container from the agent trace source. Set a
|
|
46
|
+
container only when the operator deliberately wants another namespace.
|
|
47
|
+
MemoryRecall is enabled by default for configured memory; an explicit false is
|
|
48
|
+
the opt-out.
|
|
49
|
+
|
|
50
|
+
## Verify
|
|
51
|
+
|
|
52
|
+
1. Confirm the exact plugin package resolves.
|
|
53
|
+
2. Run `mono-agent validate` and fix every memory error.
|
|
54
|
+
3. After the host reloads in a fresh turn, call MemoryRecall once. An empty
|
|
55
|
+
result is a valid registration smoke for an empty container.
|
|
56
|
+
4. Report the config change ID and rollback command. Never use a same-turn tool
|
|
57
|
+
call as proof of the newly applied backend because the active responder still
|
|
58
|
+
owns the prior store until reload.
|