@agentmemory/agentmemory 0.9.28 → 0.9.30
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/.env.example +98 -28
- package/AGENTS.md +19 -26
- package/README.md +619 -274
- package/dist/.env.example +98 -28
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +1328 -244
- package/dist/cli.mjs.map +1 -1
- package/dist/{connect-JnsJXc68.mjs → connect-B4_ca6BD.mjs} +619 -70
- package/dist/connect-B4_ca6BD.mjs.map +1 -0
- package/dist/docker-compose.yml +42 -16
- package/dist/hooks/_capture.d.mts +22 -0
- package/dist/hooks/_capture.d.mts.map +1 -0
- package/dist/hooks/_capture.mjs +908 -0
- package/dist/hooks/_capture.mjs.map +1 -0
- package/dist/hooks/antigravity-bridge.d.mts +8 -0
- package/dist/hooks/antigravity-bridge.d.mts.map +1 -0
- package/dist/hooks/antigravity-bridge.mjs +123 -0
- package/dist/hooks/antigravity-bridge.mjs.map +1 -0
- package/dist/hooks/notification.mjs +34 -27
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-commit.mjs +84 -2
- package/dist/hooks/post-commit.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +71 -26
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +99 -36
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +95 -5
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +72 -2
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +25 -22
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +93 -24
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +101 -6
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +72 -8
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +28 -26
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +29 -26
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +31 -28
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/iii-config.docker.yaml +10 -10
- package/dist/iii-config.yaml +3 -1
- package/dist/{image-refs-BKLmp_sD.mjs → image-refs-BaT-9oMU.mjs} +2 -2
- package/dist/image-refs-BaT-9oMU.mjs.map +1 -0
- package/dist/{image-refs-C2YU7BIm.mjs → image-refs-T_urbwHM.mjs} +3 -3
- package/dist/image-refs-T_urbwHM.mjs.map +1 -0
- package/dist/{keyed-mutex-DTHtcZrt.mjs → image-store-BsN4vyjr.mjs} +2 -14
- package/dist/image-store-BsN4vyjr.mjs.map +1 -0
- package/dist/index.mjs +14021 -6494
- package/dist/index.mjs.map +1 -1
- package/dist/keyed-mutex-DchXsyfP.mjs +221 -0
- package/dist/keyed-mutex-DchXsyfP.mjs.map +1 -0
- package/dist/secret-store-BnY3A50C.mjs +2348 -0
- package/dist/secret-store-BnY3A50C.mjs.map +1 -0
- package/dist/{src-CzgoepGU.mjs → src-Jsq9LCeH.mjs} +7349 -2940
- package/dist/src-Jsq9LCeH.mjs.map +1 -0
- package/dist/{standalone-YsZFFQBM.mjs → standalone-DKCdrf1d.mjs} +62 -24
- package/dist/standalone-DKCdrf1d.mjs.map +1 -0
- package/dist/standalone.d.mts.map +1 -1
- package/dist/standalone.mjs +298 -27
- package/dist/standalone.mjs.map +1 -1
- package/dist/status-IRz7ta8-.mjs +2344 -0
- package/dist/status-IRz7ta8-.mjs.map +1 -0
- package/dist/viewer/favicon.svg +35 -1
- package/dist/viewer/index.html +7428 -2608
- package/docker-compose.yml +42 -16
- package/iii-config.docker.yaml +10 -10
- package/iii-config.yaml +3 -1
- package/integrations/pi/README.md +77 -0
- package/integrations/pi/index.ts +402 -0
- package/integrations/pi/package.json +32 -0
- package/integrations/pi/security.ts +87 -0
- package/package.json +15 -7
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +26 -4
- package/plugin/.devin-plugin/plugin.json +32 -0
- package/plugin/.mcp.codex.json +12 -0
- package/plugin/.mcp.copilot.json +2 -7
- package/plugin/.mcp.json +2 -7
- package/plugin/assets/icon.svg +35 -0
- package/plugin/cursor/hooks.json +41 -0
- package/plugin/cursor/mcp.json +12 -0
- package/plugin/hooks/hooks.antigravity.json +43 -0
- package/plugin/hooks/hooks.copilot.json +11 -11
- package/plugin/hooks/hooks.devin.json +67 -0
- package/plugin/hooks/hooks.droid.json +55 -0
- package/plugin/opencode/README.md +267 -31
- package/plugin/opencode/agentmemory-capture.ts +644 -15
- package/plugin/opencode/plugin.json +1 -1
- package/plugin/plugin.json +2 -2
- package/plugin/scripts/_capture.d.mts +22 -0
- package/plugin/scripts/_capture.d.mts.map +1 -0
- package/plugin/scripts/_capture.mjs +908 -0
- package/plugin/scripts/_capture.mjs.map +1 -0
- package/plugin/scripts/antigravity-bridge.d.mts +8 -0
- package/plugin/scripts/antigravity-bridge.d.mts.map +1 -0
- package/plugin/scripts/antigravity-bridge.mjs +123 -0
- package/plugin/scripts/antigravity-bridge.mjs.map +1 -0
- package/plugin/scripts/notification.mjs +34 -27
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/plugin-bridge.mjs +378 -0
- package/plugin/scripts/post-commit.mjs +84 -2
- package/plugin/scripts/post-commit.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +71 -26
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +99 -36
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +95 -5
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +72 -2
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +25 -22
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +93 -24
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +101 -6
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +72 -8
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +28 -26
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +29 -26
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +31 -28
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/plugin/skills/_shared/TROUBLESHOOTING.md +22 -6
- package/plugin/skills/agentmemory-agents/REFERENCE.md +8 -5
- package/plugin/skills/agentmemory-config/REFERENCE.md +52 -1
- package/plugin/skills/agentmemory-config/SKILL.md +44 -7
- package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +4 -3
- package/plugin/skills/agentmemory-rest-api/REFERENCE.md +23 -2
- package/plugin/skills/forget/SKILL.md +4 -1
- package/plugin/skills/handoff/SKILL.md +4 -2
- package/plugin/skills/lesson/SKILL.md +64 -0
- package/plugin/skills/memory-discipline/SKILL.md +65 -0
- package/plugin/skills/recall/SKILL.md +4 -1
- package/plugin/skills/remember/SKILL.md +6 -1
- package/dist/config-ChC9EtgV.mjs +0 -259
- package/dist/config-ChC9EtgV.mjs.map +0 -1
- package/dist/connect-JnsJXc68.mjs.map +0 -1
- package/dist/image-refs-BKLmp_sD.mjs.map +0 -1
- package/dist/image-refs-C2YU7BIm.mjs.map +0 -1
- package/dist/keyed-mutex-DTHtcZrt.mjs.map +0 -1
- package/dist/logger-BEB7pCI9.mjs +0 -43
- package/dist/logger-BEB7pCI9.mjs.map +0 -1
- package/dist/schema-CNiCWzV9.mjs +0 -78
- package/dist/schema-CNiCWzV9.mjs.map +0 -1
- package/dist/src-CzgoepGU.mjs.map +0 -1
- package/dist/standalone-YsZFFQBM.mjs.map +0 -1
- package/dist/tools-registry-D3NEoe5m.mjs +0 -1115
- package/dist/tools-registry-D3NEoe5m.mjs.map +0 -1
- package/plugin/scripts/diagnostics.d.mts +0 -17
- package/plugin/scripts/diagnostics.d.mts.map +0 -1
- package/plugin/scripts/diagnostics.mjs.map +0 -1
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<img src="https://img.shields.io/badge/MCP-
|
|
12
|
+
<img src="https://img.shields.io/badge/MCP-54_tools-1f6feb?style=flat-square" alt="54 MCP tools" />
|
|
13
13
|
<img src="https://img.shields.io/badge/Plugin-22_hooks-1f6feb?style=flat-square" alt="22 hooks" />
|
|
14
|
+
<img src="https://img.shields.io/badge/OpenCode-1.x_%2B_2.x-1f6feb?style=flat-square" alt="OpenCode 1.x and 2.x" />
|
|
14
15
|
<img src="https://img.shields.io/badge/Commands-2_slash-1f6feb?style=flat-square" alt="2 slash commands" />
|
|
15
16
|
<img src="https://img.shields.io/badge/R@5-95.2%25-00875f?style=flat-square" alt="95.2% R@5" />
|
|
16
17
|
</p>
|
|
@@ -45,20 +46,41 @@ Add to `~/.config/opencode/opencode.json` or your project's `.opencode/opencode.
|
|
|
45
46
|
|
|
46
47
|
### 3. Install the plugin
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
Copy the plugin file:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
mkdir -p ~/.config/opencode/plugins
|
|
53
|
+
cp plugin/opencode/agentmemory-capture.ts ~/.config/opencode/plugins/
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
That is the whole install. OpenCode loads every plugin file in
|
|
57
|
+
`~/.config/opencode/plugins/` automatically, so there is nothing to register.
|
|
58
|
+
|
|
59
|
+
> **Do not also add it to `opencode.json`.** Listing the file under
|
|
60
|
+
> `"plugins"` on top of leaving it in the auto-loaded directory registers the
|
|
61
|
+
> same plugin twice, and it then captures every event twice. If you see doubled
|
|
62
|
+
> observations, remove the `"plugins"` entry and keep the file where it is.
|
|
63
|
+
>
|
|
64
|
+
> If you would rather keep plugins outside that directory, install the file
|
|
65
|
+
> somewhere else and point the config key at it:
|
|
66
|
+
>
|
|
67
|
+
> ```json
|
|
68
|
+
> {
|
|
69
|
+
> "plugins": ["./my-plugins/agentmemory-capture.ts"]
|
|
70
|
+
> }
|
|
71
|
+
> ```
|
|
72
|
+
>
|
|
73
|
+
> Either location works. The two must not both be in effect at once.
|
|
74
|
+
|
|
75
|
+
**OpenCode 1.x** — the same file works, using the V1 key instead:
|
|
49
76
|
|
|
50
77
|
```json
|
|
51
78
|
{
|
|
52
|
-
"plugin": ["./plugins/agentmemory-capture.ts"]
|
|
79
|
+
"plugin": ["./my-plugins/agentmemory-capture.ts"]
|
|
53
80
|
}
|
|
54
81
|
```
|
|
55
82
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
mkdir -p ~/.config/opencode/plugins
|
|
60
|
-
cp plugin/opencode/agentmemory-capture.ts ~/.config/opencode/plugins/
|
|
61
|
-
```
|
|
83
|
+
See [OpenCode 1.x and 2.x](#opencode-1x-and-2x) below.
|
|
62
84
|
|
|
63
85
|
### 4. Add the slash commands
|
|
64
86
|
|
|
@@ -72,6 +94,213 @@ cp plugin/opencode/commands/remember.md ~/.config/opencode/commands/
|
|
|
72
94
|
|
|
73
95
|
Restart OpenCode or open a new session. The plugin auto-captures everything.
|
|
74
96
|
|
|
97
|
+
## OpenCode 1.x and 2.x
|
|
98
|
+
|
|
99
|
+
`agentmemory-capture.ts` supports both plugin APIs from a single file.
|
|
100
|
+
|
|
101
|
+
OpenCode 2 replaced the V1 `Hooks`-object plugin shape: the default export must
|
|
102
|
+
carry an `id` plus a `setup(ctx)`, and hooks are registered on the domain that
|
|
103
|
+
owns the operation. The plugin therefore default-exports both:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
export default {
|
|
107
|
+
id: "agentmemory-capture",
|
|
108
|
+
setup: v2Setup, // OpenCode 2.x
|
|
109
|
+
server: v1Hooks, // OpenCode 1.x (SDK 1.18.x era)
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
- **OpenCode 2.x** reads `id` and `setup()`.
|
|
114
|
+
- **OpenCode 1.17 and 1.18** call `server()` and use the returned hooks. They
|
|
115
|
+
also call `setup()`, with a context that has no `tool`, `session` or `event`.
|
|
116
|
+
`setup()` returns immediately when those are missing, so only the V1 hooks
|
|
117
|
+
run there.
|
|
118
|
+
- The two implementations are separate on purpose. Sharing an export does not
|
|
119
|
+
translate V1 hooks into V2 hooks, and the payloads differ enough that a shared
|
|
120
|
+
core would overstate V2 coverage.
|
|
121
|
+
- The named `export const AgentmemoryCapturePlugin` exists for direct imports
|
|
122
|
+
and for V1 releases older than 1.18.29, which expect a function as the
|
|
123
|
+
default export. A V1 loader that resolves `default` and calls `server()` on it
|
|
124
|
+
sees one plugin; the named export is not consulted unless a loader iterates
|
|
125
|
+
every export, which no observed version does.
|
|
126
|
+
|
|
127
|
+
**V1 load, verified.** OpenCode 1.17.10 and 1.18.34 (the `opencode-ai` npm
|
|
128
|
+
package) were run against this file in live sessions: one plugin instance,
|
|
129
|
+
reads and shell calls captured through the V1 hooks, and one `config_loaded`
|
|
130
|
+
per session.
|
|
131
|
+
|
|
132
|
+
Validated against **OpenCode v2.0.22**, and re-checked on **v2.0.24**, by running the plugin inside a live
|
|
133
|
+
session and logging the objects as they arrive, not by reading the generated
|
|
134
|
+
SDK types. That distinction matters: `@opencode-ai/sdk` 1.4.10 declares
|
|
135
|
+
`event.properties` and the V1 event names, and it is stale relative to the
|
|
136
|
+
runtime. Where this README says a payload was observed, it was read off a
|
|
137
|
+
running server.
|
|
138
|
+
|
|
139
|
+
### What the V2 runtime actually does
|
|
140
|
+
|
|
141
|
+
- **The payload is in `event.data`, not `event.properties`.** The envelope is
|
|
142
|
+
`created, data, id, location, type`. Reading `properties` yields `{}`.
|
|
143
|
+
- **The V1 event names are gone.** They were not renamed one-for-one; the
|
|
144
|
+
stream is organised differently. `location` on the envelope is
|
|
145
|
+
process-level, so session identity comes from `data.sessionID`.
|
|
146
|
+
- **`list()` returns `{ data, location }`.** `ctx.agent.list()`,
|
|
147
|
+
`ctx.provider.list()` and `ctx.mcp.list()` all resolve to that shape.
|
|
148
|
+
- **`ctx.model.default()` is a promise.** Unawaited it is `{}`.
|
|
149
|
+
- **`session.created` exists.** On v2.0.24 it carries `sessionID`,
|
|
150
|
+
`projectID`, `location`, `version`, `subpath` and `slug`. The title arrives
|
|
151
|
+
later in `session.renamed`, so a session registers on creation with its
|
|
152
|
+
directory in hand. The fallback to
|
|
153
|
+
"first event carrying an ID" remains for sessions that predate the plugin
|
|
154
|
+
load, which never emit the event. An earlier revision of this plugin claimed
|
|
155
|
+
`session.created` did not exist; that came from observing an already-open
|
|
156
|
+
session and never creating one, which is absence in a sample rather than
|
|
157
|
+
absence in the API.
|
|
158
|
+
- **`ctx.session.hook("compaction")` registers, but its invocation is
|
|
159
|
+
unverified.** Calling `ctx.session.compact()` only *queues* a compaction
|
|
160
|
+
request; the hook would fire when the compaction actually runs. Forcing a
|
|
161
|
+
compaction in a running v2.0.22 emitted `session.compaction.started` and
|
|
162
|
+
`session.compaction.failed` immediately, with `Nothing to compact yet`,
|
|
163
|
+
because the session was empty. That proves the events fire and says nothing
|
|
164
|
+
about the hook, which never got a real compaction to run. The hook is kept
|
|
165
|
+
and the events are captured alongside it: if the hook is invoked it attaches
|
|
166
|
+
memory to the compaction prompt, and the events record that compaction
|
|
167
|
+
happened either way.
|
|
168
|
+
- **`session.execution.succeeded` triggers `/summarize`.** It fires when a run
|
|
169
|
+
finishes and carries only `{ sessionID }`, so it adds no observation. V1
|
|
170
|
+
summarizes when a session goes idle; this is the V2 equivalent.
|
|
171
|
+
- **`session.instructions.updated` carries `delta`, a map from instruction
|
|
172
|
+
source to content hash.** The plugin records the source names, not the
|
|
173
|
+
hashes.
|
|
174
|
+
- **A standalone `opencode session delete` exits before the plugin sees
|
|
175
|
+
`session.deleted`.** The session then stays open in agentmemory. Summaries do
|
|
176
|
+
not depend on it, because they come from `session.execution.succeeded`.
|
|
177
|
+
- **`parentID` is accepted by `ctx.session.create` but appears in no event
|
|
178
|
+
payload.** The `parentID` sent to `/session/start` is therefore always null;
|
|
179
|
+
the field is kept in case a future version populates it.
|
|
180
|
+
|
|
181
|
+
### Hook mapping
|
|
182
|
+
|
|
183
|
+
| V1 | V2 | Status |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| `event` | `ctx.event.subscribe()` | ported |
|
|
186
|
+
| `tool.execute.before` | `ctx.tool.hook("execute.before")` | ported |
|
|
187
|
+
| tool results (`message.part.updated`) | `ctx.tool.hook("execute.after")` | ported |
|
|
188
|
+
| `chat.message` | `ctx.session.hook("prompt")` | ported |
|
|
189
|
+
| `experimental.chat.system.transform` | `ctx.session.hook("context")` | ported |
|
|
190
|
+
| `experimental.session.compacting` | `ctx.session.hook("compaction")` | ported, **unverified** |
|
|
191
|
+
| `config` | *(no hook)* | snapshot at `setup`, refreshed on `*.updated` |
|
|
192
|
+
| `chat.params` | *(no equivalent)* | not captured |
|
|
193
|
+
|
|
194
|
+
`output.system` (a string array) became `event.system` (`SystemPart[]`), so
|
|
195
|
+
injection pushes part objects rather than strings.
|
|
196
|
+
|
|
197
|
+
### Event mapping
|
|
198
|
+
|
|
199
|
+
| V1 event | V2 |
|
|
200
|
+
|---|---|
|
|
201
|
+
| `session.created` | `session.created` (or first event carrying `data.sessionID`) |
|
|
202
|
+
| `session.deleted` | `session.deleted` |
|
|
203
|
+
| `session.status`, `session.idle` | `session.step.started` / `session.step.ended`; `session.execution.succeeded` triggers `/summarize` |
|
|
204
|
+
| `message.updated` | `session.text.ended` (`assistant_message`), `session.reasoning.ended` |
|
|
205
|
+
| `message.part.updated` | `ctx.tool.hook("execute.after")` |
|
|
206
|
+
| `command.executed` | the command arrives through `execute.after`; `shell.exited` records a non-zero exit |
|
|
207
|
+
| `session.error` | `session.execution.failed` |
|
|
208
|
+
| `file.edited` | `file.watcher.updated` |
|
|
209
|
+
| `session.compacted` | `session.compaction.started` / `.failed` |
|
|
210
|
+
| `permission.updated` | `permission.asked` (payload is a `PermissionRequest`) |
|
|
211
|
+
| `todo.updated`, `session.diff` | *no V2 equivalent observed* |
|
|
212
|
+
|
|
213
|
+
`permission.asked` and `permission.replied` were not seen firing during
|
|
214
|
+
development. They are handled against the documented shape, reading both the
|
|
215
|
+
V2 field names and the V1 fallbacks, and are not covered by the observed
|
|
216
|
+
columns in the table below.
|
|
217
|
+
|
|
218
|
+
### Injection happens on every call, fetched once per prompt
|
|
219
|
+
|
|
220
|
+
`ctx.session.hook("context")` fires on every model call, so recalled memory is
|
|
221
|
+
injected every time. The previous implementation injected once per session,
|
|
222
|
+
which meant only the first prompt of a session carried memory.
|
|
223
|
+
|
|
224
|
+
Because the hook also fires on each tool continuation, `/context` is requested
|
|
225
|
+
at most once per prompt and then reused for the rest of the turn: the recalled
|
|
226
|
+
set does not change while a prompt is being answered. A new prompt clears the
|
|
227
|
+
cache. The `compaction` hook reuses the same turn cache.
|
|
228
|
+
|
|
229
|
+
Compaction is also captured from the `session.compaction.started` / `.failed`
|
|
230
|
+
events, which are observed.
|
|
231
|
+
|
|
232
|
+
### What V2 cannot do
|
|
233
|
+
|
|
234
|
+
- **`chat.params`** — V2's `context` hook exposes `options` with `maxTokens`
|
|
235
|
+
only; temperature and `topP` are absent, and `model` carries only
|
|
236
|
+
`id` / `providerID` / `variant`. Recorded `llm_params` would be wrong rather
|
|
237
|
+
than partial, so they are not recorded. The `model` on the hook is captured
|
|
238
|
+
in `step_start` instead, where it is real.
|
|
239
|
+
|
|
240
|
+
### Why `ctx` is typed `any`
|
|
241
|
+
|
|
242
|
+
The V2 setup signature is `async function v2Setup(ctx: any)`. That is
|
|
243
|
+
deliberate, and worth explaining because it looks like a shortcut.
|
|
244
|
+
|
|
245
|
+
Typing it properly would mean importing types from `@opencode-ai/plugin`. The
|
|
246
|
+
generated types shipped for that package are **stale for V2**: SDK 1.4.10
|
|
247
|
+
declares `EventSessionCreated = { type, properties: { sessionID, info } }` and
|
|
248
|
+
enumerates the V1 event names, none of which the v2.0.22 runtime emits. A
|
|
249
|
+
type-only import would therefore make the compiler reject correct code while
|
|
250
|
+
accepting the shape that caused the original bug. Silence was the safer of the
|
|
251
|
+
two failure modes, so `any` is used and the correctness burden moved to runtime
|
|
252
|
+
verification.
|
|
253
|
+
|
|
254
|
+
The known cost, stated plainly:
|
|
255
|
+
|
|
256
|
+
- The compiler will not catch V2 payload drift. A renamed field becomes a
|
|
257
|
+
`undefined` at runtime instead of a type error.
|
|
258
|
+
- Nothing checks that the event names in `handleEvent` are real. This branch
|
|
259
|
+
shipped a handler for fifteen V1 event names, none of which fire.
|
|
260
|
+
- There is no compile-time guarantee that `ctx.session.hook(...)` takes a name
|
|
261
|
+
that exists. The loader accepts any string, so a typo registers nothing and
|
|
262
|
+
fails silently.
|
|
263
|
+
|
|
264
|
+
That is why the verification suite drives the plugin with payloads captured
|
|
265
|
+
from a live server instead of hand-built objects, and why the
|
|
266
|
+
[Verification](#verification) section distinguishes observed from inferred. If a
|
|
267
|
+
future release ships correct V2 types, this signature should be tightened and
|
|
268
|
+
these three risks retired with it.
|
|
269
|
+
|
|
270
|
+
### Verification
|
|
271
|
+
|
|
272
|
+
- `test/opencode-plugin-v2.test.ts` — 38 cases driving the V2 path with payloads
|
|
273
|
+
captured from v2.0.22. It runs under the repo's existing vitest, so:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
npx vitest run test/opencode-plugin-v2.test.ts
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
It covers session lifecycle, the tool hooks, memory injection on every model
|
|
280
|
+
call, compaction, the event switch, and the regression where an early
|
|
281
|
+
`return` ended the event subscription. Each case added with the compaction
|
|
282
|
+
change was checked against the previous commit: the three compaction cases
|
|
283
|
+
fail on it and pass here.
|
|
284
|
+
- In a live session the plugin produced real observations for
|
|
285
|
+
`post_tool_use`, `config_loaded`, `step_start`, `step_finish`,
|
|
286
|
+
`reasoning`, `assistant_message` and `notification`, and requested
|
|
287
|
+
`/summarize` when the run finished.
|
|
288
|
+
`session.compaction.started` and `session.compaction.failed` were confirmed
|
|
289
|
+
by forcing a compaction in a running v2.0.22.
|
|
290
|
+
|
|
291
|
+
`session.text.started`, `session.reasoning.started`, `session.inbox.delivered`,
|
|
292
|
+
`shell.created` and `session.usage.updated` are read but not recorded. The
|
|
293
|
+
first two carry no text yet, the inbox event carries only an ID, `shell.created`
|
|
294
|
+
duplicates the command that `execute.after` already records, and usage
|
|
295
|
+
duplicates the token and cost figures in `step_finish`. A config snapshot equal
|
|
296
|
+
to the previous one is not recorded again.
|
|
297
|
+
|
|
298
|
+
Earlier in this branch the V2 path loaded cleanly and captured almost nothing,
|
|
299
|
+
because it was verified against a hand-built context object that agreed with
|
|
300
|
+
its own assumptions. Verifying that the plugin loads is not verifying that it
|
|
301
|
+
works, and the suite exists so that the next person does not have to learn that
|
|
302
|
+
twice.
|
|
303
|
+
|
|
75
304
|
## What gets captured
|
|
76
305
|
|
|
77
306
|
### Session lifecycle
|
|
@@ -89,12 +318,12 @@ Restart OpenCode or open a new session. The plugin auto-captures everything.
|
|
|
89
318
|
|
|
90
319
|
### Messages & prompts
|
|
91
320
|
|
|
92
|
-
| Event |
|
|
93
|
-
|
|
94
|
-
| User prompt (rich) | `chat.message` | POST /observe |
|
|
95
|
-
| User prompt metadata | `message.updated` (user) | POST /observe |
|
|
96
|
-
| Assistant response | `message.updated` (assistant) | POST /observe |
|
|
97
|
-
| Message removed (undo) | `message.removed` | POST /observe |
|
|
321
|
+
| Event | V1 hook | V2 hook | agentmemory API |
|
|
322
|
+
|---|---|---|---|
|
|
323
|
+
| User prompt (rich) | `chat.message` | `ctx.session.hook("prompt")` | POST /observe |
|
|
324
|
+
| User prompt metadata | `message.updated` (user) | `message.updated` (user) | POST /observe |
|
|
325
|
+
| Assistant response | `message.updated` (assistant) | `message.updated` (assistant) | POST /observe |
|
|
326
|
+
| Message removed (undo) | `message.removed` | `message.removed` | POST /observe |
|
|
98
327
|
|
|
99
328
|
### Parts & steps
|
|
100
329
|
|
|
@@ -112,20 +341,23 @@ Restart OpenCode or open a new session. The plugin auto-captures everything.
|
|
|
112
341
|
|
|
113
342
|
### File enrichment pipeline
|
|
114
343
|
|
|
115
|
-
| Event |
|
|
116
|
-
|
|
117
|
-
| File tool params | `tool.execute.before` → stash paths |
|
|
118
|
-
| File edited | `file.edited` → stash paths |
|
|
119
|
-
| File part attached | `message.part.updated` (file) → stash paths |
|
|
120
|
-
| Enrichment inject | `experimental.chat.system.transform` | POST /enrich →
|
|
121
|
-
| Memory context inject | `experimental.chat.system.transform` | POST /context →
|
|
344
|
+
| Event | V1 hook | V2 hook | agentmemory API |
|
|
345
|
+
|---|---|---|---|
|
|
346
|
+
| File tool params | `tool.execute.before` → stash paths | `ctx.tool.hook("execute.before")` | - |
|
|
347
|
+
| File edited | `file.edited` → stash paths | `file.edited` | - |
|
|
348
|
+
| File part attached | `message.part.updated` (file) → stash paths | `message.part.updated` (file) | - |
|
|
349
|
+
| Enrichment inject | `experimental.chat.system.transform` | `ctx.session.hook("context")` | POST /enrich → system prompt |
|
|
350
|
+
| Memory context inject | `experimental.chat.system.transform` | `ctx.session.hook("context")` | POST /context → system prompt |
|
|
351
|
+
|
|
352
|
+
On V1 the two injects land in `output.system[]`. On V2 they are pushed as
|
|
353
|
+
`SystemPart` objects onto `event.system`.
|
|
122
354
|
|
|
123
355
|
### Permissions
|
|
124
356
|
|
|
125
|
-
| Event |
|
|
126
|
-
|
|
127
|
-
| Permission prompt | `permission.updated` | POST /observe |
|
|
128
|
-
| Permission reply | `permission.replied` | POST /observe |
|
|
357
|
+
| Event | V1 hook | V2 hook | agentmemory API |
|
|
358
|
+
|---|---|---|---|
|
|
359
|
+
| Permission prompt | `permission.updated` | `permission.asked` | POST /observe |
|
|
360
|
+
| Permission reply | `permission.replied` | `permission.replied` | POST /observe |
|
|
129
361
|
|
|
130
362
|
### Tasks & commands
|
|
131
363
|
|
|
@@ -136,11 +368,15 @@ Restart OpenCode or open a new session. The plugin auto-captures everything.
|
|
|
136
368
|
|
|
137
369
|
### Model & config
|
|
138
370
|
|
|
139
|
-
| Event |
|
|
140
|
-
|
|
141
|
-
| LLM parameters | `chat.params` | POST /observe |
|
|
142
|
-
| Config loaded | `config` | POST /observe |
|
|
143
|
-
| Compaction
|
|
371
|
+
| Event | V1 hook | V2 | agentmemory API |
|
|
372
|
+
|---|---|---|---|
|
|
373
|
+
| LLM parameters | `chat.params` | not captured | POST /observe (V1 only) |
|
|
374
|
+
| Config loaded | `config` | snapshot at setup | POST /observe |
|
|
375
|
+
| Compaction context | `experimental.session.compacting` | `ctx.session.hook("compaction")`, unverified | POST /context → `event.system[]` |
|
|
376
|
+
|
|
377
|
+
These three are the only differences between the V1 and V2 paths. Everything
|
|
378
|
+
else in this document is captured identically on both. See
|
|
379
|
+
[What V2 cannot do](#what-v2-cannot-do).
|
|
144
380
|
|
|
145
381
|
### File enrichment + memory injection (two-layer pipeline)
|
|
146
382
|
|