opencode-mask-j0k3r-dev-rgl 2.0.14 → 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 +166 -10
- package/package.json +1 -1
- package/tui.tsx +23 -3
package/components.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
/** @jsxImportSource @opentui/solid */
|
|
3
|
-
import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui"
|
|
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 {
|
|
@@ -17,14 +18,12 @@ export const HomeLogo = (props: { theme: TuiThemeCurrent }) => {
|
|
|
17
18
|
|
|
18
19
|
return (
|
|
19
20
|
<box flexDirection="column" alignItems="center">
|
|
20
|
-
{/* Arch Linux logo — zone-colored */}
|
|
21
21
|
{archLogoHome.map((line, i) => {
|
|
22
22
|
const zone = homeLogoZones[i]
|
|
23
23
|
const color = zoneColors[zone] || t.primary
|
|
24
24
|
return <text fg={color}>{line}</text>
|
|
25
25
|
})}
|
|
26
26
|
|
|
27
|
-
{/* Legend: j0k3r-dev-rgl@latest */}
|
|
28
27
|
<text> </text>
|
|
29
28
|
<box flexDirection="row" gap={0}>
|
|
30
29
|
<text fg="#ff2d78" bold={true}>j0k3r</text>
|
|
@@ -36,7 +35,6 @@ export const HomeLogo = (props: { theme: TuiThemeCurrent }) => {
|
|
|
36
35
|
<text fg="#ffd166" bold={true}>latest</text>
|
|
37
36
|
</box>
|
|
38
37
|
|
|
39
|
-
{/* Subtle separator */}
|
|
40
38
|
<box flexDirection="row" gap={0} marginTop={1}>
|
|
41
39
|
<text fg={t.textMuted} dimColor={true}>╭ </text>
|
|
42
40
|
<text fg={t.textMuted}>arch linux </text>
|
|
@@ -50,21 +48,179 @@ export const HomeLogo = (props: { theme: TuiThemeCurrent }) => {
|
|
|
50
48
|
)
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
// ───
|
|
54
|
-
|
|
51
|
+
// ─── Progress bar helper ──────────────────────────────────────────────────────
|
|
52
|
+
const ProgressBar = (props: {
|
|
53
|
+
value: number // 0–100
|
|
54
|
+
width?: number
|
|
55
|
+
fillColor: string
|
|
56
|
+
emptyColor: string
|
|
57
|
+
theme: TuiThemeCurrent
|
|
58
|
+
}) => {
|
|
59
|
+
const width = props.width ?? 12
|
|
60
|
+
const pct = Math.max(0, Math.min(100, props.value))
|
|
61
|
+
const filled = Math.round((pct / 100) * width)
|
|
62
|
+
const empty = width - filled
|
|
63
|
+
const fill = "█".repeat(filled)
|
|
64
|
+
const trail = "░".repeat(empty)
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<box flexDirection="row" gap={0}>
|
|
68
|
+
<text fg={props.theme.textMuted}>[</text>
|
|
69
|
+
<text fg={props.fillColor}>{fill}</text>
|
|
70
|
+
<text fg={props.emptyColor}>{trail}</text>
|
|
71
|
+
<text fg={props.theme.textMuted}>]</text>
|
|
72
|
+
</box>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ─── Sidebar: Arch logo + stats panel ────────────────────────────────────────
|
|
77
|
+
export const SidebarArch = (props: {
|
|
78
|
+
theme: TuiThemeCurrent
|
|
79
|
+
config: Cfg
|
|
80
|
+
sessionID?: string
|
|
81
|
+
branch?: string
|
|
82
|
+
files?: ReadonlyArray<TuiSidebarFileItem>
|
|
83
|
+
mcpItems?: ReadonlyArray<TuiSidebarMcpItem>
|
|
84
|
+
lspItems?: ReadonlyArray<TuiSidebarLspItem>
|
|
85
|
+
todos?: ReadonlyArray<TuiSidebarTodoItem>
|
|
86
|
+
messages?: ReadonlyArray<Message>
|
|
87
|
+
}) => {
|
|
55
88
|
if (!props.config.show_sidebar) return null
|
|
56
89
|
|
|
90
|
+
const t = props.theme
|
|
91
|
+
|
|
92
|
+
// ── Files ─────────────────────────────────────────────────────────────────
|
|
93
|
+
const files = props.files ?? []
|
|
94
|
+
const totalAdditions = files.reduce((s, f) => s + f.additions, 0)
|
|
95
|
+
const totalDeletions = files.reduce((s, f) => s + f.deletions, 0)
|
|
96
|
+
const totalChanges = totalAdditions + totalDeletions
|
|
97
|
+
|
|
98
|
+
// ── Todos ─────────────────────────────────────────────────────────────────
|
|
99
|
+
const todos = props.todos ?? []
|
|
100
|
+
const doneTodos = todos.filter(t => t.status === "completed").length
|
|
101
|
+
const totalTodos = todos.length
|
|
102
|
+
const todoPct = totalTodos > 0 ? Math.round((doneTodos / totalTodos) * 100) : 0
|
|
103
|
+
|
|
104
|
+
// ── MCP ───────────────────────────────────────────────────────────────────
|
|
105
|
+
const mcpItems = props.mcpItems ?? []
|
|
106
|
+
const mcpConnected = mcpItems.filter(m => m.status === "connected").length
|
|
107
|
+
const mcpTotal = mcpItems.length
|
|
108
|
+
const mcpPct = mcpTotal > 0 ? Math.round((mcpConnected / mcpTotal) * 100) : 0
|
|
109
|
+
|
|
110
|
+
// ── LSP ───────────────────────────────────────────────────────────────────
|
|
111
|
+
const lspItems = props.lspItems ?? []
|
|
112
|
+
const lspActive = lspItems.filter(l => l.status === "idle" || l.status === "running").length
|
|
113
|
+
const lspTotal = lspItems.length
|
|
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
|
+
|
|
57
132
|
return (
|
|
58
133
|
<box flexDirection="column" alignItems="center">
|
|
59
|
-
|
|
134
|
+
|
|
135
|
+
{/* Mini Arch logo */}
|
|
60
136
|
{archLogoSidebar.map((line, i) => {
|
|
61
137
|
const zone = sidebarLogoZones[i]
|
|
62
|
-
const color = zoneColors[zone] ||
|
|
138
|
+
const color = zoneColors[zone] || t.primary
|
|
63
139
|
return <text fg={color}>{line}</text>
|
|
64
140
|
})}
|
|
65
141
|
|
|
66
|
-
{
|
|
67
|
-
<text
|
|
142
|
+
<text fg={t.textMuted}>j0k3r@latest</text>
|
|
143
|
+
<text> </text>
|
|
144
|
+
|
|
145
|
+
{/* Git branch */}
|
|
146
|
+
{props.branch && (
|
|
147
|
+
<box flexDirection="row" gap={1}>
|
|
148
|
+
<text fg="#ffd166">⎇</text>
|
|
149
|
+
<text fg={t.text}>{props.branch}</text>
|
|
150
|
+
</box>
|
|
151
|
+
)}
|
|
152
|
+
|
|
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 ── */}
|
|
174
|
+
{totalChanges > 0 && (
|
|
175
|
+
<box flexDirection="column" marginTop={1}>
|
|
176
|
+
<box flexDirection="row" gap={1}>
|
|
177
|
+
<text fg={t.textMuted}>files</text>
|
|
178
|
+
<text fg={t.text}>{files.length}</text>
|
|
179
|
+
</box>
|
|
180
|
+
<box flexDirection="row" gap={0}>
|
|
181
|
+
<text fg="#00e5a0">+{totalAdditions} </text>
|
|
182
|
+
<text fg="#ff2d78">-{totalDeletions}</text>
|
|
183
|
+
</box>
|
|
184
|
+
<ProgressBar
|
|
185
|
+
value={totalChanges > 0 ? Math.min(100, (totalAdditions / totalChanges) * 100) : 0}
|
|
186
|
+
width={12}
|
|
187
|
+
fillColor="#00e5a0"
|
|
188
|
+
emptyColor="#ff2d78"
|
|
189
|
+
theme={t}
|
|
190
|
+
/>
|
|
191
|
+
</box>
|
|
192
|
+
)}
|
|
193
|
+
|
|
194
|
+
{/* ── Todos ── */}
|
|
195
|
+
{totalTodos > 0 && (
|
|
196
|
+
<box flexDirection="column" marginTop={1}>
|
|
197
|
+
<box flexDirection="row" gap={1}>
|
|
198
|
+
<text fg={t.textMuted}>todos</text>
|
|
199
|
+
<text fg={t.text}>{doneTodos}/{totalTodos}</text>
|
|
200
|
+
</box>
|
|
201
|
+
<ProgressBar value={todoPct} width={12} fillColor="#9d4edd" emptyColor="#3a3a3a" theme={t} />
|
|
202
|
+
</box>
|
|
203
|
+
)}
|
|
204
|
+
|
|
205
|
+
{/* ── MCP ── */}
|
|
206
|
+
{mcpTotal > 0 && (
|
|
207
|
+
<box flexDirection="column" marginTop={1}>
|
|
208
|
+
<box flexDirection="row" gap={1}>
|
|
209
|
+
<text fg={t.textMuted}>mcp</text>
|
|
210
|
+
<text fg={t.text}>{mcpConnected}/{mcpTotal}</text>
|
|
211
|
+
</box>
|
|
212
|
+
<ProgressBar value={mcpPct} width={12} fillColor="#00c8ff" emptyColor="#3a3a3a" theme={t} />
|
|
213
|
+
</box>
|
|
214
|
+
)}
|
|
215
|
+
|
|
216
|
+
{/* ── LSP ── */}
|
|
217
|
+
{lspTotal > 0 && (
|
|
218
|
+
<box flexDirection="row" gap={1} marginTop={1}>
|
|
219
|
+
<text fg={t.textMuted}>lsp</text>
|
|
220
|
+
<text fg={lspActive > 0 ? "#00e5a0" : "#555555"}>{lspActive}/{lspTotal}</text>
|
|
221
|
+
</box>
|
|
222
|
+
)}
|
|
223
|
+
|
|
68
224
|
<text> </text>
|
|
69
225
|
</box>
|
|
70
226
|
)
|
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
|
@@ -38,9 +38,29 @@ const tui: TuiPlugin = async (api, options) => {
|
|
|
38
38
|
return <DetectedEnv theme={ctx.theme.current} providers={api.state.provider} config={boot} />
|
|
39
39
|
},
|
|
40
40
|
|
|
41
|
-
// Sidebar:
|
|
42
|
-
sidebar_content(ctx) {
|
|
43
|
-
|
|
41
|
+
// Sidebar: Arch logo + live stats with progress bars
|
|
42
|
+
sidebar_content(ctx, value) {
|
|
43
|
+
const sessionID = value?.session_id
|
|
44
|
+
const branch = api.state.vcs?.branch
|
|
45
|
+
const files = sessionID ? api.state.session.diff(sessionID) : []
|
|
46
|
+
const todos = sessionID ? api.state.session.todo(sessionID) : []
|
|
47
|
+
const messages = sessionID ? api.state.session.messages(sessionID) : []
|
|
48
|
+
const mcpItems = api.state.mcp()
|
|
49
|
+
const lspItems = api.state.lsp()
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<SidebarArch
|
|
53
|
+
theme={ctx.theme.current}
|
|
54
|
+
config={boot}
|
|
55
|
+
sessionID={sessionID}
|
|
56
|
+
branch={branch}
|
|
57
|
+
files={files}
|
|
58
|
+
todos={todos}
|
|
59
|
+
messages={messages}
|
|
60
|
+
mcpItems={mcpItems}
|
|
61
|
+
lspItems={lspItems}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
44
64
|
},
|
|
45
65
|
|
|
46
66
|
// Prompt bar right side: session info
|