skills/zhinjs/ai-skills/zhin-prompt-interaction

zhin-prompt-interaction

SKILL.md

Zhin Prompt Interaction Guide

Use this skill to collect interactive input from users during conversations in Zhin plugins. The Prompt class supports text, number, confirmation, list, option selection, and Schema-driven input.

Creating a Prompt

import { usePlugin, Prompt, MessageCommand } from 'zhin.js'

const plugin = usePlugin()

plugin.addCommand(
  new MessageCommand('setup')
    .desc('Interactive setup wizard')
    .action(async (message) => {
      const prompt = new Prompt(plugin, message)

      const name = await prompt.text('What is your name?')
      const age = await prompt.number('How old are you?')
      const confirm = await prompt.confirm('Is this correct?')

      if (confirm) {
        return `Welcome, ${name} (age ${age})!`
      }
      return 'Setup cancelled.'
    })
)

Prompt Types

Text Input

const name = await prompt.text('Enter your name')

// With timeout (ms) and default value
const name = await prompt.text('Enter your name', 30000, 'Anonymous', 'Timed out')

Number Input

const count = await prompt.number('How many items?')

// With timeout and default
const count = await prompt.number('How many items?', 30000, 1, 'Timed out')

Confirmation

// User must type "yes" to confirm
const ok = await prompt.confirm('Are you sure?')

// Custom confirmation word
const ok = await prompt.confirm('Continue?', 'ok')

// With timeout and default
const ok = await prompt.confirm('Continue?', 'yes', 30000, false, 'Timed out')

List Input

Collect multiple values separated by a delimiter:

// Text list (comma-separated by default)
const tags = await prompt.list('Enter tags')
// User types: "tag1,tag2,tag3"  → ['tag1', 'tag2', 'tag3']

// Number list with custom separator
const scores = await prompt.list('Enter scores', {
  type: 'number',
  separator: ' ',
  defaultValue: [0],
  timeout: 60000,
})

Option Selection (Pick)

// Single select
const color = await prompt.pick('Choose a color', {
  type: 'text',
  options: [
    { label: 'Red', value: 'red' },
    { label: 'Green', value: 'green' },
    { label: 'Blue', value: 'blue' },
  ],
})
// Displays:
// Choose a color
// 1.Red
// 2.Green
// 3.Blue
// User types: "2" → 'green'

// Multi-select
const colors = await prompt.pick('Choose colors', {
  type: 'text',
  multiple: true,
  separator: ',',
  options: [
    { label: 'Red', value: 'red' },
    { label: 'Green', value: 'green' },
    { label: 'Blue', value: 'blue' },
  ],
})
// User types: "1,3" → ['red', 'blue']

Schema-based Input

Collect structured input driven by Schema definitions:

import { Schema } from '@zhin.js/schema'

// Single schema value
const value = await prompt.getValueWithSchema(
  Schema.string().description('Enter your email')
)

// Multiple schema values at once
const result = await prompt.getValueWithSchemas({
  name: Schema.string().description('Your name'),
  age: Schema.number().description('Your age'),
  admin: Schema.boolean().description('Are you admin?'),
})
// result = { name: 'Alice', age: 25, admin: true }

Supported Schema Types

Type Prompt Used
string text()
number number()
boolean confirm()
object Recursively prompts each field
list list()
date Text input parsed as Date
regexp Text input parsed as RegExp
const Returns the default value
Schema with options pick()

Timeout and Error Handling

All prompts accept a timeout parameter (default: 3 minutes). On timeout, the default value is used if provided, otherwise an error is thrown:

try {
  const name = await prompt.text('Enter name', 10000) // 10 seconds
} catch (error) {
  // error.message = 'Input timeout'
  await message.$reply('You took too long!')
}

Using One-time Middleware

For lower-level control, use prompt.middleware() directly:

prompt.middleware(
  (input) => {
    if (input instanceof Error) {
      // Timeout occurred
      return
    }
    // input is the raw message string
    console.log('User said:', input)
  },
  60000,           // timeout in ms
  'Input timed out' // timeout message
)

Checklist

  • Create Prompt with new Prompt(plugin, message) inside a command action.
  • Choose the appropriate prompt type for each input.
  • Always handle timeouts with default values or try/catch.
  • Use Schema-based prompts for structured configuration collection.
  • The prompt automatically matches user sessions by adapter-bot-channel-sender.
Weekly Installs
2
First Seen
Feb 9, 2026
Installed on
opencode2
gemini-cli2
antigravity2
claude-code2
github-copilot2
codex2