engrm 0.4.37 → 0.4.39
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 +53 -2
- package/dist/cli.js +446 -62
- package/dist/hooks/elicitation-result.js +57 -1
- package/dist/hooks/post-tool-use.js +57 -1
- package/dist/hooks/pre-compact.js +57 -1
- package/dist/hooks/sentinel.js +20 -0
- package/dist/hooks/session-start.js +82 -12
- package/dist/hooks/stop.js +305 -186
- package/dist/hooks/user-prompt-submit.js +57 -1
- package/dist/server.js +347 -77
- package/opencode/README.md +70 -0
- package/opencode/install-or-update-opencode-plugin.sh +46 -0
- package/opencode/opencode.example.json +14 -0
- package/opencode/plugin/engrm-opencode.js +61 -0
- package/package.json +10 -4
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Engrm OpenCode Support
|
|
2
|
+
|
|
3
|
+
Engrm supports OpenCode in two layers:
|
|
4
|
+
|
|
5
|
+
- Engrm as an MCP server in `opencode.json`
|
|
6
|
+
- a lightweight local OpenCode plugin that improves continuity during compaction
|
|
7
|
+
|
|
8
|
+
This keeps the OpenCode integration safe:
|
|
9
|
+
|
|
10
|
+
- MCP stays responsible for durable memory, handoffs, chat recall, and resume tools
|
|
11
|
+
- the plugin only adds OpenCode-native continuity behavior where hooks make sense
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
Run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
./opencode/install-or-update-opencode-plugin.sh
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This will:
|
|
22
|
+
|
|
23
|
+
- copy the local plugin to `~/.config/opencode/plugins/engrm.js`
|
|
24
|
+
- add or update an `engrm` MCP server in `~/.config/opencode/opencode.json`
|
|
25
|
+
|
|
26
|
+
## Config Shape
|
|
27
|
+
|
|
28
|
+
The MCP entry written by the helper script matches:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"$schema": "https://opencode.ai/config.json",
|
|
33
|
+
"mcp": {
|
|
34
|
+
"engrm": {
|
|
35
|
+
"type": "local",
|
|
36
|
+
"command": ["engrm", "serve"],
|
|
37
|
+
"enabled": true,
|
|
38
|
+
"timeout": 5000
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
An example file also lives at:
|
|
45
|
+
|
|
46
|
+
- `opencode/opencode.example.json`
|
|
47
|
+
|
|
48
|
+
## What The Plugin Does
|
|
49
|
+
|
|
50
|
+
The first OpenCode plugin is intentionally conservative.
|
|
51
|
+
|
|
52
|
+
- logs plugin initialization through OpenCode's app log
|
|
53
|
+
- watches `session.created` and `session.compacted`
|
|
54
|
+
- injects Engrm continuity guidance into `experimental.session.compacting`
|
|
55
|
+
|
|
56
|
+
It does not try to replace Engrm MCP tools or perform undocumented runtime tricks.
|
|
57
|
+
|
|
58
|
+
## Use With Engrm
|
|
59
|
+
|
|
60
|
+
Inside OpenCode, the most useful Engrm tools remain:
|
|
61
|
+
|
|
62
|
+
- `resume_thread`
|
|
63
|
+
- `list_recall_items`
|
|
64
|
+
- `load_recall_item`
|
|
65
|
+
- `repair_recall`
|
|
66
|
+
- `search_recall`
|
|
67
|
+
- `save_observation`
|
|
68
|
+
- `create_handoff`
|
|
69
|
+
|
|
70
|
+
The plugin exists to make OpenCode compaction preserve that workflow better, not to fork it.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
export ENGRM_OPENCODE_SCRIPT_DIR="$SCRIPT_DIR"
|
|
6
|
+
|
|
7
|
+
python3 - <<'PY'
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import json
|
|
10
|
+
import shutil
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
root = Path(os.environ["ENGRM_OPENCODE_SCRIPT_DIR"]).resolve()
|
|
14
|
+
repo = root.parent
|
|
15
|
+
plugin_source = repo / "opencode" / "plugin" / "engrm-opencode.js"
|
|
16
|
+
config_dir = Path.home() / ".config" / "opencode"
|
|
17
|
+
plugins_dir = config_dir / "plugins"
|
|
18
|
+
config_path = config_dir / "opencode.json"
|
|
19
|
+
|
|
20
|
+
plugins_dir.mkdir(parents=True, exist_ok=True)
|
|
21
|
+
shutil.copy2(plugin_source, plugins_dir / "engrm.js")
|
|
22
|
+
|
|
23
|
+
if config_path.exists():
|
|
24
|
+
try:
|
|
25
|
+
config = json.loads(config_path.read_text())
|
|
26
|
+
except Exception:
|
|
27
|
+
config = {}
|
|
28
|
+
else:
|
|
29
|
+
config = {}
|
|
30
|
+
|
|
31
|
+
config.setdefault("$schema", "https://opencode.ai/config.json")
|
|
32
|
+
mcp = config.setdefault("mcp", {})
|
|
33
|
+
mcp["engrm"] = {
|
|
34
|
+
"type": "local",
|
|
35
|
+
"command": ["engrm", "serve"],
|
|
36
|
+
"enabled": True,
|
|
37
|
+
"timeout": 5000,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
config_path.write_text(json.dumps(config, indent=2) + "\n")
|
|
41
|
+
|
|
42
|
+
print(f"Installed plugin -> {plugins_dir / 'engrm.js'}")
|
|
43
|
+
print(f"Updated config -> {config_path}")
|
|
44
|
+
PY
|
|
45
|
+
|
|
46
|
+
echo "OpenCode Engrm integration install/update complete."
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export const EngrmPlugin = async ({ client, directory, worktree, project }) => {
|
|
2
|
+
const projectLabel = project?.name ?? directory ?? worktree ?? "unknown";
|
|
3
|
+
|
|
4
|
+
try {
|
|
5
|
+
await client.app.log({
|
|
6
|
+
body: {
|
|
7
|
+
service: "engrm-opencode",
|
|
8
|
+
level: "info",
|
|
9
|
+
message: "Engrm OpenCode plugin initialized",
|
|
10
|
+
extra: { project: projectLabel },
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
} catch {
|
|
14
|
+
// Best-effort only
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
event: async ({ event }) => {
|
|
19
|
+
if (!event?.type) return;
|
|
20
|
+
if (event.type === "session.created" || event.type === "session.compacted") {
|
|
21
|
+
try {
|
|
22
|
+
await client.app.log({
|
|
23
|
+
body: {
|
|
24
|
+
service: "engrm-opencode",
|
|
25
|
+
level: "info",
|
|
26
|
+
message: `Observed OpenCode event: ${event.type}`,
|
|
27
|
+
extra: { project: projectLabel },
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
} catch {
|
|
31
|
+
// Best-effort only
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
"experimental.session.compacting": async (_input, output) => {
|
|
37
|
+
output.context.push(`
|
|
38
|
+
## Engrm Continuity
|
|
39
|
+
|
|
40
|
+
Before finalizing the compaction summary, preserve the active working thread using Engrm's continuity model.
|
|
41
|
+
|
|
42
|
+
Prefer these Engrm tools when continuity is unclear:
|
|
43
|
+
1. \`resume_thread\`
|
|
44
|
+
2. \`list_recall_items\`
|
|
45
|
+
3. \`load_recall_item\`
|
|
46
|
+
4. \`repair_recall\`
|
|
47
|
+
|
|
48
|
+
Carry forward:
|
|
49
|
+
- the current task and status
|
|
50
|
+
- the current thread in one sentence
|
|
51
|
+
- the next actions
|
|
52
|
+
- the hot files or touched files
|
|
53
|
+
- the best exact recall key to reopen, if one is available
|
|
54
|
+
|
|
55
|
+
Do not collapse the session into generic status language if a more specific current thread exists.
|
|
56
|
+
`.trim());
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default EngrmPlugin;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "engrm",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Shared memory across devices, sessions, and agents, with thin MCP tools for durable capture and
|
|
3
|
+
"version": "0.4.39",
|
|
4
|
+
"description": "Shared memory across devices, sessions, and agents, with thin MCP tools for durable capture, live continuity, and Hermes-ready remote MCP support",
|
|
5
5
|
"mcpName": "io.github.dr12hes/engrm",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/server.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist/",
|
|
13
|
+
"opencode/",
|
|
13
14
|
"packs/",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
@@ -18,7 +19,9 @@
|
|
|
18
19
|
"init": "bun run src/cli.ts init",
|
|
19
20
|
"test": "bun test",
|
|
20
21
|
"build": "bun run bin/build.mjs",
|
|
21
|
-
"
|
|
22
|
+
"check:openclaw-plugin": "node scripts/check-openclaw-plugin-contract.mjs",
|
|
23
|
+
"check:release": "bun run build && node scripts/check-public-docs.mjs && node scripts/check-openclaw-plugin-contract.mjs",
|
|
24
|
+
"prepublishOnly": "npm run check:release"
|
|
22
25
|
},
|
|
23
26
|
"engines": {
|
|
24
27
|
"node": ">=18.0.0"
|
|
@@ -34,7 +37,10 @@
|
|
|
34
37
|
"code-audit",
|
|
35
38
|
"cross-device",
|
|
36
39
|
"team-memory",
|
|
37
|
-
"developer-tools"
|
|
40
|
+
"developer-tools",
|
|
41
|
+
"hermes",
|
|
42
|
+
"streamable-http",
|
|
43
|
+
"remote-mcp"
|
|
38
44
|
],
|
|
39
45
|
"dependencies": {
|
|
40
46
|
"@anthropic-ai/claude-agent-sdk": "^0.2.74",
|