@vellumai/cli 0.1.14 โ 0.3.2
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/package.json +1 -1
- package/src/commands/hatch.ts +43 -15
- package/src/commands/retire.ts +2 -3
- package/src/lib/local.ts +23 -0
package/package.json
CHANGED
package/src/commands/hatch.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { randomBytes } from "crypto";
|
|
2
|
-
import { existsSync, unlinkSync, writeFileSync } from "fs";
|
|
2
|
+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
|
-
import { tmpdir, userInfo } from "os";
|
|
5
|
-
import { join } from "path";
|
|
4
|
+
import { homedir, tmpdir, userInfo } from "os";
|
|
5
|
+
import { dirname, join } from "path";
|
|
6
6
|
|
|
7
7
|
import { buildOpenclawStartupScript } from "../adapters/openclaw";
|
|
8
|
-
import { saveAssistantEntry } from "../lib/assistant-config";
|
|
8
|
+
import { loadAllAssistants, saveAssistantEntry } from "../lib/assistant-config";
|
|
9
9
|
import type { AssistantEntry } from "../lib/assistant-config";
|
|
10
10
|
import { hatchAws } from "../lib/aws";
|
|
11
11
|
import {
|
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
import type { RemoteHost, Species } from "../lib/constants";
|
|
18
18
|
import { hatchGcp } from "../lib/gcp";
|
|
19
19
|
import type { PollResult, WatchHatchingResult } from "../lib/gcp";
|
|
20
|
-
import { startLocalDaemon, startGateway } from "../lib/local";
|
|
20
|
+
import { startLocalDaemon, startGateway, stopLocalProcesses } from "../lib/local";
|
|
21
|
+
import { isProcessAlive } from "../lib/process";
|
|
21
22
|
import { generateRandomSuffix } from "../lib/random-name";
|
|
22
23
|
import { exec } from "../lib/step-runner";
|
|
23
24
|
|
|
@@ -514,21 +515,35 @@ async function hatchLocal(species: Species, name: string | null, daemonOnly: boo
|
|
|
514
515
|
const instanceName =
|
|
515
516
|
name ?? process.env.VELLUM_ASSISTANT_NAME ?? `${species}-${generateRandomSuffix()}`;
|
|
516
517
|
|
|
518
|
+
// Clean up stale local state: if daemon/gateway processes are running but
|
|
519
|
+
// the lock file has no entries, stop them before starting fresh.
|
|
520
|
+
const vellumDir = join(homedir(), ".vellum");
|
|
521
|
+
const existingAssistants = loadAllAssistants();
|
|
522
|
+
const localAssistants = existingAssistants.filter((a) => a.cloud === "local");
|
|
523
|
+
if (localAssistants.length === 0) {
|
|
524
|
+
const daemonPid = isProcessAlive(join(vellumDir, "vellum.pid"));
|
|
525
|
+
const gatewayPid = isProcessAlive(join(vellumDir, "gateway.pid"));
|
|
526
|
+
if (daemonPid.alive || gatewayPid.alive) {
|
|
527
|
+
console.log("๐งน Cleaning up stale local processes (no lock file entry)...\n");
|
|
528
|
+
await stopLocalProcesses();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
517
532
|
console.log(`๐ฅ Hatching local assistant: ${instanceName}`);
|
|
518
533
|
console.log(` Species: ${species}`);
|
|
519
534
|
console.log("");
|
|
520
535
|
|
|
521
536
|
await startLocalDaemon();
|
|
522
537
|
|
|
523
|
-
// The desktop app communicates with the daemon directly via Unix socket,
|
|
524
|
-
// so the HTTP gateway is only needed for non-desktop (CLI) usage.
|
|
525
538
|
let runtimeUrl: string;
|
|
526
|
-
|
|
527
|
-
if (process.env.VELLUM_DESKTOP_APP) {
|
|
528
|
-
// No gateway needed โ the macOS app uses DaemonClient over the Unix socket.
|
|
529
|
-
runtimeUrl = "local";
|
|
530
|
-
} else {
|
|
539
|
+
try {
|
|
531
540
|
runtimeUrl = await startGateway();
|
|
541
|
+
} catch (error) {
|
|
542
|
+
// Gateway failed โ stop the daemon we just started so we don't leave
|
|
543
|
+
// orphaned processes with no lock file entry.
|
|
544
|
+
console.error(`\nโ Gateway startup failed โ stopping daemon to avoid orphaned processes.`);
|
|
545
|
+
await stopLocalProcesses();
|
|
546
|
+
throw error;
|
|
532
547
|
}
|
|
533
548
|
|
|
534
549
|
const baseDataDir = join(process.env.BASE_DATA_DIR?.trim() || (process.env.HOME ?? userInfo().homedir), ".vellum");
|
|
@@ -554,14 +569,27 @@ async function hatchLocal(species: Species, name: string | null, daemonOnly: boo
|
|
|
554
569
|
}
|
|
555
570
|
|
|
556
571
|
function getCliVersion(): string {
|
|
572
|
+
// Strategy 1: createRequire โ works in Bun dev (source tree).
|
|
557
573
|
try {
|
|
558
|
-
// Use createRequire for JSON import โ works in both Bun dev and compiled binary.
|
|
559
574
|
const require = createRequire(import.meta.url);
|
|
560
575
|
const pkg = require("../../package.json") as { version?: string };
|
|
561
|
-
|
|
576
|
+
if (pkg.version) return pkg.version;
|
|
562
577
|
} catch {
|
|
563
|
-
|
|
578
|
+
// Fall through to next strategy.
|
|
564
579
|
}
|
|
580
|
+
|
|
581
|
+
// Strategy 2: Read package.json adjacent to the compiled binary.
|
|
582
|
+
try {
|
|
583
|
+
const binPkg = join(dirname(process.execPath), "package.json");
|
|
584
|
+
if (existsSync(binPkg)) {
|
|
585
|
+
const pkg = JSON.parse(readFileSync(binPkg, "utf-8")) as { version?: string };
|
|
586
|
+
if (pkg.version) return pkg.version;
|
|
587
|
+
}
|
|
588
|
+
} catch {
|
|
589
|
+
// Fall through.
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return "unknown";
|
|
565
593
|
}
|
|
566
594
|
|
|
567
595
|
export async function hatch(): Promise<void> {
|
package/src/commands/retire.ts
CHANGED
|
@@ -59,11 +59,10 @@ async function retireLocal(): Promise<void> {
|
|
|
59
59
|
child.on("error", () => resolve());
|
|
60
60
|
});
|
|
61
61
|
} catch {}
|
|
62
|
-
|
|
63
|
-
// Only delete ~/.vellum in non-desktop mode
|
|
64
|
-
rmSync(vellumDir, { recursive: true, force: true });
|
|
65
62
|
}
|
|
66
63
|
|
|
64
|
+
rmSync(vellumDir, { recursive: true, force: true });
|
|
65
|
+
|
|
67
66
|
console.log("\u2705 Local instance retired.");
|
|
68
67
|
}
|
|
69
68
|
|
package/src/lib/local.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { dirname, join } from "path";
|
|
|
6
6
|
|
|
7
7
|
import { loadAllAssistants, loadLatestAssistant } from "./assistant-config.js";
|
|
8
8
|
import { GATEWAY_PORT } from "./constants.js";
|
|
9
|
+
import { stopProcessByPidFile } from "./process.js";
|
|
9
10
|
|
|
10
11
|
const _require = createRequire(import.meta.url);
|
|
11
12
|
|
|
@@ -49,11 +50,18 @@ function resolveGatewayDir(): string {
|
|
|
49
50
|
return override;
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
// Source tree: cli/src/lib/ โ ../../.. โ repo root โ gateway/
|
|
52
54
|
const sourceDir = join(import.meta.dir, "..", "..", "..", "gateway");
|
|
53
55
|
if (isGatewaySourceDir(sourceDir)) {
|
|
54
56
|
return sourceDir;
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
// Compiled binary: gateway/ bundled adjacent to the CLI executable.
|
|
60
|
+
const binGateway = join(dirname(process.execPath), "gateway");
|
|
61
|
+
if (isGatewaySourceDir(binGateway)) {
|
|
62
|
+
return binGateway;
|
|
63
|
+
}
|
|
64
|
+
|
|
57
65
|
const cwdSourceDir = findGatewaySourceFromCwd();
|
|
58
66
|
if (cwdSourceDir) {
|
|
59
67
|
return cwdSourceDir;
|
|
@@ -339,3 +347,18 @@ export async function startGateway(): Promise<string> {
|
|
|
339
347
|
console.log("โ
Gateway started\n");
|
|
340
348
|
return publicUrl || `http://localhost:${GATEWAY_PORT}`;
|
|
341
349
|
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Stop any locally-running daemon and gateway processes and clean up
|
|
353
|
+
* PID/socket files. Called when hatch fails partway through so we don't
|
|
354
|
+
* leave orphaned processes with no lock file entry.
|
|
355
|
+
*/
|
|
356
|
+
export async function stopLocalProcesses(): Promise<void> {
|
|
357
|
+
const vellumDir = join(homedir(), ".vellum");
|
|
358
|
+
const daemonPidFile = join(vellumDir, "vellum.pid");
|
|
359
|
+
const socketFile = join(vellumDir, "vellum.sock");
|
|
360
|
+
await stopProcessByPidFile(daemonPidFile, "daemon", [socketFile]);
|
|
361
|
+
|
|
362
|
+
const gatewayPidFile = join(vellumDir, "gateway.pid");
|
|
363
|
+
await stopProcessByPidFile(gatewayPidFile, "gateway");
|
|
364
|
+
}
|