Files
tabby/app/lib/urlHandler.ts
T
Ponder b31a48677d
Package-Build / Lint (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Docs / build (push) Has been cancelled
Package-Build / macOS-Build (arm64, aarch64-apple-darwin) (push) Has been cancelled
Package-Build / macOS-Build (x86_64, x86_64-apple-darwin) (push) Has been cancelled
Package-Build / Linux-Build (amd64, x64, ubuntu-24.04, x86_64-unknown-linux-gnu) (push) Has been cancelled
Package-Build / Linux-Build (arm64, arm64, ubuntu-24.04-arm, aarch64-unknown-linux-gnu, aarch64-linux-gnu-) (push) Has been cancelled
Package-Build / Linux-Build (armhf, arm, ubuntu-24.04, arm-unknown-linux-gnueabihf, arm-linux-gnueabihf-) (push) Has been cancelled
Package-Build / Windows-Build (arm64, aarch64-pc-windows-msvc) (push) Has been cancelled
Package-Build / Windows-Build (x64, x86_64-pc-windows-msvc) (push) Has been cancelled
feat: Implement tabby:// URL scheme handler (#11005)
Co-authored-by: Eugene <inbox@null.page>
2026-02-01 22:43:02 +01:00

63 lines
2.4 KiB
TypeScript

import { createParserConfig } from './cli'
import { parse as parseShellCommand } from 'shell-quote'
export function isTabbyURL (arg: string): boolean {
return arg.toLowerCase().startsWith('tabby://')
}
export function parseTabbyURL (url: string, cwd: string = process.cwd()): any {
try {
if (!isTabbyURL(url)) {
return null
}
// NOTE: the url host may be lowercased (xdg-open), need to use the original command
const urlInstance = new URL(url)
const command = urlInstance.host || urlInstance.pathname.replace(/^\/+/, '')
const config = createParserConfig(cwd)
const commandConfig = config.commands.find(cmd => {
const primaryCommand = Array.isArray(cmd.command) ? cmd.command[0] : cmd.command
return command.toLowerCase() === primaryCommand.split(/\s+/)[0].toLowerCase()
})
if (!commandConfig) {
console.error(`Unknown command in tabby:// URL: ${command}`)
return null
}
const primaryCommand = Array.isArray(commandConfig.command) ? commandConfig.command[0] : commandConfig.command
const actualCommand = primaryCommand.split(/\s+/)[0]
const argv: any = {
_: [actualCommand],
}
for (const [key, value] of urlInstance.searchParams.entries()) {
let parsedValue: any = value
const optionConfig = commandConfig.options?.[key] ?? commandConfig.positionals?.[key]
if (optionConfig) {
switch (optionConfig.type) {
case 'boolean':
parsedValue = value === 'true' || value === ''
break
case 'number':
parsedValue = parseInt(value, 10)
break
case 'array':
parsedValue = parseShellCommand(value).filter(item => typeof item === 'string')
break
case 'string':
default:
parsedValue = value
break
}
} else {
parsedValue = value
}
argv[key] = parsedValue
}
console.log(`URL Handler - Safely parsed [${url}] to:`, JSON.stringify(argv))
return argv
} catch (e) {
console.error('Failed to parse tabby:// URL:', e)
return null
}
}