Merge remote-tracking branch 'origin/master' into worktree/tui-file-autocomplete

# Conflicts:
#	docs/config-catalog.md
This commit is contained in:
Yichen Jiang
2026-07-23 19:30:29 +08:00
286 changed files with 13961 additions and 3531 deletions

View File

@@ -60,6 +60,7 @@ import type {} from '@deepseek-ai/dsh-llm-retry'
import {
displayPromptContent,
SessionId,
type JsonValue,
type Session,
type SessionEvent,
type SessionHeader,
@@ -840,7 +841,7 @@ function diffLines(diff: FileDiff, palette: Palette): string[] {
}
class ToolCardComponent implements Component {
private result: { content: ContentBlock[]; isError: boolean; meta?: unknown } | undefined
private result: { content: ContentBlock[]; isError: boolean; meta?: JsonValue } | undefined
private expanded = false
private callView: ToolCallView
private resultView: ToolResultView | undefined

View File

@@ -7,8 +7,7 @@ import type { Context } from 'cordis'
import { agentEvents } from '@deepseek-ai/dsh-agent'
import { CallId, type ContentBlock } from '@deepseek-ai/dsh-llm'
import type {} from '@deepseek-ai/dsh-llm-retry'
import type { Session } from '@deepseek-ai/dsh-session'
import { SessionId } from '@deepseek-ai/dsh-session'
import { SessionId, type JsonValue, type Session } from '@deepseek-ai/dsh-session'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry, { type ToolDefinition, type ToolResultView } from '@deepseek-ai/dsh-tools'
import * as ToolCordis from '@deepseek-ai/dsh-tool-cordis'
@@ -159,7 +158,7 @@ function appendToolResult(
session: Session,
id: string,
content: ContentBlock[],
options: { isError?: boolean; meta?: unknown } = {},
options: { isError?: boolean; meta?: JsonValue } = {},
): void {
session.append('tool/result', {
turn: 1,
@@ -180,6 +179,7 @@ function visualTool(
name,
description: `${name} snapshot fixture`,
parameters: {},
output: { schema: { type: 'null' }, render: () => [] },
execute: () => Promise.resolve([]),
presentCall: call,
...result === undefined ? {} : { presentResult: result },

View File

@@ -34,6 +34,11 @@ import {
type TuiHarnessOptions,
} from './harness.ts'
const UNUSED_TOOL_OUTPUT: ToolDefinition['output'] = {
schema: { type: 'null' },
render: () => [],
}
class FakeTerminal implements Terminal {
columns = 88
rows = 32
@@ -1084,6 +1089,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
name: 'read',
description: 'Read a file.',
parameters: {},
output: UNUSED_TOOL_OUTPUT,
execute: () => Promise.resolve([]),
},
},
@@ -1157,6 +1163,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
name: 'read',
description: 'Read a file.',
parameters: {},
output: UNUSED_TOOL_OUTPUT,
execute: () => Promise.resolve([]),
}
let visibility: 'none' | 'global' | 'agent' = 'none'
@@ -1986,17 +1993,17 @@ describe('renderSkillInvocation', () => {
describe('tool cards and surface replay', () => {
const tools: Record<string, ToolDefinition> = {
bash: {
name: 'bash', description: '', parameters: {}, execute: async () => [],
name: 'bash', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({ card: 'terminal', title: 'printf hello', description: 'Run command', cwd: '/tmp' }),
presentResult: () => ({ card: 'terminal', output: 'hello\nworld\nthird', exitCode: 0 }),
},
signal: {
name: 'signal', description: '', parameters: {}, execute: async () => [],
name: 'signal', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({ card: 'terminal', title: 'sleep 10' }),
presentResult: () => ({ card: 'terminal', signal: 'SIGTERM' }),
},
edit: {
name: 'edit', description: '', parameters: {}, execute: async () => [],
name: 'edit', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({
card: 'diff',
title: 'Edit files',
@@ -2008,35 +2015,35 @@ describe('tool cards and surface replay', () => {
presentResult: () => ({ card: 'diff', diffs: [{ path: 'a.txt', oldText: null, newText: 'created' }] }),
},
generic: {
name: 'generic', description: '', parameters: {}, execute: async () => [],
name: 'generic', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({ card: 'generic', title: 'Inspect value', rawInput: { alpha: 1 } }),
presentResult: () => ({ card: 'generic', title: 'Inspected', content: [{ type: 'text', text: 'result text' }] }),
},
throwing: {
name: 'throwing', description: '', parameters: {}, execute: async () => [],
name: 'throwing', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => { throw new Error('call presenter boom') },
presentResult: () => { throw new Error('result presenter boom') },
},
rawTerminal: {
name: 'rawTerminal', description: '', parameters: {}, execute: async () => [],
name: 'rawTerminal', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({ card: 'terminal', title: 'raw command' }),
},
undefinedViews: {
name: 'undefinedViews', description: '', parameters: {}, execute: async () => [],
name: 'undefinedViews', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => undefined,
presentResult: () => undefined,
},
empty: {
name: 'empty', description: '', parameters: {}, execute: async () => [],
name: 'empty', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({ card: 'generic', title: 'Empty card' }),
},
terminalResult: {
name: 'terminalResult', description: '', parameters: {}, execute: async () => [],
name: 'terminalResult', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({ card: 'generic', title: 'Becomes terminal' }),
presentResult: () => ({ card: 'terminal', output: 'converted terminal' }),
},
symbolic: {
name: 'symbolic', description: '', parameters: {}, execute: async () => [],
name: 'symbolic', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
presentCall: () => ({ card: 'generic', title: 'Symbol input', rawInput: Symbol('input') }),
},
}