@fadhelhaidar/pi-ask-user 0.0.0-stage → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE.md +43 -0
- package/README.md +111 -2
- package/dist/chunks/external-editor-5wd19nyg.js +51 -0
- package/dist/chunks/index-bx2tbz93.js +5 -0
- package/dist/chunks/index-x7fb685n.js +226 -0
- package/dist/chunks/questionnaire-session-gdq5zqtt.js +2190 -0
- package/dist/events.d.ts +53 -0
- package/dist/events.js +8 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +538 -0
- package/dist/locales/de.json +31 -0
- package/dist/locales/en.json +29 -0
- package/dist/locales/es.json +31 -0
- package/dist/locales/fr.json +31 -0
- package/dist/locales/pt-BR.json +31 -0
- package/dist/locales/pt.json +31 -0
- package/dist/locales/ru.json +31 -0
- package/dist/locales/uk.json +31 -0
- package/dist/locales/zh.json +33 -0
- package/docs/configuration.md +121 -0
- package/docs/hosts.md +97 -0
- package/docs/keyboard.md +115 -0
- package/docs/localization.md +87 -0
- package/docs/tool-schema.md +127 -0
- package/package.json +64 -4
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta.notes": "Auto-translated draft. Native-speaker review welcome via PR. TUI symbols (↑/↓, ⚠) and key names (Enter, Esc, Tab, Space, n, Ctrl+G, Ctrl+U) are universal CLI conventions and stay untranslated.",
|
|
3
|
+
|
|
4
|
+
"sentinel.other": "Escribe algo.",
|
|
5
|
+
"sentinel.next": "Siguiente",
|
|
6
|
+
|
|
7
|
+
"submit.label": "Enviar respuestas",
|
|
8
|
+
"submit.cancel": "Cancelar",
|
|
9
|
+
|
|
10
|
+
"hint.enter": "Enter para seleccionar",
|
|
11
|
+
"hint.navigate": "↑/↓ para navegar",
|
|
12
|
+
"hint.newline": "Mayús+Enter para nueva línea",
|
|
13
|
+
"hint.clear": "Ctrl+U para borrar",
|
|
14
|
+
"hint.toggle": "Espacio para alternar",
|
|
15
|
+
"hint.notes": "n para añadir notas",
|
|
16
|
+
"hint.tab": "Tab para cambiar de pregunta",
|
|
17
|
+
"hint.cancel": "Esc para cancelar",
|
|
18
|
+
|
|
19
|
+
"review.heading": "Revisa tus respuestas",
|
|
20
|
+
"review.ready": "¿Listo para enviar tus respuestas?",
|
|
21
|
+
"review.incomplete": "⚠ Responde las preguntas restantes antes de enviar:",
|
|
22
|
+
|
|
23
|
+
"preview.no_preview": "Vista previa no disponible",
|
|
24
|
+
"preview.notes_affordance": "Notas: pulsa n para añadir notas",
|
|
25
|
+
"notes.header": "Notas:",
|
|
26
|
+
|
|
27
|
+
"editor.failed": "Error del editor externo",
|
|
28
|
+
|
|
29
|
+
"rpc.multi_instructions": "Introduce los números de todas las opciones que apliquen, separados por comas (p. ej. \"1,3\"), o escribe una respuesta propia como texto.",
|
|
30
|
+
"rpc.custom_answer_title": "Escribe tu respuesta:"
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta.notes": "Auto-translated draft. Native-speaker review welcome via PR. TUI symbols (↑/↓, ⚠) and key names (Enter, Esc, Tab, Space, n, Ctrl+G, Ctrl+U) are universal CLI conventions and stay untranslated.",
|
|
3
|
+
|
|
4
|
+
"sentinel.other": "Écrivez quelque chose.",
|
|
5
|
+
"sentinel.next": "Suivant",
|
|
6
|
+
|
|
7
|
+
"submit.label": "Envoyer les réponses",
|
|
8
|
+
"submit.cancel": "Annuler",
|
|
9
|
+
|
|
10
|
+
"hint.enter": "Entrée pour sélectionner",
|
|
11
|
+
"hint.navigate": "↑/↓ pour naviguer",
|
|
12
|
+
"hint.newline": "Maj+Entrée pour une nouvelle ligne",
|
|
13
|
+
"hint.clear": "Ctrl+U pour effacer",
|
|
14
|
+
"hint.toggle": "Espace pour basculer",
|
|
15
|
+
"hint.notes": "n pour ajouter des notes",
|
|
16
|
+
"hint.tab": "Tab pour changer de question",
|
|
17
|
+
"hint.cancel": "Échap pour annuler",
|
|
18
|
+
|
|
19
|
+
"review.heading": "Vérifiez vos réponses",
|
|
20
|
+
"review.ready": "Prêt à envoyer vos réponses ?",
|
|
21
|
+
"review.incomplete": "⚠ Répondez aux questions restantes avant d'envoyer :",
|
|
22
|
+
|
|
23
|
+
"preview.no_preview": "Aucun aperçu disponible",
|
|
24
|
+
"preview.notes_affordance": "Notes : appuyez sur n pour ajouter des notes",
|
|
25
|
+
"notes.header": "Notes :",
|
|
26
|
+
|
|
27
|
+
"editor.failed": "Échec de l’éditeur externe",
|
|
28
|
+
|
|
29
|
+
"rpc.multi_instructions": "Saisissez les numéros de toutes les options applicables, séparés par des virgules (p. ex. « 1,3 »), ou tapez une réponse libre en texte.",
|
|
30
|
+
"rpc.custom_answer_title": "Tapez votre réponse :"
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta.notes": "Auto-translated draft. Native-speaker review welcome via PR. TUI symbols (↑/↓, ⚠) and key names (Enter, Esc, Tab, Space, n, Ctrl+G, Ctrl+U) are universal CLI conventions and stay untranslated.",
|
|
3
|
+
|
|
4
|
+
"sentinel.other": "Digite algo.",
|
|
5
|
+
"sentinel.next": "Próximo",
|
|
6
|
+
|
|
7
|
+
"submit.label": "Enviar respostas",
|
|
8
|
+
"submit.cancel": "Cancelar",
|
|
9
|
+
|
|
10
|
+
"hint.enter": "Enter para selecionar",
|
|
11
|
+
"hint.navigate": "↑/↓ para navegar",
|
|
12
|
+
"hint.newline": "Shift+Enter para nova linha",
|
|
13
|
+
"hint.clear": "Ctrl+U para limpar",
|
|
14
|
+
"hint.toggle": "Espaço para alternar",
|
|
15
|
+
"hint.notes": "n para adicionar notas",
|
|
16
|
+
"hint.tab": "Tab para trocar de pergunta",
|
|
17
|
+
"hint.cancel": "Esc para cancelar",
|
|
18
|
+
|
|
19
|
+
"review.heading": "Revise suas respostas",
|
|
20
|
+
"review.ready": "Pronto para enviar suas respostas?",
|
|
21
|
+
"review.incomplete": "⚠ Responda as perguntas restantes antes de enviar:",
|
|
22
|
+
|
|
23
|
+
"preview.no_preview": "Pré-visualização indisponível",
|
|
24
|
+
"preview.notes_affordance": "Notas: pressione n para adicionar notas",
|
|
25
|
+
"notes.header": "Notas:",
|
|
26
|
+
|
|
27
|
+
"editor.failed": "Falha no editor externo",
|
|
28
|
+
|
|
29
|
+
"rpc.multi_instructions": "Digite os números de todas as opções aplicáveis, separados por vírgula (ex.: \"1,3\") ou digite uma resposta própria em texto.",
|
|
30
|
+
"rpc.custom_answer_title": "Digite sua resposta:"
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta.notes": "European Portuguese (Portugal). Auto-translated draft. Native-speaker review welcome via PR. Distinct from pt-BR (Brasil): differs in lexicon (utilizador / você), conjugation, and some terms. TUI symbols (↑/↓, ⚠) and key names (Enter, Esc, Tab, Space, n, Ctrl+G, Ctrl+U) are universal CLI conventions and stay untranslated.",
|
|
3
|
+
|
|
4
|
+
"sentinel.other": "Escreva algo.",
|
|
5
|
+
"sentinel.next": "Seguinte",
|
|
6
|
+
|
|
7
|
+
"submit.label": "Enviar respostas",
|
|
8
|
+
"submit.cancel": "Cancelar",
|
|
9
|
+
|
|
10
|
+
"hint.enter": "Enter para selecionar",
|
|
11
|
+
"hint.navigate": "↑/↓ para navegar",
|
|
12
|
+
"hint.newline": "Shift+Enter para nova linha",
|
|
13
|
+
"hint.clear": "Ctrl+U para limpar",
|
|
14
|
+
"hint.toggle": "Espaço para alternar",
|
|
15
|
+
"hint.notes": "n para adicionar notas",
|
|
16
|
+
"hint.tab": "Tab para mudar de pergunta",
|
|
17
|
+
"hint.cancel": "Esc para cancelar",
|
|
18
|
+
|
|
19
|
+
"review.heading": "Reveja as suas respostas",
|
|
20
|
+
"review.ready": "Pronto para enviar as suas respostas?",
|
|
21
|
+
"review.incomplete": "⚠ Responda às perguntas restantes antes de enviar:",
|
|
22
|
+
|
|
23
|
+
"preview.no_preview": "Pré-visualização indisponível",
|
|
24
|
+
"preview.notes_affordance": "Notas: prima n para adicionar notas",
|
|
25
|
+
"notes.header": "Notas:",
|
|
26
|
+
|
|
27
|
+
"editor.failed": "Falha no editor externo",
|
|
28
|
+
|
|
29
|
+
"rpc.multi_instructions": "Introduza os números de todas as opções aplicáveis, separados por vírgulas (ex.: \"1,3\") ou escreva uma resposta própria em texto.",
|
|
30
|
+
"rpc.custom_answer_title": "Escreva a sua resposta:"
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta.notes": "Auto-translated draft. Native-speaker review welcome via PR. TUI symbols (↑/↓, ⚠) and key names (Enter, Esc, Tab, Space, n, Ctrl+G, Ctrl+U) are universal CLI conventions and stay untranslated.",
|
|
3
|
+
|
|
4
|
+
"sentinel.other": "Введите что-нибудь.",
|
|
5
|
+
"sentinel.next": "Далее",
|
|
6
|
+
|
|
7
|
+
"submit.label": "Отправить ответы",
|
|
8
|
+
"submit.cancel": "Отмена",
|
|
9
|
+
|
|
10
|
+
"hint.enter": "Enter — выбрать",
|
|
11
|
+
"hint.navigate": "↑/↓ — навигация",
|
|
12
|
+
"hint.newline": "Shift+Enter — новая строка",
|
|
13
|
+
"hint.clear": "Ctrl+U — очистить",
|
|
14
|
+
"hint.toggle": "Space — переключить",
|
|
15
|
+
"hint.notes": "n — добавить заметки",
|
|
16
|
+
"hint.tab": "Tab — следующий вопрос",
|
|
17
|
+
"hint.cancel": "Esc — отменить",
|
|
18
|
+
|
|
19
|
+
"review.heading": "Проверьте свои ответы",
|
|
20
|
+
"review.ready": "Готовы отправить ответы?",
|
|
21
|
+
"review.incomplete": "⚠ Ответьте на оставшиеся вопросы перед отправкой:",
|
|
22
|
+
|
|
23
|
+
"preview.no_preview": "Предпросмотр недоступен",
|
|
24
|
+
"preview.notes_affordance": "Заметки: нажмите n, чтобы добавить заметки",
|
|
25
|
+
"notes.header": "Заметки:",
|
|
26
|
+
|
|
27
|
+
"editor.failed": "Ошибка внешнего редактора",
|
|
28
|
+
|
|
29
|
+
"rpc.multi_instructions": "Введите номера всех подходящих вариантов через запятую (например, \"1,3\") или введите свой ответ текстом.",
|
|
30
|
+
"rpc.custom_answer_title": "Введите свой ответ:"
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta.notes": "Auto-translated draft. Native-speaker review welcome via PR. TUI symbols (↑/↓, ⚠) and key names (Enter, Esc, Tab, Space, n, Ctrl+G, Ctrl+U) are universal CLI conventions and stay untranslated.",
|
|
3
|
+
|
|
4
|
+
"sentinel.other": "Введіть щось.",
|
|
5
|
+
"sentinel.next": "Далі",
|
|
6
|
+
|
|
7
|
+
"submit.label": "Надіслати відповіді",
|
|
8
|
+
"submit.cancel": "Скасувати",
|
|
9
|
+
|
|
10
|
+
"hint.enter": "Enter — обрати",
|
|
11
|
+
"hint.navigate": "↑/↓ — навігація",
|
|
12
|
+
"hint.newline": "Shift+Enter — новий рядок",
|
|
13
|
+
"hint.clear": "Ctrl+U — очистити",
|
|
14
|
+
"hint.toggle": "Space — перемкнути",
|
|
15
|
+
"hint.notes": "n — додати нотатки",
|
|
16
|
+
"hint.tab": "Tab — наступне питання",
|
|
17
|
+
"hint.cancel": "Esc — скасувати",
|
|
18
|
+
|
|
19
|
+
"review.heading": "Перегляньте свої відповіді",
|
|
20
|
+
"review.ready": "Готові надіслати відповіді?",
|
|
21
|
+
"review.incomplete": "⚠ Дайте відповіді на решту питань перед надсиланням:",
|
|
22
|
+
|
|
23
|
+
"preview.no_preview": "Попередній перегляд недоступний",
|
|
24
|
+
"preview.notes_affordance": "Нотатки: натисніть n, щоб додати нотатки",
|
|
25
|
+
"notes.header": "Нотатки:",
|
|
26
|
+
|
|
27
|
+
"editor.failed": "Помилка зовнішнього редактора",
|
|
28
|
+
|
|
29
|
+
"rpc.multi_instructions": "Введіть номери всіх відповідних варіантів через кому (наприклад, \"1,3\") або введіть власну відповідь текстом.",
|
|
30
|
+
"rpc.custom_answer_title": "Введіть свою відповідь:"
|
|
31
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta.notes": "中文翻译。欢迎中文母语者通过 PR 审校。TUI 符号(↑/↓、⚠)为通用 CLI 约定,保持原文不译。Enter、Space 采用中文惯用说法(回车、空格);Esc、Tab、Ctrl、n 等保留原文。",
|
|
3
|
+
|
|
4
|
+
"sentinel.other": "输入内容",
|
|
5
|
+
"sentinel.next": "下一个",
|
|
6
|
+
|
|
7
|
+
"submit.label": "提交答案",
|
|
8
|
+
"submit.cancel": "取消",
|
|
9
|
+
|
|
10
|
+
"hint.enter": "回车选择",
|
|
11
|
+
"hint.navigate": "↑/↓ 导航",
|
|
12
|
+
"hint.newline": "Shift+Enter 换行",
|
|
13
|
+
"hint.clear": "Ctrl+U 清空",
|
|
14
|
+
"hint.toggle": "空格切换",
|
|
15
|
+
"hint.notes": "按 n 添加备注",
|
|
16
|
+
"hint.tab": "Tab 切换问题",
|
|
17
|
+
"hint.collapse": "{key} 折叠",
|
|
18
|
+
"hint.expand_line": "{key} 展开 · Esc 取消",
|
|
19
|
+
"hint.cancel": "Esc 取消",
|
|
20
|
+
|
|
21
|
+
"review.heading": "检查你的答案",
|
|
22
|
+
"review.ready": "准备提交答案了吗?",
|
|
23
|
+
"review.incomplete": "⚠ 提交前请先回答以下问题:",
|
|
24
|
+
|
|
25
|
+
"preview.no_preview": "暂无预览",
|
|
26
|
+
"preview.notes_affordance": "备注:按 n 添加",
|
|
27
|
+
"notes.header": "备注:",
|
|
28
|
+
|
|
29
|
+
"editor.failed": "外部编辑器启动失败",
|
|
30
|
+
|
|
31
|
+
"rpc.multi_instructions": "输入所有适用选项的编号,用逗号分隔(例如 \"1,3\"),或直接输入自定义回答。",
|
|
32
|
+
"rpc.custom_answer_title": "输入你的回答:"
|
|
33
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Every setting the package reads, where the file lives, and what happens when a value is
|
|
4
|
+
wrong.
|
|
5
|
+
|
|
6
|
+
## The config file
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
~/.config/rpiv-ask-user-question/config.json
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The file is optional — with no config at all, every setting takes its default. This
|
|
13
|
+
package only ever *reads* the file; it never creates, writes or chmods it, so its
|
|
14
|
+
permissions are whatever you give it.
|
|
15
|
+
|
|
16
|
+
A complete example:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"collapseKey": "alt+o",
|
|
21
|
+
"guidance": {
|
|
22
|
+
"description": "Ask the user structured questions whenever requirements are ambiguous.",
|
|
23
|
+
"promptSnippet": "Ask me before guessing on anything ambiguous",
|
|
24
|
+
"promptGuidelines": [
|
|
25
|
+
"Batch every clarifying question into one ask_user_question call.",
|
|
26
|
+
"Put your recommended option first and suffix it with (Recommended)."
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Where the file is looked up
|
|
33
|
+
|
|
34
|
+
1. `$XDG_CONFIG_HOME/rpiv-ask-user-question/config.json`, if `XDG_CONFIG_HOME` is set,
|
|
35
|
+
non-empty and absolute. A leading `~` is expanded first; a relative value is ignored.
|
|
36
|
+
Unset or ignored, the directory falls back to `~/.config`.
|
|
37
|
+
2. If that file does not exist, the legacy path `~/.config/rpiv-ask-user-question/config.json`
|
|
38
|
+
is read. This path deliberately ignores `XDG_CONFIG_HOME`, so an existing config keeps
|
|
39
|
+
working after you set the variable.
|
|
40
|
+
3. Neither present: all defaults.
|
|
41
|
+
|
|
42
|
+
If the XDG-path file exists, its result wins even when it is malformed — there is no
|
|
43
|
+
second chance at the legacy path.
|
|
44
|
+
|
|
45
|
+
### When the file is invalid
|
|
46
|
+
|
|
47
|
+
Malformed JSON is not fatal. The loader warns on stderr and continues with defaults:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
rpiv-config: invalid JSON at <path>, using default ({}) — <parser message>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Valid JSON that is not an object (a string, number, `null`, or an array) is rejected too,
|
|
54
|
+
falling back to defaults — but silently, with no warning. Individual keys with the wrong
|
|
55
|
+
type are likewise dropped back to their default without a warning.
|
|
56
|
+
|
|
57
|
+
## Settings
|
|
58
|
+
|
|
59
|
+
| Setting | What it does | Default |
|
|
60
|
+
| --- | --- | --- |
|
|
61
|
+
| `collapseKey` | Key that collapses and expands the dialog overlay. | `"ctrl+]"` |
|
|
62
|
+
| `guidance.description` | Full text of the tool description the model sees. Replaces the built-in default entirely — no merging. | built-in description |
|
|
63
|
+
| `guidance.promptSnippet` | One-line snippet describing the tool in the system prompt. | built-in snippet |
|
|
64
|
+
| `guidance.promptGuidelines` | List of usage guidelines given to the model. | 4 built-in guidelines |
|
|
65
|
+
|
|
66
|
+
### `collapseKey`
|
|
67
|
+
|
|
68
|
+
The value uses Pi's keybinding id format: zero or more distinct modifiers from `ctrl`,
|
|
69
|
+
`shift`, `alt`, `super`, joined by `+`, followed by a base key. Values are trimmed and
|
|
70
|
+
lowercased before matching.
|
|
71
|
+
|
|
72
|
+
The base key is either a single printable character from
|
|
73
|
+
`a-z 0-9 _ - ! @ # $ % ^ & * ( ) | ~ \` ' " : ; , . / < > ? [ ] { } = \`, or one of the
|
|
74
|
+
named keys `escape`, `esc`, `enter`, `return`, `tab`, `space`, `backspace`, `delete`,
|
|
75
|
+
`insert`, `clear`, `home`, `end`, `pageup`, `pagedown`, `up`, `down`, `left`, `right`,
|
|
76
|
+
`f1`–`f12`.
|
|
77
|
+
|
|
78
|
+
Examples that work: `"ctrl+]"`, `"alt+o"`, `"ctrl+shift+h"`, `"f9"`, `"ctrl+}"`.
|
|
79
|
+
|
|
80
|
+
Set `"off"` (any casing) to disable the collapse shortcut entirely — no raw terminal
|
|
81
|
+
listener is registered in that case.
|
|
82
|
+
|
|
83
|
+
A spec that does not match the grammar is rejected and the default is used. This is
|
|
84
|
+
strict on purpose: Pi's parser takes the last `+`-separated part as the key and ignores
|
|
85
|
+
unknown parts, so a typo like `"ctr+]"` would otherwise silently capture every bare `]`
|
|
86
|
+
keypress at the terminal level.
|
|
87
|
+
|
|
88
|
+
The footer hint inside the dialog names whatever key you configure (`Alt+O to collapse`
|
|
89
|
+
for `"alt+o"`), as do the collapsed one-line footer and the one-shot notification shown
|
|
90
|
+
when the dialog is first hidden. With `"off"` the collapse hint is dropped from the
|
|
91
|
+
footer entirely, since no shortcut can fire.
|
|
92
|
+
|
|
93
|
+
### `guidance.description`, `guidance.promptSnippet` and `guidance.promptGuidelines`
|
|
94
|
+
|
|
95
|
+
`guidance.description` replaces the entire built-in description Pi registers for the
|
|
96
|
+
`ask_user_question` tool — the text the model reads when deciding how to use it. There is
|
|
97
|
+
no merging: a valid value wins wholesale. It is used only when it is a non-empty string;
|
|
98
|
+
anything else falls back to the built-in default. Like the other guidance fields it is read
|
|
99
|
+
once, when the extension registers the tool, so changes take effect on the next Pi restart.
|
|
100
|
+
|
|
101
|
+
These replace the text Pi puts in the system prompt about when to reach for
|
|
102
|
+
`ask_user_question`. Use them to make the model ask more or less often, or to enforce a
|
|
103
|
+
house style for options.
|
|
104
|
+
|
|
105
|
+
`promptSnippet` is used only when it is a non-empty string. `promptGuidelines` is used
|
|
106
|
+
only when it is a non-empty array whose entries are all non-empty strings. Anything else
|
|
107
|
+
falls back to the built-in defaults. Both are read once, when the extension registers the
|
|
108
|
+
tool, so changes take effect on the next Pi restart.
|
|
109
|
+
|
|
110
|
+
## Environment variables
|
|
111
|
+
|
|
112
|
+
| Variable | Effect |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| `XDG_CONFIG_HOME` | Relocates the config directory, as described above. Must be absolute. |
|
|
115
|
+
|
|
116
|
+
`LANG` and `LC_ALL` influence the dialog language, but they are read by
|
|
117
|
+
[`@juicesharp/rpiv-i18n`](https://www.npmjs.com/package/@juicesharp/rpiv-i18n) rather than
|
|
118
|
+
by this package — see [localization.md](./localization.md).
|
|
119
|
+
|
|
120
|
+
No other environment variables are read. The package makes no model calls, so it needs no
|
|
121
|
+
API keys or model settings of its own.
|
package/docs/hosts.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Hosts and runtime behavior
|
|
2
|
+
|
|
3
|
+
Where the questionnaire renders, what it degrades to, and what happens when it cannot
|
|
4
|
+
render at all.
|
|
5
|
+
|
|
6
|
+
## Three environments
|
|
7
|
+
|
|
8
|
+
| Environment | What the model sees | What you see |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| Interactive terminal | `ask_user_question` in its tool list | The full tabbed TUI overlay |
|
|
11
|
+
| RPC / ACP host (VS Code pendant, Zed, Paseo) | `ask_user_question` in its tool list | A sequence of the host's own native select and input dialogs |
|
|
12
|
+
| Non-interactive run (no UI) | Nothing — the tool is removed | Nothing |
|
|
13
|
+
|
|
14
|
+
### Terminal attention
|
|
15
|
+
|
|
16
|
+
After UI availability and questionnaire validation succeed, the package emits exactly one standard terminal BEL (`\x07`) immediately before the interactive wait begins. The signal is sent to `stdout` only when `process.stdout.isTTY` is true, so redirected output and non-TTY RPC streams stay untouched. A TTY-backed RPC dialog walker receives the same signal as the TUI path.
|
|
17
|
+
|
|
18
|
+
The BEL is best effort: if the synchronous terminal write fails, the questionnaire continues and its existing prompt/blocked lifecycle and result envelope are unchanged. The terminal configuration decides whether the BEL is audible, visual, or ignored. No BEL is emitted for missing UI, invalid questionnaires, or a failed TUI session load.
|
|
19
|
+
|
|
20
|
+
### Non-interactive runs
|
|
21
|
+
|
|
22
|
+
A `before_agent_start` hook reconciles the active tool set against `ctx.hasUI` before every
|
|
23
|
+
turn. When there is no UI, `ask_user_question` is stripped from the list so the model never
|
|
24
|
+
sees a tool it cannot use — better than offering it and auto-declining every call. When UI
|
|
25
|
+
comes back, the tool is restored. The reconciler is idempotent and leaves sibling tools
|
|
26
|
+
untouched.
|
|
27
|
+
|
|
28
|
+
A second guard lives inside the tool handler as a one-turn backstop: if a call somehow
|
|
29
|
+
arrives without UI, it returns `error: "no_ui"` and the text
|
|
30
|
+
`Error: UI not available (running in non-interactive mode)`.
|
|
31
|
+
|
|
32
|
+
### RPC and ACP hosts
|
|
33
|
+
|
|
34
|
+
RPC hosts report `hasUI: true` because Pi's dialog sub-protocol works there, but custom
|
|
35
|
+
terminal UI does not render. The package detects this two ways: hosts that advertise
|
|
36
|
+
`ctx.mode === "rpc"` route straight to the dialog walker, skipping the TUI import
|
|
37
|
+
entirely, and older RPC builds are caught by a backstop when custom UI resolves without
|
|
38
|
+
rendering anything. Either path requires the host to expose both `select` and `input`.
|
|
39
|
+
|
|
40
|
+
The walker asks one question per dialog and returns exactly the same result envelope the
|
|
41
|
+
TUI produces. Trade-offs inherent to the native primitives:
|
|
42
|
+
|
|
43
|
+
- No side-by-side preview pane. Previews are folded into the dialog title instead,
|
|
44
|
+
truncated at 600 characters each.
|
|
45
|
+
- No tab bar and no Submit review tab — one dialog per question, in order.
|
|
46
|
+
- No notes. Both note kinds — per-question `n` on a question tab and global `n` on the
|
|
47
|
+
Submit tab — are terminal-only; the host's native `select` and `input` primitives carry
|
|
48
|
+
no note field.
|
|
49
|
+
- Multi-select is a free-text input: type the option numbers, comma-separated
|
|
50
|
+
(`1,3`). Any token that is not a valid option index is treated as a typed custom answer,
|
|
51
|
+
which is how the `Type something.` escape survives. An empty input commits an empty
|
|
52
|
+
selection, matching `Next` with nothing toggled.
|
|
53
|
+
- Dismissing any dialog cancels the whole questionnaire, mirroring `Esc` in the TUI.
|
|
54
|
+
|
|
55
|
+
If the host can render neither custom UI nor dialogs, the call returns
|
|
56
|
+
`error: "no_custom_ui"` with text telling the model the user never saw the questions and
|
|
57
|
+
that it should ask them as plain chat text instead — explicitly not a decline.
|
|
58
|
+
|
|
59
|
+
## Conditional surfaces
|
|
60
|
+
|
|
61
|
+
Some parts of the dialog exist only under the right conditions:
|
|
62
|
+
|
|
63
|
+
| Surface | Appears when |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| Tab bar and Submit tab | The call carries more than one question |
|
|
66
|
+
| `Next` row | The question is multi-select |
|
|
67
|
+
| `Type something.` row | Always |
|
|
68
|
+
| Side-by-side preview | An option carries a `preview`, and terminal and pane are both ≥ 100 columns |
|
|
69
|
+
| Preview pane at all | Single-select questions only |
|
|
70
|
+
| Collapse shortcut | `collapseKey` is not `"off"` |
|
|
71
|
+
| Full overlay hide on collapse | The host also exposes raw terminal input (the only path that can reopen a hidden overlay); without it, collapsing shrinks the dialog to a visible one-line row instead |
|
|
72
|
+
| Localized chrome | `@juicesharp/rpiv-i18n` is installed |
|
|
73
|
+
|
|
74
|
+
## Loading and startup cost
|
|
75
|
+
|
|
76
|
+
The dialog's render graph costs roughly 560 ms to import, so it is loaded lazily — on the
|
|
77
|
+
first tool call, not when the extension registers. To keep that first call fast and safe,
|
|
78
|
+
the graph is also pre-warmed in the background two seconds after startup. The pre-warm
|
|
79
|
+
timer is unref'd, so it never holds a process open, and a failed pre-warm is swallowed:
|
|
80
|
+
the first real call re-imports and reports properly.
|
|
81
|
+
|
|
82
|
+
The pre-warm exists for a specific failure. Pi's module loader registers a module in its
|
|
83
|
+
graph cache *before* evaluating it and does not evict it if evaluation throws. If your
|
|
84
|
+
package manager replaces the dependency store while Pi is running, one failed import can
|
|
85
|
+
poison the cache for the rest of the process. Evaluating the graph early, while the paths
|
|
86
|
+
Pi resolved at boot still exist, keeps it in memory for the process lifetime and makes
|
|
87
|
+
that unreachable.
|
|
88
|
+
|
|
89
|
+
When it does happen, you get a structured envelope rather than a raw `TypeError`:
|
|
90
|
+
|
|
91
|
+
| `error` | Meaning | Fix |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| `session_load_failed` | The dialog module could not be imported. | Repair the install if needed, then restart Pi. |
|
|
94
|
+
| `stale_module_cache` | The module cache went stale after an earlier failed import. | Restart Pi — this is unrecoverable in the running process. |
|
|
95
|
+
|
|
96
|
+
Both messages tell the model the questions were never shown and to ask them as plain chat
|
|
97
|
+
text instead of treating the failure as a decline.
|
package/docs/keyboard.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Keyboard and dialog layout
|
|
2
|
+
|
|
3
|
+
Every key the questionnaire dialog reacts to, the rows it appends for you, and how it
|
|
4
|
+
adapts to the size of your terminal.
|
|
5
|
+
|
|
6
|
+
## Keys
|
|
7
|
+
|
|
8
|
+
| Key | What it does | Where it applies |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| `↑` / `↓` | Move between rows. Wraps at both ends. | Option list, Submit picker |
|
|
11
|
+
| `Enter` | Toggle a multi-select checkbox (including custom text), confirm a single-select answer, close notes, or activate Next/Submit. | Everywhere |
|
|
12
|
+
| `Shift+Enter` | Insert a newline. | `Type something.` input, notes editor |
|
|
13
|
+
| `Esc` | Cancel the whole questionnaire. | Everywhere except the notes editor, where it closes notes |
|
|
14
|
+
| `Tab` / `Shift+Tab` | Next / previous tab, wrapping. `→` / `←` do the same. | Multi-question dialogs only |
|
|
15
|
+
| `Space` | Insert a normal space while typing; never toggle a checkbox. | Text inputs only |
|
|
16
|
+
| `n` | Open the notes editor for the focused question — or, on the Submit tab, the global note for the whole questionnaire. | Every question tab; the Submit tab in multi-question dialogs |
|
|
17
|
+
| `Ctrl+G` | Open Pi's configured external editor with the current custom-answer draft. | `Type something.` input |
|
|
18
|
+
| `Ctrl+U` | Clear the current custom-answer draft. | `Type something.` input |
|
|
19
|
+
| `Ctrl+]` | Collapse or expand the dialog. Configurable via `collapseKey`. | Everywhere, including while collapsed |
|
|
20
|
+
|
|
21
|
+
The table names the default keys; the dialog actually follows your Pi keybindings.
|
|
22
|
+
Confirm listens to both `tui.select.confirm` and `tui.input.submit`, and a key bound to
|
|
23
|
+
`tui.input.newLine` always inserts a newline even if it also matches confirm. So a
|
|
24
|
+
Slack-style configuration — `enter` folded into `tui.input.newLine`, submit moved to
|
|
25
|
+
`ctrl+enter` — keeps working: `enter` breaks lines, and your submit key confirms
|
|
26
|
+
everywhere `Enter` does.
|
|
27
|
+
|
|
28
|
+
In a multi-select question, `Enter` is the only checkbox toggle key. It does not
|
|
29
|
+
submit or move focus. Committing the question means focusing `Next`/`Submit` and
|
|
30
|
+
pressing `Enter`. Space does nothing outside text inputs.
|
|
31
|
+
|
|
32
|
+
Focusing the multi-select `Type something.` row allows immediate typing. Enter
|
|
33
|
+
selects or deselects its checkbox while retaining the draft and editor focus.
|
|
34
|
+
Space inserts an ordinary space. Typing or leaving the row does not automatically
|
|
35
|
+
select it; press Enter to include it. Unchecking keeps the text available to edit
|
|
36
|
+
or reselect later, but excludes it from the submitted answer.
|
|
37
|
+
|
|
38
|
+
## The rows the dialog adds
|
|
39
|
+
|
|
40
|
+
| Row | Label | Appended to |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| Custom answer | `Type something.` | Every question — single-select and multi-select, with or without previews |
|
|
43
|
+
| Commit | `Next` | Multi-select questions only |
|
|
44
|
+
|
|
45
|
+
Focusing `Type something.` switches the row into an inline multiline editor in
|
|
46
|
+
both single-select and multi-select questions. In preview mode it expands to the full pane width while you type, so a long custom answer is not
|
|
47
|
+
squeezed into the narrow options column. `Shift+Enter` inserts a line break; vertical
|
|
48
|
+
arrows move between lines and return to row navigation at the draft's top and bottom.
|
|
49
|
+
The draft replaces the static row label while you browse other options and is isolated
|
|
50
|
+
per question. `Ctrl+G` round-trips it through Pi's configured external editor; `Ctrl+U`
|
|
51
|
+
clears it, while `Esc` remains the explicit way to cancel the questionnaire. Confirming
|
|
52
|
+
it produces an answer of `kind: "custom"` in single-select mode. In multi-select
|
|
53
|
+
mode, checked custom text is included in the `answer` field of a `kind: "multi"`
|
|
54
|
+
answer alongside predefined `selected` labels; unchecked text remains only a draft
|
|
55
|
+
and is not submitted.
|
|
56
|
+
|
|
57
|
+
Both labels are reserved — the model cannot author an option that collides with them.
|
|
58
|
+
Both localize with the rest of the UI chrome; the reserved-label check always compares
|
|
59
|
+
against the canonical English strings.
|
|
60
|
+
|
|
61
|
+
## Notes
|
|
62
|
+
|
|
63
|
+
`n` opens a notes editor on any question tab, whether the question is single- or
|
|
64
|
+
multi-select and whether or not its options carry previews. Notes are stored in a
|
|
65
|
+
side-band keyed by tab index, not inside the answer, so writing a note does not mark a
|
|
66
|
+
question as answered — the Submit tab still lists it as outstanding. The note merges into
|
|
67
|
+
the answer when you confirm it, and reaches the model as `user notes: <text>`.
|
|
68
|
+
|
|
69
|
+
On the Submit tab, `n` opens the global note editor instead — one note covering the whole
|
|
70
|
+
questionnaire. It lives outside every answer, so it survives tab switches and never marks
|
|
71
|
+
a question as answered; it reaches the model as `global note: <text>`, and submitting with
|
|
72
|
+
nothing but a global note still returns an answered result rather than a decline.
|
|
73
|
+
|
|
74
|
+
Inside the editor, `Shift+Enter` inserts a newline, while `Esc` and `Enter` close it; other
|
|
75
|
+
keystrokes edit the buffer, so `n` types an `n`. Pasted line breaks are preserved.
|
|
76
|
+
|
|
77
|
+
## Collapse mode
|
|
78
|
+
|
|
79
|
+
`Ctrl+]` gets the dialog out of the way: the overlay is marked hidden in Pi's overlay
|
|
80
|
+
stack and shrinks to a single dim hint row, so the transcript it was covering becomes
|
|
81
|
+
readable and chat scrolling resumes. Press the same key to bring the questionnaire back
|
|
82
|
+
with your answers intact. The first time you collapse, Pi notifies you with the key to
|
|
83
|
+
press — that message names your configured key.
|
|
84
|
+
|
|
85
|
+
Because Pi routes no input to a hidden overlay, the collapse key is additionally captured
|
|
86
|
+
at the raw terminal level. It only acts when the questionnaire is hidden or focused, so a
|
|
87
|
+
different overlay on top of it (for example `/btw`) keeps its keystrokes.
|
|
88
|
+
|
|
89
|
+
While collapsed, every keystroke other than cancel is ignored, so you cannot mutate
|
|
90
|
+
answers you cannot see.
|
|
91
|
+
|
|
92
|
+
The default `ctrl+]` is free in Terminal.app, iTerm2, Warp, tmux, zellij and screen. On
|
|
93
|
+
keyboard layouts where `]` sits on the shifted layer — Latin American `es-AR` / `es-MX`,
|
|
94
|
+
among others — set a different `collapseKey`, or `"off"` to disable the shortcut.
|
|
95
|
+
|
|
96
|
+
## Layout
|
|
97
|
+
|
|
98
|
+
Options render in a vertical list. When any option in a single-select question carries a
|
|
99
|
+
`preview`, the dialog splits into a side-by-side layout with the option list on the left
|
|
100
|
+
and a bordered monospace preview box on the right — but only when both the terminal and
|
|
101
|
+
the dialog pane are at least 100 columns wide. Below that, the preview stacks underneath
|
|
102
|
+
the options instead.
|
|
103
|
+
|
|
104
|
+
When the dialog is taller than the terminal, the body scrolls between a sticky heading and
|
|
105
|
+
a sticky footer, and an overflow indicator shows which direction is clipped: `↑` for
|
|
106
|
+
content above, `↓` for content below, `↕` for both.
|
|
107
|
+
|
|
108
|
+
The footer hint line adapts to context — it drops the notes hint and appends the
|
|
109
|
+
`Shift+Enter` newline hint whenever a text editor has the keyboard, with `Ctrl+U` still at
|
|
110
|
+
the far right for custom answers. It adds the tab hint only in multi-question dialogs. The
|
|
111
|
+
Submit tab follows the same idiom: its bottom hint row sits below the picker and carries
|
|
112
|
+
an `n to add a note` part that gives way to the `Shift+Enter` newline hint while the
|
|
113
|
+
global-note editor is open; a committed note shows as a `Note` entry in the review list.
|
|
114
|
+
`Ctrl+G` remains Pi's global external-editor shortcut and is not repeated there. On narrow
|
|
115
|
+
terminals the right edge clips with `…` so the core hints survive.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Localization
|
|
2
|
+
|
|
3
|
+
How the dialog picks its language, which languages ship, and how to add one.
|
|
4
|
+
|
|
5
|
+
## Enabling it
|
|
6
|
+
|
|
7
|
+
The extension works standalone: install only this package and you get the full dialog in
|
|
8
|
+
English. Localization needs one more install:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pi install npm:@juicesharp/rpiv-i18n
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Restart your Pi session. If you installed through
|
|
15
|
+
[`@juicesharp/rpiv-pi`](https://www.npmjs.com/package/@juicesharp/rpiv-pi) and ran
|
|
16
|
+
`/rpiv-setup`, you already have it.
|
|
17
|
+
|
|
18
|
+
The dependency is a genuinely optional peer. This package loads the SDK inside a
|
|
19
|
+
`try`/`catch` at startup; when it is absent, every string falls back to its inline English
|
|
20
|
+
literal at the call site. There is no warning and no crash — the dialog simply renders in
|
|
21
|
+
English.
|
|
22
|
+
|
|
23
|
+
## Picking a language
|
|
24
|
+
|
|
25
|
+
With the SDK installed, the locale resolves in this order, first hit wins:
|
|
26
|
+
|
|
27
|
+
1. `pi --locale <code>` on the command line
|
|
28
|
+
2. `~/.config/rpiv-i18n/locale.json`
|
|
29
|
+
3. `LANG` / `LC_ALL` from the environment
|
|
30
|
+
4. English
|
|
31
|
+
|
|
32
|
+
`/languages` opens an interactive picker and flips the strings live — the dialog reads its
|
|
33
|
+
strings at render time, so an open questionnaire follows the change. Both `/languages` and
|
|
34
|
+
`--locale` are registered by `@juicesharp/rpiv-i18n`, not by this package.
|
|
35
|
+
|
|
36
|
+
## Shipped languages
|
|
37
|
+
|
|
38
|
+
Nine locale files ship in `locales/`:
|
|
39
|
+
|
|
40
|
+
| Code | Language |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `de` | Deutsch |
|
|
43
|
+
| `en` | English |
|
|
44
|
+
| `es` | Español |
|
|
45
|
+
| `fr` | Français |
|
|
46
|
+
| `pt` | Português |
|
|
47
|
+
| `pt-BR` | Português (Brasil) |
|
|
48
|
+
| `ru` | Русский |
|
|
49
|
+
| `uk` | Українська |
|
|
50
|
+
| `zh` | 中文 |
|
|
51
|
+
|
|
52
|
+
## What is translated, and what is not
|
|
53
|
+
|
|
54
|
+
Translation covers the chrome you read: the `Type something.` and `Next` sentinel rows,
|
|
55
|
+
the footer hint segments (including the collapsed-state line and the Submit tab's
|
|
56
|
+
`n to add a note` hint), the Submit picker labels, the review-tab heading with its
|
|
57
|
+
submit-readiness prompt, incomplete-answers warning, and committed-note `Note` label, the
|
|
58
|
+
preview pane's empty and notes-affordance lines, the notes header and the global-note
|
|
59
|
+
header on the Submit tab, the
|
|
60
|
+
external-editor failure notification, and the two RPC dialog prompts. Twenty-six keys in total,
|
|
61
|
+
all under the namespace `@juicesharp/rpiv-ask-user-question`.
|
|
62
|
+
|
|
63
|
+
Everything the *model* reads stays English by design: the tool description, the parameter
|
|
64
|
+
schema descriptions, error messages, and the reserved-label list. Those are prompt inputs,
|
|
65
|
+
not UI, and translating them would change model behavior rather than your reading
|
|
66
|
+
experience. It also means reserved-label validation compares against fixed English
|
|
67
|
+
strings, so `Type something.` is rejected as an authored option label in every locale.
|
|
68
|
+
|
|
69
|
+
## Adding a language
|
|
70
|
+
|
|
71
|
+
No code change is required.
|
|
72
|
+
|
|
73
|
+
1. Copy `locales/en.json` to `locales/<code>.json`, where `<code>` is a locale the SDK
|
|
74
|
+
supports.
|
|
75
|
+
2. Translate the values. Keep every key, and keep the placeholders and leading symbols
|
|
76
|
+
(`↑/↓`, `⚠`) intact. `hint.collapse` and `hint.expand_line` contain a literal `{key}`
|
|
77
|
+
placeholder that is replaced at render time with the user's configured `collapseKey` —
|
|
78
|
+
keep it verbatim, positioned wherever your language's word order wants the key name.
|
|
79
|
+
3. Restart Pi and select the language with `/languages`.
|
|
80
|
+
|
|
81
|
+
The loader iterates the SDK's supported-locale list over this directory at startup, so a
|
|
82
|
+
new file is picked up automatically. See the
|
|
83
|
+
[`@juicesharp/rpiv-i18n`](https://www.npmjs.com/package/@juicesharp/rpiv-i18n) README,
|
|
84
|
+
section "Contributing translations", for the full convention.
|
|
85
|
+
|
|
86
|
+
Keys are looked up individually with an English fallback, so a partially translated file
|
|
87
|
+
is safe — untranslated keys render in English rather than blank.
|