From 59a2b29335cb8acb48fa277ecb71729d47e7ddb1 Mon Sep 17 00:00:00 2001 From: Samuel Selleck Date: Fri, 13 Feb 2026 14:37:10 -0800 Subject: [PATCH 1/4] accept v2 field names for ssh and image endpoints --- src/lib/nodes/ssh.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/nodes/ssh.ts b/src/lib/nodes/ssh.ts index 773fe53..68909ad 100644 --- a/src/lib/nodes/ssh.ts +++ b/src/lib/nodes/ssh.ts @@ -147,9 +147,9 @@ Examples: return; } - const sshHostname = data.ssh_hostname; - const sshPort = data.ssh_port; - const sshHostKeys = data.ssh_host_keys || []; + const sshHostname = data.hostname ?? data.ssh_hostname; + const sshPort = data.port ?? data.ssh_port; + const sshHostKeys = data.host_keys ?? data.ssh_host_keys ?? []; let sshDestination = sshHostname; if (sshUsername !== undefined) { @@ -168,7 +168,7 @@ Examples: knownHostsCommand = knownHostsCommand.concat([ hostKeyAlias, sshHostKey.key_type, - sshHostKey.base64_encoded_key, + sshHostKey.key ?? sshHostKey.base64_encoded_key, ]); } // Escape all characters for proper pass through From c5c6b3db8d560441d7056a6f854929b308ff4941 Mon Sep 17 00:00:00 2001 From: Daniel Tao Date: Tue, 17 Feb 2026 13:56:59 -0800 Subject: [PATCH 2/4] feat: parse `v2/ssh` fields correctly and coerce `v0/ssh` response to `v2` Co-Authored-By: Claude Opus 4.6 --- src/lib/nodes/ssh.ts | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/lib/nodes/ssh.ts b/src/lib/nodes/ssh.ts index 68909ad..aeeb356 100644 --- a/src/lib/nodes/ssh.ts +++ b/src/lib/nodes/ssh.ts @@ -13,10 +13,16 @@ import { logSessionTokenExpiredAndQuit, } from "../../helpers/errors.ts"; import { handleNodesError, nodesClient } from "../../nodesClient.ts"; -import type { components } from "../../schema.ts"; import { jsonOption } from "./utils.ts"; -type SshInfo = components["schemas"]["vmorch_GetSshResponse"]; +// Canonical SSH info shape (v2 NodeSshInfo format) +type SshInfo = { + hostname: string; + port: number; + host_keys: { key_type: string; key: string }[]; + last_successful_key_update: number | null; + last_attempted_key_update: number | null; +}; const ssh = new Command("ssh") .description(`SSH into a VM on a node. @@ -88,7 +94,16 @@ Examples: ); if (v2Response.ok) { - data = await v2Response.json(); + const v2Data = await v2Response.json(); + data = { + hostname: v2Data.hostname, + port: v2Data.port, + host_keys: v2Data.host_keys ?? [], + last_successful_key_update: + v2Data.last_successful_key_update ?? null, + last_attempted_key_update: + v2Data.last_attempted_key_update ?? null, + }; hostKeyAlias = `${nodeOrVmId}.v2.nodes.sfcompute.dev`; } } @@ -136,7 +151,19 @@ Examples: process.exit(1); } - data = sshData; + // Coerce v0 response to v2 shape + data = { + hostname: sshData.ssh_hostname, + port: sshData.ssh_port, + host_keys: (sshData.ssh_host_keys ?? []).map((k) => ({ + key_type: k.key_type, + key: k.base64_encoded_key, + })), + last_successful_key_update: + sshData.last_successful_key_update ?? null, + last_attempted_key_update: + sshData.last_attempted_key_update ?? null, + }; hostKeyAlias = `${vmId}.vms.sfcompute.dev`; } @@ -147,9 +174,9 @@ Examples: return; } - const sshHostname = data.hostname ?? data.ssh_hostname; - const sshPort = data.port ?? data.ssh_port; - const sshHostKeys = data.host_keys ?? data.ssh_host_keys ?? []; + const sshHostname = data.hostname; + const sshPort = data.port; + const sshHostKeys = data.host_keys; let sshDestination = sshHostname; if (sshUsername !== undefined) { @@ -168,7 +195,7 @@ Examples: knownHostsCommand = knownHostsCommand.concat([ hostKeyAlias, sshHostKey.key_type, - sshHostKey.key ?? sshHostKey.base64_encoded_key, + sshHostKey.key, ]); } // Escape all characters for proper pass through From 228ce23e498cd08c18d0ab7eeea3878c13c75a3a Mon Sep 17 00:00:00 2001 From: Daniel Tao Date: Tue, 17 Feb 2026 13:58:34 -0800 Subject: [PATCH 3/4] perf: avoid unnecessary object construction Co-Authored-By: Claude Opus 4.6 --- src/lib/nodes/ssh.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/lib/nodes/ssh.ts b/src/lib/nodes/ssh.ts index aeeb356..c1c330b 100644 --- a/src/lib/nodes/ssh.ts +++ b/src/lib/nodes/ssh.ts @@ -94,16 +94,7 @@ Examples: ); if (v2Response.ok) { - const v2Data = await v2Response.json(); - data = { - hostname: v2Data.hostname, - port: v2Data.port, - host_keys: v2Data.host_keys ?? [], - last_successful_key_update: - v2Data.last_successful_key_update ?? null, - last_attempted_key_update: - v2Data.last_attempted_key_update ?? null, - }; + data = (await v2Response.json()) as SshInfo; hostKeyAlias = `${nodeOrVmId}.v2.nodes.sfcompute.dev`; } } From 74d73bbc40f46be6d17deea7bc144f0e5e778965 Mon Sep 17 00:00:00 2001 From: Daniel Tao Date: Tue, 17 Feb 2026 13:59:47 -0800 Subject: [PATCH 4/4] style: run biome Co-Authored-By: Claude Opus 4.6 --- src/lib/nodes/ssh.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/nodes/ssh.ts b/src/lib/nodes/ssh.ts index c1c330b..957d99d 100644 --- a/src/lib/nodes/ssh.ts +++ b/src/lib/nodes/ssh.ts @@ -152,8 +152,7 @@ Examples: })), last_successful_key_update: sshData.last_successful_key_update ?? null, - last_attempted_key_update: - sshData.last_attempted_key_update ?? null, + last_attempted_key_update: sshData.last_attempted_key_update ?? null, }; hostKeyAlias = `${vmId}.vms.sfcompute.dev`; }