mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-19 08:01:17 +00:00
fix: eliminate duplicate name prompts, use cloud-native terminology (#1755)
* fix: eliminate duplicate name prompts, use cloud-native terminology Users were prompted for a name up to 4 times per spawn. Now each cloud has a single prompt using its native resource terminology (e.g. "Hetzner server name", "Fly machine name") and getServerName() returns the already-collected name silently instead of re-prompting. Closes #1753 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: never use bare "spawn" as default name, always append random suffix Extract defaultSpawnName() helper to shared/ui.ts that generates "spawn-xxxx" with a random suffix. All cloud modules now use it instead of bare "spawn" for every fallback path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: lab <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d1b6a20535
commit
7c37a793de
9 changed files with 72 additions and 216 deletions
|
|
@ -13,6 +13,7 @@ import {
|
|||
validateServerName,
|
||||
validateRegionName,
|
||||
toKebabCase,
|
||||
defaultSpawnName,
|
||||
} from "../shared/ui";
|
||||
import type { CloudInitTier } from "../shared/agents";
|
||||
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
|
||||
|
|
@ -805,47 +806,25 @@ export async function getServerName(): Promise<string> {
|
|||
|
||||
const kebab = process.env.SPAWN_NAME_KEBAB
|
||||
|| (process.env.SPAWN_NAME ? toKebabCase(process.env.SPAWN_NAME) : "");
|
||||
const defaultName = kebab || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
const answer = await prompt(`Enter instance name [${defaultName}]: `);
|
||||
const name = answer || defaultName;
|
||||
|
||||
if (!validateServerName(name)) {
|
||||
logError(`Invalid instance name: '${name}'`);
|
||||
throw new Error("Invalid server name");
|
||||
}
|
||||
return name;
|
||||
return kebab || defaultSpawnName();
|
||||
}
|
||||
|
||||
export async function promptSpawnName(): Promise<void> {
|
||||
if (process.env.SPAWN_NAME_KEBAB) return;
|
||||
|
||||
let displayName: string;
|
||||
let kebab: string;
|
||||
if (process.env.SPAWN_NAME) {
|
||||
displayName = process.env.SPAWN_NAME;
|
||||
logInfo(`Spawn name: ${displayName}`);
|
||||
kebab = toKebabCase(process.env.SPAWN_NAME) || defaultSpawnName();
|
||||
} else if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
displayName = "spawn";
|
||||
kebab = defaultSpawnName();
|
||||
} else {
|
||||
const fallback = defaultSpawnName();
|
||||
process.stderr.write("\n");
|
||||
displayName = await prompt('Spawn name (e.g. "My Dev Box"): ');
|
||||
if (!displayName) displayName = "spawn";
|
||||
const answer = await prompt(`AWS instance name [${fallback}]: `);
|
||||
kebab = toKebabCase(answer || fallback) || defaultSpawnName();
|
||||
}
|
||||
|
||||
let kebab = toKebabCase(displayName) || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
const confirmed = await prompt(`Resource name [${kebab}]: `);
|
||||
if (confirmed) {
|
||||
kebab = toKebabCase(confirmed) || "spawn";
|
||||
}
|
||||
}
|
||||
|
||||
process.env.SPAWN_NAME_DISPLAY = displayName;
|
||||
process.env.SPAWN_NAME_DISPLAY = kebab;
|
||||
process.env.SPAWN_NAME_KEBAB = kebab;
|
||||
logInfo(`Using resource name: ${kebab}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
jsonEscape,
|
||||
validateServerName,
|
||||
toKebabCase,
|
||||
defaultSpawnName,
|
||||
} from "../shared/ui";
|
||||
import type { CloudInitTier } from "../shared/agents";
|
||||
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
|
||||
|
|
@ -519,47 +520,25 @@ export async function getServerName(): Promise<string> {
|
|||
|
||||
const kebab = process.env.SPAWN_NAME_KEBAB
|
||||
|| (process.env.SPAWN_NAME ? toKebabCase(process.env.SPAWN_NAME) : "");
|
||||
const defaultName = kebab || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
const answer = await prompt(`Enter sandbox name [${defaultName}]: `);
|
||||
const name = answer || defaultName;
|
||||
|
||||
if (!validateServerName(name)) {
|
||||
logError(`Invalid sandbox name: '${name}'`);
|
||||
throw new Error("Invalid server name");
|
||||
}
|
||||
return name;
|
||||
return kebab || defaultSpawnName();
|
||||
}
|
||||
|
||||
export async function promptSpawnName(): Promise<void> {
|
||||
if (process.env.SPAWN_NAME_KEBAB) return;
|
||||
|
||||
let displayName: string;
|
||||
let kebab: string;
|
||||
if (process.env.SPAWN_NAME) {
|
||||
displayName = process.env.SPAWN_NAME;
|
||||
logInfo(`Spawn name: ${displayName}`);
|
||||
kebab = toKebabCase(process.env.SPAWN_NAME) || defaultSpawnName();
|
||||
} else if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
displayName = "spawn";
|
||||
kebab = defaultSpawnName();
|
||||
} else {
|
||||
const fallback = defaultSpawnName();
|
||||
process.stderr.write("\n");
|
||||
displayName = await prompt('Spawn name (e.g. "My Dev Box"): ');
|
||||
if (!displayName) displayName = "spawn";
|
||||
const answer = await prompt(`Daytona workspace name [${fallback}]: `);
|
||||
kebab = toKebabCase(answer || fallback) || defaultSpawnName();
|
||||
}
|
||||
|
||||
let kebab = toKebabCase(displayName) || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
const confirmed = await prompt(`Resource name [${kebab}]: `);
|
||||
if (confirmed) {
|
||||
kebab = toKebabCase(confirmed) || "spawn";
|
||||
}
|
||||
}
|
||||
|
||||
process.env.SPAWN_NAME_DISPLAY = displayName;
|
||||
process.env.SPAWN_NAME_DISPLAY = kebab;
|
||||
process.env.SPAWN_NAME_KEBAB = kebab;
|
||||
logInfo(`Using resource name: ${kebab}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
validateServerName,
|
||||
validateRegionName,
|
||||
toKebabCase,
|
||||
defaultSpawnName,
|
||||
} from "../shared/ui";
|
||||
import type { CloudInitTier } from "../shared/agents";
|
||||
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
|
||||
|
|
@ -945,47 +946,25 @@ export async function getServerName(): Promise<string> {
|
|||
|
||||
const kebab = process.env.SPAWN_NAME_KEBAB
|
||||
|| (process.env.SPAWN_NAME ? toKebabCase(process.env.SPAWN_NAME) : "");
|
||||
const defaultName = kebab || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
const answer = await prompt(`Enter droplet name [${defaultName}]: `);
|
||||
const name = answer || defaultName;
|
||||
|
||||
if (!validateServerName(name)) {
|
||||
logError(`Invalid droplet name: '${name}'`);
|
||||
throw new Error("Invalid server name");
|
||||
}
|
||||
return name;
|
||||
return kebab || defaultSpawnName();
|
||||
}
|
||||
|
||||
export async function promptSpawnName(): Promise<void> {
|
||||
if (process.env.SPAWN_NAME_KEBAB) return;
|
||||
|
||||
let displayName: string;
|
||||
let kebab: string;
|
||||
if (process.env.SPAWN_NAME) {
|
||||
displayName = process.env.SPAWN_NAME;
|
||||
logInfo(`Spawn name: ${displayName}`);
|
||||
kebab = toKebabCase(process.env.SPAWN_NAME) || defaultSpawnName();
|
||||
} else if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
displayName = "spawn";
|
||||
kebab = defaultSpawnName();
|
||||
} else {
|
||||
const fallback = defaultSpawnName();
|
||||
process.stderr.write("\n");
|
||||
displayName = await prompt('Spawn name (e.g. "My Dev Box"): ');
|
||||
if (!displayName) displayName = "spawn";
|
||||
const answer = await prompt(`DigitalOcean droplet name [${fallback}]: `);
|
||||
kebab = toKebabCase(answer || fallback) || defaultSpawnName();
|
||||
}
|
||||
|
||||
let kebab = toKebabCase(displayName) || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
const confirmed = await prompt(`Resource name [${kebab}]: `);
|
||||
if (confirmed) {
|
||||
kebab = toKebabCase(confirmed) || "spawn";
|
||||
}
|
||||
}
|
||||
|
||||
process.env.SPAWN_NAME_DISPLAY = displayName;
|
||||
process.env.SPAWN_NAME_DISPLAY = kebab;
|
||||
process.env.SPAWN_NAME_KEBAB = kebab;
|
||||
logInfo(`Using resource name: ${kebab}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
validateServerName,
|
||||
validateRegionName,
|
||||
toKebabCase,
|
||||
defaultSpawnName,
|
||||
} from "../shared/ui";
|
||||
import type { CloudInitTier } from "../shared/agents";
|
||||
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
|
||||
|
|
@ -908,51 +909,27 @@ export async function getServerName(): Promise<string> {
|
|||
return name;
|
||||
}
|
||||
|
||||
// Derive from spawn name
|
||||
const kebab = process.env.SPAWN_NAME_KEBAB
|
||||
|| (process.env.SPAWN_NAME ? toKebabCase(process.env.SPAWN_NAME) : "");
|
||||
const defaultName = kebab || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
const answer = await prompt(`Enter app name [${defaultName}]: `);
|
||||
const name = answer || defaultName;
|
||||
|
||||
if (!validateServerName(name)) {
|
||||
logError(`Invalid app name: '${name}'`);
|
||||
throw new Error("Invalid server name");
|
||||
}
|
||||
return name;
|
||||
return kebab || defaultSpawnName();
|
||||
}
|
||||
|
||||
/** Prompt for a spawn display name, derive kebab-case resource name. */
|
||||
export async function promptSpawnName(): Promise<void> {
|
||||
if (process.env.SPAWN_NAME_KEBAB) return;
|
||||
|
||||
let displayName: string;
|
||||
let kebab: string;
|
||||
if (process.env.SPAWN_NAME) {
|
||||
displayName = process.env.SPAWN_NAME;
|
||||
logInfo(`Spawn name: ${displayName}`);
|
||||
kebab = toKebabCase(process.env.SPAWN_NAME) || defaultSpawnName();
|
||||
} else if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
displayName = "spawn";
|
||||
kebab = defaultSpawnName();
|
||||
} else {
|
||||
const fallback = defaultSpawnName();
|
||||
process.stderr.write("\n");
|
||||
displayName = await prompt('Spawn name (e.g. "My Dev Box"): ');
|
||||
if (!displayName) displayName = "spawn";
|
||||
const answer = await prompt(`Fly machine name [${fallback}]: `);
|
||||
kebab = toKebabCase(answer || fallback) || defaultSpawnName();
|
||||
}
|
||||
|
||||
let kebab = toKebabCase(displayName) || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
const confirmed = await prompt(`Resource name [${kebab}]: `);
|
||||
if (confirmed) {
|
||||
kebab = toKebabCase(confirmed) || "spawn";
|
||||
}
|
||||
}
|
||||
|
||||
process.env.SPAWN_NAME_DISPLAY = displayName;
|
||||
process.env.SPAWN_NAME_DISPLAY = kebab;
|
||||
process.env.SPAWN_NAME_KEBAB = kebab;
|
||||
logInfo(`Using resource name: ${kebab}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
jsonEscape,
|
||||
validateServerName,
|
||||
toKebabCase,
|
||||
defaultSpawnName,
|
||||
} from "../shared/ui";
|
||||
import type { CloudInitTier } from "../shared/agents";
|
||||
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
|
||||
|
|
@ -379,48 +380,25 @@ export async function getServerName(): Promise<string> {
|
|||
|
||||
const kebab = process.env.SPAWN_NAME_KEBAB
|
||||
|| (process.env.SPAWN_NAME ? toKebabCase(process.env.SPAWN_NAME) : "");
|
||||
const defaultName = kebab || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
const answer = await prompt(`Enter instance name [${defaultName}]: `);
|
||||
const name = answer || defaultName;
|
||||
|
||||
if (!validateServerName(name)) {
|
||||
logError(`Invalid instance name: '${name}'`);
|
||||
throw new Error("Invalid server name");
|
||||
}
|
||||
return name;
|
||||
return kebab || defaultSpawnName();
|
||||
}
|
||||
|
||||
/** Prompt for a spawn display name, derive kebab-case resource name. */
|
||||
export async function promptSpawnName(): Promise<void> {
|
||||
if (process.env.SPAWN_NAME_KEBAB) return;
|
||||
|
||||
let displayName: string;
|
||||
let kebab: string;
|
||||
if (process.env.SPAWN_NAME) {
|
||||
displayName = process.env.SPAWN_NAME;
|
||||
logInfo(`Spawn name: ${displayName}`);
|
||||
kebab = toKebabCase(process.env.SPAWN_NAME) || defaultSpawnName();
|
||||
} else if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
displayName = "spawn";
|
||||
kebab = defaultSpawnName();
|
||||
} else {
|
||||
const fallback = defaultSpawnName();
|
||||
process.stderr.write("\n");
|
||||
displayName = await prompt('Spawn name (e.g. "My Dev Box"): ');
|
||||
if (!displayName) displayName = "spawn";
|
||||
const answer = await prompt(`GCP instance name [${fallback}]: `);
|
||||
kebab = toKebabCase(answer || fallback) || defaultSpawnName();
|
||||
}
|
||||
|
||||
let kebab = toKebabCase(displayName) || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
const confirmed = await prompt(`Resource name [${kebab}]: `);
|
||||
if (confirmed) {
|
||||
kebab = toKebabCase(confirmed) || "spawn";
|
||||
}
|
||||
}
|
||||
|
||||
process.env.SPAWN_NAME_DISPLAY = displayName;
|
||||
process.env.SPAWN_NAME_DISPLAY = kebab;
|
||||
process.env.SPAWN_NAME_KEBAB = kebab;
|
||||
logInfo(`Using resource name: ${kebab}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
validateServerName,
|
||||
validateRegionName,
|
||||
toKebabCase,
|
||||
defaultSpawnName,
|
||||
} from "../shared/ui";
|
||||
import type { CloudInitTier } from "../shared/agents";
|
||||
import { getPackagesForTier, needsNode, needsBun, NODE_INSTALL_CMD } from "../shared/cloud-init";
|
||||
|
|
@ -576,47 +577,25 @@ export async function getServerName(): Promise<string> {
|
|||
|
||||
const kebab = process.env.SPAWN_NAME_KEBAB
|
||||
|| (process.env.SPAWN_NAME ? toKebabCase(process.env.SPAWN_NAME) : "");
|
||||
const defaultName = kebab || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
const answer = await prompt(`Enter server name [${defaultName}]: `);
|
||||
const name = answer || defaultName;
|
||||
|
||||
if (!validateServerName(name)) {
|
||||
logError(`Invalid server name: '${name}'`);
|
||||
throw new Error("Invalid server name");
|
||||
}
|
||||
return name;
|
||||
return kebab || defaultSpawnName();
|
||||
}
|
||||
|
||||
export async function promptSpawnName(): Promise<void> {
|
||||
if (process.env.SPAWN_NAME_KEBAB) return;
|
||||
|
||||
let displayName: string;
|
||||
let kebab: string;
|
||||
if (process.env.SPAWN_NAME) {
|
||||
displayName = process.env.SPAWN_NAME;
|
||||
logInfo(`Spawn name: ${displayName}`);
|
||||
kebab = toKebabCase(process.env.SPAWN_NAME) || defaultSpawnName();
|
||||
} else if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
displayName = "spawn";
|
||||
kebab = defaultSpawnName();
|
||||
} else {
|
||||
const fallback = defaultSpawnName();
|
||||
process.stderr.write("\n");
|
||||
displayName = await prompt('Spawn name (e.g. "My Dev Box"): ');
|
||||
if (!displayName) displayName = "spawn";
|
||||
const answer = await prompt(`Hetzner server name [${fallback}]: `);
|
||||
kebab = toKebabCase(answer || fallback) || defaultSpawnName();
|
||||
}
|
||||
|
||||
let kebab = toKebabCase(displayName) || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
const confirmed = await prompt(`Resource name [${kebab}]: `);
|
||||
if (confirmed) {
|
||||
kebab = toKebabCase(confirmed) || "spawn";
|
||||
}
|
||||
}
|
||||
|
||||
process.env.SPAWN_NAME_DISPLAY = displayName;
|
||||
process.env.SPAWN_NAME_DISPLAY = kebab;
|
||||
process.env.SPAWN_NAME_KEBAB = kebab;
|
||||
logInfo(`Using resource name: ${kebab}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,3 +141,9 @@ export function toKebabCase(name: string): string {
|
|||
.replace(/-{2,}/g, "-")
|
||||
.replace(/^-|-$/g, "");
|
||||
}
|
||||
|
||||
/** Generate a default spawn name with random suffix (e.g. "spawn-a1b2"). */
|
||||
export function defaultSpawnName(): string {
|
||||
const suffix = Math.random().toString(36).slice(2, 6);
|
||||
return `spawn-${suffix}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
ensureSpriteCli,
|
||||
ensureSpriteAuthenticated,
|
||||
promptSpawnName,
|
||||
getSpriteName,
|
||||
getServerName,
|
||||
createSprite,
|
||||
verifySpriteConnectivity,
|
||||
setupShellEnvironment,
|
||||
|
|
@ -45,7 +45,7 @@ async function main() {
|
|||
await setupShellEnvironment();
|
||||
saveVmConnection();
|
||||
},
|
||||
getServerName: getSpriteName,
|
||||
getServerName,
|
||||
async waitForReady() {},
|
||||
interactiveSession,
|
||||
saveLaunchCmd,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
prompt,
|
||||
validateServerName,
|
||||
toKebabCase,
|
||||
defaultSpawnName,
|
||||
} from "../shared/ui";
|
||||
|
||||
// ─── Configurable Constants ──────────────────────────────────────────────────
|
||||
|
|
@ -193,33 +194,24 @@ function orgFlags(): string[] {
|
|||
export async function promptSpawnName(): Promise<void> {
|
||||
if (process.env.SPAWN_NAME_KEBAB) return;
|
||||
|
||||
let displayName: string;
|
||||
let kebab: string;
|
||||
if (process.env.SPAWN_NAME) {
|
||||
displayName = process.env.SPAWN_NAME;
|
||||
logInfo(`Spawn name: ${displayName}`);
|
||||
kebab = toKebabCase(process.env.SPAWN_NAME) || defaultSpawnName();
|
||||
} else if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
displayName = "spawn";
|
||||
kebab = defaultSpawnName();
|
||||
} else {
|
||||
const fallback = defaultSpawnName();
|
||||
process.stderr.write("\n");
|
||||
displayName = await prompt('Spawn name (e.g. "My Dev Box"): ');
|
||||
if (!displayName) displayName = "spawn";
|
||||
const answer = await prompt(`Sprite name [${fallback}]: `);
|
||||
kebab = toKebabCase(answer || fallback) || defaultSpawnName();
|
||||
}
|
||||
|
||||
let kebab = toKebabCase(displayName) || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
const confirmed = await prompt(`Resource name [${kebab}]: `);
|
||||
if (confirmed) {
|
||||
kebab = toKebabCase(confirmed) || "spawn";
|
||||
}
|
||||
}
|
||||
|
||||
process.env.SPAWN_NAME_DISPLAY = displayName;
|
||||
process.env.SPAWN_NAME_DISPLAY = kebab;
|
||||
process.env.SPAWN_NAME_KEBAB = kebab;
|
||||
logInfo(`Using resource name: ${kebab}`);
|
||||
}
|
||||
|
||||
export async function getSpriteName(): Promise<string> {
|
||||
export async function getServerName(): Promise<string> {
|
||||
if (process.env.SPRITE_NAME) {
|
||||
const name = process.env.SPRITE_NAME;
|
||||
if (!validateServerName(name)) {
|
||||
|
|
@ -232,20 +224,7 @@ export async function getSpriteName(): Promise<string> {
|
|||
|
||||
const kebab = process.env.SPAWN_NAME_KEBAB
|
||||
|| (process.env.SPAWN_NAME ? toKebabCase(process.env.SPAWN_NAME) : "");
|
||||
const defaultName = kebab || "spawn";
|
||||
|
||||
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
const answer = await prompt(`Enter sprite name [${defaultName}]: `);
|
||||
const name = answer || defaultName;
|
||||
|
||||
if (!validateServerName(name)) {
|
||||
logError(`Invalid sprite name: '${name}'`);
|
||||
throw new Error("Invalid server name");
|
||||
}
|
||||
return name;
|
||||
return kebab || defaultSpawnName();
|
||||
}
|
||||
|
||||
// ─── Provisioning ────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue