@@ -29,6 +29,34 @@ function escapeQmdExactFilePattern(fileName: string): string {
|
29 | 29 | return fileName.replace(/[\\*?[\]{}()!+@]/g, "\\$&"); |
30 | 30 | } |
31 | 31 | |
| 32 | +const WINDOWS_COMMAND_EXTENSION_RE = |
| 33 | +/^((?:[A-Za-z]:[\\/]|\\\\[^\\/]+[\\/][^\\/]+[\\/]).*?\.(?:bat|cmd|cjs|exe|js|mjs|ps1))(?:\s+|$)/i; |
| 34 | + |
| 35 | +function resolveQmdCommand(rawCommand: string): string { |
| 36 | +const trimmedCommand = rawCommand.trim(); |
| 37 | +const windowsCommand = resolveWindowsAbsoluteCommand(trimmedCommand); |
| 38 | +if (windowsCommand) { |
| 39 | +return windowsCommand; |
| 40 | +} |
| 41 | + |
| 42 | +const parsedCommand = splitShellArgs(trimmedCommand); |
| 43 | +return parsedCommand?.[0] || trimmedCommand.split(/\s+/)[0] || "qmd"; |
| 44 | +} |
| 45 | + |
| 46 | +function resolveWindowsAbsoluteCommand(rawCommand: string): string | undefined { |
| 47 | +if (!path.win32.isAbsolute(rawCommand)) { |
| 48 | +return undefined; |
| 49 | +} |
| 50 | + |
| 51 | +const extensionMatch = WINDOWS_COMMAND_EXTENSION_RE.exec(rawCommand); |
| 52 | +if (extensionMatch) { |
| 53 | +return extensionMatch[1]; |
| 54 | +} |
| 55 | + |
| 56 | +const firstWhitespace = rawCommand.search(/\s/); |
| 57 | +return firstWhitespace === -1 ? rawCommand : rawCommand.slice(0, firstWhitespace); |
| 58 | +} |
| 59 | + |
32 | 60 | export type ResolvedMemoryBackendConfig = { |
33 | 61 | backend: MemoryBackend; |
34 | 62 | citations: MemoryCitationsMode; |
@@ -439,8 +467,7 @@ export function resolveMemoryBackendConfig(params: {
|
439 | 467 | ]; |
440 | 468 | |
441 | 469 | const rawCommand = qmdCfg?.command?.trim() || "qmd"; |
442 | | -const parsedCommand = splitShellArgs(rawCommand); |
443 | | -const command = parsedCommand?.[0] || rawCommand.split(/\s+/)[0] || "qmd"; |
| 470 | +const command = resolveQmdCommand(rawCommand); |
444 | 471 | const resolved: ResolvedQmdConfig = { |
445 | 472 | command, |
446 | 473 | mcporter: resolveMcporterConfig(qmdCfg?.mcporter), |
|