@vellumai/cli 0.1.3 → 0.1.5
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
CHANGED
package/src/adapters/openclaw.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { GATEWAY_PORT } from "../lib/constants";
|
|
2
2
|
import { buildOpenclawRuntimeServer } from "../lib/openclaw-runtime-server";
|
|
3
3
|
|
|
4
|
-
export function buildOpenclawStartupScript(
|
|
4
|
+
export async function buildOpenclawStartupScript(
|
|
5
5
|
bearerToken: string,
|
|
6
6
|
sshUser: string,
|
|
7
7
|
anthropicApiKey: string,
|
|
8
8
|
timestampRedirect: string,
|
|
9
9
|
userSetup: string,
|
|
10
10
|
ownershipFixup: string,
|
|
11
|
-
): string {
|
|
12
|
-
const runtimeServer = buildOpenclawRuntimeServer();
|
|
11
|
+
): Promise<string> {
|
|
12
|
+
const runtimeServer = await buildOpenclawRuntimeServer();
|
|
13
13
|
|
|
14
14
|
return `#!/bin/bash
|
|
15
15
|
set -e
|
package/src/commands/hatch.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import { randomBytes } from "crypto";
|
|
3
3
|
import { existsSync, unlinkSync, writeFileSync } from "fs";
|
|
4
|
+
import { createRequire } from "module";
|
|
4
5
|
import { tmpdir, userInfo } from "os";
|
|
5
6
|
import { dirname, join } from "path";
|
|
6
7
|
|
|
@@ -22,6 +23,8 @@ import { buildInterfacesSeed } from "../lib/interfaces-seed";
|
|
|
22
23
|
import { generateRandomSuffix } from "../lib/random-name";
|
|
23
24
|
import { exec, execOutput } from "../lib/step-runner";
|
|
24
25
|
|
|
26
|
+
const _require = createRequire(import.meta.url);
|
|
27
|
+
|
|
25
28
|
const INSTALL_SCRIPT_REMOTE_PATH = "/tmp/vellum-install.sh";
|
|
26
29
|
const INSTALL_SCRIPT_PATH = join(import.meta.dir, "..", "adapters", "install.sh");
|
|
27
30
|
const MACHINE_TYPE = "e2-standard-4"; // 4 vCPUs, 16 GB memory
|
|
@@ -76,19 +79,19 @@ chown -R "$SSH_USER:$SSH_USER" "$SSH_USER_HOME" 2>/dev/null || true
|
|
|
76
79
|
`;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
export function buildStartupScript(
|
|
82
|
+
export async function buildStartupScript(
|
|
80
83
|
species: Species,
|
|
81
84
|
bearerToken: string,
|
|
82
85
|
sshUser: string,
|
|
83
86
|
anthropicApiKey: string,
|
|
84
|
-
): string {
|
|
87
|
+
): Promise<string> {
|
|
85
88
|
const platformUrl = process.env.VELLUM_ASSISTANT_PLATFORM_URL ?? "https://assistant.vellum.ai";
|
|
86
89
|
const timestampRedirect = buildTimestampRedirect();
|
|
87
90
|
const userSetup = buildUserSetup(sshUser);
|
|
88
91
|
const ownershipFixup = buildOwnershipFixup();
|
|
89
92
|
|
|
90
93
|
if (species === "openclaw") {
|
|
91
|
-
return buildOpenclawStartupScript(
|
|
94
|
+
return await buildOpenclawStartupScript(
|
|
92
95
|
bearerToken,
|
|
93
96
|
sshUser,
|
|
94
97
|
anthropicApiKey,
|
|
@@ -117,6 +120,7 @@ ANTHROPIC_API_KEY=\$ANTHROPIC_API_KEY
|
|
|
117
120
|
GATEWAY_RUNTIME_PROXY_ENABLED=\$GATEWAY_RUNTIME_PROXY_ENABLED
|
|
118
121
|
RUNTIME_PROXY_BEARER_TOKEN=\$RUNTIME_PROXY_BEARER_TOKEN
|
|
119
122
|
INTERFACES_SEED_DIR=\$INTERFACES_SEED_DIR
|
|
123
|
+
RUNTIME_HTTP_PORT=7821
|
|
120
124
|
DOTENV_EOF
|
|
121
125
|
|
|
122
126
|
mkdir -p "\$HOME/.vellum/workspace"
|
|
@@ -485,7 +489,7 @@ async function hatchGcp(
|
|
|
485
489
|
console.error("Error: ANTHROPIC_API_KEY environment variable is not set.");
|
|
486
490
|
process.exit(1);
|
|
487
491
|
}
|
|
488
|
-
const startupScript = buildStartupScript(species, bearerToken, sshUser, anthropicApiKey);
|
|
492
|
+
const startupScript = await buildStartupScript(species, bearerToken, sshUser, anthropicApiKey);
|
|
489
493
|
const startupScriptPath = join(tmpdir(), `${instanceName}-startup.sh`);
|
|
490
494
|
writeFileSync(startupScriptPath, startupScript);
|
|
491
495
|
|
|
@@ -583,7 +587,8 @@ async function hatchGcp(
|
|
|
583
587
|
(await checkCurlFailure(instanceName, project, zone, account))
|
|
584
588
|
) {
|
|
585
589
|
console.log("");
|
|
586
|
-
|
|
590
|
+
const installScriptUrl = `${process.env.VELLUM_ASSISTANT_PLATFORM_URL ?? "https://assistant.vellum.ai"}/install.sh`;
|
|
591
|
+
console.log(`🔄 Detected install script curl failure for ${installScriptUrl}, attempting recovery...`);
|
|
587
592
|
await recoverFromCurlFailure(instanceName, project, zone, sshUser, account);
|
|
588
593
|
console.log("✅ Recovery successful!");
|
|
589
594
|
} else {
|
|
@@ -649,7 +654,7 @@ async function hatchCustom(
|
|
|
649
654
|
process.exit(1);
|
|
650
655
|
}
|
|
651
656
|
|
|
652
|
-
const startupScript = buildStartupScript(species, bearerToken, sshUser, anthropicApiKey);
|
|
657
|
+
const startupScript = await buildStartupScript(species, bearerToken, sshUser, anthropicApiKey);
|
|
653
658
|
const startupScriptPath = join(tmpdir(), `${instanceName}-startup.sh`);
|
|
654
659
|
writeFileSync(startupScriptPath, startupScript);
|
|
655
660
|
|
|
@@ -714,6 +719,22 @@ async function hatchCustom(
|
|
|
714
719
|
}
|
|
715
720
|
}
|
|
716
721
|
|
|
722
|
+
function resolveGatewayDir(): string {
|
|
723
|
+
const sourceDir = join(import.meta.dir, "..", "..", "..", "gateway");
|
|
724
|
+
if (existsSync(sourceDir)) {
|
|
725
|
+
return sourceDir;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
try {
|
|
729
|
+
const pkgPath = _require.resolve("@vellumai/vellum-gateway/package.json");
|
|
730
|
+
return dirname(pkgPath);
|
|
731
|
+
} catch {
|
|
732
|
+
throw new Error(
|
|
733
|
+
"Gateway not found. Ensure @vellumai/vellum-gateway is installed or run from the source tree.",
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
717
738
|
async function hatchLocal(species: Species, name: string | null): Promise<void> {
|
|
718
739
|
const instanceName = name ?? `${species}-${generateRandomSuffix()}`;
|
|
719
740
|
|
|
@@ -722,9 +743,9 @@ async function hatchLocal(species: Species, name: string | null): Promise<void>
|
|
|
722
743
|
console.log("");
|
|
723
744
|
|
|
724
745
|
console.log("🔨 Starting local daemon...");
|
|
725
|
-
const daemonBinary = join(dirname(process.execPath), "vellum-daemon");
|
|
726
746
|
|
|
727
|
-
if (
|
|
747
|
+
if (process.env.VELLUM_DESKTOP_APP) {
|
|
748
|
+
const daemonBinary = join(dirname(process.execPath), "vellum-daemon");
|
|
728
749
|
const child = spawn(daemonBinary, [], {
|
|
729
750
|
detached: true,
|
|
730
751
|
stdio: "ignore",
|
|
@@ -748,7 +769,17 @@ async function hatchLocal(species: Species, name: string | null): Promise<void>
|
|
|
748
769
|
console.warn("⚠️ Daemon socket did not appear within 10s — continuing anyway");
|
|
749
770
|
}
|
|
750
771
|
} else {
|
|
751
|
-
const
|
|
772
|
+
const assistantDir = join(import.meta.dir, "..", "..", "..", "assistant");
|
|
773
|
+
const assistantIndex = join(assistantDir, "src", "index.ts");
|
|
774
|
+
|
|
775
|
+
if (!existsSync(assistantIndex)) {
|
|
776
|
+
throw new Error(
|
|
777
|
+
"vellum-daemon binary not found and assistant source not available.\n" +
|
|
778
|
+
" Ensure the daemon binary is bundled alongside the CLI, or run from the source tree.",
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
const child = spawn("bun", ["run", assistantIndex, "daemon", "start"], {
|
|
752
783
|
stdio: "inherit",
|
|
753
784
|
env: { ...process.env },
|
|
754
785
|
});
|
|
@@ -766,24 +797,19 @@ async function hatchLocal(species: Species, name: string | null): Promise<void>
|
|
|
766
797
|
}
|
|
767
798
|
|
|
768
799
|
console.log("🌐 Starting gateway...");
|
|
769
|
-
const gatewayDir =
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
},
|
|
783
|
-
});
|
|
784
|
-
gateway.unref();
|
|
785
|
-
console.log("✅ Gateway started\n");
|
|
786
|
-
}
|
|
800
|
+
const gatewayDir = resolveGatewayDir();
|
|
801
|
+
const gateway = spawn("bun", ["run", "src/index.ts"], {
|
|
802
|
+
cwd: gatewayDir,
|
|
803
|
+
detached: true,
|
|
804
|
+
stdio: "ignore",
|
|
805
|
+
env: {
|
|
806
|
+
...process.env,
|
|
807
|
+
GATEWAY_RUNTIME_PROXY_ENABLED: "true",
|
|
808
|
+
GATEWAY_RUNTIME_PROXY_REQUIRE_AUTH: "false",
|
|
809
|
+
},
|
|
810
|
+
});
|
|
811
|
+
gateway.unref();
|
|
812
|
+
console.log("✅ Gateway started\n");
|
|
787
813
|
|
|
788
814
|
const runtimeUrl = `http://localhost:${GATEWAY_PORT}`;
|
|
789
815
|
const localEntry: AssistantEntry = {
|
package/src/lib/aws.ts
CHANGED
|
@@ -420,7 +420,7 @@ export async function hatchAws(
|
|
|
420
420
|
console.log("\u{1F50D} Finding latest Debian AMI...");
|
|
421
421
|
const amiId = await getLatestDebianAmi(region);
|
|
422
422
|
|
|
423
|
-
const startupScript = buildStartupScript(species, bearerToken, sshUser, anthropicApiKey);
|
|
423
|
+
const startupScript = await buildStartupScript(species, bearerToken, sshUser, anthropicApiKey);
|
|
424
424
|
const startupScriptPath = join(tmpdir(), `${instanceName}-startup.sh`);
|
|
425
425
|
writeFileSync(startupScriptPath, startupScript);
|
|
426
426
|
|
package/src/lib/gcp.ts
CHANGED
|
@@ -139,15 +139,14 @@ export async function syncFirewallRules(
|
|
|
139
139
|
"firewall-rules",
|
|
140
140
|
"list",
|
|
141
141
|
`--project=${project}`,
|
|
142
|
-
|
|
143
|
-
"--format=value(name)",
|
|
142
|
+
"--format=json(name,targetTags)",
|
|
144
143
|
];
|
|
145
144
|
if (account) listArgs.push(`--account=${account}`);
|
|
146
145
|
const output = await execOutput("gcloud", listArgs);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
.
|
|
150
|
-
.
|
|
146
|
+
const allRules = JSON.parse(output) as Array<{ name: string; targetTags?: string[] }>;
|
|
147
|
+
existingNames = allRules
|
|
148
|
+
.filter((r) => r.targetTags?.includes(tag))
|
|
149
|
+
.map((r) => r.name);
|
|
151
150
|
} catch {
|
|
152
151
|
existingNames = [];
|
|
153
152
|
}
|
|
@@ -190,10 +189,11 @@ export async function fetchFirewallRules(
|
|
|
190
189
|
"firewall-rules",
|
|
191
190
|
"list",
|
|
192
191
|
`--project=${project}`,
|
|
193
|
-
`--filter=targetTags:${tag}`,
|
|
194
192
|
"--format=json",
|
|
195
193
|
]);
|
|
196
|
-
|
|
194
|
+
const rules = JSON.parse(output) as Array<{ targetTags?: string[] }>;
|
|
195
|
+
const filtered = rules.filter((r) => r.targetTags?.includes(tag));
|
|
196
|
+
return JSON.stringify(filtered, null, 2);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
export interface GcpInstance {
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
1
|
import { join } from "path";
|
|
3
2
|
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
const constantsSource = await Bun.file(join(import.meta.dir, "constants.ts")).text();
|
|
4
|
+
const defaultMainScreenSource = await Bun.file(join(import.meta.dir, "..", "components", "DefaultMainScreen.tsx")).text();
|
|
6
5
|
|
|
7
6
|
function inlineLocalImports(source: string): string {
|
|
8
|
-
const constantsSource = readFileSync(CONSTANTS_PATH, "utf-8");
|
|
9
|
-
|
|
10
7
|
return source
|
|
11
8
|
.replace(/import\s*\{[^}]*\}\s*from\s*["'][^"']*\/constants["'];?\s*\n/, constantsSource + "\n")
|
|
12
9
|
.replace(/import\s*\{[^}]*\}\s*from\s*["']path["'];?\s*\n/, "");
|
|
13
10
|
}
|
|
14
11
|
|
|
15
12
|
export function buildInterfacesSeed(): string {
|
|
16
|
-
const
|
|
17
|
-
const mainWindowSource = inlineLocalImports(rawSource);
|
|
13
|
+
const mainWindowSource = inlineLocalImports(defaultMainScreenSource);
|
|
18
14
|
|
|
19
15
|
return `
|
|
20
16
|
INTERFACES_SEED_DIR="/tmp/interfaces-seed"
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
1
|
import { join } from "path";
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export function buildOpenclawRuntimeServer(): string {
|
|
7
|
-
const serverSource = readFileSync(ADAPTER_PATH, "utf-8");
|
|
3
|
+
export async function buildOpenclawRuntimeServer(): Promise<string> {
|
|
4
|
+
const serverSource = await Bun.file(join(import.meta.dir, "..", "adapters", "openclaw-http-server.ts")).text();
|
|
8
5
|
|
|
9
6
|
return `
|
|
10
7
|
cat > /opt/openclaw-runtime-server.ts << 'RUNTIME_SERVER_EOF'
|