opencode-mask-j0k3r-dev-rgl 2.0.21 → 2.0.23
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/ascii-frames.ts +11 -11
- package/components.tsx +222 -208
- package/package.json +1 -1
- package/tui.tsx +98 -131
package/ascii-frames.ts
CHANGED
|
@@ -47,9 +47,9 @@ export const homeLogoZones: ("hotPink" | "white")[] = [
|
|
|
47
47
|
"hotPink", // line 6: `/:-:++oooo+:
|
|
48
48
|
"hotPink", // line 7: `/++++/+++++++:
|
|
49
49
|
"hotPink", // line 8: `/+++++++++++++++:
|
|
50
|
-
"white",
|
|
51
|
-
"white",
|
|
52
|
-
"white",
|
|
50
|
+
"white", // line 9: `/+++ooooooooooooo/`
|
|
51
|
+
"white", // line 10: ./ooosssso++osssssso+`
|
|
52
|
+
"white", // line 11: .oossssso-````/ossssss+`
|
|
53
53
|
"hotPink", // line 12: -osssssso. :ssssssso.
|
|
54
54
|
"hotPink", // line 13: :osssssss/ osssso+++.
|
|
55
55
|
"hotPink", // line 14: /ossssssss/ +ssssooo/-
|
|
@@ -61,14 +61,14 @@ export const homeLogoZones: ("hotPink" | "white")[] = [
|
|
|
61
61
|
|
|
62
62
|
// ─── Sidebar logo (mini Arch) ────────────────────────────────────────────────
|
|
63
63
|
export const archLogoSidebar: string[] = [
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
" /\\ ",
|
|
65
|
+
" / \\ ",
|
|
66
|
+
" / \\ ",
|
|
67
|
+
" / \\ ",
|
|
68
|
+
" / ,, \\ ",
|
|
69
|
+
" / | | \\ ",
|
|
70
|
+
' / /-""-\\ \\ ',
|
|
71
|
+
"/___/ \\___\\",
|
|
72
72
|
];
|
|
73
73
|
|
|
74
74
|
export const sidebarLogoZones: ("hotPink" | "white")[] = [
|
package/components.tsx
CHANGED
|
@@ -1,226 +1,240 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
/** @jsxImportSource @opentui/solid */
|
|
3
|
-
import type { TuiThemeCurrent
|
|
4
|
-
import type { Cfg } from "./config"
|
|
5
|
-
import { getOSName, getProviders } from "./detection"
|
|
3
|
+
import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui";
|
|
6
4
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./ascii-frames"
|
|
5
|
+
archLogoHome,
|
|
6
|
+
archLogoSidebar,
|
|
7
|
+
homeLogoZones,
|
|
8
|
+
sidebarLogoZones,
|
|
9
|
+
zoneColors,
|
|
10
|
+
} from "./ascii-frames";
|
|
11
|
+
import type { Cfg } from "./config";
|
|
12
|
+
import { getOSName, getProviders } from "./detection";
|
|
13
13
|
|
|
14
14
|
// ─── Home screen: Large Arch Linux logo + legend ─────────────────────────────
|
|
15
15
|
export const HomeLogo = (props: { theme: TuiThemeCurrent }) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
16
|
+
const t = props.theme;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<box flexDirection="column" alignItems="center">
|
|
20
|
+
{archLogoHome.map((line, i) => {
|
|
21
|
+
const zone = homeLogoZones[i];
|
|
22
|
+
const color = zoneColors[zone] || t.primary;
|
|
23
|
+
return <text fg={color}>{line}</text>;
|
|
24
|
+
})}
|
|
25
|
+
|
|
26
|
+
<text> </text>
|
|
27
|
+
<box flexDirection="row" gap={0}>
|
|
28
|
+
<text fg="#ff2d78" bold={true}>
|
|
29
|
+
j0k3r
|
|
30
|
+
</text>
|
|
31
|
+
<text fg="#9d4edd">-</text>
|
|
32
|
+
<text fg="#00c8ff" bold={true}>
|
|
33
|
+
dev
|
|
34
|
+
</text>
|
|
35
|
+
<text fg="#9d4edd">-</text>
|
|
36
|
+
<text fg="#4dd8ff" bold={true}>
|
|
37
|
+
rgl
|
|
38
|
+
</text>
|
|
39
|
+
<text fg="#9d4edd">@</text>
|
|
40
|
+
<text fg="#ffd166" bold={true}>
|
|
41
|
+
latest
|
|
42
|
+
</text>
|
|
43
|
+
</box>
|
|
44
|
+
|
|
45
|
+
<box flexDirection="row" gap={0} marginTop={1}>
|
|
46
|
+
<text fg={t.textMuted} dimColor={true}>
|
|
47
|
+
╭{" "}
|
|
48
|
+
</text>
|
|
49
|
+
<text fg={t.textMuted}>arch linux </text>
|
|
50
|
+
<text fg={t.textMuted} dimColor={true}>
|
|
51
|
+
·
|
|
52
|
+
</text>
|
|
53
|
+
<text fg={t.textMuted}> opencode </text>
|
|
54
|
+
<text fg={t.textMuted} dimColor={true}>
|
|
55
|
+
╮
|
|
56
|
+
</text>
|
|
57
|
+
</box>
|
|
58
|
+
|
|
59
|
+
<text> </text>
|
|
60
|
+
</box>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
49
63
|
|
|
50
64
|
// ─── Progress bar helper ──────────────────────────────────────────────────────
|
|
51
65
|
const ProgressBar = (props: {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
66
|
+
value: number; // 0–100
|
|
67
|
+
width?: number;
|
|
68
|
+
fillColor: string;
|
|
69
|
+
emptyColor: string;
|
|
70
|
+
theme: TuiThemeCurrent;
|
|
57
71
|
}) => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
72
|
+
const width = props.width ?? 12;
|
|
73
|
+
const pct = Math.max(0, Math.min(100, props.value));
|
|
74
|
+
const filled = Math.round((pct / 100) * width);
|
|
75
|
+
const empty = width - filled;
|
|
76
|
+
const fill = "█".repeat(filled);
|
|
77
|
+
const trail = "░".repeat(empty);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<box flexDirection="row" gap={0}>
|
|
81
|
+
<text fg={props.theme.textMuted}>[</text>
|
|
82
|
+
<text fg={props.fillColor}>{fill}</text>
|
|
83
|
+
<text fg={props.emptyColor}>{trail}</text>
|
|
84
|
+
<text fg={props.theme.textMuted}>]</text>
|
|
85
|
+
</box>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
74
88
|
|
|
75
89
|
// ─── Sidebar: Arch logo + stats panel ────────────────────────────────────────
|
|
76
90
|
export const SidebarArch = (props: {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
todos?: ReadonlyArray<TuiSidebarTodoItem>
|
|
83
|
-
contextTokens: number
|
|
84
|
-
contextCost: number
|
|
85
|
-
contextLimit: number
|
|
91
|
+
theme: TuiThemeCurrent;
|
|
92
|
+
config: Cfg;
|
|
93
|
+
branch?: string;
|
|
94
|
+
getMessages?: () => any[];
|
|
95
|
+
contextLimit: number;
|
|
86
96
|
}) => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
97
|
+
if (!props.config.show_sidebar) return null;
|
|
98
|
+
|
|
99
|
+
const t = props.theme;
|
|
100
|
+
|
|
101
|
+
// ── Context — Reactivo y con la misma lógica interna de OpenCode ──────────
|
|
102
|
+
const getContextTokens = () => {
|
|
103
|
+
const messages = props.getMessages ? props.getMessages() : [];
|
|
104
|
+
// Buscar el último mensaje de asistente que tuvo output de tokens
|
|
105
|
+
const last = [...messages]
|
|
106
|
+
.reverse()
|
|
107
|
+
.find((m: any) => m.role === "assistant" && m.tokens?.output > 0);
|
|
108
|
+
if (!last) return 0;
|
|
109
|
+
|
|
110
|
+
// Suma total de todos los tokens del contexto de ese mensaje exacto
|
|
111
|
+
const tk = last.tokens;
|
|
112
|
+
return (
|
|
113
|
+
(tk.input ?? 0) +
|
|
114
|
+
(tk.output ?? 0) +
|
|
115
|
+
(tk.reasoning ?? 0) +
|
|
116
|
+
(tk.cache?.read ?? 0) +
|
|
117
|
+
(tk.cache?.write ?? 0)
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const getTotalCost = () => {
|
|
122
|
+
const messages = props.getMessages ? props.getMessages() : [];
|
|
123
|
+
return messages.reduce(
|
|
124
|
+
(sum, item) => sum + (item.role === "assistant" ? (item.cost ?? 0) : 0),
|
|
125
|
+
0,
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const getContextPct = () => {
|
|
130
|
+
const limit = props.contextLimit || 1_000_000;
|
|
131
|
+
return Math.min(100, Math.round((getContextTokens() / limit) * 100));
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const getCostPct = () => Math.min(100, Math.round(getTotalCost() * 100));
|
|
135
|
+
|
|
136
|
+
const fmtTokens = (n: number) =>
|
|
137
|
+
n >= 1000 ? `${(n / 1000).toFixed(1)}k` : `${n}`;
|
|
138
|
+
const fmtCost = (n: number) => `$${n.toFixed(2)}`;
|
|
139
|
+
|
|
140
|
+
// Color: verde → amarillo → rojo según el %
|
|
141
|
+
const getCtxColor = () => {
|
|
142
|
+
const pct = getContextPct();
|
|
143
|
+
return pct < 50 ? "#00e5a0" : pct < 80 ? "#ffd166" : "#ff2d78";
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<box flexDirection="column" alignItems="center">
|
|
148
|
+
{/* Mini Arch logo */}
|
|
149
|
+
{archLogoSidebar.map((line, i) => {
|
|
150
|
+
const zone = sidebarLogoZones[i];
|
|
151
|
+
const color = zoneColors[zone] || t.primary;
|
|
152
|
+
return <text fg={color}>{line}</text>;
|
|
153
|
+
})}
|
|
154
|
+
|
|
155
|
+
<text fg={t.textMuted}>j0k3r@latest</text>
|
|
156
|
+
<text> </text>
|
|
157
|
+
|
|
158
|
+
{/* Git branch */}
|
|
159
|
+
{props.branch && (
|
|
160
|
+
<box flexDirection="row" gap={1}>
|
|
161
|
+
<text fg="#ffd166">⎇</text>
|
|
162
|
+
<text fg={t.text}>{props.branch}</text>
|
|
163
|
+
</box>
|
|
164
|
+
)}
|
|
165
|
+
|
|
166
|
+
{/* ── Context (tokens + % used + cost) ── siempre visible */}
|
|
167
|
+
<box flexDirection="column" alignItems="center" marginTop={1}>
|
|
168
|
+
<text fg={t.textMuted} bold={true}>
|
|
169
|
+
Context
|
|
170
|
+
</text>
|
|
171
|
+
|
|
172
|
+
{/* tokens */}
|
|
173
|
+
<box flexDirection="row" gap={1}>
|
|
174
|
+
<text fg={t.text}>{fmtTokens(getContextTokens())}</text>
|
|
175
|
+
<text fg={t.textMuted}>tokens</text>
|
|
176
|
+
</box>
|
|
177
|
+
<ProgressBar
|
|
178
|
+
value={getContextPct()}
|
|
179
|
+
width={18}
|
|
180
|
+
fillColor={getCtxColor()}
|
|
181
|
+
emptyColor="#3a3a3a"
|
|
182
|
+
theme={t}
|
|
183
|
+
/>
|
|
184
|
+
|
|
185
|
+
{/* % used */}
|
|
186
|
+
<box flexDirection="row" gap={1}>
|
|
187
|
+
<text fg={getCtxColor()}>{getContextPct()}%</text>
|
|
188
|
+
<text fg={t.textMuted}>used</text>
|
|
189
|
+
</box>
|
|
190
|
+
<ProgressBar
|
|
191
|
+
value={getContextPct()}
|
|
192
|
+
width={18}
|
|
193
|
+
fillColor={getCtxColor()}
|
|
194
|
+
emptyColor="#3a3a3a"
|
|
195
|
+
theme={t}
|
|
196
|
+
/>
|
|
197
|
+
|
|
198
|
+
{/* $ spent */}
|
|
199
|
+
<box flexDirection="row" gap={1}>
|
|
200
|
+
<text fg="#ffd166">{fmtCost(getTotalCost())}</text>
|
|
201
|
+
<text fg={t.textMuted}>spent</text>
|
|
202
|
+
</box>
|
|
203
|
+
<ProgressBar
|
|
204
|
+
value={getCostPct()}
|
|
205
|
+
width={18}
|
|
206
|
+
fillColor="#ffd166"
|
|
207
|
+
emptyColor="#3a3a3a"
|
|
208
|
+
theme={t}
|
|
209
|
+
/>
|
|
210
|
+
</box>
|
|
211
|
+
|
|
212
|
+
<text> </text>
|
|
213
|
+
</box>
|
|
214
|
+
);
|
|
215
|
+
};
|
|
204
216
|
|
|
205
217
|
// ─── Environment detection line ──────────────────────────────────────────────
|
|
206
218
|
export const DetectedEnv = (props: {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
219
|
+
theme: TuiThemeCurrent;
|
|
220
|
+
providers: ReadonlyArray<{ id: string; name: string }> | undefined;
|
|
221
|
+
config: Cfg;
|
|
210
222
|
}) => {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
223
|
+
if (!props.config.show_detected) return null;
|
|
224
|
+
|
|
225
|
+
const os = props.config.show_os ? getOSName() : null;
|
|
226
|
+
const providers = props.config.show_providers
|
|
227
|
+
? getProviders(props.providers)
|
|
228
|
+
: null;
|
|
229
|
+
|
|
230
|
+
if (!os && !providers) return null;
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
<box flexDirection="row" gap={1}>
|
|
234
|
+
<text fg={props.theme.textMuted}>detected:</text>
|
|
235
|
+
{os && <text fg={props.theme.text}>{os}</text>}
|
|
236
|
+
{os && providers && <text fg={props.theme.textMuted}>·</text>}
|
|
237
|
+
{providers && <text fg={props.theme.text}>{providers}</text>}
|
|
238
|
+
</box>
|
|
239
|
+
);
|
|
240
|
+
};
|
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.23",
|
|
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
|
@@ -1,141 +1,108 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
/** @jsxImportSource @opentui/solid */
|
|
3
|
-
import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
|
4
|
-
import {
|
|
5
|
-
import { cfg } from "./config"
|
|
6
|
-
import { HomeLogo, SidebarArch, DetectedEnv } from "./components"
|
|
3
|
+
import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui";
|
|
4
|
+
import { DetectedEnv, HomeLogo, SidebarArch } from "./components";
|
|
5
|
+
import { cfg } from "./config";
|
|
7
6
|
|
|
8
|
-
const id = "j0k3r-dev-rgl"
|
|
7
|
+
const id = "j0k3r-dev-rgl";
|
|
9
8
|
|
|
10
9
|
const rec = (value: unknown) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
10
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
11
|
+
return Object.fromEntries(Object.entries(value));
|
|
12
|
+
};
|
|
14
13
|
|
|
15
14
|
const tui: TuiPlugin = async (api, options) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const todos = sessionID ? api.state.session.todo(sessionID) : []
|
|
104
|
-
const mcpItems = api.state.mcp()
|
|
105
|
-
const lspItems = api.state.lsp()
|
|
106
|
-
|
|
107
|
-
return (
|
|
108
|
-
<SidebarArch
|
|
109
|
-
theme={ctx.theme.current}
|
|
110
|
-
config={boot}
|
|
111
|
-
branch={branch}
|
|
112
|
-
todos={todos}
|
|
113
|
-
mcpItems={mcpItems}
|
|
114
|
-
lspItems={lspItems}
|
|
115
|
-
contextTokens={stats.tokens}
|
|
116
|
-
contextCost={stats.cost}
|
|
117
|
-
contextLimit={getContextLimit()}
|
|
118
|
-
/>
|
|
119
|
-
)
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
session_prompt_right(ctx, value) {
|
|
123
|
-
const t = ctx.theme.current
|
|
124
|
-
return (
|
|
125
|
-
<text fg={t.textMuted}>
|
|
126
|
-
<span style={{ fg: "#ff2d78" }}>j0k3r</span>
|
|
127
|
-
<span style={{ fg: "#9d4edd" }}>@</span>
|
|
128
|
-
{(value.session_id ?? "").slice(0, 6)}
|
|
129
|
-
</text>
|
|
130
|
-
)
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
})
|
|
134
|
-
}
|
|
15
|
+
const boot = cfg(rec(options));
|
|
16
|
+
if (!boot.enabled) return;
|
|
17
|
+
|
|
18
|
+
// Theme setup
|
|
19
|
+
try {
|
|
20
|
+
await api.theme.install("./themes/j0k3r-dev-rgl.json");
|
|
21
|
+
if (boot.set_theme) api.theme.set(boot.theme);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
// Silent fail
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Asegurarnos de que los plugins internos estén ACTIVOS
|
|
27
|
+
// (los reactivamos por si quedaron apagados de la sesión anterior)
|
|
28
|
+
const enableInternal = async () => {
|
|
29
|
+
try {
|
|
30
|
+
await api.plugins.deactivate("internal:sidebar-context");
|
|
31
|
+
await api.plugins.deactivate("internal:sidebar-mcp");
|
|
32
|
+
await api.plugins.activate("internal:sidebar-lsp");
|
|
33
|
+
await api.plugins.activate("internal:sidebar-todo");
|
|
34
|
+
await api.plugins.activate("internal:sidebar-files");
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Silent fail
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
enableInternal();
|
|
40
|
+
|
|
41
|
+
// Resolver context window real del modelo activo
|
|
42
|
+
const getContextLimit = (): number => {
|
|
43
|
+
try {
|
|
44
|
+
const modelStr = api.state.config?.model ?? "";
|
|
45
|
+
const [providerID, modelID] = modelStr.split("/");
|
|
46
|
+
const provider = api.state.provider.find((p) => p.id === providerID);
|
|
47
|
+
const model = provider?.models?.[modelID];
|
|
48
|
+
if (model?.limit?.context) return model.limit.context;
|
|
49
|
+
} catch (_) {}
|
|
50
|
+
return 1_000_000;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Slot registration
|
|
54
|
+
api.slots.register({
|
|
55
|
+
slots: {
|
|
56
|
+
home_logo(ctx) {
|
|
57
|
+
return <HomeLogo theme={ctx.theme.current} />;
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
home_bottom(ctx) {
|
|
61
|
+
return (
|
|
62
|
+
<DetectedEnv
|
|
63
|
+
theme={ctx.theme.current}
|
|
64
|
+
providers={api.state.provider}
|
|
65
|
+
config={boot}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
sidebar_content(ctx, value) {
|
|
71
|
+
const sessionID = value?.session_id;
|
|
72
|
+
|
|
73
|
+
const branch = api.state.vcs?.branch;
|
|
74
|
+
const contextLimit = getContextLimit();
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<SidebarArch
|
|
78
|
+
theme={ctx.theme.current}
|
|
79
|
+
config={boot}
|
|
80
|
+
branch={branch}
|
|
81
|
+
getMessages={() =>
|
|
82
|
+
sessionID ? api.state.session.messages(sessionID) : []
|
|
83
|
+
}
|
|
84
|
+
contextLimit={contextLimit}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
session_prompt_right(ctx, value) {
|
|
90
|
+
const t = ctx.theme.current;
|
|
91
|
+
return (
|
|
92
|
+
<text fg={t.textMuted}>
|
|
93
|
+
<span style={{ fg: "#ff2d78" }}>j0k3r</span>
|
|
94
|
+
<span style={{ fg: "#9d4edd" }}>@</span>
|
|
95
|
+
{(value.session_id ?? "").slice(0, 6)}
|
|
96
|
+
</text>
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
};
|
|
135
102
|
|
|
136
103
|
const plugin: TuiPluginModule & { id: string } = {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
104
|
+
id,
|
|
105
|
+
tui,
|
|
106
|
+
};
|
|
140
107
|
|
|
141
|
-
export default plugin
|
|
108
|
+
export default plugin;
|