@henryqw/pi-ask-question 0.1.7 → 0.1.9
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/README.md +0 -1
- package/extensions/ask-question.ts +9 -8
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Editor,
|
|
4
4
|
type EditorTheme,
|
|
5
5
|
Key,
|
|
6
|
+
type KeyId,
|
|
6
7
|
matchesKey,
|
|
7
8
|
Text,
|
|
8
9
|
visibleWidth,
|
|
@@ -18,7 +19,9 @@ interface QuestionOption {
|
|
|
18
19
|
type DisplayOption = QuestionOption & { isOther?: boolean };
|
|
19
20
|
|
|
20
21
|
const CUSTOM_OPTION_LABEL = "Something else.";
|
|
21
|
-
|
|
22
|
+
// Models are told to omit "(Recommended)" from labels but don't always comply; normalize instead of duplicating.
|
|
23
|
+
const RECOMMENDED_SUFFIX = /\s*\(recommended\)\s*$/i;
|
|
24
|
+
const withRecommended = (label: string): string => `${label.replace(RECOMMENDED_SUFFIX, "")} (Recommended)`;
|
|
22
25
|
|
|
23
26
|
interface QuestionDetails {
|
|
24
27
|
question: string;
|
|
@@ -72,8 +75,7 @@ export default function askQuestionExtension(pi: ExtensionAPI): void {
|
|
|
72
75
|
};
|
|
73
76
|
}
|
|
74
77
|
let validationError: string | undefined;
|
|
75
|
-
if (
|
|
76
|
-
else if (!question) validationError = "Question must not be blank";
|
|
78
|
+
if (!question) validationError = "Question must not be blank";
|
|
77
79
|
else if (suppliedOptions.some((option) => !option.label)) validationError = "Option labels must not be blank";
|
|
78
80
|
else if (new Set(options.map((option) => option.toLowerCase())).size !== options.length) validationError = "Option labels must be unique";
|
|
79
81
|
else if (options.some((option) => option.toLowerCase() === CUSTOM_OPTION_LABEL.toLowerCase())) validationError = `Option label "${CUSTOM_OPTION_LABEL}" is reserved`;
|
|
@@ -136,7 +138,7 @@ export default function askQuestionExtension(pi: ExtensionAPI): void {
|
|
|
136
138
|
return;
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
const numberIndex =
|
|
141
|
+
const numberIndex = allOptions.findIndex((_, index) => matchesKey(data, `${index + 1}` as KeyId));
|
|
140
142
|
if (numberIndex >= 0) {
|
|
141
143
|
optionIndex = numberIndex;
|
|
142
144
|
selectOption();
|
|
@@ -154,11 +156,10 @@ export default function askQuestionExtension(pi: ExtensionAPI): void {
|
|
|
154
156
|
if (cachedLines) return cachedLines;
|
|
155
157
|
const lines: string[] = [];
|
|
156
158
|
const renderWidth = Math.max(1, width);
|
|
157
|
-
const addWrapped = (text: string): void => { lines.push(...wrapTextWithAnsi(text, renderWidth)); };
|
|
158
159
|
const addWrappedWithPrefix = (prefix: string, text: string): void => {
|
|
159
160
|
const prefixWidth = visibleWidth(prefix);
|
|
160
161
|
if (prefixWidth >= renderWidth) {
|
|
161
|
-
|
|
162
|
+
lines.push(...wrapTextWithAnsi(prefix + text, renderWidth));
|
|
162
163
|
return;
|
|
163
164
|
}
|
|
164
165
|
const wrapped = wrapTextWithAnsi(text, renderWidth - prefixWidth);
|
|
@@ -175,7 +176,7 @@ export default function askQuestionExtension(pi: ExtensionAPI): void {
|
|
|
175
176
|
const option = allOptions[index]!;
|
|
176
177
|
const selected = index === optionIndex;
|
|
177
178
|
const prefix = selected ? theme.fg("accent", "> ") : " ";
|
|
178
|
-
const label = `${index + 1}. ${
|
|
179
|
+
const label = `${index + 1}. ${index === 0 ? withRecommended(option.label) : option.label}${option.isOther && editMode ? " ✎" : ""}`;
|
|
179
180
|
addWrappedWithPrefix(prefix, theme.fg(selected || (option.isOther && editMode) ? "accent" : "text", label));
|
|
180
181
|
if (option.description) addWrappedWithPrefix(" ", theme.fg("muted", option.description));
|
|
181
182
|
}
|
|
@@ -230,7 +231,7 @@ export default function askQuestionExtension(pi: ExtensionAPI): void {
|
|
|
230
231
|
const options = Array.isArray(args.options) ? args.options : [];
|
|
231
232
|
if (options.length) {
|
|
232
233
|
const labels = options.map((option: QuestionOption) => option.label);
|
|
233
|
-
const numbered = [...labels, CUSTOM_OPTION_LABEL].map((option, index) => `${index + 1}. ${
|
|
234
|
+
const numbered = [...labels, CUSTOM_OPTION_LABEL].map((option, index) => `${index + 1}. ${index === 0 ? withRecommended(option) : option}`);
|
|
234
235
|
text += `\n${theme.fg("dim", ` Options: ${numbered.join(", ")}`)}`;
|
|
235
236
|
}
|
|
236
237
|
return new Text(text, 0, 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@henryqw/pi-ask-question",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Ask Pi users one interactive question with choices or a custom answer.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"LICENSE"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"test": "node --test test/*.test.ts",
|
|
23
22
|
"test:manual": "pi --no-extensions -e ./extensions/ask-question.ts --tools ask_question --no-session \"We need storage for a small team app. Before making changes, ask me to choose storage.\"",
|
|
24
23
|
"typecheck": "tsc --noEmit --allowImportingTsExtensions --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck extensions/ask-question.ts",
|
|
25
24
|
"pack:check": "npm pack --dry-run"
|