pi-ask-questions 0.3.0 → 0.4.0
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/CHANGELOG.md +5 -0
- package/README.md +18 -5
- package/package.json +1 -1
- package/src/extension.ts +13 -10
- package/src/schema.ts +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,8 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2026-10-25
|
|
11
|
+
|
|
10
12
|
### Changed
|
|
11
13
|
|
|
14
|
+
- Added explicit `mode: "urgent"` (blocking) and `mode: "background"` (default) choices. `noWait` remains a compatibility alias; an explicit mode takes precedence.
|
|
15
|
+
- Background answers now use steering delivery at the next model/tool boundary instead of waiting in the follow-up queue.
|
|
16
|
+
|
|
12
17
|
- Tabs preserve unfinished drafts, caret positions, and option cursors when revisiting questions.
|
|
13
18
|
- Multiline extra answers support arrow-key editing between lines; PageUp and PageDown navigate long option lists.
|
|
14
19
|
- Questionnaires show progress, live selection counts, and optional-question hints. The review tab preserves answer summaries while displaying specific validation errors.
|
package/README.md
CHANGED
|
@@ -53,7 +53,8 @@ Once installed, run `/ask-demo` to preview the UI, or just let the model call `a
|
|
|
53
53
|
- **Optional questions** (`required: false`) that can be skipped, plus preset answers (`selected: true`) and defaults.
|
|
54
54
|
- **Review tab** — see your answers and specific validation errors together before submitting; jump back to any question to edit it.
|
|
55
55
|
- **Validation** — required answers and `min`/`max` selection counts are enforced before submit.
|
|
56
|
-
- **
|
|
56
|
+
- **Urgent mode** — set `mode: "urgent"` to block further work until the questionnaire is answered or cancelled.
|
|
57
|
+
- **Background mode** — use `mode: "background"` (the default) and the tool returns immediately while the questionnaire stays open; answers steer the active run at the next model/tool boundary.
|
|
57
58
|
- **Safe cancel** — `Esc` arms cancellation, a second `Esc` or `Ctrl+C` cancels immediately.
|
|
58
59
|
- **Scrollable option lists** — long lists show “n more above / below” indicators. Use `PageUp` / `PageDown` to move eight rows at a time.
|
|
59
60
|
- **Structured results** — the tool returns text for the model and a machine-readable `structuredContent` payload for codemode scripts.
|
|
@@ -130,13 +131,25 @@ Notes: (skipped)
|
|
|
130
131
|
| `questions[].min` / `max` | integer | Selection bounds for multi-select. |
|
|
131
132
|
| `questions[].placeholder` | string | Placeholder for the free-form editor. |
|
|
132
133
|
| `questions[].otherLabel` | string | Custom label for the typed-answer entry. |
|
|
133
|
-
| `
|
|
134
|
+
| `mode` | `"urgent"` / `"background"` | `"urgent"` waits for answers. Default `"background"` returns immediately and delivers answers as steering (interactive TUI only; other interactive modes wait). Only one background questionnaire can be open at a time. |
|
|
135
|
+
| `noWait` | boolean | Compatibility alias: `true` means background, `false` means urgent. An explicit `mode` takes precedence. |
|
|
136
|
+
|
|
137
|
+
Choose `mode: "urgent"` when the model needs input before proceeding anywhere. Choose `mode: "background"` when it can continue independent work:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"mode": "background",
|
|
142
|
+
"questions": [{ "question": "Which deployment environment should I use?" }]
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Background answers use Pi's steering queue, so they are considered at the next model/tool boundary instead of waiting for the agent to finish. Steering does not interrupt a response mid-token or abort a running tool. If the agent has already stopped, submitting answers starts a new turn. Cancellation is also reported. In RPC mode, both modes wait for the dialog answers.
|
|
134
147
|
|
|
135
148
|
### Structured results
|
|
136
149
|
|
|
137
150
|
`structuredContent` mirrors the answers for codemode scripts: `cancelled`, an optional `pending`, and `answers[]` with `{ id, question, skipped, answers: [{ value, label, custom }] }`.
|
|
138
151
|
|
|
139
|
-
While a background questionnaire is open, `pending` is `true` and each `answers[]` entry is a stub with an empty `answers` array. Branch on `pending` before reading them; the real answers arrive as a
|
|
152
|
+
While a background questionnaire is open, `pending` is `true` and each `answers[]` entry is a stub with an empty `answers` array. Branch on `pending` before reading them; the real answers arrive as a steering message.
|
|
140
153
|
|
|
141
154
|
### Keyboard reference
|
|
142
155
|
|
|
@@ -159,8 +172,8 @@ In a multiline extra answer, `↑` / `↓` edits between text lines. Moving up f
|
|
|
159
172
|
|
|
160
173
|
| Mode | Behavior |
|
|
161
174
|
| --- | --- |
|
|
162
|
-
| Interactive TUI | Full tabbed questionnaire. |
|
|
163
|
-
| Interactive TUI + `
|
|
175
|
+
| Interactive TUI + `mode: "urgent"` | Full tabbed questionnaire; tool waits for answers before further work. |
|
|
176
|
+
| Interactive TUI + `mode: "background"` (default) | Tool returns immediately; answers steer the active run at the next model/tool boundary. |
|
|
164
177
|
| RPC | Sequential fallback built from the dialog API (`select` / `input`). |
|
|
165
178
|
| Print / JSON | The tool reports that no UI is available and lists the questions so the model can ask them in plain text. |
|
|
166
179
|
|
package/package.json
CHANGED
package/src/extension.ts
CHANGED
|
@@ -28,13 +28,13 @@ import { runQuestionnaire, type QuestionnaireContext } from "./ui/ask-questionna
|
|
|
28
28
|
/** Structured details stored with the tool result for rendering. */
|
|
29
29
|
export interface AskToolDetails {
|
|
30
30
|
cancelled: boolean;
|
|
31
|
-
/** True while a
|
|
31
|
+
/** True while a background questionnaire is still open. */
|
|
32
32
|
pending?: boolean;
|
|
33
33
|
answers: QuestionAnswer[];
|
|
34
34
|
questions: NormalizedQuestion[];
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const TOOL_DESCRIPTION = `Ask the user one or more questions
|
|
37
|
+
const TOOL_DESCRIPTION = `Ask the user one or more questions, either blocking for answers or continuing in the background. Use it when you need a decision, preference, or piece of information that only the user can provide.
|
|
38
38
|
|
|
39
39
|
The interactive UI supports:
|
|
40
40
|
- Tabs: every question gets its own tab (Tab / Shift+Tab and arrow keys switch).
|
|
@@ -42,14 +42,16 @@ The interactive UI supports:
|
|
|
42
42
|
- Free-form typing: a question with no options is a text prompt. Option questions can also hold one typed answer alongside the selected option(s) unless allowOther is false, and the answer is edited inline.
|
|
43
43
|
- Optional questions (required: false) that can be skipped, preselected options (selected: true), and min/max selection counts.
|
|
44
44
|
- Space or number keys 1-9 select or clear options without submitting; Enter confirms. A selects all; C clears a multi-select.
|
|
45
|
-
- Set
|
|
45
|
+
- Set mode: "urgent" to wait for the user before proceeding with any further work.
|
|
46
|
+
- Use mode: "background" (default) to continue independent work while the questionnaire stays open. Answers are injected as steering at the next model/tool boundary, before further work; they do not wait until the agent finishes. This does not abort an in-flight response or running tool.
|
|
47
|
+
- noWait is a compatibility alias: true means background, false means urgent. An explicit mode takes precedence.
|
|
46
48
|
|
|
47
49
|
Guidelines:
|
|
48
50
|
- Prefer this tool over asking questions in prose when you actually need the answer to proceed.
|
|
49
51
|
- Group related questions into one call (2-6 questions) instead of asking repeatedly.
|
|
50
52
|
- Provide concrete, labeled options whenever you can; use a free-form question only when the answer space is open.
|
|
51
53
|
- Put recommended options first.
|
|
52
|
-
-
|
|
54
|
+
- Choose urgent when an answer is required before any further work; choose background only when you can continue independent work. In non-TUI interactive modes, background falls back to waiting for answers.`;
|
|
53
55
|
|
|
54
56
|
const HELP_TEXT = `Interactive UI is not available in this mode. Ask the user the following questions directly in your reply instead:
|
|
55
57
|
{{questions}}`;
|
|
@@ -92,8 +94,8 @@ function resultContent(result: AskResult): string {
|
|
|
92
94
|
|
|
93
95
|
/** Start the questionnaire and wait for the user. */
|
|
94
96
|
export default function askQuestionsExtension(pi: ExtensionAPI): void {
|
|
95
|
-
// A
|
|
96
|
-
// session-scoped abort controller and reports its answers with a
|
|
97
|
+
// A background questionnaire stays open after its tool call returns. It owns a
|
|
98
|
+
// session-scoped abort controller and reports its answers with a steering
|
|
97
99
|
// message instead of a tool result.
|
|
98
100
|
let backgroundController: AbortController | undefined;
|
|
99
101
|
let shuttingDown = false;
|
|
@@ -116,7 +118,7 @@ export default function askQuestionsExtension(pi: ExtensionAPI): void {
|
|
|
116
118
|
promptGuidelines: [
|
|
117
119
|
"Use ask_user when you need a decision or missing detail from the user; batch related questions into one call instead of asking repeatedly.",
|
|
118
120
|
"Give ask_user questions labeled options where possible, keep them self-contained, and put recommended options first.",
|
|
119
|
-
|
|
121
|
+
'Use mode: "urgent" when input is required before proceeding anywhere. Use mode: "background" (default) for independent work; answers steer the active run at the next model/tool boundary.',
|
|
120
122
|
],
|
|
121
123
|
parameters: AskUserParamsSchema,
|
|
122
124
|
outputSchema: AskUserOutputSchema,
|
|
@@ -140,7 +142,8 @@ export default function askQuestionsExtension(pi: ExtensionAPI): void {
|
|
|
140
142
|
|
|
141
143
|
const submitLabel = params.submitLabel?.trim() || DEFAULT_SUBMIT_LABEL;
|
|
142
144
|
|
|
143
|
-
|
|
145
|
+
const mode = params.mode ?? (params.noWait === false ? "urgent" : "background");
|
|
146
|
+
if (mode === "background" && ctx.mode === "tui") {
|
|
144
147
|
if (backgroundController) {
|
|
145
148
|
return {
|
|
146
149
|
content: [
|
|
@@ -172,7 +175,7 @@ export default function askQuestionsExtension(pi: ExtensionAPI): void {
|
|
|
172
175
|
display: true,
|
|
173
176
|
details: { cancelled: result.cancelled, answers: result.answers, questions },
|
|
174
177
|
},
|
|
175
|
-
{ triggerTurn: true, deliverAs: "
|
|
178
|
+
{ triggerTurn: true, deliverAs: "steer" },
|
|
176
179
|
);
|
|
177
180
|
})
|
|
178
181
|
.catch((error: unknown) => {
|
|
@@ -199,7 +202,7 @@ export default function askQuestionsExtension(pi: ExtensionAPI): void {
|
|
|
199
202
|
content: [
|
|
200
203
|
{
|
|
201
204
|
type: "text",
|
|
202
|
-
text: `Questionnaire shown to the user in the background. Continue with other work; the answers will
|
|
205
|
+
text: `Questionnaire shown to the user in the background. Continue with other work; the answers will be injected as steering at the next model/tool boundary. Incorporate them before continuing further work.`,
|
|
203
206
|
},
|
|
204
207
|
],
|
|
205
208
|
details: { cancelled: false, pending: true, answers: [], questions },
|
package/src/schema.ts
CHANGED
|
@@ -111,10 +111,16 @@ export const AskUserParamsSchema = Type.Object({
|
|
|
111
111
|
description:
|
|
112
112
|
"Questions to ask, in order. Each question gets its own tab; the user can move between tabs freely.",
|
|
113
113
|
}),
|
|
114
|
+
mode: Type.Optional(
|
|
115
|
+
Type.Union([Type.Literal("urgent"), Type.Literal("background")], {
|
|
116
|
+
description:
|
|
117
|
+
'"urgent" blocks further work until the questionnaire is answered or cancelled. "background" (default) returns immediately and injects answers as steering at the next model/tool boundary (interactive TUI only; other interactive modes wait). Takes precedence over noWait. Only one background questionnaire can be open at a time.',
|
|
118
|
+
}),
|
|
119
|
+
),
|
|
114
120
|
noWait: Type.Optional(
|
|
115
121
|
Type.Boolean({
|
|
116
122
|
description:
|
|
117
|
-
"
|
|
123
|
+
"Compatibility alias: true selects background mode, false selects urgent mode. Prefer mode; an explicit mode takes precedence.",
|
|
118
124
|
}),
|
|
119
125
|
),
|
|
120
126
|
});
|
|
@@ -126,7 +132,7 @@ export const AskUserOutputSchema = Type.Object({
|
|
|
126
132
|
pending: Type.Optional(
|
|
127
133
|
Type.Boolean({
|
|
128
134
|
description:
|
|
129
|
-
"True when the questionnaire is still open in
|
|
135
|
+
"True when the questionnaire is still open in background mode; answers arrive as a steering message.",
|
|
130
136
|
}),
|
|
131
137
|
),
|
|
132
138
|
answers: Type.Array(
|