diff --git a/packages/client/ui-tool/src/client/tool/models/terminal-card-model.ts b/packages/client/ui-tool/src/client/tool/models/terminal-card-model.ts index a34a56dfc7..548a024562 100644 --- a/packages/client/ui-tool/src/client/tool/models/terminal-card-model.ts +++ b/packages/client/ui-tool/src/client/tool/models/terminal-card-model.ts @@ -156,8 +156,9 @@ function shellCall(name: string, args: Record): ShellCall | nul if (background !== undefined && typeof background !== 'boolean') return null if (!validEscalationFields(args)) return null if (description === undefined) { - // Persistent shell providers consume only `command`; parameter roots are - // open, so unrelated fields do not change their running-card behavior. + // Standard dsh-tool-bash and dsh-tool-pwsh schemas require `description`; + // persistent shell providers omit it. Their parameter roots stay open, so + // unrelated fields do not change their running-card behavior. return { command, description: undefined, workdir: undefined, persistent: true, background: false } } if (typeof description !== 'string' || description.trim() === '') return null @@ -183,12 +184,20 @@ function terminalSendCall(name: string, args: Record): Terminal if (submit !== undefined && typeof submit !== 'boolean') return null if (background !== undefined && typeof background !== 'boolean') return null return { + // Keep this visible fallback aligned with dsh-tool-terminal's + // `terminal_send.presentCall` implementation. command: text || '(send input)', description: `Terminal ${sessionId}`, background: background === true, } } +/** + * Parse the marker literals owned by `@deepseek-ai/dsh-shell/render` without + * importing that Host-only package into the Client dependency graph. + * @param text - rendered shell result text. + * @returns output with a trailing exit-code or signal marker extracted. + */ function parseExitStatus(text: string): { output: string; exitCode?: number; signal?: string } { const signal = /\n\[killed by signal: ([^\]\n]+)\]$/.exec(text) if (signal?.[1] !== undefined) return { output: text.slice(0, signal.index), signal: signal[1] } diff --git a/packages/shell/shell/src/render.ts b/packages/shell/shell/src/render.ts index 3b077d64f1..8fc924ef63 100644 --- a/packages/shell/shell/src/render.ts +++ b/packages/shell/shell/src/render.ts @@ -1,7 +1,8 @@ /** * Shared rendering helpers for the shell tools (`dsh-tool-bash`, - * `dsh-tool-pwsh`): the exit-status marker contract the tools' renderers - * emit and the presentation layer parses back. + * `dsh-tool-pwsh`): the exit-status marker contract the tools' renderers emit, + * Host `presentResult` implementations parse here, and the Web terminal card + * model mirrors without importing Host code. * @module @deepseek-ai/dsh-shell/render */ diff --git a/packages/terminal/tool-terminal/src/index.ts b/packages/terminal/tool-terminal/src/index.ts index e0ed86a289..0ab37fdc31 100644 --- a/packages/terminal/tool-terminal/src/index.ts +++ b/packages/terminal/tool-terminal/src/index.ts @@ -284,6 +284,8 @@ export function apply(ctx: Context, config: Config = {}): void { if (parsed.run_in_background === true) { return { card: 'generic', title: `Send to terminal ${parsed.sessionId as string} in background`, kind: 'execute', rawInput: parsed.text } } + // Keep this visible fallback aligned with dsh-client-ui-tool's + // terminal-card model, which cannot import this Host package. return { card: 'terminal', title: parsed.text || '(send input)', description: `Terminal ${parsed.sessionId as string}` } }, presentResult(args, result) {