@oh-my-pi/user-prompt 0.8.3 → 1.3.371
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 +11 -16
- package/package.json +2 -7
- package/tools/index.ts +245 -0
- package/tools/user-prompt/index.ts +0 -263
package/README.md
CHANGED
|
@@ -39,13 +39,8 @@ Asks the user questions during execution and returns their response. Useful for:
|
|
|
39
39
|
|
|
40
40
|
```json
|
|
41
41
|
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{ "label": "PostgreSQL (Recommended)" },
|
|
45
|
-
{ "label": "MySQL" },
|
|
46
|
-
{ "label": "SQLite" },
|
|
47
|
-
{ "label": "MongoDB" }
|
|
48
|
-
]
|
|
42
|
+
"question": "Which database would you like to use?",
|
|
43
|
+
"options": [{ "label": "PostgreSQL (Recommended)" }, { "label": "MySQL" }, { "label": "SQLite" }, { "label": "MongoDB" }]
|
|
49
44
|
}
|
|
50
45
|
```
|
|
51
46
|
|
|
@@ -53,15 +48,15 @@ Asks the user questions during execution and returns their response. Useful for:
|
|
|
53
48
|
|
|
54
49
|
```json
|
|
55
50
|
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
"question": "Which features should I implement?",
|
|
52
|
+
"options": [
|
|
53
|
+
{ "label": "Authentication" },
|
|
54
|
+
{ "label": "API endpoints" },
|
|
55
|
+
{ "label": "Database models" },
|
|
56
|
+
{ "label": "Unit tests" },
|
|
57
|
+
{ "label": "Documentation" }
|
|
58
|
+
],
|
|
59
|
+
"multi": true
|
|
65
60
|
}
|
|
66
61
|
```
|
|
67
62
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/user-prompt",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.3.371",
|
|
4
4
|
"description": "Interactive user prompting tool for gathering user input during execution",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"omp-plugin",
|
|
@@ -17,12 +17,7 @@
|
|
|
17
17
|
"directory": "plugins/user-prompt"
|
|
18
18
|
},
|
|
19
19
|
"omp": {
|
|
20
|
-
"
|
|
21
|
-
{
|
|
22
|
-
"src": "tools/user-prompt/index.ts",
|
|
23
|
-
"dest": "agent/tools/user-prompt/index.ts"
|
|
24
|
-
}
|
|
25
|
-
]
|
|
20
|
+
"tools": "tools"
|
|
26
21
|
},
|
|
27
22
|
"files": [
|
|
28
23
|
"tools"
|
package/tools/index.ts
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Prompt Tool - Ask questions to the user during execution
|
|
3
|
+
*
|
|
4
|
+
* Use this tool when you need to ask the user questions during execution.
|
|
5
|
+
* This allows you to:
|
|
6
|
+
* 1. Gather user preferences or requirements
|
|
7
|
+
* 2. Clarify ambiguous instructions
|
|
8
|
+
* 3. Get decisions on implementation choices as you work
|
|
9
|
+
* 4. Offer choices to the user about what direction to take
|
|
10
|
+
*
|
|
11
|
+
* Usage notes:
|
|
12
|
+
* - Users will always be able to select "Other" to provide custom text input
|
|
13
|
+
* - Use multi: true to allow multiple answers to be selected for a question
|
|
14
|
+
* - If you recommend a specific option, make that the first option in the list
|
|
15
|
+
* and add "(Recommended)" at the end of the label
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { CustomAgentTool, CustomToolFactory, ToolAPI } from '@mariozechner/pi-coding-agent'
|
|
19
|
+
import { Text } from '@mariozechner/pi-tui'
|
|
20
|
+
import { Type } from '@sinclair/typebox'
|
|
21
|
+
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// Tool Definition
|
|
24
|
+
// =============================================================================
|
|
25
|
+
|
|
26
|
+
const OTHER_OPTION = 'Other (type your own)'
|
|
27
|
+
|
|
28
|
+
const OptionItem = Type.Object({
|
|
29
|
+
label: Type.String({ description: 'Display label for this option' }),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const UserPromptParams = Type.Object({
|
|
33
|
+
question: Type.String({ description: 'The question to ask the user' }),
|
|
34
|
+
options: Type.Array(OptionItem, {
|
|
35
|
+
description: 'Available options for the user to choose from.',
|
|
36
|
+
minItems: 1,
|
|
37
|
+
}),
|
|
38
|
+
multi: Type.Optional(
|
|
39
|
+
Type.Boolean({
|
|
40
|
+
description: 'Allow multiple options to be selected (default: false)',
|
|
41
|
+
default: false,
|
|
42
|
+
})
|
|
43
|
+
),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
interface UserPromptDetails {
|
|
47
|
+
question: string
|
|
48
|
+
options: string[]
|
|
49
|
+
multi: boolean
|
|
50
|
+
selectedOptions: string[]
|
|
51
|
+
customInput?: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const DESCRIPTION = `Use this tool when you need to ask the user questions during execution. This allows you to:
|
|
55
|
+
1. Gather user preferences or requirements
|
|
56
|
+
2. Clarify ambiguous instructions
|
|
57
|
+
3. Get decisions on implementation choices as you work
|
|
58
|
+
4. Offer choices to the user about what direction to take.
|
|
59
|
+
|
|
60
|
+
Usage notes:
|
|
61
|
+
- Users will always be able to select "Other" to provide custom text input
|
|
62
|
+
- Use multi: true to allow multiple answers to be selected for a question
|
|
63
|
+
- If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
|
|
64
|
+
|
|
65
|
+
Example usage:
|
|
66
|
+
|
|
67
|
+
<example>
|
|
68
|
+
assistant: Let me ask which features you want to include.
|
|
69
|
+
assistant: Uses the user_prompt tool:
|
|
70
|
+
{
|
|
71
|
+
"question": "Which features should I implement?",
|
|
72
|
+
"options": [
|
|
73
|
+
{"label": "Authentication"},
|
|
74
|
+
{"label": "API endpoints"},
|
|
75
|
+
{"label": "Database models"},
|
|
76
|
+
{"label": "Unit tests"},
|
|
77
|
+
{"label": "Documentation"}
|
|
78
|
+
],
|
|
79
|
+
"multi": true
|
|
80
|
+
}
|
|
81
|
+
</example>`
|
|
82
|
+
|
|
83
|
+
const factory: CustomToolFactory = (pi: ToolAPI) => {
|
|
84
|
+
const tool: CustomAgentTool<typeof UserPromptParams, UserPromptDetails> = {
|
|
85
|
+
name: 'user_prompt',
|
|
86
|
+
label: 'User Prompt',
|
|
87
|
+
description: DESCRIPTION,
|
|
88
|
+
parameters: UserPromptParams,
|
|
89
|
+
|
|
90
|
+
async execute(_toolCallId, params, _signal, _onUpdate) {
|
|
91
|
+
const { question, options, multi = false } = params
|
|
92
|
+
const optionLabels = options.map(o => o.label)
|
|
93
|
+
|
|
94
|
+
if (!pi.hasUI) {
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: 'text',
|
|
99
|
+
text: 'Error: User prompt requires interactive mode',
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
details: {
|
|
103
|
+
question,
|
|
104
|
+
options: optionLabels,
|
|
105
|
+
multi,
|
|
106
|
+
selectedOptions: [],
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let selectedOptions: string[] = []
|
|
112
|
+
let customInput: string | undefined
|
|
113
|
+
|
|
114
|
+
if (multi) {
|
|
115
|
+
// Multi-select: show checkboxes in the label to indicate selection state
|
|
116
|
+
const DONE = '✓ Done selecting'
|
|
117
|
+
const selected = new Set<string>()
|
|
118
|
+
|
|
119
|
+
while (true) {
|
|
120
|
+
// Build options with checkbox indicators
|
|
121
|
+
const opts: string[] = []
|
|
122
|
+
|
|
123
|
+
// Add "Done" option if any selected
|
|
124
|
+
if (selected.size > 0) {
|
|
125
|
+
opts.push(DONE)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Add all options with [X] or [ ] prefix
|
|
129
|
+
for (const opt of optionLabels) {
|
|
130
|
+
const checkbox = selected.has(opt) ? '[X]' : '[ ]'
|
|
131
|
+
opts.push(`${checkbox} ${opt}`)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Add "Other" option
|
|
135
|
+
opts.push(OTHER_OPTION)
|
|
136
|
+
|
|
137
|
+
const prefix = selected.size > 0 ? `(${selected.size} selected) ` : ''
|
|
138
|
+
const choice = await pi.ui.select(`${prefix}${question}`, opts)
|
|
139
|
+
|
|
140
|
+
if (choice === null || choice === DONE) break
|
|
141
|
+
|
|
142
|
+
if (choice === OTHER_OPTION) {
|
|
143
|
+
const input = await pi.ui.input('Enter your response:')
|
|
144
|
+
if (input) customInput = input
|
|
145
|
+
break
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Toggle selection - extract the actual option name
|
|
149
|
+
const optMatch = choice.match(/^\[.\] (.+)$/)
|
|
150
|
+
if (optMatch) {
|
|
151
|
+
const opt = optMatch[1]
|
|
152
|
+
if (selected.has(opt)) {
|
|
153
|
+
selected.delete(opt)
|
|
154
|
+
} else {
|
|
155
|
+
selected.add(opt)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
selectedOptions = Array.from(selected)
|
|
160
|
+
} else {
|
|
161
|
+
// Single select with "Other" option
|
|
162
|
+
const choice = await pi.ui.select(question, [...optionLabels, OTHER_OPTION])
|
|
163
|
+
if (choice === OTHER_OPTION) {
|
|
164
|
+
const input = await pi.ui.input('Enter your response:')
|
|
165
|
+
if (input) customInput = input
|
|
166
|
+
} else if (choice) {
|
|
167
|
+
selectedOptions = [choice]
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const details: UserPromptDetails = {
|
|
172
|
+
question,
|
|
173
|
+
options: optionLabels,
|
|
174
|
+
multi,
|
|
175
|
+
selectedOptions,
|
|
176
|
+
customInput,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
let responseText: string
|
|
180
|
+
if (customInput) {
|
|
181
|
+
responseText = `User provided custom input: ${customInput}`
|
|
182
|
+
} else if (selectedOptions.length > 0) {
|
|
183
|
+
responseText = multi ? `User selected: ${selectedOptions.join(', ')}` : `User selected: ${selectedOptions[0]}`
|
|
184
|
+
} else {
|
|
185
|
+
responseText = 'User cancelled the selection'
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return { content: [{ type: 'text', text: responseText }], details }
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
renderCall(args, t) {
|
|
192
|
+
if (!args.question) {
|
|
193
|
+
return new Text(t.fg('error', 'user_prompt: no question provided'), 0, 0)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const multiTag = args.multi ? t.fg('muted', ' [multi-select]') : ''
|
|
197
|
+
let text = t.fg('toolTitle', '? ') + t.fg('accent', args.question) + multiTag
|
|
198
|
+
|
|
199
|
+
if (args.options?.length) {
|
|
200
|
+
for (const opt of args.options) {
|
|
201
|
+
text += `\n${t.fg('dim', ' ○ ')}${t.fg('muted', opt.label)}`
|
|
202
|
+
}
|
|
203
|
+
text += `\n${t.fg('dim', ' ○ ')}${t.fg('muted', 'Other (custom input)')}`
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return new Text(text, 0, 0)
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
renderResult(result, _opts, t) {
|
|
210
|
+
const { details } = result
|
|
211
|
+
if (!details) {
|
|
212
|
+
const txt = result.content[0]
|
|
213
|
+
return new Text(txt?.type === 'text' ? txt.text : '', 0, 0)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let text = t.fg('toolTitle', '? ') + t.fg('accent', details.question)
|
|
217
|
+
|
|
218
|
+
if (details.customInput) {
|
|
219
|
+
// Custom input provided
|
|
220
|
+
text += `\n${t.fg('dim', ' ⎿ ')}${t.fg('success', details.customInput)}`
|
|
221
|
+
} else if (details.selectedOptions.length > 0) {
|
|
222
|
+
// Show only selected options
|
|
223
|
+
const selected = details.selectedOptions
|
|
224
|
+
if (selected.length === 1) {
|
|
225
|
+
text += `\n${t.fg('dim', ' ⎿ ')}${t.fg('success', selected[0])}`
|
|
226
|
+
} else {
|
|
227
|
+
// Multiple selections
|
|
228
|
+
for (let i = 0; i < selected.length; i++) {
|
|
229
|
+
const isLast = i === selected.length - 1
|
|
230
|
+
const branch = isLast ? '└─' : '├─'
|
|
231
|
+
text += `\n${t.fg('dim', ` ${branch} `)}${t.fg('success', selected[i])}`
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
text += `\n${t.fg('dim', ' ⎿ ')}${t.fg('warning', 'Cancelled')}`
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return new Text(text, 0, 0)
|
|
239
|
+
},
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return tool
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export default factory
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Prompt Tool - Ask questions to the user during execution
|
|
3
|
-
*
|
|
4
|
-
* Use this tool when you need to ask the user questions during execution.
|
|
5
|
-
* This allows you to:
|
|
6
|
-
* 1. Gather user preferences or requirements
|
|
7
|
-
* 2. Clarify ambiguous instructions
|
|
8
|
-
* 3. Get decisions on implementation choices as you work
|
|
9
|
-
* 4. Offer choices to the user about what direction to take
|
|
10
|
-
*
|
|
11
|
-
* Usage notes:
|
|
12
|
-
* - Users will always be able to select "Other" to provide custom text input
|
|
13
|
-
* - Use multi: true to allow multiple answers to be selected for a question
|
|
14
|
-
* - If you recommend a specific option, make that the first option in the list
|
|
15
|
-
* and add "(Recommended)" at the end of the label
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { Type } from "@sinclair/typebox";
|
|
19
|
-
import { Text } from "@mariozechner/pi-tui";
|
|
20
|
-
import type {
|
|
21
|
-
CustomAgentTool,
|
|
22
|
-
CustomToolFactory,
|
|
23
|
-
ToolAPI,
|
|
24
|
-
} from "@mariozechner/pi-coding-agent";
|
|
25
|
-
|
|
26
|
-
// =============================================================================
|
|
27
|
-
// Tool Definition
|
|
28
|
-
// =============================================================================
|
|
29
|
-
|
|
30
|
-
const OTHER_OPTION = "Other (type your own)";
|
|
31
|
-
|
|
32
|
-
const OptionItem = Type.Object({
|
|
33
|
-
label: Type.String({ description: "Display label for this option" }),
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const UserPromptParams = Type.Object({
|
|
37
|
-
question: Type.String({ description: "The question to ask the user" }),
|
|
38
|
-
options: Type.Array(OptionItem, {
|
|
39
|
-
description: "Available options for the user to choose from.",
|
|
40
|
-
minItems: 1,
|
|
41
|
-
}),
|
|
42
|
-
multi: Type.Optional(
|
|
43
|
-
Type.Boolean({
|
|
44
|
-
description: "Allow multiple options to be selected (default: false)",
|
|
45
|
-
default: false,
|
|
46
|
-
}),
|
|
47
|
-
),
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
interface UserPromptDetails {
|
|
51
|
-
question: string;
|
|
52
|
-
options: string[];
|
|
53
|
-
multi: boolean;
|
|
54
|
-
selectedOptions: string[];
|
|
55
|
-
customInput?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const DESCRIPTION = `Use this tool when you need to ask the user questions during execution. This allows you to:
|
|
59
|
-
1. Gather user preferences or requirements
|
|
60
|
-
2. Clarify ambiguous instructions
|
|
61
|
-
3. Get decisions on implementation choices as you work
|
|
62
|
-
4. Offer choices to the user about what direction to take.
|
|
63
|
-
|
|
64
|
-
Usage notes:
|
|
65
|
-
- Users will always be able to select "Other" to provide custom text input
|
|
66
|
-
- Use multi: true to allow multiple answers to be selected for a question
|
|
67
|
-
- If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
|
|
68
|
-
|
|
69
|
-
Example usage:
|
|
70
|
-
|
|
71
|
-
<example>
|
|
72
|
-
assistant: Let me ask which features you want to include.
|
|
73
|
-
assistant: Uses the user_prompt tool:
|
|
74
|
-
{
|
|
75
|
-
"question": "Which features should I implement?",
|
|
76
|
-
"options": [
|
|
77
|
-
{"label": "Authentication"},
|
|
78
|
-
{"label": "API endpoints"},
|
|
79
|
-
{"label": "Database models"},
|
|
80
|
-
{"label": "Unit tests"},
|
|
81
|
-
{"label": "Documentation"}
|
|
82
|
-
],
|
|
83
|
-
"multi": true
|
|
84
|
-
}
|
|
85
|
-
</example>`;
|
|
86
|
-
|
|
87
|
-
const factory: CustomToolFactory = (pi: ToolAPI) => {
|
|
88
|
-
const tool: CustomAgentTool<typeof UserPromptParams, UserPromptDetails> = {
|
|
89
|
-
name: "user_prompt",
|
|
90
|
-
label: "User Prompt",
|
|
91
|
-
description: DESCRIPTION,
|
|
92
|
-
parameters: UserPromptParams,
|
|
93
|
-
|
|
94
|
-
async execute(_toolCallId, params, _signal, _onUpdate) {
|
|
95
|
-
const { question, options, multi = false } = params;
|
|
96
|
-
const optionLabels = options.map((o) => o.label);
|
|
97
|
-
|
|
98
|
-
if (!pi.hasUI) {
|
|
99
|
-
return {
|
|
100
|
-
content: [
|
|
101
|
-
{
|
|
102
|
-
type: "text",
|
|
103
|
-
text: "Error: User prompt requires interactive mode",
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
details: {
|
|
107
|
-
question,
|
|
108
|
-
options: optionLabels,
|
|
109
|
-
multi,
|
|
110
|
-
selectedOptions: [],
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
let selectedOptions: string[] = [];
|
|
116
|
-
let customInput: string | undefined;
|
|
117
|
-
|
|
118
|
-
if (multi) {
|
|
119
|
-
// Multi-select: show checkboxes in the label to indicate selection state
|
|
120
|
-
const DONE = "✓ Done selecting";
|
|
121
|
-
const selected = new Set<string>();
|
|
122
|
-
|
|
123
|
-
while (true) {
|
|
124
|
-
// Build options with checkbox indicators
|
|
125
|
-
const opts: string[] = [];
|
|
126
|
-
|
|
127
|
-
// Add "Done" option if any selected
|
|
128
|
-
if (selected.size > 0) {
|
|
129
|
-
opts.push(DONE);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Add all options with [X] or [ ] prefix
|
|
133
|
-
for (const opt of optionLabels) {
|
|
134
|
-
const checkbox = selected.has(opt) ? "[X]" : "[ ]";
|
|
135
|
-
opts.push(`${checkbox} ${opt}`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Add "Other" option
|
|
139
|
-
opts.push(OTHER_OPTION);
|
|
140
|
-
|
|
141
|
-
const prefix =
|
|
142
|
-
selected.size > 0 ? `(${selected.size} selected) ` : "";
|
|
143
|
-
const choice = await pi.ui.select(`${prefix}${question}`, opts);
|
|
144
|
-
|
|
145
|
-
if (choice === null || choice === DONE) break;
|
|
146
|
-
|
|
147
|
-
if (choice === OTHER_OPTION) {
|
|
148
|
-
const input = await pi.ui.input("Enter your response:");
|
|
149
|
-
if (input) customInput = input;
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Toggle selection - extract the actual option name
|
|
154
|
-
const optMatch = choice.match(/^\[.\] (.+)$/);
|
|
155
|
-
if (optMatch) {
|
|
156
|
-
const opt = optMatch[1];
|
|
157
|
-
if (selected.has(opt)) {
|
|
158
|
-
selected.delete(opt);
|
|
159
|
-
} else {
|
|
160
|
-
selected.add(opt);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
selectedOptions = Array.from(selected);
|
|
165
|
-
} else {
|
|
166
|
-
// Single select with "Other" option
|
|
167
|
-
const choice = await pi.ui.select(question, [
|
|
168
|
-
...optionLabels,
|
|
169
|
-
OTHER_OPTION,
|
|
170
|
-
]);
|
|
171
|
-
if (choice === OTHER_OPTION) {
|
|
172
|
-
const input = await pi.ui.input("Enter your response:");
|
|
173
|
-
if (input) customInput = input;
|
|
174
|
-
} else if (choice) {
|
|
175
|
-
selectedOptions = [choice];
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const details: UserPromptDetails = {
|
|
180
|
-
question,
|
|
181
|
-
options: optionLabels,
|
|
182
|
-
multi,
|
|
183
|
-
selectedOptions,
|
|
184
|
-
customInput,
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
let responseText: string;
|
|
188
|
-
if (customInput) {
|
|
189
|
-
responseText = `User provided custom input: ${customInput}`;
|
|
190
|
-
} else if (selectedOptions.length > 0) {
|
|
191
|
-
responseText = multi
|
|
192
|
-
? `User selected: ${selectedOptions.join(", ")}`
|
|
193
|
-
: `User selected: ${selectedOptions[0]}`;
|
|
194
|
-
} else {
|
|
195
|
-
responseText = "User cancelled the selection";
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return { content: [{ type: "text", text: responseText }], details };
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
renderCall(args, t) {
|
|
202
|
-
if (!args.question) {
|
|
203
|
-
return new Text(
|
|
204
|
-
t.fg("error", "user_prompt: no question provided"),
|
|
205
|
-
0,
|
|
206
|
-
0,
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const multiTag = args.multi ? t.fg("muted", " [multi-select]") : "";
|
|
211
|
-
let text =
|
|
212
|
-
t.fg("toolTitle", "? ") + t.fg("accent", args.question) + multiTag;
|
|
213
|
-
|
|
214
|
-
if (args.options?.length) {
|
|
215
|
-
for (const opt of args.options) {
|
|
216
|
-
text += "\n" + t.fg("dim", " ○ ") + t.fg("muted", opt.label);
|
|
217
|
-
}
|
|
218
|
-
text +=
|
|
219
|
-
"\n" + t.fg("dim", " ○ ") + t.fg("muted", "Other (custom input)");
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return new Text(text, 0, 0);
|
|
223
|
-
},
|
|
224
|
-
|
|
225
|
-
renderResult(result, { expanded }, t) {
|
|
226
|
-
const { details } = result;
|
|
227
|
-
if (!details) {
|
|
228
|
-
const txt = result.content[0];
|
|
229
|
-
return new Text(txt?.type === "text" ? txt.text : "", 0, 0);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
let text = t.fg("toolTitle", "? ") + t.fg("accent", details.question);
|
|
233
|
-
|
|
234
|
-
if (details.customInput) {
|
|
235
|
-
// Custom input provided
|
|
236
|
-
text +=
|
|
237
|
-
"\n" + t.fg("dim", " ⎿ ") + t.fg("success", details.customInput);
|
|
238
|
-
} else if (details.selectedOptions.length > 0) {
|
|
239
|
-
// Show only selected options
|
|
240
|
-
const selected = details.selectedOptions;
|
|
241
|
-
if (selected.length === 1) {
|
|
242
|
-
text += "\n" + t.fg("dim", " ⎿ ") + t.fg("success", selected[0]);
|
|
243
|
-
} else {
|
|
244
|
-
// Multiple selections
|
|
245
|
-
for (let i = 0; i < selected.length; i++) {
|
|
246
|
-
const isLast = i === selected.length - 1;
|
|
247
|
-
const branch = isLast ? "└─" : "├─";
|
|
248
|
-
text +=
|
|
249
|
-
"\n" + t.fg("dim", ` ${branch} `) + t.fg("success", selected[i]);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
} else {
|
|
253
|
-
text += "\n" + t.fg("dim", " ⎿ ") + t.fg("warning", "Cancelled");
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return new Text(text, 0, 0);
|
|
257
|
-
},
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
return tool;
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
export default factory;
|