opencode-mask-j0k3r-dev-rgl 2.0.15 → 2.0.16

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 (3) hide show
  1. package/components.tsx +55 -27
  2. package/package.json +1 -1
  3. package/tui.tsx +2 -0
package/components.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  // @ts-nocheck
2
2
  /** @jsxImportSource @opentui/solid */
3
3
  import type { TuiThemeCurrent, TuiSidebarFileItem, TuiSidebarMcpItem, TuiSidebarLspItem, TuiSidebarTodoItem } from "@opencode-ai/plugin/tui"
4
+ import type { Message } from "@opencode-ai/sdk/v2"
4
5
  import type { Cfg } from "./config"
5
6
  import { getOSName, getProviders } from "./detection"
6
7
  import {
@@ -48,7 +49,6 @@ export const HomeLogo = (props: { theme: TuiThemeCurrent }) => {
48
49
  }
49
50
 
50
51
  // ─── Progress bar helper ──────────────────────────────────────────────────────
51
- // Renders a ASCII bar like: [████░░░░░░] 40%
52
52
  const ProgressBar = (props: {
53
53
  value: number // 0–100
54
54
  width?: number
@@ -83,32 +83,52 @@ export const SidebarArch = (props: {
83
83
  mcpItems?: ReadonlyArray<TuiSidebarMcpItem>
84
84
  lspItems?: ReadonlyArray<TuiSidebarLspItem>
85
85
  todos?: ReadonlyArray<TuiSidebarTodoItem>
86
+ messages?: ReadonlyArray<Message>
86
87
  }) => {
87
88
  if (!props.config.show_sidebar) return null
88
89
 
89
90
  const t = props.theme
90
91
 
91
- // ── Stats ─────────────────────────────────────────────────────────────────
92
+ // ── Files ─────────────────────────────────────────────────────────────────
92
93
  const files = props.files ?? []
93
- const todos = props.todos ?? []
94
- const mcpItems = props.mcpItems ?? []
95
- const lspItems = props.lspItems ?? []
96
-
97
94
  const totalAdditions = files.reduce((s, f) => s + f.additions, 0)
98
95
  const totalDeletions = files.reduce((s, f) => s + f.deletions, 0)
99
96
  const totalChanges = totalAdditions + totalDeletions
100
97
 
98
+ // ── Todos ─────────────────────────────────────────────────────────────────
99
+ const todos = props.todos ?? []
101
100
  const doneTodos = todos.filter(t => t.status === "completed").length
102
101
  const totalTodos = todos.length
103
102
  const todoPct = totalTodos > 0 ? Math.round((doneTodos / totalTodos) * 100) : 0
104
103
 
104
+ // ── MCP ───────────────────────────────────────────────────────────────────
105
+ const mcpItems = props.mcpItems ?? []
105
106
  const mcpConnected = mcpItems.filter(m => m.status === "connected").length
106
107
  const mcpTotal = mcpItems.length
107
108
  const mcpPct = mcpTotal > 0 ? Math.round((mcpConnected / mcpTotal) * 100) : 0
108
109
 
110
+ // ── LSP ───────────────────────────────────────────────────────────────────
111
+ const lspItems = props.lspItems ?? []
109
112
  const lspActive = lspItems.filter(l => l.status === "idle" || l.status === "running").length
110
113
  const lspTotal = lspItems.length
111
114
 
115
+ // ── Tokens & Cost — sumados de los AssistantMessages ─────────────────────
116
+ const messages = props.messages ?? []
117
+ const assistantMsgs = messages.filter(m => m.role === "assistant")
118
+ const totalTokens = assistantMsgs.reduce((s, m) => s + (m.tokens?.total ?? (m.tokens?.input ?? 0) + (m.tokens?.output ?? 0)), 0)
119
+ const totalCost = assistantMsgs.reduce((s, m) => s + (m.cost ?? 0), 0)
120
+
121
+ // Context window: OpenCode muestra "% used" basado en el modelo.
122
+ // Usamos 200_000 como referencia (Claude 3.5 Sonnet / GPT-4o max).
123
+ const CONTEXT_LIMIT = 200_000
124
+ const contextPct = Math.min(100, Math.round((totalTokens / CONTEXT_LIMIT) * 100))
125
+
126
+ const fmtTokens = (n: number) => n >= 1000 ? `${(n / 1000).toFixed(1)}k` : `${n}`
127
+ const fmtCost = (n: number) => `$${n.toFixed(2)}`
128
+
129
+ // Color del context bar: verde → amarillo → rojo según el %
130
+ const ctxColor = contextPct < 50 ? "#00e5a0" : contextPct < 80 ? "#ffd166" : "#ff2d78"
131
+
112
132
  return (
113
133
  <box flexDirection="column" alignItems="center">
114
134
 
@@ -130,12 +150,32 @@ export const SidebarArch = (props: {
130
150
  </box>
131
151
  )}
132
152
 
133
- {/* Files changed bar */}
153
+ {/* ── Context (tokens + cost) ── */}
154
+ {totalTokens > 0 && (
155
+ <box flexDirection="column" marginTop={1}>
156
+ <text fg={t.textMuted} bold={true}>Context</text>
157
+ <box flexDirection="row" gap={1}>
158
+ <text fg={t.text}>{fmtTokens(totalTokens)}</text>
159
+ <text fg={t.textMuted}>tokens</text>
160
+ </box>
161
+ <ProgressBar value={contextPct} width={12} fillColor={ctxColor} emptyColor="#3a3a3a" theme={t} />
162
+ <box flexDirection="row" gap={1}>
163
+ <text fg={ctxColor}>{contextPct}%</text>
164
+ <text fg={t.textMuted}>used</text>
165
+ </box>
166
+ <box flexDirection="row" gap={1}>
167
+ <text fg="#ffd166">{fmtCost(totalCost)}</text>
168
+ <text fg={t.textMuted}>spent</text>
169
+ </box>
170
+ </box>
171
+ )}
172
+
173
+ {/* ── Files changed ── */}
134
174
  {totalChanges > 0 && (
135
175
  <box flexDirection="column" marginTop={1}>
136
176
  <box flexDirection="row" gap={1}>
137
177
  <text fg={t.textMuted}>files</text>
138
- <text fg={t.textMuted}>{files.length}</text>
178
+ <text fg={t.text}>{files.length}</text>
139
179
  </box>
140
180
  <box flexDirection="row" gap={0}>
141
181
  <text fg="#00e5a0">+{totalAdditions} </text>
@@ -151,41 +191,29 @@ export const SidebarArch = (props: {
151
191
  </box>
152
192
  )}
153
193
 
154
- {/* Todos bar */}
194
+ {/* ── Todos ── */}
155
195
  {totalTodos > 0 && (
156
196
  <box flexDirection="column" marginTop={1}>
157
197
  <box flexDirection="row" gap={1}>
158
198
  <text fg={t.textMuted}>todos</text>
159
- <text fg={t.textMuted}>{doneTodos}/{totalTodos}</text>
199
+ <text fg={t.text}>{doneTodos}/{totalTodos}</text>
160
200
  </box>
161
- <ProgressBar
162
- value={todoPct}
163
- width={12}
164
- fillColor="#9d4edd"
165
- emptyColor="#3a3a3a"
166
- theme={t}
167
- />
201
+ <ProgressBar value={todoPct} width={12} fillColor="#9d4edd" emptyColor="#3a3a3a" theme={t} />
168
202
  </box>
169
203
  )}
170
204
 
171
- {/* MCP bar */}
205
+ {/* ── MCP ── */}
172
206
  {mcpTotal > 0 && (
173
207
  <box flexDirection="column" marginTop={1}>
174
208
  <box flexDirection="row" gap={1}>
175
209
  <text fg={t.textMuted}>mcp</text>
176
- <text fg={t.textMuted}>{mcpConnected}/{mcpTotal}</text>
210
+ <text fg={t.text}>{mcpConnected}/{mcpTotal}</text>
177
211
  </box>
178
- <ProgressBar
179
- value={mcpPct}
180
- width={12}
181
- fillColor="#00c8ff"
182
- emptyColor="#3a3a3a"
183
- theme={t}
184
- />
212
+ <ProgressBar value={mcpPct} width={12} fillColor="#00c8ff" emptyColor="#3a3a3a" theme={t} />
185
213
  </box>
186
214
  )}
187
215
 
188
- {/* LSP status */}
216
+ {/* ── LSP ── */}
189
217
  {lspTotal > 0 && (
190
218
  <box flexDirection="row" gap={1} marginTop={1}>
191
219
  <text fg={t.textMuted}>lsp</text>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "opencode-mask-j0k3r-dev-rgl",
4
- "version": "2.0.15",
4
+ "version": "2.0.16",
5
5
  "description": "Arch Linux TUI mask for OpenCode — hot pink theme with prominent ASCII logo and j0k3r-dev-rgl@latest legend",
6
6
  "type": "module",
7
7
  "exports": {
package/tui.tsx CHANGED
@@ -44,6 +44,7 @@ const tui: TuiPlugin = async (api, options) => {
44
44
  const branch = api.state.vcs?.branch
45
45
  const files = sessionID ? api.state.session.diff(sessionID) : []
46
46
  const todos = sessionID ? api.state.session.todo(sessionID) : []
47
+ const messages = sessionID ? api.state.session.messages(sessionID) : []
47
48
  const mcpItems = api.state.mcp()
48
49
  const lspItems = api.state.lsp()
49
50
 
@@ -55,6 +56,7 @@ const tui: TuiPlugin = async (api, options) => {
55
56
  branch={branch}
56
57
  files={files}
57
58
  todos={todos}
59
+ messages={messages}
58
60
  mcpItems={mcpItems}
59
61
  lspItems={lspItems}
60
62
  />