colana 1.0.0-beta.3 → 1.0.0-beta.30
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/colana.js +83 -7
- package/package.json +2 -4
- package/public/admin-panel.js +735 -0
- package/public/app.js +497 -29
- package/public/styles.css +115 -0
- package/public/wizard.js +1585 -0
- package/server/auth.js +9 -6
- package/server/auto-installer.js +413 -9
- package/server/config.js +1 -1
- package/server/diagnostics-routes.js +2 -1
- package/server/index.js +27 -7
- package/server/personal-agent-routes.js +6 -1
- package/server/platform.js +50 -1
- package/server/preflight.js +17 -0
- package/server/pty-manager.js +81 -32
- package/server/service-manager.js +21 -4
- package/server/spawn-env.js +7 -1
package/bin/colana.js
CHANGED
|
@@ -11,7 +11,7 @@ import { execSync, spawn } from 'child_process';
|
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import readline from 'readline';
|
|
14
|
-
import { fileURLToPath } from 'url';
|
|
14
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
15
15
|
import { commandExistsSync, getCommandPath } from '../server/platform.js';
|
|
16
16
|
import { c, icons, brandName, tagline, printBanner } from '../server/brand.js';
|
|
17
17
|
|
|
@@ -19,6 +19,9 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
19
19
|
const ROOT = path.resolve(__dirname, '..');
|
|
20
20
|
const DATA_DIR = path.join(ROOT, 'data');
|
|
21
21
|
|
|
22
|
+
/** Convert absolute path to import-safe specifier (Windows requires file:// URLs for ESM) */
|
|
23
|
+
const toImportPath = (p) => process.platform === 'win32' ? pathToFileURL(p).href : p;
|
|
24
|
+
|
|
22
25
|
// ---------------------------------------------------------------------------
|
|
23
26
|
// Provider definitions for detection & installation
|
|
24
27
|
// ---------------------------------------------------------------------------
|
|
@@ -133,12 +136,63 @@ function runInstall(cmd) {
|
|
|
133
136
|
const proc = spawn(parts[0], parts.slice(1), {
|
|
134
137
|
stdio: 'inherit',
|
|
135
138
|
env: { ...process.env },
|
|
139
|
+
...(process.platform === 'win32' && { shell: true }),
|
|
136
140
|
});
|
|
137
141
|
proc.on('close', (code) => resolve(code === 0));
|
|
138
142
|
proc.on('error', () => resolve(false));
|
|
139
143
|
});
|
|
140
144
|
}
|
|
141
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Spawn a binary with an explicit args array (needed when arguments contain spaces,
|
|
148
|
+
* e.g. winget --override "..." where the value must stay as one argument).
|
|
149
|
+
*/
|
|
150
|
+
function runInstallArgs(binary, args) {
|
|
151
|
+
return new Promise((resolve) => {
|
|
152
|
+
// No shell: true here — winget/xcode-select are real executables, not .cmd files.
|
|
153
|
+
// shell: true would cause cmd.exe to split quoted --override values into separate args.
|
|
154
|
+
const proc = spawn(binary, args, {
|
|
155
|
+
stdio: 'inherit',
|
|
156
|
+
env: { ...process.env },
|
|
157
|
+
});
|
|
158
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
159
|
+
proc.on('error', () => resolve(false));
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Attempt to auto-install C/C++ build tools needed for native npm modules.
|
|
165
|
+
* Returns true if tools were installed (or install was triggered), false otherwise.
|
|
166
|
+
*/
|
|
167
|
+
async function tryInstallBuildTools() {
|
|
168
|
+
const platform = process.platform;
|
|
169
|
+
|
|
170
|
+
if (platform === 'win32') {
|
|
171
|
+
// Try winget (available on Windows 10 21H2+ / Windows 11)
|
|
172
|
+
if (commandExistsSync('winget')) {
|
|
173
|
+
print(` ${c.muted}Installing Visual Studio Build Tools via winget...${c.reset}`);
|
|
174
|
+
const ok = await runInstallArgs('winget', [
|
|
175
|
+
'install', 'Microsoft.VisualStudio.2022.BuildTools',
|
|
176
|
+
'--override', '--add Microsoft.VisualStudio.Workload.VCTools --passive --norestart',
|
|
177
|
+
'--accept-source-agreements', '--accept-package-agreements',
|
|
178
|
+
]);
|
|
179
|
+
return ok;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (platform === 'darwin') {
|
|
185
|
+
print(` ${c.muted}Installing Xcode Command Line Tools...${c.reset}`);
|
|
186
|
+
// xcode-select --install opens a system dialog; returns non-zero if already installed
|
|
187
|
+
const ok = await runInstallArgs('xcode-select', ['--install']);
|
|
188
|
+
// Even if xcode-select exits non-zero (already installed), the tools may be present
|
|
189
|
+
return ok;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Linux — requires sudo, skip auto-install
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
142
196
|
// ---------------------------------------------------------------------------
|
|
143
197
|
// Doctor Checks (standalone + used by wizard)
|
|
144
198
|
// ---------------------------------------------------------------------------
|
|
@@ -349,7 +403,7 @@ async function firstRunWizard() {
|
|
|
349
403
|
const serviceAnswer = await ask(' Start Colana automatically on login? [Y/n] ');
|
|
350
404
|
if (serviceAnswer.toLowerCase() !== 'n') {
|
|
351
405
|
try {
|
|
352
|
-
const { installService } = await import(path.join(ROOT, 'server', 'service-manager.js'));
|
|
406
|
+
const { installService } = await import(toImportPath(path.join(ROOT, 'server', 'service-manager.js')));
|
|
353
407
|
const result = installService();
|
|
354
408
|
if (result.success) {
|
|
355
409
|
print(` ${icons.pass} Auto-start enabled. ${result.message}`);
|
|
@@ -395,8 +449,30 @@ async function installProvider(provider) {
|
|
|
395
449
|
if (success) {
|
|
396
450
|
print(` ${icons.pass} ${provider.name} installed`);
|
|
397
451
|
} else {
|
|
398
|
-
|
|
399
|
-
|
|
452
|
+
// For npm packages, try auto-installing build tools and retrying
|
|
453
|
+
if (provider.runtime === 'npm') {
|
|
454
|
+
print(` ${c.muted}Build tools may be needed. Attempting automatic install...${c.reset}`);
|
|
455
|
+
const toolsInstalled = await tryInstallBuildTools();
|
|
456
|
+
|
|
457
|
+
if (toolsInstalled) {
|
|
458
|
+
print(` ${c.muted}Retrying ${provider.name} install...${c.reset}`);
|
|
459
|
+
success = await runInstall(provider.installCmd);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (success) {
|
|
463
|
+
print(` ${icons.pass} ${provider.name} installed`);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Build tools auto-install failed or not available — show minimal fallback
|
|
468
|
+
print(` ${icons.fail} ${c.error}Installation failed.${c.reset}`);
|
|
469
|
+
if (process.platform === 'linux') {
|
|
470
|
+
print(` ${c.muted}Build tools required:${c.reset} ${c.cmd}sudo apt install python3 build-essential${c.reset}`);
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
print(` ${icons.fail} ${c.error}Installation failed.${c.reset}`);
|
|
474
|
+
}
|
|
475
|
+
print(` ${c.muted}Install manually:${c.reset} ${provider.installCmd}`);
|
|
400
476
|
}
|
|
401
477
|
}
|
|
402
478
|
|
|
@@ -410,7 +486,7 @@ async function startServer() {
|
|
|
410
486
|
|
|
411
487
|
// Use dynamic import to start the server
|
|
412
488
|
try {
|
|
413
|
-
const server = await import(serverPath);
|
|
489
|
+
const server = await import(toImportPath(serverPath));
|
|
414
490
|
// The server module starts listening on import
|
|
415
491
|
// If it exports a URL or port, we could use it
|
|
416
492
|
return server;
|
|
@@ -513,14 +589,14 @@ ${c.muted}v${pkg.version}${c.reset} ${c.muted}—${c.reset} ${c.url}https://cola
|
|
|
513
589
|
if (process.argv[2] === 'admin') {
|
|
514
590
|
const adminPath = path.join(__dirname, 'admin.js');
|
|
515
591
|
process.argv.splice(2, 1); // remove 'admin' from args
|
|
516
|
-
await import(adminPath);
|
|
592
|
+
await import(toImportPath(adminPath));
|
|
517
593
|
return;
|
|
518
594
|
}
|
|
519
595
|
|
|
520
596
|
// Handle service subcommand
|
|
521
597
|
if (process.argv[2] === 'service') {
|
|
522
598
|
const { installService, uninstallService, getServiceStatus, getServiceLogs } =
|
|
523
|
-
await import(path.join(ROOT, 'server', 'service-manager.js'));
|
|
599
|
+
await import(toImportPath(path.join(ROOT, 'server', 'service-manager.js')));
|
|
524
600
|
|
|
525
601
|
const action = process.argv[3];
|
|
526
602
|
|
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.30",
|
|
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
|
],
|