diff options
| author | Arun Isaac | 2026-05-17 19:36:41 +0100 |
|---|---|---|
| committer | Arun Isaac | 2026-05-17 23:10:17 +0100 |
| commit | a47a9e899383fba7e3488ae9d494af9caf0492fa (patch) | |
| tree | 7c71412828440ff0537456eec1580223a4f69eea | |
| parent | 3414bec6245100e809ce6a24a5a4095e8fcd51ef (diff) | |
| download | kaagum-a47a9e899383fba7e3488ae9d494af9caf0492fa.tar.gz kaagum-a47a9e899383fba7e3488ae9d494af9caf0492fa.tar.lz kaagum-a47a9e899383fba7e3488ae9d494af9caf0492fa.zip | |
Check types of tool call arguments.
| -rw-r--r-- | kaagum/tools.scm | 42 | ||||
| -rw-r--r-- | tests/tools.scm | 46 |
2 files changed, 87 insertions, 1 deletions
diff --git a/kaagum/tools.scm b/kaagum/tools.scm index f561e65..97f0796 100644 --- a/kaagum/tools.scm +++ b/kaagum/tools.scm @@ -22,6 +22,8 @@ #:use-module (rnrs exceptions) #:use-module (rnrs records syntactic) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-43) #:use-module (ice-9 match) #:use-module (gnu build linux-container) #:use-module (gnu system file-systems) @@ -146,6 +148,34 @@ tool-call-failure tool-call-failure? (message tool-call-failure-message)) +(define (check-type value type) + "Check type of JSON @var{value}. Return @code{#t} if it matches @var{type}, else +return @code{#f}. @var{type} is a JSON Schema type defined in +@url{https://json-schema.org/draft/2020-12/json-schema-validation#section-6.1.1}." + (match type + ("null" + (eq? value 'null)) + ("boolean" + (boolean? value)) + ("integer" + (integer? value)) + ("number" + (number? value)) + ("string" + (string? value)) + ((? array-type? type) + (and (vector? value) + (vector-every (cut check-type <> (array-type-subtype type)) + value))) + ("object" + (every (match-lambda + ((key . _) + (string? key))) + value)) + (#(types ...) + (any (cut check-type value <>) + types)))) + (define (spec->tool-call session-id session-cwd tools allowed-tools rejected-tools spec) "Deserialize JSON tool call @var{spec} into a @code{<tool-call>} object. Raise a @code{&tool-call-parse-failure} condition if deserialization @@ -183,7 +213,17 @@ names that have been respectively allowed and rejected by the user in advance." ((arg-name . parameter) (cond ((assoc arg-name args) - => identity) + => (match-lambda + ((and (_ . value) + key-value) + (let ((type (tool-parameter-type parameter))) + (unless (check-type value type) + (raise-exception + (tool-call-parse-failure + (string-append "Error: Argument " + arg-name + " of invalid type")))) + key-value)))) (else (and (tool-parameter-required? parameter) (raise-exception diff --git a/tests/tools.scm b/tests/tools.scm new file mode 100644 index 0000000..1ad0c62 --- /dev/null +++ b/tests/tools.scm @@ -0,0 +1,46 @@ +;;; 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/>. + +(use-modules (srfi srfi-64) + (kaagum tools)) + +(test-begin "tools") + +(test-equal "tool call with parameter type mismatch must error out" + "Error: Argument arg of invalid type" + (guard (c ((tool-call-parse-failure? c) + (tool-call-parse-failure-message c))) + (spec->tool-call "foo" + "/foo/bar" + `(("read" . ,(tool #:description "A dummy test tool" + #:parameters `(("arg" . ,(tool-parameter + #:description "an argument" + #:type "integer" + #:required? #t))) + #:proc identity + #:title identity + #:kind "read"))) + (list "read") + (list) + `(("id" . "foo123") + ("type" . "function") + ("function" + ("name" . "read") + ("arguments" . "{\"arg\": \"[738\"}")))))) + +(test-end "tools") |
