Files
orca/src/main/ssh/ssh-relay-opencode-runtime-commands.ts
T
OrcaWinandm4air da6d483ab9 fix(vault): read OpenCode SQLite inside WSL and SSH hosts (#23128)
* fix(vault): read OpenCode SQLite on WSL and SSH execution hosts

* fix(vault): bound host setup and preserve cancellation across readers

* fix(vault): keep WSL discovery visible and isolate probe tests

* fix: retry local Vault runtime downloads without reserving remote stages

Preserve verified remote cache reuse and latch only unresolved host work.
Update WSL source-guard and remote dedup test integration.

* fix(queue): discard aborted requests before respawn

* fix(vault): preserve host paths and recover setup after reconnect

* fix(ssh): fence every runtime platform probe across reconnects

* fix(vault): reject setup results from superseded SSH connections

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 03:59:38 -07:00

152 lines
6.5 KiB
TypeScript

import { shellEscape } from './ssh-connection-utils'
import { posix, win32 } from 'node:path'
import { powerShellCommand, powerShellLiteral, powerShellNativeArg } from './ssh-remote-powershell'
import { isWindowsRemoteHost, type RemoteHostPlatform } from './ssh-remote-platform'
export const OPENCODE_RUNTIME_RESULT = 'ORCA_VAULT_SQLITE:'
function nodeCommand(
host: RemoteHostPlatform,
nodePath: string,
script: string,
args: string[]
): string {
if (isWindowsRemoteHost(host)) {
return powerShellCommand(
`& ${powerShellLiteral(nodePath)} -e ${powerShellNativeArg(script)} -- ${args.map(powerShellNativeArg).join(' ')}; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }`
)
}
return `${shellEscape(nodePath)} -e ${shellEscape(script)} -- ${args.map(shellEscape).join(' ')}`
}
const SEND = `const send=(value)=>console.log(${JSON.stringify(OPENCODE_RUNTIME_RESULT)}+JSON.stringify(value));`
const HASH = `const fs=require('node:fs');const fsp=fs.promises;const path=require('node:path');
async function hash(file){try{const digest=require('node:crypto').createHash('sha256');for await(const chunk of fs.createReadStream(file))digest.update(chunk);return digest.digest('hex')}catch(error){if(error.code==='ENOENT')return null;throw error}}
`
export function probeOpenCodeNodeSqliteCommand(
host: RemoteHostPlatform,
nodePath: string,
homeDirectory: string
): string {
return nodeCommand(
host,
nodePath,
`${SEND}
const fs=require('node:fs/promises');const path=require('node:path');
(async()=>{const data=path.join(process.env.XDG_DATA_HOME?.trim()||path.join(process.argv[1],'.local','share'),'opencode');
const override=process.env.OPENCODE_DB?.trim();let present=false;
try{if(override&&override!==':memory:'){present=(await fs.stat(path.isAbsolute(override)?override:path.join(data,override))).isFile()}
else if(!override){const directory=await fs.opendir(data);for await(const entry of directory){if(entry.isFile()&&/^opencode(?:-[A-Za-z0-9_.-]+)?\\.db$/.test(entry.name)){present=true;break}}}}
catch(error){if(error.code!=='ENOENT'&&error.code!=='ENOTDIR')throw error}
if(!present){send({status:'not-needed'});return}
let db;try{db=new(require('node:sqlite').DatabaseSync)(':memory:');
if(db.prepare('SELECT 1 AS ready').get().ready!==1)throw Error('SQLite read failed');
send({status:'ready',executable:process.execPath})}catch{send({status:'unsupported'})}finally{if(db)db.close()}
})().catch(error=>{console.error(error.message);process.exitCode=1})`,
[homeDirectory]
)
}
export function probeOpenCodeRuntimeCacheCommand(args: {
host: RemoteHostPlatform
nodePath: string
executable: string
expectedHash: string
reference: string
}): string {
return nodeCommand(
args.host,
args.nodePath,
`${HASH}${SEND}
(async()=>{const [executable,expected,reference]=process.argv.slice(1);
let candidate=executable;let digest=candidate?await hash(candidate):null;
if(candidate&&digest!==expected){try{const ref=JSON.parse(await fsp.readFile(reference,'utf8'));
const relative=path.relative(path.dirname(executable),ref.executable);
if(ref.protocol===1&&relative&&!relative.startsWith('..'+path.sep)&&relative!=='..'&&!path.isAbsolute(relative)){candidate=ref.executable;digest=await hash(candidate)}}catch{}}
if(candidate&&digest===expected){if(process.platform!=='win32')await fsp.chmod(candidate,448);send({status:'ready',executable:candidate});return}
send({status:'missing'})})().catch(error=>{console.error(error.message);process.exitCode=1})`,
[args.executable, args.expectedHash, args.reference]
)
}
export function promoteOpenCodeRuntimeCommand(args: {
host: RemoteHostPlatform
nodePath: string
stagedBinary: string
executable: string
expectedHash: string
repairToken: string
}): string {
return nodeCommand(
args.host,
args.nodePath,
`${HASH}${SEND}
(async()=>{const [source,destination,expected,token]=process.argv.slice(1);
if(await hash(source)!==expected)throw Error('Uploaded SQLite runtime checksum mismatch');
let executable=destination;const existing=await hash(destination);
if(existing!==expected){
if(existing!==null)executable=path.join(path.dirname(destination),'repair-'+token,path.basename(destination));
await fsp.mkdir(path.dirname(executable),{recursive:true,mode:448});
if(process.platform!=='win32')await fsp.chmod(source,448);
try{await fsp.link(source,executable)}catch(error){if(await hash(executable)!==expected){
if(!['EPERM','EOPNOTSUPP','ENOTSUP','ENOSYS','EXDEV'].includes(error.code))throw error;
executable=path.join(path.dirname(destination),'repair-'+token,path.basename(destination));
await fsp.mkdir(path.dirname(executable),{recursive:true,mode:448});await fsp.rename(source,executable)
}}
}
send({status:'ready',executable})})().catch(error=>{console.error(error.message);process.exitCode=1})`,
[args.stagedBinary, args.executable, args.expectedHash, args.repairToken]
)
}
export function publishOpenCodeRuntimeReferenceCommand(args: {
host: RemoteHostPlatform
nodePath: string
stagedReference: string
reference: string
token: string
}): string {
return nodeCommand(
args.host,
args.nodePath,
`${SEND}
const fs=require('node:fs/promises');const path=require('node:path');
(async()=>{const [source,destination,token]=process.argv.slice(1);const temporary=destination+'.upload-'+token;
try{await fs.copyFile(source,temporary,require('node:fs').constants.COPYFILE_EXCL);
await fs.rename(temporary,destination);send({status:'published'})}
finally{await fs.rm(temporary,{force:true})}})().catch(error=>{console.error(error.message);process.exitCode=1})`,
[args.stagedReference, args.reference, args.token]
)
}
export function parseOpenCodeRuntimeResult(output: string): {
status: string
executable?: string
} {
const line = output.split(/\r?\n/).findLast((entry) => entry.startsWith(OPENCODE_RUNTIME_RESULT))
if (!line) {
throw new Error('The host did not confirm SQLite runtime setup.')
}
const result: unknown = JSON.parse(line.slice(OPENCODE_RUNTIME_RESULT.length))
if (
typeof result !== 'object' ||
result === null ||
!('status' in result) ||
typeof result.status !== 'string'
) {
throw new Error('Invalid SQLite runtime setup result.')
}
if ('executable' in result) {
if (
typeof result.executable !== 'string' ||
!(posix.isAbsolute(result.executable) || win32.isAbsolute(result.executable)) ||
/[\0\r\n]/.test(result.executable)
) {
throw new Error('SQLite runtime setup returned an invalid executable path.')
}
return { status: result.status, executable: result.executable }
}
return { status: result.status }
}