From 73ea0f4397ed2efe58dd3e2f11b9fa187fc5497a Mon Sep 17 00:00:00 2001
From: Arun Isaac
Date: Sun, 17 May 2026 23:10:40 +0100
Subject: Refactor web request utilities to separate module.
---
kaagum/openai.scm | 60 +---------------------------------------
kaagum/web.scm | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 59 deletions(-)
create mode 100644 kaagum/web.scm
diff --git a/kaagum/openai.scm b/kaagum/openai.scm
index 4cf643d..436a755 100644
--- a/kaagum/openai.scm
+++ b/kaagum/openai.scm
@@ -17,15 +17,10 @@
;;; along with kaagum. If not, see .
(define-module (kaagum openai)
- #:use-module (rnrs conditions)
#:use-module (rnrs exceptions)
- #:use-module (srfi srfi-11)
- #:use-module (web client)
- #:use-module (web http)
- #:use-module (web response)
- #:use-module (json)
#:use-module (lens)
#:use-module (kaagum records)
+ #:use-module (kaagum web)
#:export (get-api-key
openai-query
openai-models))
@@ -35,59 +30,6 @@
(description model-description)
(context-length model-context-length lensed)))
-;; TODO: URIs must not be operated on using string operations. Replace with a
-;; more principled implementation involving (web uri).
-(define (uri-join base uri)
- (string-append base uri))
-
-(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."
- (let-values (((response body)
- (http-request url
- #:method method
- #:headers headers
- #:body body
- #:streaming? #t)))
- ;; Guile does not consider application/json responses as textual, and does
- ;; not automatically set the port encoding to UTF-8.
- (set-port-encoding! body "UTF-8")
- (case (quotient (response-code response)
- 100)
- ((2) (json->scm body))
- ((4)
- (raise-exception
- (condition (make-violation)
- (make-irritants-condition (list method url headers body))
- (make-message-condition
- (string-append "JSON API request failed with client error code "
- (number->string (response-code response)))))))
- (else
- (raise-exception
- (condition (make-error)
- (make-irritants-condition (list method url headers body))
- (make-message-condition
- (string-append "JSON API request failed with code "
- (number->string (response-code response))))))))))
-
-(define* (json-get url #:key (headers '()))
- "Send a GET request to @var{url}. Return JSON response."
- (json-request 'GET url
- #:headers headers))
-
-(define* (json-post url #:key (headers '()) json)
- "Send a POST request to @var{url} with @var{json} body and additional
-@var{headers}. The @samp{Content-Type} header is set to @samp{application/json}
-and need not be specified in @var{headers}. Return JSON response."
- (json-request 'POST url
- #:headers `((content-type application/json)
- ,@headers)
- #:body (scm->json-string json)))
-
-;; Declare the Authorization header as opaque so that Guile doesn't try to mess
-;; with it.
-(declare-opaque-header! "Authorization")
-
(define (openai-query base-uri api-key model messages tools)
"Send a request to the OpenAI completions API and return the JSON response.
@var{base-uri} is the base URI of the OpenAI-compatible service. @var{api-key}
diff --git a/kaagum/web.scm b/kaagum/web.scm
new file mode 100644
index 0000000..ce29bdd
--- /dev/null
+++ b/kaagum/web.scm
@@ -0,0 +1,82 @@
+;;; kaagum --- Tiny, security-focused AI agent in Guile
+;;; Copyright © 2026 Arun Isaac
+;;;
+;;; 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 .
+
+(define-module (kaagum web)
+ #:use-module (rnrs conditions)
+ #:use-module (srfi srfi-11)
+ #:use-module (web client)
+ #:use-module (web http)
+ #:use-module (web response)
+ #:use-module (json)
+ #:export (uri-join
+ json-request
+ json-get
+ json-post))
+
+;; Declare the Authorization header as opaque so that Guile doesn't try to mess
+;; with it.
+(declare-opaque-header! "Authorization")
+
+;; TODO: URIs must not be operated on using string operations. Replace with a
+;; more principled implementation involving (web uri).
+(define (uri-join base uri)
+ (string-append base uri))
+
+(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."
+ (let-values (((response body)
+ (http-request url
+ #:method method
+ #:headers headers
+ #:body body
+ #:streaming? #t)))
+ ;; Guile does not consider application/json responses as textual, and does
+ ;; not automatically set the port encoding to UTF-8.
+ (set-port-encoding! body "UTF-8")
+ (case (quotient (response-code response)
+ 100)
+ ((2) (json->scm body))
+ ((4)
+ (raise-exception
+ (condition (make-violation)
+ (make-irritants-condition (list method url headers body))
+ (make-message-condition
+ (string-append "JSON API request failed with client error code "
+ (number->string (response-code response)))))))
+ (else
+ (raise-exception
+ (condition (make-error)
+ (make-irritants-condition (list method url headers body))
+ (make-message-condition
+ (string-append "JSON API request failed with code "
+ (number->string (response-code response))))))))))
+
+(define* (json-get url #:key (headers '()))
+ "Send a GET request to @var{url}. Return JSON response."
+ (json-request 'GET url
+ #:headers headers))
+
+(define* (json-post url #:key (headers '()) json)
+ "Send a POST request to @var{url} with @var{json} body and additional
+@var{headers}. The @samp{Content-Type} header is set to @samp{application/json}
+and need not be specified in @var{headers}. Return JSON response."
+ (json-request 'POST url
+ #:headers `((content-type application/json)
+ ,@headers)
+ #:body (scm->json-string json)))
--
cgit 1.4.1