@mindstudio-ai/local-model-tunnel 0.4.0 → 0.4.2
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/README.md +27 -11
- package/dist/{chunk-44NXQXRB.js → chunk-KLOTDVWL.js} +4 -2
- package/dist/chunk-KLOTDVWL.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{tui-BW6XKMWK.js → tui-OZLGNBGD.js} +608 -370
- package/dist/tui-OZLGNBGD.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-44NXQXRB.js.map +0 -1
- package/dist/tui-BW6XKMWK.js.map +0 -1
|
@@ -20,19 +20,21 @@ import {
|
|
|
20
20
|
setUserId,
|
|
21
21
|
syncModels,
|
|
22
22
|
verifyApiKey
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-KLOTDVWL.js";
|
|
24
24
|
|
|
25
25
|
// src/tui/index.tsx
|
|
26
26
|
import { render } from "ink";
|
|
27
27
|
import { execFileSync, execSync as execSync2 } from "child_process";
|
|
28
28
|
|
|
29
29
|
// src/tui/App.tsx
|
|
30
|
-
import { useEffect as
|
|
30
|
+
import { useEffect as useEffect16, useCallback as useCallback10, useState as useState16, useRef as useRef9 } from "react";
|
|
31
31
|
import { Box as Box10, useApp, useStdout as useStdout7 } from "ink";
|
|
32
32
|
|
|
33
33
|
// src/tui/components/Header.tsx
|
|
34
|
+
import { useState, useEffect, useMemo } from "react";
|
|
34
35
|
import os from "os";
|
|
35
36
|
import { Box, Text } from "ink";
|
|
37
|
+
import chalk from "chalk";
|
|
36
38
|
import { createRequire } from "module";
|
|
37
39
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
38
40
|
var require2 = createRequire(import.meta.url);
|
|
@@ -46,6 +48,52 @@ var LogoString = ` .=+-. :++.
|
|
|
46
48
|
=@@@@@@@-.@@@@@@@#.-@@@@@@+
|
|
47
49
|
:@@@@@@: +@@@@@#. .@@@@@@:
|
|
48
50
|
.++: .-*-. .++:`;
|
|
51
|
+
function useActiveShimmerLogo(active) {
|
|
52
|
+
const [frame, setFrame] = useState(0);
|
|
53
|
+
const lines = useMemo(() => LogoString.split("\n"), []);
|
|
54
|
+
const totalChars = useMemo(() => {
|
|
55
|
+
let count = 0;
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
for (const ch of line) {
|
|
58
|
+
if (ch !== " " && ch !== " ") count++;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return count;
|
|
62
|
+
}, [lines]);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!active) return;
|
|
65
|
+
const interval = setInterval(() => {
|
|
66
|
+
setFrame((f) => f + 1);
|
|
67
|
+
}, 25);
|
|
68
|
+
return () => clearInterval(interval);
|
|
69
|
+
}, [active]);
|
|
70
|
+
return useMemo(() => {
|
|
71
|
+
if (!active) return null;
|
|
72
|
+
const waveLength = 20;
|
|
73
|
+
let charIdx = 0;
|
|
74
|
+
return lines.map((line) => {
|
|
75
|
+
let result = "";
|
|
76
|
+
for (let i = 0; i < line.length; i++) {
|
|
77
|
+
const ch = line[i];
|
|
78
|
+
if (ch === " " || ch === " ") {
|
|
79
|
+
result += ch;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const phase = (charIdx - frame * 0.5) / waveLength * Math.PI * 2;
|
|
83
|
+
const brightness = 0.65 + 0.35 * Math.sin(phase);
|
|
84
|
+
if (brightness >= 0.85) {
|
|
85
|
+
result += chalk.cyanBright(ch);
|
|
86
|
+
} else if (brightness >= 0.65) {
|
|
87
|
+
result += chalk.cyan(ch);
|
|
88
|
+
} else {
|
|
89
|
+
result += chalk.rgb(0, 140, 160)(ch);
|
|
90
|
+
}
|
|
91
|
+
charIdx++;
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}).join("\n");
|
|
95
|
+
}, [active, frame, lines, totalChars]);
|
|
96
|
+
}
|
|
49
97
|
var getConnectionDisplay = (status) => {
|
|
50
98
|
switch (status) {
|
|
51
99
|
case "connected":
|
|
@@ -65,9 +113,11 @@ function Header({
|
|
|
65
113
|
environment,
|
|
66
114
|
configPath,
|
|
67
115
|
connectionError,
|
|
68
|
-
compact
|
|
116
|
+
compact,
|
|
117
|
+
hasActiveRequest
|
|
69
118
|
}) {
|
|
70
119
|
const { color: connectionColor, text: connectionText } = getConnectionDisplay(connection);
|
|
120
|
+
const shimmerLogo = useActiveShimmerLogo(!compact && !!hasActiveRequest);
|
|
71
121
|
return /* @__PURE__ */ jsxs(
|
|
72
122
|
Box,
|
|
73
123
|
{
|
|
@@ -79,7 +129,7 @@ function Header({
|
|
|
79
129
|
paddingY: 1,
|
|
80
130
|
width: "100%",
|
|
81
131
|
children: [
|
|
82
|
-
!compact && /* @__PURE__ */ jsx(Box, { paddingLeft: 3, children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: LogoString }) }),
|
|
132
|
+
!compact && /* @__PURE__ */ jsx(Box, { paddingLeft: 3, children: shimmerLogo ? /* @__PURE__ */ jsx(Text, { children: shimmerLogo }) : /* @__PURE__ */ jsx(Text, { color: "cyan", children: LogoString }) }),
|
|
83
133
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: compact ? 0 : 4, children: [
|
|
84
134
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
85
135
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "white", children: "MindStudio Local Tunnel" }),
|
|
@@ -92,10 +142,6 @@ function Header({
|
|
|
92
142
|
/* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "[LOCAL]" })
|
|
93
143
|
] })
|
|
94
144
|
] }),
|
|
95
|
-
!compact && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
96
|
-
"v",
|
|
97
|
-
pkg.version
|
|
98
|
-
] }),
|
|
99
145
|
/* @__PURE__ */ jsxs(Text, { color: connectionColor, children: [
|
|
100
146
|
"\u25CF ",
|
|
101
147
|
connectionText
|
|
@@ -104,6 +150,10 @@ function Header({
|
|
|
104
150
|
/* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
105
151
|
"Config: ",
|
|
106
152
|
configPath.replace(os.homedir(), "~")
|
|
153
|
+
] }),
|
|
154
|
+
!compact && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
155
|
+
"v",
|
|
156
|
+
pkg.version
|
|
107
157
|
] })
|
|
108
158
|
] })
|
|
109
159
|
]
|
|
@@ -112,18 +162,22 @@ function Header({
|
|
|
112
162
|
}
|
|
113
163
|
|
|
114
164
|
// src/tui/components/NavigationMenu.tsx
|
|
115
|
-
import { useState, useEffect } from "react";
|
|
165
|
+
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
116
166
|
import { Box as Box2, Text as Text2, useInput, useStdout } from "ink";
|
|
117
167
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
118
|
-
function NavigationMenu({
|
|
168
|
+
function NavigationMenu({
|
|
169
|
+
items,
|
|
170
|
+
onSelect,
|
|
171
|
+
title
|
|
172
|
+
}) {
|
|
119
173
|
const { stdout } = useStdout();
|
|
120
174
|
const compact = (stdout?.rows ?? 24) < 40;
|
|
121
175
|
const getDefaultIndex = () => {
|
|
122
176
|
const firstIdx = items.findIndex((i) => !i.disabled && !i.isSeparator);
|
|
123
177
|
return firstIdx >= 0 ? firstIdx : 0;
|
|
124
178
|
};
|
|
125
|
-
const [selectedIndex, setSelectedIndex] =
|
|
126
|
-
|
|
179
|
+
const [selectedIndex, setSelectedIndex] = useState2(getDefaultIndex);
|
|
180
|
+
useEffect2(() => {
|
|
127
181
|
setSelectedIndex(getDefaultIndex());
|
|
128
182
|
}, [items]);
|
|
129
183
|
const selectableItems = items.filter((i) => !i.isSeparator);
|
|
@@ -159,60 +213,98 @@ function NavigationMenu({ items, onSelect, title }) {
|
|
|
159
213
|
const hasBack = items.some((i) => i.id === "back");
|
|
160
214
|
if (compact) {
|
|
161
215
|
const selectedItem = items[selectedIndex];
|
|
162
|
-
return /* @__PURE__ */ jsx2(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
item
|
|
174
|
-
|
|
175
|
-
|
|
216
|
+
return /* @__PURE__ */ jsx2(
|
|
217
|
+
Box2,
|
|
218
|
+
{
|
|
219
|
+
flexDirection: "column",
|
|
220
|
+
paddingX: 1,
|
|
221
|
+
borderStyle: "single",
|
|
222
|
+
borderTop: true,
|
|
223
|
+
borderBottom: false,
|
|
224
|
+
borderLeft: false,
|
|
225
|
+
borderRight: false,
|
|
226
|
+
borderColor: "gray",
|
|
227
|
+
children: /* @__PURE__ */ jsx2(Box2, { height: 1, overflow: "hidden", gap: 1, children: items.map((item, index) => {
|
|
228
|
+
if (item.isSeparator) return null;
|
|
229
|
+
const isSelected = index === selectedIndex;
|
|
230
|
+
return /* @__PURE__ */ jsx2(
|
|
231
|
+
Text2,
|
|
232
|
+
{
|
|
233
|
+
color: item.disabled ? "gray" : isSelected ? "cyan" : "white",
|
|
234
|
+
bold: isSelected,
|
|
235
|
+
wrap: "truncate-end",
|
|
236
|
+
children: isSelected ? `\u276F ${item.label}` : ` ${item.label}`
|
|
237
|
+
},
|
|
238
|
+
item.id
|
|
239
|
+
);
|
|
240
|
+
}) })
|
|
241
|
+
}
|
|
242
|
+
);
|
|
176
243
|
}
|
|
177
|
-
const separatorExtraLines = items.filter(
|
|
244
|
+
const separatorExtraLines = items.filter(
|
|
245
|
+
(item, idx) => item.isSeparator && idx > 0
|
|
246
|
+
).length;
|
|
178
247
|
const menuHeight = items.length + 4 + separatorExtraLines;
|
|
179
|
-
return /* @__PURE__ */ jsxs2(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
" "
|
|
199
|
-
item.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
248
|
+
return /* @__PURE__ */ jsxs2(
|
|
249
|
+
Box2,
|
|
250
|
+
{
|
|
251
|
+
flexDirection: "column",
|
|
252
|
+
paddingX: 1,
|
|
253
|
+
marginBottom: 1,
|
|
254
|
+
borderStyle: "single",
|
|
255
|
+
borderTop: true,
|
|
256
|
+
borderBottom: false,
|
|
257
|
+
borderLeft: false,
|
|
258
|
+
borderRight: false,
|
|
259
|
+
borderColor: "gray",
|
|
260
|
+
children: [
|
|
261
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: title ?? "Actions" }) }),
|
|
262
|
+
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: items.map((item, index) => {
|
|
263
|
+
if (item.isSeparator) {
|
|
264
|
+
return /* @__PURE__ */ jsx2(Box2, { marginTop: index > 0 ? 1 : 0, children: item.label ? /* @__PURE__ */ jsx2(Text2, { bold: true, color: item.color ?? "gray", wrap: "truncate-end", children: item.label }) : null }, item.id);
|
|
265
|
+
}
|
|
266
|
+
const isSelected = index === selectedIndex;
|
|
267
|
+
const prefix = isSelected ? "\u276F" : " ";
|
|
268
|
+
if (item.disabled) {
|
|
269
|
+
return /* @__PURE__ */ jsx2(Box2, { height: 1, overflow: "hidden", children: /* @__PURE__ */ jsxs2(Text2, { color: "gray", wrap: "truncate-end", children: [
|
|
270
|
+
prefix,
|
|
271
|
+
" ",
|
|
272
|
+
item.label,
|
|
273
|
+
item.disabledReason ? ` (${item.disabledReason})` : ""
|
|
274
|
+
] }) }, item.id);
|
|
275
|
+
}
|
|
276
|
+
return /* @__PURE__ */ jsxs2(Box2, { height: 1, overflow: "hidden", children: [
|
|
277
|
+
/* @__PURE__ */ jsxs2(
|
|
278
|
+
Text2,
|
|
279
|
+
{
|
|
280
|
+
color: isSelected ? "cyan" : "white",
|
|
281
|
+
bold: isSelected,
|
|
282
|
+
wrap: "truncate-end",
|
|
283
|
+
children: [
|
|
284
|
+
prefix,
|
|
285
|
+
" ",
|
|
286
|
+
item.label
|
|
287
|
+
]
|
|
288
|
+
}
|
|
289
|
+
),
|
|
290
|
+
isSelected && /* @__PURE__ */ jsxs2(Text2, { color: "gray", wrap: "truncate-end", children: [
|
|
291
|
+
" ",
|
|
292
|
+
"- ",
|
|
293
|
+
item.description
|
|
294
|
+
] })
|
|
295
|
+
] }, item.id);
|
|
296
|
+
}) }),
|
|
297
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, height: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", wrap: "truncate-end", children: hasBack ? "Up/Down Navigate \u2022 Enter Select \u2022 q/Esc Back" : "Up/Down Navigate \u2022 Enter Select \u2022 q Quit" }) })
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
);
|
|
209
301
|
}
|
|
210
302
|
|
|
211
303
|
// src/tui/hooks/useConnection.ts
|
|
212
|
-
import { useState as
|
|
304
|
+
import { useState as useState3, useEffect as useEffect3, useCallback } from "react";
|
|
213
305
|
function useConnection() {
|
|
214
|
-
const [status, setStatus] =
|
|
215
|
-
const [error, setError] =
|
|
306
|
+
const [status, setStatus] = useState3("connecting");
|
|
307
|
+
const [error, setError] = useState3(null);
|
|
216
308
|
const environment = getEnvironment();
|
|
217
309
|
const connect = useCallback(async () => {
|
|
218
310
|
setStatus("connecting");
|
|
@@ -235,7 +327,7 @@ function useConnection() {
|
|
|
235
327
|
setError(err instanceof Error ? err.message : "Connection failed");
|
|
236
328
|
}
|
|
237
329
|
}, []);
|
|
238
|
-
|
|
330
|
+
useEffect3(() => {
|
|
239
331
|
connect();
|
|
240
332
|
}, [connect]);
|
|
241
333
|
return {
|
|
@@ -246,14 +338,65 @@ function useConnection() {
|
|
|
246
338
|
};
|
|
247
339
|
}
|
|
248
340
|
|
|
249
|
-
// src/tui/
|
|
250
|
-
import { useState as
|
|
251
|
-
function
|
|
252
|
-
const [
|
|
253
|
-
const [loading, setLoading] =
|
|
254
|
-
const [
|
|
341
|
+
// src/tui/interfaces/hooks/useEditorSessions.ts
|
|
342
|
+
import { useState as useState4, useEffect as useEffect4, useCallback as useCallback2, useRef } from "react";
|
|
343
|
+
function useEditorSessions() {
|
|
344
|
+
const [sessions, setSessions] = useState4([]);
|
|
345
|
+
const [loading, setLoading] = useState4(true);
|
|
346
|
+
const [error, setError] = useState4(null);
|
|
347
|
+
const [refreshStatus, setRefreshStatus] = useState4("idle");
|
|
255
348
|
const initialLoadDone = useRef(false);
|
|
349
|
+
const timerRef = useRef();
|
|
350
|
+
const pollRef = useRef();
|
|
256
351
|
const refresh = useCallback2(async () => {
|
|
352
|
+
if (!initialLoadDone.current) {
|
|
353
|
+
setLoading(true);
|
|
354
|
+
} else {
|
|
355
|
+
setRefreshStatus("refreshing");
|
|
356
|
+
}
|
|
357
|
+
setError(null);
|
|
358
|
+
try {
|
|
359
|
+
const data = await getEditorSessions();
|
|
360
|
+
setSessions(data);
|
|
361
|
+
initialLoadDone.current = true;
|
|
362
|
+
setRefreshStatus("refreshed");
|
|
363
|
+
clearTimeout(timerRef.current);
|
|
364
|
+
timerRef.current = setTimeout(() => setRefreshStatus("idle"), 1500);
|
|
365
|
+
} catch (err) {
|
|
366
|
+
setError(err instanceof Error ? err.message : "Failed to fetch sessions");
|
|
367
|
+
setRefreshStatus("idle");
|
|
368
|
+
} finally {
|
|
369
|
+
setLoading(false);
|
|
370
|
+
}
|
|
371
|
+
}, []);
|
|
372
|
+
useEffect4(() => {
|
|
373
|
+
refresh();
|
|
374
|
+
}, [refresh]);
|
|
375
|
+
useEffect4(() => {
|
|
376
|
+
pollRef.current = setInterval(async () => {
|
|
377
|
+
if (!initialLoadDone.current) return;
|
|
378
|
+
try {
|
|
379
|
+
const data = await getEditorSessions();
|
|
380
|
+
setSessions(data);
|
|
381
|
+
} catch {
|
|
382
|
+
}
|
|
383
|
+
}, 5e3);
|
|
384
|
+
return () => clearInterval(pollRef.current);
|
|
385
|
+
}, []);
|
|
386
|
+
useEffect4(() => {
|
|
387
|
+
return () => clearTimeout(timerRef.current);
|
|
388
|
+
}, []);
|
|
389
|
+
return { sessions, loading, error, refreshStatus, refresh };
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/tui/models/hooks/useSetupProviders.ts
|
|
393
|
+
import { useState as useState5, useEffect as useEffect5, useCallback as useCallback3, useRef as useRef2 } from "react";
|
|
394
|
+
function useSetupProviders() {
|
|
395
|
+
const [providers, setProviders] = useState5([]);
|
|
396
|
+
const [loading, setLoading] = useState5(true);
|
|
397
|
+
const [refreshing, setRefreshing] = useState5(false);
|
|
398
|
+
const initialLoadDone = useRef2(false);
|
|
399
|
+
const refresh = useCallback3(async () => {
|
|
257
400
|
if (!initialLoadDone.current) {
|
|
258
401
|
setLoading(true);
|
|
259
402
|
} else {
|
|
@@ -265,21 +408,21 @@ function useSetupProviders() {
|
|
|
265
408
|
setLoading(false);
|
|
266
409
|
setRefreshing(false);
|
|
267
410
|
}, []);
|
|
268
|
-
|
|
411
|
+
useEffect5(() => {
|
|
269
412
|
refresh();
|
|
270
413
|
}, [refresh]);
|
|
271
414
|
return { providers, loading, refreshing, refresh };
|
|
272
415
|
}
|
|
273
416
|
|
|
274
417
|
// src/tui/models/hooks/useModels.ts
|
|
275
|
-
import { useState as
|
|
418
|
+
import { useState as useState6, useEffect as useEffect6, useCallback as useCallback4, useRef as useRef3 } from "react";
|
|
276
419
|
function useModels() {
|
|
277
|
-
const [models, setModels] =
|
|
278
|
-
const [warnings, setWarnings] =
|
|
279
|
-
const [loading, setLoading] =
|
|
280
|
-
const [refreshing, setRefreshing] =
|
|
281
|
-
const initialLoadDone =
|
|
282
|
-
const refresh =
|
|
420
|
+
const [models, setModels] = useState6([]);
|
|
421
|
+
const [warnings, setWarnings] = useState6([]);
|
|
422
|
+
const [loading, setLoading] = useState6(true);
|
|
423
|
+
const [refreshing, setRefreshing] = useState6(false);
|
|
424
|
+
const initialLoadDone = useRef3(false);
|
|
425
|
+
const refresh = useCallback4(async () => {
|
|
283
426
|
if (!initialLoadDone.current) {
|
|
284
427
|
setLoading(true);
|
|
285
428
|
} else {
|
|
@@ -298,7 +441,7 @@ function useModels() {
|
|
|
298
441
|
setRefreshing(false);
|
|
299
442
|
}
|
|
300
443
|
}, []);
|
|
301
|
-
|
|
444
|
+
useEffect6(() => {
|
|
302
445
|
refresh();
|
|
303
446
|
}, [refresh]);
|
|
304
447
|
return {
|
|
@@ -311,11 +454,11 @@ function useModels() {
|
|
|
311
454
|
}
|
|
312
455
|
|
|
313
456
|
// src/tui/models/hooks/useRequests.ts
|
|
314
|
-
import { useState as
|
|
457
|
+
import { useState as useState7, useEffect as useEffect7, useCallback as useCallback5, useRef as useRef4 } from "react";
|
|
315
458
|
function useRequests(maxHistory = 50) {
|
|
316
|
-
const [requests, setRequests] =
|
|
317
|
-
const requestsRef =
|
|
318
|
-
|
|
459
|
+
const [requests, setRequests] = useState7([]);
|
|
460
|
+
const requestsRef = useRef4(/* @__PURE__ */ new Map());
|
|
461
|
+
useEffect7(() => {
|
|
319
462
|
const interval = setInterval(() => {
|
|
320
463
|
setRequests((prev) => {
|
|
321
464
|
const hasActive = prev.some((r) => r.status === "processing");
|
|
@@ -324,7 +467,7 @@ function useRequests(maxHistory = 50) {
|
|
|
324
467
|
}, 1e3);
|
|
325
468
|
return () => clearInterval(interval);
|
|
326
469
|
}, []);
|
|
327
|
-
|
|
470
|
+
useEffect7(() => {
|
|
328
471
|
const unsubStart = requestEvents.onStart((event) => {
|
|
329
472
|
const entry = {
|
|
330
473
|
id: event.id,
|
|
@@ -343,7 +486,9 @@ function useRequests(maxHistory = 50) {
|
|
|
343
486
|
...existing,
|
|
344
487
|
...event.content !== void 0 && { content: event.content },
|
|
345
488
|
...event.step !== void 0 && { step: event.step },
|
|
346
|
-
...event.totalSteps !== void 0 && {
|
|
489
|
+
...event.totalSteps !== void 0 && {
|
|
490
|
+
totalSteps: event.totalSteps
|
|
491
|
+
}
|
|
347
492
|
};
|
|
348
493
|
requestsRef.current.set(event.id, updated);
|
|
349
494
|
setRequests(
|
|
@@ -375,7 +520,7 @@ function useRequests(maxHistory = 50) {
|
|
|
375
520
|
};
|
|
376
521
|
}, [maxHistory]);
|
|
377
522
|
const activeCount = requests.filter((r) => r.status === "processing").length;
|
|
378
|
-
const clear =
|
|
523
|
+
const clear = useCallback5(() => {
|
|
379
524
|
requestsRef.current.clear();
|
|
380
525
|
setRequests([]);
|
|
381
526
|
}, []);
|
|
@@ -387,13 +532,11 @@ function useRequests(maxHistory = 50) {
|
|
|
387
532
|
}
|
|
388
533
|
|
|
389
534
|
// src/tui/models/hooks/useRegisteredModels.ts
|
|
390
|
-
import { useState as
|
|
535
|
+
import { useState as useState8, useEffect as useEffect8, useCallback as useCallback6 } from "react";
|
|
391
536
|
function useSyncedModels(connectionStatus) {
|
|
392
|
-
const [syncedNames, setSyncedNames] =
|
|
393
|
-
|
|
394
|
-
)
|
|
395
|
-
const [syncedModels, setSyncedModels] = useState6([]);
|
|
396
|
-
const refresh = useCallback5(async () => {
|
|
537
|
+
const [syncedNames, setSyncedNames] = useState8(/* @__PURE__ */ new Set());
|
|
538
|
+
const [syncedModels, setSyncedModels] = useState8([]);
|
|
539
|
+
const refresh = useCallback6(async () => {
|
|
397
540
|
if (connectionStatus !== "connected") {
|
|
398
541
|
setSyncedNames(/* @__PURE__ */ new Set());
|
|
399
542
|
setSyncedModels([]);
|
|
@@ -406,7 +549,7 @@ function useSyncedModels(connectionStatus) {
|
|
|
406
549
|
} catch {
|
|
407
550
|
}
|
|
408
551
|
}, [connectionStatus]);
|
|
409
|
-
|
|
552
|
+
useEffect8(() => {
|
|
410
553
|
refresh();
|
|
411
554
|
}, [refresh]);
|
|
412
555
|
return {
|
|
@@ -417,7 +560,7 @@ function useSyncedModels(connectionStatus) {
|
|
|
417
560
|
}
|
|
418
561
|
|
|
419
562
|
// src/tui/models/pages/DashboardPage.tsx
|
|
420
|
-
import { useMemo } from "react";
|
|
563
|
+
import { useMemo as useMemo2 } from "react";
|
|
421
564
|
import { Box as Box4, Text as Text4, useStdout as useStdout3 } from "ink";
|
|
422
565
|
import Spinner2 from "ink-spinner";
|
|
423
566
|
|
|
@@ -455,7 +598,10 @@ function snippetLine(content, maxWidth) {
|
|
|
455
598
|
if (flat.length <= maxWidth) return flat;
|
|
456
599
|
return "\u2026" + flat.slice(-(maxWidth - 1));
|
|
457
600
|
}
|
|
458
|
-
function RequestItem({
|
|
601
|
+
function RequestItem({
|
|
602
|
+
request,
|
|
603
|
+
width
|
|
604
|
+
}) {
|
|
459
605
|
const time = formatTime(request.startTime);
|
|
460
606
|
const typeLabel = getRequestTypeLabel(request.requestType);
|
|
461
607
|
const snippetIndent = " ";
|
|
@@ -470,13 +616,13 @@ function RequestItem({ request, width }) {
|
|
|
470
616
|
/* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
471
617
|
" ",
|
|
472
618
|
time,
|
|
473
|
-
"
|
|
619
|
+
" "
|
|
474
620
|
] }),
|
|
475
621
|
/* @__PURE__ */ jsx3(Text3, { color: "white", children: request.modelId }),
|
|
476
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "
|
|
622
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: " " }),
|
|
477
623
|
/* @__PURE__ */ jsx3(Text3, { color: typeLabel.color, children: typeLabel.label }),
|
|
478
624
|
/* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
479
|
-
"
|
|
625
|
+
" ",
|
|
480
626
|
formatDuration(elapsed),
|
|
481
627
|
"..."
|
|
482
628
|
] })
|
|
@@ -508,13 +654,13 @@ function RequestItem({ request, width }) {
|
|
|
508
654
|
/* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
509
655
|
" ",
|
|
510
656
|
time,
|
|
511
|
-
"
|
|
657
|
+
" "
|
|
512
658
|
] }),
|
|
513
659
|
/* @__PURE__ */ jsx3(Text3, { color: "white", children: request.modelId }),
|
|
514
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "
|
|
660
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: " " }),
|
|
515
661
|
/* @__PURE__ */ jsx3(Text3, { color: typeLabel.color, children: typeLabel.label }),
|
|
516
662
|
/* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
517
|
-
"
|
|
663
|
+
" ",
|
|
518
664
|
duration,
|
|
519
665
|
resultInfo
|
|
520
666
|
] })
|
|
@@ -530,18 +676,22 @@ function RequestItem({ request, width }) {
|
|
|
530
676
|
/* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
531
677
|
" ",
|
|
532
678
|
time,
|
|
533
|
-
"
|
|
679
|
+
" "
|
|
534
680
|
] }),
|
|
535
681
|
/* @__PURE__ */ jsx3(Text3, { color: "white", children: request.modelId }),
|
|
536
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "
|
|
682
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: " " }),
|
|
537
683
|
/* @__PURE__ */ jsx3(Text3, { color: typeLabel.color, children: typeLabel.label }),
|
|
538
684
|
/* @__PURE__ */ jsxs3(Text3, { color: "red", children: [
|
|
539
|
-
"
|
|
685
|
+
" ",
|
|
540
686
|
request.error || "Failed"
|
|
541
687
|
] })
|
|
542
688
|
] }) });
|
|
543
689
|
}
|
|
544
|
-
function RequestLog({
|
|
690
|
+
function RequestLog({
|
|
691
|
+
requests,
|
|
692
|
+
maxVisible = 8,
|
|
693
|
+
hasModels = true
|
|
694
|
+
}) {
|
|
545
695
|
const { stdout } = useStdout2();
|
|
546
696
|
const width = stdout?.columns ?? 80;
|
|
547
697
|
const activeRequests = requests.filter((r) => r.status === "processing");
|
|
@@ -615,6 +765,8 @@ function DashboardPage({
|
|
|
615
765
|
syncedNames,
|
|
616
766
|
modelsLoading,
|
|
617
767
|
syncStatus = "idle",
|
|
768
|
+
editorSessions,
|
|
769
|
+
editorsLoading,
|
|
618
770
|
onNavigate
|
|
619
771
|
}) {
|
|
620
772
|
const { stdout } = useStdout3();
|
|
@@ -629,11 +781,11 @@ function DashboardPage({
|
|
|
629
781
|
(name) => !allModelNames.has(name)
|
|
630
782
|
);
|
|
631
783
|
const syncDescription = syncStatus === "syncing" ? "Syncing..." : syncStatus === "synced" ? "\u2713 Synced" : "Re-detect providers and sync models to MindStudio";
|
|
632
|
-
const menuItems =
|
|
784
|
+
const menuItems = useMemo2(() => {
|
|
633
785
|
return [
|
|
634
786
|
{
|
|
635
787
|
id: "interfaces",
|
|
636
|
-
label: "Connect to
|
|
788
|
+
label: "Connect to Agent",
|
|
637
789
|
description: "Connect your local editor to a MindStudio interface or script"
|
|
638
790
|
},
|
|
639
791
|
{
|
|
@@ -663,16 +815,25 @@ function DashboardPage({
|
|
|
663
815
|
const headerLines = compactHeader ? 7 : 14;
|
|
664
816
|
const providerContentLines = providersLoading ? 1 : installedProviders.length === 0 ? 2 : installedProviders.length;
|
|
665
817
|
const providersLines = 3 + providerContentLines;
|
|
818
|
+
const editorsContentLines = editorsLoading ? 1 : editorSessions.length === 0 ? 1 : editorSessions.length;
|
|
819
|
+
const editorsLines = 3 + editorsContentLines;
|
|
666
820
|
const modelContentLines = modelsLoading ? 1 : models.length === 0 && unavailableSynced.length === 0 && modelWarnings.length === 0 ? 2 : models.length + modelWarnings.length + (unavailableSynced.length > 0 ? 1 + unavailableSynced.length : 0);
|
|
667
821
|
const modelsLines = 3 + modelContentLines;
|
|
668
822
|
const requestLogOverhead = 3;
|
|
669
823
|
const compactMenu = termHeight + 4 < 40;
|
|
670
824
|
const menuLines = compactMenu ? 2 : menuItems.length + 6;
|
|
671
|
-
const usedLines = headerLines + providersLines + modelsLines + requestLogOverhead + menuLines;
|
|
825
|
+
const usedLines = headerLines + providersLines + editorsLines + modelsLines + requestLogOverhead + menuLines;
|
|
672
826
|
const maxVisible = Math.max(3, termHeight - usedLines);
|
|
673
827
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", flexGrow: 1, children: [
|
|
674
828
|
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
|
|
675
|
-
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", underline: true, children: "
|
|
829
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", underline: true, children: "Open Agents" }),
|
|
830
|
+
editorsLoading ? /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
831
|
+
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: /* @__PURE__ */ jsx4(Spinner2, { type: "dots" }) }),
|
|
832
|
+
/* @__PURE__ */ jsx4(Text4, { children: " Loading editor sessions..." })
|
|
833
|
+
] }) : editorSessions.length === 0 ? /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Agents you are editing in the MindStudio IDE will appear here." }) }) : /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginTop: 1, children: editorSessions.map((session) => /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(Text4, { color: "white", children: session.appName }) }, session.appId)) })
|
|
834
|
+
] }),
|
|
835
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
|
|
836
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", underline: true, children: "AI Model Providers" }),
|
|
676
837
|
providersLoading ? /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
677
838
|
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: /* @__PURE__ */ jsx4(Spinner2, { type: "dots" }) }),
|
|
678
839
|
/* @__PURE__ */ jsx4(Text4, { children: " Detecting providers..." })
|
|
@@ -691,7 +852,7 @@ function DashboardPage({
|
|
|
691
852
|
}) })
|
|
692
853
|
] }),
|
|
693
854
|
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
|
|
694
|
-
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", underline: true, children: "Models" }),
|
|
855
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "white", underline: true, children: "Local Models" }),
|
|
695
856
|
modelsLoading ? /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
696
857
|
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: /* @__PURE__ */ jsx4(Spinner2, { type: "dots" }) }),
|
|
697
858
|
/* @__PURE__ */ jsx4(Text4, { children: " Discovering models..." })
|
|
@@ -748,18 +909,18 @@ function DashboardPage({
|
|
|
748
909
|
}
|
|
749
910
|
|
|
750
911
|
// src/tui/models/pages/SetupPage.tsx
|
|
751
|
-
import { useState as
|
|
912
|
+
import { useState as useState9, useMemo as useMemo4, useEffect as useEffect9 } from "react";
|
|
752
913
|
import { Box as Box5, Text as Text6, useInput as useInput2, useStdout as useStdout5 } from "ink";
|
|
753
914
|
import Spinner3 from "ink-spinner";
|
|
754
915
|
|
|
755
916
|
// src/tui/components/MarkdownText.tsx
|
|
756
|
-
import { useMemo as
|
|
917
|
+
import { useMemo as useMemo3 } from "react";
|
|
757
918
|
import { Text as Text5, useStdout as useStdout4 } from "ink";
|
|
758
|
-
import
|
|
919
|
+
import chalk2 from "chalk";
|
|
759
920
|
import { marked } from "marked";
|
|
760
921
|
import { markedTerminal } from "marked-terminal";
|
|
761
922
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
762
|
-
var codeStyle =
|
|
923
|
+
var codeStyle = chalk2.cyan;
|
|
763
924
|
var identity = (s) => s;
|
|
764
925
|
function renderMarkdown(content, width) {
|
|
765
926
|
marked.use(
|
|
@@ -793,7 +954,7 @@ function ProviderDetailView({
|
|
|
793
954
|
provider,
|
|
794
955
|
onBack
|
|
795
956
|
}) {
|
|
796
|
-
const [scrollOffset, setScrollOffset] =
|
|
957
|
+
const [scrollOffset, setScrollOffset] = useState9(0);
|
|
797
958
|
const { stdout } = useStdout5();
|
|
798
959
|
const termHeight = (stdout?.rows ?? 24) - 4;
|
|
799
960
|
const headerHeight = 14;
|
|
@@ -801,7 +962,7 @@ function ProviderDetailView({
|
|
|
801
962
|
const contentPadding = 2;
|
|
802
963
|
const viewHeight = termHeight - headerHeight - footerLines - contentPadding;
|
|
803
964
|
const contentWidth = (stdout?.columns ?? 80) - 4;
|
|
804
|
-
const renderedLines =
|
|
965
|
+
const renderedLines = useMemo4(() => {
|
|
805
966
|
const rendered = renderMarkdown(provider.readme, contentWidth);
|
|
806
967
|
return rendered.split("\n");
|
|
807
968
|
}, [provider.readme, contentWidth]);
|
|
@@ -818,7 +979,7 @@ function ProviderDetailView({
|
|
|
818
979
|
}
|
|
819
980
|
});
|
|
820
981
|
const visibleContent = renderedLines.slice(scrollOffset, scrollOffset + viewHeight).join("\n");
|
|
821
|
-
const scrollbar =
|
|
982
|
+
const scrollbar = useMemo4(() => {
|
|
822
983
|
if (maxScroll === 0) return null;
|
|
823
984
|
const thumbSize = Math.max(
|
|
824
985
|
1,
|
|
@@ -888,27 +1049,27 @@ function ProviderDetailView({
|
|
|
888
1049
|
}
|
|
889
1050
|
function SetupPage({ onBack }) {
|
|
890
1051
|
const { providers, loading } = useSetupProviders();
|
|
891
|
-
const [selectedProvider, setSelectedProvider] =
|
|
892
|
-
const running =
|
|
1052
|
+
const [selectedProvider, setSelectedProvider] = useState9(null);
|
|
1053
|
+
const running = useMemo4(
|
|
893
1054
|
() => providers.filter((p) => p.status.running),
|
|
894
1055
|
[providers]
|
|
895
1056
|
);
|
|
896
|
-
const installed =
|
|
1057
|
+
const installed = useMemo4(
|
|
897
1058
|
() => providers.filter((p) => p.status.installed && !p.status.running),
|
|
898
1059
|
[providers]
|
|
899
1060
|
);
|
|
900
|
-
const notInstalled =
|
|
1061
|
+
const notInstalled = useMemo4(
|
|
901
1062
|
() => providers.filter((p) => !p.status.installed),
|
|
902
1063
|
[providers]
|
|
903
1064
|
);
|
|
904
|
-
const allProviders =
|
|
1065
|
+
const allProviders = useMemo4(
|
|
905
1066
|
() => [...running, ...installed, ...notInstalled],
|
|
906
1067
|
[running, installed, notInstalled]
|
|
907
1068
|
);
|
|
908
1069
|
const totalItems = allProviders.length + 1;
|
|
909
1070
|
const backIndex = allProviders.length;
|
|
910
|
-
const [cursorIndex, setCursorIndex] =
|
|
911
|
-
|
|
1071
|
+
const [cursorIndex, setCursorIndex] = useState9(0);
|
|
1072
|
+
useEffect9(() => {
|
|
912
1073
|
setCursorIndex(0);
|
|
913
1074
|
}, [allProviders.length]);
|
|
914
1075
|
useInput2((input, key) => {
|
|
@@ -1088,51 +1249,11 @@ function SetupPage({ onBack }) {
|
|
|
1088
1249
|
}
|
|
1089
1250
|
|
|
1090
1251
|
// src/tui/interfaces/pages/InterfacesPage.tsx
|
|
1091
|
-
import { useState as
|
|
1252
|
+
import { useState as useState13, useMemo as useMemo6, useEffect as useEffect13, useRef as useRef7 } from "react";
|
|
1092
1253
|
import { Box as Box8, Text as Text9, useInput as useInput5 } from "ink";
|
|
1093
|
-
import Spinner5 from "ink-spinner";
|
|
1094
|
-
|
|
1095
|
-
// src/tui/interfaces/hooks/useEditorSessions.ts
|
|
1096
|
-
import { useState as useState8, useEffect as useEffect8, useCallback as useCallback6, useRef as useRef4 } from "react";
|
|
1097
|
-
function useEditorSessions() {
|
|
1098
|
-
const [sessions, setSessions] = useState8([]);
|
|
1099
|
-
const [loading, setLoading] = useState8(true);
|
|
1100
|
-
const [error, setError] = useState8(null);
|
|
1101
|
-
const [refreshStatus, setRefreshStatus] = useState8("idle");
|
|
1102
|
-
const initialLoadDone = useRef4(false);
|
|
1103
|
-
const timerRef = useRef4();
|
|
1104
|
-
const refresh = useCallback6(async () => {
|
|
1105
|
-
if (!initialLoadDone.current) {
|
|
1106
|
-
setLoading(true);
|
|
1107
|
-
} else {
|
|
1108
|
-
setRefreshStatus("refreshing");
|
|
1109
|
-
}
|
|
1110
|
-
setError(null);
|
|
1111
|
-
try {
|
|
1112
|
-
const data = await getEditorSessions();
|
|
1113
|
-
setSessions(data);
|
|
1114
|
-
initialLoadDone.current = true;
|
|
1115
|
-
setRefreshStatus("refreshed");
|
|
1116
|
-
clearTimeout(timerRef.current);
|
|
1117
|
-
timerRef.current = setTimeout(() => setRefreshStatus("idle"), 1500);
|
|
1118
|
-
} catch (err) {
|
|
1119
|
-
setError(err instanceof Error ? err.message : "Failed to fetch sessions");
|
|
1120
|
-
setRefreshStatus("idle");
|
|
1121
|
-
} finally {
|
|
1122
|
-
setLoading(false);
|
|
1123
|
-
}
|
|
1124
|
-
}, []);
|
|
1125
|
-
useEffect8(() => {
|
|
1126
|
-
refresh();
|
|
1127
|
-
}, [refresh]);
|
|
1128
|
-
useEffect8(() => {
|
|
1129
|
-
return () => clearTimeout(timerRef.current);
|
|
1130
|
-
}, []);
|
|
1131
|
-
return { sessions, loading, error, refreshStatus, refresh };
|
|
1132
|
-
}
|
|
1133
1254
|
|
|
1134
1255
|
// src/tui/interfaces/hooks/useLocalInterface.ts
|
|
1135
|
-
import { useState as
|
|
1256
|
+
import { useState as useState10, useCallback as useCallback7, useRef as useRef5, useEffect as useEffect10 } from "react";
|
|
1136
1257
|
import { spawn } from "child_process";
|
|
1137
1258
|
import crypto from "crypto";
|
|
1138
1259
|
import fs from "fs";
|
|
@@ -1148,7 +1269,7 @@ function useLocalInterface({
|
|
|
1148
1269
|
sessionId
|
|
1149
1270
|
}) {
|
|
1150
1271
|
const key = `${appId}:${stepId}`;
|
|
1151
|
-
const [hasLocalCopy, setHasLocalCopy] =
|
|
1272
|
+
const [hasLocalCopy, setHasLocalCopy] = useState10(() => {
|
|
1152
1273
|
const existing = getLocalInterfacePath(key);
|
|
1153
1274
|
if (!existing) return false;
|
|
1154
1275
|
try {
|
|
@@ -1157,13 +1278,13 @@ function useLocalInterface({
|
|
|
1157
1278
|
return false;
|
|
1158
1279
|
}
|
|
1159
1280
|
});
|
|
1160
|
-
const [phase, setPhase] =
|
|
1161
|
-
const [outputLines, setOutputLines] =
|
|
1162
|
-
const [errorMessage, setErrorMessage] =
|
|
1281
|
+
const [phase, setPhase] = useState10("idle");
|
|
1282
|
+
const [outputLines, setOutputLines] = useState10([]);
|
|
1283
|
+
const [errorMessage, setErrorMessage] = useState10(null);
|
|
1163
1284
|
const processRef = useRef5(null);
|
|
1164
1285
|
const mountedRef = useRef5(true);
|
|
1165
1286
|
const stoppedRef = useRef5(false);
|
|
1166
|
-
|
|
1287
|
+
useEffect10(() => {
|
|
1167
1288
|
mountedRef.current = true;
|
|
1168
1289
|
return () => {
|
|
1169
1290
|
mountedRef.current = false;
|
|
@@ -1218,16 +1339,21 @@ function useLocalInterface({
|
|
|
1218
1339
|
const env = {};
|
|
1219
1340
|
if (getEnvironment() === "local") {
|
|
1220
1341
|
env.MINDSTUDIO_API_URL = getApiBaseUrl();
|
|
1342
|
+
env.MINDSTUDIO_WS_URL = "ws://localhost:8888";
|
|
1221
1343
|
}
|
|
1222
|
-
|
|
1223
|
-
env.MINDSTUDIO_API_KEY = getApiKey() ?? "";
|
|
1224
|
-
return {
|
|
1225
|
-
args: ["run", "dev:local", "--", "--app", appId, "--workflow", workflowId, "--step", stepId],
|
|
1226
|
-
env
|
|
1227
|
-
};
|
|
1228
|
-
}
|
|
1344
|
+
env.MINDSTUDIO_API_KEY = getApiKey() ?? "";
|
|
1229
1345
|
return {
|
|
1230
|
-
args: [
|
|
1346
|
+
args: [
|
|
1347
|
+
"run",
|
|
1348
|
+
"dev:local",
|
|
1349
|
+
"--",
|
|
1350
|
+
"--app",
|
|
1351
|
+
appId,
|
|
1352
|
+
"--workflow",
|
|
1353
|
+
workflowId,
|
|
1354
|
+
"--step",
|
|
1355
|
+
stepId
|
|
1356
|
+
],
|
|
1231
1357
|
env
|
|
1232
1358
|
};
|
|
1233
1359
|
};
|
|
@@ -1290,14 +1416,21 @@ function useLocalInterface({
|
|
|
1290
1416
|
} catch (err) {
|
|
1291
1417
|
if (mountedRef.current) {
|
|
1292
1418
|
setPhase("error");
|
|
1293
|
-
setErrorMessage(
|
|
1294
|
-
err instanceof Error ? err.message : "Unknown error"
|
|
1295
|
-
);
|
|
1419
|
+
setErrorMessage(err instanceof Error ? err.message : "Unknown error");
|
|
1296
1420
|
}
|
|
1297
1421
|
}
|
|
1298
1422
|
};
|
|
1299
1423
|
run();
|
|
1300
|
-
}, [
|
|
1424
|
+
}, [
|
|
1425
|
+
key,
|
|
1426
|
+
mode,
|
|
1427
|
+
appId,
|
|
1428
|
+
stepId,
|
|
1429
|
+
workflowId,
|
|
1430
|
+
sessionId,
|
|
1431
|
+
appendOutput,
|
|
1432
|
+
runCommand
|
|
1433
|
+
]);
|
|
1301
1434
|
const stop = useCallback7(() => {
|
|
1302
1435
|
stoppedRef.current = true;
|
|
1303
1436
|
if (processRef.current) {
|
|
@@ -1324,9 +1457,7 @@ function useLocalInterface({
|
|
|
1324
1457
|
setHasLocalCopy(false);
|
|
1325
1458
|
appendOutput("Deleted successfully.");
|
|
1326
1459
|
} catch (err) {
|
|
1327
|
-
setErrorMessage(
|
|
1328
|
-
err instanceof Error ? err.message : "Failed to delete"
|
|
1329
|
-
);
|
|
1460
|
+
setErrorMessage(err instanceof Error ? err.message : "Failed to delete");
|
|
1330
1461
|
}
|
|
1331
1462
|
setPhase("idle");
|
|
1332
1463
|
}, [key, appendOutput]);
|
|
@@ -1343,7 +1474,7 @@ function useLocalInterface({
|
|
|
1343
1474
|
}
|
|
1344
1475
|
|
|
1345
1476
|
// src/tui/interfaces/pages/InterfaceSessionView.tsx
|
|
1346
|
-
import { useState as
|
|
1477
|
+
import { useState as useState11, useEffect as useEffect11 } from "react";
|
|
1347
1478
|
import { Box as Box6, Text as Text7, useInput as useInput3 } from "ink";
|
|
1348
1479
|
import os2 from "os";
|
|
1349
1480
|
import open from "open";
|
|
@@ -1364,8 +1495,8 @@ function InterfaceSessionView({
|
|
|
1364
1495
|
menuItems.push({ id: "delete", label: "Delete Local Copy" });
|
|
1365
1496
|
}
|
|
1366
1497
|
menuItems.push({ id: "back", label: "Back" });
|
|
1367
|
-
const [cursorIndex, setCursorIndex] =
|
|
1368
|
-
|
|
1498
|
+
const [cursorIndex, setCursorIndex] = useState11(0);
|
|
1499
|
+
useEffect11(() => {
|
|
1369
1500
|
setCursorIndex(0);
|
|
1370
1501
|
}, [hasLocalCopy]);
|
|
1371
1502
|
useInput3((input, key) => {
|
|
@@ -1447,7 +1578,7 @@ function InterfaceSessionView({
|
|
|
1447
1578
|
}
|
|
1448
1579
|
|
|
1449
1580
|
// src/tui/interfaces/pages/InterfaceRunningView.tsx
|
|
1450
|
-
import { useState as
|
|
1581
|
+
import { useState as useState12, useMemo as useMemo5, useRef as useRef6, useEffect as useEffect12 } from "react";
|
|
1451
1582
|
import { Box as Box7, Text as Text8, useInput as useInput4, useStdout as useStdout6 } from "ink";
|
|
1452
1583
|
import { execSync } from "child_process";
|
|
1453
1584
|
import os3 from "os";
|
|
@@ -1473,13 +1604,21 @@ function getPhaseLabel(phase) {
|
|
|
1473
1604
|
case "cloning":
|
|
1474
1605
|
return { text: "Cloning scaffold...", color: "cyan", showSpinner: true };
|
|
1475
1606
|
case "installing":
|
|
1476
|
-
return {
|
|
1607
|
+
return {
|
|
1608
|
+
text: "Installing dependencies...",
|
|
1609
|
+
color: "cyan",
|
|
1610
|
+
showSpinner: true
|
|
1611
|
+
};
|
|
1477
1612
|
case "running":
|
|
1478
1613
|
return { text: "Dev server running", color: "green", showSpinner: true };
|
|
1479
1614
|
case "error":
|
|
1480
1615
|
return { text: "Error", color: "red", showSpinner: false };
|
|
1481
1616
|
case "deleting":
|
|
1482
|
-
return {
|
|
1617
|
+
return {
|
|
1618
|
+
text: "Deleting local copy...",
|
|
1619
|
+
color: "yellow",
|
|
1620
|
+
showSpinner: true
|
|
1621
|
+
};
|
|
1483
1622
|
default:
|
|
1484
1623
|
return { text: "Idle", color: "gray", showSpinner: false };
|
|
1485
1624
|
}
|
|
@@ -1497,20 +1636,28 @@ function InterfaceRunningView({
|
|
|
1497
1636
|
const termHeight = (stdout?.rows ?? 24) - 4;
|
|
1498
1637
|
const isActive = phase === "cloning" || phase === "installing" || phase === "running" || phase === "deleting";
|
|
1499
1638
|
const displayPath = localPath?.replace(os3.homedir(), "~");
|
|
1500
|
-
const menuItems =
|
|
1639
|
+
const menuItems = useMemo5(() => {
|
|
1501
1640
|
const items = [];
|
|
1502
1641
|
if (isActive && displayPath) {
|
|
1503
|
-
items.push({
|
|
1504
|
-
|
|
1642
|
+
items.push({
|
|
1643
|
+
id: "claude",
|
|
1644
|
+
label: "Copy Claude Code Command",
|
|
1645
|
+
copyValue: `cd ${displayPath} && claude`
|
|
1646
|
+
});
|
|
1647
|
+
items.push({
|
|
1648
|
+
id: "codex",
|
|
1649
|
+
label: "Copy Codex Command",
|
|
1650
|
+
copyValue: `cd ${displayPath} && codex`
|
|
1651
|
+
});
|
|
1505
1652
|
items.push({ id: "reveal", label: "Open Folder" });
|
|
1506
1653
|
}
|
|
1507
1654
|
items.push({ id: "action", label: isActive ? "Stop" : "Back" });
|
|
1508
1655
|
return items;
|
|
1509
1656
|
}, [isActive, displayPath]);
|
|
1510
|
-
const [cursorIndex, setCursorIndex] =
|
|
1511
|
-
const [copiedId, setCopiedId] =
|
|
1657
|
+
const [cursorIndex, setCursorIndex] = useState12(0);
|
|
1658
|
+
const [copiedId, setCopiedId] = useState12(null);
|
|
1512
1659
|
const copiedTimerRef = useRef6();
|
|
1513
|
-
|
|
1660
|
+
useEffect12(() => {
|
|
1514
1661
|
return () => clearTimeout(copiedTimerRef.current);
|
|
1515
1662
|
}, []);
|
|
1516
1663
|
const headerHeight = 14;
|
|
@@ -1590,14 +1737,15 @@ function InterfaceRunningView({
|
|
|
1590
1737
|
"\u2022",
|
|
1591
1738
|
" Enter Select ",
|
|
1592
1739
|
"\u2022",
|
|
1593
|
-
" q/Esc
|
|
1740
|
+
" q/Esc",
|
|
1741
|
+
" ",
|
|
1594
1742
|
isActive ? "Stop" : "Back"
|
|
1595
1743
|
] }) })
|
|
1596
1744
|
] }) });
|
|
1597
1745
|
}
|
|
1598
1746
|
|
|
1599
1747
|
// src/tui/interfaces/pages/InterfacesPage.tsx
|
|
1600
|
-
import {
|
|
1748
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1601
1749
|
function getSessionStatus(item) {
|
|
1602
1750
|
if (item.kind === "script") return "running";
|
|
1603
1751
|
const status = item.step.spaEditorSession?.status;
|
|
@@ -1640,10 +1788,7 @@ function formatCount(interfaces, scripts) {
|
|
|
1640
1788
|
}
|
|
1641
1789
|
return parts.join(", ");
|
|
1642
1790
|
}
|
|
1643
|
-
function OfflineView({
|
|
1644
|
-
item,
|
|
1645
|
-
onBack
|
|
1646
|
-
}) {
|
|
1791
|
+
function OfflineView({ item, onBack }) {
|
|
1647
1792
|
useInput5((input, key) => {
|
|
1648
1793
|
if (input === "q" || key.escape || key.return) {
|
|
1649
1794
|
onBack();
|
|
@@ -1673,8 +1818,8 @@ function AgentListView({
|
|
|
1673
1818
|
const refreshIndex = sessions.length;
|
|
1674
1819
|
const backIndex = sessions.length + 1;
|
|
1675
1820
|
const totalItems = sessions.length + 2;
|
|
1676
|
-
const [cursorIndex, setCursorIndex] =
|
|
1677
|
-
|
|
1821
|
+
const [cursorIndex, setCursorIndex] = useState13(0);
|
|
1822
|
+
useEffect13(() => {
|
|
1678
1823
|
setCursorIndex(sessions.length > 0 ? 0 : backIndex);
|
|
1679
1824
|
}, [sessions.length, backIndex]);
|
|
1680
1825
|
useInput5((input, key) => {
|
|
@@ -1698,35 +1843,48 @@ function AgentListView({
|
|
|
1698
1843
|
});
|
|
1699
1844
|
return /* @__PURE__ */ jsx9(Box8, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
|
|
1700
1845
|
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "white", underline: true, children: "Choose an Agent" }),
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
/* @__PURE__ */ jsx9(Text9, { color: "gray", children: "Open an app in MindStudio's editor to see sessions here." })
|
|
1704
|
-
] }) : /* @__PURE__ */ jsx9(Box8, { flexDirection: "column", marginTop: 1, children: sessions.map((session, i) => {
|
|
1846
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", children: "Don't see your agent? Make sure it's open in the MindStudio editor." }),
|
|
1847
|
+
sessions.length === 0 ? /* @__PURE__ */ jsx9(Box8, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "No active editor sessions." }) }) : /* @__PURE__ */ jsx9(Box8, { flexDirection: "column", marginTop: 1, children: sessions.map((session, i) => {
|
|
1705
1848
|
const isSelected = i === cursorIndex;
|
|
1706
1849
|
const stats = formatCount(
|
|
1707
1850
|
session.customInterfaceSteps.length,
|
|
1708
1851
|
session.scriptSteps.length
|
|
1709
1852
|
);
|
|
1710
|
-
return /* @__PURE__ */ jsxs8(
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1853
|
+
return /* @__PURE__ */ jsxs8(
|
|
1854
|
+
Box8,
|
|
1855
|
+
{
|
|
1856
|
+
flexDirection: "column",
|
|
1857
|
+
marginTop: i > 0 ? 1 : 0,
|
|
1858
|
+
children: [
|
|
1859
|
+
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1860
|
+
/* @__PURE__ */ jsxs8(
|
|
1861
|
+
Text9,
|
|
1862
|
+
{
|
|
1863
|
+
color: isSelected ? "cyan" : "white",
|
|
1864
|
+
bold: isSelected,
|
|
1865
|
+
children: [
|
|
1866
|
+
isSelected ? "\u276F" : " ",
|
|
1867
|
+
" ",
|
|
1868
|
+
session.appName
|
|
1869
|
+
]
|
|
1870
|
+
}
|
|
1871
|
+
),
|
|
1872
|
+
isSelected && /* @__PURE__ */ jsx9(Text9, { color: "gray", children: " - Connect to this Agent" })
|
|
1873
|
+
] }),
|
|
1874
|
+
/* @__PURE__ */ jsxs8(Text9, { color: "gray", children: [
|
|
1875
|
+
" ",
|
|
1876
|
+
"https://app.mindstudio.ai/agents/",
|
|
1877
|
+
session.appId,
|
|
1878
|
+
"/edit"
|
|
1879
|
+
] }),
|
|
1880
|
+
stats !== "" && /* @__PURE__ */ jsxs8(Text9, { color: "gray", children: [
|
|
1881
|
+
" ",
|
|
1882
|
+
stats
|
|
1883
|
+
] })
|
|
1884
|
+
]
|
|
1885
|
+
},
|
|
1886
|
+
session.appId
|
|
1887
|
+
);
|
|
1730
1888
|
}) }),
|
|
1731
1889
|
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
|
|
1732
1890
|
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
@@ -1774,11 +1932,8 @@ function AgentDetailView({
|
|
|
1774
1932
|
onRefresh,
|
|
1775
1933
|
refreshStatus
|
|
1776
1934
|
}) {
|
|
1777
|
-
const [offlineItem, setOfflineItem] =
|
|
1778
|
-
|
|
1779
|
-
onRefresh();
|
|
1780
|
-
}, []);
|
|
1781
|
-
const interfaces = useMemo5(
|
|
1935
|
+
const [offlineItem, setOfflineItem] = useState13(null);
|
|
1936
|
+
const interfaces = useMemo6(
|
|
1782
1937
|
() => session.customInterfaceSteps.map((step) => ({
|
|
1783
1938
|
kind: "interface",
|
|
1784
1939
|
appId: session.appId,
|
|
@@ -1787,7 +1942,7 @@ function AgentDetailView({
|
|
|
1787
1942
|
})),
|
|
1788
1943
|
[session]
|
|
1789
1944
|
);
|
|
1790
|
-
const scripts =
|
|
1945
|
+
const scripts = useMemo6(
|
|
1791
1946
|
() => session.scriptSteps.map((step) => ({
|
|
1792
1947
|
kind: "script",
|
|
1793
1948
|
appId: session.appId,
|
|
@@ -1796,15 +1951,15 @@ function AgentDetailView({
|
|
|
1796
1951
|
})),
|
|
1797
1952
|
[session]
|
|
1798
1953
|
);
|
|
1799
|
-
const allItems =
|
|
1954
|
+
const allItems = useMemo6(
|
|
1800
1955
|
() => [...interfaces, ...scripts],
|
|
1801
1956
|
[interfaces, scripts]
|
|
1802
1957
|
);
|
|
1803
1958
|
const refreshIndex = allItems.length;
|
|
1804
1959
|
const backIndex = allItems.length + 1;
|
|
1805
1960
|
const totalItems = allItems.length + 2;
|
|
1806
|
-
const [cursorIndex, setCursorIndex] =
|
|
1807
|
-
|
|
1961
|
+
const [cursorIndex, setCursorIndex] = useState13(0);
|
|
1962
|
+
useEffect13(() => {
|
|
1808
1963
|
setCursorIndex(0);
|
|
1809
1964
|
}, [allItems.length]);
|
|
1810
1965
|
useInput5((input, key) => {
|
|
@@ -1840,48 +1995,83 @@ function AgentDetailView({
|
|
|
1840
1995
|
const scriptsOffset = interfaces.length;
|
|
1841
1996
|
return /* @__PURE__ */ jsx9(Box8, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
|
|
1842
1997
|
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "white", underline: true, children: session.appName }),
|
|
1998
|
+
/* @__PURE__ */ jsxs8(Text9, { color: "gray", children: [
|
|
1999
|
+
"https://app.mindstudio.ai/agents/",
|
|
2000
|
+
session.appId,
|
|
2001
|
+
"/edit"
|
|
2002
|
+
] }),
|
|
1843
2003
|
/* @__PURE__ */ jsx9(Text9, { color: "gray", children: "Select an interface or script to connect your local editor." }),
|
|
1844
2004
|
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
2005
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "white", children: "Interfaces" }),
|
|
2006
|
+
interfaces.length > 0 ? /* @__PURE__ */ jsx9(Box8, { flexDirection: "column", marginTop: 1, children: interfaces.map((item, i) => {
|
|
2007
|
+
const isSelected = i === cursorIndex;
|
|
2008
|
+
const status = getSessionStatus(item);
|
|
2009
|
+
const statusLabel = getStatusLabel(status);
|
|
2010
|
+
return /* @__PURE__ */ jsxs8(
|
|
2011
|
+
Box8,
|
|
2012
|
+
{
|
|
2013
|
+
flexDirection: "column",
|
|
2014
|
+
marginTop: i > 0 ? 1 : 0,
|
|
2015
|
+
children: [
|
|
2016
|
+
/* @__PURE__ */ jsxs8(
|
|
2017
|
+
Text9,
|
|
2018
|
+
{
|
|
2019
|
+
color: isSelected ? "cyan" : "white",
|
|
2020
|
+
bold: isSelected,
|
|
2021
|
+
children: [
|
|
2022
|
+
isSelected ? "\u276F" : " ",
|
|
2023
|
+
" ",
|
|
2024
|
+
item.step.workflowName,
|
|
2025
|
+
" -",
|
|
2026
|
+
" ",
|
|
2027
|
+
item.step.displayName
|
|
2028
|
+
]
|
|
2029
|
+
}
|
|
2030
|
+
),
|
|
2031
|
+
/* @__PURE__ */ jsx9(Box8, { children: /* @__PURE__ */ jsxs8(Text9, { color: statusLabel.color, children: [
|
|
2032
|
+
" ",
|
|
2033
|
+
statusLabel.text
|
|
2034
|
+
] }) })
|
|
2035
|
+
]
|
|
2036
|
+
},
|
|
2037
|
+
`${item.step.workflowId}:${item.step.stepId}`
|
|
2038
|
+
);
|
|
2039
|
+
}) }) : /* @__PURE__ */ jsx9(Text9, { color: "gray", children: " No interfaces in this agent." }),
|
|
2040
|
+
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
|
|
2041
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "white", children: "Scripts" }),
|
|
2042
|
+
scripts.length > 0 ? /* @__PURE__ */ jsx9(Box8, { flexDirection: "column", marginTop: 1, children: scripts.map((item, i) => {
|
|
1869
2043
|
const index = scriptsOffset + i;
|
|
1870
2044
|
const isSelected = index === cursorIndex;
|
|
1871
|
-
return /* @__PURE__ */ jsxs8(
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
2045
|
+
return /* @__PURE__ */ jsxs8(
|
|
2046
|
+
Box8,
|
|
2047
|
+
{
|
|
2048
|
+
flexDirection: "column",
|
|
2049
|
+
marginTop: i > 0 ? 1 : 0,
|
|
2050
|
+
children: [
|
|
2051
|
+
/* @__PURE__ */ jsxs8(
|
|
2052
|
+
Text9,
|
|
2053
|
+
{
|
|
2054
|
+
color: isSelected ? "cyan" : "white",
|
|
2055
|
+
bold: isSelected,
|
|
2056
|
+
children: [
|
|
2057
|
+
isSelected ? "\u276F" : " ",
|
|
2058
|
+
" ",
|
|
2059
|
+
item.step.workflowName,
|
|
2060
|
+
" -",
|
|
2061
|
+
" ",
|
|
2062
|
+
item.step.displayName
|
|
2063
|
+
]
|
|
2064
|
+
}
|
|
2065
|
+
),
|
|
2066
|
+
/* @__PURE__ */ jsxs8(Text9, { color: "gray", children: [
|
|
2067
|
+
" ",
|
|
2068
|
+
item.step.entryFile
|
|
2069
|
+
] })
|
|
2070
|
+
]
|
|
2071
|
+
},
|
|
2072
|
+
`${item.step.workflowId}:${item.step.stepId}`
|
|
2073
|
+
);
|
|
2074
|
+
}) }) : /* @__PURE__ */ jsx9(Text9, { color: "gray", children: " No scripts in this agent." })
|
|
1885
2075
|
] }),
|
|
1886
2076
|
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
|
|
1887
2077
|
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
@@ -1952,7 +2142,7 @@ function LocalDevView({
|
|
|
1952
2142
|
const name = `${item.step.workflowName} - ${item.step.displayName}`;
|
|
1953
2143
|
const isActive = phase === "cloning" || phase === "installing" || phase === "running" || phase === "deleting";
|
|
1954
2144
|
const wasActiveRef = useRef7(false);
|
|
1955
|
-
|
|
2145
|
+
useEffect13(() => {
|
|
1956
2146
|
if (isActive) {
|
|
1957
2147
|
wasActiveRef.current = true;
|
|
1958
2148
|
} else if (wasActiveRef.current && phase === "idle") {
|
|
@@ -1986,33 +2176,16 @@ function LocalDevView({
|
|
|
1986
2176
|
}
|
|
1987
2177
|
);
|
|
1988
2178
|
}
|
|
1989
|
-
function InterfacesPage({
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: /* @__PURE__ */ jsx9(Spinner5, { type: "dots" }) }),
|
|
1998
|
-
/* @__PURE__ */ jsx9(Text9, { children: " Loading editor sessions..." })
|
|
1999
|
-
] })
|
|
2000
|
-
] });
|
|
2001
|
-
}
|
|
2002
|
-
if (error) {
|
|
2003
|
-
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", flexGrow: 1, paddingX: 1, marginTop: 1, children: [
|
|
2004
|
-
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "white", underline: true, children: "Choose an Agent" }),
|
|
2005
|
-
/* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "red", children: error }) })
|
|
2006
|
-
] });
|
|
2007
|
-
}
|
|
2179
|
+
function InterfacesPage({
|
|
2180
|
+
onBack,
|
|
2181
|
+
sessions,
|
|
2182
|
+
refreshStatus,
|
|
2183
|
+
refresh
|
|
2184
|
+
}) {
|
|
2185
|
+
const [selectedAppId, setSelectedAppId] = useState13(null);
|
|
2186
|
+
const [selectedItem, setSelectedItem] = useState13(null);
|
|
2008
2187
|
if (selectedItem) {
|
|
2009
|
-
return /* @__PURE__ */ jsx9(
|
|
2010
|
-
LocalDevView,
|
|
2011
|
-
{
|
|
2012
|
-
item: selectedItem,
|
|
2013
|
-
onBack: () => setSelectedItem(null)
|
|
2014
|
-
}
|
|
2015
|
-
);
|
|
2188
|
+
return /* @__PURE__ */ jsx9(LocalDevView, { item: selectedItem, onBack: () => setSelectedItem(null) });
|
|
2016
2189
|
}
|
|
2017
2190
|
if (selectedAppId) {
|
|
2018
2191
|
const session = sessions.find((s) => s.appId === selectedAppId);
|
|
@@ -2044,23 +2217,23 @@ function InterfacesPage({ onBack }) {
|
|
|
2044
2217
|
}
|
|
2045
2218
|
|
|
2046
2219
|
// src/tui/pages/OnboardingPage.tsx
|
|
2047
|
-
import { useEffect as
|
|
2220
|
+
import { useEffect as useEffect15, useCallback as useCallback9, useState as useState15, useMemo as useMemo7 } from "react";
|
|
2048
2221
|
import { Box as Box9, Text as Text10, useInput as useInput6 } from "ink";
|
|
2049
|
-
import
|
|
2050
|
-
import
|
|
2222
|
+
import Spinner5 from "ink-spinner";
|
|
2223
|
+
import chalk3 from "chalk";
|
|
2051
2224
|
|
|
2052
2225
|
// src/tui/hooks/useAuth.ts
|
|
2053
|
-
import { useState as
|
|
2226
|
+
import { useState as useState14, useCallback as useCallback8, useRef as useRef8, useEffect as useEffect14 } from "react";
|
|
2054
2227
|
import open3 from "open";
|
|
2055
2228
|
var POLL_INTERVAL = 2e3;
|
|
2056
2229
|
var MAX_ATTEMPTS = 30;
|
|
2057
2230
|
function useAuth() {
|
|
2058
|
-
const [status, setStatus] =
|
|
2059
|
-
const [authUrl, setAuthUrl] =
|
|
2060
|
-
const [timeRemaining, setTimeRemaining] =
|
|
2231
|
+
const [status, setStatus] = useState14("idle");
|
|
2232
|
+
const [authUrl, setAuthUrl] = useState14(null);
|
|
2233
|
+
const [timeRemaining, setTimeRemaining] = useState14(0);
|
|
2061
2234
|
const cancelledRef = useRef8(false);
|
|
2062
2235
|
const timerRef = useRef8(null);
|
|
2063
|
-
|
|
2236
|
+
useEffect14(() => {
|
|
2064
2237
|
return () => {
|
|
2065
2238
|
cancelledRef.current = true;
|
|
2066
2239
|
if (timerRef.current) clearInterval(timerRef.current);
|
|
@@ -2137,12 +2310,12 @@ function useAuth() {
|
|
|
2137
2310
|
}
|
|
2138
2311
|
|
|
2139
2312
|
// src/tui/pages/OnboardingPage.tsx
|
|
2140
|
-
import { Fragment as
|
|
2313
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2141
2314
|
var SHIMMER_SPEED = 35;
|
|
2142
2315
|
function useShimmerLogo() {
|
|
2143
|
-
const [frame, setFrame] =
|
|
2144
|
-
const lines =
|
|
2145
|
-
const totalChars =
|
|
2316
|
+
const [frame, setFrame] = useState15(0);
|
|
2317
|
+
const lines = useMemo7(() => LogoString.split("\n"), []);
|
|
2318
|
+
const totalChars = useMemo7(() => {
|
|
2146
2319
|
let count = 0;
|
|
2147
2320
|
for (const line of lines) {
|
|
2148
2321
|
for (const ch of line) {
|
|
@@ -2152,13 +2325,13 @@ function useShimmerLogo() {
|
|
|
2152
2325
|
return count;
|
|
2153
2326
|
}, [lines]);
|
|
2154
2327
|
const cycleLength = totalChars + 40;
|
|
2155
|
-
|
|
2328
|
+
useEffect15(() => {
|
|
2156
2329
|
const interval = setInterval(() => {
|
|
2157
2330
|
setFrame((f) => (f + 1) % cycleLength);
|
|
2158
2331
|
}, SHIMMER_SPEED);
|
|
2159
2332
|
return () => clearInterval(interval);
|
|
2160
2333
|
}, [cycleLength]);
|
|
2161
|
-
return
|
|
2334
|
+
return useMemo7(() => {
|
|
2162
2335
|
const sweepPos = frame;
|
|
2163
2336
|
const holdEnd = totalChars + 20;
|
|
2164
2337
|
let charIdx = 0;
|
|
@@ -2182,13 +2355,13 @@ function useShimmerLogo() {
|
|
|
2182
2355
|
brightness = Math.max(0.1, 1 - fadeProgress);
|
|
2183
2356
|
}
|
|
2184
2357
|
if (brightness >= 0.9) {
|
|
2185
|
-
result +=
|
|
2358
|
+
result += chalk3.cyanBright.bold(ch);
|
|
2186
2359
|
} else if (brightness >= 0.6) {
|
|
2187
|
-
result +=
|
|
2360
|
+
result += chalk3.cyan(ch);
|
|
2188
2361
|
} else if (brightness >= 0.3) {
|
|
2189
|
-
result +=
|
|
2362
|
+
result += chalk3.rgb(0, 100, 120)(ch);
|
|
2190
2363
|
} else {
|
|
2191
|
-
result +=
|
|
2364
|
+
result += chalk3.rgb(0, 50, 60)(ch);
|
|
2192
2365
|
}
|
|
2193
2366
|
charIdx++;
|
|
2194
2367
|
}
|
|
@@ -2205,13 +2378,13 @@ function OnboardingPage({ onComplete }) {
|
|
|
2205
2378
|
cancel: cancelAuth
|
|
2206
2379
|
} = useAuth();
|
|
2207
2380
|
const shimmerLogo = useShimmerLogo();
|
|
2208
|
-
|
|
2381
|
+
useEffect15(() => {
|
|
2209
2382
|
if (authStatus === "success") {
|
|
2210
2383
|
const timer = setTimeout(() => onComplete(), 1500);
|
|
2211
2384
|
return () => clearTimeout(timer);
|
|
2212
2385
|
}
|
|
2213
2386
|
}, [authStatus, onComplete]);
|
|
2214
|
-
|
|
2387
|
+
useEffect15(() => {
|
|
2215
2388
|
return () => cancelAuth();
|
|
2216
2389
|
}, []);
|
|
2217
2390
|
const handleAction = useCallback9(() => {
|
|
@@ -2230,17 +2403,17 @@ function OnboardingPage({ onComplete }) {
|
|
|
2230
2403
|
/* @__PURE__ */ jsx10(Text10, { children: shimmerLogo }),
|
|
2231
2404
|
/* @__PURE__ */ jsx10(Box9, { flexDirection: "column", alignItems: "center", marginTop: 2, children: /* @__PURE__ */ jsx10(Text10, { bold: true, color: "white", children: "MindStudio Local Tunnel" }) }),
|
|
2232
2405
|
/* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", alignItems: "center", children: [
|
|
2233
|
-
authStatus === "idle" && /* @__PURE__ */ jsxs9(
|
|
2406
|
+
authStatus === "idle" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
2234
2407
|
/* @__PURE__ */ jsx10(Text10, { color: "gray", children: "Connect your MindStudio account to get started." }),
|
|
2235
2408
|
/* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { color: "cyan", bold: true, children: "Press any key to Connect Account" }) })
|
|
2236
2409
|
] }),
|
|
2237
|
-
(authStatus === "expired" || authStatus === "timeout") && /* @__PURE__ */ jsxs9(
|
|
2410
|
+
(authStatus === "expired" || authStatus === "timeout") && /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
2238
2411
|
/* @__PURE__ */ jsx10(Text10, { color: "red", children: authStatus === "expired" ? "Authorization expired." : "Authorization timed out." }),
|
|
2239
2412
|
/* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { color: "cyan", bold: true, children: "Press any key to Try Again" }) })
|
|
2240
2413
|
] }),
|
|
2241
|
-
authStatus === "waiting" && /* @__PURE__ */ jsxs9(
|
|
2414
|
+
authStatus === "waiting" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
2242
2415
|
/* @__PURE__ */ jsxs9(Box9, { children: [
|
|
2243
|
-
/* @__PURE__ */ jsx10(Text10, { color: "cyan", children: /* @__PURE__ */ jsx10(
|
|
2416
|
+
/* @__PURE__ */ jsx10(Text10, { color: "cyan", children: /* @__PURE__ */ jsx10(Spinner5, { type: "dots" }) }),
|
|
2244
2417
|
/* @__PURE__ */ jsxs9(Text10, { children: [
|
|
2245
2418
|
" ",
|
|
2246
2419
|
"Waiting for browser authorization... (",
|
|
@@ -2264,7 +2437,7 @@ function OnboardingPage({ onComplete }) {
|
|
|
2264
2437
|
}
|
|
2265
2438
|
|
|
2266
2439
|
// src/tui/App.tsx
|
|
2267
|
-
import { Fragment as
|
|
2440
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2268
2441
|
var MODEL_TYPE_MAP = {
|
|
2269
2442
|
text: "llm_chat",
|
|
2270
2443
|
image: "image_generation",
|
|
@@ -2279,6 +2452,7 @@ function App({ runner }) {
|
|
|
2279
2452
|
error: connectionError,
|
|
2280
2453
|
retry: retryConnection
|
|
2281
2454
|
} = useConnection();
|
|
2455
|
+
const editorSessions = useEditorSessions();
|
|
2282
2456
|
const {
|
|
2283
2457
|
providers,
|
|
2284
2458
|
loading: providersLoading,
|
|
@@ -2290,37 +2464,37 @@ function App({ runner }) {
|
|
|
2290
2464
|
loading: modelsLoading,
|
|
2291
2465
|
refresh: refreshModels
|
|
2292
2466
|
} = useModels();
|
|
2293
|
-
const { requests } = useRequests();
|
|
2467
|
+
const { requests, activeCount: activeRequestCount } = useRequests();
|
|
2294
2468
|
const {
|
|
2295
2469
|
syncedNames,
|
|
2296
2470
|
syncedModels,
|
|
2297
2471
|
refresh: refreshSynced
|
|
2298
2472
|
} = useSyncedModels(connectionStatus);
|
|
2299
2473
|
const shouldOnboard = getApiKey() === void 0 || getUserId() === void 0;
|
|
2300
|
-
const [page, setPage] =
|
|
2474
|
+
const [page, setPage] = useState16(
|
|
2301
2475
|
shouldOnboard ? "onboarding" : "dashboard"
|
|
2302
2476
|
);
|
|
2303
|
-
const [syncStatus, setSyncStatus] =
|
|
2477
|
+
const [syncStatus, setSyncStatus] = useState16(
|
|
2304
2478
|
"idle"
|
|
2305
2479
|
);
|
|
2306
|
-
const syncTimerRef = useRef9();
|
|
2480
|
+
const syncTimerRef = useRef9(void 0);
|
|
2307
2481
|
const lastSyncPayloadRef = useRef9("");
|
|
2308
|
-
|
|
2482
|
+
useEffect16(() => {
|
|
2309
2483
|
if (connectionStatus === "not_authenticated") {
|
|
2310
2484
|
setPage("onboarding");
|
|
2311
2485
|
}
|
|
2312
2486
|
}, [connectionStatus]);
|
|
2313
|
-
|
|
2487
|
+
useEffect16(() => {
|
|
2314
2488
|
if (page === "dashboard") {
|
|
2315
2489
|
refreshAll();
|
|
2316
2490
|
}
|
|
2317
2491
|
}, [page]);
|
|
2318
|
-
|
|
2492
|
+
useEffect16(() => {
|
|
2319
2493
|
if (connectionStatus === "connected" && syncedModels.length > 0) {
|
|
2320
2494
|
runner.start(syncedModels);
|
|
2321
2495
|
}
|
|
2322
2496
|
}, [connectionStatus, syncedModels, runner]);
|
|
2323
|
-
|
|
2497
|
+
useEffect16(() => () => runner.stop(), [runner]);
|
|
2324
2498
|
const refreshAll = useCallback10(
|
|
2325
2499
|
async (silent = false) => {
|
|
2326
2500
|
if (!silent) setSyncStatus("syncing");
|
|
@@ -2351,7 +2525,7 @@ function App({ runner }) {
|
|
|
2351
2525
|
},
|
|
2352
2526
|
[refreshProviders, refreshModels, refreshSynced]
|
|
2353
2527
|
);
|
|
2354
|
-
|
|
2528
|
+
useEffect16(() => {
|
|
2355
2529
|
if (connectionStatus !== "connected" || page !== "dashboard") return;
|
|
2356
2530
|
const interval = setInterval(() => refreshAll(true), 1500);
|
|
2357
2531
|
return () => clearInterval(interval);
|
|
@@ -2400,11 +2574,11 @@ function App({ runner }) {
|
|
|
2400
2574
|
},
|
|
2401
2575
|
[handleNavigate]
|
|
2402
2576
|
);
|
|
2403
|
-
const [termSize, setTermSize] =
|
|
2577
|
+
const [termSize, setTermSize] = useState16({
|
|
2404
2578
|
rows: stdout?.rows ?? 24,
|
|
2405
2579
|
columns: stdout?.columns ?? 80
|
|
2406
2580
|
});
|
|
2407
|
-
|
|
2581
|
+
useEffect16(() => {
|
|
2408
2582
|
if (!stdout) return;
|
|
2409
2583
|
const onResize = () => {
|
|
2410
2584
|
stdout.write("\x1B[2J\x1B[H");
|
|
@@ -2417,7 +2591,7 @@ function App({ runner }) {
|
|
|
2417
2591
|
}, [stdout]);
|
|
2418
2592
|
const termHeight = termSize.rows - 4;
|
|
2419
2593
|
const compactHeader = termSize.rows <= 45 || termSize.columns <= 90;
|
|
2420
|
-
return /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", height: termHeight, overflow: "hidden", children: page === "onboarding" ? /* @__PURE__ */ jsx11(OnboardingPage, { onComplete: handleOnboardingComplete }) : /* @__PURE__ */ jsxs10(
|
|
2594
|
+
return /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", height: termHeight, overflow: "hidden", children: page === "onboarding" ? /* @__PURE__ */ jsx11(OnboardingPage, { onComplete: handleOnboardingComplete }) : /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
2421
2595
|
/* @__PURE__ */ jsx11(
|
|
2422
2596
|
Header,
|
|
2423
2597
|
{
|
|
@@ -2425,7 +2599,8 @@ function App({ runner }) {
|
|
|
2425
2599
|
environment,
|
|
2426
2600
|
configPath: getConfigPath(),
|
|
2427
2601
|
connectionError,
|
|
2428
|
-
compact: compactHeader
|
|
2602
|
+
compact: compactHeader,
|
|
2603
|
+
hasActiveRequest: activeRequestCount > 0
|
|
2429
2604
|
}
|
|
2430
2605
|
),
|
|
2431
2606
|
page === "dashboard" && /* @__PURE__ */ jsx11(
|
|
@@ -2439,6 +2614,8 @@ function App({ runner }) {
|
|
|
2439
2614
|
syncedNames,
|
|
2440
2615
|
modelsLoading,
|
|
2441
2616
|
syncStatus,
|
|
2617
|
+
editorSessions: editorSessions.sessions,
|
|
2618
|
+
editorsLoading: editorSessions.loading,
|
|
2442
2619
|
onNavigate: handleNavigate
|
|
2443
2620
|
}
|
|
2444
2621
|
),
|
|
@@ -2446,7 +2623,10 @@ function App({ runner }) {
|
|
|
2446
2623
|
page === "interfaces" && /* @__PURE__ */ jsx11(
|
|
2447
2624
|
InterfacesPage,
|
|
2448
2625
|
{
|
|
2449
|
-
onBack: () => setPage("dashboard")
|
|
2626
|
+
onBack: () => setPage("dashboard"),
|
|
2627
|
+
sessions: editorSessions.sessions,
|
|
2628
|
+
refreshStatus: editorSessions.refreshStatus,
|
|
2629
|
+
refresh: editorSessions.refresh
|
|
2450
2630
|
}
|
|
2451
2631
|
),
|
|
2452
2632
|
page !== "dashboard" && page !== "setup" && page !== "interfaces" && /* @__PURE__ */ jsx11(Box10, { flexGrow: 1 }),
|
|
@@ -2500,38 +2680,99 @@ async function checkForUpdate() {
|
|
|
2500
2680
|
}
|
|
2501
2681
|
|
|
2502
2682
|
// src/tui/components/UpdatePrompt.tsx
|
|
2503
|
-
import {
|
|
2683
|
+
import { useState as useState17, useEffect as useEffect17, useMemo as useMemo8 } from "react";
|
|
2684
|
+
import { Box as Box11, Text as Text11, useInput as useInput7, useStdout as useStdout8 } from "ink";
|
|
2685
|
+
import chalk4 from "chalk";
|
|
2504
2686
|
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2687
|
+
var SHIMMER_SPEED2 = 35;
|
|
2688
|
+
function useShimmerLogo2() {
|
|
2689
|
+
const [frame, setFrame] = useState17(0);
|
|
2690
|
+
const lines = useMemo8(() => LogoString.split("\n"), []);
|
|
2691
|
+
const totalChars = useMemo8(() => {
|
|
2692
|
+
let count = 0;
|
|
2693
|
+
for (const line of lines) {
|
|
2694
|
+
for (const ch of line) {
|
|
2695
|
+
if (ch !== " " && ch !== " ") count++;
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
return count;
|
|
2699
|
+
}, [lines]);
|
|
2700
|
+
const cycleLength = totalChars + 40;
|
|
2701
|
+
useEffect17(() => {
|
|
2702
|
+
const interval = setInterval(() => {
|
|
2703
|
+
setFrame((f) => (f + 1) % cycleLength);
|
|
2704
|
+
}, SHIMMER_SPEED2);
|
|
2705
|
+
return () => clearInterval(interval);
|
|
2706
|
+
}, [cycleLength]);
|
|
2707
|
+
return useMemo8(() => {
|
|
2708
|
+
const sweepPos = frame;
|
|
2709
|
+
const holdEnd = totalChars + 20;
|
|
2710
|
+
let charIdx = 0;
|
|
2711
|
+
return lines.map((line) => {
|
|
2712
|
+
let result = "";
|
|
2713
|
+
for (let i = 0; i < line.length; i++) {
|
|
2714
|
+
const ch = line[i];
|
|
2715
|
+
if (ch === " " || ch === " ") {
|
|
2716
|
+
result += ch;
|
|
2717
|
+
continue;
|
|
2718
|
+
}
|
|
2719
|
+
let brightness;
|
|
2720
|
+
if (sweepPos <= totalChars) {
|
|
2721
|
+
const lag = charIdx;
|
|
2722
|
+
const t = sweepPos - lag;
|
|
2723
|
+
brightness = t <= 0 ? 0.1 : Math.min(1, t / 8);
|
|
2724
|
+
} else if (sweepPos <= holdEnd) {
|
|
2725
|
+
brightness = 1;
|
|
2726
|
+
} else {
|
|
2727
|
+
const fadeProgress = (sweepPos - holdEnd) / (cycleLength - holdEnd);
|
|
2728
|
+
brightness = Math.max(0.1, 1 - fadeProgress);
|
|
2729
|
+
}
|
|
2730
|
+
if (brightness >= 0.9) {
|
|
2731
|
+
result += chalk4.cyanBright.bold(ch);
|
|
2732
|
+
} else if (brightness >= 0.6) {
|
|
2733
|
+
result += chalk4.cyan(ch);
|
|
2734
|
+
} else if (brightness >= 0.3) {
|
|
2735
|
+
result += chalk4.rgb(0, 100, 120)(ch);
|
|
2736
|
+
} else {
|
|
2737
|
+
result += chalk4.rgb(0, 50, 60)(ch);
|
|
2738
|
+
}
|
|
2739
|
+
charIdx++;
|
|
2740
|
+
}
|
|
2741
|
+
return result;
|
|
2742
|
+
}).join("\n");
|
|
2743
|
+
}, [frame, lines, totalChars, cycleLength]);
|
|
2744
|
+
}
|
|
2505
2745
|
function UpdatePrompt({
|
|
2506
2746
|
currentVersion,
|
|
2507
2747
|
latestVersion,
|
|
2508
2748
|
onChoice
|
|
2509
2749
|
}) {
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
onChoice(false);
|
|
2515
|
-
}
|
|
2750
|
+
const { stdout } = useStdout8();
|
|
2751
|
+
const shimmerLogo = useShimmerLogo2();
|
|
2752
|
+
useInput7(() => {
|
|
2753
|
+
onChoice(true);
|
|
2516
2754
|
});
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2755
|
+
const termHeight = (stdout?.rows ?? 24) - 4;
|
|
2756
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", height: termHeight, children: [
|
|
2757
|
+
/* @__PURE__ */ jsx12(Box11, { flexGrow: 1 }),
|
|
2758
|
+
/* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", alignItems: "center", children: [
|
|
2759
|
+
/* @__PURE__ */ jsx12(Text11, { children: shimmerLogo }),
|
|
2760
|
+
/* @__PURE__ */ jsx12(Box11, { flexDirection: "column", alignItems: "center", marginTop: 2, children: /* @__PURE__ */ jsx12(Text11, { bold: true, color: "white", children: "MindStudio Local Tunnel" }) }),
|
|
2761
|
+
/* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", alignItems: "center", children: [
|
|
2762
|
+
/* @__PURE__ */ jsxs11(Text11, { color: "gray", children: [
|
|
2763
|
+
"Update required ",
|
|
2764
|
+
"\u2022",
|
|
2765
|
+
" v",
|
|
2766
|
+
currentVersion,
|
|
2767
|
+
" ",
|
|
2768
|
+
"\u2192",
|
|
2769
|
+
" v",
|
|
2770
|
+
latestVersion
|
|
2771
|
+
] }),
|
|
2772
|
+
/* @__PURE__ */ jsx12(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text11, { color: "cyan", bold: true, children: "Press any key to update" }) })
|
|
2528
2773
|
] })
|
|
2529
2774
|
] }),
|
|
2530
|
-
/* @__PURE__ */ jsx12(Box11, {
|
|
2531
|
-
"Press ",
|
|
2532
|
-
/* @__PURE__ */ jsx12(Text11, { bold: true, color: "cyan", children: "y" }),
|
|
2533
|
-
" to update, any other key to skip"
|
|
2534
|
-
] }) })
|
|
2775
|
+
/* @__PURE__ */ jsx12(Box11, { flexGrow: 1 })
|
|
2535
2776
|
] });
|
|
2536
2777
|
}
|
|
2537
2778
|
|
|
@@ -2581,16 +2822,13 @@ async function startTUI() {
|
|
|
2581
2822
|
console.clear();
|
|
2582
2823
|
}
|
|
2583
2824
|
const runner = new TunnelRunner();
|
|
2584
|
-
const { waitUntilExit } = render(
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
exitOnCtrlC: true
|
|
2588
|
-
}
|
|
2589
|
-
);
|
|
2825
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx13(App, { runner }), {
|
|
2826
|
+
exitOnCtrlC: true
|
|
2827
|
+
});
|
|
2590
2828
|
await waitUntilExit();
|
|
2591
2829
|
runner.stop();
|
|
2592
2830
|
}
|
|
2593
2831
|
export {
|
|
2594
2832
|
startTUI
|
|
2595
2833
|
};
|
|
2596
|
-
//# sourceMappingURL=tui-
|
|
2834
|
+
//# sourceMappingURL=tui-OZLGNBGD.js.map
|