codemaxxing 0.4.7 โ 0.4.9
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/dist/index.js +29 -24
- package/dist/utils/ollama.d.ts +1 -1
- package/dist/utils/ollama.js +17 -1
- package/package.json +1 -1
- package/src/index.tsx +29 -24
- package/src/utils/ollama.ts +18 -1
package/dist/index.js
CHANGED
|
@@ -1465,34 +1465,39 @@ function App() {
|
|
|
1465
1465
|
if (key.return) {
|
|
1466
1466
|
// Auto-install Ollama if not present
|
|
1467
1467
|
if (!isOllamaInstalled()) {
|
|
1468
|
-
|
|
1468
|
+
setWizardPullProgress({ status: "Installing Ollama...", percent: 0 });
|
|
1469
|
+
setWizardScreen("pulling");
|
|
1470
|
+
// Run install async so the UI can update
|
|
1469
1471
|
const installCmd = getOllamaInstallCommand(wizardHardware?.os ?? "linux");
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1472
|
+
(async () => {
|
|
1473
|
+
try {
|
|
1474
|
+
const { exec } = _require("child_process");
|
|
1475
|
+
await new Promise((resolve, reject) => {
|
|
1476
|
+
exec(installCmd, { timeout: 180000 }, (err, _stdout, stderr) => {
|
|
1477
|
+
if (err)
|
|
1478
|
+
reject(new Error(stderr || err.message));
|
|
1479
|
+
else
|
|
1480
|
+
resolve();
|
|
1481
|
+
});
|
|
1482
|
+
});
|
|
1483
|
+
addMsg("info", "โ
Ollama installed! Proceeding to model download...");
|
|
1484
|
+
// Small delay for PATH to update on Windows
|
|
1485
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
1486
|
+
// Go back to models screen so user can pick and it'll proceed to pull
|
|
1487
|
+
setWizardScreen("models");
|
|
1488
|
+
setWizardPullProgress(null);
|
|
1481
1489
|
}
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
addMsg("error", `Install failed: ${errMsg}`);
|
|
1490
|
+
catch (e) {
|
|
1491
|
+
addMsg("error", `Install failed: ${e.message}`);
|
|
1485
1492
|
addMsg("info", `Try manually in a separate terminal: ${installCmd}`);
|
|
1486
|
-
|
|
1493
|
+
setWizardScreen("install-ollama");
|
|
1494
|
+
setWizardPullProgress(null);
|
|
1487
1495
|
}
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
addMsg("error", `Install failed: ${e.message}`);
|
|
1491
|
-
addMsg("info", `Try manually in a separate terminal: ${installCmd}`);
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1496
|
+
})();
|
|
1497
|
+
return;
|
|
1494
1498
|
}
|
|
1495
|
-
|
|
1499
|
+
// Ollama already installed โ proceed to pull
|
|
1500
|
+
{
|
|
1496
1501
|
const selected = wizardSelectedModel;
|
|
1497
1502
|
if (selected) {
|
|
1498
1503
|
setWizardScreen("pulling");
|
|
@@ -1820,7 +1825,7 @@ function App() {
|
|
|
1820
1825
|
{ key: "openrouter", icon: "\uD83C\uDF10", label: "OpenRouter", desc: "200+ cloud models, browser login" },
|
|
1821
1826
|
{ key: "apikey", icon: "\uD83D\uDD11", label: "Enter API key manually", desc: "" },
|
|
1822
1827
|
{ key: "existing", icon: "\u2699\uFE0F", label: "I already have a server running", desc: "" },
|
|
1823
|
-
].map((item, i) => (_jsxs(Text, { children: [i === wizardIndex ? _jsx(Text, { color: theme.colors.suggestion, bold: true, children: " \u25B8 " }) : _jsx(Text, { children: " " }), _jsxs(Text, { color: i === wizardIndex ? theme.colors.suggestion : theme.colors.primary, bold: true, children: [item.icon, " ", item.label] }), item.desc ? _jsxs(Text, { color: theme.colors.muted, children: [" (", item.desc, ")"] }) : null] }, item.key))), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " \u2191\u2193 navigate \u00B7 Enter to select" })] })), wizardScreen === "models" && wizardHardware && (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.border, paddingX: 1, marginBottom: 0, children: [_jsx(Text, { bold: true, color: theme.colors.secondary, children: "Your hardware:" }), _jsxs(Text, { color: theme.colors.muted, children: [" CPU: ", wizardHardware.cpu.name, " (", wizardHardware.cpu.cores, " cores)"] }), _jsxs(Text, { color: theme.colors.muted, children: [" RAM: ", formatBytes(wizardHardware.ram)] }), wizardHardware.gpu ? (_jsxs(Text, { color: theme.colors.muted, children: [" GPU: ", wizardHardware.gpu.name, wizardHardware.gpu.vram > 0 ? ` (${formatBytes(wizardHardware.gpu.vram)})` : ""] })) : (_jsx(Text, { color: theme.colors.muted, children: " GPU: none detected" })), !isLlmfitAvailable() && (_jsx(Text, { dimColor: true, children: " Tip: Install llmfit for smarter recommendations: brew install llmfit" })), _jsx(Text, { children: "" }), _jsx(Text, { bold: true, color: theme.colors.secondary, children: "Recommended models:" }), _jsx(Text, { children: "" }), wizardModels.map((m, i) => (_jsxs(Text, { children: [i === wizardIndex ? _jsx(Text, { color: theme.colors.suggestion, bold: true, children: " \u25B8 " }) : _jsx(Text, { children: " " }), _jsxs(Text, { children: [getFitIcon(m.fit), " "] }), _jsx(Text, { color: i === wizardIndex ? theme.colors.suggestion : theme.colors.primary, bold: true, children: m.name }), _jsxs(Text, { color: theme.colors.muted, children: [" ~", m.size, " GB \u00B7 ", m.quality === "best" ? "Best" : m.quality === "great" ? "Great" : "Good", " quality \u00B7 ", m.speed] })] }, m.ollamaId))), wizardModels.length === 0 && (_jsx(Text, { color: theme.colors.error, children: " No suitable models found for your hardware." })), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " \u2191\u2193 navigate \u00B7 Enter to install \u00B7 Esc back" })] })), wizardScreen === "install-ollama" && (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.warning, paddingX: 1, marginBottom: 0, children: [_jsx(Text, { bold: true, color: theme.colors.warning, children: "Ollama is required for local models." }), _jsx(Text, { children: "" }), _jsx(Text, { color: theme.colors.primary, children: " Press Enter to install Ollama automatically" }), _jsxs(Text, { dimColor: true, children: [" Or install manually: ", _jsx(Text, { children: getOllamaInstallCommand(wizardHardware?.os ?? "linux") })] }), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " Enter to install ยท Esc to go back" })] })), wizardScreen === "pulling" && wizardSelectedModel && (_jsx(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.border, paddingX: 1, marginBottom: 0, children: wizardPullError ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: theme.colors.error, bold: true, children: [" \u274C Error: ", wizardPullError] }), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " Press Enter to retry \u00B7 Esc to go back" })] })) : wizardPullProgress ? (_jsxs(_Fragment, { children: [_jsxs(Text, { bold: true, color: theme.colors.secondary, children: ["
|
|
1828
|
+
].map((item, i) => (_jsxs(Text, { children: [i === wizardIndex ? _jsx(Text, { color: theme.colors.suggestion, bold: true, children: " \u25B8 " }) : _jsx(Text, { children: " " }), _jsxs(Text, { color: i === wizardIndex ? theme.colors.suggestion : theme.colors.primary, bold: true, children: [item.icon, " ", item.label] }), item.desc ? _jsxs(Text, { color: theme.colors.muted, children: [" (", item.desc, ")"] }) : null] }, item.key))), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " \u2191\u2193 navigate \u00B7 Enter to select" })] })), wizardScreen === "models" && wizardHardware && (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.border, paddingX: 1, marginBottom: 0, children: [_jsx(Text, { bold: true, color: theme.colors.secondary, children: "Your hardware:" }), _jsxs(Text, { color: theme.colors.muted, children: [" CPU: ", wizardHardware.cpu.name, " (", wizardHardware.cpu.cores, " cores)"] }), _jsxs(Text, { color: theme.colors.muted, children: [" RAM: ", formatBytes(wizardHardware.ram)] }), wizardHardware.gpu ? (_jsxs(Text, { color: theme.colors.muted, children: [" GPU: ", wizardHardware.gpu.name, wizardHardware.gpu.vram > 0 ? ` (${formatBytes(wizardHardware.gpu.vram)})` : ""] })) : (_jsx(Text, { color: theme.colors.muted, children: " GPU: none detected" })), !isLlmfitAvailable() && (_jsx(Text, { dimColor: true, children: " Tip: Install llmfit for smarter recommendations: brew install llmfit" })), _jsx(Text, { children: "" }), _jsx(Text, { bold: true, color: theme.colors.secondary, children: "Recommended models:" }), _jsx(Text, { children: "" }), wizardModels.map((m, i) => (_jsxs(Text, { children: [i === wizardIndex ? _jsx(Text, { color: theme.colors.suggestion, bold: true, children: " \u25B8 " }) : _jsx(Text, { children: " " }), _jsxs(Text, { children: [getFitIcon(m.fit), " "] }), _jsx(Text, { color: i === wizardIndex ? theme.colors.suggestion : theme.colors.primary, bold: true, children: m.name }), _jsxs(Text, { color: theme.colors.muted, children: [" ~", m.size, " GB \u00B7 ", m.quality === "best" ? "Best" : m.quality === "great" ? "Great" : "Good", " quality \u00B7 ", m.speed] })] }, m.ollamaId))), wizardModels.length === 0 && (_jsx(Text, { color: theme.colors.error, children: " No suitable models found for your hardware." })), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " \u2191\u2193 navigate \u00B7 Enter to install \u00B7 Esc back" })] })), wizardScreen === "install-ollama" && (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.warning, paddingX: 1, marginBottom: 0, children: [_jsx(Text, { bold: true, color: theme.colors.warning, children: "Ollama is required for local models." }), _jsx(Text, { children: "" }), _jsx(Text, { color: theme.colors.primary, children: " Press Enter to install Ollama automatically" }), _jsxs(Text, { dimColor: true, children: [" Or install manually: ", _jsx(Text, { children: getOllamaInstallCommand(wizardHardware?.os ?? "linux") })] }), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " Enter to install ยท Esc to go back" })] })), wizardScreen === "pulling" && (wizardSelectedModel || wizardPullProgress) && (_jsx(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.border, paddingX: 1, marginBottom: 0, children: wizardPullError ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: theme.colors.error, bold: true, children: [" \u274C Error: ", wizardPullError] }), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " Press Enter to retry \u00B7 Esc to go back" })] })) : wizardPullProgress ? (_jsxs(_Fragment, { children: [_jsxs(Text, { bold: true, color: theme.colors.secondary, children: [" ", wizardSelectedModel ? `Downloading ${wizardSelectedModel.name}...` : wizardPullProgress?.status || "Working..."] }), wizardPullProgress.status === "downloading" || wizardPullProgress.percent > 0 ? (_jsx(_Fragment, { children: _jsxs(Text, { children: [" ", _jsxs(Text, { color: theme.colors.primary, children: ["\u2588".repeat(Math.floor(wizardPullProgress.percent / 5)), "\u2591".repeat(20 - Math.floor(wizardPullProgress.percent / 5))] }), " ", _jsxs(Text, { bold: true, children: [wizardPullProgress.percent, "%"] }), wizardPullProgress.completed != null && wizardPullProgress.total != null ? (_jsxs(Text, { color: theme.colors.muted, children: [" \u00B7 ", formatBytes(wizardPullProgress.completed), " / ", formatBytes(wizardPullProgress.total)] })) : null] }) })) : (_jsxs(Text, { color: theme.colors.muted, children: [" ", wizardPullProgress.status, "..."] }))] })) : null })), showSuggestions && (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: theme.colors.muted, paddingX: 1, marginBottom: 0, children: [cmdMatches.slice(0, 6).map((c, i) => (_jsxs(Text, { children: [i === cmdIndex ? _jsx(Text, { color: theme.colors.suggestion, bold: true, children: "โธ " }) : _jsx(Text, { children: " " }), _jsx(Text, { color: i === cmdIndex ? theme.colors.suggestion : theme.colors.primary, bold: true, children: c.cmd }), _jsxs(Text, { color: theme.colors.muted, children: [" โ ", c.desc] })] }, i))), _jsx(Text, { dimColor: true, children: " โโ navigate ยท Tab select" })] })), _jsxs(Box, { borderStyle: "single", borderColor: approval ? theme.colors.warning : theme.colors.border, paddingX: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: "> " }), approval ? (_jsx(Text, { color: theme.colors.warning, children: "waiting for approval..." })) : ready && !loading && !wizardScreen ? (_jsxs(Box, { children: [pastedChunks.map((p) => (_jsxs(Text, { color: theme.colors.muted, children: ["[Pasted text #", p.id, " +", p.lines, " lines]"] }, p.id))), _jsx(TextInput, { value: input, onChange: (v) => { setInput(v); setCmdIndex(0); }, onSubmit: handleSubmit }, inputKey)] })) : (_jsx(Text, { dimColor: true, children: loading ? "waiting for response..." : "initializing..." }))] }), agent && (_jsx(Box, { paddingX: 2, children: _jsxs(Text, { dimColor: true, children: ["๐ฌ ", agent.getContextLength(), " messages ยท ~", (() => {
|
|
1824
1829
|
const tokens = agent.estimateTokens();
|
|
1825
1830
|
return tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}k` : String(tokens);
|
|
1826
1831
|
})(), " tokens", (() => {
|
package/dist/utils/ollama.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Check if ollama binary exists on PATH */
|
|
1
|
+
/** Check if ollama binary exists on PATH or known install locations */
|
|
2
2
|
export declare function isOllamaInstalled(): boolean;
|
|
3
3
|
/** Check if ollama server is responding */
|
|
4
4
|
export declare function isOllamaRunning(): Promise<boolean>;
|
package/dist/utils/ollama.js
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { execSync, spawn } from "child_process";
|
|
2
|
-
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
/** Get known Ollama binary paths for Windows */
|
|
5
|
+
function getWindowsOllamaPaths() {
|
|
6
|
+
const paths = [];
|
|
7
|
+
const localAppData = process.env.LOCALAPPDATA || join(process.env.USERPROFILE || "", "AppData", "Local");
|
|
8
|
+
const programFiles = process.env.ProgramFiles || "C:\\Program Files";
|
|
9
|
+
paths.push(join(localAppData, "Programs", "Ollama", "ollama.exe"));
|
|
10
|
+
paths.push(join(programFiles, "Ollama", "ollama.exe"));
|
|
11
|
+
paths.push(join(localAppData, "Ollama", "ollama.exe"));
|
|
12
|
+
return paths;
|
|
13
|
+
}
|
|
14
|
+
/** Check if ollama binary exists on PATH or known install locations */
|
|
3
15
|
export function isOllamaInstalled() {
|
|
4
16
|
try {
|
|
5
17
|
const cmd = process.platform === "win32" ? "where ollama" : "which ollama";
|
|
@@ -7,6 +19,10 @@ export function isOllamaInstalled() {
|
|
|
7
19
|
return true;
|
|
8
20
|
}
|
|
9
21
|
catch {
|
|
22
|
+
// Fallback: check known install paths on Windows
|
|
23
|
+
if (process.platform === "win32") {
|
|
24
|
+
return getWindowsOllamaPaths().some(p => existsSync(p));
|
|
25
|
+
}
|
|
10
26
|
return false;
|
|
11
27
|
}
|
|
12
28
|
}
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -1489,32 +1489,37 @@ function App() {
|
|
|
1489
1489
|
if (key.return) {
|
|
1490
1490
|
// Auto-install Ollama if not present
|
|
1491
1491
|
if (!isOllamaInstalled()) {
|
|
1492
|
-
|
|
1492
|
+
setWizardPullProgress({ status: "Installing Ollama...", percent: 0 });
|
|
1493
|
+
setWizardScreen("pulling");
|
|
1494
|
+
|
|
1495
|
+
// Run install async so the UI can update
|
|
1493
1496
|
const installCmd = getOllamaInstallCommand(wizardHardware?.os ?? "linux");
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1497
|
+
(async () => {
|
|
1498
|
+
try {
|
|
1499
|
+
const { exec } = _require("child_process");
|
|
1500
|
+
await new Promise<void>((resolve, reject) => {
|
|
1501
|
+
exec(installCmd, { timeout: 180000 }, (err: any, _stdout: string, stderr: string) => {
|
|
1502
|
+
if (err) reject(new Error(stderr || err.message));
|
|
1503
|
+
else resolve();
|
|
1504
|
+
});
|
|
1505
|
+
});
|
|
1506
|
+
addMsg("info", "โ
Ollama installed! Proceeding to model download...");
|
|
1507
|
+
// Small delay for PATH to update on Windows
|
|
1508
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
1509
|
+
// Go back to models screen so user can pick and it'll proceed to pull
|
|
1510
|
+
setWizardScreen("models");
|
|
1511
|
+
setWizardPullProgress(null);
|
|
1512
|
+
} catch (e: any) {
|
|
1513
|
+
addMsg("error", `Install failed: ${e.message}`);
|
|
1508
1514
|
addMsg("info", `Try manually in a separate terminal: ${installCmd}`);
|
|
1509
|
-
|
|
1515
|
+
setWizardScreen("install-ollama");
|
|
1516
|
+
setWizardPullProgress(null);
|
|
1510
1517
|
}
|
|
1511
|
-
}
|
|
1512
|
-
|
|
1513
|
-
addMsg("info", `Try manually in a separate terminal: ${installCmd}`);
|
|
1514
|
-
return;
|
|
1515
|
-
}
|
|
1518
|
+
})();
|
|
1519
|
+
return;
|
|
1516
1520
|
}
|
|
1517
|
-
|
|
1521
|
+
// Ollama already installed โ proceed to pull
|
|
1522
|
+
{
|
|
1518
1523
|
const selected = wizardSelectedModel;
|
|
1519
1524
|
if (selected) {
|
|
1520
1525
|
setWizardScreen("pulling");
|
|
@@ -2178,7 +2183,7 @@ function App() {
|
|
|
2178
2183
|
</Box>
|
|
2179
2184
|
)}
|
|
2180
2185
|
|
|
2181
|
-
{wizardScreen === "pulling" && wizardSelectedModel && (
|
|
2186
|
+
{wizardScreen === "pulling" && (wizardSelectedModel || wizardPullProgress) && (
|
|
2182
2187
|
<Box flexDirection="column" borderStyle="single" borderColor={theme.colors.border} paddingX={1} marginBottom={0}>
|
|
2183
2188
|
{wizardPullError ? (
|
|
2184
2189
|
<>
|
|
@@ -2188,7 +2193,7 @@ function App() {
|
|
|
2188
2193
|
</>
|
|
2189
2194
|
) : wizardPullProgress ? (
|
|
2190
2195
|
<>
|
|
2191
|
-
<Text bold color={theme.colors.secondary}>{"
|
|
2196
|
+
<Text bold color={theme.colors.secondary}>{" "}{wizardSelectedModel ? `Downloading ${wizardSelectedModel.name}...` : wizardPullProgress?.status || "Working..."}</Text>
|
|
2192
2197
|
{wizardPullProgress.status === "downloading" || wizardPullProgress.percent > 0 ? (
|
|
2193
2198
|
<>
|
|
2194
2199
|
<Text>
|
package/src/utils/ollama.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
import { execSync, spawn } from "child_process";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
|
|
5
|
+
/** Get known Ollama binary paths for Windows */
|
|
6
|
+
function getWindowsOllamaPaths(): string[] {
|
|
7
|
+
const paths: string[] = [];
|
|
8
|
+
const localAppData = process.env.LOCALAPPDATA || join(process.env.USERPROFILE || "", "AppData", "Local");
|
|
9
|
+
const programFiles = process.env.ProgramFiles || "C:\\Program Files";
|
|
10
|
+
paths.push(join(localAppData, "Programs", "Ollama", "ollama.exe"));
|
|
11
|
+
paths.push(join(programFiles, "Ollama", "ollama.exe"));
|
|
12
|
+
paths.push(join(localAppData, "Ollama", "ollama.exe"));
|
|
13
|
+
return paths;
|
|
14
|
+
}
|
|
2
15
|
|
|
3
|
-
/** Check if ollama binary exists on PATH */
|
|
16
|
+
/** Check if ollama binary exists on PATH or known install locations */
|
|
4
17
|
export function isOllamaInstalled(): boolean {
|
|
5
18
|
try {
|
|
6
19
|
const cmd = process.platform === "win32" ? "where ollama" : "which ollama";
|
|
7
20
|
execSync(cmd, { stdio: ["pipe", "pipe", "pipe"], timeout: 3000 });
|
|
8
21
|
return true;
|
|
9
22
|
} catch {
|
|
23
|
+
// Fallback: check known install paths on Windows
|
|
24
|
+
if (process.platform === "win32") {
|
|
25
|
+
return getWindowsOllamaPaths().some(p => existsSync(p));
|
|
26
|
+
}
|
|
10
27
|
return false;
|
|
11
28
|
}
|
|
12
29
|
}
|