Merge branch 'codex/goal-session' into codex/commands
# Conflicts: # docs/architecture.md # docs/capability-seams.md # docs/config-catalog.md # docs/module-graph.md # knip.json # packages/examples/README.md # packages/examples/stdio-demo/README.md # packages/examples/stdio-demo/src/index.ts # packages/examples/tui-demo/package.json # packages/ui/README.md # packages/ui/tui/src/index.ts
This commit is contained in:
@@ -36,6 +36,7 @@ import z from 'schemastery'
|
||||
import type { Agent, AgentStatus } from '@deepseek-ai/dsh-agent'
|
||||
import type {} from '@deepseek-ai/dsh-agent-loop'
|
||||
import type {} from '@deepseek-ai/dsh-commands'
|
||||
import { errorChain } from '@deepseek-ai/dsh-llm'
|
||||
import type { ContentBlock, StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
import { SessionId, type Session, type SessionEvent, type TodoItem } from '@deepseek-ai/dsh-session'
|
||||
import type {
|
||||
@@ -192,15 +193,6 @@ function displayText(text: string): string {
|
||||
`\\x${control.charCodeAt(0).toString(16).padStart(2, '0')}`)
|
||||
}
|
||||
|
||||
/** Render an arbitrary failure without allowing hostile coercion to escape the UI boundary. */
|
||||
function renderThrown(value: unknown): string {
|
||||
try {
|
||||
return String(value)
|
||||
} catch {
|
||||
return '<unrenderable thrown value>'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme-agnostic palette built from the standard 16-color ANSI set plus SGR
|
||||
* attributes, which every terminal remaps to its active color scheme. Body
|
||||
@@ -1231,7 +1223,7 @@ export function createTuiChat(
|
||||
},
|
||||
(error: unknown) => {
|
||||
if (!disposed) {
|
||||
appendNotice(`Command failed: ${renderThrown(error)}`, 'error')
|
||||
appendNotice(`Command failed: ${errorChain(error)}`, 'error')
|
||||
}
|
||||
},
|
||||
).finally(() => { commandControllers.delete(controller) })
|
||||
@@ -1312,7 +1304,9 @@ export function createTuiChat(
|
||||
const disposeError = ctx.on('agent/error', (subject, turn, step, error) => {
|
||||
if (subject !== agent) return
|
||||
liveErrors.add(`${turn}:${step}`)
|
||||
appendNotice(error.message, 'error')
|
||||
// Full cause chain: wrapper messages like `fetch failed` carry the
|
||||
// actionable transport detail on `cause`.
|
||||
appendNotice(errorChain(error), 'error')
|
||||
})
|
||||
const disposeAgent = ctx.on('agent/disposed', (subject) => {
|
||||
if (subject !== agent) return
|
||||
@@ -1339,7 +1333,7 @@ export function createTuiChat(
|
||||
void commandFiber.dispose().catch(
|
||||
/* v8 ignore next 2 -- command registration cleanup is non-throwing; this guards a future disposer regression */
|
||||
(cleanupError: unknown) => {
|
||||
ctx.logger.warn(`ui-tui: command cleanup after startup failure failed: ${renderThrown(cleanupError)}`)
|
||||
ctx.logger.warn(`ui-tui: command cleanup after startup failure failed: ${errorChain(cleanupError)}`)
|
||||
},
|
||||
)
|
||||
clearStatus()
|
||||
@@ -1387,7 +1381,7 @@ export function mountTui(ctx: Context, config: Config, runtime: TuiRuntime): voi
|
||||
if (settled || failedSessionId !== sessionId) return
|
||||
settled = true
|
||||
stopWaiting()
|
||||
runtime.terminal.write(displayText(`ui-tui: session "${sessionId}" failed to start: ${renderThrown(error)}\n`))
|
||||
runtime.terminal.write(displayText(`ui-tui: session "${sessionId}" failed to start: ${errorChain(error)}\n`))
|
||||
runtime.exit(1)
|
||||
}
|
||||
|
||||
@@ -1399,10 +1393,10 @@ export function mountTui(ctx: Context, config: Config, runtime: TuiRuntime): voi
|
||||
|
||||
/** Cordis entry point using the process terminal; explicit TUI composition requires a TTY pair. */
|
||||
/* v8 ignore start -- production process wiring; fake-terminal tests cover mountTui/createTuiChat,
|
||||
and the repl-agent PTY smoke covers the real entry */
|
||||
and the tui-agent PTY smoke covers the real entry */
|
||||
export function apply(ctx: Context, config: Config): void {
|
||||
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
||||
throw new Error('ui-tui: both stdin and stdout must be TTYs; use @deepseek-ai/dsh-stdio for pipes')
|
||||
throw new Error('ui-tui: both stdin and stdout must be TTYs; use @deepseek-ai/dsh-cli-demo for non-interactive runs')
|
||||
}
|
||||
mountTui(ctx, config, {
|
||||
terminal: new ProcessTerminal(),
|
||||
|
||||
Reference in New Issue
Block a user