Show tool arg signatures in system prompt

ober

490059d00344560f3caede05d23f80d0ec9cd056

diff --git a/src/jcode/core/agent.ss b/src/jcode/core/agent.ss
index 71f7f5b..8684b29 100644
--- a/src/jcode/core/agent.ss
+++ b/src/jcode/core/agent.ss
@@ -75,10 +75,12 @@ Be concise. Prefer edit over write for modifying existing files.
     (collect-agent-instructions)))
 
 (def (format-tool-list)
-  "Build a bullet list of all registered tools for the system prompt."
+  "Build a bullet list of registered tools with their arg signatures, so
+   models that can't see the tools schema (e.g. reasoning models that reject
+   the tools API) still know which arg names exist. ! marks required, ? optional."
   (let ((names (sort string<? (list-tools))))
     (string-join
-      (map (lambda (n) (string-append "- " n)) names)
+      (map (lambda (n) (string-append "- " (tool-signature n))) names)
       "\n")))
 
 (def (mode-label m)
diff --git a/src/jcode/tool/registry.ss b/src/jcode/tool/registry.ss
index 8cc7d33..755c33c 100644
--- a/src/jcode/tool/registry.ss
+++ b/src/jcode/tool/registry.ss
@@ -13,7 +13,8 @@
         register-write-tools!
         set-tool-internal!
         tool-exists?
-        tool-primary-arg)
+        tool-primary-arg
+        tool-signature)
 
 (import :std/text/json
         :std/misc/string
@@ -142,6 +143,24 @@
                           (hash-get schema "required"))))
            (and (pair? req) (car req))))))
 
+(def (tool-signature name)
+  ;; Return a short signature string like 'glob(pattern!, path?)' for use in
+  ;; system prompts when the model can't see the tools schema directly.
+  (let ((tool (hash-get *tools* name)))
+    (cond
+      ((not tool) name)
+      (else
+       (let* ((schema (hash-ref tool "schema" (make-hash-table)))
+              (props  (or (and (hash-table? schema) (hash-get schema "properties"))
+                          (make-hash-table)))
+              (req    (or (and (hash-table? schema) (hash-get schema "required"))
+                          '()))
+              (keys   (if (hash-table? props) (hash-keys props) '()))
+              (parts  (map (lambda (k)
+                             (string-append k (if (member k req) "!" "?")))
+                           keys)))
+         (string-append name "(" (string-join parts ", ") ")"))))))
+
 (def (set-tool-internal! name internal?)
   "Toggle the 'internal' flag on a registered tool. When #t, the tool is
    hidden from get-tool-schemas (and therefore from the LLM). Used by serve