gitignore: stop tracking generated lib/**/*.sls and tui-shim binaries

ober

20eb32498d80a260801182e5920029f0554c2b14

diff --git a/.gitignore b/.gitignore
index 6557c8d..8661307 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,11 @@
 .jerbuild-hashes
 jcode.json
 
+# Generated Scheme libraries (built from src/**/*.ss by jerbuild)
+/lib/**/*.sls
+/jcode_tui_shim.dylib
+/jcode_tui_shim.so
+
 # Android build outputs
 /android/android.jar
 /android/build/
diff --git a/lib/jcode/core/agent.sls b/lib/jcode/core/agent.sls
deleted file mode 100644
index 2d595a1..0000000
--- a/lib/jcode/core/agent.sls
+++ /dev/null
@@ -1,430 +0,0 @@
-#!chezscheme
-;;; Generated by jerbuild — DO NOT EDIT
-;;; Source: src/jcode/core/agent.ss
-
-(library (jcode core agent)
-  (export agent-run agent-chat agent-step current-stream-cb
-    current-tool-cb current-usage-cb current-provider-override
-    current-model-override)
-  (import
-    (except (chezscheme) make-hash-table hash-table? iota \x31;+ \x31;-
-      getenv path-extension path-absolute? thread? make-mutex
-      mutex? mutex-name)
-    (std text json) (std misc thread) (std misc string)
-    (std os path) (jcode core config) (jcode core log)
-    (jcode core message) (jcode core session)
-    (jcode provider provider) (jcode tool registry)
-    (jerboa core) (jerboa runtime))
-  (def logger (make-logger "agent"))
-  (def current-provider-override (make-parameter #f))
-  (def current-model-override (make-parameter #f))
-  (def (system-prompt)
-       (format
-         "You are an expert AI coding assistant. You help users with software development tasks.\nWorking directory: ~a\nCurrent mode: ~a\n\nYou have access to these tools:\n~a\n\n~a\n\nIMPORTANT: Do NOT call the same tool repeatedly with the same or similar arguments.\nIf you already retrieved information, use what you have. Use batch to parallelize.\nUse glob to find files by pattern instead of exploring directory by directory with ls.\n\nWhen the user asks you to do something:\n1. Think about what tools you need\n2. Use tools to gather information or make changes\n3. Report back with results\n\nBe concise and helpful. When editing files, make minimal targeted changes.\nPrefer using the edit tool over write for modifying existing files."
-         (current-directory) (mode-label (current-mode))
-         (format-tool-list) (mode-instructions (current-mode))))
-  (def (format-tool-list)
-       "Build a bullet list of all registered tools for the system prompt."
-       (let ([names (sort string<? (list-tools))])
-         (string-join
-           (map (lambda (n) (string-append "- " n)) names)
-           "\n")))
-  (def (mode-label m)
-       (case m
-         [(plan) "PLAN (read-only)"]
-         [(build) "BUILD (read+write)"]
-         [else (format "~a" m)]))
-  (def (mode-instructions m)
-       (case m
-         [(plan)
-          "You are in PLAN mode: write/edit/bash/git_commit are disabled. Investigate the codebase with read tools (read, ls, glob, grep, git_status, git_diff, git_log, git_show, fetch) and produce a plan describing what you would change. Do NOT attempt write operations — they will be rejected. Tell the user to switch to BUILD mode (/build) when they want you to apply the plan."]
-         [else
-          "You are in BUILD mode: full read+write access is available."]))
-  (def current-stream-cb (make-parameter #f))
-  (def current-tool-cb (make-parameter #f))
-  (def current-usage-cb (make-parameter #f))
-  (def *max-tool-rounds* 100)
-  (def *max-tool-lines* 2000)
-  (def *max-tool-bytes* 51200)
-  (def (refresh-system-prompt messages)
-       "Replace the leading system message (if any) with a fresh one reflecting\n   the current mode. Returns a NEW list — does not mutate. If there's no\n   leading system message, prepends one."
-       (let ([fresh (make-system-message (system-prompt))])
-         (cond
-           [(null? messages) (list fresh)]
-           [(equal? (message-role (car messages)) "system")
-            (cons fresh (cdr messages))]
-           [else (cons fresh messages)])))
-  (def (truncated-dir)
-       "Return ~/.jcode/truncated/, creating it if needed."
-       (let ([dir (path-join (jcode-home) "truncated")])
-         (unless (file-exists? dir) (mkdir dir))
-         dir))
-  (def (truncate-tool-output text)
-       "Cap tool output at *max-tool-lines* / *max-tool-bytes*. If truncated,\n   save the full output to ~/.jcode/truncated/ and return a preview + hint."
-       (let* ([lines (string-split text #\newline)]
-              [total-bytes (string-length text)]
-              [total-lines (length lines)])
-         (if (and (<= total-lines *max-tool-lines*)
-                  (<= total-bytes *max-tool-bytes*))
-             text
-             (let loop ([remaining lines] [count 0] [bytes 0] [acc '()])
-               (if (or (null? remaining)
-                       (>= count *max-tool-lines*)
-                       (>= bytes *max-tool-bytes*))
-                   (let* ([preview (string-join (reverse acc) "\n")]
-                          [file (path-join
-                                  (truncated-dir)
-                                  (format
-                                    "tool-~a.txt"
-                                    (time-second (current-time))))]
-                          [removed (if (> total-bytes *max-tool-bytes*)
-                                       (format
-                                         "~a bytes"
-                                         (- total-bytes
-                                            (string-length preview)))
-                                       (format
-                                         "~a lines"
-                                         (- total-lines count)))])
-                     (with-output-to-file file (lambda () (display text)))
-                     (string-append
-                       preview
-                       (format
-                         "\n\n...~a truncated...\n\nFull output saved to: ~a\nUse grep to search or read with specific line ranges."
-                         removed
-                         file)))
-                   (let ([line (car remaining)])
-                     (loop
-                       (cdr remaining)
-                       (+ count 1)
-                       (+ bytes (string-length line) 1)
-                       (cons line acc))))))))
-  (def (try-parse-text-tool-calls text)
-       "Check if text consists entirely of tool-call patterns like 'read(path=\"f\")'.\n   Returns list of tool-call objects, or '()."
-       (let* ([trimmed (string-trim text)]
-              [lines (string-split trimmed #\newline)]
-              [non-empty (filter
-                           (lambda (l) (not (string=? (string-trim l) "")))
-                           lines)]
-              [parsed (filter
-                        (lambda (x) x)
-                        (map parse-one-text-tool-call non-empty))])
-         (if (and (not (null? parsed))
-                  (= (length parsed) (length non-empty)))
-             (begin
-               (log-warn
-                 logger
-                 "text-tool-calls-detected"
-                 `((count . ,(length parsed))
-                    (names . ,(map tool-call-name parsed))))
-               parsed)
-             '())))
-  (def (parse-one-text-tool-call line)
-       "Parse 'tool_name(key=\"val\")' into a tool-call, or #f if not a tool call."
-       (let* ([trimmed (string-trim line)]
-              [len (string-length trimmed)])
-         (and (> len 3)
-              (char=? (string-ref trimmed (- len 1)) #\))
-              (let ([paren (string-contains trimmed "(")])
-                (and paren
-                     (> paren 0)
-                     (let ([name (substring trimmed 0 paren)])
-                       (and (tool-exists? name)
-                            (let* ([args-str (substring
-                                               trimmed
-                                               (+ paren 1)
-                                               (- len 1))]
-                                   [json-args (parse-text-tool-args
-                                                args-str)])
-                              (and json-args
-                                   (restore-tool-call
-                                     (format
-                                       "text_~a_~a"
-                                       name
-                                       (time-second (current-time)))
-                                     name
-                                     json-args))))))))))
-  (def (parse-text-tool-args args-str)
-       "Parse key=\"value\" pairs or JSON into a JSON string. Returns string or #f."
-       (let ([trimmed (string-trim args-str)])
-         (if (string=? trimmed "")
-             "{}"
-             (or (guard (e [#t #f])
-                   (let ([ht (string->json-object trimmed)])
-                     (and (hash-table? ht) (json-object->string ht))))
-                 (guard (e [#t #f])
-                   (let ([ht (string->json-object
-                               (string-append "{" trimmed "}"))])
-                     (and (hash-table? ht) (json-object->string ht))))
-                 (guard (e [#t #f])
-                   (let ([ht (make-hash-table)])
-                     (for-each
-                       (lambda (pair)
-                         (let* ([p (string-trim pair)]
-                                [eq-pos (string-contains p "=")])
-                           (when (and eq-pos (> eq-pos 0))
-                             (let* ([key (string-trim
-                                           (substring p 0 eq-pos))]
-                                    [val (string-trim
-                                           (substring
-                                             p
-                                             (+ eq-pos 1)
-                                             (string-length p)))])
-                               (hash-put!
-                                 ht
-                                 key
-                                 (if (and (>= (string-length val) 2)
-                                          (char=? (string-ref val 0) #\")
-                                          (char=?
-                                            (string-ref
-                                              val
-                                              (- (string-length val) 1))
-                                            #\"))
-                                     (substring
-                                       val
-                                       1
-                                       (- (string-length val) 1))
-                                     val))))))
-                       (string-split args-str #\,))
-                     (and (> (length (hash-keys ht)) 0)
-                          (json-object->string ht))))))))
-  (def (agent-run session-id user-input)
-       (log-info logger "agent-run" `((session . ,session-id)))
-       (let ([existing (session-get-messages session-id)])
-         (when (null? existing)
-           (session-add-message
-             session-id
-             (make-system-message (system-prompt)))))
-       (session-add-message
-         session-id
-         (make-user-message user-input))
-       (if (current-stream-cb)
-           (agent-loop-stream
-             session-id
-             (session-get-messages session-id)
-             0)
-           (agent-loop
-             session-id
-             (session-get-messages session-id)
-             0)))
-  (def (agent-loop session-id messages round)
-       (let* ([provider (get-current-provider)]
-              [tools (get-tool-schemas)]
-              [msgs (refresh-system-prompt messages)]
-              [response (provider-chat provider msgs tools)])
-         (log-debug
-           logger
-           "got-response"
-           `((role . ,(message-role response))))
-         (let* ([content (or (message-content response) "")]
-                [real-tcs (message-tool-calls response)]
-                [text-tcs (if (and (not real-tcs)
-                                   (not (string=? content "")))
-                              (try-parse-text-tool-calls content)
-                              '())]
-                [effective (if (null? text-tcs)
-                               response
-                               (make-assistant-message #f text-tcs))]
-                [tcs (or (message-tool-calls effective) '())])
-           (session-add-message session-id effective)
-           (cond
-             [(null? tcs) effective]
-             [(>= round *max-tool-rounds*)
-              (log-warn logger "max-rounds" `((round . ,round)))
-              (let ([results (execute-tool-calls tcs)])
-                (for-each
-                  (lambda (r) (session-add-message session-id r))
-                  results)
-                (let* ([final-msgs (refresh-system-prompt
-                                     (session-get-messages session-id))]
-                       [final (provider-chat provider final-msgs '())])
-                  (session-add-message session-id final)
-                  final))]
-             [else
-              (let ([results (execute-tool-calls tcs)])
-                (for-each
-                  (lambda (result) (session-add-message session-id result))
-                  results)
-                (agent-loop
-                  session-id
-                  (session-get-messages session-id)
-                  (+ round 1)))]))))
-  (def (agent-loop-stream session-id messages round)
-       (let* ([provider (get-current-provider)]
-              [tools (get-tool-schemas)]
-              [msgs (refresh-system-prompt messages)])
-         (let-values ([(content tool-calls usage)
-                       (provider-stream-chat
-                         provider
-                         msgs
-                         tools
-                         (current-stream-cb))])
-           (when (and usage (current-usage-cb))
-             ((current-usage-cb) usage))
-           (let* ([text-tcs (if (and (null? tool-calls)
-                                     (not (string=? content "")))
-                                (try-parse-text-tool-calls content)
-                                '())]
-                  [effective-tcs (if (null? tool-calls)
-                                     text-tcs
-                                     tool-calls)]
-                  [effective-content (if (and (null? tool-calls)
-                                              (not (null? text-tcs)))
-                                         #f
-                                         (if (string=? content "")
-                                             #f
-                                             content))]
-                  [response (make-assistant-message
-                              effective-content
-                              (if (null? effective-tcs)
-                                  #f
-                                  effective-tcs))])
-             (session-add-message session-id response)
-             (cond
-               [(null? effective-tcs) response]
-               [(>= round *max-tool-rounds*)
-                (log-warn logger "max-rounds" `((round . ,round)))
-                (let ([results (execute-tool-calls effective-tcs)])
-                  (for-each
-                    (lambda (r) (session-add-message session-id r))
-                    results)
-                  (let-values ([(fc _tc _u)
-                                (provider-stream-chat
-                                  provider
-                                  (refresh-system-prompt
-                                    (session-get-messages session-id))
-                                  '()
-                                  (current-stream-cb))])
-                    (let ([final (make-assistant-message
-                                   (if (string=? fc "") #f fc)
-                                   #f)])
-                      (session-add-message session-id final)
-                      final)))]
-               [else
-                (let ([results (execute-tool-calls effective-tcs)])
-                  (for-each
-                    (lambda (r) (session-add-message session-id r))
-                    results)
-                  (agent-loop-stream
-                    session-id
-                    (session-get-messages session-id)
-                    (+ round 1)))])))))
-  (def (execute-tool-calls tool-calls)
-       (log-info
-         logger
-         "executing-tools"
-         `((count . ,(length tool-calls))))
-       (if (<= (length tool-calls) 1)
-           (map execute-single-tool tool-calls)
-           (let ([threads (map (lambda (tc)
-                                 (spawn
-                                   (lambda () (execute-single-tool tc))))
-                               tool-calls)])
-             (map thread-join! threads))))
-  (def (execute-single-tool tc)
-       (let* ([name (tool-call-name tc)]
-              [raw-args (tool-call-arguments tc)]
-              [args (guard (e [#t #f]) (string->json-object raw-args))]
-              [cb (current-tool-cb)])
-         (if (not args)
-             (begin
-               (log-error
-                 logger
-                 "tool-args-parse-failed"
-                 `((tool . ,name)
-                    (raw-args
-                      .
-                      ,(if (> (string-length raw-args) 200)
-                           (substring raw-args 0 200)
-                           raw-args))))
-               (make-tool-result
-                 (tool-call-id tc)
-                 (format
-                   "Error: malformed tool arguments JSON — ~a"
-                   raw-args)))
-             (begin
-               (when cb (cb 'start name args))
-               (let* ([raw-result (tool-execute name args)]
-                      [result (truncate-tool-output raw-result)])
-                 (log-debug
-                   logger
-                   "tool-result"
-                   `((tool . ,name)
-                      (result-length . ,(string-length result))))
-                 (when cb (cb 'end name args))
-                 (make-tool-result (tool-call-id tc) result))))))
-  (def (get-current-provider)
-       (let* ([provider-name (or (current-provider-override)
-                                 (config-provider))]
-              [api-key (config-get-provider-key provider-name)]
-              [model (or (current-model-override)
-                         (config-ref "model")
-                         (config-default-model provider-name))])
-         (make-provider provider-name api-key model)))
-  (def (agent-chat user-input)
-       (let* ([provider (get-current-provider)]
-              [tools (get-tool-schemas)]
-              [messages (list
-                          (make-system-message (system-prompt))
-                          (make-user-message user-input))])
-         (if (current-stream-cb)
-             (agent-chat-loop-stream provider messages tools 0)
-             (agent-chat-loop provider messages tools 0))))
-  (def (agent-chat-loop provider messages tools round)
-       (let* ([msgs messages]
-              [response (provider-chat provider msgs tools)])
-         (cond
-           [(not (message-tool-calls response))
-            (message-content response)]
-           [(>= round *max-tool-rounds*)
-            (let* ([results (execute-tool-calls
-                              (message-tool-calls response))]
-                   [new-messages (append msgs (list response) results)]
-                   [final (provider-chat provider new-messages '())])
-              (or (message-content final) ""))]
-           [else
-            (let* ([results (execute-tool-calls
-                              (message-tool-calls response))]
-                   [new-messages (append msgs (list response) results)])
-              (agent-chat-loop
-                provider
-                new-messages
-                tools
-                (+ round 1)))])))
-  (def (agent-chat-loop-stream provider messages tools round)
-       (let* ([msgs messages])
-         (let-values ([(content tool-calls usage)
-                       (provider-stream-chat
-                         provider
-                         msgs
-                         tools
-                         (current-stream-cb))])
-           (cond
-             [(null? tool-calls) content]
-             [(>= round *max-tool-rounds*)
-              (let* ([response (make-assistant-message
-                                 (if (string=? content "") #f content)
-                                 tool-calls)]
-                     [results (execute-tool-calls tool-calls)]
-                     [new-msgs (append msgs (list response) results)])
-                (let-values ([(fc _tc _u)
-                              (provider-stream-chat
-                                provider
-                                new-msgs
-                                '()
-                                (current-stream-cb))])
-                  fc))]
-             [else
-              (let* ([response (make-assistant-message
-                                 (if (string=? content "") #f content)
-                                 tool-calls)]
-                     [results (execute-tool-calls tool-calls)]
-                     [new-msgs (append msgs (list response) results)])
-                (agent-chat-loop-stream
-                  provider
-                  new-msgs
-                  tools
-                  (+ round 1)))]))))
-  (def (agent-step messages)
-       (let* ([provider (get-current-provider)]
-              [tools (get-tool-schemas)])
-         (provider-chat provider messages tools))))
diff --git a/lib/jcode/core/config.sls b/lib/jcode/core/config.sls
deleted file mode 100644
index c4600d5..0000000
--- a/lib/jcode/core/config.sls
+++ /dev/null
@@ -1,119 +0,0 @@
-#!chezscheme
-;;; Generated by jerbuild — DO NOT EDIT
-;;; Source: src/jcode/core/config.ss
-
-(library (jcode core config)
-  (export load-config jcode-home config-ref config-api-key
-    config-model config-provider config-get-provider-key
-    config-default-model *config*)
-  (import
-    (except (chezscheme) make-hash-table hash-table? iota \x31;+ \x31;-
-      getenv path-extension path-absolute? thread? make-mutex
-      mutex? mutex-name)
-    (std text json) (std os path) (jcode core models)
-    (jerboa core) (jerboa runtime))
-  (define *config*--cell (vector (make-parameter #f)))
-  (def (jcode-home)
-       "Return ~/.jcode, creating it if needed."
-       (let ([dir (path-join (getenv "HOME") ".jcode")])
-         (unless (file-exists? dir) (mkdir dir))
-         dir))
-  (def (config-paths)
-       (list
-         (path-join (current-directory) "jcode.json")
-         (path-join (jcode-home) "config.json")))
-  (def (find-config-file)
-       (let loop ([paths (config-paths)])
-         (cond
-           [(null? paths) #f]
-           [(file-exists? (car paths)) (car paths)]
-           [else (loop (cdr paths))])))
-  (def (load-config)
-       (let* ([file (find-config-file)]
-              [file-config (if file
-                               (call-with-input-file file read-json)
-                               (make-hash-table))]
-              [config (merge-env-config file-config)])
-         (*config* config)
-         config))
-  (def (merge-env-config config)
-       (let ([providers (or (hash-get config "providers")
-                            (make-hash-table))])
-         (merge-opencode-keys! providers)
-         (for-each
-           (lambda (pair)
-             (let ([key (getenv (car pair))])
-               (when key
-                 (let ([p (or (hash-get providers (cdr pair))
-                              (make-hash-table))])
-                   (hash-put! p "api_key" key)
-                   (hash-put! providers (cdr pair) p)))))
-           '(("OPENAI_API_KEY" . "openai") ("ANTHROPIC_API_KEY" . "anthropic")
-              ("GOOGLE_API_KEY" . "google")
-              ("OPENROUTER_API_KEY" . "openrouter")
-              ("DEEPSEEK_API_KEY" . "deepseek") ("XAI_API_KEY" . "xai")
-              ("GROQ_API_KEY" . "groq") ("MISTRAL_API_KEY" . "mistral")
-              ("TOGETHER_API_KEY" . "together")
-              ("CEREBRAS_API_KEY" . "cerebras")
-              ("PERPLEXITY_API_KEY" . "perplexity")))
-         (hash-put! config "providers" providers)
-         config))
-  (def (merge-opencode-keys! providers)
-       (let ([auth-file (let ([jcode-auth (path-join
-                                            (jcode-home)
-                                            "auth.json")])
-                          (if (file-exists? jcode-auth)
-                              jcode-auth
-                              (path-join (getenv "HOME") ".local" "share"
-                                "opencode" "auth.json")))])
-         (when (file-exists? auth-file)
-           (try (let ([auth (call-with-input-file
-                              auth-file
-                              read-json)])
-                  (for-each
-                    (lambda (name)
-                      (let ([entry (hash-get auth name)])
-                        (when (and entry (hash-get entry "key"))
-                          (let ([p (or (hash-get providers name)
-                                       (make-hash-table))])
-                            (unless (hash-get p "api_key")
-                              (hash-put!
-                                p
-                                "api_key"
-                                (hash-ref entry "key"))
-                              (hash-put! providers name p))))))
-                    '("openrouter" "deepseek" "google" "openai" "anthropic" "xai"
-                       "groq" "mistral" "together" "cerebras"
-                       "perplexity")))
-                (catch (e) (void))))))
-  (def (config-ref . keys)
-       (let loop ([obj (*config*)] [keys keys])
-         (cond
-           [(null? keys) obj]
-           [(not (hash-table? obj)) #f]
-           [else (loop (hash-get obj (car keys)) (cdr keys))])))
-  (def (config-get-provider-key provider)
-       (config-ref "providers" provider "api_key"))
-  (def (config-model)
-       (or (config-ref "model")
-           (config-default-model (config-provider))))
-  (def (config-default-model provider)
-       (provider-default-model provider))
-  (def (config-provider)
-       (or (config-ref "provider")
-           (config-detect-provider)
-           "anthropic"))
-  (def (config-detect-provider)
-       (let loop ([names '("anthropic" "openrouter" "openai" "deepseek" "google" "xai"
-                            "groq" "mistral" "together" "cerebras"
-                            "perplexity")])
-         (cond
-           [(null? names) #f]
-           [(config-get-provider-key (car names)) (car names)]
-           [#t (loop (cdr names))])))
-  (def (config-api-key)
-       (config-get-provider-key (config-provider)))
-  (define-syntax *config*
-    (identifier-syntax
-      [id (vector-ref *config*--cell 0)]
-      [(set! id val) (vector-set! *config*--cell 0 val)])))
diff --git a/lib/jcode/core/debug-repl.sls b/lib/jcode/core/debug-repl.sls
deleted file mode 100644
index 2a863f3..0000000
--- a/lib/jcode/core/debug-repl.sls
+++ /dev/null
@@ -1,217 +0,0 @@
-#!chezscheme
-;;; Generated by jerbuild — DO NOT EDIT
-;;; Source: src/jcode/core/debug-repl.ss
-
-(library (jcode core debug-repl)
-  (export start-jcode-repl! stop-jcode-repl! jcode-repl-port)
-  (import
-    (except (chezscheme) make-hash-table hash-table? iota \x31;+ \x31;-
-      getenv path-extension path-absolute? thread? make-mutex
-      mutex? mutex-name)
-    (jcode core log)
-    (jerboa core)
-    (jerboa runtime))
-  (def logger (make-logger "debug-repl"))
-  (def _libc-loaded
-       (guard (e [#t #f]) (load-shared-object #f)))
-  (def c-socket
-       (foreign-procedure "socket" (int int int) int))
-  (def c-bind (foreign-procedure "bind" (int void* int) int))
-  (def c-listen (foreign-procedure "listen" (int int) int))
-  (def c-accept
-       (foreign-procedure "accept" (int void* void*) int))
-  (def c-close (foreign-procedure "close" (int) int))
-  (def c-setsockopt
-       (foreign-procedure "setsockopt"
-         (int int int void* int)
-         int))
-  (def c-htons
-       (foreign-procedure "htons" (unsigned-short) unsigned-short))
-  (def c-getsockname
-       (foreign-procedure "getsockname" (int void* void*) int))
-  (def c-fcntl (foreign-procedure "fcntl" (int int int) int))
-  (def c-dup (foreign-procedure "dup" (int) int))
-  (def c-errno-location
-       (let ([mt (symbol->string (machine-type))])
-         (if (and (>= (string-length mt) 3)
-                  (string=?
-                    (substring
-                      mt
-                      (- (string-length mt) 3)
-                      (string-length mt))
-                    "osx"))
-             (foreign-procedure "__error" () void*)
-             (foreign-procedure "__errno_location" () void*))))
-  (def (get-errno) (foreign-ref 'int (c-errno-location) 0))
-  (def AF_INET 2)
-  (def SOCK_STREAM 1)
-  (def SOL_SOCKET 65535)
-  (def SO_REUSEADDR 4)
-  (def SOCKADDR_IN_SIZE 16)
-  (def F_GETFL 3)
-  (def F_SETFL 4)
-  (def O_NONBLOCK 4)
-  (def EINTR 4)
-  (def EAGAIN 35)
-  (def *retry-delay* (make-time 'time-duration 10000000 0))
-  (def (set-nonblocking! fd)
-       (let ([flags (c-fcntl fd F_GETFL 0)])
-         (c-fcntl fd F_SETFL (bitwise-ior flags O_NONBLOCK))))
-  (def (make-sockaddr-in port)
-       (let ([buf (foreign-alloc SOCKADDR_IN_SIZE)])
-         (let lp ([i 0])
-           (when (< i SOCKADDR_IN_SIZE)
-             (foreign-set! 'unsigned-8 buf i 0)
-             (lp (+ i 1))))
-         (foreign-set! 'unsigned-8 buf 0 SOCKADDR_IN_SIZE)
-         (foreign-set! 'unsigned-8 buf 1 AF_INET)
-         (foreign-set! 'unsigned-short buf 2 (c-htons port))
-         (foreign-set! 'unsigned-8 buf 4 127)
-         (foreign-set! 'unsigned-8 buf 5 0)
-         (foreign-set! 'unsigned-8 buf 6 0)
-         (foreign-set! 'unsigned-8 buf 7 1)
-         buf))
-  (def (sockaddr-in-port buf)
-       (let ([hi (foreign-ref 'unsigned-8 buf 2)]
-             [lo (foreign-ref 'unsigned-8 buf 3)])
-         (+ (* hi 256) lo)))
-  (def *server-fd* #f)
-  (def *server-port* #f)
-  (def *server-running* #f)
-  (def *repl-port-file*
-       (string-append
-         (or (getenv "HOME") ".")
-         "/.jcode-repl-port"))
-  (def (write-port-file! port-num)
-       (when (file-exists? *repl-port-file*)
-         (delete-file *repl-port-file*))
-       (call-with-output-file
-         *repl-port-file*
-         (lambda (p) (display port-num p) (newline p))))
-  (def (delete-port-file!)
-       (when (file-exists? *repl-port-file*)
-         (guard (e [#t (void)]) (delete-file *repl-port-file*))))
-  (def (client-repl fd)
-       (let* ([write-fd (c-dup fd)]
-              [ip (open-fd-input-port
-                    fd
-                    (buffer-mode block)
-                    (make-transcoder
-                      (utf-8-codec)
-                      (eol-style none)
-                      (error-handling-mode replace)))]
-              [op (open-fd-output-port
-                    write-fd
-                    (buffer-mode line)
-                    (make-transcoder
-                      (utf-8-codec)
-                      (eol-style lf)
-                      (error-handling-mode replace)))])
-         (dynamic-wind
-           void
-           (lambda ()
-             (let loop ()
-               (guard (e [#t (void)])
-                 (display "jcode> " op)
-                 (flush-output-port op)
-                 (let ([expr (guard (e
-                                      [#t
-                                       (display
-                                         (format
-                                           #f
-                                           "read error: ~a\n"
-                                           (if (message-condition? e)
-                                               (condition-message e)
-                                               e))
-                                         op)
-                                       (flush-output-port op)
-                                       'continue])
-                               (read ip))])
-                   (cond
-                     [(eof-object? expr) (void)]
-                     [(eq? expr 'continue) (loop)]
-                     [else
-                      (guard (e
-                               [#t
-                                (display
-                                  (format
-                                    #f
-                                    "error: ~a\n"
-                                    (if (message-condition? e)
-                                        (condition-message e)
-                                        e))
-                                  op)
-                                (flush-output-port op)])
-                        (call-with-values
-                          (lambda () (eval expr (interaction-environment)))
-                          (lambda results
-                            (for-each
-                              (lambda (v)
-                                (unless (eq? v (void))
-                                  (write v op)
-                                  (newline op)))
-                              results)
-                            (flush-output-port op))))
-                      (loop)])))))
-           (lambda ()
-             (guard (e [#t (void)]) (close-port ip))
-             (guard (e [#t (void)]) (close-port op))))))
-  (def (accept-loop server-fd)
-       (let loop ()
-         (when *server-running*
-           (let ([client-fd (c-accept server-fd 0 0)])
-             (cond
-               [(>= client-fd 0)
-                (fork-thread (lambda () (client-repl client-fd)))
-                (loop)]
-               [(let ([e (get-errno)]) (or (= e EINTR) (= e EAGAIN)))
-                (sleep *retry-delay*)
-                (loop)]
-               [else
-                (when *server-running* (sleep *retry-delay*) (loop))])))))
-  (def (start-jcode-repl! . args)
-       "Start the debug REPL. Pass a port number or 0 for auto-assign."
-       (stop-jcode-repl!)
-       (let ([port (if (pair? args) (car args) 0)])
-         (let ([fd (c-socket AF_INET SOCK_STREAM 0)])
-           (when (< fd 0) (error 'start-jcode-repl! "socket() failed"))
-           (let ([one (foreign-alloc 4)])
-             (foreign-set! 'int one 0 1)
-             (c-setsockopt fd SOL_SOCKET SO_REUSEADDR one 4)
-             (foreign-free one))
-           (let ([addr (make-sockaddr-in port)])
-             (let ([rc (c-bind fd addr SOCKADDR_IN_SIZE)])
-               (foreign-free addr)
-               (when (< rc 0)
-                 (c-close fd)
-                 (error 'start-jcode-repl! "bind() failed" port))))
-           (when (< (c-listen fd 4) 0)
-             (c-close fd)
-             (error 'start-jcode-repl! "listen() failed"))
-           (set-nonblocking! fd)
-           (let ([buf (foreign-alloc SOCKADDR_IN_SIZE)]
-                 [len (foreign-alloc 4)])
-             (foreign-set! 'int len 0 SOCKADDR_IN_SIZE)
-             (c-getsockname fd buf len)
-             (let ([actual-port (sockaddr-in-port buf)])
-               (foreign-free buf)
-               (foreign-free len)
-               (set! *server-fd* fd)
-               (set! *server-port* actual-port)
-               (set! *server-running* #t)
-               (write-port-file! actual-port)
-               (fork-thread (lambda () (accept-loop fd)))
-               (log-info logger "started" `((port . ,actual-port)))
-               actual-port)))))
-  (def (stop-jcode-repl!)
-       "Stop the debug REPL if running."
-       (when *server-running*
-         (set! *server-running* #f)
-         (when *server-fd*
-           (guard (e [#t (void)]) (c-close *server-fd*))
-           (set! *server-fd* #f)
-           (set! *server-port* #f))
-         (delete-port-file!)))
-  (def (jcode-repl-port)
-       "Return the port the debug REPL is listening on, or #f."
-       *server-port*))
diff --git a/lib/jcode/core/log.sls b/lib/jcode/core/log.sls
deleted file mode 100644
index d97bfd2..0000000
--- a/lib/jcode/core/log.sls
+++ /dev/null
@@ -1,51 +0,0 @@
-#!chezscheme
-;;; Generated by jerbuild — DO NOT EDIT
-;;; Source: src/jcode/core/log.ss
-
-(library (jcode core log)
-  (export make-logger current-log-level log-debug log-info
-    log-warn log-error err->string)
-  (import
-    (except (chezscheme) make-hash-table hash-table? iota \x31;+ \x31;-
-      getenv path-extension path-absolute? thread? make-mutex
-      mutex? mutex-name)
-    (std misc string)
-    (jerboa core)
-    (jerboa runtime))
-  (def *log-level* (make-parameter 'info))
-  (def (current-log-level . args)
-       (if (null? args) (*log-level*) (*log-level* (car args))))
-  (def (err->string e)
-       (with-output-to-string (lambda () (display-condition e))))
-  (def (log-at level label name msg data)
-       (when (level-enabled? level (*log-level*))
-         (let ([line (format "[~a] ~a: ~a" label name msg)])
-           (if (null? data)
-               (fprintf (current-error-port) "~a~n" line)
-               (fprintf
-                 (current-error-port)
-                 "~a  ~a~n"
-                 line
-                 (format-alist data))))))
-  (def (level-enabled? level min-level)
-       (case level
-         [(0) (eq? min-level 'debug)]
-         [(1) (memq min-level '(debug info))]
-         [(2) (memq min-level '(debug info warn))]
-         [(3) #t]
-         [else #t]))
-  (def (format-alist pairs)
-       (string-join
-         (map (lambda (p) (format "~a=~a" (car p) (cdr p))) pairs)
-         "  "))
-  (def (make-logger name) name)
-  (def (log-debug name msg . rest)
-       (log-at 0 "DEBUG" name msg
-         (if (null? rest) '() (car rest))))
-  (def (log-info name msg . rest)
-       (log-at 1 "INFO" name msg (if (null? rest) '() (car rest))))
-  (def (log-warn name msg . rest)
-       (log-at 2 "WARN" name msg (if (null? rest) '() (car rest))))
-  (def (log-error name msg . rest)
-       (log-at 3 "ERROR" name msg
-         (if (null? rest) '() (car rest)))))
diff --git a/lib/jcode/core/message.sls b/lib/jcode/core/message.sls
deleted file mode 100644
index b828b26..0000000
--- a/lib/jcode/core/message.sls
+++ /dev/null
@@ -1,86 +0,0 @@
-#!chezscheme
-;;; Generated by jerbuild — DO NOT EDIT
-;;; Source: src/jcode/core/message.ss
-
-(library (jcode core message)
-  (export make-message message? make-user-message
-    make-assistant-message make-tool-call restore-tool-call
-    make-tool-result make-system-message message-role
-    message-content message-tool-calls message-tool-call-id
-    message->json json->message tool-call-id tool-call-name
-    tool-call-arguments tool-call?)
-  (import
-    (except (chezscheme) make-hash-table hash-table? iota \x31;+ \x31;-
-      getenv path-extension path-absolute? thread? make-mutex
-      mutex? mutex-name)
-    (std text json) (std misc uuid) (jerboa core)
-    (jerboa runtime))
-  (defstruct message (role content tool-calls tool-call-id))
-  (defstruct tool-call-data (id name arguments))
-  (def (tool-call? x) (tool-call-data? x))
-  (def (tool-call-id tc) (tool-call-data-id tc))
-  (def (tool-call-name tc) (tool-call-data-name tc))
-  (def (tool-call-arguments tc) (tool-call-data-arguments tc))
-  (def (make-tool-call name arguments)
-       (make-tool-call-data (uuid-string) name arguments))
-  (def (restore-tool-call id name arguments)
-       (make-tool-call-data id name arguments))
-  (def (make-user-message content)
-       (make-message "user" content #f #f))
-  (def (make-assistant-message content . tool-calls)
-       (make-message
-         "assistant"
-         content
-         (if (null? tool-calls) #f (car tool-calls))
-         #f))
-  (def (make-tool-result call-id content)
-       (make-message "tool" content #f call-id))
-  (def (make-system-message content)
-       (make-message "system" content #f #f))
-  (def (json-null->false v) (if (eq? v (void)) #f v))
-  (def (message->json msg)
-       (let ([ht (make-hash-table)])
-         (hash-put! ht "role" (message-role msg))
-         (when (message-content msg)
-           (hash-put! ht "content" (message-content msg)))
-         (when (message-tool-calls msg)
-           (hash-put!
-             ht
-             "tool_calls"
-             (map tool-call->json (message-tool-calls msg))))
-         (when (message-tool-call-id msg)
-           (hash-put! ht "tool_call_id" (message-tool-call-id msg)))
-         ht))
-  (def (tool-call->json tc)
-       (let ([ht (make-hash-table)] [fn (make-hash-table)])
-         (hash-put! ht "id" (tool-call-id tc))
-         (hash-put! ht "type" "function")
-         (hash-put! fn "name" (tool-call-name tc))
-         (hash-put!
-           fn
-           "arguments"
-           (if (string? (tool-call-arguments tc))
-               (tool-call-arguments tc)
-               (json-object->string (tool-call-arguments tc))))
-         (hash-put! ht "function" fn)
-         ht))
-  (def (json->message json)
-       (let ([role (hash-ref json "role" "assistant")]
-             [content (json-null->false (hash-ref json "content" #f))]
-             [tool-calls-json (json-null->false
-                                (hash-ref json "tool_calls" #f))]
-             [tc-id (json-null->false
-                      (hash-ref json "tool_call_id" #f))])
-         (make-message
-           role
-           content
-           (and tool-calls-json
-                (pair? tool-calls-json)
-                (map json->tool-call tool-calls-json))
-           tc-id)))
-  (def (json->tool-call json)
-       (let ([fn (hash-ref json "function" #f)])
-         (restore-tool-call
-           (hash-ref json "id" "")
-           (hash-ref fn "name" "")
-           (hash-ref fn "arguments" "{}")))))
diff --git a/lib/jcode/core/models.sls b/lib/jcode/core/models.sls
deleted file mode 100644
index 32d2307..0000000
--- a/lib/jcode/core/models.sls
+++ /dev/null
@@ -1,199 +0,0 @@
-#!chezscheme
-;;; Generated by jerbuild — DO NOT EDIT
-;;; Source: src/jcode/core/models.ss
-
-(library (jcode core models)
-  (export provider-models all-providers provider-display-name
-    provider-default-model models-cache-path load-models-cache!
-    write-models-cache!)
-  (import
-    (except (chezscheme) make-hash-table hash-table? iota \x31;+ \x31;-
-      getenv path-extension path-absolute? thread? make-mutex
-      mutex? mutex-name)
-    (std text json) (std os path) (jerboa core)
-    (jerboa runtime))
-  (def (all-providers)
-       '("anthropic" "openai" "openrouter" "deepseek" "google" "ollama" "xai"
-          "groq" "mistral" "together" "cerebras" "perplexity"))
-  (def (provider-display-name p)
-       (case (string->symbol p)
-         [(anthropic) "Anthropic"]
-         [(openai) "OpenAI"]
-         [(openrouter) "OpenRouter"]
-         [(deepseek) "DeepSeek"]
-         [(google) "Google"]
-         [(ollama) "Ollama (local)"]
-         [(xai) "xAI (Grok)"]
-         [(groq) "Groq"]
-         [(mistral) "Mistral"]
-         [(together) "Together AI"]
-         [(cerebras) "Cerebras"]
-         [(perplexity) "Perplexity"]
-         [else p]))
-  (def (provider-default-model provider)
-       (case (string->symbol provider)
-         [(anthropic) "claude-sonnet-4-20250514"]
-         [(openai) "gpt-4o"]
-         [(openrouter) "anthropic/claude-sonnet-4"]
-         [(deepseek) "deepseek-chat"]
-         [(google) "gemini-2.5-flash"]
-         [(ollama) "llama3.2"]
-         [(xai) "grok-3-mini"]
-         [(groq) "llama-3.3-70b-versatile"]
-         [(mistral) "mistral-large-latest"]
-         [(together) "meta-llama/Llama-3.3-70B-Instruct-Turbo"]
-         [(cerebras) "llama-3.3-70b"]
-         [(perplexity) "sonar-pro"]
-         [else "gpt-4o"]))
-  (def (provider-models provider)
-       (unless (*models-cache*) (load-models-cache!))
-       (let ([cached (and (*models-cache*)
-                          (hash-get (*models-cache*) provider))])
-         (if (and cached (pair? cached))
-             (cache-entries->pairs cached)
-             (provider-default-models provider))))
-  (def (provider-default-models provider)
-       (case (string->symbol provider)
-         [(anthropic) anthropic-models]
-         [(openai) openai-models]
-         [(deepseek) deepseek-models]
-         [(google) google-models]
-         [(openrouter) openrouter-models]
-         [(ollama) ollama-models]
-         [(xai) xai-models]
-         [(groq) groq-models]
-         [(mistral) mistral-models]
-         [(together) together-models]
-         [(cerebras) cerebras-models]
-         [(perplexity) perplexity-models]
-         [else '()]))
-  (def *models-cache* (make-parameter #f))
-  (def (models-cache-path)