echoes-vault-opencode 1.0.38 → 1.1.1
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/index.ts +40 -0
- package/package.json +1 -1
- package/tui.tsx +35 -0
package/index.ts
CHANGED
|
@@ -19,10 +19,17 @@ type VaultPaths = {
|
|
|
19
19
|
assets: string
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
type VaultStats = {
|
|
23
|
+
totalPages: number
|
|
24
|
+
totalDailyLogs: number
|
|
25
|
+
deprecatedPages: number
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
type EchoesState = {
|
|
23
29
|
version: number
|
|
24
30
|
pluginVersion: string
|
|
25
31
|
initialized: boolean
|
|
32
|
+
stats: VaultStats
|
|
26
33
|
session: {
|
|
27
34
|
started: boolean
|
|
28
35
|
saved: boolean
|
|
@@ -47,6 +54,7 @@ const defaultState = (): EchoesState => ({
|
|
|
47
54
|
version: 1,
|
|
48
55
|
pluginVersion: "0.0.0",
|
|
49
56
|
initialized: false,
|
|
57
|
+
stats: { totalPages: 0, totalDailyLogs: 0, deprecatedPages: 0 },
|
|
50
58
|
session: {
|
|
51
59
|
started: false,
|
|
52
60
|
saved: false,
|
|
@@ -55,6 +63,32 @@ const defaultState = (): EchoesState => ({
|
|
|
55
63
|
},
|
|
56
64
|
})
|
|
57
65
|
|
|
66
|
+
const collectStats = async (vaultPaths: VaultPaths): Promise<VaultStats> => {
|
|
67
|
+
let totalPages = 0
|
|
68
|
+
let deprecatedPages = 0
|
|
69
|
+
let totalDailyLogs = 0
|
|
70
|
+
try {
|
|
71
|
+
const pageFiles = (await fs.readdir(vaultPaths.pages)).filter((f) => f.endsWith(".md"))
|
|
72
|
+
totalPages = pageFiles.length
|
|
73
|
+
for (const file of pageFiles) {
|
|
74
|
+
const content = await fs.readFile(path.join(vaultPaths.pages, file), "utf-8")
|
|
75
|
+
if (content.includes("> [!warning] DEPRECATED")) {
|
|
76
|
+
deprecatedPages++
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} catch { /* pages dir may not exist */ }
|
|
80
|
+
try {
|
|
81
|
+
totalDailyLogs = (await fs.readdir(vaultPaths.daily)).filter((f) => f.endsWith(".md")).length
|
|
82
|
+
} catch { /* daily dir may not exist */ }
|
|
83
|
+
return { totalPages, totalDailyLogs, deprecatedPages }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const updateStats = async (directory: string, vaultPaths: VaultPaths): Promise<void> => {
|
|
87
|
+
const st = await readState(directory)
|
|
88
|
+
st.stats = await collectStats(vaultPaths)
|
|
89
|
+
await writeState(directory, st)
|
|
90
|
+
}
|
|
91
|
+
|
|
58
92
|
const readState = async (directory: string): Promise<EchoesState> => {
|
|
59
93
|
try {
|
|
60
94
|
const raw = await fs.readFile(path.join(directory, STATE_FILENAME), "utf-8")
|
|
@@ -373,6 +407,7 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
373
407
|
|
|
374
408
|
const state = await readState(directory)
|
|
375
409
|
state.pluginVersion = await getPluginVersion()
|
|
410
|
+
state.stats = await collectStats(paths)
|
|
376
411
|
state.session.started = false
|
|
377
412
|
state.session.saved = false
|
|
378
413
|
await writeState(directory, state)
|
|
@@ -479,6 +514,7 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
479
514
|
const st = await readState(directory)
|
|
480
515
|
st.session.saved = true
|
|
481
516
|
st.session.lastSave = new Date().toISOString()
|
|
517
|
+
st.stats = await collectStats(paths)
|
|
482
518
|
await writeState(directory, st)
|
|
483
519
|
|
|
484
520
|
return [
|
|
@@ -506,6 +542,7 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
506
542
|
const timestamp = new Date().toISOString()
|
|
507
543
|
const entry = `### Scratchpad — ${timestamp}\n\n${args.logEntry}\n\n`
|
|
508
544
|
await fs.appendFile(dailyFile, entry)
|
|
545
|
+
await updateStats(directory, paths)
|
|
509
546
|
return `✅ Scratchpad note saved to EchoesVault/daily/${today}.md`
|
|
510
547
|
},
|
|
511
548
|
}),
|
|
@@ -587,6 +624,8 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
587
624
|
}
|
|
588
625
|
}
|
|
589
626
|
|
|
627
|
+
await updateStats(directory, paths)
|
|
628
|
+
|
|
590
629
|
const action = existed ? "updated" : "created"
|
|
591
630
|
const parts = [`✅ Page ${action}: EchoesVault/pages/${fileName}`]
|
|
592
631
|
if (!existed && args.indexDescription) {
|
|
@@ -602,6 +641,7 @@ const OpenCodeEchoes: Plugin = async ({ directory }) => {
|
|
|
602
641
|
async execute(_args, _ctx) {
|
|
603
642
|
const st = await readState(directory)
|
|
604
643
|
st.initialized = true
|
|
644
|
+
st.stats = await collectStats(paths)
|
|
605
645
|
await writeState(directory, st)
|
|
606
646
|
return "EchoesVault activated."
|
|
607
647
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "echoes-vault-opencode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
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",
|
package/tui.tsx
CHANGED
|
@@ -4,10 +4,17 @@ import { createSignal, onCleanup } from "solid-js"
|
|
|
4
4
|
import * as fs from "node:fs"
|
|
5
5
|
import * as path from "node:path"
|
|
6
6
|
|
|
7
|
+
type VaultStats = {
|
|
8
|
+
totalPages: number
|
|
9
|
+
totalDailyLogs: number
|
|
10
|
+
deprecatedPages: number
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
type EchoesState = {
|
|
8
14
|
version: number
|
|
9
15
|
pluginVersion: string
|
|
10
16
|
initialized: boolean
|
|
17
|
+
stats: VaultStats
|
|
11
18
|
session: {
|
|
12
19
|
started: boolean
|
|
13
20
|
saved: boolean
|
|
@@ -16,6 +23,9 @@ type EchoesState = {
|
|
|
16
23
|
}
|
|
17
24
|
}
|
|
18
25
|
|
|
26
|
+
const CAPACITY_LIMIT = 200
|
|
27
|
+
const CAPACITY_WARNING = 170
|
|
28
|
+
|
|
19
29
|
const STATE_PATH = path.join(process.cwd(), ".opencode", "echoes-state.json")
|
|
20
30
|
|
|
21
31
|
const readState = (): EchoesState | null => {
|
|
@@ -78,6 +88,17 @@ const tui: TuiPlugin = async (api) => {
|
|
|
78
88
|
return "to load context"
|
|
79
89
|
}
|
|
80
90
|
|
|
91
|
+
const pages = () => state()?.stats?.totalPages ?? 0
|
|
92
|
+
|
|
93
|
+
const capacityColor = () => {
|
|
94
|
+
const p = pages()
|
|
95
|
+
if (p > CAPACITY_LIMIT) return theme.error
|
|
96
|
+
if (p > CAPACITY_WARNING) return theme.warning
|
|
97
|
+
return theme.success
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const capacityPercent = () => Math.round((pages() / CAPACITY_LIMIT) * 100)
|
|
101
|
+
|
|
81
102
|
return (
|
|
82
103
|
<box flexDirection="column">
|
|
83
104
|
<box flexDirection="row">
|
|
@@ -97,6 +118,20 @@ const tui: TuiPlugin = async (api) => {
|
|
|
97
118
|
<text fg={theme.textMuted}> {statusCmdHint()}</text>
|
|
98
119
|
</box>
|
|
99
120
|
)}
|
|
121
|
+
{state()?.initialized && (
|
|
122
|
+
<box flexDirection="column">
|
|
123
|
+
<text> </text>
|
|
124
|
+
<box flexDirection="row">
|
|
125
|
+
<text fg={capacityColor()}><b>• </b></text>
|
|
126
|
+
<text fg={theme.text}><b>Vault Capacity</b></text>
|
|
127
|
+
</box>
|
|
128
|
+
<text fg={theme.textMuted}>Pages: {pages()}</text>
|
|
129
|
+
<text fg={theme.textMuted}>Usage: {capacityPercent()}%</text>
|
|
130
|
+
{pages() > CAPACITY_LIMIT && (
|
|
131
|
+
<text fg={theme.textMuted}>Consider migrating to RAG</text>
|
|
132
|
+
)}
|
|
133
|
+
</box>
|
|
134
|
+
)}
|
|
100
135
|
</box>
|
|
101
136
|
)
|
|
102
137
|
},
|