AI streaming

[VDS7] Instead of waiting for a whole AI reply, a script can receive it progressively — the "typewriter" effect — and show it in a dialog as it arrives. The request is started with ai stream, which returns immediately, so the application stays alive (buttons and other timers keep responding) while the reply streams in.

There are two modes, chosen by whether you add ,EVENT:

  • ai stream,<prompt>pull mode (single-threaded): the script reads the pieces at its own pace with @AI(chunk), typically on a TIMER event.
  • ai stream,<prompt>,EVENTpush mode: a background thread reads the stream and raises an AI event for each fragment, then an AIEND event at the end. The script handles :AI / :AIEND directly, with no timer.

Both modes share the same accessors:

  • @AI(chunk) — the next fragment of text (empty if nothing new). In pull mode, call it in the timer loop; in push mode, call it once per AI event.
  • @AI(streaming)1 while the stream is active, 0 once finished.
  • @AI(response) — the text assembled so far (and complete at the end). @AI(tokens) and @AI(error) behave as for @AI. The conversation is remembered at the end, so multi-turn is preserved.

Pull mode (TIMER)

ai config,anthropic,claude-haiku-4-5-20251001
ai stream,Tell the story of the Mediterranean in 200 words.
timer 1,100
:loop
  wait event
  gosub @event()
goto loop
:TIMER
  %c = @ai(chunk)
  if @unequal(%c,)  dialog set,output,@dlgtext(output)%c
  if @equal(@ai(streaming),0)  stop
  exit

Push mode (AI event, no timer)

ai config,anthropic,claude-haiku-4-5-20251001
ai stream,Tell the story of the Mediterranean in 200 words.,EVENT
:loop
  wait event
  gosub @event()
goto loop
:AI
  dialog set,output,@dlgtext(output)@ai(chunk)
  exit
:AIEND
  REM ... end-of-stream actions (log, enable a button...) ...
  stop

A note on EXIT and STOP

DialogScript has no return keyword — exit does both jobs depending on context: inside a subroutine called by gosub it returns; at the main level it ends the script. To stop from anywhere — including deep inside a gosub — use stop. So an event handler does exit to go back to the wait loop, or runs its final actions and then stop to end.

See also