diff options
| -rwxr-xr-x | bin/kaagum | 24 | ||||
| -rw-r--r-- | kaagum/tea.scm | 13 | ||||
| -rw-r--r-- | kaagum/trace.scm | 32 | ||||
| -rw-r--r-- | kaagum/web.scm | 8 |
4 files changed, 67 insertions, 10 deletions
diff --git a/bin/kaagum b/bin/kaagum index 138e62c..9d5353d 100755 --- a/bin/kaagum +++ b/bin/kaagum @@ -21,6 +21,7 @@ exec guile --no-auto-compile -e main -s "$0" "$@" ;;; along with kaagum. If not, see <https://www.gnu.org/licenses/>. (use-modules (rnrs io ports) + (srfi srfi-26) (srfi srfi-37) (ice-9 match) (kaagum config) @@ -28,6 +29,7 @@ exec guile --no-auto-compile -e main -s "$0" "$@" (kaagum tea) (kaagum tools base) (kaagum tools forges) + (kaagum trace) (kaagum utils)) (define (invalid-option opt name arg result) @@ -47,6 +49,9 @@ exec guile --no-auto-compile -e main -s "$0" "$@" (option (list #\k "api-key-command") #t #f (lambda (opt name arg result) (acons 'api-key-command arg result))) + (option (list "trace-file") #t #f + (lambda (opt name arg result) + (acons 'trace-file arg result))) (option (list #\v "version") #f #f (lambda (opt name arg result) (acons 'version #t result))) @@ -67,6 +72,8 @@ Run kaagum AI agent. --model=MODEL LLM model name to start new sessions with (default: \"anthropic/claude-opus-4.6\") + --trace-file=FILE trace out all interactions in FILE + --version print version and exit --help print this help and exit " @@ -105,8 +112,15 @@ Run kaagum AI agent. (exit #t)) (unless (assq-ref args 'api-key-command) (die "--api-key-command not specified")) - (run-tea-loop (assq-ref args 'api-base-uri) - (get-api-key (assq-ref args 'api-key-command)) - (assq-ref args 'model) - (append %base-tools - %forge-tools)))))) + (let ((thunk (cut run-tea-loop + (assq-ref args 'api-base-uri) + (get-api-key (assq-ref args 'api-key-command)) + (assq-ref args 'model) + (append %base-tools + %forge-tools)))) + (if (assq-ref args 'trace-file) + (call-with-output-file (assq-ref args 'trace-file) + (lambda (trace-port) + (parameterize ((%trace-port trace-port)) + (thunk)))) + (thunk))))))) diff --git a/kaagum/tea.scm b/kaagum/tea.scm index 6e750c0..1ac674e 100644 --- a/kaagum/tea.scm +++ b/kaagum/tea.scm @@ -34,6 +34,7 @@ #:use-module (kaagum openai) #:use-module (kaagum records) #:use-module (kaagum tools) + #:use-module (kaagum trace) #:use-module (kaagum utils) #:export (run-tea-loop)) @@ -957,7 +958,9 @@ in @code{tea-loop}." (define* (tea-loop state llm-base-uri llm-api-key models tools #:optional (events (let ((line (get-line (current-input-port)))) (and (not (eof-object? line)) - (list (acp-message (json-string->scm line))))))) + (begin + (trace 'acp "<- ~a" line) + (list (acp-message (json-string->scm line)))))))) "Run a @acronym{TEA, The Elm Architecture} loop starting with @var{state}. @var{llm-base-uri}, @var{llm-api-key} and @var{tools} are the same as in @@ -986,9 +989,11 @@ in @code{tea-loop}." (cond ;; Send message to client, and return the state unchanged. ((acp-message? effect) - (display (scm->json-string (focus acp-message-json effect))) - (newline) - (flush-output-port (current-output-port)) + (let ((json-message (scm->json-string (focus acp-message-json effect)))) + (display json-message) + (newline) + (flush-output-port (current-output-port)) + (trace 'acp "-> ~a" json-message)) (list)) ;; Send request to LLM, handle the response, and return the new state. ((llm-request? effect) diff --git a/kaagum/trace.scm b/kaagum/trace.scm new file mode 100644 index 0000000..2c2c4ed --- /dev/null +++ b/kaagum/trace.scm @@ -0,0 +1,32 @@ +;;; kaagum --- Tiny, security-focused AI agent in Guile +;;; Copyright © 2026 Arun Isaac <arunisaac@systemreboot.net> +;;; +;;; This file is part of kaagum. +;;; +;;; kaagum is free software: you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation, either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; kaagum is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with kaagum. If not, see <https://www.gnu.org/licenses/>. + +(define-module (kaagum trace) + #:export (%trace-port + trace)) + +(define %trace-port + (make-parameter #f)) + +(define (trace subsystem message . args) + "Print out tracing @var{message} with @var{args} for @var{subsystem}." + (when (%trace-port) + (display subsystem (%trace-port)) + (display ": " (%trace-port)) + (apply format (%trace-port) message args) + (newline (%trace-port)))) diff --git a/kaagum/web.scm b/kaagum/web.scm index ce29bdd..db6f33a 100644 --- a/kaagum/web.scm +++ b/kaagum/web.scm @@ -22,6 +22,7 @@ #:use-module (web client) #:use-module (web http) #:use-module (web response) + #:use-module (kaagum trace) #:use-module (json) #:export (uri-join json-request @@ -40,6 +41,9 @@ (define* (json-request method url #:key (headers '()) body) "Send a HTTP @var{method} request to @var{url} with @var{body} and additional @var{headers}. Return JSON response." + (if body + (trace 'web "-> ~a ~a ~a" method url body) + (trace 'web "-> ~a ~a" method url)) (let-values (((response body) (http-request url #:method method @@ -51,7 +55,9 @@ additional @var{headers}. Return JSON response." (set-port-encoding! body "UTF-8") (case (quotient (response-code response) 100) - ((2) (json->scm body)) + ((2) (let ((result (json->scm body))) + (trace 'web "<- ~a ~a" (response-code response) (scm->json-string result)) + result)) ((4) (raise-exception (condition (make-violation) |
