Files
deepseek-harness/docs/core-data-structures/user-interaction.zh.md
Ziya 5270dcd61d docs(i18n): core-data-structures and postmortem batch — 22 bilingual pairs
core-data-structures 18 篇(core.md 因超长仍在产出、随后补)、
postmortem 3 篇与 RFC 前门 README 配对;流水线 + 二遍校验产出。
生成文件 docs/rfc/INDEX.md(gen-rfc-index 产物)列入排除。中文侧
页内锚点统一指向英文侧锚名,满足配对门禁的链接目标一致规则。
2026-07-15 23:11:25 -07:00

3.3 KiB
Raw Blame History

用户交互

English | 中文

dsh-user-interaction 的用户交互 seam。它是工具或权限插件在需要人类回答后 agent 才能继续时所使用的提供方无关词汇。UI 表面提供活跃的 UserInteractionProviderdsh-stdio-demo 在 readline 中渲染问题,dsh-acp 将其映射为 ACP 表单引出。

源码:packages/ui/user-interaction/src/index.ts

问题选项

AskUserQuestionOption 是可选择项的形状。label 是面向用户的选项文字,同时也是模型侧选中后的值;description 是可选的 UI 辅助文字。

interface AskUserQuestionOption {
  /** User-facing label. */
  label: string
  /** Optional extra context rendered by capable UIs. */
  description?: string
}

问题条目

AskUserQuestionItem 是请求中的一个问题。模型提供一个稳定的 id,回答时原样回传,使批量问题可路由。

interface AskUserQuestionItem {
  /** Stable model-provided question id, echoed in the answer. */
  id: string
  /** The question to display. */
  question: string
  /** Optional short heading/group label. */
  header?: string
  /** Optional choices the UI can render as a menu. */
  options?: AskUserQuestionOption[]
  /** Whether more than one option may be selected. Defaults to single-select. */
  multiSelect?: boolean
}

提问请求

AskUserQuestionRequest 是跨包请求。questions 是数组,这样 UI 可以在一次流程中展示相关问题,同时为每个回答保留稳定的 id。

interface AskUserQuestionRequest {
  /** Questions to display. */
  questions: AskUserQuestionItem[]
  /** Calling agent, when the request came from an agent tool call. */
  agent?: Agent
  /** Abort signal for the owning tool/step. */
  signal?: AbortSignal
}

回答

提供方为每个已回答的问题 id 返回一条回答。selected 包含选中的选项 labelcustom 在用户输入了自由文本"其他"答案时携带该内容。当 custom 存在时,selected 为空;自定义文本是对选中项的覆盖,而非补充。

interface AskUserQuestionAnswerItem {
  /** The answered question id. */
  id: string
  /** Selected option labels. Empty when the answer is purely custom text. */
  selected: string[]
  /** Optional free-text "Other" answer. */
  custom?: string
}
interface AskUserQuestionAnswer {
  /** Structured answers keyed by question id. */
  answers: AskUserQuestionAnswerItem[]
}

提供方

同一上下文中只能有一个活跃的提供方。提供方注册与 effect 绑定,因此 HMR热模块替换或 dispose资源释放会移除活跃的 UI。

interface UserInteractionProvider {
  ask(request: AskUserQuestionRequest): Promise<AskUserQuestionAnswer>
}

错误

UserInteractionError 继承 HarnessError,因此 ctx.tools.execute() 会为面向模型的工具失败保留 { name, code },例如 EMPTY_QUESTIONSNO_PROVIDERASK_ABORTED 或 ACP 侧的取消。

class UserInteractionError extends HarnessError {
  constructor(message: string, code: string, options?: ErrorOptions) {
    super(message, code, options)
    this.name = 'UserInteractionError'
  }
}