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.
- package/components.tsx +55 -27
- package/package.json +1 -1
- 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
|
-
// ──
|
|
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
|
-
{/*
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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
|
/>
|