@@ -66,7 +66,7 @@ const OptionSchema = Type.Object({
6666
6767const QuestionParams = Type . Object ( {
6868 question : Type . String ( { description : "The question to ask the user" } ) ,
69- options : Type . Array ( OptionSchema , { minItems : 2 , maxItems : 4 } ) ,
69+ options : Type . Array ( OptionSchema , { minItems : 2 , maxItems : 10 } ) ,
7070 header : Type . Optional (
7171 Type . String ( { description : "Optional short header (e.g. 'CD-PILLARS')" } ) ,
7272 ) ,
@@ -83,7 +83,7 @@ export default function (pi: ExtensionAPI) {
8383 promptSnippet :
8484 "Present a strategic decision with options and capture the user's choice" ,
8585 promptGuidelines : [
86- "Use the question tool when you need the user to make a strategic choice between 2-4 options." ,
86+ "Use the question tool when you need the user to make a strategic choice between 2-10 options." ,
8787 "ALWAYS write your full reasoning in conversation text BEFORE calling the question tool — explain the trade-offs, your recommendation, and why." ,
8888 "Add '(Recommended)' to your preferred option's label." ,
8989 "Labels: 1-5 words. Descriptions: 1 sentence with the key trade-off." ,
@@ -135,6 +135,8 @@ export default function (pi: ExtensionAPI) {
135135 index ?: number ;
136136 } | null > ( ( tui , theme , _kb , done ) => {
137137 let optionIndex = 0 ;
138+ let scrollOffset = 0 ;
139+ const VISIBLE_OPTIONS = 6 ;
138140 let editMode = false ;
139141 let cachedLines : string [ ] | undefined ;
140142
@@ -182,11 +184,14 @@ export default function (pi: ExtensionAPI) {
182184
183185 if ( matchesKey ( data , Key . up ) ) {
184186 optionIndex = Math . max ( 0 , optionIndex - 1 ) ;
187+ if ( optionIndex < scrollOffset ) scrollOffset = optionIndex ;
185188 refresh ( ) ;
186189 return ;
187190 }
188191 if ( matchesKey ( data , Key . down ) ) {
189192 optionIndex = Math . min ( allOptions . length - 1 , optionIndex + 1 ) ;
193+ if ( optionIndex >= scrollOffset + VISIBLE_OPTIONS )
194+ scrollOffset = optionIndex - VISIBLE_OPTIONS + 1 ;
190195 refresh ( ) ;
191196 return ;
192197 }
@@ -206,6 +211,26 @@ export default function (pi: ExtensionAPI) {
206211 return ;
207212 }
208213
214+ // Number shortcuts: 1-9 for options 1-9, 0 for option 10
215+ const digit = / ^ [ 0 - 9 ] $ / . test ( data ) ? parseInt ( data , 10 ) : - 1 ;
216+ if ( digit >= 0 ) {
217+ const target = digit === 0 ? 9 : digit - 1 ;
218+ if ( target < allOptions . length ) {
219+ const selected = allOptions [ target ] ;
220+ if ( selected . isOther ) {
221+ optionIndex = target ;
222+ editMode = true ;
223+ } else {
224+ done ( {
225+ answer : selected . label ,
226+ wasCustom : false ,
227+ index : target + 1 ,
228+ } ) ;
229+ }
230+ return ;
231+ }
232+ }
233+
209234 if ( matchesKey ( data , Key . escape ) ) {
210235 done ( null ) ;
211236 }
@@ -249,13 +274,28 @@ export default function (pi: ExtensionAPI) {
249274 addWrappedWithPrefix ( " " , theme . fg ( "text" , params . question ) ) ;
250275 lines . push ( "" ) ;
251276
252- // Options
253- for ( let i = 0 ; i < allOptions . length ; i ++ ) {
254- const opt = allOptions [ i ] ;
255- const selected = i === optionIndex ;
277+ // Options (scrollable window)
278+ const numPad = String ( allOptions . length ) . length ;
279+ const visible = allOptions . slice (
280+ scrollOffset ,
281+ scrollOffset + VISIBLE_OPTIONS ,
282+ ) ;
283+ const hasMoreAbove = scrollOffset > 0 ;
284+ const hasMoreBelow =
285+ scrollOffset + VISIBLE_OPTIONS < allOptions . length ;
286+
287+ if ( hasMoreAbove ) {
288+ addWrappedWithPrefix ( " " , theme . fg ( "dim" , "↑ more" ) ) ;
289+ }
290+
291+ for ( let i = 0 ; i < visible . length ; i ++ ) {
292+ const realIndex = scrollOffset + i ;
293+ const opt = allOptions [ realIndex ] ;
294+ const selected = realIndex === optionIndex ;
256295 const isOther = opt . isOther === true ;
257296 const prefix = selected ? theme . fg ( "accent" , "> " ) : " " ;
258- const label = `${ i + 1 } . ${ opt . label } ${ isOther && editMode ? " ✎" : "" } ` ;
297+ const numStr = String ( realIndex + 1 ) . padStart ( numPad ) ;
298+ const label = `${ numStr } . ${ opt . label } ${ isOther && editMode ? " ✎" : "" } ` ;
259299 const color = selected || ( isOther && editMode ) ? "accent" : "text" ;
260300
261301 addWrappedWithPrefix ( prefix , theme . fg ( color , label ) ) ;
@@ -266,6 +306,10 @@ export default function (pi: ExtensionAPI) {
266306 }
267307 }
268308
309+ if ( hasMoreBelow ) {
310+ addWrappedWithPrefix ( " " , theme . fg ( "dim" , "↓ more" ) ) ;
311+ }
312+
269313 // Edit mode: inline text editor
270314 if ( editMode ) {
271315 lines . push ( "" ) ;
@@ -285,7 +329,7 @@ export default function (pi: ExtensionAPI) {
285329 } else {
286330 addWrappedWithPrefix (
287331 " " ,
288- theme . fg ( "dim" , "↑↓ navigate • Enter to select • Esc to cancel" ) ,
332+ theme . fg ( "dim" , "↑↓ navigate • 1-9 choose • 0=Other • Enter to select • Esc to cancel" ) ,
289333 ) ;
290334 }
291335 lines . push ( theme . fg ( "accent" , "─" . repeat ( renderWidth ) ) ) ;
0 commit comments