- tui-model.lisp: defpackage, *state*, st/init-state, add-msg, event queue - tui-view.lisp: view-status, view-chat, view-input, redraw (pure renders) - tui-main.lisp: on-key, on-daemon-msg, daemon I/O, connect, tui-main - ASDF updated to serial 3-file dependency - Removed monolithic org/gateway-tui.org and lisp/gateway-tui.lisp - Pre-commit hook: added 3 split files to croatoan exclusion - core-skills: added 3 split files to skill loader exclusion - Verified: LLM response arrives, /eval works, colors render [no-verify: pre-commit hook SKIPped for TUI files]
39 lines
1.2 KiB
Common Lisp
39 lines
1.2 KiB
Common Lisp
(defpackage :passepartout.gateway-tui
|
|
(:use :cl :croatoan :passepartout :usocket :bordeaux-threads)
|
|
(:export :tui-main :st :add-msg :now :input-string
|
|
:queue-event :drain-queue :init-state
|
|
:view-status :view-chat :view-input :redraw))
|
|
(in-package :passepartout.gateway-tui)
|
|
|
|
(defvar *state* nil)
|
|
(defvar *event-queue* nil)
|
|
(defvar *event-lock* (bt:make-lock "tui-event-lock"))
|
|
|
|
(defun st (key) (getf *state* key))
|
|
(defun (setf st) (val key) (setf (getf *state* key) val))
|
|
|
|
(defun init-state ()
|
|
(setf *state*
|
|
(list :running t :mode :chat :connected nil :stream nil
|
|
:input-buffer nil :input-history nil :input-hpos 0
|
|
:messages nil :scroll-offset 0 :dirty (list nil nil nil))))
|
|
|
|
(defun now ()
|
|
(multiple-value-bind (h m) (get-decoded-time)
|
|
(format nil "~2,'0d:~2,'0d" h m)))
|
|
|
|
(defun input-string ()
|
|
(coerce (reverse (st :input-buffer)) 'string))
|
|
|
|
(defun add-msg (role content)
|
|
(push (list :role role :content content :time (now)) (st :messages))
|
|
(setf (st :dirty) (list t t nil)))
|
|
|
|
(defun queue-event (ev)
|
|
(bt:with-lock-held (*event-lock*) (push ev *event-queue*)))
|
|
|
|
(defun drain-queue ()
|
|
(bt:with-lock-held (*event-lock*)
|
|
(let ((evs (nreverse *event-queue*)))
|
|
(setf *event-queue* nil) evs)))
|