Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules/
out/
claude/
claude/
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ Commits are managed via the Vers orchestrator API at `https://api.vers.sh/api/v1
## Development

```bash
npm install
npm test
bun install
bun test
```

## Optional flags
Expand Down
34 changes: 20 additions & 14 deletions src/boot.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ function remotePublicUrl(vmId) {

export function buildRuntimeEnv(vm, topology, options = {}) {
const rootUrl = options.rootUrl || remotePublicUrl(topology.root.vmId);
const llmProxyKey =
options.llmProxyKey && String(options.llmProxyKey).trim()
? shellQuote(options.llmProxyKey)
: process.env.LLM_PROXY_KEY
? shellQuote(process.env.LLM_PROXY_KEY)
: "";
const anthropicApiKey =
options.anthropicApiKey && String(options.anthropicApiKey).trim()
? shellQuote(options.anthropicApiKey)
: process.env.ANTHROPIC_API_KEY
? shellQuote(process.env.ANTHROPIC_API_KEY)
: "";
const env = {
PORT: "3000",
VERS_VM_ID: vm.vmId,
Expand All @@ -31,20 +43,14 @@ export function buildRuntimeEnv(vm, topology, options = {}) {
? shellQuote(options.versAuthToken)
: `\${${topology.env.versAuthTokenEnv}:-}`,
VERS_INFRA_URL: shellQuote(rootUrl),
LLM_PROXY_KEY:
options.llmProxyKey && String(options.llmProxyKey).trim()
? shellQuote(options.llmProxyKey)
: process.env.LLM_PROXY_KEY
? shellQuote(process.env.LLM_PROXY_KEY)
: "",
// Punkin-pi's AI package requires ANTHROPIC_API_KEY at startup before
// the vers provider is selected via set_model. Alias it to LLM_PROXY_KEY
// so the Anthropic SDK initializes with the vers proxy key.
ANTHROPIC_API_KEY:
options.llmProxyKey && String(options.llmProxyKey).trim()
? shellQuote(options.llmProxyKey)
: process.env.LLM_PROXY_KEY
? shellQuote(process.env.LLM_PROXY_KEY)
LLM_PROXY_KEY: llmProxyKey,
// Optional secondary provider key for internal runtime failover.
ANTHROPIC_API_KEY: anthropicApiKey,
REEF_MODEL_PROVIDER:
options.modelProvider && String(options.modelProvider).trim()
? shellQuote(options.modelProvider)
: process.env.REEF_MODEL_PROVIDER
? shellQuote(process.env.REEF_MODEL_PROVIDER)
: "",
REEF_ROLE: vm.runtime.reefRole,
REEF_CATEGORY: vm.category,
Expand Down
27 changes: 13 additions & 14 deletions src/orchestrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,29 +191,26 @@ async function registerRootFleetRecords(topology, authToken, fetchImpl = fetch)
await apiRequest(rootBaseUrl, authToken, "PATCH", `/vm-tree/vms/${encodeURIComponent(topology.root.vmId)}`, {
name: topology.root.name,
category: topology.root.category,
status: "running",
address: `${topology.root.vmId}.vm.vers.sh`,
lastHeartbeat: Date.now(),
reefConfig: topology.root.reefConfig,
}, fetchImpl).catch(async () => {
await apiRequest(rootBaseUrl, authToken, "POST", "/vm-tree/vms", {
vmId: topology.root.vmId,
name: topology.root.name,
category: topology.root.category,
status: "running",
address: `${topology.root.vmId}.vm.vers.sh`,
lastHeartbeat: Date.now(),
reefConfig: topology.root.reefConfig,
}, fetchImpl);
await apiRequest(rootBaseUrl, authToken, "PATCH", `/vm-tree/vms/${encodeURIComponent(topology.root.vmId)}`, {
status: "running",
address: `${topology.root.vmId}.vm.vers.sh`,
lastHeartbeat: Date.now(),
}, fetchImpl);
});

await apiRequest(rootBaseUrl, authToken, "POST", "/registry/vms", {
id: topology.root.vmId,
name: topology.root.name,
role: "infra",
address: `${topology.root.vmId}.vm.vers.sh`,
reefConfig: topology.root.reefConfig,
registeredBy: "vers-fleets",
metadata: {
category: topology.root.category,
publicUrl: rootBaseUrl,
sqliteAuthority: true,
},
}, fetchImpl);
}

function writeDeployment(outDir, deployment) {
Expand Down Expand Up @@ -457,6 +454,7 @@ export async function provisionFleet(input = {}, options = {}) {
versApiKey: auth.apiKey,
versAuthToken: authToken,
llmProxyKey: llmProxy.key,
anthropicApiKey: options.anthropicApiKey || process.env.ANTHROPIC_API_KEY,
rootCommitId,
goldenCommitId,
});
Expand All @@ -474,6 +472,7 @@ export async function provisionFleet(input = {}, options = {}) {
versApiKey: auth.apiKey,
versAuthToken: authToken,
llmProxyKey: llmProxy.key,
anthropicApiKey: options.anthropicApiKey || process.env.ANTHROPIC_API_KEY,
goldenCommitId,
},
);
Expand Down
4 changes: 2 additions & 2 deletions src/topology.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ function defaultRootVmConfig() {

export function defaultSharedOperationalDna() {
return {
services: ["bootloader", "cron", "docs", "github", "installer", "lieutenant", "services", "swarm", "ui", "vers-config"],
services: ["bootloader", "cron", "docs", "github", "installer", "lieutenant", "logs", "probe", "services", "signals", "swarm", "ui", "vers-config"],
capabilities: ["github", "pi-vers", "punkin", "reef-extension", "vers-fleets"],
};
}

export function defaultRootAuthorityOverlayDna() {
return {
services: ["commits", "registry", "store", "vm-tree"],
services: ["commits", "scheduled", "store", "usage", "vm-tree"],
capabilities: ["reef-root", "root-lineage", "sqlite-authority"],
};
}
Expand Down
59 changes: 52 additions & 7 deletions test/topology.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ test("buildTopology creates root-only sqlite authority topology", () => {
assert.equal(topology.profiles.rootAuthorityOverlay.capabilities.includes("sqlite-authority"), true);
assert.equal(topology.root.runtime.hasSqliteAuthority, true);
assert.equal(topology.root.runtime.profile, "root-with-authority-overlay");
assert.equal(topology.root.reefConfig.services.includes("registry"), true);
assert.equal(topology.root.reefConfig.services.includes("vm-tree"), true);
assert.equal(topology.root.reefConfig.services.includes("store"), true);
assert.equal(topology.root.reefConfig.services.includes("scheduled"), true);
assert.equal(topology.root.reefConfig.services.includes("usage"), true);
assert.equal(topology.root.reefConfig.services.includes("probe"), true);
assert.equal(topology.root.reefConfig.services.includes("commits"), true);
assert.equal(topology.lieutenant, null);
assert.deepEqual(topology.swarm, []);
Expand Down Expand Up @@ -73,6 +75,24 @@ test("buildBootstrapBundle can inline runtime secrets for remote bootstrap", ()
assert.match(bundle.scripts.root, /LLM_PROXY_KEY='sk-vers-secret'/);
});

test("buildBootstrapBundle prefers a dedicated secondary provider key when provided", () => {
const bundle = buildBootstrapBundle(
{
rootName: "reef-root",
},
{
rootUrl: "https://infra.vm.vers.sh:3000",
versApiKey: "vers-secret",
versAuthToken: "auth-secret",
llmProxyKey: "sk-vers-secret",
anthropicApiKey: "sk-ant-secret",
},
);

assert.match(bundle.scripts.root, /LLM_PROXY_KEY='sk-vers-secret'/);
assert.match(bundle.scripts.root, /ANTHROPIC_API_KEY='sk-ant-secret'/);
});

test("buildImageScript produces a secret-free image build script", () => {
const topology = buildTopology({ rootName: "reef-root" });
const script = buildImageScript(topology);
Expand All @@ -89,18 +109,43 @@ test("buildImageScript produces a secret-free image build script", () => {
});

test("buildRuntimeScript injects secrets and starts reef", () => {
const originalAnthropicKey = process.env.ANTHROPIC_API_KEY;
delete process.env.ANTHROPIC_API_KEY;
const topology = buildTopology({ rootName: "reef-root", rootVmId: "vm-1" });
try {
const script = buildRuntimeScript(topology.root, topology, {
versApiKey: "vers-key",
versAuthToken: "auth-token",
llmProxyKey: "sk-vers-proxy",
goldenCommitId: "golden-abc-123",
});
assert.match(script, /configuring runtime for reef-root/);
assert.match(script, /VERS_API_KEY='vers-key'/);
assert.match(script, /VERS_AUTH_TOKEN='auth-token'/);
assert.match(script, /LLM_PROXY_KEY='sk-vers-proxy'/);
assert.doesNotMatch(script, /ANTHROPIC_API_KEY=/);
assert.match(script, /VERS_GOLDEN_COMMIT_ID='golden-abc-123'/);
assert.match(script, /bun run src\/main\.ts/);
assert.match(script, /reef is healthy/);
} finally {
if (originalAnthropicKey === undefined) {
delete process.env.ANTHROPIC_API_KEY;
} else {
process.env.ANTHROPIC_API_KEY = originalAnthropicKey;
}
}
});

test("buildRuntimeScript prefers a dedicated secondary provider key", () => {
const topology = buildTopology({ rootName: "reef-root", rootVmId: "vm-1" });
const script = buildRuntimeScript(topology.root, topology, {
versApiKey: "vers-key",
versAuthToken: "auth-token",
llmProxyKey: "sk-vers-proxy",
anthropicApiKey: "sk-ant-secret",
goldenCommitId: "golden-abc-123",
});
assert.match(script, /configuring runtime for reef-root/);
assert.match(script, /VERS_API_KEY='vers-key'/);
assert.match(script, /VERS_AUTH_TOKEN='auth-token'/);

assert.match(script, /LLM_PROXY_KEY='sk-vers-proxy'/);
assert.match(script, /VERS_GOLDEN_COMMIT_ID='golden-abc-123'/);
assert.match(script, /bun run src\/main\.ts/);
assert.match(script, /reef is healthy/);
assert.match(script, /ANTHROPIC_API_KEY='sk-ant-secret'/);
});