luv

Workshop wiki

command-tool.lisp

application-agent/command-tool.lisp

system luv/application-agent · 28 definitions · on GitHub

in-package#:luv.application-agent

A command argument is semantic definition metadata captured from McCLIM's parser once. It can drive provider JSON today and parameter prompting in M-x later without coupling either interface to the other.

defclasscommand-argument-specification
name:initarg:name:readercommand-argument-name
json-name:initarg:json-name:readercommand-argument-json-name
type:initarg:type:readercommand-argument-type
options:initarg:options:readercommand-argument-options
required-p:initarg:required-p:readercommand-argument-required-p
keyword-p:initarg:keyword-p:readercommand-argument-keyword-p
defunargument-json-name
argument-name
string-downcase
symbol-nameargument-name
defuncommand-argument-active-p
options
let
when-form
getfoptions:whent
or
not
constantpwhen-form
evalwhen-form
defunmake-command-argument-specification
descriptionrequired-pkeyword-p
destructuring-bind
nametype-form&restoptions
description
make-instance'command-argument-specification:namename:json-name:type
evaltype-form
:optionsoptions:required-prequired-p:keyword-pkeyword-p
defuncommand-argument-specifications
command

Return command's active required and named argument definitions.

let
parsers
gethashcommandclimi::*command-parser-table*
unlessparsers
error"~S is not a CLIM command."command
append
mapcar
lambda
description
climi::required-argsparsers
loopfordescriptionin
climi::keyword-argsparsers
foroptions=
cddrdescription
whencollect
make-command-argument-specificationdescription
not
member:defaultoptions
t
defunschema-with-argument-documentation
argument
let*
options
command-argument-optionsargument
schema
presentation-type-specifier-json-schema
command-argument-typeargument
documentation
or
getfoptions:documentation
getfoptions:prompt
if
anddocumentation
not
assoc"description"schema:test#'string=
appendschema`
"description".,documentation
schema
defuncommand-tool-parameters
arguments

Return a strict JSON Schema object for ARGUMENT specifications.

let
properties
mapcar
lambda
argument
cons
command-argument-json-nameargument
arguments
required
loopforargumentinargumentswhen
command-argument-required-pargument
collect
command-argument-json-nameargument
`
"type"."object"
"properties".,
orproperties
make-hash-table:test#'equal
"required".,
coercerequired'vector
"additionalProperties".,openai:+json-false+
defuncommand-tool-name
command
let
name
string-downcase
symbol-namecommand
if
and
>
lengthname
4
string="com-"name:end24
subseqname4
name
defclasscommand-tool
openai:tool
command:initarg:command:readercommand-tool-command
arguments:initarg:arguments:readercommand-tool-argument-specifications
defunmake-command-tool
command&keydescription
let
make-instance'command-tool:commandcommand:argumentsarguments:name:description
ordescription
:parameters
define-conditiontool-argument-error
error
name:initarg:name:readertool-argument-error-name
detail:initarg:detail:readertool-argument-error-detail
:report
lambda
conditionstream
formatstream"argument ~A: ~A"
tool-argument-error-namecondition
tool-argument-error-detailcondition
defunjson-argument-cell
argumentarguments
assoc
command-argument-json-nameargument
arguments:test#'string-equal
defunaccept-command-argument
argumentarguments

Parse argument from a decoded JSON alist with its presentation type.

let*
json-name
command-argument-json-nameargument
cell
json-argument-cellargumentarguments
unlesscell
when
command-argument-required-pargument
error'tool-argument-error:namejson-name:detail"missing"
return-fromaccept-command-argument
valuesnilnil
let*
value
cdrcell
text
if
stringpvalue
value
princ-to-stringvalue
handler-case
values
accept-from-string
command-argument-typeargument
text
t
error
condition
error'tool-argument-error:namejson-name:detail
formatnil"~S: ~A"textcondition
defunvalidate-command-tool-arguments
toolarguments
unless
listparguments
error'tool-argument-error:name"arguments":detail"expected a JSON object"
let
known
mapcar#'command-argument-json-name
command-tool-argument-specificationstool
seen
make-hash-table:test#'equalp
dolist
cellarguments
unless
conspcell
error'tool-argument-error:name"arguments":detail"expected name/value properties"
let
name
string-downcase
string
carcell
unless
membernameknown:test#'string=
error'tool-argument-error:namename:detail"unknown"
when
gethashnameseen
error'tool-argument-error:namename:detail"duplicated"
setf
gethashnameseen
t
arguments
defuncommand-tool-parse
toolarguments

Return a validated CLIM command form for decoded JSON arguments.

let
required-values'
keyword-values'
dolist
argument
command-tool-argument-specificationstool
multiple-value-bind
valuepresent-p
accept-command-argumentargumentarguments
whenpresent-p
if
command-argument-keyword-pargument
setfkeyword-values
nconckeyword-values
list
intern
symbol-name
command-argument-nameargument
:keyword
value
pushvaluerequired-values
list*
command-tool-commandtool
nconc
nreverserequired-values
keyword-values

The application side is deliberately just these two methods. There is no unsafe default for a command that claims it needs the canvas thread.

defgenericapplication-command-frame
application
:documentation

Return application's McCLIM command frame.

defgenericcall-in-application-frame
applicationfunction
:documentation

Run no-argument function briefly at application's frame boundary.

defgenericcall-with-agent-command-context
:documentation

Call function with agent's dynamic command context.

defmethodcall-with-agent-command-context
let
*handles*
application-agent-handlesagent
funcallfunction
defgenericcommand-tool-runs-on-canvas-p
command
:documentation

Whether command must execute at its application's frame boundary.

:method
commandt
t
defgenericcommand-result-presentation-type
commandvalue
:documentation

The presentation type used to show command's value.

:method
commandt
value
declare
ignorecommand
presentation-type-ofvalue
defgenericcommand-output-line-limit
command
:documentation

The provider line limit for command's presented output.

:method
commandt
*model-text-max-lines*
defgenericcommand-provider-output
commandvaluestext
:documentation

Return the provider result after values produced text.

:method
commandt
valuestext
declare
ignorecommandvalues
text
defgenericsettle-command-result
commandvalue
:documentation

Finish value's off-canvas work on the provider worker before presentation.

:method
commandt
value
declare
ignorecommand
value
defunexecute-command-for-agent
agentcommand
let*
run
lambda
call-with-agent-command-contextagent
lambda
multiple-value-list
execute-frame-commandcommand
defmethodopenai:call-tool
let
call
make-instance'tool-call:tooltool:argumentsarguments
provider-outputnil
*handles*
application-agent-handlesagent
handler-case
let*
command
command-tool-parsetoolarguments
raw-values
progn
setf
tool-call-commandcall
command
values
mapcar
lambda
value
settle-command-result
firstcommand
value
raw-values
output
formatnil"~{~A~^~%~}"
mapcar
lambda
value
values
let
text
if
string=output""
"ok"output
setf
tool-call-resultcall
firstvalues
tool-call-outputcall
text
tool-call-statuscall
:ok
provider-output
command-provider-output
firstcommand
valuestext
error
condition
setf
tool-call-errorcall
condition
tool-call-outputcall
formatnil"error: ~A"condition
tool-call-statuscall
:error
setf
tool-call-finishedcall
get-internal-real-time
orprovider-output
tool-call-outputcall
defunmake-application-agent
&keyapplicationmodelcommandsinstructionsreasoning-summaryreasoning-effort
api-key
openai:default-api-key
initargs

Open a provider-backed class attached to application and commands.

unlessapplication
error":APPLICATION is required."
openai:make-agent:classclass:initargs
append
list:applicationapplication
initargs
:modelmodel:instructionsinstructions:reasoning-summaryreasoning-summary:reasoning-effortreasoning-effort:api-keyapi-key:tools
mapcar#'make-command-toolcommands