about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xbin/kaagum24
-rw-r--r--kaagum/tea.scm13
-rw-r--r--kaagum/trace.scm32
-rw-r--r--kaagum/web.scm8
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)