feat(terminal): shell 覆盖去引号进解析、标题跟随覆盖、close reason 机器标记
This commit is contained in:
+27
-9
@@ -41,7 +41,7 @@ import { registerBundleRoute } from './bundle-route.ts'
|
||||
import { launchExternal } from './open-external.ts'
|
||||
import * as git from './git.ts'
|
||||
import { SettingsConflictError } from '@deepseek-ai/dsh-settings'
|
||||
import { defaultShell, ensureSpawnHelper, PtyManager, shellDisplayName } from './pty-manager.ts'
|
||||
import { defaultShell, ensureSpawnHelper, PtyManager, shellDisplayName, splitShellArgs, unquotePath } from './pty-manager.ts'
|
||||
import { AgentPtyRegistry, armPtyResizeGate, tryResizePty, type AgentTerminalHandle } from './agent-pty.ts'
|
||||
import {
|
||||
DSH_NODE_PTY_RANGE,
|
||||
@@ -250,11 +250,11 @@ function shellOverridesOf(getSettings: () => SidebarSettingsFace | undefined): {
|
||||
const value = settings?.get().value
|
||||
if (value === null || typeof value !== 'object') return {}
|
||||
const record = value as Record<string, unknown>
|
||||
const shell = typeof record.terminalShell === 'string' ? record.terminalShell.trim() : ''
|
||||
const shell = typeof record.terminalShell === 'string' ? unquotePath(record.terminalShell.trim()) : ''
|
||||
const args = typeof record.terminalShellArgs === 'string' ? record.terminalShellArgs.trim() : ''
|
||||
return {
|
||||
shell: shell === '' ? undefined : shell,
|
||||
shellArgs: args === '' ? undefined : args.split(/\s+/).filter(Boolean),
|
||||
shellArgs: args === '' ? undefined : splitShellArgs(args),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,11 +559,14 @@ function buildApi(
|
||||
// Subagent live previews: one batch request per refresh; the route folds
|
||||
// the newest text/tool activity of every running child in the tree.
|
||||
'subagents.live': (payload) => subagentLiveApi.live(payload),
|
||||
// The effective terminal shell and its display name. The client uses
|
||||
// this to title terminal tabs with the shell name instead of a numbered
|
||||
// "Terminal N" label; the shell itself is configured through
|
||||
// `cordis.patch.yml` (`config.shell`) or resolved by the host default.
|
||||
'shell.get': () => ({ shell: terminalShell, name: shellDisplayName(terminalShell) }),
|
||||
// The effective terminal shell and its display name: the settings-page
|
||||
// override when set (quotes stripped), else the boot-time resolution.
|
||||
// The client titles terminal tabs with the name, so a changed setting is
|
||||
// visible on the next opened tab without a plugin restart.
|
||||
'shell.get': () => {
|
||||
const effective = shellOverridesOf(getSettings).shell ?? terminalShell
|
||||
return { shell: effective, name: shellDisplayName(effective) }
|
||||
},
|
||||
// The side card preferences. The settings service is optional in the
|
||||
// composition; while absent the routes report undefined and the client
|
||||
// keeps the schema defaults. Writes are revision-guarded: a stale editor
|
||||
@@ -1176,6 +1179,21 @@ async function attachAgentList(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The WS close reason for a failed terminal attach. A missing configured
|
||||
* shell gets a SHORT machine-readable marker (`shell-not-found:<name>`,
|
||||
* capped — a WS close reason allows at most 123 bytes) that the client maps
|
||||
* to a localized, actionable banner; every other failure keeps the raw
|
||||
* message (the model-side tool errors read it verbatim).
|
||||
*/
|
||||
export function wsCloseReasonOf(error: unknown): string {
|
||||
if (error instanceof SidebarError && error.code === 'shell-not-found') {
|
||||
const name = shellDisplayName(String(error.meta?.shell ?? '')).slice(0, 100)
|
||||
return `shell-not-found:${name}`
|
||||
}
|
||||
return error instanceof Error ? error.message : String(error)
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire one terminal socket to its pty: replay transcript, pump both ways.
|
||||
* Two attach modes share the wire protocol:
|
||||
@@ -1304,7 +1322,7 @@ async function attachTerminal(
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
ws.close(1011, error instanceof Error ? error.message : String(error))
|
||||
ws.close(1011, wsCloseReasonOf(error))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user