feat: click file name to open file in toolcall, remove hover bg of toolcall, do not trigger sidebar any more (follow designer's instruction)
This commit is contained in:
78
packages/host/apiproxy/src/native-path-opener.ts
Normal file
78
packages/host/apiproxy/src/native-path-opener.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/** Cross-platform open-with-default-application used by the local GUI carrier. */
|
||||
|
||||
import { execFile } from 'node:child_process'
|
||||
|
||||
/** Testable command boundary; native implementations never invoke a shell. */
|
||||
export type PathOpenerRunner = (
|
||||
command: string,
|
||||
args: readonly string[],
|
||||
signal: AbortSignal,
|
||||
) => Promise<{ stdout: string; stderr: string }>
|
||||
|
||||
/** Injectable platform facts for deterministic adapter tests. */
|
||||
export interface PathOpenerInternals {
|
||||
platform?: NodeJS.Platform
|
||||
run?: PathOpenerRunner
|
||||
}
|
||||
|
||||
const runCommand: PathOpenerRunner = (command, args, signal) =>
|
||||
new Promise((resolve, reject) => {
|
||||
execFile(
|
||||
command,
|
||||
[...args],
|
||||
{ encoding: 'utf8', signal, windowsHide: true },
|
||||
(error, stdout, stderr) => {
|
||||
if (error !== null) {
|
||||
const failure = Object.assign(new Error(error.message, { cause: error }), {
|
||||
code: error.code,
|
||||
stdout,
|
||||
stderr,
|
||||
})
|
||||
reject(failure)
|
||||
return
|
||||
}
|
||||
resolve({ stdout, stderr })
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
/** PowerShell single-quoted literal (doubles embedded quotes). */
|
||||
function powershellLiteral(path: string): string {
|
||||
return `'${path.replace(/'/g, "''")}'`
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a filesystem path with the operating system's default application.
|
||||
* @param path - absolute or host-resolvable path (caller owns resolution).
|
||||
* @param signal - caller/connection lifetime; abort terminates the native command.
|
||||
* @param internals - platform and runner seam for deterministic tests.
|
||||
*/
|
||||
export async function openNativePath(
|
||||
path: string,
|
||||
signal: AbortSignal,
|
||||
internals: PathOpenerInternals = {},
|
||||
): Promise<void> {
|
||||
const platform = internals.platform ?? process.platform
|
||||
const run = internals.run ?? runCommand
|
||||
|
||||
if (platform === 'darwin') {
|
||||
await run('open', [path], signal)
|
||||
return
|
||||
}
|
||||
|
||||
if (platform === 'win32') {
|
||||
await run('powershell.exe', [
|
||||
'-NoProfile',
|
||||
'-Command',
|
||||
`Invoke-Item -LiteralPath ${powershellLiteral(path)}`,
|
||||
], signal)
|
||||
return
|
||||
}
|
||||
|
||||
if (platform === 'linux') {
|
||||
await run('xdg-open', [path], signal)
|
||||
return
|
||||
}
|
||||
|
||||
throw new Error(`native path opener is unsupported on ${platform}`)
|
||||
}
|
||||
Reference in New Issue
Block a user