fix(terminal-bash): fall back to dialect defaults when Schemastery materializes empty shell values

This commit is contained in:
Huanqi Cao
2026-08-13 10:41:33 +08:00
parent 7da062f61b
commit 82c53ee209
2 changed files with 21 additions and 4 deletions
+10 -4
View File
@@ -59,8 +59,10 @@ export const DEFAULT_PWSH_ARGS = ['-NoLogo', '-NoProfile']
/**
* Resolve the effective per-dialect shell specification. Defaulting is this
* explicit step: an unset `shellPath`/`shellArgs` selects the dialect's
* defaults, while an explicit value always wins.
* explicit step: an unset or empty `shellPath`/`shellArgs` selects the
* dialect's defaults, while a non-empty explicit value always wins.
* (Schemastery materializes an absent optional array as `[]`, so emptiness —
* not just `undefined` — means "dialect default".)
* @param config - Schemastery-resolved plugin configuration.
* @returns the fully resolved configuration.
*/
@@ -69,8 +71,12 @@ export function resolveConfig(config: Config): ResolvedConfig {
return {
...(config as Required<Config>),
shellDialect,
shellPath: config.shellPath ?? (shellDialect === 'pwsh' ? resolvePwshPath() : DEFAULT_BASH_SHELL),
shellArgs: config.shellArgs ?? (shellDialect === 'pwsh' ? DEFAULT_PWSH_ARGS : DEFAULT_BASH_ARGS),
shellPath: config.shellPath !== undefined && config.shellPath.length > 0
? config.shellPath
: (shellDialect === 'pwsh' ? resolvePwshPath() : DEFAULT_BASH_SHELL),
shellArgs: config.shellArgs !== undefined && config.shellArgs.length > 0
? config.shellArgs
: (shellDialect === 'pwsh' ? DEFAULT_PWSH_ARGS : DEFAULT_BASH_ARGS),
}
}
@@ -54,6 +54,17 @@ describe('terminal-bash dialect resolution', () => {
expect(resolved.shellArgs).toEqual(['-NoProfile'])
})
it('treats empty shell values as unset so Schemastery materialization cannot drop the dialect defaults', () => {
// Schemastery materializes an absent optional array as `[]`; the resolver
// must treat that shape like an unset value or a real bash spawn would
// start non-interactive without the controlled prompt.
const resolved = resolveConfig({
backendType: 'shell', shellDialect: 'bash', shellPath: '', shellArgs: [], rows: 24, cols: 80,
})
expect(resolved.shellPath).toBe('/bin/bash')
expect(resolved.shellArgs).toEqual(['--noprofile', '--norc', '-i'])
})
it('validates the effective shell path, not only the raw one', () => {
expect(() => { validateConfig(resolveConfig({ backendType: 'shell', shellDialect: 'bash', rows: 24, cols: 80 })) }).not.toThrow()
expect(() => { validateConfig(resolveConfig({ backendType: 'shell', shellDialect: 'pwsh', rows: 24, cols: 80 })) }).not.toThrow()