@n24q02m/mnemo-plugin 1.0.1 → 1.2.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 +54 -27
- package/build/src/bridge.d.ts +12 -0
- package/build/src/bridge.d.ts.map +1 -1
- package/build/src/bridge.js +64 -5
- package/build/src/bridge.js.map +1 -1
- package/build/src/hooks/auto-capture.js +3 -0
- package/build/src/hooks/auto-capture.js.map +1 -1
- package/build/src/hooks/compaction.d.ts.map +1 -1
- package/build/src/hooks/compaction.js +3 -0
- package/build/src/hooks/compaction.js.map +1 -1
- package/build/src/hooks/system-prompt.d.ts.map +1 -1
- package/build/src/hooks/system-prompt.js +5 -2
- package/build/src/hooks/system-prompt.js.map +1 -1
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +6 -3
- package/build/src/index.js.map +1 -1
- package/build/tests/auto-capture.test.d.ts +8 -0
- package/build/tests/auto-capture.test.d.ts.map +1 -0
- package/build/tests/auto-capture.test.js +168 -0
- package/build/tests/auto-capture.test.js.map +1 -0
- package/build/tests/bridge.test.js +1 -1
- package/build/tests/bridge.test.js.map +1 -1
- package/build/tests/bridge.unit.test.d.ts +7 -0
- package/build/tests/bridge.unit.test.d.ts.map +1 -0
- package/build/tests/bridge.unit.test.js +271 -0
- package/build/tests/bridge.unit.test.js.map +1 -0
- package/build/tests/compaction.test.d.ts +5 -0
- package/build/tests/compaction.test.d.ts.map +1 -0
- package/build/tests/compaction.test.js +117 -0
- package/build/tests/compaction.test.js.map +1 -0
- package/build/tests/system-prompt.test.d.ts +5 -0
- package/build/tests/system-prompt.test.d.ts.map +1 -0
- package/build/tests/system-prompt.test.js +113 -0
- package/build/tests/system-prompt.test.js.map +1 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,21 +14,28 @@ Gives your AI coding assistant **persistent memory** across sessions. Facts, pre
|
|
|
14
14
|
- **Automatic Capture** -- Detects user preferences and constraints from chat (always/never/must/prefer patterns)
|
|
15
15
|
- **Adaptive Context Injection** -- Smart budget system scales memory injection to model context window
|
|
16
16
|
- **Project-Scoped** -- Memories auto-tagged with project name for relevant recall
|
|
17
|
-
- **Dual Platform** -- Works with both OpenCode
|
|
17
|
+
- **Dual Platform** -- Works with both OpenCode and Claude Code
|
|
18
18
|
|
|
19
19
|
## Architecture
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Full memory support requires **both** the plugin and the MCP server working together:
|
|
22
|
+
|
|
23
|
+
| Component | Role | Behavior |
|
|
24
|
+
|-----------|------|----------|
|
|
25
|
+
| **Plugin** (this package) | Proactive | Hooks: inject memories into system prompt, auto-capture constraints, preserve context on compaction |
|
|
26
|
+
| **MCP Server** ([mnemo-mcp](https://github.com/n24q02m/mnemo-mcp)) | Reactive | Tools: AI calls search/remember/forget when it decides to |
|
|
22
27
|
|
|
23
28
|
```
|
|
24
|
-
|
|
29
|
+
AI Coding Assistant
|
|
30
|
+
|
|
|
31
|
+
+-- mnemo-plugin (TypeScript) ........... hooks (proactive)
|
|
32
|
+
| |
|
|
33
|
+
| +-- bridge -> mnemo-mcp subprocess
|
|
25
34
|
|
|
|
26
|
-
+-- mnemo-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|-- Qwen3 embeddings (semantic search)
|
|
31
|
-
|-- rclone sync (backup)
|
|
35
|
+
+-- mnemo-mcp (Python, standalone) ..... tools (reactive)
|
|
36
|
+
|-- SQLite FTS5 (keyword search)
|
|
37
|
+
|-- Qwen3 embeddings (semantic search)
|
|
38
|
+
|-- rclone sync (backup)
|
|
32
39
|
```
|
|
33
40
|
|
|
34
41
|
## Prerequisites
|
|
@@ -38,43 +45,63 @@ OpenCode / Claude Code
|
|
|
38
45
|
|
|
39
46
|
## Installation
|
|
40
47
|
|
|
48
|
+
Both plugin **and** MCP server are required for full functionality.
|
|
49
|
+
|
|
41
50
|
### OpenCode
|
|
42
51
|
|
|
43
|
-
Add to your `opencode.json`:
|
|
52
|
+
Add **both** to your `opencode.json`:
|
|
44
53
|
|
|
45
54
|
```json
|
|
46
55
|
{
|
|
47
|
-
"plugin": ["@n24q02m/mnemo-plugin"]
|
|
56
|
+
"plugin": ["@n24q02m/mnemo-plugin@latest"],
|
|
57
|
+
"mcp": {
|
|
58
|
+
"mnemo": {
|
|
59
|
+
"type": "local",
|
|
60
|
+
"command": ["uvx", "--python", "3.13", "mnemo-mcp@latest"],
|
|
61
|
+
"environment": {
|
|
62
|
+
"LOG_LEVEL": "WARNING"
|
|
63
|
+
},
|
|
64
|
+
"enabled": true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
48
67
|
}
|
|
49
68
|
```
|
|
50
69
|
|
|
70
|
+
- **Plugin** provides hooks (system-prompt injection, auto-capture, compaction)
|
|
71
|
+
- **MCP server** provides tools (mnemo_memory_add, search, delete, etc.)
|
|
72
|
+
|
|
73
|
+
Restart OpenCode after configuration.
|
|
74
|
+
|
|
51
75
|
### Claude Code
|
|
52
76
|
|
|
53
|
-
|
|
77
|
+
The plugin bundles both MCP server and hooks in one install:
|
|
54
78
|
|
|
55
79
|
```
|
|
56
80
|
/plugin marketplace add n24q02m/mnemo-plugin
|
|
57
|
-
|
|
58
|
-
/plugin install mnemo-plugin
|
|
81
|
+
/plugin install mnemo-plugin@n24q02m
|
|
59
82
|
```
|
|
60
83
|
|
|
61
|
-
Restart Claude Code.
|
|
84
|
+
Restart Claude Code. The plugin automatically registers:
|
|
85
|
+
- MCP server (`uvx mnemo-mcp`) for memory tools
|
|
86
|
+
- SessionStart hook for health check
|
|
87
|
+
|
|
88
|
+
## Tools (via MCP server)
|
|
62
89
|
|
|
63
|
-
|
|
90
|
+
The MCP server provides three mega-tools. See [mnemo-mcp](https://github.com/n24q02m/mnemo-mcp) for full documentation.
|
|
64
91
|
|
|
65
|
-
| Tool | Description |
|
|
66
|
-
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
92
|
+
| Tool | Actions | Description |
|
|
93
|
+
|------|---------|-------------|
|
|
94
|
+
| `memory` | add, search, list, update, delete, export, import, stats | Persistent memory CRUD and management |
|
|
95
|
+
| `config` | status, sync, set | Server configuration and cloud sync |
|
|
96
|
+
| `help` | -- | Full documentation for all tools |
|
|
70
97
|
|
|
71
|
-
## Hooks (
|
|
98
|
+
## Hooks (via plugin)
|
|
72
99
|
|
|
73
|
-
| Hook | Description |
|
|
74
|
-
|
|
75
|
-
| `system-prompt` | Injects relevant memories into system prompt with adaptive budget |
|
|
76
|
-
| `auto-capture` | Buffers chat messages and extracts constraints
|
|
77
|
-
| `compaction` | Preserves memory context during session compaction |
|
|
100
|
+
| Hook | Trigger | Description |
|
|
101
|
+
|------|---------|-------------|
|
|
102
|
+
| `system-prompt` | Session start | Injects relevant memories into system prompt with adaptive budget |
|
|
103
|
+
| `auto-capture` | Session idle | Buffers chat messages and extracts constraints automatically |
|
|
104
|
+
| `compaction` | Context compaction | Preserves memory context during session compaction |
|
|
78
105
|
|
|
79
106
|
## Development
|
|
80
107
|
|
package/build/src/bridge.d.ts
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* Singleton class that manages a persistent MCP connection to the mnemo-mcp
|
|
5
5
|
* Python server via stdio transport. Spawns `uvx mnemo-mcp` as a subprocess
|
|
6
6
|
* and communicates via JSON-RPC 2.0.
|
|
7
|
+
*
|
|
8
|
+
* Includes circuit breaker to prevent repeated connection attempts when
|
|
9
|
+
* mnemo-mcp is unavailable, and timeouts to prevent indefinite hangs.
|
|
7
10
|
*/
|
|
8
11
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
9
12
|
export declare class MnemoBridge {
|
|
@@ -12,8 +15,17 @@ export declare class MnemoBridge {
|
|
|
12
15
|
private transport;
|
|
13
16
|
private connecting;
|
|
14
17
|
private availableTools;
|
|
18
|
+
/** Circuit breaker state */
|
|
19
|
+
private failCount;
|
|
20
|
+
private lastFailTime;
|
|
15
21
|
private constructor();
|
|
16
22
|
static getInstance(): MnemoBridge;
|
|
23
|
+
/**
|
|
24
|
+
* Check if the bridge is likely available.
|
|
25
|
+
* Returns false when circuit breaker is open (too many recent failures).
|
|
26
|
+
* Hooks should check this before attempting calls to avoid log noise.
|
|
27
|
+
*/
|
|
28
|
+
isAvailable(): boolean;
|
|
17
29
|
/** Connect to mnemo-mcp server, reusing existing connection if available */
|
|
18
30
|
connect(): Promise<Client>;
|
|
19
31
|
private doConnect;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/bridge.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AA0ClE,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAa;IACpC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,cAAc,CAA2B;IAEjD,4BAA4B;IAC5B,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,YAAY,CAAI;IAExB,OAAO;WAEO,WAAW,IAAI,WAAW;IAOxC;;;;OAIG;IACI,WAAW,IAAI,OAAO;IAS7B,4EAA4E;IAC/D,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;YA8BzB,SAAS;IA+BvB;;;;OAIG;IACU,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAuChF,6DAA6D;IAChD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAQvC"}
|
package/build/src/bridge.js
CHANGED
|
@@ -4,16 +4,45 @@
|
|
|
4
4
|
* Singleton class that manages a persistent MCP connection to the mnemo-mcp
|
|
5
5
|
* Python server via stdio transport. Spawns `uvx mnemo-mcp` as a subprocess
|
|
6
6
|
* and communicates via JSON-RPC 2.0.
|
|
7
|
+
*
|
|
8
|
+
* Includes circuit breaker to prevent repeated connection attempts when
|
|
9
|
+
* mnemo-mcp is unavailable, and timeouts to prevent indefinite hangs.
|
|
7
10
|
*/
|
|
8
11
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
9
12
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
10
13
|
import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
14
|
+
/** Wrap a promise with a timeout. Rejects with TimeoutError if deadline exceeded. */
|
|
15
|
+
function withTimeout(promise, ms, label) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const timer = setTimeout(() => {
|
|
18
|
+
reject(new Error(`${label} timed out after ${ms}ms`));
|
|
19
|
+
}, ms);
|
|
20
|
+
promise.then((val) => {
|
|
21
|
+
clearTimeout(timer);
|
|
22
|
+
resolve(val);
|
|
23
|
+
}, (err) => {
|
|
24
|
+
clearTimeout(timer);
|
|
25
|
+
reject(err);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** Circuit breaker: stop retrying after repeated failures */
|
|
30
|
+
const MAX_FAILURES = 3;
|
|
31
|
+
/** Cooldown period before resetting circuit breaker (5 minutes) */
|
|
32
|
+
const COOLDOWN_MS = 300_000;
|
|
33
|
+
/** Timeout for MCP connection handshake (30 seconds) */
|
|
34
|
+
const CONNECT_TIMEOUT_MS = 30_000;
|
|
35
|
+
/** Timeout for individual tool calls (15 seconds) */
|
|
36
|
+
const CALL_TIMEOUT_MS = 15_000;
|
|
11
37
|
export class MnemoBridge {
|
|
12
38
|
constructor() {
|
|
13
39
|
this.client = null;
|
|
14
40
|
this.transport = null;
|
|
15
41
|
this.connecting = null;
|
|
16
42
|
this.availableTools = null;
|
|
43
|
+
/** Circuit breaker state */
|
|
44
|
+
this.failCount = 0;
|
|
45
|
+
this.lastFailTime = 0;
|
|
17
46
|
}
|
|
18
47
|
static getInstance() {
|
|
19
48
|
if (!MnemoBridge.instance) {
|
|
@@ -21,18 +50,47 @@ export class MnemoBridge {
|
|
|
21
50
|
}
|
|
22
51
|
return MnemoBridge.instance;
|
|
23
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if the bridge is likely available.
|
|
55
|
+
* Returns false when circuit breaker is open (too many recent failures).
|
|
56
|
+
* Hooks should check this before attempting calls to avoid log noise.
|
|
57
|
+
*/
|
|
58
|
+
isAvailable() {
|
|
59
|
+
if (this.client)
|
|
60
|
+
return true;
|
|
61
|
+
if (this.failCount < MAX_FAILURES)
|
|
62
|
+
return true;
|
|
63
|
+
// Circuit breaker open -- check if cooldown has elapsed
|
|
64
|
+
const elapsed = Date.now() - this.lastFailTime;
|
|
65
|
+
return elapsed >= COOLDOWN_MS;
|
|
66
|
+
}
|
|
24
67
|
/** Connect to mnemo-mcp server, reusing existing connection if available */
|
|
25
68
|
async connect() {
|
|
26
69
|
if (this.client)
|
|
27
70
|
return this.client;
|
|
71
|
+
// Circuit breaker: reject immediately if too many recent failures
|
|
72
|
+
if (this.failCount >= MAX_FAILURES) {
|
|
73
|
+
const elapsed = Date.now() - this.lastFailTime;
|
|
74
|
+
if (elapsed < COOLDOWN_MS) {
|
|
75
|
+
throw new Error('mnemo-mcp temporarily unavailable (circuit breaker open)');
|
|
76
|
+
}
|
|
77
|
+
// Cooldown elapsed -- reset and allow retry
|
|
78
|
+
this.failCount = 0;
|
|
79
|
+
}
|
|
28
80
|
// If already connecting, wait for that promise to resolve
|
|
29
81
|
if (this.connecting)
|
|
30
82
|
return this.connecting;
|
|
31
83
|
this.connecting = this.doConnect();
|
|
32
84
|
try {
|
|
33
85
|
const client = await this.connecting;
|
|
86
|
+
this.failCount = 0;
|
|
34
87
|
return client;
|
|
35
88
|
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
this.failCount++;
|
|
91
|
+
this.lastFailTime = Date.now();
|
|
92
|
+
throw e;
|
|
93
|
+
}
|
|
36
94
|
finally {
|
|
37
95
|
this.connecting = null;
|
|
38
96
|
}
|
|
@@ -44,7 +102,7 @@ export class MnemoBridge {
|
|
|
44
102
|
this.transport = new StdioClientTransport({
|
|
45
103
|
command: 'uvx',
|
|
46
104
|
args: ['mnemo-mcp'],
|
|
47
|
-
stderr: '
|
|
105
|
+
stderr: 'ignore', // Prevent stderr backpressure and log noise
|
|
48
106
|
env: { ...process.env, LOG_LEVEL: 'WARNING' }
|
|
49
107
|
});
|
|
50
108
|
this.client = new Client({
|
|
@@ -53,9 +111,10 @@ export class MnemoBridge {
|
|
|
53
111
|
}, {
|
|
54
112
|
capabilities: {}
|
|
55
113
|
});
|
|
56
|
-
|
|
114
|
+
// Connect with timeout to prevent indefinite hang during first-run model download
|
|
115
|
+
await withTimeout(this.client.connect(this.transport), CONNECT_TIMEOUT_MS, 'MCP connect');
|
|
57
116
|
// Cache available tool names on first connect
|
|
58
|
-
const toolsResult = await this.client.listTools();
|
|
117
|
+
const toolsResult = await withTimeout(this.client.listTools(), CALL_TIMEOUT_MS, 'listTools');
|
|
59
118
|
this.availableTools = new Set(toolsResult.tools.map((t) => t.name));
|
|
60
119
|
return this.client;
|
|
61
120
|
}
|
|
@@ -70,10 +129,10 @@ export class MnemoBridge {
|
|
|
70
129
|
if (this.availableTools && !this.availableTools.has(name)) {
|
|
71
130
|
throw new Error(`Tool "${name}" not found in mnemo-mcp server. Available: ${[...this.availableTools].join(', ')}`);
|
|
72
131
|
}
|
|
73
|
-
const result = await client.callTool({
|
|
132
|
+
const result = await withTimeout(client.callTool({
|
|
74
133
|
name,
|
|
75
134
|
arguments: args
|
|
76
|
-
}, CallToolResultSchema);
|
|
135
|
+
}, CallToolResultSchema), CALL_TIMEOUT_MS, `callTool(${name})`);
|
|
77
136
|
if (result.isError) {
|
|
78
137
|
const errorText = result.content.find((c) => c.type === 'text')?.text || 'Unknown mnemo-mcp error';
|
|
79
138
|
throw new Error(`mnemo-mcp error: ${errorText}`);
|
package/build/src/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/bridge.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,6 +62,9 @@ export const autoCaptureHook = async (input, directory) => {
|
|
|
62
62
|
async function processCapture(directory) {
|
|
63
63
|
try {
|
|
64
64
|
const bridge = MnemoBridge.getInstance();
|
|
65
|
+
// Skip if bridge is unavailable (circuit breaker open)
|
|
66
|
+
if (!bridge.isAvailable())
|
|
67
|
+
return;
|
|
65
68
|
const projectName = getProjectName(directory);
|
|
66
69
|
const content = sessionBuffer.join('\n');
|
|
67
70
|
sessionBuffer.length = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-capture.js","sourceRoot":"","sources":["../../../src/hooks/auto-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,kEAAkE;AAClE,MAAM,aAAa,GAAa,EAAE,CAAA;AAElC,kEAAkE;AAClE,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAA;AAExC,oDAAoD;AACpD,IAAI,eAAe,GAAG,CAAC,CAAA;AAEvB,8DAA8D;AAC9D,MAAM,cAAc,GAAG,MAAM,CAAA;AAE7B,uDAAuD;AACvD,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAE9B,sDAAsD;AACtD,MAAM,gBAAgB,GAAG,kFAAkF,CAAA;AAE3G,2CAA2C;AAC3C,SAAS,WAAW,CAAC,OAAe;IAClC,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAClC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;IACxC,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AAC1B,CAAC;AAED,+CAA+C;AAC/C,SAAS,cAAc,CAAC,SAAiB;IACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,SAAS,CAAA;AAC7C,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,MAAe,EAAE,MAAoD,EAAE,EAAE;IACzG,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC;SAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAc,CAAC;SAC5B,IAAI,CAAC,IAAI,CAAC;SACV,IAAI,EAAE,CAAA;IAET,IAAI,QAAQ,EAAE,CAAC;QACb,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC9B,CAAC;AACH,CAAC,CAAA;AAED,iDAAiD;AACjD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,KAAuB,EAAE,SAAiB,EAAE,EAAE;IAClF,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc;QAAE,OAAM;IAE/C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,IAAI,GAAG,GAAG,eAAe,IAAI,cAAc;QAAE,OAAM;IACnD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAEtC,MAAM,cAAc,CAAC,SAAS,CAAC,CAAA;IAC/B,eAAe,GAAG,GAAG,CAAA;AACvB,CAAC,CAAA;AAED,wEAAwE;AACxE,KAAK,UAAU,cAAc,CAAC,SAAiB;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"auto-capture.js","sourceRoot":"","sources":["../../../src/hooks/auto-capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/hooks/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,eAAO,MAAM,cAAc,GAAU,QAAQ;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/hooks/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,eAAO,MAAM,cAAc,GAAU,QAAQ;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,kBAqCjH,CAAA"}
|
|
@@ -9,6 +9,9 @@ import { MnemoBridge } from '../bridge.js';
|
|
|
9
9
|
export const compactionHook = async (_input, output) => {
|
|
10
10
|
try {
|
|
11
11
|
const bridge = MnemoBridge.getInstance();
|
|
12
|
+
// Skip if bridge is unavailable (circuit breaker open)
|
|
13
|
+
if (!bridge.isAvailable())
|
|
14
|
+
return;
|
|
12
15
|
// Fetch recent/important memories to preserve during compaction
|
|
13
16
|
const statsRes = await bridge.callTool('memory', {
|
|
14
17
|
action: 'stats'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/hooks/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ1C,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,MAA6B,EAAE,MAA8C,EAAE,EAAE;IACpH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;QAExC,gEAAgE;QAChE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAC/C,MAAM,EAAE,OAAO;SAChB,CAAC,CAAA;QAEF,MAAM,aAAa,GAAG,QAAQ,EAAE,cAAc,IAAI,CAAC,CAAA;QAEnD,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACtB,qDAAqD;YACrD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;gBAC9C,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,EAAE;aACV,CAAC,CAAA;YAEF,IAAI,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,QAAQ,GAAI,OAAO,CAAC,OAA0B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAE5G,MAAM,CAAC,OAAO,CAAC,IAAI,CACjB,2IAA2I,QAAQ,EAAE,CACtJ,CAAA;YACH,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,MAAM,CAAC,OAAO,CAAC,IAAI,CACjB,kOAAkO,CACnO,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,EAAE,CAAC,CAAA;IAC7D,CAAC;AACH,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/hooks/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ1C,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,MAA6B,EAAE,MAA8C,EAAE,EAAE;IACpH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;QAExC,uDAAuD;QACvD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;YAAE,OAAM;QAEjC,gEAAgE;QAChE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAC/C,MAAM,EAAE,OAAO;SAChB,CAAC,CAAA;QAEF,MAAM,aAAa,GAAG,QAAQ,EAAE,cAAc,IAAI,CAAC,CAAA;QAEnD,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACtB,qDAAqD;YACrD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;gBAC9C,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,EAAE;aACV,CAAC,CAAA;YAEF,IAAI,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,QAAQ,GAAI,OAAO,CAAC,OAA0B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAE5G,MAAM,CAAC,OAAO,CAAC,IAAI,CACjB,2IAA2I,QAAQ,EAAE,CACtJ,CAAA;YACH,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,MAAM,CAAC,OAAO,CAAC,IAAI,CACjB,kOAAkO,CACnO,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,EAAE,CAAC,CAAA;IAC7D,CAAC;AACH,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../../src/hooks/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AA+C7C,eAAO,MAAM,gBAAgB,GAC3B,OAAO;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,EAC3C,QAAQ;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAC5B,WAAW,MAAM,
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../../src/hooks/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AA+C7C,eAAO,MAAM,gBAAgB,GAC3B,OAAO;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,EAC3C,QAAQ;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAC5B,WAAW,MAAM,kBA+ClB,CAAA"}
|
|
@@ -40,10 +40,13 @@ function truncateToFit(text, budget) {
|
|
|
40
40
|
export const systemPromptHook = async (input, output, directory) => {
|
|
41
41
|
try {
|
|
42
42
|
const bridge = MnemoBridge.getInstance();
|
|
43
|
-
const projectName = getProjectName(directory);
|
|
44
|
-
const budget = computeBudget(input.model);
|
|
45
43
|
// Always inject self-awareness block (outside budget)
|
|
46
44
|
output.system.push(SELF_AWARENESS);
|
|
45
|
+
// Skip memory injection if bridge is unavailable (circuit breaker open)
|
|
46
|
+
if (!bridge.isAvailable())
|
|
47
|
+
return;
|
|
48
|
+
const projectName = getProjectName(directory);
|
|
49
|
+
const budget = computeBudget(input.model);
|
|
47
50
|
// Search memories relevant to current project
|
|
48
51
|
const searchRes = await bridge.callTool('memory', {
|
|
49
52
|
action: 'search',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../../src/hooks/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAU1C,uEAAuE;AACvE,MAAM,cAAc,GAAG,KAAK,CAAA;AAE5B,kCAAkC;AAClC,MAAM,UAAU,GAAG,GAAG,CAAA;AACtB,MAAM,UAAU,GAAG,IAAI,CAAA;AAEvB,sFAAsF;AACtF,MAAM,cAAc,GAAG;;;;mGAI4E,CAAA;AAEnG,+CAA+C;AAC/C,SAAS,cAAc,CAAC,SAAiB;IACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,SAAS,CAAA;AAC7C,CAAC;AAED,4DAA4D;AAC5D,SAAS,aAAa,CAAC,KAAY;IACjC,MAAM,YAAY,GAAG,KAAK,EAAE,KAAK,EAAE,OAAO,CAAA;IAC1C,IAAI,CAAC,YAAY,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,UAAU,CAAA;IAEzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,cAAc,GAAG,CAAC,CAAC,CAAA,CAAC,qBAAqB;IAClF,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,mDAAmD;AACnD,SAAS,aAAa,CAAC,IAAY,EAAE,MAAc;IACjD,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,IAAI,CAAA;IACtC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,CAAA;AAC1C,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,KAA2C,EAC3C,MAA4B,EAC5B,SAAiB,EACjB,EAAE;IACF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../../src/hooks/system-prompt.ts"],"names":[],"mappings":"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"}
|
package/build/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAOjD,QAAA,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAOjD,QAAA,MAAM,MAAM,EAAE,MAyCb,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/build/src/index.js
CHANGED
|
@@ -12,14 +12,17 @@ import { systemPromptHook } from './hooks/system-prompt.js';
|
|
|
12
12
|
import { mnemoForget, mnemoRemember, mnemoSearch } from './tools/memory.js';
|
|
13
13
|
const plugin = async (input) => {
|
|
14
14
|
const bridge = MnemoBridge.getInstance();
|
|
15
|
-
// Start bridge connection in background (non-blocking)
|
|
15
|
+
// Start bridge connection in background (non-blocking).
|
|
16
|
+
// If this fails, the circuit breaker in MnemoBridge will prevent repeated
|
|
17
|
+
// connection attempts from hooks, avoiding log noise.
|
|
16
18
|
setTimeout(async () => {
|
|
17
19
|
try {
|
|
18
20
|
await bridge.connect();
|
|
19
21
|
console.log(`[Mnemo] Connected to persistent memory for ${input.directory}`);
|
|
20
22
|
}
|
|
21
|
-
catch
|
|
22
|
-
|
|
23
|
+
catch {
|
|
24
|
+
// Silently handled -- circuit breaker will prevent further attempts.
|
|
25
|
+
// Hooks check bridge.isAvailable() before calling, so no cascading errors.
|
|
23
26
|
}
|
|
24
27
|
}, 100);
|
|
25
28
|
return {
|
package/build/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE3E,MAAM,MAAM,GAAW,KAAK,EAAE,KAAK,EAAE,EAAE;IACrC,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;IAExC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE3E,MAAM,MAAM,GAAW,KAAK,EAAE,KAAK,EAAE,EAAE;IACrC,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;IAExC,wDAAwD;IACxD,0EAA0E;IAC1E,sDAAsD;IACtD,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;YACtB,OAAO,CAAC,GAAG,CAAC,8CAA8C,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;QAC9E,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,2EAA2E;QAC7E,CAAC;IACH,CAAC,EAAE,GAAG,CAAC,CAAA;IAEP,OAAO;QACL,QAAQ;QACR,IAAI,EAAE;YACJ,YAAY,EAAE,WAAW;YACzB,cAAc,EAAE,aAAa;YAC7B,YAAY,EAAE,WAAW;SAC1B;QAED,QAAQ;QACR,oCAAoC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;YAClE,MAAM,gBAAgB,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;QAC9D,CAAC;QAED,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;YAC5C,MAAM,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;QACxC,CAAC;QAED,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YACxB,MAAM,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;QAClD,CAAC;QAED,iCAAiC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;YAC/D,MAAM,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;QAC3C,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED,eAAe,MAAM,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for auto-capture hooks — message buffering, constraint extraction, dedup.
|
|
3
|
+
*
|
|
4
|
+
* Each test gets a fresh module instance because auto-capture.ts has
|
|
5
|
+
* module-level mutable state (sessionBuffer, capturedHashes, lastCaptureTime).
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=auto-capture.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-capture.test.d.ts","sourceRoot":"","sources":["../../tests/auto-capture.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for auto-capture hooks — message buffering, constraint extraction, dedup.
|
|
3
|
+
*
|
|
4
|
+
* Each test gets a fresh module instance because auto-capture.ts has
|
|
5
|
+
* module-level mutable state (sessionBuffer, capturedHashes, lastCaptureTime).
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
8
|
+
/** Create fresh mock functions and module for each test */
|
|
9
|
+
async function freshModule() {
|
|
10
|
+
vi.resetModules();
|
|
11
|
+
const mockIsAvailable = vi.fn().mockReturnValue(true);
|
|
12
|
+
const mockCallTool = vi.fn().mockResolvedValue({ status: 'saved' });
|
|
13
|
+
vi.doMock('../src/bridge.js', () => ({
|
|
14
|
+
MnemoBridge: {
|
|
15
|
+
getInstance: () => ({
|
|
16
|
+
isAvailable: mockIsAvailable,
|
|
17
|
+
callTool: mockCallTool
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
const mod = await import('../src/hooks/auto-capture.js');
|
|
22
|
+
return { mod, mockIsAvailable, mockCallTool };
|
|
23
|
+
}
|
|
24
|
+
describe('auto-capture', () => {
|
|
25
|
+
describe('messageHook', () => {
|
|
26
|
+
it('buffers text parts from output', async () => {
|
|
27
|
+
const { mod } = await freshModule();
|
|
28
|
+
const output = {
|
|
29
|
+
parts: [
|
|
30
|
+
{ type: 'text', text: 'Hello world' },
|
|
31
|
+
{ type: 'image', data: 'abc' },
|
|
32
|
+
{ type: 'text', text: 'Always use TypeScript' }
|
|
33
|
+
]
|
|
34
|
+
};
|
|
35
|
+
await mod.messageHook({}, output);
|
|
36
|
+
// Buffer is populated; verified indirectly by triggering capture
|
|
37
|
+
});
|
|
38
|
+
it('ignores non-text parts', async () => {
|
|
39
|
+
const { mod } = await freshModule();
|
|
40
|
+
const output = {
|
|
41
|
+
parts: [{ type: 'image', data: 'abc' }]
|
|
42
|
+
};
|
|
43
|
+
await mod.messageHook({}, output);
|
|
44
|
+
// No text buffered
|
|
45
|
+
});
|
|
46
|
+
it('ignores empty text', async () => {
|
|
47
|
+
const { mod } = await freshModule();
|
|
48
|
+
const output = {
|
|
49
|
+
parts: [{ type: 'text', text: ' ' }]
|
|
50
|
+
};
|
|
51
|
+
await mod.messageHook({}, output);
|
|
52
|
+
// Whitespace-only is trimmed to empty, not buffered
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('autoCaptureHook', () => {
|
|
56
|
+
it('only triggers on session.idle event', async () => {
|
|
57
|
+
const { mod, mockCallTool } = await freshModule();
|
|
58
|
+
await mod.autoCaptureHook({ event: { type: 'session.start' } }, '/home/user/app');
|
|
59
|
+
expect(mockCallTool).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
it('skips when buffer is empty', async () => {
|
|
62
|
+
const { mod, mockCallTool } = await freshModule();
|
|
63
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
64
|
+
expect(mockCallTool).not.toHaveBeenCalled();
|
|
65
|
+
});
|
|
66
|
+
it('captures constraint-like messages on idle', async () => {
|
|
67
|
+
const { mod, mockCallTool } = await freshModule();
|
|
68
|
+
await mod.messageHook({}, {
|
|
69
|
+
parts: [{ type: 'text', text: 'You must always use pnpm for package management' }]
|
|
70
|
+
});
|
|
71
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/my-project');
|
|
72
|
+
expect(mockCallTool).toHaveBeenCalledWith('memory', expect.objectContaining({
|
|
73
|
+
action: 'add',
|
|
74
|
+
category: 'auto-capture',
|
|
75
|
+
tags: ['my-project', 'preference']
|
|
76
|
+
}));
|
|
77
|
+
});
|
|
78
|
+
it('skips non-constraint messages', async () => {
|
|
79
|
+
const { mod, mockCallTool } = await freshModule();
|
|
80
|
+
await mod.messageHook({}, {
|
|
81
|
+
parts: [{ type: 'text', text: 'Hello, how are you today?' }]
|
|
82
|
+
});
|
|
83
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
84
|
+
expect(mockCallTool).not.toHaveBeenCalled();
|
|
85
|
+
});
|
|
86
|
+
it('deduplicates identical content within session', async () => {
|
|
87
|
+
const { mod, mockCallTool } = await freshModule();
|
|
88
|
+
// First capture
|
|
89
|
+
await mod.messageHook({}, {
|
|
90
|
+
parts: [{ type: 'text', text: 'Always use strict mode' }]
|
|
91
|
+
});
|
|
92
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
93
|
+
expect(mockCallTool).toHaveBeenCalledTimes(1);
|
|
94
|
+
// Same content again — buffer the same text
|
|
95
|
+
await mod.messageHook({}, {
|
|
96
|
+
parts: [{ type: 'text', text: 'Always use strict mode' }]
|
|
97
|
+
});
|
|
98
|
+
// Second capture attempt should be deduped by hash
|
|
99
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
100
|
+
// Still only 1 call — second was deduped
|
|
101
|
+
expect(mockCallTool).toHaveBeenCalledTimes(1);
|
|
102
|
+
});
|
|
103
|
+
it('skips when bridge is unavailable', async () => {
|
|
104
|
+
const { mod, mockIsAvailable, mockCallTool } = await freshModule();
|
|
105
|
+
mockIsAvailable.mockReturnValue(false);
|
|
106
|
+
await mod.messageHook({}, {
|
|
107
|
+
parts: [{ type: 'text', text: 'You must always test your code' }]
|
|
108
|
+
});
|
|
109
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
110
|
+
expect(mockCallTool).not.toHaveBeenCalled();
|
|
111
|
+
});
|
|
112
|
+
it('truncates long content to MAX_CAPTURE_LENGTH', async () => {
|
|
113
|
+
const { mod, mockCallTool } = await freshModule();
|
|
114
|
+
const longConstraint = `You must always ${'follow this rule '.repeat(100)}`;
|
|
115
|
+
await mod.messageHook({}, {
|
|
116
|
+
parts: [{ type: 'text', text: longConstraint }]
|
|
117
|
+
});
|
|
118
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
119
|
+
const callArgs = mockCallTool.mock.calls[0][1];
|
|
120
|
+
// Content should be truncated (500 char limit + prefix)
|
|
121
|
+
expect(callArgs.content.length).toBeLessThan(longConstraint.length);
|
|
122
|
+
});
|
|
123
|
+
it('catches errors without throwing', async () => {
|
|
124
|
+
const { mod, mockCallTool } = await freshModule();
|
|
125
|
+
mockCallTool.mockRejectedValue(new Error('bridge down'));
|
|
126
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
127
|
+
await mod.messageHook({}, {
|
|
128
|
+
parts: [{ type: 'text', text: 'Never use var in JavaScript' }]
|
|
129
|
+
});
|
|
130
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
131
|
+
expect(consoleSpy).toHaveBeenCalled();
|
|
132
|
+
consoleSpy.mockRestore();
|
|
133
|
+
});
|
|
134
|
+
it('extracts project name from Windows path', async () => {
|
|
135
|
+
const { mod, mockCallTool } = await freshModule();
|
|
136
|
+
await mod.messageHook({}, {
|
|
137
|
+
parts: [{ type: 'text', text: 'Ensure all tests pass before commit' }]
|
|
138
|
+
});
|
|
139
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, 'C:\\Users\\dev\\projects\\win-project');
|
|
140
|
+
expect(mockCallTool).toHaveBeenCalledWith('memory', expect.objectContaining({
|
|
141
|
+
tags: ['win-project', 'preference']
|
|
142
|
+
}));
|
|
143
|
+
});
|
|
144
|
+
it('matches various constraint keywords', async () => {
|
|
145
|
+
const keywords = [
|
|
146
|
+
'always',
|
|
147
|
+
'never',
|
|
148
|
+
'must',
|
|
149
|
+
'prefer',
|
|
150
|
+
"don't",
|
|
151
|
+
'do not',
|
|
152
|
+
'should not',
|
|
153
|
+
'make sure',
|
|
154
|
+
'ensure',
|
|
155
|
+
'require'
|
|
156
|
+
];
|
|
157
|
+
for (const keyword of keywords) {
|
|
158
|
+
const { mod, mockCallTool } = await freshModule();
|
|
159
|
+
await mod.messageHook({}, {
|
|
160
|
+
parts: [{ type: 'text', text: `You ${keyword} use this convention in code` }]
|
|
161
|
+
});
|
|
162
|
+
await mod.autoCaptureHook({ event: { type: 'session.idle' } }, '/home/user/app');
|
|
163
|
+
expect(mockCallTool).toHaveBeenCalled();
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=auto-capture.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-capture.test.js","sourceRoot":"","sources":["../../tests/auto-capture.test.ts"],"names":[],"mappings":"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"}
|