Function: gptel--dispatch-schema-type
gptel--dispatch-schema-type is a natively compiled function defined in
gptel-request.el.
Signature
(gptel--dispatch-schema-type SCHEMA)
Documentation
Convert SCHEMA to a valid elisp representation.
SCHEMA can be specified in several ways:
- As a plist readable by gptel--json-encode
Ex: (:type object :properties (:key1 (:type number :description "...")
:key2 (:type string)))
- As a serialized JSON string, which will be passed as-is.
- In shorthand form #1, a single-line comma-separated string with object
keys and (optionally) types:
Ex: "key1, key2 number"
Ex: "key1 string, key2 int"
The default type is string, and types can be shortened (integer -> int) as
long as they match a JSON schema type uniquely.
- In shorthand form #2, a multi-line string with keys, (optionally) types and
(optionally) descriptions
Ex: "key1: description 1 here
key2 integer: description 2 here"
- Shorthand forms can be placed inside [ and ] to specify an array of
objects:
Ex: "[key1, key2 number]"
Ex: "[key1: description 1 here
key2 int: description 2 here]"
Source Code
;; Defined in /nix/store/q3r7g81pvghw7a523kjk2k2zih3pfk8z-emacs-packages-deps/share/emacs/site-lisp/elpa/gptel-20261002.545/gptel-request.el
(defun gptel--dispatch-schema-type (schema)
"Convert SCHEMA to a valid elisp representation.
SCHEMA can be specified in several ways:
- As a plist readable by `gptel--json-encode'
Ex: (:type object :properties (:key1 (:type number :description \"...\")
:key2 (:type string)))
- As a serialized JSON string, which will be passed as-is.
- In shorthand form #1, a single-line comma-separated string with object
keys and (optionally) types:
Ex: \"key1, key2 number\"
Ex: \"key1 string, key2 int\"
The default type is string, and types can be shortened (integer -> int) as
long as they match a JSON schema type uniquely.
- In shorthand form #2, a multi-line string with keys, (optionally) types and
(optionally) descriptions
Ex: \"key1: description 1 here
key2 integer: description 2 here\"
- Shorthand forms can be placed inside [ and ] to specify an array of
objects:
Ex: \"[key1, key2 number]\"
Ex: \"[key1: description 1 here
key2 int: description 2 here]\""
(when (stringp schema) ;Two possibilities: serialized JSON, or shorthand form
(let (wrap-in-array) ;Flag to wrap the object type in an array
(with-temp-buffer ;Parser for (possibly) shorthand forms
(insert schema)
(goto-char (point-min)) (skip-chars-forward " \n\r\t")
(if (= (char-after) ?{)
(setq schema (gptel--json-read)) ;Assume serialized JSON schema, we're done
(when (= (char-after) ?\[) ;Shorthand: assume array top-level type
(save-excursion
(goto-char (point-max)) (skip-chars-backward " \n\r\t") (delete-char -1))
(delete-char 1) ;Delete array markers [ and ]
(setq wrap-in-array t))
(let ( props types descriptions ;Nested object and array types are disallowed in shorthand
(all-types '("number" "string" "integer" "boolean" "null")))
(if (= (point-max) (line-end-position)) ; Single or multi-line?
;; Single line format (type optional): "key1 type, key2, ..."
(while (re-search-forward ",?\\([^ ,]+\\) *\\([^ ,]*\\]?\\)" nil t)
(push (match-string 1) props)
(push (if (string-empty-p (match-string 2))
"string" (car (all-completions (match-string 2) all-types)))
types)
(push nil descriptions))
;; Multi-line format (type, description optional):
;; "key1 type: description1 \n key2: description2..."
(while (re-search-forward "\\([^ :]+\\) *\\([^ :]*\\):?"
(line-end-position) t)
(push (match-string 1) props)
(push (if (string-empty-p (match-string 2))
"string" (car (all-completions (match-string 2) all-types)))
types)
(skip-chars-forward " \t")
(push (if (eolp) nil (buffer-substring-no-properties
(point) (line-end-position)))
descriptions)
(forward-line 1)))
(let ((object
(list :type "object"
:properties
(cl-mapcan
(lambda (prop type desc)
`(,(intern (concat ":" prop))
(:type ,type ,@(when desc
(list :description (string-trim desc))))))
(nreverse props) (nreverse types) (nreverse descriptions)))))
(setq schema
(if wrap-in-array (list :type "array" :items object) object))))))))
;; The OpenAI and Anthropic APIs don't allow arrays at the root of the schema.
;; Work around this by wrapping it in an object with the field "items".
;; TODO(schema): Find some way to strip this extra layer from the response.
(if (member (plist-get schema :type) '("array" array))
(list :type "object"
:properties (list :items schema)
:required ["items"]
:additionalProperties :json-false)
schema))