| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- /**
- * Serializable configuration and defaults for the pi-tui terminal mode. Loader
- * schema validation normally fills defaults; {@link resolveTuiConfig} applies
- * the same defaults for direct callers that bypass the Loader.
- * @module @deepseek-ai/dsh-tui/config
- */
- import z from 'schemastery'
- import {
- DEFAULT_FILE_SEARCH_EXCLUDED_DIRECTORIES,
- DEFAULT_FILE_SEARCH_MAX_ENTRIES,
- DEFAULT_FILE_SEARCH_MAX_RESULTS,
- } from './chat/file-autocomplete.ts'
- /** Theme and prompt-template settings for the pi-tui terminal mode. */
- export interface TuiThemeConfig {
- /** Apply the built-in ANSI color palette. */
- color?: boolean
- /** Paint the startup banner with the 24-bit DeepSeek brand gradient. */
- truecolor?: boolean
- /** Left-aligned template on the row above the editor. */
- leftPrompt?: string
- /** Right-aligned template on the row above the editor. */
- rightPrompt?: string
- /** Template used as the editor's first-line prefix. */
- inputPrompt?: string
- /** Static placeholder shown in an empty editor while the agent is running. */
- inputPlaceholder?: string
- }
- /** Interaction and presentation settings for the pi-tui terminal mode. */
- export interface TuiConfig {
- /** Render model reasoning blocks. */
- showReasoning?: boolean
- /** Maximum tool-card body lines retained in its collapsed head/tail preview. */
- maxToolOutputLines?: number
- /** Maximum options visible at once in a user-question panel. */
- maxQuestionOptions?: number
- /** Maximum models visible at once in the model selector. */
- maxModelOptions?: number
- /** Maximum sessions visible at once in the resume selector. */
- maxResumeOptions?: number
- /** User-question panel width in terminal columns, clamped to the terminal. */
- questionDialogWidth?: number
- /** User-question panel maximum height in terminal rows. */
- questionDialogMaxHeight?: number
- /** Model-selector width in terminal columns. */
- modelDialogWidth?: number
- /** Model-selector maximum height in terminal rows. */
- modelDialogMaxHeight?: number
- /** Maximum fuzzy file candidates displayed for one `@` query. */
- fileSearchMaxResults?: number
- /** Maximum paths retained in one `@` workspace index. */
- fileSearchMaxEntries?: number
- /** Directory basenames excluded from `@` traversal and completion. */
- fileSearchExcludedDirectories?: string[]
- /** Show the terminal's hardware cursor at the pi editor's IME marker. */
- showHardwareCursor?: boolean
- /** Color and prompt-template settings. */
- theme?: TuiThemeConfig
- /** Terminal window title while the UI is mounted; a logged session title prefixes it. */
- title?: string
- }
- const showReasoningSchema = z.boolean().default(true)
- const maxToolOutputLinesSchema = z.number().step(1).min(1).default(6)
- const maxQuestionOptionsSchema = z.number().step(1).min(1).default(8)
- const maxModelOptionsSchema = z.number().step(1).min(1).default(8)
- const maxResumeOptionsSchema = z.number().step(1).min(1).default(8)
- const questionDialogWidthSchema = z.number().step(1).min(20).default(200)
- const questionDialogMaxHeightSchema = z.number().step(1).min(6).default(20)
- const modelDialogWidthSchema = z.number().step(1).min(20).default(76)
- const modelDialogMaxHeightSchema = z.number().step(1).min(6).default(20)
- const fileSearchMaxResultsSchema = z.number().step(1).min(1).default(DEFAULT_FILE_SEARCH_MAX_RESULTS)
- const fileSearchMaxEntriesSchema = z.number().step(1).min(1).default(DEFAULT_FILE_SEARCH_MAX_ENTRIES)
- const fileSearchExcludedDirectoriesSchema = z.array(z.string()).default([...DEFAULT_FILE_SEARCH_EXCLUDED_DIRECTORIES])
- const showHardwareCursorSchema = z.boolean().default(false)
- const colorSchema = z.boolean().default(true)
- // No default: an unset value auto-detects truecolor from COLORTERM in `apply`.
- const truecolorSchema = z.boolean()
- const DEFAULT_LEFT_PROMPT = '${cwd}${git/worktree}${model}${token_meter/cache_hit_rate}${context}'
- const DEFAULT_RIGHT_PROMPT = '${timing}'
- const DEFAULT_INPUT_PROMPT = '${symbol} ${indicator}'
- const DEFAULT_INPUT_PLACEHOLDER = 'press enter to steer and esc to cancel'
- const TuiThemeConfigSchema: z<TuiThemeConfig> = z.object({
- color: colorSchema,
- truecolor: truecolorSchema,
- leftPrompt: z.string().default(DEFAULT_LEFT_PROMPT),
- rightPrompt: z.string().default(DEFAULT_RIGHT_PROMPT),
- inputPrompt: z.string().default(DEFAULT_INPUT_PROMPT),
- inputPlaceholder: z.string().default(DEFAULT_INPUT_PLACEHOLDER),
- })
- const titleSchema = z.string().default('DeepSeek Harness')
- const tuiConfigSchemaFields = {
- showReasoning: showReasoningSchema,
- maxToolOutputLines: maxToolOutputLinesSchema,
- maxQuestionOptions: maxQuestionOptionsSchema,
- maxModelOptions: maxModelOptionsSchema,
- maxResumeOptions: maxResumeOptionsSchema,
- questionDialogWidth: questionDialogWidthSchema,
- questionDialogMaxHeight: questionDialogMaxHeightSchema,
- modelDialogWidth: modelDialogWidthSchema,
- modelDialogMaxHeight: modelDialogMaxHeightSchema,
- fileSearchMaxResults: fileSearchMaxResultsSchema,
- fileSearchMaxEntries: fileSearchMaxEntriesSchema,
- fileSearchExcludedDirectories: fileSearchExcludedDirectoriesSchema,
- showHardwareCursor: showHardwareCursorSchema,
- theme: TuiThemeConfigSchema,
- title: titleSchema,
- }
- /** Schemastery schema for presentation settings embedded by app bundles. */
- export const TuiConfigSchema: z<TuiConfig> = z.object(tuiConfigSchemaFields)
- /** Serializable plugin configuration. */
- export interface Config extends TuiConfig {
- /** Banner subtitle line. When absent, the banner has no subtitle and sweeps in on start. */
- welcome?: string
- /** Exact shared agent/session identity driven by this terminal. Defaults to `main`. */
- sessionId?: string
- /**
- * Shell command fallback printed on exit or after selecting a session when
- * the host cannot hand off in place. Every `{session}` becomes the selected
- * id; the TUI never executes this text. Absent disables only the fallback,
- * not the interactive selector.
- */
- resumeCommand?: string
- }
- /** Schemastery schema for the full plugin configuration. */
- export const Config: z<Config> = z.object({
- welcome: z.string(),
- sessionId: z.string().default('main'),
- resumeCommand: z.string(),
- showReasoning: tuiConfigSchemaFields.showReasoning,
- maxToolOutputLines: tuiConfigSchemaFields.maxToolOutputLines,
- maxQuestionOptions: tuiConfigSchemaFields.maxQuestionOptions,
- maxModelOptions: tuiConfigSchemaFields.maxModelOptions,
- maxResumeOptions: tuiConfigSchemaFields.maxResumeOptions,
- questionDialogWidth: tuiConfigSchemaFields.questionDialogWidth,
- questionDialogMaxHeight: tuiConfigSchemaFields.questionDialogMaxHeight,
- modelDialogWidth: tuiConfigSchemaFields.modelDialogWidth,
- modelDialogMaxHeight: tuiConfigSchemaFields.modelDialogMaxHeight,
- fileSearchMaxResults: tuiConfigSchemaFields.fileSearchMaxResults,
- fileSearchMaxEntries: tuiConfigSchemaFields.fileSearchMaxEntries,
- fileSearchExcludedDirectories: tuiConfigSchemaFields.fileSearchExcludedDirectories,
- showHardwareCursor: tuiConfigSchemaFields.showHardwareCursor,
- theme: tuiConfigSchemaFields.theme,
- title: tuiConfigSchemaFields.title,
- })
- /** Fully defaulted TUI theme settings. */
- export interface ResolvedTuiThemeConfig {
- color: boolean
- truecolor: boolean
- leftPrompt: string
- rightPrompt: string
- inputPrompt: string
- inputPlaceholder: string
- }
- /** Fully defaulted TUI presentation settings. */
- export interface ResolvedTuiConfig {
- showReasoning: boolean
- maxToolOutputLines: number
- maxQuestionOptions: number
- maxModelOptions: number
- maxResumeOptions: number
- questionDialogWidth: number
- questionDialogMaxHeight: number
- modelDialogWidth: number
- modelDialogMaxHeight: number
- fileSearchMaxResults: number
- fileSearchMaxEntries: number
- fileSearchExcludedDirectories: string[]
- showHardwareCursor: boolean
- theme: ResolvedTuiThemeConfig
- title: string
- }
- /**
- * Apply direct-call defaults after Loader schema validation has normally run.
- *
- * @param config - Deployment-provided terminal presentation settings.
- * @returns Complete settings consumed by the TUI renderer.
- */
- export function resolveTuiConfig(config: TuiConfig | undefined): ResolvedTuiConfig {
- return {
- showReasoning: config?.showReasoning ?? true,
- maxToolOutputLines: config?.maxToolOutputLines ?? 6,
- maxQuestionOptions: config?.maxQuestionOptions ?? 8,
- maxModelOptions: config?.maxModelOptions ?? 8,
- maxResumeOptions: config?.maxResumeOptions ?? 8,
- questionDialogWidth: config?.questionDialogWidth ?? 200,
- questionDialogMaxHeight: config?.questionDialogMaxHeight ?? 20,
- modelDialogWidth: config?.modelDialogWidth ?? 76,
- modelDialogMaxHeight: config?.modelDialogMaxHeight ?? 20,
- fileSearchMaxResults: config?.fileSearchMaxResults ?? DEFAULT_FILE_SEARCH_MAX_RESULTS,
- fileSearchMaxEntries: config?.fileSearchMaxEntries ?? DEFAULT_FILE_SEARCH_MAX_ENTRIES,
- fileSearchExcludedDirectories: [...(config?.fileSearchExcludedDirectories ?? DEFAULT_FILE_SEARCH_EXCLUDED_DIRECTORIES)],
- showHardwareCursor: config?.showHardwareCursor ?? false,
- theme: {
- color: config?.theme?.color ?? true,
- truecolor: config?.theme?.truecolor ?? false,
- leftPrompt: config?.theme?.leftPrompt ?? DEFAULT_LEFT_PROMPT,
- rightPrompt: config?.theme?.rightPrompt ?? DEFAULT_RIGHT_PROMPT,
- inputPrompt: config?.theme?.inputPrompt ?? DEFAULT_INPUT_PROMPT,
- inputPlaceholder: config?.theme?.inputPlaceholder ?? DEFAULT_INPUT_PLACEHOLDER,
- },
- title: config?.title ?? 'DeepSeek Harness',
- }
- }
|