| 1 | // Slash commands for the extension-host tests: text, a submitted prompt, an |
| 2 | // error, escape sequences in output, a wait that honours cancellation, and |
| 3 | // both the Codewhale-native and the DSH-compatible registration shapes. |
| 4 | export const name = 'ext-commands' |
| 5 | export const inject = ['commands'] |
| 6 | |
| 7 | export function apply(ctx) { |
| 8 | ctx.commands.register({ |
| 9 | name: 'ext-echo', |
| 10 | description: 'Echo the arguments.', |
| 11 | argumentHint: '<text>', |
| 12 | handler: ({ args }) => ({ kind: 'success', text: `echo: ${args}` }), |
| 13 | }) |
| 14 | ctx.commands.register({ |
| 15 | name: 'ext-ask', |
| 16 | description: 'Submit a prompt built from the arguments.', |
| 17 | input: { hint: '<topic>' }, |
| 18 | handler: ({ args }) => ({ kind: 'submit', prompt: `Summarize: ${args}`, text: 'Asking the model.' }), |
| 19 | }) |
| 20 | ctx.commands.register({ |
| 21 | name: 'ext-fail', |
| 22 | description: 'Report an error.', |
| 23 | handler: () => ({ kind: 'error', text: 'unknown topic' }), |
| 24 | }) |
| 25 | ctx.commands.register({ |
| 26 | name: 'ext-throw', |
| 27 | description: 'Throw from the handler.', |
| 28 | handler: () => { |
| 29 | throw new Error('boom') |
| 30 | }, |
| 31 | }) |
| 32 | ctx.commands.register({ |
| 33 | name: 'ext-ansi', |
| 34 | description: 'Return terminal escape sequences.', |
| 35 | handler: () => 'plain \u001b[31mred\u001b[0m \u001b]0;title\u0007end', |
| 36 | }) |
| 37 | // DSH shape: `rawInput` carries its leading separator. |
| 38 | ctx.commands.register({ |
| 39 | name: 'ext-dsh', |
| 40 | description: 'DSH-style handler.', |
| 41 | input: { hint: '<x>' }, |
| 42 | handler: ({ rawInput }) => ({ kind: 'success', text: JSON.stringify(rawInput) }), |
| 43 | }) |
| 44 | ctx.commands.register({ |
| 45 | name: 'ext-slow', |
| 46 | description: 'Wait for the given milliseconds (default 30000), or until cancelled.', |
| 47 | argumentHint: '<ms>', |
| 48 | handler: ({ args, signal }) => |
| 49 | new Promise((resolve, reject) => { |
| 50 | const timer = setTimeout(() => resolve({ kind: 'success', text: 'waited' }), Number(args) || 30000) |
| 51 | signal.addEventListener('abort', () => { |
| 52 | clearTimeout(timer) |
| 53 | reject(new Error('aborted')) |
| 54 | }) |
| 55 | }), |
| 56 | }) |
| 57 | } |
| 58 |