colana 1.0.0-beta.7 → 1.0.0-beta.71
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/bin/admin.js +6 -0
- package/bin/colana.js +193 -19
- package/package.json +11 -6
- package/public/admin-panel.js +735 -0
- package/public/app.js +767 -50
- package/public/index.html +1 -1
- package/public/styles.css +199 -0
- package/public/wizard.js +1585 -0
- package/scripts/postinstall.cjs +27 -0
- package/server/agent-control-routes.js +15 -0
- package/server/auto-installer.js +590 -21
- package/server/config.js +4 -1
- package/server/diagnostics-routes.js +2 -1
- package/server/index.js +23 -0
- package/server/license.js +1 -1
- package/server/openclaw-config.js +216 -8
- package/server/personal-agent-routes.js +133 -9
- package/server/platform.js +56 -1
- package/server/preflight.js +52 -1
- package/server/pty-manager.js +483 -42
- package/server/spawn-env.js +7 -1
package/bin/admin.js
CHANGED
|
@@ -187,6 +187,12 @@ async function createKey(flags) {
|
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
if (!result || !result.name) {
|
|
191
|
+
console.error(`\n ${icons.fail} ${c.error}Key generation returned an unexpected response.${c.reset}\n`);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
return; // Guard for test environments where process.exit is mocked
|
|
194
|
+
}
|
|
195
|
+
|
|
190
196
|
console.log('');
|
|
191
197
|
console.log(` ${icons.pass} Key generated successfully!`);
|
|
192
198
|
console.log(` ${c.muted}${'─'.repeat(40)}${c.reset}`);
|
package/bin/colana.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Normal run: start server → open browser
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { execSync, spawn } from 'child_process';
|
|
10
|
+
import { execSync, execFileSync, spawn } from 'child_process';
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import readline from 'readline';
|
|
@@ -125,6 +125,79 @@ function detectProvider(provider) {
|
|
|
125
125
|
return commandExistsSync(provider.binary);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Detect the system Python version. Returns { major, minor } or null.
|
|
130
|
+
*/
|
|
131
|
+
function detectPythonVersion() {
|
|
132
|
+
for (const bin of ['python3', 'python']) {
|
|
133
|
+
try {
|
|
134
|
+
const out = execFileSync(bin, ['--version'], {
|
|
135
|
+
timeout: 5000, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'],
|
|
136
|
+
}).trim();
|
|
137
|
+
const match = out.match(/Python\s+(\d+)\.(\d+)/);
|
|
138
|
+
if (match) return { major: parseInt(match[1]), minor: parseInt(match[2]) };
|
|
139
|
+
} catch { /* try next */ }
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Return platform-specific numbered next-steps for a failed install.
|
|
146
|
+
* @param {object} provider - Provider object from CLI_PROVIDERS
|
|
147
|
+
* @param {string} [hint] - Optional hint about why it failed
|
|
148
|
+
* @returns {string[]} Steps array
|
|
149
|
+
*/
|
|
150
|
+
function getCliNextSteps(provider, hint = '') {
|
|
151
|
+
const h = hint.toLowerCase();
|
|
152
|
+
const platform = process.platform;
|
|
153
|
+
|
|
154
|
+
// Build tools failures (npm providers)
|
|
155
|
+
if (provider.runtime === 'npm' && (h.includes('gyp') || h.includes('msbuild') || h.includes('native') || h.includes('build tools'))) {
|
|
156
|
+
if (platform === 'win32') {
|
|
157
|
+
return [
|
|
158
|
+
'Open PowerShell as Administrator (right-click > "Run as administrator")',
|
|
159
|
+
`Run: ${c.cmd}winget install Microsoft.VisualStudio.2022.BuildTools --override "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --passive --norestart" --accept-source-agreements --accept-package-agreements${c.reset}`,
|
|
160
|
+
'Wait for the install to complete (2-5 minutes)',
|
|
161
|
+
'Close and reopen your terminal',
|
|
162
|
+
`Run: ${c.cmd}${provider.installCmd}${c.reset}`,
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
if (platform === 'darwin') {
|
|
166
|
+
return [
|
|
167
|
+
`Run: ${c.cmd}xcode-select --install${c.reset}`,
|
|
168
|
+
'Complete the system dialog that appears',
|
|
169
|
+
`Run: ${c.cmd}${provider.installCmd}${c.reset}`,
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
return [
|
|
173
|
+
`Run: ${c.cmd}sudo apt update && sudo apt install -y build-essential python3${c.reset}`,
|
|
174
|
+
`Run: ${c.cmd}${provider.installCmd}${c.reset}`,
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Python version issues (aider)
|
|
179
|
+
if (provider.runtime === 'pipx' && (h.includes('python') || h.includes('setuptools'))) {
|
|
180
|
+
if (platform === 'win32') {
|
|
181
|
+
return [
|
|
182
|
+
`Run: ${c.cmd}pip install uv${c.reset}`,
|
|
183
|
+
`Run: ${c.cmd}uv tool install --python python3.12 aider-chat${c.reset}`,
|
|
184
|
+
'Close and reopen your terminal',
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
return [
|
|
188
|
+
`Run: ${c.cmd}pip install uv${c.reset} (or: ${c.cmd}brew install uv${c.reset})`,
|
|
189
|
+
`Run: ${c.cmd}uv tool install --python python3.12 aider-chat${c.reset}`,
|
|
190
|
+
'Restart your terminal',
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Generic fallback
|
|
195
|
+
return [
|
|
196
|
+
`Run: ${c.cmd}${provider.installCmd}${c.reset}`,
|
|
197
|
+
'If that fails, check the error output above for details',
|
|
198
|
+
];
|
|
199
|
+
}
|
|
200
|
+
|
|
128
201
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
129
202
|
const ask = (q) => new Promise(r => rl.question(q, r));
|
|
130
203
|
|
|
@@ -136,12 +209,63 @@ function runInstall(cmd) {
|
|
|
136
209
|
const proc = spawn(parts[0], parts.slice(1), {
|
|
137
210
|
stdio: 'inherit',
|
|
138
211
|
env: { ...process.env },
|
|
212
|
+
...(process.platform === 'win32' && { shell: true }),
|
|
213
|
+
});
|
|
214
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
215
|
+
proc.on('error', () => resolve(false));
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Spawn a binary with an explicit args array (needed when arguments contain spaces,
|
|
221
|
+
* e.g. winget --override "..." where the value must stay as one argument).
|
|
222
|
+
*/
|
|
223
|
+
function runInstallArgs(binary, args) {
|
|
224
|
+
return new Promise((resolve) => {
|
|
225
|
+
// No shell: true here — winget/xcode-select are real executables, not .cmd files.
|
|
226
|
+
// shell: true would cause cmd.exe to split quoted --override values into separate args.
|
|
227
|
+
const proc = spawn(binary, args, {
|
|
228
|
+
stdio: 'inherit',
|
|
229
|
+
env: { ...process.env },
|
|
139
230
|
});
|
|
140
231
|
proc.on('close', (code) => resolve(code === 0));
|
|
141
232
|
proc.on('error', () => resolve(false));
|
|
142
233
|
});
|
|
143
234
|
}
|
|
144
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Attempt to auto-install C/C++ build tools needed for native npm modules.
|
|
238
|
+
* Returns true if tools were installed (or install was triggered), false otherwise.
|
|
239
|
+
*/
|
|
240
|
+
async function tryInstallBuildTools() {
|
|
241
|
+
const platform = process.platform;
|
|
242
|
+
|
|
243
|
+
if (platform === 'win32') {
|
|
244
|
+
// Try winget (available on Windows 10 21H2+ / Windows 11)
|
|
245
|
+
if (commandExistsSync('winget')) {
|
|
246
|
+
print(` ${c.muted}Installing Visual Studio Build Tools via winget...${c.reset}`);
|
|
247
|
+
const ok = await runInstallArgs('winget', [
|
|
248
|
+
'install', 'Microsoft.VisualStudio.2022.BuildTools',
|
|
249
|
+
'--override', '--add Microsoft.VisualStudio.Workload.VCTools --passive --norestart',
|
|
250
|
+
'--accept-source-agreements', '--accept-package-agreements',
|
|
251
|
+
]);
|
|
252
|
+
return ok;
|
|
253
|
+
}
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (platform === 'darwin') {
|
|
258
|
+
print(` ${c.muted}Installing Xcode Command Line Tools...${c.reset}`);
|
|
259
|
+
// xcode-select --install opens a system dialog; returns non-zero if already installed
|
|
260
|
+
const ok = await runInstallArgs('xcode-select', ['--install']);
|
|
261
|
+
// Even if xcode-select exits non-zero (already installed), the tools may be present
|
|
262
|
+
return ok;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Linux — requires sudo, skip auto-install
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
|
|
145
269
|
// ---------------------------------------------------------------------------
|
|
146
270
|
// Doctor Checks (standalone + used by wizard)
|
|
147
271
|
// ---------------------------------------------------------------------------
|
|
@@ -387,37 +511,87 @@ async function installProvider(provider) {
|
|
|
387
511
|
}
|
|
388
512
|
}
|
|
389
513
|
|
|
514
|
+
// Aider: detect Python 3.13+ and use uv with Python 3.12 pin
|
|
515
|
+
let installCmd = provider.installCmd;
|
|
516
|
+
let fallbackCmd = provider.fallbackCmd;
|
|
517
|
+
let failureHint = '';
|
|
518
|
+
|
|
519
|
+
if (provider.binary === 'aider') {
|
|
520
|
+
const pyVer = detectPythonVersion();
|
|
521
|
+
if (pyVer && pyVer.major >= 3 && pyVer.minor >= 13) {
|
|
522
|
+
print(` ${c.muted}Python ${pyVer.major}.${pyVer.minor} detected — aider requires Python 3.10-3.12${c.reset}`);
|
|
523
|
+
print(` ${c.muted}Using uv to install with Python 3.12...${c.reset}`);
|
|
524
|
+
failureHint = 'python 3.13';
|
|
525
|
+
|
|
526
|
+
// Try installing uv first if not available
|
|
527
|
+
let hasUv = commandExistsSync('uv');
|
|
528
|
+
if (!hasUv) {
|
|
529
|
+
print(` ${c.muted}Installing uv (universal Python package manager)...${c.reset}`);
|
|
530
|
+
hasUv = await runInstall('pip install uv');
|
|
531
|
+
if (!hasUv) hasUv = await runInstall('pip3 install uv');
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
if (hasUv) {
|
|
535
|
+
installCmd = 'uv tool install --python python3.12 aider-chat';
|
|
536
|
+
fallbackCmd = null;
|
|
537
|
+
} else {
|
|
538
|
+
print(` ${icons.fail} ${c.error}Could not install uv.${c.reset}`);
|
|
539
|
+
printNextSteps(provider, 'python setuptools');
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
390
545
|
print(` Installing ${provider.name}...`);
|
|
391
|
-
let success = await runInstall(
|
|
546
|
+
let success = await runInstall(installCmd);
|
|
392
547
|
|
|
393
|
-
if (!success &&
|
|
394
|
-
print(` Trying fallback: ${
|
|
395
|
-
success = await runInstall(
|
|
548
|
+
if (!success && fallbackCmd) {
|
|
549
|
+
print(` Trying fallback: ${fallbackCmd}...`);
|
|
550
|
+
success = await runInstall(fallbackCmd);
|
|
396
551
|
}
|
|
397
552
|
|
|
398
553
|
if (success) {
|
|
399
554
|
print(` ${icons.pass} ${provider.name} installed`);
|
|
400
555
|
} else {
|
|
401
|
-
|
|
402
|
-
// Platform-specific hints for native module failures (npm packages may need C/C++ build tools)
|
|
556
|
+
// For npm packages, try auto-installing build tools and retrying
|
|
403
557
|
if (provider.runtime === 'npm') {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
print(`
|
|
409
|
-
|
|
410
|
-
print(` ${c.muted}If you see build errors, ensure Xcode CLT is installed:${c.reset}`);
|
|
411
|
-
print(` ${c.cmd}xcode-select --install${c.reset}`);
|
|
412
|
-
} else {
|
|
413
|
-
print(` ${c.muted}If you see build errors, ensure build tools are installed:${c.reset}`);
|
|
414
|
-
print(` ${c.cmd}sudo apt install python3 build-essential${c.reset}`);
|
|
558
|
+
print(` ${c.muted}Build tools may be needed. Attempting automatic install...${c.reset}`);
|
|
559
|
+
const toolsInstalled = await tryInstallBuildTools();
|
|
560
|
+
|
|
561
|
+
if (toolsInstalled) {
|
|
562
|
+
print(` ${c.muted}Retrying ${provider.name} install...${c.reset}`);
|
|
563
|
+
success = await runInstall(installCmd);
|
|
415
564
|
}
|
|
565
|
+
|
|
566
|
+
if (success) {
|
|
567
|
+
print(` ${icons.pass} ${provider.name} installed`);
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
failureHint = failureHint || 'build tools';
|
|
416
572
|
}
|
|
417
|
-
|
|
573
|
+
|
|
574
|
+
// Enterprise-grade: show numbered next-steps
|
|
575
|
+
print(` ${icons.fail} ${c.error}Installation failed.${c.reset}`);
|
|
576
|
+
printNextSteps(provider, failureHint);
|
|
418
577
|
}
|
|
419
578
|
}
|
|
420
579
|
|
|
580
|
+
/**
|
|
581
|
+
* Print numbered next-steps for a failed install.
|
|
582
|
+
* @param {object} provider - CLI_PROVIDERS entry
|
|
583
|
+
* @param {string} [hint] - Failure hint
|
|
584
|
+
*/
|
|
585
|
+
function printNextSteps(provider, hint = '') {
|
|
586
|
+
const steps = getCliNextSteps(provider, hint);
|
|
587
|
+
print('');
|
|
588
|
+
print(` ${c.heading}Next steps to resolve:${c.reset}`);
|
|
589
|
+
steps.forEach((step, i) => {
|
|
590
|
+
print(` ${c.muted}${i + 1}.${c.reset} ${step}`);
|
|
591
|
+
});
|
|
592
|
+
print('');
|
|
593
|
+
}
|
|
594
|
+
|
|
421
595
|
// ---------------------------------------------------------------------------
|
|
422
596
|
// Start Server
|
|
423
597
|
// ---------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "colana",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.71",
|
|
4
4
|
"description": "Agent-First. Multiplied. Multi-agent command center for AI coding agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "server/index.js",
|
|
@@ -16,11 +16,9 @@
|
|
|
16
16
|
"scripts/postinstall.cjs",
|
|
17
17
|
"public/*.html",
|
|
18
18
|
"public/*.css",
|
|
19
|
-
"public
|
|
19
|
+
"public/*.js",
|
|
20
20
|
"public/vendor/**",
|
|
21
21
|
"public/manifest.json",
|
|
22
|
-
"public/service-worker.js",
|
|
23
|
-
"public/sw-register.js",
|
|
24
22
|
"public/icons/*",
|
|
25
23
|
"data/.gitkeep"
|
|
26
24
|
],
|
|
@@ -88,8 +86,15 @@
|
|
|
88
86
|
],
|
|
89
87
|
"license": "SEE LICENSE IN LICENSE",
|
|
90
88
|
"private": false,
|
|
91
|
-
"os": [
|
|
92
|
-
|
|
89
|
+
"os": [
|
|
90
|
+
"linux",
|
|
91
|
+
"darwin",
|
|
92
|
+
"win32"
|
|
93
|
+
],
|
|
94
|
+
"cpu": [
|
|
95
|
+
"x64",
|
|
96
|
+
"arm64"
|
|
97
|
+
],
|
|
93
98
|
"devDependencies": {
|
|
94
99
|
"@playwright/test": "^1.58.2",
|
|
95
100
|
"@vitest/coverage-v8": "^4.0.18",
|