fix: use getSpawnDir()/getConnectionPath() in all cloud providers (#1774)

Fixes #1769

All 8 cloud providers hard-coded `${process.env.HOME}/.spawn` for
connection data, bypassing the SPAWN_HOME env var support in history.ts.
Replaced all 16 occurrences with getSpawnDir() and getConnectionPath().

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
A 2026-02-22 19:27:21 -08:00 committed by GitHub
parent cc133343ad
commit 16c8a2b90b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 25 additions and 17 deletions

View file

@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "0.7.1",
"version": "0.7.2",
"type": "module",
"bin": {
"spawn": "cli.js"

View file

@ -21,6 +21,7 @@ import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../sh
import { SSH_BASE_OPTS, sleep, waitForSsh as sharedWaitForSsh } from "../shared/ssh";
import * as v from "valibot";
import { parseJsonWith } from "../shared/parse";
import { getSpawnDir, getConnectionPath } from "../history.js";
const DASHBOARD_URL = "https://lightsail.aws.amazon.com/";
@ -863,7 +864,7 @@ export async function waitForInstance(maxAttempts = 60): Promise<void> {
// ─── Connection Tracking ────────────────────────────────────────────────────
function saveVmConnection(ip: string, user: string, serverId: string, serverName: string, cloud: string): void {
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -884,7 +885,7 @@ function saveVmConnection(ip: string, user: string, serverId: string, serverName
}
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;

View file

@ -18,6 +18,7 @@ import type { CloudInitTier } from "../shared/agents";
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
import { parseJsonWith, parseJsonRaw } from "../shared/parse";
import * as v from "valibot";
import { getSpawnDir, getConnectionPath } from "../history.js";
const DAYTONA_API_BASE = "https://app.daytona.io/api";
const DAYTONA_DASHBOARD_URL = "https://app.daytona.io/";
@ -220,7 +221,7 @@ function saveVmConnection(
cloud: string,
launchCmd?: string,
): void {
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -244,7 +245,7 @@ function saveVmConnection(
}
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;

View file

@ -20,6 +20,7 @@ import type { CloudInitTier } from "../shared/agents";
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
import { parseJsonWith } from "../shared/parse";
import { SSH_BASE_OPTS, sleep, waitForSsh as sharedWaitForSsh } from "../shared/ssh";
import { getSpawnDir, getConnectionPath } from "../history.js";
const DO_API_BASE = "https://api.digitalocean.com/v2";
const DO_DASHBOARD_URL = "https://cloud.digitalocean.com/droplets";
@ -696,7 +697,7 @@ function saveVmConnection(
cloud: string,
launchCmd?: string,
): void {
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -720,7 +721,7 @@ function saveVmConnection(
}
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;

View file

@ -20,6 +20,7 @@ import type { CloudInitTier } from "../shared/agents";
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
import * as v from "valibot";
import { parseJsonWith, parseJsonRaw } from "../shared/parse";
import { getSpawnDir, getConnectionPath } from "../history.js";
const FLY_API_BASE = "https://api.machines.dev/v1";
const FLY_DASHBOARD_URL = "https://fly.io/dashboard";
@ -325,7 +326,7 @@ export function saveVmConnection(
cloud: string,
launchCmd?: string,
): void {
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -350,7 +351,7 @@ export function saveVmConnection(
/** Append launch_cmd to the last-connection.json file */
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;

View file

@ -18,6 +18,7 @@ import {
import type { CloudInitTier } from "../shared/agents";
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
import { SSH_BASE_OPTS, sleep, waitForSsh as sharedWaitForSsh } from "../shared/ssh";
import { getSpawnDir, getConnectionPath } from "../history.js";
const DASHBOARD_URL = "https://console.cloud.google.com/compute/instances";
@ -750,7 +751,7 @@ export async function createInstance(
logInfo(`Instance created: IP=${gcpServerIp}`);
// Save connection info
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -1007,7 +1008,7 @@ export async function destroyInstance(name?: string): Promise<void> {
// ─── Connection Tracking ────────────────────────────────────────────────────
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;

View file

@ -20,6 +20,7 @@ import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../sh
import { SSH_BASE_OPTS, sleep, waitForSsh as sharedWaitForSsh } from "../shared/ssh";
import * as v from "valibot";
import { parseJsonWith } from "../shared/parse";
import { getSpawnDir, getConnectionPath } from "../history.js";
const HETZNER_API_BASE = "https://api.hetzner.cloud/v1";
const HETZNER_DASHBOARD_URL = "https://console.hetzner.cloud/";
@ -339,7 +340,7 @@ export function saveVmConnection(
cloud: string,
launchCmd?: string,
): void {
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -363,7 +364,7 @@ export function saveVmConnection(
}
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;

View file

@ -3,6 +3,7 @@
import { copyFileSync, mkdirSync, readFileSync } from "node:fs";
import { dirname } from "node:path";
import { spawn } from "node:child_process";
import { getSpawnDir, getConnectionPath } from "../history.js";
// ─── Execution ───────────────────────────────────────────────────────────────
@ -82,7 +83,7 @@ export async function interactiveSession(cmd: string): Promise<number> {
// ─── Connection Tracking ─────────────────────────────────────────────────────
export function saveLocalConnection(): void {
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -111,7 +112,7 @@ export function saveLocalConnection(): void {
/** Save launch command to the last-connection.json file. */
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;

View file

@ -13,6 +13,7 @@ import {
defaultSpawnName,
} from "../shared/ui";
import { sleep } from "../shared/ssh";
import { getSpawnDir, getConnectionPath } from "../history.js";
// ─── Configurable Constants ──────────────────────────────────────────────────
@ -426,7 +427,7 @@ export async function setupShellEnvironment(): Promise<void> {
// ─── Connection Tracking ─────────────────────────────────────────────────────
export function saveVmConnection(): void {
const dir = `${process.env.HOME}/.spawn`;
const dir = getSpawnDir();
mkdirSync(dir, {
recursive: true,
});
@ -440,7 +441,7 @@ export function saveVmConnection(): void {
}
export function saveLaunchCmd(launchCmd: string): void {
const connFile = `${process.env.HOME}/.spawn/last-connection.json`;
const connFile = getConnectionPath();
try {
const data = JSON.parse(readFileSync(connFile, "utf-8"));
data.launch_cmd = launchCmd;