echoes-vault-opencode 1.1.6 → 1.1.8

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.
Files changed (2) hide show
  1. package/package.json +4 -2
  2. package/tui.tsx +103 -114
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "echoes-vault-opencode",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
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",
@@ -28,7 +28,9 @@
28
28
  ],
29
29
  "license": "MIT",
30
30
  "dependencies": {
31
- "@opencode-ai/plugin": ">=1.16.0"
31
+ "@opencode-ai/plugin": ">=1.16.0",
32
+ "@opentui/solid": ">=0.4.3",
33
+ "solid-js": ">=1.9.0"
32
34
  },
33
35
  "devDependencies": {
34
36
  "@types/node": "^22.0.0",
package/tui.tsx CHANGED
@@ -4,14 +4,6 @@ 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
- console.log("[EchoesVault TUI] Module loaded")
8
-
9
- type VaultStats = {
10
- totalPages: number
11
- totalDailyLogs: number
12
- deprecatedPages: number
13
- }
14
-
15
7
  type EchoesState = {
16
8
  version: number
17
9
  pluginVersion: string
@@ -22,134 +14,131 @@ type EchoesState = {
22
14
  lastStart: string | null
23
15
  lastSave: string | null
24
16
  }
25
- stats?: VaultStats
17
+ stats?: {
18
+ totalPages: number
19
+ totalDailyLogs: number
20
+ deprecatedPages: number
21
+ }
26
22
  }
27
23
 
28
24
  const STATE_PATH = path.join(process.cwd(), ".opencode", "echoes-state.json")
29
- console.log("[EchoesVault TUI] STATE_PATH:", STATE_PATH)
30
25
 
31
26
  const readState = (): EchoesState | null => {
32
27
  try {
33
28
  const raw = fs.readFileSync(STATE_PATH, "utf-8")
34
- const parsed = JSON.parse(raw) as EchoesState
35
- console.log("[EchoesVault TUI] State read OK, initialized:", parsed.initialized, "stats:", JSON.stringify(parsed.stats))
36
- return parsed
37
- } catch (e) {
38
- console.log("[EchoesVault TUI] State read failed:", e)
29
+ return JSON.parse(raw) as EchoesState
30
+ } catch {
39
31
  return null
40
32
  }
41
33
  }
42
34
 
43
35
  const tui: TuiPlugin = async (api) => {
44
- console.log("[EchoesVault TUI] tui() called, api.theme available:", !!api.theme)
45
36
  const theme = api.theme.current
46
- console.log("[EchoesVault TUI] theme.current loaded")
47
-
48
- try {
49
- api.slots.register({
50
- slots: {
51
- sidebar_content() {
52
- console.log("[EchoesVault TUI] sidebar_content() rendering")
53
- const [state, setState] = createSignal<EchoesState | null>(readState())
54
-
55
- const interval = setInterval(() => setState(readState()), 3000)
56
- onCleanup(() => clearInterval(interval))
57
-
58
- const statusColor = () => {
59
- const s = state()
60
- if (!s || !s.initialized) return theme.error
61
- if (s.session.saved) return theme.accent
62
- if (s.session.started) return theme.success
63
- return theme.warning
64
- }
65
-
66
- const statusLabel = () => {
67
- const s = state()
68
- if (!s || !s.initialized) return "Not Activated"
69
- if (s.session.saved) return "Memory Saved"
70
- if (s.session.started) return "Active"
71
- return "Session Not Started"
72
- }
73
-
74
- const vaultHealthColor = () => {
75
- const pages = state()?.stats?.totalPages ?? 0
76
- if (pages > 200) return theme.error
77
- if (pages >= 170) return theme.warning
78
- return theme.success
79
- }
80
-
81
- const vaultUsagePercent = () => {
82
- const pages = state()?.stats?.totalPages ?? 0
83
- return Math.round((pages / 200) * 100)
84
- }
85
-
86
- const statusDesc = () => {
87
- const s = state()
88
- if (!s || !s.initialized) return null
89
- if (s.session.saved) return "Vault memorized session data"
90
- if (s.session.started) return null
91
- return null
92
- }
93
-
94
- const statusCmd = () => {
95
- const s = state()
96
- if (!s || !s.initialized) return "/echoes-init"
97
- if (s.session.saved) return null
98
- if (s.session.started) return "/echoes-end"
99
- return "/echoes-start"
100
- }
101
-
102
- const statusCmdHint = () => {
103
- const s = state()
104
- if (!s || !s.initialized) return "to activate vault"
105
- if (s.session.saved) return null
106
- if (s.session.started) return "before closing"
107
- return "to load context"
108
- }
109
-
110
- console.log("[EchoesVault TUI] About to return JSX")
111
37
 
38
+ api.slots.register({
39
+ slots: {
40
+ sidebar_content() {
41
+ const [state, setState] = createSignal<EchoesState | null>(readState())
42
+
43
+ const interval = setInterval(() => setState(readState()), 3000)
44
+ onCleanup(() => clearInterval(interval))
45
+
46
+ const statusColor = () => {
47
+ const s = state()
48
+ if (!s || !s.initialized) return theme.error
49
+ if (s.session.saved) return theme.accent
50
+ if (s.session.started) return theme.success
51
+ return theme.warning
52
+ }
53
+
54
+ const statusLabel = () => {
55
+ const s = state()
56
+ if (!s || !s.initialized) return "Not Activated"
57
+ if (s.session.saved) return "Memory Saved"
58
+ if (s.session.started) return "Active"
59
+ return "Session Not Started"
60
+ }
61
+
62
+ const vaultHealthColor = () => {
63
+ const pages = state()?.stats?.totalPages ?? 0
64
+ if (pages > 200) return theme.error
65
+ if (pages >= 170) return theme.warning
66
+ return theme.success
67
+ }
68
+
69
+ const vaultUsagePercent = () => {
70
+ const pages = state()?.stats?.totalPages ?? 0
71
+ return Math.round((pages / 200) * 100)
72
+ }
73
+
74
+ const statusDesc = () => {
75
+ const s = state()
76
+ if (!s || !s.initialized) return null
77
+ if (s.session.saved) return "Vault memorized session data"
78
+ if (s.session.started) return null
79
+ return null
80
+ }
81
+
82
+ const statusCmd = () => {
83
+ const s = state()
84
+ if (!s || !s.initialized) return "/echoes-init"
85
+ if (s.session.saved) return null
86
+ if (s.session.started) return "/echoes-end"
87
+ return "/echoes-start"
88
+ }
89
+
90
+ const statusCmdHint = () => {
91
+ const s = state()
92
+ if (!s || !s.initialized) return "to activate vault"
93
+ if (s.session.saved) return null
94
+ if (s.session.started) return "before closing"
95
+ return "to load context"
96
+ }
97
+
98
+ const vaultHealthSection = () => {
99
+ const s = state()
100
+ if (!s || !s.initialized) return null
101
+ const pages = s.stats?.totalPages ?? 0
112
102
  return (
113
103
  <box flexDirection="column">
114
104
  <box flexDirection="row">
115
- <text fg={statusColor()}><b>• </b></text>
116
- <text fg={theme.textMuted}><b>Echoes</b></text>
117
- <text fg={theme.text}><b>Vault</b></text>
118
- <text fg={theme.textMuted}> v{state()?.pluginVersion ?? ""}</text>
105
+ <text fg={vaultHealthColor()}>{"• "}</text>
106
+ <text fg={theme.text}><b>Vault Health</b></text>
119
107
  </box>
120
- <text fg={statusColor()}>{statusLabel()}</text>
121
- {statusDesc() && (
122
- <text fg={theme.textMuted}>{statusDesc()}</text>
123
- )}
124
- {statusCmd() && (
125
- <box flexDirection="row">
126
- <text fg={theme.textMuted}>Run </text>
127
- <text fg={theme.text}>{statusCmd()}</text>
128
- <text fg={theme.textMuted}> {statusCmdHint()}</text>
129
- </box>
130
- )}
131
- {state()?.initialized ? (
132
- <box flexDirection="column">
133
- <box flexDirection="row">
134
- <text fg={vaultHealthColor()}>{"• "}</text>
135
- <text fg={theme.text}><b>Vault Health</b></text>
136
- </box>
137
- <text fg={theme.textMuted}>{" Pages: "}{state()?.stats?.totalPages ?? 0}</text>
138
- <text fg={theme.textMuted}>{" Usage: "}{vaultUsagePercent()}{"%"}</text>
139
- {(state()?.stats?.totalPages ?? 0) > 200 ? (
140
- <text fg={theme.textMuted}>{" Consider migrating to RAG"}</text>
141
- ) : null}
142
- </box>
108
+ <text fg={theme.textMuted}>{" Pages: "}{pages}</text>
109
+ <text fg={theme.textMuted}>{" Usage: "}{vaultUsagePercent()}{"%"}</text>
110
+ {pages > 200 ? (
111
+ <text fg={theme.textMuted}>{" Consider migrating to RAG"}</text>
143
112
  ) : null}
144
113
  </box>
145
114
  )
146
- },
115
+ }
116
+
117
+ return (
118
+ <box flexDirection="column">
119
+ <box flexDirection="row">
120
+ <text fg={statusColor()}><b>• </b></text>
121
+ <text fg={theme.textMuted}><b>Echoes</b></text>
122
+ <text fg={theme.text}><b>Vault</b></text>
123
+ <text fg={theme.textMuted}> v{state()?.pluginVersion ?? ""}</text>
124
+ </box>
125
+ <text fg={statusColor()}>{statusLabel()}</text>
126
+ {statusDesc() && (
127
+ <text fg={theme.textMuted}>{statusDesc()}</text>
128
+ )}
129
+ {statusCmd() && (
130
+ <box flexDirection="row">
131
+ <text fg={theme.textMuted}>Run </text>
132
+ <text fg={theme.text}>{statusCmd()}</text>
133
+ <text fg={theme.textMuted}> {statusCmdHint()}</text>
134
+ </box>
135
+ )}
136
+ {vaultHealthSection()}
137
+ </box>
138
+ )
147
139
  },
148
- })
149
- console.log("[EchoesVault TUI] slots.register() OK")
150
- } catch (e) {
151
- console.error("[EchoesVault TUI] slots.register() FAILED:", e)
152
- }
140
+ },
141
+ })
153
142
  }
154
143
 
155
144
  export default { id: "echoes-vault-ui", tui }