feat: configurable terminal shell with Windows pwsh auto-probe (#95)

* feat: configurable terminal shell with Windows pwsh auto-probe

Windows previously hardcoded powershell.exe (5.1) in defaultShell(), ignoring PowerShell 7 installs. Resolve the shell in priority order: explicit shell config -> DSH_SIDEBAR_SHELL -> PATH/known-dir probe for pwsh.exe -> inbox 5.1 fallback. The same resolved shell feeds both the UI terminal tabs (PtyManager) and the model-facing terminal_* tools (AgentPtyRegistry).

defaultShell() now accepts injectable platform/env/exists options so the Windows chain is unit-testable on the ubuntu CI, which never executes win32 branches. The probe also checks ProgramW6432 for 32-bit Node, and machines without PowerShell 7 keep the 5.1 fallback.

Refs: #46

* fix: trim resolved SHELL and document ProgramW6432 in resolver contract

- POSIX SHELL is validated with trim() but was returned untrimmed; trailing whitespace could leak into the spawned executable path. Return the trimmed value like the explicit/config and Windows/env branches.
- ShellResolutionOptions.env comment now lists ProgramW6432, which the Windows probe prefers over ProgramFiles on 32-bit Node.
- Test pins the SHELL trimming behavior.
This commit is contained in:
oy-g
2026-08-16 16:34:21 +08:00
committed by GitHub
parent 835d1538e0
commit fd9544f16b
5 changed files with 165 additions and 32 deletions
+7
View File
@@ -34,6 +34,13 @@ describe('dsh-better-sidebar plugin export shape', () => {
expect(resolved.listLimit).toBe(1000)
expect(resolved.terminalsPerSession).toBe(3)
expect(resolved.reconnectGraceMs).toBe(30_000)
// The terminal shell config defaults to auto-resolution (empty shell =
// the platform chain in defaultShell()).
expect(resolved.shell).toBe('')
const configured = (schema as unknown as {
(input: Record<string, unknown> | undefined): Record<string, unknown>
})({ shell: 'pwsh.exe' })
expect(configured.shell).toBe('pwsh.exe')
})
it('registers the side card preferences schema with the documented defaults', async () => {