echoes-vault-opencode 1.2.2 → 1.2.3
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 +2 -0
- package/index.ts +42 -8
- package/package.json +1 -1
- package/prompts/commands/echoes-end.md +2 -0
- package/tui.tsx +1 -1
package/README.md
CHANGED
|
@@ -100,6 +100,8 @@ Reads the last 3 daily logs and the full index, then summarizes where you left o
|
|
|
100
100
|
```
|
|
101
101
|
The AI distills the session into a dense technical summary, writes new encyclopedia pages for any concepts decided today, and updates the index. All via a single tool call.
|
|
102
102
|
|
|
103
|
+
Vault status is never automatic: the user controls its transitions with `/echoes-init`, `/echoes-start`, and `/echoes-end`. In particular, `Memory Saved` is shown only after `/echoes-end`. Agents may add intermediate scratchpad notes during work, but those notes do not change the session status.
|
|
104
|
+
|
|
103
105
|
---
|
|
104
106
|
|
|
105
107
|
### Slash commands reference
|
package/index.ts
CHANGED
|
@@ -188,6 +188,14 @@ const parseCommandFrontmatter = (cmd: string): { template: string; description?:
|
|
|
188
188
|
return { template: match[2], description: frontmatter.description, agent: frontmatter.agent }
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
const statusActions = {
|
|
192
|
+
"echoes-init": "init",
|
|
193
|
+
"echoes-start": "start",
|
|
194
|
+
"echoes-end": "end",
|
|
195
|
+
} as const
|
|
196
|
+
|
|
197
|
+
type StatusAction = (typeof statusActions)[keyof typeof statusActions]
|
|
198
|
+
|
|
191
199
|
const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
192
200
|
const pluginDir = path.dirname(new URL(import.meta.url).pathname)
|
|
193
201
|
|
|
@@ -229,10 +237,11 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
229
237
|
await ensureCommands(directory, commands)
|
|
230
238
|
await ensureSkills(directory, skills)
|
|
231
239
|
|
|
240
|
+
// Sidebar status can change only through the matching user-invoked command.
|
|
241
|
+
const authorizedStatusActions = new Map<string, StatusAction>()
|
|
242
|
+
|
|
232
243
|
const state = await readState(directory)
|
|
233
244
|
state.pluginVersion = await getPluginVersion()
|
|
234
|
-
state.session.started = false
|
|
235
|
-
state.session.saved = false
|
|
236
245
|
state.stats = await collectStats(paths)
|
|
237
246
|
await writeState(directory, state)
|
|
238
247
|
|
|
@@ -244,10 +253,17 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
244
253
|
input.command[name.replace(".md", "")] = { template, description, agent }
|
|
245
254
|
}
|
|
246
255
|
},
|
|
256
|
+
"command.execute.before": async (input) => {
|
|
257
|
+
const command = input.command.replace(/^\//, "") as keyof typeof statusActions
|
|
258
|
+
const action = statusActions[command]
|
|
259
|
+
if (action) {
|
|
260
|
+
authorizedStatusActions.set(input.sessionID, action)
|
|
261
|
+
}
|
|
262
|
+
},
|
|
247
263
|
tool: {
|
|
248
264
|
commit_memory_to_echoes_vault: tool({
|
|
249
265
|
description:
|
|
250
|
-
"Save session memory to EchoesVault.
|
|
266
|
+
"Save final session memory to EchoesVault. This succeeds only after the user explicitly runs /echoes-end; never call it merely because a task is complete.",
|
|
251
267
|
args: {
|
|
252
268
|
dailySummary: tool.schema
|
|
253
269
|
.string()
|
|
@@ -285,7 +301,14 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
285
301
|
.optional()
|
|
286
302
|
.describe("Lines to find and replace in place within EchoesVault/index.md"),
|
|
287
303
|
},
|
|
288
|
-
async execute(args,
|
|
304
|
+
async execute(args, ctx) {
|
|
305
|
+
if (authorizedStatusActions.get(ctx.sessionID) !== "end") {
|
|
306
|
+
return [
|
|
307
|
+
"Final memory was not saved.",
|
|
308
|
+
"Only an explicit user /echoes-end command can save final memory and set the status to Memory Saved.",
|
|
309
|
+
].join("\n")
|
|
310
|
+
}
|
|
311
|
+
|
|
289
312
|
const today = getDateStr()
|
|
290
313
|
|
|
291
314
|
await ensureVaultDirs(paths)
|
|
@@ -334,6 +357,7 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
334
357
|
st.session.lastSave = new Date().toISOString()
|
|
335
358
|
st.stats = await collectStats(paths)
|
|
336
359
|
await writeState(directory, st)
|
|
360
|
+
authorizedStatusActions.delete(ctx.sessionID)
|
|
337
361
|
|
|
338
362
|
return [
|
|
339
363
|
`✅ Memory committed to EchoesVault.`,
|
|
@@ -454,26 +478,36 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
454
478
|
}),
|
|
455
479
|
echoes_activate_vault: tool({
|
|
456
480
|
description:
|
|
457
|
-
"Mark the EchoesVault as activated.
|
|
481
|
+
"Mark the EchoesVault as activated. This succeeds only after the user explicitly runs /echoes-init.",
|
|
458
482
|
args: {},
|
|
459
|
-
async execute(_args,
|
|
483
|
+
async execute(_args, ctx) {
|
|
484
|
+
if (authorizedStatusActions.get(ctx.sessionID) !== "init") {
|
|
485
|
+
return "Vault status was not changed. Only an explicit user /echoes-init command can activate EchoesVault."
|
|
486
|
+
}
|
|
487
|
+
|
|
460
488
|
const st = await readState(directory)
|
|
461
489
|
st.initialized = true
|
|
462
490
|
st.stats = await collectStats(paths)
|
|
463
491
|
await writeState(directory, st)
|
|
492
|
+
authorizedStatusActions.delete(ctx.sessionID)
|
|
464
493
|
return "EchoesVault activated."
|
|
465
494
|
},
|
|
466
495
|
}),
|
|
467
496
|
echoes_start_session: tool({
|
|
468
497
|
description:
|
|
469
|
-
"Mark the current EchoesVault session as started.
|
|
498
|
+
"Mark the current EchoesVault session as started. This succeeds only after the user explicitly runs /echoes-start.",
|
|
470
499
|
args: {},
|
|
471
|
-
async execute(_args,
|
|
500
|
+
async execute(_args, ctx) {
|
|
501
|
+
if (authorizedStatusActions.get(ctx.sessionID) !== "start") {
|
|
502
|
+
return "Vault status was not changed. Only an explicit user /echoes-start command can start an EchoesVault session."
|
|
503
|
+
}
|
|
504
|
+
|
|
472
505
|
const st = await readState(directory)
|
|
473
506
|
st.session.started = true
|
|
474
507
|
st.session.saved = false
|
|
475
508
|
st.session.lastStart = new Date().toISOString()
|
|
476
509
|
await writeState(directory, st)
|
|
510
|
+
authorizedStatusActions.delete(ctx.sessionID)
|
|
477
511
|
return "EchoesVault session started."
|
|
478
512
|
},
|
|
479
513
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "echoes-vault-opencode",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "EchoesVault — persistent memory plugin for OpenCode. Obsidian-style knowledge base with daily logs, encyclopedia pages, and session resumption.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -6,6 +6,8 @@ agent: build
|
|
|
6
6
|
# SYSTEM MESSAGE: Session Distillation (Distill & Save)
|
|
7
7
|
Our current session is coming to an end. Your task is to crystallize the knowledge we've gained today and commit it to EchoesVault.
|
|
8
8
|
|
|
9
|
+
This command is the user's explicit approval to finalize the session. Never invoke the final-memory tool outside this command, including after an ordinary task completion.
|
|
10
|
+
|
|
9
11
|
Adhere to the principle of technical density: we do not need a transcript of our chat. We need dry architectural facts, bug fixes, applied configurations, and explicit decisions. Remember to use `> [!warning] DEPRECATED` tags if we rewrote legacy logic today.
|
|
10
12
|
|
|
11
13
|
## ACTION
|
package/tui.tsx
CHANGED
|
@@ -74,7 +74,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
74
74
|
const statusDesc = () => {
|
|
75
75
|
const s = state()
|
|
76
76
|
if (!s || !s.initialized) return null
|
|
77
|
-
if (s.session.saved) return "
|
|
77
|
+
if (s.session.saved) return "Final memory saved by /echoes-end"
|
|
78
78
|
if (s.session.started) return null
|
|
79
79
|
return null
|
|
80
80
|
}
|