@mindstudio-ai/local-model-tunnel 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/README.md +30 -115
  2. package/dist/chunk-PTK4SJQK.js +1768 -0
  3. package/dist/chunk-PTK4SJQK.js.map +1 -0
  4. package/dist/cli.d.ts +0 -2
  5. package/dist/cli.js +8 -517
  6. package/dist/cli.js.map +1 -1
  7. package/dist/index.d.ts +24 -5
  8. package/dist/index.js +6 -13
  9. package/dist/index.js.map +1 -1
  10. package/dist/tui-QOSKXZWU.js +1560 -0
  11. package/dist/tui-QOSKXZWU.js.map +1 -0
  12. package/package.json +11 -4
  13. package/dist/api.d.ts +0 -88
  14. package/dist/api.d.ts.map +0 -1
  15. package/dist/api.js +0 -168
  16. package/dist/api.js.map +0 -1
  17. package/dist/cli.d.ts.map +0 -1
  18. package/dist/config.d.ts +0 -27
  19. package/dist/config.d.ts.map +0 -1
  20. package/dist/config.js +0 -109
  21. package/dist/config.js.map +0 -1
  22. package/dist/helpers.d.ts +0 -4
  23. package/dist/helpers.d.ts.map +0 -1
  24. package/dist/helpers.js +0 -33
  25. package/dist/helpers.js.map +0 -1
  26. package/dist/index.d.ts.map +0 -1
  27. package/dist/ollama.d.ts +0 -11
  28. package/dist/ollama.d.ts.map +0 -1
  29. package/dist/ollama.js +0 -36
  30. package/dist/ollama.js.map +0 -1
  31. package/dist/providers/comfyui.d.ts +0 -29
  32. package/dist/providers/comfyui.d.ts.map +0 -1
  33. package/dist/providers/comfyui.js +0 -359
  34. package/dist/providers/comfyui.js.map +0 -1
  35. package/dist/providers/index.d.ts +0 -63
  36. package/dist/providers/index.d.ts.map +0 -1
  37. package/dist/providers/index.js +0 -126
  38. package/dist/providers/index.js.map +0 -1
  39. package/dist/providers/lmstudio.d.ts +0 -11
  40. package/dist/providers/lmstudio.d.ts.map +0 -1
  41. package/dist/providers/lmstudio.js +0 -106
  42. package/dist/providers/lmstudio.js.map +0 -1
  43. package/dist/providers/ollama.d.ts +0 -11
  44. package/dist/providers/ollama.d.ts.map +0 -1
  45. package/dist/providers/ollama.js +0 -59
  46. package/dist/providers/ollama.js.map +0 -1
  47. package/dist/providers/stable-diffusion.d.ts +0 -41
  48. package/dist/providers/stable-diffusion.d.ts.map +0 -1
  49. package/dist/providers/stable-diffusion.js +0 -283
  50. package/dist/providers/stable-diffusion.js.map +0 -1
  51. package/dist/providers/types.d.ts +0 -196
  52. package/dist/providers/types.d.ts.map +0 -1
  53. package/dist/providers/types.js +0 -19
  54. package/dist/providers/types.js.map +0 -1
  55. package/dist/quickstart/QuickstartScreen.d.ts +0 -5
  56. package/dist/quickstart/QuickstartScreen.d.ts.map +0 -1
  57. package/dist/quickstart/QuickstartScreen.js +0 -617
  58. package/dist/quickstart/QuickstartScreen.js.map +0 -1
  59. package/dist/quickstart/detect.d.ts +0 -22
  60. package/dist/quickstart/detect.d.ts.map +0 -1
  61. package/dist/quickstart/detect.js +0 -243
  62. package/dist/quickstart/detect.js.map +0 -1
  63. package/dist/quickstart/index.d.ts +0 -4
  64. package/dist/quickstart/index.d.ts.map +0 -1
  65. package/dist/quickstart/index.js +0 -274
  66. package/dist/quickstart/index.js.map +0 -1
  67. package/dist/quickstart/installers.d.ts +0 -109
  68. package/dist/quickstart/installers.d.ts.map +0 -1
  69. package/dist/quickstart/installers.js +0 -1296
  70. package/dist/quickstart/installers.js.map +0 -1
  71. package/dist/runner.d.ts +0 -19
  72. package/dist/runner.d.ts.map +0 -1
  73. package/dist/runner.js +0 -314
  74. package/dist/runner.js.map +0 -1
  75. package/dist/tui/App.d.ts +0 -7
  76. package/dist/tui/App.d.ts.map +0 -1
  77. package/dist/tui/App.js +0 -53
  78. package/dist/tui/App.js.map +0 -1
  79. package/dist/tui/TunnelRunner.d.ts +0 -19
  80. package/dist/tui/TunnelRunner.d.ts.map +0 -1
  81. package/dist/tui/TunnelRunner.js +0 -228
  82. package/dist/tui/TunnelRunner.js.map +0 -1
  83. package/dist/tui/components/Header.d.ts +0 -9
  84. package/dist/tui/components/Header.d.ts.map +0 -1
  85. package/dist/tui/components/Header.js +0 -21
  86. package/dist/tui/components/Header.js.map +0 -1
  87. package/dist/tui/components/ModelsPanel.d.ts +0 -7
  88. package/dist/tui/components/ModelsPanel.d.ts.map +0 -1
  89. package/dist/tui/components/ModelsPanel.js +0 -28
  90. package/dist/tui/components/ModelsPanel.js.map +0 -1
  91. package/dist/tui/components/ProvidersPanel.d.ts +0 -7
  92. package/dist/tui/components/ProvidersPanel.d.ts.map +0 -1
  93. package/dist/tui/components/ProvidersPanel.js +0 -6
  94. package/dist/tui/components/ProvidersPanel.js.map +0 -1
  95. package/dist/tui/components/RequestLog.d.ts +0 -8
  96. package/dist/tui/components/RequestLog.d.ts.map +0 -1
  97. package/dist/tui/components/RequestLog.js +0 -60
  98. package/dist/tui/components/RequestLog.js.map +0 -1
  99. package/dist/tui/components/StatusBar.d.ts +0 -10
  100. package/dist/tui/components/StatusBar.d.ts.map +0 -1
  101. package/dist/tui/components/StatusBar.js +0 -7
  102. package/dist/tui/components/StatusBar.js.map +0 -1
  103. package/dist/tui/components/index.d.ts +0 -6
  104. package/dist/tui/components/index.d.ts.map +0 -1
  105. package/dist/tui/components/index.js +0 -6
  106. package/dist/tui/components/index.js.map +0 -1
  107. package/dist/tui/events.d.ts +0 -35
  108. package/dist/tui/events.d.ts.map +0 -1
  109. package/dist/tui/events.js +0 -26
  110. package/dist/tui/events.js.map +0 -1
  111. package/dist/tui/hooks/index.d.ts +0 -5
  112. package/dist/tui/hooks/index.d.ts.map +0 -1
  113. package/dist/tui/hooks/index.js +0 -5
  114. package/dist/tui/hooks/index.js.map +0 -1
  115. package/dist/tui/hooks/useConnection.d.ts +0 -10
  116. package/dist/tui/hooks/useConnection.d.ts.map +0 -1
  117. package/dist/tui/hooks/useConnection.js +0 -42
  118. package/dist/tui/hooks/useConnection.js.map +0 -1
  119. package/dist/tui/hooks/useModels.d.ts +0 -9
  120. package/dist/tui/hooks/useModels.d.ts.map +0 -1
  121. package/dist/tui/hooks/useModels.js +0 -28
  122. package/dist/tui/hooks/useModels.js.map +0 -1
  123. package/dist/tui/hooks/useProviders.d.ts +0 -9
  124. package/dist/tui/hooks/useProviders.d.ts.map +0 -1
  125. package/dist/tui/hooks/useProviders.js +0 -30
  126. package/dist/tui/hooks/useProviders.js.map +0 -1
  127. package/dist/tui/hooks/useRequests.d.ts +0 -9
  128. package/dist/tui/hooks/useRequests.d.ts.map +0 -1
  129. package/dist/tui/hooks/useRequests.js +0 -60
  130. package/dist/tui/hooks/useRequests.js.map +0 -1
  131. package/dist/tui/index.d.ts +0 -2
  132. package/dist/tui/index.d.ts.map +0 -1
  133. package/dist/tui/index.js +0 -19
  134. package/dist/tui/index.js.map +0 -1
  135. package/dist/tui/screens/ConfigScreen.d.ts +0 -2
  136. package/dist/tui/screens/ConfigScreen.d.ts.map +0 -1
  137. package/dist/tui/screens/ConfigScreen.js +0 -18
  138. package/dist/tui/screens/ConfigScreen.js.map +0 -1
  139. package/dist/tui/screens/HomeScreen.d.ts +0 -2
  140. package/dist/tui/screens/HomeScreen.d.ts.map +0 -1
  141. package/dist/tui/screens/HomeScreen.js +0 -156
  142. package/dist/tui/screens/HomeScreen.js.map +0 -1
  143. package/dist/tui/screens/ModelsScreen.d.ts +0 -2
  144. package/dist/tui/screens/ModelsScreen.d.ts.map +0 -1
  145. package/dist/tui/screens/ModelsScreen.js +0 -59
  146. package/dist/tui/screens/ModelsScreen.js.map +0 -1
  147. package/dist/tui/screens/StatusScreen.d.ts +0 -2
  148. package/dist/tui/screens/StatusScreen.d.ts.map +0 -1
  149. package/dist/tui/screens/StatusScreen.js +0 -53
  150. package/dist/tui/screens/StatusScreen.js.map +0 -1
  151. package/dist/tui/screens/index.d.ts +0 -9
  152. package/dist/tui/screens/index.d.ts.map +0 -1
  153. package/dist/tui/screens/index.js +0 -38
  154. package/dist/tui/screens/index.js.map +0 -1
  155. package/dist/tui/types.d.ts +0 -30
  156. package/dist/tui/types.d.ts.map +0 -1
  157. package/dist/tui/types.js +0 -2
  158. package/dist/tui/types.js.map +0 -1
  159. package/dist/workflows/index.d.ts +0 -47
  160. package/dist/workflows/index.d.ts.map +0 -1
  161. package/dist/workflows/index.js +0 -95
  162. package/dist/workflows/index.js.map +0 -1
  163. package/dist/workflows/ltx-video.d.ts +0 -45
  164. package/dist/workflows/ltx-video.d.ts.map +0 -1
  165. package/dist/workflows/ltx-video.js +0 -114
  166. package/dist/workflows/ltx-video.js.map +0 -1
  167. package/dist/workflows/wan2.1.d.ts +0 -44
  168. package/dist/workflows/wan2.1.d.ts.map +0 -1
  169. package/dist/workflows/wan2.1.js +0 -119
  170. package/dist/workflows/wan2.1.js.map +0 -1
@@ -1,617 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect } from "react";
3
- import { Box, Text, useApp, useInput } from "ink";
4
- import TextInput from "ink-text-input";
5
- import Spinner from "ink-spinner";
6
- import * as path from "path";
7
- import * as os from "os";
8
- import { detectAllProviders } from "./detect.js";
9
- import { installOllama, installLMStudio, installStableDiffusion, installComfyUI, installComfyUICustomNodes, pullOllamaModel, startOllama, hasDefaultSdModel, getComfyUIModelStatus, getPythonVersion, isPythonVersionOk, } from "./installers.js";
10
- import { LogoString } from "../helpers.js";
11
- export function QuickstartScreen({ onExternalAction } = {}) {
12
- const { exit } = useApp();
13
- const [screen, setScreen] = useState("detecting");
14
- const [providers, setProviders] = useState([]);
15
- const [selectedIndex, setSelectedIndex] = useState(0);
16
- const [installProgress, setInstallProgress] = useState(null);
17
- const [logs, setLogs] = useState([]);
18
- // Track what action was completed for context-specific done screen
19
- const [completedAction, setCompletedAction] = useState(null);
20
- // Path input state for Stable Diffusion
21
- const defaultSdPath = path.join(os.homedir(), "sd-webui-forge-neo");
22
- const [sdInstallPath, setSdInstallPath] = useState(defaultSdPath);
23
- // Model download state for Ollama
24
- const [modelName, setModelName] = useState("");
25
- // Track if default SD model already exists
26
- const [sdModelExists, setSdModelExists] = useState(false);
27
- // ComfyUI state
28
- const defaultComfyPath = path.join(os.homedir(), "ComfyUI");
29
- const [comfyInstallPath, setComfyInstallPath] = useState(defaultComfyPath);
30
- const [comfyModelStatus, setComfyModelStatus] = useState([]);
31
- // Refresh provider detection and model status
32
- const refreshProviders = async () => {
33
- const detected = await detectAllProviders();
34
- setProviders(detected);
35
- const modelExists = await hasDefaultSdModel();
36
- setSdModelExists(modelExists);
37
- setComfyModelStatus(getComfyUIModelStatus());
38
- };
39
- // Navigate to a screen with a clean slate
40
- const navigateTo = (target) => {
41
- // Clear screen + scrollback buffer + reset cursor position
42
- process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
43
- setInstallProgress(null);
44
- setLogs([]);
45
- setScreen(target);
46
- };
47
- // Detect providers on mount
48
- useEffect(() => {
49
- async function detect() {
50
- await refreshProviders();
51
- setScreen("menu");
52
- }
53
- detect();
54
- }, []);
55
- // Build menu items based on detected providers
56
- const menuItems = [];
57
- const ollama = providers.find((p) => p.id === "ollama");
58
- const lmstudio = providers.find((p) => p.id === "lmstudio");
59
- const sd = providers.find((p) => p.id === "stable-diffusion");
60
- // --- Text providers (Ollama, LM Studio) ---
61
- if (ollama) {
62
- if (!ollama.installed) {
63
- menuItems.push({
64
- id: "install-ollama",
65
- category: "text",
66
- label: ollama.installable
67
- ? "Install Ollama (automatic)"
68
- : "Download Ollama (opens browser)",
69
- action: async () => {
70
- if (ollama.installable) {
71
- // Use external action so Ink exits and sudo prompt is visible
72
- if (onExternalAction) {
73
- onExternalAction("install-ollama");
74
- }
75
- exit();
76
- }
77
- else {
78
- navigateTo("installing");
79
- await installOllama((progress) => {
80
- setInstallProgress(progress);
81
- if (progress.message) {
82
- setLogs((prev) => [...prev.slice(-10), progress.message]);
83
- }
84
- });
85
- setCompletedAction("install-ollama");
86
- navigateTo("done");
87
- }
88
- },
89
- });
90
- }
91
- else if (!ollama.running) {
92
- menuItems.push({
93
- id: "start-ollama",
94
- category: "text",
95
- label: "Start Ollama server",
96
- action: async () => {
97
- navigateTo("installing");
98
- await startOllama((progress) => {
99
- setInstallProgress(progress);
100
- });
101
- setCompletedAction("start-ollama");
102
- navigateTo("done");
103
- },
104
- });
105
- }
106
- else {
107
- // Ollama is installed and running - offer to download models and stop
108
- menuItems.push({
109
- id: "download-model",
110
- category: "text",
111
- label: "Download Ollama Models",
112
- action: async () => {
113
- setModelName("");
114
- navigateTo("model-download");
115
- },
116
- });
117
- menuItems.push({
118
- id: "stop-ollama",
119
- category: "text",
120
- label: "Stop Ollama server",
121
- action: async () => {
122
- if (onExternalAction) {
123
- onExternalAction("stop-ollama");
124
- }
125
- exit();
126
- },
127
- });
128
- }
129
- }
130
- if (lmstudio && !lmstudio.installed) {
131
- menuItems.push({
132
- id: "install-lmstudio",
133
- category: "text",
134
- label: "Download LM Studio (opens browser)",
135
- action: async () => {
136
- navigateTo("installing");
137
- await installLMStudio((progress) => {
138
- setInstallProgress(progress);
139
- });
140
- setCompletedAction("install-lmstudio");
141
- navigateTo("done");
142
- },
143
- });
144
- }
145
- // --- Image providers (Stable Diffusion) ---
146
- if (sd) {
147
- if (sd.warning) {
148
- menuItems.push({
149
- id: "fix-python",
150
- category: "image",
151
- label: "Install Python 3.13 (required for Forge Neo)",
152
- action: async () => {
153
- if (onExternalAction) {
154
- onExternalAction("fix-python");
155
- }
156
- exit();
157
- },
158
- });
159
- }
160
- if (!sd.installed) {
161
- menuItems.push({
162
- id: "install-sd",
163
- category: "image",
164
- label: sd.installable
165
- ? "Install Stable Diffusion Forge Neo"
166
- : "Stable Diffusion (requires git & python)",
167
- disabled: !sd.installable,
168
- action: async () => {
169
- navigateTo("path-input");
170
- },
171
- });
172
- }
173
- else if (!sd.running) {
174
- menuItems.push({
175
- id: "start-sd",
176
- category: "image",
177
- label: "Start Stable Diffusion server",
178
- action: async () => {
179
- const pyInfo = await getPythonVersion();
180
- if (!pyInfo) {
181
- setInstallProgress({
182
- stage: "error",
183
- message: "Python not found",
184
- error: "Python is not installed. Forge Neo requires Python 3.13+.\nInstall from https://www.python.org/downloads/",
185
- });
186
- setCompletedAction("start-sd");
187
- navigateTo("done");
188
- return;
189
- }
190
- if (!isPythonVersionOk(pyInfo)) {
191
- setInstallProgress({
192
- stage: "error",
193
- message: `Python ${pyInfo.version} is too old`,
194
- error: `Forge Neo requires Python 3.13+. You have ${pyInfo.version}.\nUse "Install Python 3.13" from the setup menu for instructions.`,
195
- });
196
- setCompletedAction("start-sd");
197
- navigateTo("done");
198
- return;
199
- }
200
- if (onExternalAction) {
201
- onExternalAction("start-sd");
202
- }
203
- exit();
204
- },
205
- });
206
- }
207
- else {
208
- menuItems.push({
209
- id: "stop-sd",
210
- category: "image",
211
- label: "Stop Stable Diffusion server",
212
- action: async () => {
213
- if (onExternalAction) {
214
- onExternalAction("stop-sd");
215
- }
216
- exit();
217
- },
218
- });
219
- }
220
- if (sd.installed && !sdModelExists) {
221
- menuItems.push({
222
- id: "download-sd-model",
223
- category: "image",
224
- label: "Download default SDXL model (~6.5 GB)",
225
- action: async () => {
226
- if (onExternalAction) {
227
- onExternalAction("download-sd-model");
228
- }
229
- exit();
230
- },
231
- });
232
- }
233
- }
234
- // Function to start SD installation with the chosen path
235
- const startSdInstallation = async () => {
236
- navigateTo("installing");
237
- await installStableDiffusion((progress) => {
238
- setInstallProgress(progress);
239
- if (progress.message) {
240
- setLogs((prev) => [...prev.slice(-10), progress.message]);
241
- }
242
- }, sdInstallPath);
243
- setCompletedAction("install-sd");
244
- navigateTo("done");
245
- };
246
- // Function to download an Ollama model
247
- const startModelDownload = async () => {
248
- if (!modelName.trim())
249
- return;
250
- navigateTo("installing");
251
- await pullOllamaModel(modelName.trim(), (progress) => {
252
- setInstallProgress(progress);
253
- if (progress.message) {
254
- setLogs((prev) => [...prev.slice(-10), progress.message]);
255
- }
256
- });
257
- setCompletedAction("download-model");
258
- navigateTo("done");
259
- };
260
- // --- Video providers (ComfyUI) ---
261
- const comfyui = providers.find((p) => p.id === "comfyui");
262
- if (comfyui) {
263
- if (!comfyui.installed) {
264
- menuItems.push({
265
- id: "install-comfyui",
266
- category: "video",
267
- label: comfyui.installable
268
- ? "Install ComfyUI"
269
- : "ComfyUI (requires git & python)",
270
- disabled: !comfyui.installable,
271
- action: async () => {
272
- navigateTo("installing");
273
- setInstallProgress({
274
- stage: "start",
275
- message: "Installing ComfyUI...",
276
- });
277
- const success = await installComfyUI(comfyInstallPath, (progress) => {
278
- setInstallProgress(progress);
279
- if (progress.message) {
280
- setLogs((prev) => [...prev.slice(-10), progress.message]);
281
- }
282
- });
283
- if (success) {
284
- setInstallProgress({
285
- stage: "start",
286
- message: "Installing LTX-Video custom nodes...",
287
- });
288
- await installComfyUICustomNodes((progress) => {
289
- setInstallProgress(progress);
290
- if (progress.message) {
291
- setLogs((prev) => [...prev.slice(-10), progress.message]);
292
- }
293
- });
294
- }
295
- setCompletedAction("install-comfyui");
296
- navigateTo("done");
297
- },
298
- });
299
- }
300
- else if (!comfyui.running) {
301
- menuItems.push({
302
- id: "start-comfyui",
303
- category: "video",
304
- label: "Start ComfyUI server",
305
- action: async () => {
306
- if (onExternalAction) {
307
- onExternalAction("start-comfyui");
308
- }
309
- exit();
310
- },
311
- });
312
- }
313
- else {
314
- for (const model of comfyModelStatus) {
315
- if (!model.installed) {
316
- menuItems.push({
317
- id: `download-comfyui-${model.id}`,
318
- category: "video",
319
- label: `Download ${model.label} (${model.totalSize})`,
320
- action: async () => {
321
- if (onExternalAction) {
322
- onExternalAction(`download-comfyui-model:${model.id}`);
323
- }
324
- exit();
325
- },
326
- });
327
- }
328
- }
329
- menuItems.push({
330
- id: "stop-comfyui",
331
- category: "video",
332
- label: "Stop ComfyUI server",
333
- action: async () => {
334
- if (onExternalAction) {
335
- onExternalAction("stop-comfyui");
336
- }
337
- exit();
338
- },
339
- });
340
- }
341
- }
342
- // --- General ---
343
- menuItems.push({
344
- id: "model-guide",
345
- category: "general",
346
- label: "How to Add Your Own Models",
347
- action: async () => {
348
- navigateTo("model-guide");
349
- },
350
- });
351
- menuItems.push({
352
- id: "exit",
353
- category: "general",
354
- label: "Exit",
355
- action: async () => {
356
- exit();
357
- },
358
- });
359
- // Keyboard navigation
360
- useInput((input, key) => {
361
- if (screen === "menu") {
362
- if (key.upArrow) {
363
- setSelectedIndex((prev) => Math.max(0, prev - 1));
364
- }
365
- if (key.downArrow) {
366
- setSelectedIndex((prev) => Math.min(menuItems.length - 1, prev + 1));
367
- }
368
- if (key.return) {
369
- const item = menuItems[selectedIndex];
370
- if (item && !item.disabled) {
371
- item.action();
372
- }
373
- }
374
- }
375
- // Allow escape to go back from path input
376
- if (screen === "path-input" && key.escape) {
377
- navigateTo("menu");
378
- return;
379
- }
380
- // Allow escape to go back from model download
381
- if (screen === "model-download" && key.escape) {
382
- navigateTo("menu");
383
- return;
384
- }
385
- // Allow escape or Enter to go back from model guide
386
- if (screen === "model-guide" && (key.escape || key.return)) {
387
- navigateTo("menu");
388
- return;
389
- }
390
- // Allow Enter to exit from done screen (return to main menu)
391
- if (screen === "done" && key.return) {
392
- exit();
393
- return;
394
- }
395
- // Global quit (but not during input screens, done screen, or guide)
396
- if (screen !== "path-input" &&
397
- screen !== "model-download" &&
398
- screen !== "model-guide" &&
399
- screen !== "done" &&
400
- (input === "q" || key.escape)) {
401
- exit();
402
- }
403
- });
404
- // Detecting screen
405
- if (screen === "detecting") {
406
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "cyan", children: LogoString }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Detecting installed providers..." })] })] }));
407
- }
408
- // Path input screen for Stable Diffusion
409
- if (screen === "path-input") {
410
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "cyan", children: LogoString }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: "white", children: "Install Stable Diffusion Forge Neo" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [_jsx(Text, { children: "Installation path:" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: "> " }), _jsx(TextInput, { value: sdInstallPath, onChange: setSdInstallPath, onSubmit: () => {
411
- startSdInstallation();
412
- } })] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "gray", children: "Enter: Confirm and install" }), _jsx(Text, { color: "gray", children: "Esc: Go back" })] })] }));
413
- }
414
- // Model download screen for Ollama
415
- if (screen === "model-download") {
416
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "cyan", children: LogoString }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: "white", children: "Download Ollama Model" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { children: "Browse available models at:" }), _jsx(Text, { color: "cyan", bold: true, children: "https://ollama.com/library" })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "gray", children: "Popular models:" }), _jsx(Text, { color: "gray", children: " llama3.2, mistral, codellama, phi3, gemma2" })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [_jsx(Text, { children: "Enter model name:" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: "> " }), _jsx(TextInput, { value: modelName, onChange: setModelName, placeholder: "e.g. llama3.2", onSubmit: () => {
417
- if (modelName.trim()) {
418
- startModelDownload();
419
- }
420
- } })] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "gray", children: "Enter: Download model" }), _jsx(Text, { color: "gray", children: "Esc: Go back" })] })] }));
421
- }
422
- // Model guide screen
423
- if (screen === "model-guide") {
424
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "cyan", children: LogoString }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: "white", children: "How to Add Your Own Models" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [_jsx(Text, { bold: true, children: "Text Models (Ollama)" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: ["Browse models at", " ", _jsx(Text, { color: "cyan", children: "https://ollama.com/library" })] }), _jsx(Text, { color: "gray", children: "Download via the setup menu or run:" }), _jsxs(Text, { color: "white", children: [" ollama pull ", "<model-name>"] })] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [_jsx(Text, { bold: true, children: "Image Models (Stable Diffusion)" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: ["Download ", _jsx(Text, { color: "white", children: ".safetensors" }), " files from", " ", _jsx(Text, { color: "cyan", children: "https://civitai.com" })] }), _jsxs(Text, { color: "gray", children: ["Filter by ", _jsx(Text, { color: "white", children: "SDXL 1.0" }), " for best compatibility."] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "gray", children: "Place them in:" }), _jsxs(Text, { color: "white", children: [" ", sdInstallPath, "/models/Stable-diffusion/"] })] }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(Text, { color: "gray", children: "Restart the SD server to pick up new models." }) })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [_jsx(Text, { bold: true, children: "Video Models (ComfyUI)" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: ["Download models from", " ", _jsx(Text, { color: "cyan", children: "https://huggingface.co" }), " ", "and place in the folders below."] }), _jsx(Text, { color: "gray", children: "Models marked with * can be auto-downloaded from the setup menu." })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, color: "white", children: "LTX-Video" }), _jsxs(Text, { color: "gray", children: [" * ltx-video-2b-v0.9.5.safetensors ", _jsx(Text, { color: "white", children: "checkpoints/" }), " ", _jsx(Text, { color: "gray", children: "(~6 GB)" })] }), _jsxs(Text, { color: "gray", children: [" * t5xxl_fp16.safetensors ", _jsx(Text, { color: "white", children: "text_encoders/" }), " ", _jsx(Text, { color: "gray", children: "(~10 GB)" })] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, color: "white", children: "Wan 2.1 Text-to-Video" }), _jsxs(Text, { color: "gray", children: [" * wan2.1_t2v_1.3B_fp16.safetensors ", _jsx(Text, { color: "white", children: "diffusion_models/" }), " ", _jsx(Text, { color: "gray", children: "(~2.6 GB)" })] }), _jsxs(Text, { color: "gray", children: [" wan2.1_t2v_14B_fp16.safetensors ", _jsx(Text, { color: "white", children: "diffusion_models/" }), " ", _jsx(Text, { color: "gray", children: "(~28 GB)" })] }), _jsxs(Text, { color: "gray", children: [" * umt5_xxl_fp8_e4m3fn_scaled ", _jsx(Text, { color: "white", children: "text_encoders/" }), " ", _jsx(Text, { color: "gray", children: "(~5 GB, shared)" })] }), _jsxs(Text, { color: "gray", children: [" * wan_2.1_vae.safetensors ", _jsx(Text, { color: "white", children: "vae/" }), " ", _jsx(Text, { color: "gray", children: "(~0.3 GB, shared)" })] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: ["All folders are relative to: ", _jsxs(Text, { color: "white", children: [comfyInstallPath, "/models/"] })] }), _jsx(Text, { color: "gray", children: "The 14B model uses the same text encoder and VAE as the 1.3B." }), _jsx(Text, { color: "gray", children: "Restart the ComfyUI server to pick up new models." })] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press Esc or Enter to go back" }) })] }));
425
- }
426
- // Installing screen
427
- if (screen === "installing") {
428
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "cyan", children: LogoString }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: "white", children: "Loading..." }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [installProgress && (_jsxs(Box, { children: [!installProgress.complete && !installProgress.error && (_jsxs(Text, { color: "cyan", children: [_jsx(Spinner, { type: "dots" }), " "] })), installProgress.complete && _jsx(Text, { color: "green", children: "\u2713 " }), installProgress.error && _jsx(Text, { color: "red", children: "\u2717 " }), _jsx(Text, { children: installProgress.message })] })), installProgress?.error && (_jsxs(Text, { color: "red", children: ["Error: ", installProgress.error] }))] }), logs.length > 0 && (_jsx(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: logs.slice(-5).map((log, i) => (_jsx(Text, { color: "gray", children: log }, i))) }))] }));
429
- }
430
- // Done screen - context-aware based on completed action
431
- if (screen === "done") {
432
- const getDoneMessage = () => {
433
- switch (completedAction) {
434
- case "start-ollama":
435
- return {
436
- title: "Ollama is now running!",
437
- description: "Ollama server is running in the background on port 11434.",
438
- nextSteps: [
439
- "Return to main menu to authenticate or start the tunnel.",
440
- ],
441
- note: "Ollama will keep running until you restart your computer or stop it manually.",
442
- };
443
- case "stop-ollama":
444
- return {
445
- title: "Ollama server stopped!",
446
- description: "The Ollama server has been shut down.",
447
- nextSteps: [],
448
- note: null,
449
- };
450
- case "download-model":
451
- return {
452
- title: "Model downloaded!",
453
- description: `The model "${modelName}" has been pulled successfully.`,
454
- nextSteps: [
455
- "Return to main menu to register models and start the tunnel.",
456
- ],
457
- note: null,
458
- };
459
- case "install-ollama":
460
- return {
461
- title: "Ollama installed successfully!",
462
- description: "Ollama has been installed and the llama3.2 model has been pulled.",
463
- nextSteps: [
464
- "Return to main menu to authenticate and start the tunnel.",
465
- ],
466
- note: null,
467
- };
468
- case "install-lmstudio":
469
- return {
470
- title: "LM Studio download started!",
471
- description: "The download page has been opened in your browser.",
472
- nextSteps: [
473
- "Complete the installation from the downloaded file.",
474
- "Launch LM Studio and download a model.",
475
- "Start the local server in LM Studio.",
476
- "Return to main menu to start the tunnel.",
477
- ],
478
- note: null,
479
- };
480
- case "install-sd":
481
- return {
482
- title: "Stable Diffusion Forge Neo cloned!",
483
- description: `Repository cloned to: ${sdInstallPath}`,
484
- nextSteps: [
485
- 'Use "Download default SDXL model" from the setup menu to get a model automatically.',
486
- 'Or download from https://civitai.com/models (filter by "SDXL 1.0").',
487
- "Then start the server from the setup menu.",
488
- ],
489
- note: `To add your own models, download .safetensors files from https://civitai.com and place them in:\n ${sdInstallPath}/models/Stable-diffusion/`,
490
- };
491
- case "install-comfyui":
492
- return {
493
- title: "ComfyUI installed!",
494
- description: `Installed to: ${comfyInstallPath}`,
495
- nextSteps: [
496
- "Start the ComfyUI server from the setup menu.",
497
- "Download a video model (LTX-Video or Wan 2.1) once the server is running.",
498
- "Then start the tunnel to connect to MindStudio.",
499
- ],
500
- note: [
501
- "LTX-Video custom nodes have been installed for best compatibility.",
502
- "",
503
- "To add your own video models, download .safetensors files from https://huggingface.co and place them in:",
504
- ` Checkpoints: ${comfyInstallPath}/models/checkpoints/`,
505
- ` Diffusion models: ${comfyInstallPath}/models/diffusion_models/`,
506
- ` Text encoders: ${comfyInstallPath}/models/text_encoders/`,
507
- ` VAE: ${comfyInstallPath}/models/vae/`,
508
- ].join("\n"),
509
- };
510
- case "start-sd":
511
- // If there was a pre-flight error (Python version), show it
512
- if (installProgress?.error) {
513
- return {
514
- title: installProgress.message,
515
- description: installProgress.error,
516
- nextSteps: [
517
- 'Use "Install Python 3.13" from the setup menu for instructions.',
518
- `If you recently updated Python, delete the old venv: rm -rf ${sdInstallPath}/venv`,
519
- ],
520
- note: null,
521
- };
522
- }
523
- return {
524
- title: "Stable Diffusion server stopped.",
525
- description: "The server has been shut down.",
526
- nextSteps: [
527
- "Return to main menu to start it again or start the tunnel.",
528
- ],
529
- note: null,
530
- };
531
- case "stop-sd":
532
- return {
533
- title: "Stable Diffusion server stopped!",
534
- description: "The server has been shut down.",
535
- nextSteps: ["Return to main menu to start it again if needed."],
536
- note: null,
537
- };
538
- default:
539
- return {
540
- title: "Setup complete!",
541
- description: null,
542
- nextSteps: [
543
- "Return to main menu to authenticate and start the tunnel.",
544
- ],
545
- note: null,
546
- };
547
- }
548
- };
549
- const msg = getDoneMessage();
550
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "cyan", children: LogoString }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "green", bold: true, children: msg.title }), msg.description && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "white", children: msg.description }) })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "white", bold: true, children: "Next steps:" }), msg.nextSteps.map((step, i) => (_jsxs(Text, { color: "gray", children: [" ", i + 1, ". ", step] }, i)))] }), msg.note && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "yellow", children: ["Note: ", msg.note] }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "cyan", children: "Press Enter to return to main menu" }) })] })] }));
551
- }
552
- // Menu screen
553
- const allInstalled = providers.every((p) => p.installed);
554
- const allRunning = providers
555
- .filter((p) => p.installed)
556
- .every((p) => p.running);
557
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "cyan", children: LogoString }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: "white", children: "Quickstart Setup" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { bold: true, children: "Provider Status" }), [
558
- { label: "Text", ids: ["ollama", "lmstudio"] },
559
- { label: "Image", ids: ["stable-diffusion"] },
560
- { label: "Video", ids: ["comfyui"] },
561
- ].map((group) => {
562
- const groupProviders = providers.filter((p) => group.ids.includes(p.id));
563
- if (groupProviders.length === 0)
564
- return null;
565
- return (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "gray", dimColor: true, children: group.label }), groupProviders.map((provider) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: provider.installed
566
- ? provider.running
567
- ? "green"
568
- : "yellow"
569
- : "red", children: provider.installed
570
- ? provider.running
571
- ? "●"
572
- : "○"
573
- : "✗" }), _jsxs(Text, { children: [" ", provider.name, " - "] }), _jsx(Text, { color: "gray", children: provider.running
574
- ? "Running"
575
- : provider.installed
576
- ? "Installed (not running)"
577
- : "Not installed" })] }), provider.warning && (_jsx(Box, { children: _jsxs(Text, { color: "yellow", children: [" \u26A0 ", provider.warning] }) }))] }, provider.id)))] }, group.label));
578
- })] }), process.platform === "darwin" && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "yellow", children: "\u26A0 macOS: Stable Diffusion and ComfyUI may have compatibility issues due to limited CUDA support. GPU acceleration requires Apple Silicon with MPS." }) })), allInstalled && allRunning && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "green", children: "\u2713 All providers are installed and running!" }) })), menuItems.length > 1 &&
579
- (() => {
580
- const categoryOrder = [
581
- "text",
582
- "image",
583
- "video",
584
- "general",
585
- ];
586
- const categoryLabels = {
587
- text: "Text Generation",
588
- image: "Image Generation",
589
- video: "Video Generation",
590
- general: "",
591
- };
592
- const categoryIcons = {
593
- text: "💬",
594
- image: "🎨",
595
- video: "🎬",
596
- general: "",
597
- };
598
- // Only show categories that have items
599
- const activeCategories = categoryOrder.filter((cat) => menuItems.some((item) => item.category === cat));
600
- // Track the global index for selection
601
- let globalIndex = 0;
602
- return (_jsx(Box, { marginTop: 1, flexDirection: "column", children: activeCategories.map((cat, catIdx) => {
603
- const items = menuItems.filter((item) => item.category === cat);
604
- const startIdx = globalIndex;
605
- globalIndex += items.length;
606
- return (_jsxs(Box, { flexDirection: "column", marginTop: catIdx > 0 ? 1 : 0, children: [cat !== "general" && (_jsxs(Text, { bold: true, color: "gray", children: [categoryIcons[cat], " ", categoryLabels[cat]] })), items.map((item, i) => {
607
- const idx = startIdx + i;
608
- return (_jsxs(Box, { children: [_jsx(Text, { color: idx === selectedIndex ? "cyan" : "white", children: idx === selectedIndex ? " ❯ " : " " }), _jsx(Text, { color: item.disabled
609
- ? "gray"
610
- : idx === selectedIndex
611
- ? "cyan"
612
- : "white", dimColor: item.disabled, children: item.label })] }, item.id));
613
- })] }, cat));
614
- }) }));
615
- })(), (sd?.installed || comfyui?.installed) && (_jsxs(Box, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { bold: true, color: "gray", children: "Add Your Own Models" }), sd?.installed && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: ["Image models (.safetensors) from", " ", _jsx(Text, { color: "cyan", children: "https://civitai.com" })] }), _jsxs(Text, { color: "gray", children: [" ", "Place in:", " ", _jsxs(Text, { color: "white", children: [sdInstallPath, "/models/Stable-diffusion/"] })] })] })), comfyui?.installed && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: ["Video models (.safetensors) from", " ", _jsx(Text, { color: "cyan", children: "https://huggingface.co" })] }), _jsxs(Text, { color: "gray", children: [" ", "Checkpoints:", " ", _jsxs(Text, { color: "white", children: [comfyInstallPath, "/models/checkpoints/"] })] }), _jsxs(Text, { color: "gray", children: [" ", "Diffusion models:", " ", _jsxs(Text, { color: "white", children: [comfyInstallPath, "/models/diffusion_models/"] })] })] }))] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "\u2191\u2193 Navigate \u2022 Enter Select \u2022 q Quit" }) })] }));
616
- }
617
- //# sourceMappingURL=QuickstartScreen.js.map