Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 38 additions & 7 deletions docs/skills-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,27 +96,58 @@ AI 在调用 Skill 时遵循以下规范:

```json
{
"kind": "choice_or_text",
"prompt": "请选择下一步操作",
"options": [
{"value": "a", "label": "方案 A"},
{"value": "b", "label": "方案 B"}
{"value": "a", "label": "方案 A", "description": "适合风险较低、改动较小的情况"},
{"value": "b", "label": "方案 B", "description": "适合需要更完整验证的情况"}
],
"default": "a",
"title": "选择",
"allow_cancel": true,
"allow_custom_input": true,
"custom_label": "其他(自行输入)",
"custom_prompt": "请输入自定义内容"
"custom": {
"label": "其他(自行输入)",
"placeholder": "请输入自定义内容"
}
}
```

推荐约定:

- `single_select`:只能选择预设项,不要传 `custom`
- `text_input`:只允许自由输入,不要传 `options`
- `choice_or_text`:既给 `options`,也给 `custom`,用于“候选项可能不完整”的场景

### ask_user 返回

- 用户选中某项:返回 JSON(`status=selected`)
- 用户选中某项:返回结构化结果(`status=selected`),并保留选中的 value/label
- 用户输入自定义内容:返回结构化结果(`status=custom`),并保留输入文本;可通过 `answer_type=text` 区分于预设选项
- 用户取消或交互不可用:任务会暂停并提示用户继续方式。你可以:
- 直接回复选项 value/编号/文字
- 输入 `; 使用默认继续`(或 `; continue with default`)明确使用默认值继续
- 若启用 `allow_custom_input`,UI 会提供“自定义输入”行,用户可直接输入内容并回车,返回 `status=custom`
- 若使用 `choice_or_text`,会显示支持自定义输入的对话框;用户可直接输入内容并回车,返回 `status=custom`
- 若为选项提供 `description`,UI 和暂停提示会把说明展示在选项下方

### 推荐调用示例

```json
{
"kind": "choice_or_text",
"prompt": "请选择一个水果,或输入列表中没有的水果",
"title": "水果选择",
"options": [
{"value": "apple", "label": "苹果"},
{"value": "banana", "label": "香蕉"},
{"value": "orange", "label": "橙子"}
],
"default": "apple",
"custom": {
"label": "其他水果",
"placeholder": "输入自定义水果名称"
},
"allow_cancel": true
}
```

## 开发新 Skill

Expand Down
4 changes: 0 additions & 4 deletions src/aish/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,6 @@ class TUISettings(BaseModel):
)
show_time: bool = Field(default=True, description="Show time in status bar")
show_cwd: bool = Field(default=True, description="Show current directory in status bar")
inline_ui: bool = Field(
default=True,
description="Use inline UI for selections (ask_user) at bottom of screen",
)


class ConfigModel(BaseModel):
Expand Down
4 changes: 2 additions & 2 deletions src/aish/i18n/de-DE.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ shell:
ask_user:
title: "Option auswählen"
custom_label: "Benutzerdefiniert:"
hint_select: "↑/↓ zum Bewegen • Enter zum Bestätigen • Esc zum Abbrechen"
hint_custom: "Zum Eingeben tippen • Enter zum Bestätigen • Tab zu den Optionen • Esc zum Abbrechen"
hint_select: "Enter zum Auswählen · ↑/↓ zum Navigieren · Esc zum Abbrechen"
hint_custom: "Enter zum Auswählen · ↑/↓ zum Navigieren · Esc zum Abbrechen"
paused:
title: "⏸ Benutzereingabe erforderlich (Aufgabe pausiert)"
prompt: "Frage: {prompt}"
Expand Down
6 changes: 3 additions & 3 deletions src/aish/i18n/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -298,15 +298,15 @@ shell:
ask_user:
title: "Select an option"
custom_label: "Custom:"
hint_select: "↑/↓ to move • Enter to confirm • Esc to cancel"
hint_custom: "Type to input custom value • Enter to confirm • Tab to options • Esc to cancel"
hint_select: "Enter to confirm · ↑/↓ to navigate · Esc to cancel"
hint_custom: "Enter to confirm · ↑/↓ to navigate · Esc to cancel"
paused:
title: "⏸ User input required (task paused)"
prompt: "Question: {prompt}"
reason: "Reason: {reason}"
options_header: "Options:"
custom_input: "You can also reply with any custom value."
how_to: "Reply with an option value (or number), or type `; continue with default` (default: {default})."
how_to: "Reply with an option value (or number), or type `; continue with default` (default: {default}). Option descriptions are shown beneath each choice when available."

diagnose_cancelled: " └─ ❌ System diagnosis cancelled"

Expand Down
4 changes: 2 additions & 2 deletions src/aish/i18n/es-ES.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ shell:
ask_user:
title: "Selecciona una opción"
custom_label: "Personalizado:"
hint_select: "↑/↓ para moverte • Enter para confirmar • Esc para cancelar"
hint_custom: "Escribe para introducir un valor • Enter para confirmar • Tab para ir a las opciones • Esc para cancelar"
hint_select: "Enter para elegir · ↑/↓ para navegar · Esc para cancelar"
hint_custom: "Enter para elegir · ↑/↓ para navegar · Esc para cancelar"
paused:
title: "⏸ Se requiere entrada del usuario (tarea en pausa)"
prompt: "Pregunta: {prompt}"
Expand Down
4 changes: 2 additions & 2 deletions src/aish/i18n/fr-FR.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ shell:
ask_user:
title: "Selectionnez une option"
custom_label: "Personnalise :"
hint_select: "↑/↓ pour se deplacer • Enter pour confirmer • Esc pour annuler"
hint_custom: "Tapez pour saisir une valeur • Enter pour confirmer • Tab pour aller aux options • Esc pour annuler"
hint_select: "Entree pour choisir · ↑/↓ pour naviguer · Esc pour annuler"
hint_custom: "Entree pour choisir · ↑/↓ pour naviguer · Esc pour annuler"
paused:
title: "⏸ Saisie utilisateur requise (tache en pause)"
prompt: "Question : {prompt}"
Expand Down
4 changes: 2 additions & 2 deletions src/aish/i18n/ja-JP.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ shell:
ask_user:
title: "オプションを選択"
custom_label: "カスタム:"
hint_select: "↑/↓ で移動 • Enter で確定 • Esc でキャンセル"
hint_custom: "入力して値を指定 • Enter で確定 • Tab で選択肢へ移動 • Esc でキャンセル"
hint_select: "Enter で選択 ・ ↑/↓ で移動 Esc でキャンセル"
hint_custom: "Enter で選択 ・ ↑/↓ で移動 ・ Esc でキャンセル"
paused:
title: "⏸ ユーザー入力が必要です(タスクは一時停止中)"
prompt: "質問: {prompt}"
Expand Down
6 changes: 3 additions & 3 deletions src/aish/i18n/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -298,15 +298,15 @@ shell:
ask_user:
title: "请选择"
custom_label: "自定义:"
hint_select: "↑/↓ 选择 • Enter 确认 • Esc 取消"
hint_custom: "直接输入自定义内容 • Enter 确认 • Tab 切换选项 • Esc 取消"
hint_select: "按 Enter 键选择 · 按 ↑/↓ 键导航 · 按 Esc 键取消"
hint_custom: "Enter 键选择 · 按 ↑/↓ 键导航 · 按 Esc 键取消"
paused:
title: "⏸ 需要你的选择(任务已暂停)"
prompt: "问题:{prompt}"
reason: "原因:{reason}"
options_header: "可选项:"
custom_input: "你也可以直接回复任意自定义内容。"
how_to: "你可以直接回复选项 value(或编号),或输入 `; 使用默认继续` / `; continue with default`(默认:{default})。"
how_to: "你可以直接回复选项 value(或编号),或输入 `; 使用默认继续` / `; continue with default`(默认:{default})。如有选项说明,会显示在选项下方。"

diagnose_cancelled: " └─ ❌ 系统诊断已取消"

Expand Down
37 changes: 37 additions & 0 deletions src/aish/interaction/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from __future__ import annotations

from .ask_user import (
apply_interaction_response_to_data,
AskUserRequestBuilder,
AskUserInteractionAdapter,
)
from .models import (
InteractionAnswer,
InteractionAnswerType,
InteractionCustomConfig,
InteractionKind,
InteractionOption,
InteractionRequest,
InteractionResponse,
InteractionSource,
InteractionStatus,
InteractionValidation,
)
from .service import InteractionService

__all__ = [
"AskUserRequestBuilder",
"AskUserInteractionAdapter",
"apply_interaction_response_to_data",
"InteractionAnswer",
"InteractionAnswerType",
"InteractionCustomConfig",
"InteractionKind",
"InteractionOption",
"InteractionRequest",
"InteractionResponse",
"InteractionService",
"InteractionSource",
"InteractionStatus",
"InteractionValidation",
]
Loading
Loading