-
Notifications
You must be signed in to change notification settings - Fork 300
feat: use an OpenAPI definition as a tool file #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
pkg/types/jsonschema.go
Outdated
Description string `json:"description,omitempty"` | ||
Type string `json:"type,omitempty"` | ||
Ref string `json:"$ref,omitempty"` | ||
Items *JSONSchema `json:"items,omitempty"` | ||
Enum []string `json:"enum,omitempty"` | ||
|
||
ID string `json:"$id,omitempty"` | ||
Title string `json:"title,omitempty"` | ||
Properties map[string]Property `json:"properties"` | ||
Properties map[string]JSONSchema `json:"properties"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are some fixes that I made to the JSONSchema type. There was no need to have a separate Property
struct.
pkg/engine/openapi.go
Outdated
// Check for a bearer token (only if using HTTPS) | ||
if u.Scheme == "https" { | ||
// For "https://example.com" the bearer token env name would be GPTSCRIPT_EXAMPLE_COM_BEARER_TOKEN | ||
bearerEnv := "GPTSCRIPT_" + strings.ToUpper(strings.Replace(u.Host, ".", "_", -1)) + "_BEARER_TOKEN" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want u.Hostname() so that you don't get the port part if there is a port, like :8443
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for finding that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
pkg/loader/loader.go
Outdated
if err != nil { | ||
return types.Tool{}, err | ||
var tools []types.Tool | ||
if strings.HasSuffix(base.Name, ".json") || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should detect if the data is openapi format by inspecting the data itself and not by file extension. That should be more flexible in the future. I also don't want something where the openai schema is hosted at path like "https://example.com/openapi" and it not working becaues it doesn't end with the extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
pkg/engine/openapi.go
Outdated
// Check for a bearer token (only if using HTTPS) | ||
if u.Scheme == "https" { | ||
// For "https://example.com" the bearer token env name would be GPTSCRIPT_EXAMPLE_COM_BEARER_TOKEN | ||
bearerEnv := "GPTSCRIPT_" + strings.ToUpper(strings.Replace(u.Hostname(), ".", "_", -1)) + "_BEARER_TOKEN" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a function somewhere ToEnvLike. Can you use that. It's handles -
-> _
also which tends to break env vars also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ibuildthecloud that function doesn't replace .
with _
. Should I modify it to do that also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nvm, I hadn't updated my local branch on main yet. Fixed.
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
f4a06bc
to
877862d
Compare
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
This adds the ability to use an OpenAPI definition file as though it were a GPTScript tool file. gptscript will now attempt to parse any .json, .yaml, or .yml files as OpenAPI definitions, and if it gets an error while doing that, only then will it attempt to treat it as a standard gptscript file. (Files ending in any other extension are just treated as standard scripts and not checked for OpenAPI definitions.)
When parsing the file, gptscript creates an in-memory tool definition for each operation (path + HTTP method) defined in the file. It also creates one top-level tool that exports all the rest. Each tool's name matches the corresponding operation's
operationId
. Each tool's instructions (the bit after the preamble, where you would ordinarily prompt the model or run a command) starts with the unique sequence#!sys.openapi
, followed by a JSON string with information about the operation. This tells gptscript's tool runner to handle this tool uniquely. The code that runs the tool will unmarshal the JSON and use the instructions to set up and do the HTTP request, print the body, and exit.The typical use case for this would be to hand an OpenAPI definition to GPTScript and ask the model to just perform a series of tasks, and let it choose which operations it needs to use. It is still possible to restrict which tools you give it using the
toolName from file.yaml
syntax.For more details on how to use this, see the doc that I added in this PR.