helixevo 0.2.13 → 0.2.15
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.
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
|
|
3
|
+
export const dynamic = 'force-dynamic'
|
|
4
|
+
|
|
5
|
+
// Exit code 75 signals the parent CLI to auto-restart the dashboard
|
|
6
|
+
const RESTART_EXIT_CODE = 75
|
|
7
|
+
|
|
8
|
+
export async function POST() {
|
|
9
|
+
// Send response first, then exit after a brief delay
|
|
10
|
+
setTimeout(() => {
|
|
11
|
+
process.exit(RESTART_EXIT_CODE)
|
|
12
|
+
}, 500)
|
|
13
|
+
|
|
14
|
+
return NextResponse.json({ restarting: true })
|
|
15
|
+
}
|
|
@@ -1,31 +1,80 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { execSync } from 'child_process'
|
|
3
|
+
import { existsSync, cpSync, readdirSync, rmSync, writeFileSync, mkdirSync } from 'fs'
|
|
4
|
+
import { join } from 'path'
|
|
5
|
+
import { homedir } from 'os'
|
|
3
6
|
|
|
4
7
|
export const dynamic = 'force-dynamic'
|
|
5
8
|
|
|
9
|
+
const HELIX_DASHBOARD_DIR = join(homedir(), '.helix', 'dashboard')
|
|
10
|
+
|
|
11
|
+
function findNewDashboardSource(): string | null {
|
|
12
|
+
const candidates: string[] = []
|
|
13
|
+
|
|
14
|
+
// From npm global prefix
|
|
15
|
+
try {
|
|
16
|
+
const globalPrefix = execSync('npm prefix -g', { encoding: 'utf-8' }).trim()
|
|
17
|
+
candidates.push(join(globalPrefix, 'lib', 'node_modules', 'helixevo', 'dashboard'))
|
|
18
|
+
candidates.push(join(globalPrefix, 'node_modules', 'helixevo', 'dashboard'))
|
|
19
|
+
} catch {}
|
|
20
|
+
|
|
21
|
+
for (const dir of candidates) {
|
|
22
|
+
if (existsSync(join(dir, 'package.json'))) {
|
|
23
|
+
return dir
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function copyDashboardFiles(sourceDir: string, newVersion: string): void {
|
|
30
|
+
mkdirSync(HELIX_DASHBOARD_DIR, { recursive: true })
|
|
31
|
+
|
|
32
|
+
// Copy source files (exclude node_modules, .next, package-lock.json)
|
|
33
|
+
const items = readdirSync(sourceDir, { withFileTypes: true })
|
|
34
|
+
for (const item of items) {
|
|
35
|
+
if (item.name === 'node_modules' || item.name === '.next' || item.name === 'package-lock.json') continue
|
|
36
|
+
const src = join(sourceDir, item.name)
|
|
37
|
+
const dest = join(HELIX_DASHBOARD_DIR, item.name)
|
|
38
|
+
cpSync(src, dest, { recursive: true })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Clear .next cache so Next.js recompiles from new source
|
|
42
|
+
const nextCache = join(HELIX_DASHBOARD_DIR, '.next')
|
|
43
|
+
if (existsSync(nextCache)) rmSync(nextCache, { recursive: true })
|
|
44
|
+
|
|
45
|
+
// Write version marker
|
|
46
|
+
writeFileSync(join(HELIX_DASHBOARD_DIR, '.helixevo-version'), newVersion)
|
|
47
|
+
}
|
|
48
|
+
|
|
6
49
|
export async function POST() {
|
|
7
50
|
try {
|
|
8
|
-
//
|
|
51
|
+
// 1. Install the new package
|
|
9
52
|
const output = execSync('npm install -g helixevo@latest 2>&1', {
|
|
10
53
|
encoding: 'utf-8',
|
|
11
|
-
timeout: 120000,
|
|
54
|
+
timeout: 120000,
|
|
12
55
|
env: { ...process.env },
|
|
13
56
|
})
|
|
14
57
|
|
|
15
|
-
// Get the new version
|
|
58
|
+
// 2. Get the new version
|
|
16
59
|
let newVersion = ''
|
|
17
60
|
try {
|
|
18
61
|
newVersion = execSync('helixevo --version 2>/dev/null', { encoding: 'utf-8' }).trim()
|
|
19
62
|
} catch {
|
|
20
|
-
// Try parsing from output
|
|
21
63
|
const match = output.match(/helixevo@(\d+\.\d+\.\d+)/)
|
|
22
64
|
newVersion = match?.[1] ?? 'unknown'
|
|
23
65
|
}
|
|
24
66
|
|
|
67
|
+
// 3. Copy new dashboard files to ~/.helix/dashboard
|
|
68
|
+
const newSource = findNewDashboardSource()
|
|
69
|
+
if (newSource) {
|
|
70
|
+
copyDashboardFiles(newSource, newVersion)
|
|
71
|
+
}
|
|
72
|
+
|
|
25
73
|
return NextResponse.json({
|
|
26
74
|
success: true,
|
|
27
75
|
version: newVersion,
|
|
28
|
-
|
|
76
|
+
dashboardUpdated: !!newSource,
|
|
77
|
+
output: output.slice(-500),
|
|
29
78
|
})
|
|
30
79
|
} catch (err: unknown) {
|
|
31
80
|
const message = err instanceof Error ? err.message : String(err)
|
|
@@ -56,10 +56,24 @@ export function UpdateBanner({ currentVersion }: { currentVersion: string }) {
|
|
|
56
56
|
if (data.success) {
|
|
57
57
|
setState('success')
|
|
58
58
|
setNewVersion(data.version)
|
|
59
|
-
//
|
|
60
|
-
setTimeout(() => {
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
// Trigger dashboard restart — the CLI will auto-relaunch
|
|
60
|
+
setTimeout(async () => {
|
|
61
|
+
try {
|
|
62
|
+
await fetch('/api/restart', { method: 'POST' })
|
|
63
|
+
} catch {}
|
|
64
|
+
// Poll until the new server is ready, then reload
|
|
65
|
+
const poll = setInterval(async () => {
|
|
66
|
+
try {
|
|
67
|
+
const res = await fetch('/', { cache: 'no-store' })
|
|
68
|
+
if (res.ok) {
|
|
69
|
+
clearInterval(poll)
|
|
70
|
+
window.location.reload()
|
|
71
|
+
}
|
|
72
|
+
} catch {}
|
|
73
|
+
}, 1500)
|
|
74
|
+
// Stop polling after 60s
|
|
75
|
+
setTimeout(() => clearInterval(poll), 60000)
|
|
76
|
+
}, 1500)
|
|
63
77
|
} else {
|
|
64
78
|
setState('error')
|
|
65
79
|
setErrorMsg(data.error ?? 'Update failed')
|
package/dist/cli.js
CHANGED
|
@@ -12378,20 +12378,45 @@ async function dashboardCommand() {
|
|
|
12378
12378
|
ensureSkillGraph();
|
|
12379
12379
|
console.log(` \uD83C\uDF10 Starting HelixEvo Dashboard v${VERSION} at http://localhost:3847
|
|
12380
12380
|
`);
|
|
12381
|
+
launchDashboard(dir, true);
|
|
12382
|
+
}
|
|
12383
|
+
var RESTART_EXIT_CODE = 75;
|
|
12384
|
+
function launchDashboard(dir, openBrowser) {
|
|
12385
|
+
let currentVersion = VERSION;
|
|
12386
|
+
try {
|
|
12387
|
+
currentVersion = execSync2("helixevo --version 2>/dev/null", { encoding: "utf-8" }).trim() || VERSION;
|
|
12388
|
+
} catch {}
|
|
12381
12389
|
const child = spawn2("npx", ["next", "dev", "--port", "3847"], {
|
|
12382
12390
|
cwd: dir,
|
|
12383
12391
|
stdio: "inherit",
|
|
12384
|
-
env: { ...process.env, HELIXEVO_VERSION:
|
|
12392
|
+
env: { ...process.env, HELIXEVO_VERSION: currentVersion }
|
|
12385
12393
|
});
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
|
|
12394
|
+
if (openBrowser) {
|
|
12395
|
+
setTimeout(() => {
|
|
12396
|
+
try {
|
|
12397
|
+
const platform = process.platform;
|
|
12398
|
+
const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
|
|
12399
|
+
execSync2(`${cmd} http://localhost:3847`, { stdio: "ignore" });
|
|
12400
|
+
} catch {}
|
|
12401
|
+
}, 3000);
|
|
12402
|
+
}
|
|
12393
12403
|
child.on("close", (code) => {
|
|
12394
|
-
|
|
12404
|
+
if (code === RESTART_EXIT_CODE) {
|
|
12405
|
+
console.log(`
|
|
12406
|
+
\uD83D\uDD04 Restarting dashboard after update...
|
|
12407
|
+
`);
|
|
12408
|
+
const newDir = prepareDashboard() ?? dir;
|
|
12409
|
+
ensureSkillGraph();
|
|
12410
|
+
let updatedVersion = currentVersion;
|
|
12411
|
+
try {
|
|
12412
|
+
updatedVersion = execSync2("helixevo --version 2>/dev/null", { encoding: "utf-8" }).trim() || currentVersion;
|
|
12413
|
+
} catch {}
|
|
12414
|
+
console.log(` \uD83C\uDF10 HelixEvo Dashboard v${updatedVersion} at http://localhost:3847
|
|
12415
|
+
`);
|
|
12416
|
+
launchDashboard(newDir, false);
|
|
12417
|
+
} else {
|
|
12418
|
+
process.exit(code ?? 0);
|
|
12419
|
+
}
|
|
12395
12420
|
});
|
|
12396
12421
|
}
|
|
12397
12422
|
function prepareDashboard() {
|
package/dist/postinstall.js
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/postinstall.ts
|
|
4
|
-
import {
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
5
|
import { join, dirname } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
var
|
|
8
|
-
var
|
|
7
|
+
var __dirname = "/Users/tianchichen/Documents/GitHub/helixevo/src";
|
|
8
|
+
var version = "unknown";
|
|
9
|
+
try {
|
|
10
|
+
const candidates = [
|
|
11
|
+
join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"),
|
|
12
|
+
join(process.cwd(), "package.json"),
|
|
13
|
+
join(__dirname, "..", "package.json")
|
|
14
|
+
];
|
|
15
|
+
for (const p of candidates) {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(readFileSync(p, "utf-8"));
|
|
18
|
+
if (pkg.name === "helixevo" && pkg.version) {
|
|
19
|
+
version = pkg.version;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
} catch {}
|
|
9
25
|
var green = "\x1B[32m";
|
|
10
26
|
var cyan = "\x1B[36m";
|
|
11
27
|
var bold = "\x1B[1m";
|
|
12
28
|
var dim = "\x1B[2m";
|
|
13
29
|
var reset = "\x1B[0m";
|
|
14
30
|
console.log();
|
|
15
|
-
console.log(` ${green}✓${reset} ${bold}HelixEvo v${
|
|
31
|
+
console.log(` ${green}✓${reset} ${bold}HelixEvo v${version}${reset} installed successfully`);
|
|
16
32
|
console.log();
|
|
17
33
|
console.log(` ${dim}Get started:${reset}`);
|
|
18
34
|
console.log(` ${cyan}helixevo init${reset} Import skills + generate skill tests`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helixevo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
4
|
"description": "Self-evolving skill ecosystem for AI agents. Skills and projects co-evolve through multi-judge evaluation and a Pareto frontier.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
25
25
|
"prepare": "npm run build",
|
|
26
26
|
"prepublishOnly": "npm run typecheck && npm run build",
|
|
27
|
-
"postinstall": "node dist/postinstall.js
|
|
27
|
+
"postinstall": "node dist/postinstall.js || true"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"commander": "^13.1.0",
|