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

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 +54 -39
  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,62 +150,57 @@ export const SidebarArch = (props: {
130
150
  </box>
131
151
  )}
132
152
 
133
- {/* Files changed bar */}
134
- {totalChanges > 0 && (
153
+ {/* ── Context (tokens + % used + cost) ── */}
154
+ {totalTokens > 0 && (
135
155
  <box flexDirection="column" marginTop={1}>
156
+ <text fg={t.textMuted} bold={true}>Context</text>
157
+
158
+ {/* tokens */}
159
+ <box flexDirection="row" gap={1}>
160
+ <text fg={t.text}>{fmtTokens(totalTokens)}</text>
161
+ <text fg={t.textMuted}>tokens</text>
162
+ </box>
163
+ <ProgressBar value={contextPct} width={12} fillColor={ctxColor} emptyColor="#3a3a3a" theme={t} />
164
+
165
+ {/* % used */}
136
166
  <box flexDirection="row" gap={1}>
137
- <text fg={t.textMuted}>files</text>
138
- <text fg={t.textMuted}>{files.length}</text>
167
+ <text fg={ctxColor}>{contextPct}%</text>
168
+ <text fg={t.textMuted}>used</text>
139
169
  </box>
140
- <box flexDirection="row" gap={0}>
141
- <text fg="#00e5a0">+{totalAdditions} </text>
142
- <text fg="#ff2d78">-{totalDeletions}</text>
170
+ <ProgressBar value={contextPct} width={12} fillColor={ctxColor} emptyColor="#3a3a3a" theme={t} />
171
+
172
+ {/* $ spent */}
173
+ <box flexDirection="row" gap={1}>
174
+ <text fg="#ffd166">{fmtCost(totalCost)}</text>
175
+ <text fg={t.textMuted}>spent</text>
143
176
  </box>
144
- <ProgressBar
145
- value={totalChanges > 0 ? Math.min(100, (totalAdditions / totalChanges) * 100) : 0}
146
- width={12}
147
- fillColor="#00e5a0"
148
- emptyColor="#ff2d78"
149
- theme={t}
150
- />
177
+ <ProgressBar value={Math.min(100, totalCost * 100)} width={12} fillColor="#ffd166" emptyColor="#3a3a3a" theme={t} />
151
178
  </box>
152
179
  )}
153
180
 
154
- {/* Todos bar */}
181
+ {/* ── Todos ── */}
155
182
  {totalTodos > 0 && (
156
183
  <box flexDirection="column" marginTop={1}>
157
184
  <box flexDirection="row" gap={1}>
158
185
  <text fg={t.textMuted}>todos</text>
159
- <text fg={t.textMuted}>{doneTodos}/{totalTodos}</text>
186
+ <text fg={t.text}>{doneTodos}/{totalTodos}</text>
160
187
  </box>
161
- <ProgressBar
162
- value={todoPct}
163
- width={12}
164
- fillColor="#9d4edd"
165
- emptyColor="#3a3a3a"
166
- theme={t}
167
- />
188
+ <ProgressBar value={todoPct} width={12} fillColor="#9d4edd" emptyColor="#3a3a3a" theme={t} />
168
189
  </box>
169
190
  )}
170
191
 
171
- {/* MCP bar */}
192
+ {/* ── MCP ── */}
172
193
  {mcpTotal > 0 && (
173
194
  <box flexDirection="column" marginTop={1}>
174
195
  <box flexDirection="row" gap={1}>
175
196
  <text fg={t.textMuted}>mcp</text>
176
- <text fg={t.textMuted}>{mcpConnected}/{mcpTotal}</text>
197
+ <text fg={t.text}>{mcpConnected}/{mcpTotal}</text>
177
198
  </box>
178
- <ProgressBar
179
- value={mcpPct}
180
- width={12}
181
- fillColor="#00c8ff"
182
- emptyColor="#3a3a3a"
183
- theme={t}
184
- />
199
+ <ProgressBar value={mcpPct} width={12} fillColor="#00c8ff" emptyColor="#3a3a3a" theme={t} />
185
200
  </box>
186
201
  )}
187
202
 
188
- {/* LSP status */}
203
+ {/* ── LSP ── */}
189
204
  {lspTotal > 0 && (
190
205
  <box flexDirection="row" gap={1} marginTop={1}>
191
206
  <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.17",
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
  />